diff --git a/README.md b/README.md index 89cb9bbb..2ca00b05 100644 --- a/README.md +++ b/README.md @@ -55,6 +55,43 @@ The code within the engine is relatively clean with some code for the actual gam This project is based on ES5. Some ES2015 features are used but most of them are too slow, especially when polyfilled. For example, `Array.prototype.forEach` is only used within non-critical loops since its slower than a plain for loop. +#### Adding a new component + +1. Create the component file in `src/js/game/components/.js` +2. Create a component class (e.g. `MyFancyComponent`) which `extends Component` +3. Create a `static getId()` method which should return the `CamelCaseName` without component (e.g. `MyFancy`) +4. If any data needs to be persisted, create a `static getSchema()` which should return the properties to be saved (See other components) +5. Add a constructor. **The constructor must be called with optional parameters only!** `new MyFancyComponent({})` should always work. +6. Add any props you need in the constructor. +7. Add the component in `src/js/game/component_registry.js` +8. Add the componetn in `src/js/game/entity_components.js` +9. Done! You can use your component now + +#### Adding a new building + +(The easiest way is to copy an existing building) + +1. Create your building in `src/js/game/buildings/` +2. Create the building meta class, e.g. `MetaMyFancyBuilding extends MetaBuilding` +3. Override the methods from MetaBuilding you want to override. +4. Most important is `setupEntityComponents` +5. Add the building to `src/js/game/meta_building_registry.js`: You need to register it on the registry, and also call `registerBuildingVariant`. +6. Add the building to the right toolbar, e.g. `src/js/game/hud/parts/buildings_toolbar.js`:`supportedBuildings` +7. Add a keybinding for the building in `src/js/game/key_action_mapper.js` in `KEYMAPPINGS.buildings` +8. In `translations/base-en.yaml` add it to two sections: `buildings.[my_building].XXX` (See other buildings) and also `keybindings.mappings.[my_building]`. Be sure to do it the same way as other buildings do! +9. Create a icon (128x128, [prefab](https://github.com/tobspr/shapez.io-artwork/blob/master/ui/toolbar-icons.psd)) for your building and save it in `res/ui/buildings_icons` with the id of your building +10. Create a tutorial image (600x600) for your building and save it in `res/ui/building_tutorials` +11. In `src/css/icons.scss` add your building to `$buildings` as well as `$buildingAndVariants` +12. Done! Optional: Add a new reward for unlocking your building at some point. + +#### Adding a new game system + +1. Create the class in `src/js/game/systems/.js` +2. Derive it from `GameSystemWithFilter` if you want it to work on certain entities only which have the given components. Otherwise use `GameSystem` to do more generic stuff. +3. Implement the `update()` method. +4. Add the system in `src/js/game/game_system_manager.js` (To `this.systems` and also call `add` in the `internalInitSystems()` method) +5. If your system should draw stuff, this is a bit more complicated. Have a look at existing systems on how they do it. + ### Assets For most assets I use Adobe Photoshop, you can find them in `assets/`. diff --git a/gulp/buildutils.js b/gulp/buildutils.js index 1fb2a9a3..041c8b1d 100644 --- a/gulp/buildutils.js +++ b/gulp/buildutils.js @@ -11,6 +11,7 @@ module.exports = { ); return commitHash.replace(/^\s+|\s+$/g, ""); }, + getAllResourceImages() { return glob .sync("res/**/*.@(png|svg|jpg)", { cwd: ".." }) @@ -24,18 +25,6 @@ module.exports = { }); }, - getAllAtlasImages() { - return glob - .sync("res_built/atlas/*.png", { cwd: ".." }) - .map(s => s.replace("res_built/atlas/", "res/")); - }, - - getAllSounds() { - return glob - .sync("res_built/sounds/**/*.mp3", { cwd: ".." }) - .map(s => s.replace("res_built/sounds/", "res/sounds/")); - }, - getVersion() { return trim(fs.readFileSync(path.join(__dirname, "..", "version")).toString()); }, diff --git a/gulp/cordova.js b/gulp/cordova.js index dc968df0..22274dba 100644 --- a/gulp/cordova.js +++ b/gulp/cordova.js @@ -132,25 +132,6 @@ function gulptasksCordova($, gulp, buildFolder) { }) ); }); - - // gulp.task("pushToStagingRepo", (cb) => { - // var cmd = spawn('../push-pgb.sh', ['https://TOKEN@github.com/tobspr/shapezapp-cordova-buildslave.git'], - // { stdio: 'inherit', stdout: 'inherit', stderr: 'inherit', shell: true }); - // cmd.on('close', function (code) { - // console.log('push staging exited with code ' + code + " / " + cmd.stdout + " / " + cmd.stderr); - // cb(code); - // }); - - // }); - - // gulp.task("pushToProdRepo", (cb) => { - // var cmd = spawn('../push-pgb.sh', ['https://TOKEN@github.com/tobspr/shapezapp-cordova-buildslave-release.git'], - // { stdio: 'inherit', stdout: 'inherit', stderr: 'inherit', shell: true }); - // cmd.on('close', function (code) { - // console.log('push prod exited with code ' + code + " / " + cmd.stdout + " / " + cmd.stderr); - // cb(code); - // }); - // }); } module.exports = { diff --git a/gulp/css.js b/gulp/css.js index 729d0432..6734f1ae 100644 --- a/gulp/css.js +++ b/gulp/css.js @@ -77,7 +77,6 @@ function gulptasksCSS($, gulp, buildFolder, browserSync) { .pipe($.plumber()) .pipe($.sass.sync({ outputStyle: "compressed" }).on("error", $.sass.logError)) .pipe($.postcss(postcssPlugins(true, { cachebust: true }))) - // .pipe($.cssbeautify()) .pipe(gulp.dest(buildFolder)) ); }); @@ -90,7 +89,6 @@ function gulptasksCSS($, gulp, buildFolder, browserSync) { .pipe($.plumber()) .pipe($.sass.sync({ outputStyle: "compressed" }).on("error", $.sass.logError)) .pipe($.postcss(postcssPlugins(true, { cachebust: false }))) - // .pipe($.cssbeautify()) .pipe(gulp.dest(buildFolder)) ); }); diff --git a/gulp/html.js b/gulp/html.js index a21d66cb..b49fc1b2 100644 --- a/gulp/html.js +++ b/gulp/html.js @@ -9,7 +9,7 @@ function computeIntegrityHash(fullPath, algorithm = "sha256") { return algorithm + "-" + hash; } -function gulptasksHTML($, gulp, buildFolder, browserSync) { +function gulptasksHTML($, gulp, buildFolder) { const commitHash = buildUtils.getRevision(); async function buildHtml( apiUrl, @@ -27,9 +27,8 @@ function gulptasksHTML($, gulp, buildFolder, browserSync) { return gulp .src("../src/html/" + (standalone ? "index.standalone.html" : "index.html")) .pipe( - $.dom(function () { - // @ts-ignore - const document = /** @type {Document} */ (this); + $.dom(/** @this {Document} **/ function () { + const document = this; // Preconnect to api const prefetchLink = document.createElement("link"); @@ -38,21 +37,6 @@ function gulptasksHTML($, gulp, buildFolder, browserSync) { prefetchLink.setAttribute("crossorigin", "anonymous"); document.head.appendChild(prefetchLink); - // // Append css preload - // const cssPreload = document.createElement("link"); - // cssPreload.rel = "preload"; - // cssPreload.href = cachebust("main.css"); - // cssPreload.setAttribute("as", "style"); - // document.head.appendChild(cssPreload); - // document.head.appendChild(prefetchLink); - - // // Append js preload - // const jsPreload = document.createElement("link"); - // jsPreload.rel = "preload"; - // jsPreload.href = cachebust("bundle.js"); - // jsPreload.setAttribute("as", "script"); - // document.head.appendChild(jsPreload); - // Append css const css = document.createElement("link"); css.rel = "stylesheet"; @@ -68,17 +52,6 @@ function gulptasksHTML($, gulp, buildFolder, browserSync) { } document.head.appendChild(css); - if (analytics) { - // Logrocket - // const logrocketScript = document.createElement("script"); - // logrocketScript.src = "https://cdn.lr-ingest.io/LogRocket.min.js"; - // logrocketScript.setAttribute("crossorigin", "anonymous"); - // document.head.appendChild(logrocketScript); - // const logrocketInit = document.createElement("script"); - // logrocketInit.textContent = "window.LogRocket && window.LogRocket.init('TODO: GET LOGROCKET ID');"; - // document.head.appendChild(logrocketInit); - } - if (app) { // Append cordova link const cdv = document.createElement("script"); @@ -114,18 +87,9 @@ function gulptasksHTML($, gulp, buildFolder, browserSync) { // Do not need to preload in app or standalone if (!hasLocalFiles) { - // Preload images - const images = buildUtils.getAllResourceImages(); - // Preload essentials const preloads = ["fonts/GameFont.woff2"]; - // for (let i = 0; i < images.length; ++i) { - // if (preloads.indexOf(images[i]) < 0) { - // preloads.push(images[i]); - // } - // } - preloads.forEach(src => { const preloadLink = document.createElement("link"); preloadLink.rel = "preload"; @@ -138,23 +102,6 @@ function gulptasksHTML($, gulp, buildFolder, browserSync) { } document.head.appendChild(preloadLink); }); - - // Sound preloads - // const sounds = buildUtils.getAllSounds(); - // sounds.forEach((src) => { - - // if (src.indexOf("sounds/music/") >= 0) { - // // skip music - // return; - // } - - // const preloadLink = document.createElement("link"); - // preloadLink.rel = "preload"; - // preloadLink.href = cachebust(src); - // // preloadLink.setAttribute("crossorigin", "anonymous"); - // preloadLink.setAttribute("as", "fetch"); - // document.head.appendChild(preloadLink); - // }); } const loadingSvg = `background-image: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHN0eWxlPSJtYXJnaW46YXV0bztiYWNrZ3JvdW5kOjAgMCIgd2lkdGg9IjIwMCIgaGVpZ2h0PSIyMDAiIHZpZXdCb3g9IjAgMCAxMDAgMTAwIiBwcmVzZXJ2ZUFzcGVjdFJhdGlvPSJ4TWlkWU1pZCIgZGlzcGxheT0iYmxvY2siPjxjaXJjbGUgY3g9IjUwIiBjeT0iNTAiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzM5Mzc0NyIgc3Ryb2tlLXdpZHRoPSIzIiByPSI0MiIgc3Ryb2tlLWRhc2hhcnJheT0iMTk3LjkyMDMzNzE3NjE1Njk4IDY3Ljk3MzQ0NTcyNTM4NTY2IiB0cmFuc2Zvcm09InJvdGF0ZSg0OC4yNjUgNTAgNTApIj48YW5pbWF0ZVRyYW5zZm9ybSBhdHRyaWJ1dGVOYW1lPSJ0cmFuc2Zvcm0iIHR5cGU9InJvdGF0ZSIgcmVwZWF0Q291bnQ9ImluZGVmaW5pdGUiIGR1cj0iNS41NTU1NTU1NTU1NTU1NTVzIiB2YWx1ZXM9IjAgNTAgNTA7MzYwIDUwIDUwIiBrZXlUaW1lcz0iMDsxIi8+PC9jaXJjbGU+PC9zdmc+")`; @@ -167,7 +114,7 @@ function gulptasksHTML($, gulp, buildFolder, browserSync) { font-display: swap; src: url('${cachebust("res/fonts/GameFont.woff2")}') format('woff2'); } - + #ll_fp { font-family: GameFont; font-size: 14px; @@ -177,7 +124,7 @@ function gulptasksHTML($, gulp, buildFolder, browserSync) { left: 0; opacity: 0.05; } - + #ll_p { display: flex; position: fixed; @@ -190,7 +137,7 @@ function gulptasksHTML($, gulp, buildFolder, browserSync) { center; align-items: center; } - + #ll_p > div { position: absolute; text-align: center; @@ -201,7 +148,7 @@ function gulptasksHTML($, gulp, buildFolder, browserSync) { font-family: 'GameFont', sans-serif; font-size: 20px; } - + #ll_p > span { width: 60px; height: 60px; diff --git a/gulp/js.js b/gulp/js.js index 6faccfca..28c037bd 100644 --- a/gulp/js.js +++ b/gulp/js.js @@ -6,12 +6,6 @@ function requireUncached(module) { } function gulptasksJS($, gulp, buildFolder, browserSync) { - gulp.task("js.prettify", () => { - return gulp - .src(path.join(buildFolder, "bundle.js")) - .pipe($.jsbeautifier(require("./jsbeautify.json"))) - .pipe(gulp.dest(buildFolder)); - }); //// DEV @@ -71,6 +65,7 @@ function gulptasksJS($, gulp, buildFolder, browserSync) { gulp.task("js.staging", gulp.parallel("js.staging.transpiled", "js.staging.latest")); //// PROD + gulp.task("js.prod.transpiled", () => { return gulp .src("../src/js/main.js") @@ -167,8 +162,6 @@ function gulptasksJS($, gulp, buildFolder, browserSync) { ) .pipe(gulp.dest(buildFolder)); }); - - // TODO: Tasks for te app } module.exports = { diff --git a/gulp/package.json b/gulp/package.json index 6279afc8..9c3d0182 100644 --- a/gulp/package.json +++ b/gulp/package.json @@ -3,7 +3,6 @@ "version": "1.0.0", "description": "builder", "private": true, - "main": "main.js", "scripts": { "gulp": "gulp" }, @@ -41,7 +40,6 @@ "lz-string": "^1.4.4", "markdown-loader": "^5.1.0", "node-sri": "^1.1.1", - "obfuscator-loader": "^1.1.2", "phonegap-plugin-mobile-accessibility": "^1.0.5", "promise-polyfill": "^8.1.0", "query-string": "^6.8.1", @@ -54,7 +52,6 @@ "uglify-template-string-loader": "^1.1.0", "unused-files-webpack-plugin": "^3.4.0", "webpack": "^4.43.0", - "webpack-bundle-analyzer": "^3.0.3", "webpack-cli": "^3.1.0", "webpack-deep-scope-plugin": "^1.6.0", "webpack-plugin-replace": "^1.1.1", @@ -76,8 +73,6 @@ "gulp-cache": "^1.1.3", "gulp-cached": "^1.1.1", "gulp-clean": "^0.4.0", - "gulp-cssbeautify": "^2.0.1", - "gulp-csslint": "^1.0.1", "gulp-dom": "^1.0.0", "gulp-flatten": "^0.4.0", "gulp-fluent-ffmpeg": "^2.0.0", @@ -85,8 +80,6 @@ "gulp-htmlmin": "^5.0.1", "gulp-if": "^3.0.0", "gulp-imagemin": "^7.1.0", - "gulp-javascript-obfuscator": "^1.1.5", - "gulp-jsbeautifier": "^3.0.0", "gulp-load-plugins": "^2.0.3", "gulp-phonegap-build": "^0.1.5", "gulp-plumber": "^1.2.1", @@ -104,13 +97,11 @@ "imagemin-pngquant": "^9.0.0", "jimp": "^0.6.1", "js-yaml": "^3.13.1", - "onesky-fetch": "^0.0.7", "postcss-assets": "^5.0.0", "postcss-preset-env": "^6.5.0", "postcss-round-subpixels": "^1.2.0", "postcss-unprefix": "^2.1.3", "sass-unused": "^0.3.0", - "speed-measure-webpack-plugin": "^1.3.1", "strip-json-comments": "^3.0.1", "trim": "^0.0.1", "webpack-stream": "^5.2.1", diff --git a/gulp/standalone.js b/gulp/standalone.js index c4f33417..3b0112d4 100644 --- a/gulp/standalone.js +++ b/gulp/standalone.js @@ -1,11 +1,11 @@ const packager = require("electron-packager"); const path = require("path"); -const buildutils = require("./buildutils"); +const { getVersion } = require("./buildutils"); const fs = require("fs"); const fse = require("fs-extra"); const execSync = require("child_process").execSync; -function gulptasksStandalone($, gulp, buildFolder) { +function gulptasksStandalone($, gulp) { const electronBaseDir = path.join(__dirname, "..", "electron"); const tempDestDir = path.join(__dirname, "..", "tmp_standalone_files"); @@ -47,49 +47,7 @@ function gulptasksStandalone($, gulp, buildFolder) { }); gulp.task("standalone.prepare.minifyCode", () => { - return ( - gulp - .src(path.join(electronBaseDir, "*.js")) - // .pipe( - // $.terser({ - // ecma: 6, - // parse: {}, - // module: false, - // toplevel: true, - // keep_classnames: false, - // keep_fnames: false, - // safari10: false, - // compress: { - // arguments: false, // breaks - // drop_console: false, - // // keep_fargs: false, - // keep_infinity: true, - // passes: 2, - // module: false, - // toplevel: true, - // unsafe_math: true, - // unsafe_arrows: false, - // warnings: true, - // }, - // mangle: { - // eval: true, - // keep_classnames: false, - // keep_fnames: false, - // module: false, - // toplevel: true, - // safari10: false, - // }, - // output: { - // comments: false, - // ascii_only: true, - // beautify: false, - // braces: false, - // ecma: 6, - // }, - // }) - // ) - .pipe(gulp.dest(tempDestBuildDir)) - ); + return gulp.src(path.join(electronBaseDir, "*.js")).pipe(gulp.dest(tempDestBuildDir)); }); gulp.task("standalone.prepare.copyGamefiles", () => { @@ -122,15 +80,14 @@ function gulptasksStandalone($, gulp, buildFolder) { * @param {'win32'|'linux'|'darwin'} platform * @param {'x64'|'ia32'} arch * @param {function():void} cb - * @param {boolean=} isRelease */ - function packageStandalone(platform, arch, cb, isRelease = false) { + function packageStandalone(platform, arch, cb) { const tomlFile = fs.readFileSync(path.join(__dirname, ".itch.toml")); packager({ dir: tempDestBuildDir, appCopyright: "Tobias Springer", - appVersion: buildutils.getVersion(), + appVersion: getVersion(), buildVersion: "1.0.0", arch, platform, @@ -164,19 +121,6 @@ function gulptasksStandalone($, gulp, buildFolder) { '#!/usr/bin/env bash\n./shapezio --no-sandbox "$@"\n' ); fs.chmodSync(path.join(appPath, "play.sh"), 0o775); - } else if (platform === "win32") { - // Optional: Create a playable copy. Shouldn't be required - // const playablePath = appPath + "_playable"; - // fse.copySync(appPath, playablePath); - // fs.writeFileSync(path.join(playablePath, "steam_appid.txt"), "1134480"); - // fs.writeFileSync( - // path.join(playablePath, "play.bat"), - // "start shapezio --dev --disable-direct-composition --in-process-gpu\r\n" - // ); - // fs.writeFileSync( - // path.join(playablePath, "play_local.bat"), - // "start shapezio --local --dev --disable-direct-composition --in-process-gpu\r\n" - // ); } if (platform === "darwin") { @@ -226,11 +170,11 @@ function gulptasksStandalone($, gulp, buildFolder) { ); } - gulp.task("standalone.package.prod.win64", cb => packageStandalone("win32", "x64", cb, true)); - gulp.task("standalone.package.prod.win32", cb => packageStandalone("win32", "ia32", cb, true)); - gulp.task("standalone.package.prod.linux64", cb => packageStandalone("linux", "x64", cb, true)); - gulp.task("standalone.package.prod.linux32", cb => packageStandalone("linux", "ia32", cb, true)); - gulp.task("standalone.package.prod.darwin64", cb => packageStandalone("darwin", "x64", cb, true)); + gulp.task("standalone.package.prod.win64", cb => packageStandalone("win32", "x64", cb)); + gulp.task("standalone.package.prod.win32", cb => packageStandalone("win32", "ia32", cb)); + gulp.task("standalone.package.prod.linux64", cb => packageStandalone("linux", "x64", cb)); + gulp.task("standalone.package.prod.linux32", cb => packageStandalone("linux", "ia32", cb)); + gulp.task("standalone.package.prod.darwin64", cb => packageStandalone("darwin", "x64", cb)); gulp.task( "standalone.package.prod", @@ -240,8 +184,6 @@ function gulptasksStandalone($, gulp, buildFolder) { "standalone.package.prod.win64", "standalone.package.prod.linux64", "standalone.package.prod.darwin64" - // "standalone.package.prod.win32", - // "standalone.package.prod.linux32", ) ) ); diff --git a/gulp/translations.js b/gulp/translations.js index 50404390..56054476 100644 --- a/gulp/translations.js +++ b/gulp/translations.js @@ -5,7 +5,7 @@ const yaml = require("gulp-yaml"); const translationsSourceDir = path.join(__dirname, "..", "translations"); const translationsJsonDir = path.join(__dirname, "..", "src", "js", "built-temp"); -function gulptasksTranslations($, gulp, buildFolder) { +function gulptasksTranslations($, gulp) { gulp.task("translations.convertToJson", () => { return gulp .src(path.join(translationsSourceDir, "*.yaml")) diff --git a/gulp/webpack.config.js b/gulp/webpack.config.js index 022e2773..6e1d7388 100644 --- a/gulp/webpack.config.js +++ b/gulp/webpack.config.js @@ -2,9 +2,8 @@ const path = require("path"); const webpack = require("webpack"); -const utils = require("./buildutils"); +const { getRevision, getVersion, getAllResourceImages } = require("./buildutils"); const lzString = require("lz-string"); -// const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin; const CircularDependencyPlugin = require("circular-dependency-plugin"); module.exports = ({ watch = false, standalone = false }) => { @@ -41,9 +40,9 @@ module.exports = ({ watch = false, standalone = false }) => { G_IS_BROWSER: "true", G_IS_STANDALONE: standalone ? "true" : "false", G_BUILD_TIME: "" + new Date().getTime(), - G_BUILD_COMMIT_HASH: JSON.stringify(utils.getRevision()), - G_BUILD_VERSION: JSON.stringify(utils.getVersion()), - G_ALL_UI_IMAGES: JSON.stringify(utils.getAllResourceImages()), + G_BUILD_COMMIT_HASH: JSON.stringify(getRevision()), + G_BUILD_VERSION: JSON.stringify(getVersion()), + G_ALL_UI_IMAGES: JSON.stringify(getAllResourceImages()), }), new CircularDependencyPlugin({ @@ -60,7 +59,6 @@ module.exports = ({ watch = false, standalone = false }) => { // set the current working directory for displaying module paths cwd: path.join(__dirname, "..", "src", "js"), }), - // new BundleAnalyzerPlugin() ], module: { rules: [ @@ -94,6 +92,16 @@ module.exports = ({ watch = false, standalone = false }) => { }, ], }, + { + test: /\.worker\.js$/, + use: { + loader: "worker-loader", + options: { + fallback: false, + inline: true, + }, + }, + }, { test: /\.ya?ml$/, type: "json", // Required by Webpack v4 diff --git a/gulp/webpack.production.config.js b/gulp/webpack.production.config.js index 1b89283f..c26bca68 100644 --- a/gulp/webpack.production.config.js +++ b/gulp/webpack.production.config.js @@ -2,14 +2,12 @@ const path = require("path"); const webpack = require("webpack"); -const utils = require("./buildutils"); +const { getRevision, getVersion, getAllResourceImages } = require("./buildutils"); const lzString = require("lz-string"); const TerserPlugin = require("terser-webpack-plugin"); const StringReplacePlugin = require("string-replace-webpack-plugin"); -// const BundleAnalyzerPlugin = require("webpack-bundle-analyzer").BundleAnalyzerPlugin; const UnusedFilesPlugin = require("unused-files-webpack-plugin").UnusedFilesWebpackPlugin; -// const SpeedMeasurePlugin = require("speed-measure-webpack-plugin"); module.exports = ({ enableAssert = false, @@ -34,9 +32,9 @@ module.exports = ({ G_APP_ENVIRONMENT: JSON.stringify(environment), G_HAVE_ASSERT: enableAssert ? "true" : "false", G_BUILD_TIME: "" + new Date().getTime(), - G_BUILD_COMMIT_HASH: JSON.stringify(utils.getRevision()), - G_BUILD_VERSION: JSON.stringify(utils.getVersion()), - G_ALL_UI_IMAGES: JSON.stringify(utils.getAllResourceImages()), + G_BUILD_COMMIT_HASH: JSON.stringify(getRevision()), + G_BUILD_VERSION: JSON.stringify(getVersion()), + G_ALL_UI_IMAGES: JSON.stringify(getAllResourceImages()), }; const minifyNames = environment === "prod"; @@ -143,9 +141,9 @@ module.exports = ({ ecma: es6 ? 6 : 5, preamble: "/* shapez.io Codebase - Copyright 2020 Tobias Springer - " + - utils.getVersion() + + getVersion() + " @ " + - utils.getRevision() + + getRevision() + " */", }, }, @@ -164,15 +162,6 @@ module.exports = ({ cwd: path.join(__dirname, "..", "src", "js"), patterns: ["../src/js/**/*.js"], }), - - // new webpack.SourceMapDevToolPlugin({ - // filename: "[name].map", - // publicPath: "/v/" + utils.getRevision() + "/", - // }), - // new ReplaceCompressBlocks() - // new webpack.optimize.ModuleConcatenationPlugin() - // new WebpackDeepScopeAnalysisPlugin() - // new BundleAnalyzerPlugin() ], module: { rules: [ diff --git a/gulp/yarn.lock b/gulp/yarn.lock index 37fbfbb0..d0628aa3 100644 --- a/gulp/yarn.lock +++ b/gulp/yarn.lock @@ -718,21 +718,6 @@ js-levenshtein "^1.1.3" semver "^5.5.0" -"@babel/runtime@7.0.0-beta.42": - version "7.0.0-beta.42" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.0.0-beta.42.tgz#352e40c92e0460d3e82f49bd7e79f6cda76f919f" - integrity sha512-iOGRzUoONLOtmCvjUsZv3mZzgCT6ljHQY5fr1qG1QIiJQwtM7zbPWGGpa3QWETq+UqwWyJnoi5XZDZRwZDFciQ== - dependencies: - core-js "^2.5.3" - regenerator-runtime "^0.11.1" - -"@babel/runtime@7.0.0-rc.1": - version "7.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.0.0-rc.1.tgz#42f36fc5817911c89ea75da2b874054922967616" - integrity sha512-Nifv2kwP/nwR39cAOasNxzjYfpeuf/ZbZNtQz5eYxWTC9yHARU9wItFnAwz1GTZ62MU+AtSjzZPMbLK5Q9hmbg== - dependencies: - regenerator-runtime "^0.12.0" - "@babel/runtime@^7.5.5": version "7.9.2" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.9.2.tgz#d90df0583a3a252f09aaa619665367bae518db06" @@ -1328,7 +1313,7 @@ abbrev@1: resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== -accepts@~1.3.4, accepts@~1.3.7: +accepts@~1.3.4: version "1.3.7" resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.7.tgz#531bc726517a3b2b41f850021c6cc15eaab507cd" integrity sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA== @@ -1351,19 +1336,12 @@ acorn-jsx@^3.0.0: dependencies: acorn "^3.0.4" -acorn-jsx@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-4.1.1.tgz#e8e41e48ea2fe0c896740610ab6a4ffd8add225e" - integrity sha512-JY+iV6r+cO21KtntVvFkD+iqjtdpRUpGqKWgfkCdZq1R+kbreEl8EcdcJR4SmiIgsIQT33s6QzheQ9a275Q8xw== - dependencies: - acorn "^5.0.3" - acorn-jsx@^5.0.0: version "5.0.2" resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.0.2.tgz#84b68ea44b373c4f8686023a551f61a21b7c4a4f" integrity sha512-tiNTrP1MP0QrChmD2DdupCr6HWSFeKVw5d/dHTu4Y7rkAkRhU/Dt7dphAfIUyxtHpl/eBVip5uTNSpQJHylpAw== -acorn-walk@^6.0.1, acorn-walk@^6.1.1: +acorn-walk@^6.0.1: version "6.2.0" resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-6.2.0.tgz#123cb8f3b84c2171f1f7fb252615b1c78a6b1a8c" integrity sha512-7evsyfH1cLOCdAzZAd43Cic04yKydNx0cF+7tiA19p1XnLLPU4dpCQOqpjqwokFe//vS0QqfqqjCS2JkiIs0cA== @@ -1373,7 +1351,7 @@ acorn@^3.0.4: resolved "https://registry.yarnpkg.com/acorn/-/acorn-3.3.0.tgz#45e37fb39e8da3f25baee3ff5369e2bb5f22017a" integrity sha1-ReN/s56No/JbruP/U2niu18iAXo= -acorn@^5.0.3, acorn@^5.5.0, acorn@^5.6.0: +acorn@^5.5.0: version "5.7.3" resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.7.3.tgz#67aa231bf8812974b85235a96771eb6bd07ea279" integrity sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw== @@ -1453,7 +1431,7 @@ ansi-colors@^1.0.1: dependencies: ansi-wrap "^0.1.0" -ansi-colors@^4.1.0, ansi-colors@^4.1.1: +ansi-colors@^4.1.0: version "4.1.1" resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348" integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA== @@ -1685,11 +1663,6 @@ array-find-index@^1.0.1: resolved "https://registry.yarnpkg.com/array-find-index/-/array-find-index-1.0.2.tgz#df010aa1287e164bbda6f9723b0a96a1ec4187a1" integrity sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E= -array-flatten@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" - integrity sha1-ml9pkFGx5wczKPKgCJaLZOopVdI= - array-initial@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/array-initial/-/array-initial-1.1.0.tgz#2fa74b26739371c3947bd7a7adc73be334b3d795" @@ -1724,19 +1697,12 @@ array-sort@^1.0.0: get-value "^2.0.6" kind-of "^5.0.2" -array-union@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/array-union/-/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39" - integrity sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk= - dependencies: - array-uniq "^1.0.1" - array-union@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== -array-uniq@^1.0.1, array-uniq@^1.0.2: +array-uniq@^1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6" integrity sha1-r2rId6Jcx/dOBYiUdThY39sk/bY= @@ -1756,11 +1722,6 @@ arraybuffer.slice@~0.0.7: resolved "https://registry.yarnpkg.com/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz#3bbc4275dd584cc1b10809b89d4e8b63a69e7675" integrity sha512-wGUIVQXuehL5TCqQun8OW81jGzAWycqzFF8lFp+GOM5BXLYj3bKNsYC4daB7n6XjCqxQA/qgTJ+8ANR3acjrog== -arrify@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" - integrity sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0= - asar@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/asar/-/asar-2.0.1.tgz#8518a1c62c238109c15a5f742213e83a09b9fd38" @@ -1995,23 +1956,6 @@ babel-plugin-dynamic-import-node@^2.3.0: dependencies: object.assign "^4.1.0" -babel-polyfill@6.23.0: - version "6.23.0" - resolved "https://registry.yarnpkg.com/babel-polyfill/-/babel-polyfill-6.23.0.tgz#8364ca62df8eafb830499f699177466c3b03499d" - integrity sha1-g2TKYt+Or7gwSZ9pkXdGbDsDSZ0= - dependencies: - babel-runtime "^6.22.0" - core-js "^2.4.0" - regenerator-runtime "^0.10.0" - -babel-runtime@^6.22.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe" - integrity sha1-llxwWGaOgrVde/4E/yM3vItWR/4= - dependencies: - core-js "^2.4.0" - regenerator-runtime "^0.11.0" - babel-runtime@^7.0.0-beta.3: version "7.0.0-beta.3" resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-7.0.0-beta.3.tgz#7c750de5514452c27612172506b49085a4a630f2" @@ -2097,16 +2041,6 @@ better-assert@~1.0.0: dependencies: callsite "1.0.0" -bfj@^6.1.1: - version "6.1.2" - resolved "https://registry.yarnpkg.com/bfj/-/bfj-6.1.2.tgz#325c861a822bcb358a41c78a33b8e6e2086dde7f" - integrity sha512-BmBJa4Lip6BPRINSZ0BPEIfB1wUY/9rwbwvIHQA1KjX9om29B6id0wnWXq7m3bn5JrUVjeOTnVuhPT1FiHwPGw== - dependencies: - bluebird "^3.5.5" - check-types "^8.0.3" - hoopy "^0.1.4" - tryer "^1.0.1" - big.js@^3.1.3: version "3.2.0" resolved "https://registry.yarnpkg.com/big.js/-/big.js-3.2.0.tgz#a5fc298b81b9e0dca2e458824784b65c52ba588e" @@ -2224,22 +2158,6 @@ bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.1.1, bn.js@^4.4.0: resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.8.tgz#2cde09eb5ee341f484746bb0309b3253b1b1442f" integrity sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA== -body-parser@1.19.0: - version "1.19.0" - resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.19.0.tgz#96b2709e57c9c4e09a6fd66a8fd979844f69f08a" - integrity sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw== - dependencies: - bytes "3.1.0" - content-type "~1.0.4" - debug "2.6.9" - depd "~1.1.2" - http-errors "1.7.2" - iconv-lite "0.4.24" - on-finished "~2.3.0" - qs "6.7.0" - raw-body "2.4.0" - type-is "~1.6.17" - body-parser@~1.8.0: version "1.8.4" resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.8.4.tgz#d497e04bc13b3f9a8bd8c70bb0cdc16f2e028898" @@ -2734,36 +2652,7 @@ caw@^2.0.0, caw@^2.0.1: tunnel-agent "^0.6.0" url-to-options "^1.0.1" -chalk@1.1.3, chalk@^1.0.0, chalk@^1.1.1, chalk@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" - integrity sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg= - dependencies: - ansi-styles "^2.2.1" - escape-string-regexp "^1.0.2" - has-ansi "^2.0.0" - strip-ansi "^3.0.0" - supports-color "^2.0.0" - -chalk@2.3.2: - version "2.3.2" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.3.2.tgz#250dc96b07491bfd601e648d66ddf5f60c7a5c65" - integrity sha512-ZM4j2/ld/YZDc3Ma8PgN7gyAk+kHMMMyzLNryCPGhWrsfAuDVeuid5bpRFTDgMH9JBK2lA4dyyAkkZYF/WcqDQ== - dependencies: - ansi-styles "^3.2.1" - escape-string-regexp "^1.0.5" - supports-color "^5.3.0" - -chalk@2.4.1: - version "2.4.1" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.1.tgz#18c49ab16a037b6eb0152cc83e3471338215b66e" - integrity sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ== - dependencies: - ansi-styles "^3.2.1" - escape-string-regexp "^1.0.5" - supports-color "^5.3.0" - -chalk@2.4.2, chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.3.0, chalk@^2.4.1, chalk@^2.4.2: +chalk@2.4.2, chalk@^2.0.0, chalk@^2.1.0, chalk@^2.3.0, chalk@^2.4.1, chalk@^2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== @@ -2783,6 +2672,17 @@ chalk@^0.5.0: strip-ansi "^0.3.0" supports-color "^0.2.0" +chalk@^1.0.0, chalk@^1.1.1, chalk@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" + integrity sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg= + dependencies: + ansi-styles "^2.2.1" + escape-string-regexp "^1.0.2" + has-ansi "^2.0.0" + strip-ansi "^3.0.0" + supports-color "^2.0.0" + chalk@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/chalk/-/chalk-3.0.0.tgz#3f73c2bf526591f574cc492c51e2456349f844e4" @@ -2791,36 +2691,11 @@ chalk@^3.0.0: ansi-styles "^4.1.0" supports-color "^7.1.0" -chance@1.0.13: - version "1.0.13" - resolved "https://registry.yarnpkg.com/chance/-/chance-1.0.13.tgz#666bec2db42b3084456a3e4f4c28a82db5ccb7e6" - integrity sha512-9cpcgmAIQiXC0eMgQuMZgXuHR2Y+gKUyGQnalqSAg5LlUJyJFsZeKyuHVSGhj+bx18ppH+Jo3VOayNeXR/7p9Q== - -chance@1.0.16: - version "1.0.16" - resolved "https://registry.yarnpkg.com/chance/-/chance-1.0.16.tgz#bd61912716b0010c3dca8e3948a960efcaa7bb1b" - integrity sha512-2bgDHH5bVfAXH05SPtjqrsASzZ7h90yCuYT2z4mkYpxxYvJXiIydBFzVieVHZx7wLH1Ag2Azaaej2/zA1XUrNQ== - -chardet@^0.4.0: - version "0.4.2" - resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.4.2.tgz#b5473b33dc97c424e5d98dc87d55d4d8a29c8bf2" - integrity sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I= - chardet@^0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA== -charenc@~0.0.1: - version "0.0.2" - resolved "https://registry.yarnpkg.com/charenc/-/charenc-0.0.2.tgz#c0a1d2f3a7092e03774bfa83f14c0fc5790a8667" - integrity sha1-wKHS86cJLgN3S/qD8UwPxXkKhmc= - -check-types@^8.0.3: - version "8.0.3" - resolved "https://registry.yarnpkg.com/check-types/-/check-types-8.0.3.tgz#3356cca19c889544f2d7a95ed49ce508a0ecf552" - integrity sha512-YpeKZngUmG65rLudJ4taU7VLkOCTMhNl/u4ctNC56LQS/zJTyNH0Lrtwm1tfTsbLlwvlfsA2d1c8vCf/Kh2KwQ== - chokidar@^2.0.0, chokidar@^2.1.8: version "2.1.8" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.1.8.tgz#804b3a7b6a99358c3c5c61e71d8728f041cff917" @@ -2905,21 +2780,6 @@ class-utils@^0.3.5: isobject "^3.0.0" static-extend "^0.1.1" -class-validator@0.8.5: - version "0.8.5" - resolved "https://registry.yarnpkg.com/class-validator/-/class-validator-0.8.5.tgz#484785acda98f68549c3a84dc1bb2f77b736dc58" - integrity sha512-84yezRo44aP4oGhvPmqj6obAFQF1NzUyfR0+f8jubzdAspO5pmjpHhBBlPf335epUskzXAFe5uo4Qf+c7SI+DA== - dependencies: - validator "9.2.0" - -class-validator@0.9.1: - version "0.9.1" - resolved "https://registry.yarnpkg.com/class-validator/-/class-validator-0.9.1.tgz#d60e58c5d14abca0a41bce38cf792ad4c46d1531" - integrity sha512-3wApflrd3ywVZyx4jaasGoFt8pmo4aGLPPAEKCKCsTRWVGPilahD88q3jQjRQwja50rl9a7rsP5LAxJYwGK8/Q== - dependencies: - google-libphonenumber "^3.1.6" - validator "10.4.0" - clean-css@4.2.x: version "4.2.1" resolved "https://registry.yarnpkg.com/clean-css/-/clean-css-4.2.1.tgz#2d411ef76b8569b6d0c84068dabe85b0aa5e5c17" @@ -3010,7 +2870,7 @@ clone@^1.0.0, clone@^1.0.2: resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e" integrity sha1-2jCcwmPfFZlMaIypAheco8fNfH4= -clone@^2.1.1, clone@~2.1.0: +clone@^2.1.1: version "2.1.2" resolved "https://registry.yarnpkg.com/clone/-/clone-2.1.2.tgz#1b7f4b9f591f1e8f83670401600345a02887435f" integrity sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18= @@ -3122,17 +2982,12 @@ combined-stream@^1.0.6, combined-stream@~1.0.6: dependencies: delayed-stream "~1.0.0" -commander@2.15.1: - version "2.15.1" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.15.1.tgz#df46e867d0fc2aec66a34662b406a9ccafff5b0f" - integrity sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag== - -commander@2.17.1, commander@2.17.x: +commander@2.17.x: version "2.17.1" resolved "https://registry.yarnpkg.com/commander/-/commander-2.17.1.tgz#bd77ab7de6de94205ceacc72f1716d29f20a77bf" integrity sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg== -commander@^2.18.0, commander@^2.19.0, commander@^2.2.0, commander@^2.20.0, commander@^2.8.1: +commander@^2.19.0, commander@^2.2.0, commander@^2.20.0, commander@^2.8.1: version "2.20.0" resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.0.tgz#d58bb2b5c1ee8f87b0d340027e9e94e222c5a422" integrity sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ== @@ -3273,18 +3128,13 @@ constants-browserify@^1.0.0: resolved "https://registry.yarnpkg.com/constants-browserify/-/constants-browserify-1.0.0.tgz#c20b96d8c617748aaf1c16021760cd27fcb8cb75" integrity sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U= -content-disposition@0.5.3, content-disposition@^0.5.2: +content-disposition@^0.5.2: version "0.5.3" resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.3.tgz#e130caf7e7279087c5616c2007d0485698984fbd" integrity sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g== dependencies: safe-buffer "5.1.2" -content-type@~1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b" - integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA== - convert-source-map@^1.5.0, convert-source-map@^1.7.0: version "1.7.0" resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.7.0.tgz#17a2cb882d7f77d3490585e2ce6c524424a3a442" @@ -3292,21 +3142,11 @@ convert-source-map@^1.5.0, convert-source-map@^1.7.0: dependencies: safe-buffer "~5.1.1" -cookie-signature@1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" - integrity sha1-4wOogrNCzD7oylE6eZmXNNqzriw= - cookie@0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.3.1.tgz#e7e0a1f9ef43b4c8ba925c5c5a96e806d16873bb" integrity sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s= -cookie@0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.0.tgz#beb437e7022b3b6d49019d088665303ebe9c14ba" - integrity sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg== - copy-concurrently@^1.0.0: version "1.0.5" resolved "https://registry.yarnpkg.com/copy-concurrently/-/copy-concurrently-1.0.5.tgz#92297398cae34937fcafd6ec8139c18051f0b5e0" @@ -3345,7 +3185,7 @@ core-js@3: resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.2.1.tgz#cd41f38534da6cc59f7db050fe67307de9868b09" integrity sha512-Qa5XSVefSVPRxy2XfUC13WbvqkxhkwB3ve+pgCQveNgYzbM/UxZeu1dcOX/xr4UmfUd+muuvsaxilQzCyUurMw== -core-js@^2.4.0, core-js@^2.5.3, core-js@^2.5.7: +core-js@^2.4.0, core-js@^2.5.7: version "2.6.9" resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.9.tgz#6b4b214620c834152e179323727fc19741b084f2" integrity sha512-HOpZf6eXmnl7la+cUdMnLvUxKNqLUzJvgIziQ0DiF3JwSImNphIqdGqzj6hIKyX04MmV0poclQ7+wjWvxQyR2A== @@ -3355,7 +3195,7 @@ core-util-is@1.0.2, core-util-is@~1.0.0: resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= -cosmiconfig@^5.0.0, cosmiconfig@^5.2.1: +cosmiconfig@^5.0.0: version "5.2.1" resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-5.2.1.tgz#040f726809c591e77a17c0a3626ca45b4f168b1a" integrity sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA== @@ -3448,11 +3288,6 @@ cross-zip@^2.1.5: dependencies: rimraf "^3.0.0" -crypt@~0.0.1: - version "0.0.2" - resolved "https://registry.yarnpkg.com/crypt/-/crypt-0.0.2.tgz#88d7ff7ec0dfb86f713dc87bbb42d044d3e6c41b" - integrity sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs= - crypto-browserify@^3.11.0: version "3.12.0" resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.12.0.tgz#396cf9f3137f03e4b8e532c58f698254e00f80ec" @@ -3568,11 +3403,6 @@ css-what@^2.1.2: resolved "https://registry.yarnpkg.com/css-what/-/css-what-2.1.3.tgz#a6d7604573365fe74686c3f311c56513d88285f2" integrity sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg== -cssbeautify@^0.3.1: - version "0.3.1" - resolved "https://registry.yarnpkg.com/cssbeautify/-/cssbeautify-0.3.1.tgz#12dd1f734035c2e6faca67dcbdcef74e42811397" - integrity sha1-Et0fc0A1wub6ymfcvc73TkKBE5c= - cssdb@^4.4.0: version "4.4.0" resolved "https://registry.yarnpkg.com/cssdb/-/cssdb-4.4.0.tgz#3bf2f2a68c10f5c6a08abd92378331ee803cddb0" @@ -3583,14 +3413,6 @@ cssesc@^2.0.0: resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-2.0.0.tgz#3b13bd1bb1cb36e1bcb5a4dcd27f54c5dcb35703" integrity sha512-MsCAG1z9lPdoO/IUMLSBWBSVxVtJ1395VGIQ+Fc2gNdkQ1hNDnQdw3YhA71WJCBW1vdwA0cAnk/DnW6bqoEUYg== -csslint@^1.0.2: - version "1.0.5" - resolved "https://registry.yarnpkg.com/csslint/-/csslint-1.0.5.tgz#19cc3eda322160fd3f7232af1cb2a360e898a2e9" - integrity sha1-Gcw+2jIhYP0/cjKvHLKjYOiYouk= - dependencies: - clone "~2.1.0" - parserlib "~1.1.1" - cssnano-preset-advanced@^4.0.7: version "4.0.7" resolved "https://registry.yarnpkg.com/cssnano-preset-advanced/-/cssnano-preset-advanced-4.0.7.tgz#d981527b77712e2f3f3f09c73313e9b71b278b88" @@ -4124,11 +3946,6 @@ duplexer3@^0.1.4: resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2" integrity sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI= -duplexer@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.1.tgz#ace6ff808c1ce66b57d1ebf97977acb02334cfc1" - integrity sha1-rOb/gIwc5mtX0ev5eXessCM0z8E= - duplexify@^3.4.2, duplexify@^3.6.0: version "3.7.1" resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-3.7.1.tgz#2a4df5317f6ccfd91f86d6fd25d8d8a103b88309" @@ -4199,11 +4016,6 @@ ee-first@1.1.1: resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= -ejs@^2.6.1: - version "2.7.1" - resolved "https://registry.yarnpkg.com/ejs/-/ejs-2.7.1.tgz#5b5ab57f718b79d4aca9254457afecd36fa80228" - integrity sha512-kS/gEPzZs3Y1rRsbGX4UOSjtP/CeJP0CxSNZHYxGfVM/VgLcv0ZqM7C45YyTj2DI2g7+P9Dd24C+IMIg6D0nYQ== - electron-notarize@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/electron-notarize/-/electron-notarize-0.1.1.tgz#c3563d70c5e7b3315f44e8495b30050a8c408b91" @@ -4295,13 +4107,6 @@ encodeurl@~1.0.1, encodeurl@~1.0.2: resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k= -encoding@^0.1.11: - version "0.1.12" - resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.12.tgz#538b66f3ee62cd1ab51ec323829d1f9480c74beb" - integrity sha1-U4tm8+5izRq1HsMjgp0flIDHS+s= - dependencies: - iconv-lite "~0.4.13" - end-of-stream@^1.0.0, end-of-stream@^1.1.0: version "1.4.1" resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.1.tgz#ed29634d19baba463b6ce6b80a37213eab71ec43" @@ -4534,30 +4339,6 @@ escape-string-regexp@^1.0.0, escape-string-regexp@^1.0.2, escape-string-regexp@^ resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= -escodegen-wallaby@1.6.18: - version "1.6.18" - resolved "https://registry.yarnpkg.com/escodegen-wallaby/-/escodegen-wallaby-1.6.18.tgz#95a41e2fdc88687466e43550c7bf136386fd4363" - integrity sha512-3UvR14JRNh8VfKJixTDHWmhPNKAJiVZS807KUjECBk6f05WMe8ZeWL1gbrswNYhDiAUeDBQccyTWR91fayx3og== - dependencies: - esprima "^2.7.1" - estraverse "^1.9.1" - esutils "^2.0.2" - optionator "^0.8.1" - optionalDependencies: - source-map "~0.2.0" - -escodegen-wallaby@1.6.19: - version "1.6.19" - resolved "https://registry.yarnpkg.com/escodegen-wallaby/-/escodegen-wallaby-1.6.19.tgz#acd6bbd73f9270763e18570cdc13c0d694759a23" - integrity sha512-q+JGvR5+NR+EJBLnGAevCk5PIiIhPkUFCvcm6w9MWYtm8sv4FdGUsgzWsY6At/YHkgMyA366sjphA/JTNC8CeQ== - dependencies: - esprima "^2.7.1" - estraverse "^1.9.1" - esutils "^2.0.2" - optionator "^0.8.1" - optionalDependencies: - source-map "~0.2.0" - escodegen@^1.11.0: version "1.12.0" resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.12.0.tgz#f763daf840af172bb3a2b6dd7219c0e17f7ff541" @@ -4681,7 +4462,7 @@ eslint@^5.9.0: table "^5.2.3" text-table "^0.2.0" -espree@3.5.4, espree@^3.1.6: +espree@^3.1.6: version "3.5.4" resolved "https://registry.yarnpkg.com/espree/-/espree-3.5.4.tgz#b0f447187c8a8bed944b815a660bddf5deb5d1a7" integrity sha512-yAcIQxtmMiB/jL32dzEp2enBeidsB7xWPLNiw3IIkpVds1P+h7qF9YwJq1yUNzp2OKXgAprs4F61ih66UsoD1A== @@ -4689,14 +4470,6 @@ espree@3.5.4, espree@^3.1.6: acorn "^5.5.0" acorn-jsx "^3.0.0" -espree@4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/espree/-/espree-4.0.0.tgz#253998f20a0f82db5d866385799d912a83a36634" - integrity sha512-kapdTCt1bjmspxStVKX6huolXVV5ZfyZguY1lcfhVVZstce3bqxH9mcLzNn3/mlgW6wQ732+0fuG9v7h0ZQoKg== - dependencies: - acorn "^5.6.0" - acorn-jsx "^4.1.1" - espree@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/espree/-/espree-5.0.1.tgz#5d6526fa4fc7f0788a5cf75b15f30323e2f81f7a" @@ -4706,11 +4479,6 @@ espree@^5.0.1: acorn-jsx "^5.0.0" eslint-visitor-keys "^1.0.0" -esprima@^2.7.1: - version "2.7.3" - resolved "https://registry.yarnpkg.com/esprima/-/esprima-2.7.3.tgz#96e3b70d5779f6ad49cd032673d1c312767ba581" - integrity sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE= - esprima@^3.1.3, esprima@~3.1.0: version "3.1.3" resolved "https://registry.yarnpkg.com/esprima/-/esprima-3.1.3.tgz#fdca51cee6133895e3c88d535ce49dbff62a4633" @@ -4735,16 +4503,6 @@ esrecurse@^4.1.0, esrecurse@^4.2.1: dependencies: estraverse "^4.1.0" -estraverse@4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.2.0.tgz#0dee3fed31fcd469618ce7342099fc1afa0bdb13" - integrity sha1-De4/7TH81GlhjOc0IJn8GvoL2xM= - -estraverse@^1.9.1: - version "1.9.3" - resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-1.9.3.tgz#af67f2dc922582415950926091a4005d29c9bb44" - integrity sha1-r2fy3JIlgkFZUJJgkaQAXSnJu0Q= - estraverse@^4.0.0, estraverse@^4.1.0, estraverse@^4.1.1, estraverse@^4.2.0: version "4.3.0" resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" @@ -4888,42 +4646,6 @@ expand-tilde@^2.0.0, expand-tilde@^2.0.2: dependencies: homedir-polyfill "^1.0.1" -express@^4.16.3: - version "4.17.1" - resolved "https://registry.yarnpkg.com/express/-/express-4.17.1.tgz#4491fc38605cf51f8629d39c2b5d026f98a4c134" - integrity sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g== - dependencies: - accepts "~1.3.7" - array-flatten "1.1.1" - body-parser "1.19.0" - content-disposition "0.5.3" - content-type "~1.0.4" - cookie "0.4.0" - cookie-signature "1.0.6" - debug "2.6.9" - depd "~1.1.2" - encodeurl "~1.0.2" - escape-html "~1.0.3" - etag "~1.8.1" - finalhandler "~1.1.2" - fresh "0.5.2" - merge-descriptors "1.0.1" - methods "~1.1.2" - on-finished "~2.3.0" - parseurl "~1.3.3" - path-to-regexp "0.1.7" - proxy-addr "~2.0.5" - qs "6.7.0" - range-parser "~1.2.1" - safe-buffer "5.1.2" - send "0.17.1" - serve-static "1.14.1" - setprototypeof "1.1.1" - statuses "~1.5.0" - type-is "~1.6.18" - utils-merge "1.0.1" - vary "~1.1.2" - ext-list@^2.0.0: version "2.2.2" resolved "https://registry.yarnpkg.com/ext-list/-/ext-list-2.2.2.tgz#0b98e64ed82f5acf0f2931babf69212ef52ddd37" @@ -4966,15 +4688,6 @@ extend@^3.0.0, extend@~3.0.2: resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== -external-editor@^2.0.1: - version "2.2.0" - resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-2.2.0.tgz#045511cfd8d133f3846673d1047c154e214ad3d5" - integrity sha512-bSn6gvGxKt+b7+6TKEv1ZycHleA7aHhRHyAqJyp5pbUFuYYNIzpZnQDk7AsYckyWdEnTeAnay0aCy2aV6iTk9A== - dependencies: - chardet "^0.4.0" - iconv-lite "^0.4.17" - tmp "^0.0.33" - external-editor@^3.0.3: version "3.1.0" resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-3.1.0.tgz#cb03f740befae03ea4d283caed2741a83f335495" @@ -5189,11 +4902,6 @@ filenamify@^2.0.0: strip-outer "^1.0.0" trim-repeated "^1.0.0" -filesize@^3.6.1: - version "3.6.1" - resolved "https://registry.yarnpkg.com/filesize/-/filesize-3.6.1.tgz#090bb3ee01b6f801a8a8be99d31710b3422bb317" - integrity sha512-7KjR1vv6qnicaPMi1iiTcI85CyYwRO/PSFCu6SvqL8jN2Wjt/NIYQTFtFs7fSDCYOstUkEWIQGFUg5YZQfjlcg== - fill-range@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7" @@ -5224,7 +4932,7 @@ finalhandler@1.1.0: statuses "~1.3.1" unpipe "~1.0.0" -finalhandler@1.1.2, finalhandler@~1.1.2: +finalhandler@1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.2.tgz#b7e7d000ffd11938d0fdb053506f6ebabe9f587d" integrity sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA== @@ -5443,11 +5151,6 @@ form-data@~2.3.2: combined-stream "^1.0.6" mime-types "^2.1.12" -forwarded@~0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.1.2.tgz#98c23dab1175657b8c0573e8ceccd91b0ff18c84" - integrity sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ= - fragment-cache@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19" @@ -5962,11 +5665,6 @@ gonzales-pe@^4.2.3: dependencies: minimist "1.1.x" -google-libphonenumber@^3.1.6: - version "3.2.5" - resolved "https://registry.yarnpkg.com/google-libphonenumber/-/google-libphonenumber-3.2.5.tgz#2ebe6437fd3dbbffd65f4339ad1ba93b3dc56836" - integrity sha512-Y0r7MFCI11UDLn0KaMPBEInhROyIOkWkQIyvWMFVF2I+h+sHE3vbl5a7FVe39td6u/w+nlKDdUMP9dMOZyv+2Q== - got@^7.0.0: version "7.1.0" resolved "https://registry.yarnpkg.com/got/-/got-7.1.0.tgz#05450fd84094e6bbea56f451a43a9c289166385a" @@ -6119,27 +5817,6 @@ gulp-cli@^2.2.0: v8flags "^3.2.0" yargs "^7.1.0" -gulp-cssbeautify@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/gulp-cssbeautify/-/gulp-cssbeautify-2.0.1.tgz#39903a8fa0b4f384f20d4eb4bc6591d83c4e47ac" - integrity sha512-IOFGr2KQuO9koeQ5i0aWFhyUU4DBXmIHHblE5xfVxQEzPy5YXdKb54maP1sXTIDDhihilL+y3RhcCcxStem4Ig== - dependencies: - cssbeautify "^0.3.1" - plugin-error "^1.0.1" - through2 "^3.0.1" - -gulp-csslint@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/gulp-csslint/-/gulp-csslint-1.0.1.tgz#112a908f7aef98efc27b7bd00801f13a77becb93" - integrity sha512-Rec56+RpCGg7feK3d/S45oqgxyLV3end0ed+UjWFv6YziQae2Bp4DNSDobwEvJdfCAsOhOSExEEB+jcfMx430w== - dependencies: - csslint "^1.0.2" - fancy-log "^1.3.2" - plugin-error "^1.0.1" - rcloader "^0.2.1" - through2 "^2.0.1" - vinyl "^2.1.0" - gulp-dom@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/gulp-dom/-/gulp-dom-1.0.0.tgz#f834d5299c09b85e11c32505044a2ebe86ae1375" @@ -6212,29 +5889,6 @@ gulp-imagemin@^7.1.0: imagemin-optipng "^7.0.0" imagemin-svgo "^7.0.0" -gulp-javascript-obfuscator@^1.1.5: - version "1.1.6" - resolved "https://registry.yarnpkg.com/gulp-javascript-obfuscator/-/gulp-javascript-obfuscator-1.1.6.tgz#4615ce5adb6a0f846246aacea8e1402d8fe04e06" - integrity sha512-oiROhi7Zlu/0fM2h20jBFPaDOZicilT6kN+97Si82yieeFqr6l70o2R3gZ2Ah0u8v5IqGa+Pt8c2q3UnkMuk2A== - dependencies: - javascript-obfuscator latest - plugin-error "^1.0.1" - through2 "^2.0.0" - vinyl "^2.2.0" - -gulp-jsbeautifier@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/gulp-jsbeautifier/-/gulp-jsbeautifier-3.0.1.tgz#4b26991e0adf063130452c5d74910239fadbf254" - integrity sha512-zSXsXQy0/s6qjhhtTun+/ZfC/q8cz/fZpZmxoGPKpmxjuP7/F+oGpV/LHqtOAaWNo+WjcxLVey0cFoNrPZiHWg== - dependencies: - ansi-colors "^4.1.1" - cosmiconfig "^5.2.1" - fancy-log "^1.3.3" - js-beautify "^1.10.1" - lodash.mergewith "^4.6.2" - plugin-error "^1.0.1" - through2 "^3.0.1" - gulp-load-plugins@^2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/gulp-load-plugins/-/gulp-load-plugins-2.0.3.tgz#5f275c0b7f1925d8a1ce57cbd5c346d6af6b64fb" @@ -6455,14 +6109,6 @@ gulplog@^1.0.0: dependencies: glogg "^1.0.0" -gzip-size@^5.0.0: - version "5.1.1" - resolved "https://registry.yarnpkg.com/gzip-size/-/gzip-size-5.1.1.tgz#cb9bee692f87c0612b232840a873904e4c135274" - integrity sha512-FNHi6mmoHvs1mxZAds4PpdCS6QG8B4C1krxJsMutgxl5t3+GlRTzzI3NEkifXx2pVsOvJdOGSmIgDhQ55FwdPA== - dependencies: - duplexer "^0.1.1" - pify "^4.0.1" - har-schema@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" @@ -6626,11 +6272,6 @@ homedir-polyfill@^1.0.1: dependencies: parse-passwd "^1.0.0" -hoopy@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/hoopy/-/hoopy-0.1.4.tgz#609207d661100033a9a9402ad3dea677381c1b1d" - integrity sha512-HRcs+2mr52W0K+x8RzcLzuPPmVIKMSv97RGHy0Ea9y/mpcaK+xTrjICA04KAHi4GRzxliNqNJEFYWHghy3rSfQ== - hosted-git-info@^2.1.4: version "2.8.4" resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.4.tgz#44119abaf4bc64692a16ace34700fed9c03e2546" @@ -6697,17 +6338,6 @@ http-cache-semantics@^4.0.0: resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.0.3.tgz#495704773277eeef6e43f9ab2c2c7d259dda25c5" integrity sha512-TcIMG3qeVLgDr1TEd2XvHaTnMPwYQUQMIBLy+5pLSDKYFc7UIqj39w8EGzZkaxoLv/l2K8HaI0t5AVA+YYgUew== -http-errors@1.7.2: - version "1.7.2" - resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.2.tgz#4f5029cf13239f31036e5b2e55292bcfbcc85c8f" - integrity sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg== - dependencies: - depd "~1.1.2" - inherits "2.0.3" - setprototypeof "1.1.1" - statuses ">= 1.5.0 < 2" - toidentifier "1.0.0" - http-errors@1.7.3, http-errors@~1.7.2: version "1.7.3" resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.3.tgz#6c619e4f9c60308c38519498c14fbb10aacebb06" @@ -6762,7 +6392,7 @@ human-signals@^1.1.1: resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-1.1.1.tgz#c5b1cd14f50aeae09ab6c59fe63ba3395fe4dfa3" integrity sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw== -iconv-lite@0.4.24, iconv-lite@^0.4.17, iconv-lite@^0.4.24, iconv-lite@^0.4.4, iconv-lite@~0.4.13: +iconv-lite@0.4.24, iconv-lite@^0.4.24, iconv-lite@^0.4.4: version "0.4.24" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== @@ -6992,25 +6622,6 @@ ini@^1.3.4, ini@^1.3.5, ini@~1.3.0: resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927" integrity sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw== -inquirer@3.0.6: - version "3.0.6" - resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-3.0.6.tgz#e04aaa9d05b7a3cb9b0f407d04375f0447190347" - integrity sha1-4EqqnQW3o8ubD0B9BDdfBEcZA0c= - dependencies: - ansi-escapes "^1.1.0" - chalk "^1.0.0" - cli-cursor "^2.1.0" - cli-width "^2.0.0" - external-editor "^2.0.1" - figures "^2.0.0" - lodash "^4.3.0" - mute-stream "0.0.7" - run-async "^2.2.0" - rx "^4.1.0" - string-width "^2.0.0" - strip-ansi "^3.0.0" - through "^2.3.6" - inquirer@^0.12.0: version "0.12.0" resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-0.12.0.tgz#1ef2bfd63504df0bc75785fff8c2c41df12f077e" @@ -7079,16 +6690,6 @@ invariant@^2.2.2: dependencies: loose-envify "^1.0.0" -inversify@4.11.1: - version "4.11.1" - resolved "https://registry.yarnpkg.com/inversify/-/inversify-4.11.1.tgz#9a10635d1fd347da11da96475b3608babd5945a6" - integrity sha512-9bs/36crPdTSOCcoomHMb96s+B8W0+2c9dHFP/Srv9ZQaPnUvsMgzmMHfgVECqfHVUIW+M5S7SYOjoig8khWuQ== - -inversify@4.13.0: - version "4.13.0" - resolved "https://registry.yarnpkg.com/inversify/-/inversify-4.13.0.tgz#0ab40570bfa4474b04d5b919bbab3a4f682a72f5" - integrity sha512-O5d8y7gKtyRwrvTLZzYET3kdFjqUy58sGpBYMARF13mzqDobpfBXVOPLH7HmnD2VR6Q+1HzZtslGvsdQfeb0SA== - invert-kv@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6" @@ -7099,11 +6700,6 @@ invert-kv@^2.0.0: resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-2.0.0.tgz#7393f5afa59ec9ff5f67a27620d11c226e3eec02" integrity sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA== -ipaddr.js@1.9.0: - version "1.9.0" - resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.0.tgz#37df74e430a0e47550fe54a2defe30d8acd95f65" - integrity sha512-M4Sjn6N/+O6/IXSJseKqHoFc+5FdGJ22sXqnjTpdZweHK64MzEPAyQZyEU3R/KRv2GLoa7nNtg/C2Ev6m7z+eA== - irregular-plurals@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/irregular-plurals/-/irregular-plurals-2.0.0.tgz#39d40f05b00f656d0b7fa471230dd3b714af2872" @@ -7160,7 +6756,7 @@ is-binary-path@~2.1.0: dependencies: binary-extensions "^2.0.0" -is-buffer@^1.1.5, is-buffer@~1.1.1: +is-buffer@^1.1.5: version "1.1.6" resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== @@ -7412,7 +7008,7 @@ is-retry-allowed@^1.0.0, is-retry-allowed@^1.1.0: resolved "https://registry.yarnpkg.com/is-retry-allowed/-/is-retry-allowed-1.2.0.tgz#d778488bd0a4666a3be8a1482b9f2baafedea8b4" integrity sha512-RUbUeKwvm3XG2VYamhJL1xFktgjvPzL0Hq8C+6yrWIswDy3BIXGqCxhxkc30N9jqK311gVU137K8Ei55/zVJRg== -is-stream@^1.0.0, is-stream@^1.0.1, is-stream@^1.1.0: +is-stream@^1.0.0, is-stream@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ= @@ -7525,55 +7121,6 @@ isurl@^1.0.0-alpha5: has-to-string-tag-x "^1.2.0" is-object "^1.0.1" -javascript-obfuscator@^0.15.0: - version "0.15.0" - resolved "https://registry.yarnpkg.com/javascript-obfuscator/-/javascript-obfuscator-0.15.0.tgz#e2b348c3a6895ef9195e3088f05747cff7a914f1" - integrity sha512-d4mzMLkwZarZE9ZDFXQapNba4iHEj6ARveU4qCz7j/T/TlrHJVbyhVRcZigIuiQqgotTWGub5vMCa2/ep+hA+w== - dependencies: - "@babel/runtime" "7.0.0-beta.42" - chalk "2.3.2" - chance "1.0.13" - class-validator "0.8.5" - commander "2.15.1" - escodegen-wallaby "1.6.18" - espree "3.5.4" - estraverse "4.2.0" - inversify "4.11.1" - js-string-escape "1.0.1" - md5 "2.2.1" - mkdirp "0.5.1" - multimatch "2.1.0" - opencollective "1.0.3" - pjson "1.0.9" - reflect-metadata "0.1.12" - source-map-support "0.5.4" - string-template "1.0.0" - tslib "1.9.0" - -javascript-obfuscator@latest: - version "0.18.1" - resolved "https://registry.yarnpkg.com/javascript-obfuscator/-/javascript-obfuscator-0.18.1.tgz#ed536645bd64998c8d284c1ab87957d6d8d8294c" - integrity sha512-pQ2DyRV4j0neaWdII1S7iJftCyks9H7afVkQRSE4gslkqpeqyM1DE0eapsZKHR0BnYvw3tPU+Ky+j4yhzcxRZA== - dependencies: - "@babel/runtime" "7.0.0-rc.1" - chalk "2.4.1" - chance "1.0.16" - class-validator "0.9.1" - commander "2.17.1" - escodegen-wallaby "1.6.19" - espree "4.0.0" - estraverse "4.2.0" - inversify "4.13.0" - js-string-escape "1.0.1" - md5 "2.2.1" - mkdirp "0.5.1" - multimatch "2.1.0" - opencollective "1.0.3" - reflect-metadata "0.1.12" - source-map-support "0.5.8" - string-template "1.0.0" - tslib "1.9.3" - jimp@^0.6.1: version "0.6.8" resolved "https://registry.yarnpkg.com/jimp/-/jimp-0.6.8.tgz#63074984337cc469cd4030946e503e7c02a18b5c" @@ -7604,7 +7151,7 @@ js-base64@^2.1.8, js-base64@^2.1.9: resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-2.5.1.tgz#1efa39ef2c5f7980bb1784ade4a8af2de3291121" integrity sha512-M7kLczedRMYX4L8Mdh4MzyAMM9O5osx+4FcOQuTvr3A9F2D9S5JXheN0ewNbrvK2UatkTRhL5ejGmGSjNMiZuw== -js-beautify@^1.10.1, js-beautify@^1.5.10: +js-beautify@^1.5.10: version "1.10.2" resolved "https://registry.yarnpkg.com/js-beautify/-/js-beautify-1.10.2.tgz#88c9099cd6559402b124cfab18754936f8a7b178" integrity sha512-ZtBYyNUYJIsBWERnQP0rPN9KjkrDfJcMjuVGcvXOUJrD1zmOGwhRwQ4msG+HJ+Ni/FA7+sRQEMYVzdTQDvnzvQ== @@ -7620,11 +7167,6 @@ js-levenshtein@^1.1.3: resolved "https://registry.yarnpkg.com/js-levenshtein/-/js-levenshtein-1.1.6.tgz#c6cee58eb3550372df8deb85fad5ce66ce01d59d" integrity sha512-X2BB11YZtrRqY4EnQcLX5Rh373zbK4alC1FW7D7MBhL2gtcC17cTnr6DmfHZeS0s2rTHjUTMMHfG7gO8SSdw+g== -js-string-escape@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/js-string-escape/-/js-string-escape-1.0.1.tgz#e2625badbc0d67c7533e9edc1068c587ae4137ef" - integrity sha1-4mJbrbwNZ8dTPp7cEGjFh65BN+8= - "js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" @@ -8114,11 +7656,6 @@ lodash._shimkeys@~2.4.1: dependencies: lodash._objecttypes "~2.4.1" -lodash.assign@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/lodash.assign/-/lodash.assign-4.2.0.tgz#0d99f3ccd7a6d261d19bdaeb9245005d285808e7" - integrity sha1-DZnzzNem0mHRm9rrkkUAXShYCOc= - lodash.capitalize@^4.1.0: version "4.2.1" resolved "https://registry.yarnpkg.com/lodash.capitalize/-/lodash.capitalize-4.2.1.tgz#f826c9b4e2a8511d84e3aca29db05e1a4f3b72a9" @@ -8183,11 +7720,6 @@ lodash.isfinite@^3.3.2: resolved "https://registry.yarnpkg.com/lodash.isfinite/-/lodash.isfinite-3.3.2.tgz#fb89b65a9a80281833f0b7478b3a5104f898ebb3" integrity sha1-+4m2WpqAKBgz8LdHizpRBPiY67M= -lodash.isobject@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/lodash.isobject/-/lodash.isobject-3.0.2.tgz#3c8fb8d5b5bf4bf90ae06e14f2a530a4ed935e1d" - integrity sha1-PI+41bW/S/kK4G4U8qUwpO2TXh0= - lodash.isobject@~2.4.1: version "2.4.1" resolved "https://registry.yarnpkg.com/lodash.isobject/-/lodash.isobject-2.4.1.tgz#5a2e47fe69953f1ee631a7eba1fe64d2d06558f5" @@ -8223,16 +7755,6 @@ lodash.memoize@^4.1.2: resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" integrity sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4= -lodash.merge@^4.6.0: - version "4.6.2" - resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" - integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== - -lodash.mergewith@^4.6.2: - version "4.6.2" - resolved "https://registry.yarnpkg.com/lodash.mergewith/-/lodash.mergewith-4.6.2.tgz#617121f89ac55f59047c7aec1ccd6654c6590f55" - integrity sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ== - lodash.restparam@^3.0.0: version "3.6.1" resolved "https://registry.yarnpkg.com/lodash.restparam/-/lodash.restparam-3.6.1.tgz#936a4e309ef330a7645ed4145986c85ae5b20805" @@ -8324,7 +7846,7 @@ lodash@^3.0.1: resolved "https://registry.yarnpkg.com/lodash/-/lodash-3.10.1.tgz#5bf45e8e49ba4189e17d482789dfd15bd140b7b6" integrity sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y= -lodash@^4.0.0, lodash@^4.15.0, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.3.0, lodash@~4.17.10: +lodash@^4.0.0, lodash@^4.15.0, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.3.0, lodash@~4.17.10: version "4.17.15" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A== @@ -8507,15 +8029,6 @@ md5.js@^1.3.4: inherits "^2.0.1" safe-buffer "^5.1.2" -md5@2.2.1, md5@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/md5/-/md5-2.2.1.tgz#53ab38d5fe3c8891ba465329ea23fac0540126f9" - integrity sha1-U6s41f48iJG6RlMp6iP6wFQBJvk= - dependencies: - charenc "~0.0.1" - crypt "~0.0.1" - is-buffer "~1.1.1" - mdn-data@2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.4.tgz#699b3c38ac6f1d728091a64650b65d388502fd5b" @@ -8564,11 +8077,6 @@ meow@^3.3.0, meow@^3.7.0: redent "^1.0.0" trim-newlines "^1.0.0" -merge-descriptors@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" - integrity sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E= - merge-stream@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" @@ -8589,11 +8097,6 @@ merge@^1.2.0: resolved "https://registry.yarnpkg.com/merge/-/merge-1.2.1.tgz#38bebf80c3220a8a487b6fcfb3941bb11720c145" integrity sha512-VjFo4P5Whtj4vsLzsYBu5ayHhoHJ0UqNm7ibvShmbmoz7tGi0vXaoJbGdB+GmDMLUdg8DpQXEIeVDAe8MaABvQ== -methods@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" - integrity sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4= - micromatch@^3.0.4, micromatch@^3.1.10, micromatch@^3.1.4: version "3.1.10" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" @@ -8713,7 +8216,7 @@ minimatch@0.3: lru-cache "2" sigmund "~1.0.0" -"minimatch@2 || 3", minimatch@^3.0.0, minimatch@^3.0.2, minimatch@^3.0.3, minimatch@^3.0.4, minimatch@~3.0.2: +"minimatch@2 || 3", minimatch@^3.0.2, minimatch@^3.0.3, minimatch@^3.0.4, minimatch@~3.0.2: version "3.0.4" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== @@ -8745,11 +8248,6 @@ minimist@1.1.x: resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.1.3.tgz#3bedfd91a92d39016fcfaa1c681e8faa1a1efda8" integrity sha1-O+39kaktOQFvz6ocaB6Pqhoe/ag= -minimist@1.2.0, minimist@^1.1.0, minimist@^1.1.3, minimist@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" - integrity sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ= - minimist@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.1.0.tgz#99df657a52574c21c9057497df742790b2b4c0de" @@ -8760,6 +8258,11 @@ minimist@^0.2.0: resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.2.0.tgz#4dffe525dae2b864c66c2e23c6271d7afdecefce" integrity sha1-Tf/lJdriuGTGbC4jxicdev3s784= +minimist@^1.1.0, minimist@^1.1.3, minimist@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" + integrity sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ= + minimist@^1.2.5: version "1.2.5" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" @@ -8864,16 +8367,6 @@ ms@^2.1.1: resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== -multimatch@2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/multimatch/-/multimatch-2.1.0.tgz#9c7906a22fb4c02919e2f5f75161b4cdbd4b2a2b" - integrity sha1-nHkGoi+0wCkZ4vX3UWG0zb1LKis= - dependencies: - array-differ "^1.0.0" - array-union "^1.0.1" - arrify "^1.0.0" - minimatch "^3.0.0" - multipipe@^0.1.0, multipipe@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/multipipe/-/multipipe-0.1.2.tgz#2a8f2ddf70eed564dff2d57f1e1a137d9f05078b" @@ -8969,22 +8462,6 @@ no-case@^2.2.0: dependencies: lower-case "^1.1.1" -node-fetch@1.6.3: - version "1.6.3" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-1.6.3.tgz#dc234edd6489982d58e8f0db4f695029abcd8c04" - integrity sha1-3CNO3WSJmC1Y6PDbT2lQKavNjAQ= - dependencies: - encoding "^0.1.11" - is-stream "^1.0.1" - -node-fetch@^1.6.3: - version "1.7.3" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-1.7.3.tgz#980f6f72d85211a5347c6b2bc18c5b84c3eb47ef" - integrity sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ== - dependencies: - encoding "^0.1.11" - is-stream "^1.0.1" - node-gyp@^3.8.0: version "3.8.0" resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-3.8.0.tgz#540304261c330e80d0d5edce253a68cb3964218c" @@ -9231,15 +8708,6 @@ oauth-sign@~0.9.0: resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== -obfuscator-loader@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/obfuscator-loader/-/obfuscator-loader-1.1.2.tgz#6e8460066296fc642a68c945e64906e3c964cb0f" - integrity sha512-5PKsa4Vzq8uLJG0GT9BvC9ZxCr44wyV0c9wi782RYWh44GdFMSqlnUldgqSV+HQkFH3MWNc34AlSVSEhg7I26w== - dependencies: - esprima "^4.0.0" - javascript-obfuscator "^0.15.0" - loader-utils "^1.1.0" - object-assign@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-3.0.0.tgz#9bedd5ca0897949bca47e7ff408062d549f587f2" @@ -9390,14 +8858,6 @@ once@~1.3.0: dependencies: wrappy "1" -onesky-fetch@^0.0.7: - version "0.0.7" - resolved "https://registry.yarnpkg.com/onesky-fetch/-/onesky-fetch-0.0.7.tgz#96fce1a258a80683d6a37840958bae2f6fdb2809" - integrity sha1-lvzholioBoPWo3hAlYuuL2/bKAk= - dependencies: - md5 "^2.2.1" - node-fetch "^1.6.3" - onetime@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/onetime/-/onetime-1.1.0.tgz#a1f7838f8314c516f05ecefcbc4ccfe04b4ed789" @@ -9422,36 +8882,11 @@ open@^0.0.5: resolved "https://registry.yarnpkg.com/open/-/open-0.0.5.tgz#42c3e18ec95466b6bf0dc42f3a2945c3f0cad8fc" integrity sha1-QsPhjslUZra/DcQvOilFw/DK2Pw= -opencollective@1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/opencollective/-/opencollective-1.0.3.tgz#aee6372bc28144583690c3ca8daecfc120dd0ef1" - integrity sha1-ruY3K8KBRFg2kMPKja7PwSDdDvE= - dependencies: - babel-polyfill "6.23.0" - chalk "1.1.3" - inquirer "3.0.6" - minimist "1.2.0" - node-fetch "1.6.3" - opn "4.0.2" - -opener@^1.5.1: - version "1.5.1" - resolved "https://registry.yarnpkg.com/opener/-/opener-1.5.1.tgz#6d2f0e77f1a0af0032aca716c2c1fbb8e7e8abed" - integrity sha512-goYSy5c2UXE4Ra1xixabeVh1guIX/ZV/YokJksb6q2lubWu6UbvPQ20p542/sFIll1nl8JnCyK9oBaOcCWXwvA== - openurl@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/openurl/-/openurl-1.1.1.tgz#3875b4b0ef7a52c156f0db41d4609dbb0f94b387" integrity sha1-OHW0sO96UsFW8NtB1GCduw+Us4c= -opn@4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/opn/-/opn-4.0.2.tgz#7abc22e644dff63b0a96d5ab7f2790c0f01abc95" - integrity sha1-erwi5kTf9jsKltWrfyeQwPAavJU= - dependencies: - object-assign "^4.0.1" - pinkie-promise "^2.0.0" - opn@5.3.0: version "5.3.0" resolved "https://registry.yarnpkg.com/opn/-/opn-5.3.0.tgz#64871565c863875f052cfdf53d3e3cb5adb53b1c" @@ -9820,11 +9255,6 @@ parseqs@0.0.5: dependencies: better-assert "~1.0.0" -parserlib@~1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/parserlib/-/parserlib-1.1.1.tgz#a64cfa724062434fdfc351c9a4ec2d92b94c06f4" - integrity sha1-pkz6ckBiQ0/fw1HJpOwtkrlMBvQ= - parseuri@0.0.5: version "0.0.5" resolved "https://registry.yarnpkg.com/parseuri/-/parseuri-0.0.5.tgz#80204a50d4dbb779bfdc6ebe2778d90e4bce320a" @@ -9916,11 +9346,6 @@ path-starts-with@^2.0.0: resolved "https://registry.yarnpkg.com/path-starts-with/-/path-starts-with-2.0.0.tgz#ffd6d51926cd497022b44d392196033d5451892f" integrity sha512-3UHTHbJz5+NLkPafFR+2ycJOjoc4WV2e9qCZCnm71zHiWaFrm1XniLVTkZXvaRgxr1xFh9JsTdicpH2yM03nLA== -path-to-regexp@0.1.7: - version "0.1.7" - resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" - integrity sha1-32BBeABfUi8V60SQ5yR6G/qmf4w= - path-type@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441" @@ -10012,11 +9437,6 @@ pixelmatch@^4.0.2: dependencies: pngjs "^3.0.0" -pjson@1.0.9: - version "1.0.9" - resolved "https://registry.yarnpkg.com/pjson/-/pjson-1.0.9.tgz#8a9520ce76a4739f8fee91679dad6b065b1c7938" - integrity sha512-4hRJH3YzkUpOlShRzhyxAmThSNnAaIlWZCAb27hd0pVUAXNUAHAO7XZbsPPvsCYwBFEScTmCCL6DGE8NyZ8BdQ== - pkg-dir@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-3.0.0.tgz#2749020f239ed990881b1f71210d51eb6523bea3" @@ -10854,14 +10274,6 @@ proto-list@~1.2.1: resolved "https://registry.yarnpkg.com/proto-list/-/proto-list-1.2.4.tgz#212d5bfe1318306a420f6402b8e26ff39647a849" integrity sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk= -proxy-addr@~2.0.5: - version "2.0.5" - resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.5.tgz#34cbd64a2d81f4b1fd21e76f9f06c8a45299ee34" - integrity sha512-t/7RxHXPH6cJtP0pRG6smSr9QJidhB+3kXu0KgXnbGYMgzEnUxRQ4/LDdfOwZEMyIh3/xHb8PX3t+lfL9z+YVQ== - dependencies: - forwarded "~0.1.2" - ipaddr.js "1.9.0" - proxy-middleware@^0.5.0: version "0.5.1" resolved "https://registry.yarnpkg.com/proxy-middleware/-/proxy-middleware-0.5.1.tgz#da24d5d58c1ddf13dad237c7eca503849eaea903" @@ -10959,11 +10371,6 @@ qs@6.2.3: resolved "https://registry.yarnpkg.com/qs/-/qs-6.2.3.tgz#1cfcb25c10a9b2b483053ff39f5dfc9233908cfe" integrity sha1-HPyyXBCpsrSDBT/zn138kjOQjP4= -qs@6.7.0: - version "6.7.0" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.7.0.tgz#41dc1a015e3d581f1621776be31afb2876a9b1bc" - integrity sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ== - qs@~2.2.3: version "2.2.5" resolved "https://registry.yarnpkg.com/qs/-/qs-2.2.5.tgz#1088abaf9dcc0ae5ae45b709e6c6b5888b23923c" @@ -11030,16 +10437,6 @@ raw-body@1.3.0: bytes "1" iconv-lite "0.4.4" -raw-body@2.4.0: - version "2.4.0" - resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.4.0.tgz#a1ce6fb9c9bc356ca52e89256ab59059e13d0332" - integrity sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q== - dependencies: - bytes "3.1.0" - http-errors "1.7.2" - iconv-lite "0.4.24" - unpipe "1.0.0" - raw-body@^2.3.2: version "2.4.1" resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.4.1.tgz#30ac82f98bb5ae8c152e67149dac8d55153b168c" @@ -11080,16 +10477,6 @@ rcloader@^0.1.4: lodash "^3.0.1" rcfinder "^0.1.6" -rcloader@^0.2.1: - version "0.2.2" - resolved "https://registry.yarnpkg.com/rcloader/-/rcloader-0.2.2.tgz#58d2298b462d0b9bfd2133d2a1ec74fbd705c717" - integrity sha1-WNIpi0YtC5v9ITPSoex0+9cFxxc= - dependencies: - lodash.assign "^4.2.0" - lodash.isobject "^3.0.2" - lodash.merge "^4.6.0" - rcfinder "^0.1.6" - read-pkg-up@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-1.0.1.tgz#9d63c13276c065918d57f002a57f40a1b643fb02" @@ -11232,11 +10619,6 @@ redent@^1.0.0: indent-string "^2.1.0" strip-indent "^1.0.1" -reflect-metadata@0.1.12: - version "0.1.12" - resolved "https://registry.yarnpkg.com/reflect-metadata/-/reflect-metadata-0.1.12.tgz#311bf0c6b63cd782f228a81abe146a2bfa9c56f2" - integrity sha512-n+IyV+nGz3+0q3/Yf1ra12KpCyi001bi4XFxSjbiWWjfqb52iTTtpGXmCCAOWWIAn9KEuFZKGqBERHmrtScZ3A== - regenerate-unicode-properties@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-8.1.0.tgz#ef51e0f0ea4ad424b77bf7cb41f3e015c70a3f0e" @@ -11249,21 +10631,11 @@ regenerate@^1.4.0: resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.0.tgz#4a856ec4b56e4077c557589cae85e7a4c8869a11" integrity sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg== -regenerator-runtime@^0.10.0: - version "0.10.5" - resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz#336c3efc1220adcedda2c9fab67b5a7955a33658" - integrity sha1-M2w+/BIgrc7dosn6tntaeVWjNlg= - -regenerator-runtime@^0.11.0, regenerator-runtime@^0.11.1: +regenerator-runtime@^0.11.0: version "0.11.1" resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9" integrity sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg== -regenerator-runtime@^0.12.0: - version "0.12.1" - resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.12.1.tgz#fa1a71544764c036f8c49b13a08b2594c9f8a0de" - integrity sha512-odxIc1/vDlo4iZcfXqRYFj0vpXFNoGdKMAUieAlFYO6m/nl5e9KR/beGf41z4a1FI+aQgtjhuaSlDxQ0hmkrHg== - regenerator-runtime@^0.13.3: version "0.13.3" resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.3.tgz#7cf6a77d8f5c6f60eb73c5fc1955b2ceb01e6bf5" @@ -11628,7 +11000,7 @@ rx-lite@^3.1.2: resolved "https://registry.yarnpkg.com/rx-lite/-/rx-lite-3.1.2.tgz#19ce502ca572665f3b647b10939f97fd1615f102" integrity sha1-Gc5QLKVyZl87ZHsQk5+X/RYV8QI= -rx@4.1.0, rx@^4.1.0: +rx@4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/rx/-/rx-4.1.0.tgz#a5f13ff79ef3b740fe30aa803fb09f98805d4782" integrity sha1-pfE/957zt0D+MKqAP7CfmIBdR4I= @@ -11888,7 +11260,7 @@ serve-static@1.13.2: parseurl "~1.3.2" send "0.16.2" -serve-static@1.14.1, serve-static@^1.3.0: +serve-static@^1.3.0: version "1.14.1" resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.14.1.tgz#666e636dc4f010f7ef29970a88a674320898b2f9" integrity sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg== @@ -12148,21 +11520,6 @@ source-map-resolve@^0.5.0: source-map-url "^0.4.0" urix "^0.1.0" -source-map-support@0.5.4: - version "0.5.4" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.4.tgz#54456efa89caa9270af7cd624cc2f123e51fbae8" - integrity sha512-PETSPG6BjY1AHs2t64vS2aqAgu6dMIMXJULWFBGbh2Gr8nVLbCFDo6i/RMMvviIQ2h1Z8+5gQhVKSn2je9nmdg== - dependencies: - source-map "^0.6.0" - -source-map-support@0.5.8: - version "0.5.8" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.8.tgz#04f5581713a8a65612d0175fbf3a01f80a162613" - integrity sha512-WqAEWPdb78u25RfKzOF0swBpY0dKrNdjc4GvLwm7ScX/o9bj8Eh/YL8mcMhBHYDGl87UkkSXDOFnW4G7GhWhGg== - dependencies: - buffer-from "^1.0.0" - source-map "^0.6.0" - source-map-support@~0.5.12: version "0.5.13" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.13.tgz#31b24a9c2e73c2de85066c0feb7d44767ed52932" @@ -12200,13 +11557,6 @@ source-map@~0.1.38: dependencies: amdefine ">=0.0.4" -source-map@~0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.2.0.tgz#dab73fbcfc2ba819b4de03bd6f6eaa48164b3f9d" - integrity sha1-2rc/vPwrqBm03gO9b26qSBZLP50= - dependencies: - amdefine ">=0.0.4" - sparkles@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/sparkles/-/sparkles-1.0.1.tgz#008db65edce6c50eec0c5e228e1945061dd0437c" @@ -12238,13 +11588,6 @@ spdx-license-ids@^3.0.0: resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz#3694b5804567a458d3c8045842a6358632f62654" integrity sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q== -speed-measure-webpack-plugin@^1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/speed-measure-webpack-plugin/-/speed-measure-webpack-plugin-1.3.1.tgz#69840a5cdc08b4638697dac7db037f595d7f36a0" - integrity sha512-qVIkJvbtS9j/UeZumbdfz0vg+QfG/zxonAjzefZrqzkr7xOncLVXkeGbTpzd1gjCBM4PmVNkWlkeTVhgskAGSQ== - dependencies: - chalk "^2.0.1" - split-on-first@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/split-on-first/-/split-on-first-1.1.0.tgz#f610afeee3b12bce1d0c30425e76398b78249a5f" @@ -12436,11 +11779,6 @@ string-replace-webpack-plugin@^0.1.3: file-loader "^0.8.1" style-loader "^0.8.3" -string-template@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/string-template/-/string-template-1.0.0.tgz#9e9f2233dc00f218718ec379a28a5673ecca8b96" - integrity sha1-np8iM9wA8hhxjsN5oopWc+zKi5Y= - string-width@^1.0.1, string-width@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" @@ -13149,21 +12487,6 @@ truncate-utf8-bytes@^1.0.0: dependencies: utf8-byte-length "^1.0.1" -tryer@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/tryer/-/tryer-1.0.1.tgz#f2c85406800b9b0f74c9f7465b81eaad241252f8" - integrity sha512-c3zayb8/kWWpycWYg87P71E1S1ZL6b6IJxfb5fvsUgsf0S2MVGaDhDXXjDMpdCpfWXqptc+4mXwmiy1ypXqRAA== - -tslib@1.9.0: - version "1.9.0" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.0.tgz#e37a86fda8cbbaf23a057f473c9f4dc64e5fc2e8" - integrity sha512-f/qGG2tUkrISBlQZEjEqoZ3B2+npJjIf04H1wuAv9iA8i04Icp+61KRXxFdha22670NJopsZCIjhC3SnjPRKrQ== - -tslib@1.9.3: - version "1.9.3" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.3.tgz#d7e4dd79245d85428c4d7e4822a79917954ca286" - integrity sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ== - tslib@^1.9.0: version "1.10.0" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.10.0.tgz#c3c19f95973fb0a62973fb09d90d961ee43e5c8a" @@ -13206,14 +12529,6 @@ type-is@~1.5.1: media-typer "0.3.0" mime-types "~2.0.9" -type-is@~1.6.17, type-is@~1.6.18: - version "1.6.18" - resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" - integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g== - dependencies: - media-typer "0.3.0" - mime-types "~2.1.24" - type@^1.0.1: version "1.2.0" resolved "https://registry.yarnpkg.com/type/-/type-1.2.0.tgz#848dd7698dafa3e54a6c479e759c4bc3f18847a0" @@ -13538,26 +12853,11 @@ validate-npm-package-license@^3.0.1: spdx-correct "^3.0.0" spdx-expression-parse "^3.0.0" -validator@10.4.0: - version "10.4.0" - resolved "https://registry.yarnpkg.com/validator/-/validator-10.4.0.tgz#ee99a44afb3bb5ed350a159f056ca72a204cfc3c" - integrity sha512-Q/wBy3LB1uOyssgNlXSRmaf22NxjvDNZM2MtIQ4jaEOAB61xsh1TQxsq1CgzUMBV1lDrVMogIh8GjG1DYW0zLg== - -validator@9.2.0: - version "9.2.0" - resolved "https://registry.yarnpkg.com/validator/-/validator-9.2.0.tgz#ad216eed5f37cac31a6fe00ceab1f6b88bded03e" - integrity sha512-6Ij4Eo0KM4LkR0d0IegOwluG5453uqT5QyF5SV5Ezvm8/zmkKI/L4eoraafZGlZPC9guLkwKzgypcw8VGWWnGA== - value-or-function@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/value-or-function/-/value-or-function-3.0.0.tgz#1c243a50b595c1be54a754bfece8563b9ff8d813" integrity sha1-HCQ6ULWVwb5Up1S/7OhWO5/42BM= -vary@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" - integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw= - vendors@^1.0.0: version "1.0.3" resolved "https://registry.yarnpkg.com/vendors/-/vendors-1.0.3.tgz#a6467781abd366217c050f8202e7e50cc9eef8c0" @@ -13728,25 +13028,6 @@ webidl-conversions@^4.0.2: resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-4.0.2.tgz#a855980b1f0b6b359ba1d5d9fb39ae941faa63ad" integrity sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg== -webpack-bundle-analyzer@^3.0.3: - version "3.5.1" - resolved "https://registry.yarnpkg.com/webpack-bundle-analyzer/-/webpack-bundle-analyzer-3.5.1.tgz#84aabb1547178d842ebb4ccc7324084b6c3b0ea9" - integrity sha512-CDdaT3TTu4F9X3tcDq6PNJOiNGgREOM0WdN2vVAoUUn+M6NLB5kJ543HImCWbrDwOpbpGARSwU8r+u0Pl367kA== - dependencies: - acorn "^6.0.7" - acorn-walk "^6.1.1" - bfj "^6.1.1" - chalk "^2.4.1" - commander "^2.18.0" - ejs "^2.6.1" - express "^4.16.3" - filesize "^3.6.1" - gzip-size "^5.0.0" - lodash "^4.17.15" - mkdirp "^0.5.1" - opener "^1.5.1" - ws "^6.0.0" - webpack-cli@^3.1.0: version "3.3.9" resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-3.3.9.tgz#79c27e71f94b7fe324d594ab64a8e396b9daa91a" @@ -13989,7 +13270,7 @@ write@^0.2.1: dependencies: mkdirp "^0.5.1" -ws@^6.0.0, ws@^6.1.0: +ws@^6.1.0: version "6.2.1" resolved "https://registry.yarnpkg.com/ws/-/ws-6.2.1.tgz#442fdf0a47ed64f59b6a5d8ff130f4748ed524fb" integrity sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA== diff --git a/package.json b/package.json index bca0eac3..1228ead9 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,7 @@ "scripts": { "dev": "cd gulp && yarn gulp main.serveDev", "tslint": "cd src/js && tsc", - "lint": "npx eslint src/js", + "lint": "eslint src/js", "prettier-all": "prettier --write src/**/*.* && prettier --write gulp/**/*.*", "publishOnItchWindows": "butler push tmp_standalone_files/shapez.io-standalone-win32-x64 tobspr/shapezio:windows --userversion-file version", "publishOnItchLinux": "butler push tmp_standalone_files/shapez.io-standalone-linux-x64 tobspr/shapezio:linux --userversion-file version", @@ -34,6 +34,7 @@ "clipboard-copy": "^3.1.0", "colors": "^1.3.3", "core-js": "3", + "crc": "^3.8.0", "cssnano-preset-advanced": "^4.0.7", "email-validator": "^2.0.4", "eslint": "7.1.0", @@ -46,7 +47,6 @@ "lz-string": "^1.4.4", "markdown-loader": "^4.0.0", "match-all": "^1.2.5", - "obfuscator-loader": "^1.1.2", "phonegap-plugin-mobile-accessibility": "^1.0.5", "promise-polyfill": "^8.1.0", "query-string": "^6.8.1", @@ -86,14 +86,12 @@ "imagemin-pngquant": "^8.0.0", "jimp": "^0.6.1", "js-yaml": "^3.13.1", - "onesky-fetch": "^0.0.7", "postcss-assets": "^5.0.0", "postcss-preset-env": "^6.5.0", "postcss-round-subpixels": "^1.2.0", "postcss-unprefix": "^2.1.3", "prettier": "^2.0.4", "sass-unused": "^0.3.0", - "speed-measure-webpack-plugin": "^1.3.1", "strip-json-comments": "^3.0.1", "trim": "^0.0.1", "yarn": "^1.22.4" diff --git a/res/ui/building_icons/advanced_processor.png b/res/ui/building_icons/advanced_processor.png deleted file mode 100644 index fe7cc8f2..00000000 Binary files a/res/ui/building_icons/advanced_processor.png and /dev/null differ diff --git a/res/ui/building_icons/constant_signal.png b/res/ui/building_icons/constant_signal.png new file mode 100644 index 00000000..b438fa29 Binary files /dev/null and b/res/ui/building_icons/constant_signal.png differ diff --git a/res/ui/building_icons/display.png b/res/ui/building_icons/display.png new file mode 100644 index 00000000..14c48d7e Binary files /dev/null and b/res/ui/building_icons/display.png differ diff --git a/res/ui/building_icons/energy_generator.png b/res/ui/building_icons/energy_generator.png deleted file mode 100644 index fc419cde..00000000 Binary files a/res/ui/building_icons/energy_generator.png and /dev/null differ diff --git a/res/ui/building_icons/filter.png b/res/ui/building_icons/filter.png new file mode 100644 index 00000000..2e87af28 Binary files /dev/null and b/res/ui/building_icons/filter.png differ diff --git a/res/ui/building_icons/lever.png b/res/ui/building_icons/lever.png new file mode 100644 index 00000000..77eea9f3 Binary files /dev/null and b/res/ui/building_icons/lever.png differ diff --git a/res/ui/building_icons/logic_gate.png b/res/ui/building_icons/logic_gate.png new file mode 100644 index 00000000..81a0bdd6 Binary files /dev/null and b/res/ui/building_icons/logic_gate.png differ diff --git a/res/ui/building_icons/wire_crossings.png b/res/ui/building_icons/wire_crossings.png deleted file mode 100644 index 2ef869dc..00000000 Binary files a/res/ui/building_icons/wire_crossings.png and /dev/null differ diff --git a/res/ui/building_icons/wire_tunnel.png b/res/ui/building_icons/wire_tunnel.png new file mode 100644 index 00000000..d0e185f9 Binary files /dev/null and b/res/ui/building_icons/wire_tunnel.png differ diff --git a/res_built/atlas/atlas0_10.json b/res_built/atlas/atlas0_10.json deleted file mode 100644 index 044fb143..00000000 --- a/res_built/atlas/atlas0_10.json +++ /dev/null @@ -1,1404 +0,0 @@ -{"frames": { - -"sprites/belt/forward_0.png": -{ - "frame": {"x":85,"y":167,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/forward_1.png": -{ - "frame": {"x":91,"y":258,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/forward_2.png": -{ - "frame": {"x":107,"y":332,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/forward_3.png": -{ - "frame": {"x":42,"y":434,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/forward_4.png": -{ - "frame": {"x":45,"y":467,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/forward_5.png": -{ - "frame": {"x":45,"y":484,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/forward_6.png": -{ - "frame": {"x":45,"y":501,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/forward_7.png": -{ - "frame": {"x":45,"y":518,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/forward_8.png": -{ - "frame": {"x":59,"y":399,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/forward_9.png": -{ - "frame": {"x":59,"y":416,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/forward_10.png": -{ - "frame": {"x":91,"y":275,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/forward_11.png": -{ - "frame": {"x":91,"y":292,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/forward_12.png": -{ - "frame": {"x":108,"y":264,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/forward_13.png": -{ - "frame": {"x":108,"y":281,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/forward_14.png": -{ - "frame": {"x":108,"y":298,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/forward_15.png": -{ - "frame": {"x":91,"y":309,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/forward_16.png": -{ - "frame": {"x":90,"y":326,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/forward_17.png": -{ - "frame": {"x":90,"y":343,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/forward_18.png": -{ - "frame": {"x":90,"y":360,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/forward_19.png": -{ - "frame": {"x":108,"y":315,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/forward_20.png": -{ - "frame": {"x":107,"y":349,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/forward_21.png": -{ - "frame": {"x":107,"y":366,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/forward_22.png": -{ - "frame": {"x":90,"y":377,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/forward_23.png": -{ - "frame": {"x":107,"y":383,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/forward_24.png": -{ - "frame": {"x":52,"y":382,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/forward_25.png": -{ - "frame": {"x":69,"y":380,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/forward_26.png": -{ - "frame": {"x":42,"y":400,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/forward_27.png": -{ - "frame": {"x":42,"y":417,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/left_0.png": -{ - "frame": {"x":59,"y":433,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/left_1.png": -{ - "frame": {"x":76,"y":397,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/left_2.png": -{ - "frame": {"x":59,"y":450,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/left_3.png": -{ - "frame": {"x":79,"y":512,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/left_4.png": -{ - "frame": {"x":96,"y":493,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/left_5.png": -{ - "frame": {"x":96,"y":510,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/left_6.png": -{ - "frame": {"x":79,"y":529,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/left_7.png": -{ - "frame": {"x":96,"y":527,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/left_8.png": -{ - "frame": {"x":96,"y":544,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/left_9.png": -{ - "frame": {"x":43,"y":628,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/left_10.png": -{ - "frame": {"x":76,"y":414,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/left_11.png": -{ - "frame": {"x":76,"y":431,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/left_12.png": -{ - "frame": {"x":93,"y":408,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/left_13.png": -{ - "frame": {"x":110,"y":400,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/left_14.png": -{ - "frame": {"x":110,"y":417,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/left_15.png": -{ - "frame": {"x":93,"y":425,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/left_16.png": -{ - "frame": {"x":110,"y":434,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/left_17.png": -{ - "frame": {"x":93,"y":442,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/left_18.png": -{ - "frame": {"x":110,"y":451,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/left_19.png": -{ - "frame": {"x":76,"y":448,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/left_20.png": -{ - "frame": {"x":93,"y":459,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/left_21.png": -{ - "frame": {"x":110,"y":468,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/left_22.png": -{ - "frame": {"x":62,"y":467,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/left_23.png": -{ - "frame": {"x":62,"y":484,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/left_24.png": -{ - "frame": {"x":62,"y":501,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/left_25.png": -{ - "frame": {"x":62,"y":518,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/left_26.png": -{ - "frame": {"x":79,"y":478,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/left_27.png": -{ - "frame": {"x":79,"y":495,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/right_0.png": -{ - "frame": {"x":43,"y":645,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/right_1.png": -{ - "frame": {"x":43,"y":662,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/right_2.png": -{ - "frame": {"x":61,"y":603,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/right_3.png": -{ - "frame": {"x":95,"y":612,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/right_4.png": -{ - "frame": {"x":61,"y":620,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/right_5.png": -{ - "frame": {"x":60,"y":637,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/right_6.png": -{ - "frame": {"x":60,"y":654,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/right_7.png": -{ - "frame": {"x":60,"y":671,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/right_8.png": -{ - "frame": {"x":78,"y":631,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/right_9.png": -{ - "frame": {"x":95,"y":629,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/right_10.png": -{ - "frame": {"x":43,"y":679,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/right_11.png": -{ - "frame": {"x":44,"y":536,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/right_12.png": -{ - "frame": {"x":44,"y":553,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/right_13.png": -{ - "frame": {"x":44,"y":570,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/right_14.png": -{ - "frame": {"x":44,"y":587,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/right_15.png": -{ - "frame": {"x":44,"y":604,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/right_16.png": -{ - "frame": {"x":61,"y":535,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/right_17.png": -{ - "frame": {"x":61,"y":552,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/right_18.png": -{ - "frame": {"x":61,"y":569,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/right_19.png": -{ - "frame": {"x":61,"y":586,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/right_20.png": -{ - "frame": {"x":78,"y":546,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/right_21.png": -{ - "frame": {"x":78,"y":563,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/right_22.png": -{ - "frame": {"x":78,"y":580,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/right_23.png": -{ - "frame": {"x":78,"y":597,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/right_24.png": -{ - "frame": {"x":95,"y":561,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/right_25.png": -{ - "frame": {"x":95,"y":578,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/right_26.png": -{ - "frame": {"x":95,"y":595,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/belt/right_27.png": -{ - "frame": {"x":78,"y":614,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/blueprints/advanced_processor.png": -{ - "frame": {"x":82,"y":3,"w":38,"h":38}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":38,"h":38}, - "sourceSize": {"w":38,"h":38} -}, -"sprites/blueprints/belt_left.png": -{ - "frame": {"x":77,"y":648,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/blueprints/belt_right.png": -{ - "frame": {"x":77,"y":665,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/blueprints/belt_top.png": -{ - "frame": {"x":77,"y":682,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/blueprints/cutter-quad.png": -{ - "frame": {"x":3,"y":129,"w":76,"h":19}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":1,"y":0,"w":76,"h":19}, - "sourceSize": {"w":77,"h":19} -}, -"sprites/blueprints/cutter.png": -{ - "frame": {"x":3,"y":628,"w":36,"h":19}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":1,"y":0,"w":36,"h":19}, - "sourceSize": {"w":38,"h":19} -}, -"sprites/blueprints/energy_generator.png": -{ - "frame": {"x":3,"y":301,"w":37,"h":37}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":1,"y":1,"w":37,"h":37}, - "sourceSize": {"w":38,"h":38} -}, -"sprites/blueprints/miner-chainable.png": -{ - "frame": {"x":45,"y":198,"w":19,"h":19}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":19,"h":19}, - "sourceSize": {"w":19,"h":19} -}, -"sprites/blueprints/miner.png": -{ - "frame": {"x":45,"y":221,"w":19,"h":19}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":19,"h":19}, - "sourceSize": {"w":19,"h":19} -}, -"sprites/blueprints/mixer.png": -{ - "frame": {"x":3,"y":536,"w":37,"h":19}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":0,"w":37,"h":19}, - "sourceSize": {"w":38,"h":19} -}, -"sprites/blueprints/painter-double.png": -{ - "frame": {"x":3,"y":175,"w":38,"h":38}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":38,"h":38}, - "sourceSize": {"w":38,"h":38} -}, -"sprites/blueprints/painter-mirrored.png": -{ - "frame": {"x":82,"y":45,"w":38,"h":19}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":38,"h":19}, - "sourceSize": {"w":38,"h":19} -}, -"sprites/blueprints/painter-quad.png": -{ - "frame": {"x":3,"y":83,"w":77,"h":19}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":77,"h":19}, - "sourceSize": {"w":77,"h":19} -}, -"sprites/blueprints/painter.png": -{ - "frame": {"x":3,"y":467,"w":38,"h":19}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":38,"h":19}, - "sourceSize": {"w":38,"h":19} -}, -"sprites/blueprints/rotater-ccw.png": -{ - "frame": {"x":45,"y":244,"w":19,"h":19}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":19,"h":19}, - "sourceSize": {"w":19,"h":19} -}, -"sprites/blueprints/rotater-fl.png": -{ - "frame": {"x":45,"y":267,"w":19,"h":19}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":19,"h":19}, - "sourceSize": {"w":19,"h":19} -}, -"sprites/blueprints/rotater.png": -{ - "frame": {"x":68,"y":198,"w":19,"h":19}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":19,"h":19}, - "sourceSize": {"w":19,"h":19} -}, -"sprites/blueprints/splitter-compact-inverse.png": -{ - "frame": {"x":68,"y":221,"w":19,"h":19}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":19,"h":19}, - "sourceSize": {"w":19,"h":19} -}, -"sprites/blueprints/splitter-compact.png": -{ - "frame": {"x":68,"y":244,"w":19,"h":19}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":19,"h":19}, - "sourceSize": {"w":19,"h":19} -}, -"sprites/blueprints/splitter.png": -{ - "frame": {"x":3,"y":651,"w":36,"h":19}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":1,"y":0,"w":36,"h":19}, - "sourceSize": {"w":38,"h":19} -}, -"sprites/blueprints/stacker.png": -{ - "frame": {"x":3,"y":559,"w":37,"h":19}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":0,"w":37,"h":19}, - "sourceSize": {"w":38,"h":19} -}, -"sprites/blueprints/trash-storage.png": -{ - "frame": {"x":3,"y":383,"w":35,"h":38}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":0,"w":35,"h":38}, - "sourceSize": {"w":38,"h":38} -}, -"sprites/blueprints/trash.png": -{ - "frame": {"x":68,"y":267,"w":19,"h":19}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":19,"h":19}, - "sourceSize": {"w":19,"h":19} -}, -"sprites/blueprints/underground_belt_entry-tier2.png": -{ - "frame": {"x":67,"y":336,"w":19,"h":18}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":1,"w":19,"h":18}, - "sourceSize": {"w":19,"h":19} -}, -"sprites/blueprints/underground_belt_entry.png": -{ - "frame": {"x":84,"y":127,"w":19,"h":16}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":3,"w":19,"h":16}, - "sourceSize": {"w":19,"h":19} -}, -"sprites/blueprints/underground_belt_exit-tier2.png": -{ - "frame": {"x":83,"y":147,"w":19,"h":16}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":0,"w":19,"h":16}, - "sourceSize": {"w":19,"h":19} -}, -"sprites/blueprints/underground_belt_exit.png": -{ - "frame": {"x":102,"y":173,"w":19,"h":16}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":0,"w":19,"h":16}, - "sourceSize": {"w":19,"h":19} -}, -"sprites/blueprints/wire_crossings-merger.png": -{ - "frame": {"x":84,"y":81,"w":14,"h":19}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":5,"y":0,"w":14,"h":19}, - "sourceSize": {"w":19,"h":19} -}, -"sprites/blueprints/wire_crossings.png": -{ - "frame": {"x":107,"y":104,"w":14,"h":19}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":5,"y":0,"w":14,"h":19}, - "sourceSize": {"w":19,"h":19} -}, -"sprites/blueprints/wire_left.png": -{ - "frame": {"x":79,"y":465,"w":10,"h":9}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":4,"w":10,"h":9}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/blueprints/wire_right.png": -{ - "frame": {"x":114,"y":225,"w":9,"h":9}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":4,"y":4,"w":9,"h":9}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/blueprints/wire_top.png": -{ - "frame": {"x":42,"y":383,"w":6,"h":13}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":4,"y":0,"w":6,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/buildings/advanced_processor.png": -{ - "frame": {"x":3,"y":217,"w":38,"h":38}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":38,"h":38}, - "sourceSize": {"w":38,"h":38} -}, -"sprites/buildings/belt_left.png": -{ - "frame": {"x":95,"y":646,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/buildings/belt_right.png": -{ - "frame": {"x":94,"y":663,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/buildings/belt_top.png": -{ - "frame": {"x":85,"y":167,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/buildings/cutter-quad.png": -{ - "frame": {"x":3,"y":152,"w":76,"h":19}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":1,"y":0,"w":76,"h":19}, - "sourceSize": {"w":77,"h":19} -}, -"sprites/buildings/cutter.png": -{ - "frame": {"x":3,"y":674,"w":36,"h":19}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":1,"y":0,"w":36,"h":19}, - "sourceSize": {"w":38,"h":19} -}, -"sprites/buildings/energy_generator.png": -{ - "frame": {"x":3,"y":342,"w":37,"h":37}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":1,"y":1,"w":37,"h":37}, - "sourceSize": {"w":38,"h":38} -}, -"sprites/buildings/hub.png": -{ - "frame": {"x":3,"y":3,"w":75,"h":76}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":1,"y":1,"w":75,"h":76}, - "sourceSize": {"w":77,"h":77} -}, -"sprites/buildings/miner-chainable.png": -{ - "frame": {"x":104,"y":68,"w":19,"h":19}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":19,"h":19}, - "sourceSize": {"w":19,"h":19} -}, -"sprites/buildings/miner.png": -{ - "frame": {"x":84,"y":104,"w":19,"h":19}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":19,"h":19}, - "sourceSize": {"w":19,"h":19} -}, -"sprites/buildings/mixer.png": -{ - "frame": {"x":3,"y":582,"w":37,"h":19}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":0,"w":37,"h":19}, - "sourceSize": {"w":38,"h":19} -}, -"sprites/buildings/painter-double.png": -{ - "frame": {"x":3,"y":259,"w":38,"h":38}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":38,"h":38}, - "sourceSize": {"w":38,"h":38} -}, -"sprites/buildings/painter-mirrored.png": -{ - "frame": {"x":3,"y":490,"w":38,"h":19}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":38,"h":19}, - "sourceSize": {"w":38,"h":19} -}, -"sprites/buildings/painter-quad.png": -{ - "frame": {"x":3,"y":106,"w":77,"h":19}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":77,"h":19}, - "sourceSize": {"w":77,"h":19} -}, -"sprites/buildings/painter.png": -{ - "frame": {"x":3,"y":513,"w":38,"h":19}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":38,"h":19}, - "sourceSize": {"w":38,"h":19} -}, -"sprites/buildings/rotater-ccw.png": -{ - "frame": {"x":45,"y":290,"w":19,"h":19}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":19,"h":19}, - "sourceSize": {"w":19,"h":19} -}, -"sprites/buildings/rotater-fl.png": -{ - "frame": {"x":68,"y":290,"w":19,"h":19}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":19,"h":19}, - "sourceSize": {"w":19,"h":19} -}, -"sprites/buildings/rotater.png": -{ - "frame": {"x":44,"y":313,"w":19,"h":19}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":19,"h":19}, - "sourceSize": {"w":19,"h":19} -}, -"sprites/buildings/splitter-compact-inverse.png": -{ - "frame": {"x":44,"y":336,"w":19,"h":19}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":19,"h":19}, - "sourceSize": {"w":19,"h":19} -}, -"sprites/buildings/splitter-compact.png": -{ - "frame": {"x":67,"y":313,"w":19,"h":19}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":19,"h":19}, - "sourceSize": {"w":19,"h":19} -}, -"sprites/buildings/splitter.png": -{ - "frame": {"x":45,"y":175,"w":36,"h":19}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":1,"y":0,"w":36,"h":19}, - "sourceSize": {"w":38,"h":19} -}, -"sprites/buildings/stacker.png": -{ - "frame": {"x":3,"y":605,"w":37,"h":19}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":0,"w":37,"h":19}, - "sourceSize": {"w":38,"h":19} -}, -"sprites/buildings/trash-storage.png": -{ - "frame": {"x":3,"y":425,"w":35,"h":38}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":0,"w":35,"h":38}, - "sourceSize": {"w":38,"h":38} -}, -"sprites/buildings/trash.png": -{ - "frame": {"x":44,"y":359,"w":19,"h":19}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":19,"h":19}, - "sourceSize": {"w":19,"h":19} -}, -"sprites/buildings/underground_belt_entry-tier2.png": -{ - "frame": {"x":67,"y":358,"w":19,"h":18}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":1,"w":19,"h":18}, - "sourceSize": {"w":19,"h":19} -}, -"sprites/buildings/underground_belt_entry.png": -{ - "frame": {"x":91,"y":198,"w":19,"h":16}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":3,"w":19,"h":16}, - "sourceSize": {"w":19,"h":19} -}, -"sprites/buildings/underground_belt_exit-tier2.png": -{ - "frame": {"x":91,"y":218,"w":19,"h":16}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":0,"w":19,"h":16}, - "sourceSize": {"w":19,"h":19} -}, -"sprites/buildings/underground_belt_exit.png": -{ - "frame": {"x":91,"y":238,"w":19,"h":16}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":0,"w":19,"h":16}, - "sourceSize": {"w":19,"h":19} -}, -"sprites/buildings/wire_crossings-merger.png": -{ - "frame": {"x":107,"y":127,"w":14,"h":19}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":5,"y":0,"w":14,"h":19}, - "sourceSize": {"w":19,"h":19} -}, -"sprites/buildings/wire_crossings.png": -{ - "frame": {"x":106,"y":150,"w":14,"h":19}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":5,"y":0,"w":14,"h":19}, - "sourceSize": {"w":19,"h":19} -}, -"sprites/buildings/wire_left.png": -{ - "frame": {"x":114,"y":238,"w":9,"h":9}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":4,"w":9,"h":9}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/buildings/wire_right.png": -{ - "frame": {"x":114,"y":251,"w":9,"h":9}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":4,"y":4,"w":9,"h":9}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/buildings/wire_top.png": -{ - "frame": {"x":96,"y":476,"w":5,"h":13}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":4,"y":0,"w":5,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/debug/acceptor_slot.png": -{ - "frame": {"x":112,"y":577,"w":6,"h":6}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":6,"h":6}, - "sourceSize": {"w":6,"h":6} -}, -"sprites/debug/ejector_slot.png": -{ - "frame": {"x":112,"y":587,"w":6,"h":6}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":6,"h":6}, - "sourceSize": {"w":6,"h":6} -}, -"sprites/map_overview/belt_forward.png": -{ - "frame": {"x":44,"y":621,"w":3,"h":3}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":3,"h":3}, - "sourceSize": {"w":3,"h":3} -}, -"sprites/map_overview/belt_left.png": -{ - "frame": {"x":51,"y":621,"w":3,"h":3}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":3,"h":3}, - "sourceSize": {"w":3,"h":3} -}, -"sprites/map_overview/belt_right.png": -{ - "frame": {"x":70,"y":688,"w":3,"h":3}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":3,"h":3}, - "sourceSize": {"w":3,"h":3} -}, -"sprites/misc/deletion_marker.png": -{ - "frame": {"x":85,"y":184,"w":10,"h":10}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":10,"h":10}, - "sourceSize": {"w":10,"h":10} -}, -"sprites/misc/energy_generator_overlay.png": -{ - "frame": {"x":82,"y":68,"w":18,"h":9}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":17,"y":27,"w":18,"h":9}, - "sourceSize": {"w":38,"h":38} -}, -"sprites/misc/hub_direction_indicator.png": -{ - "frame": {"x":111,"y":666,"w":3,"h":3}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":3,"h":3}, - "sourceSize": {"w":3,"h":3} -}, -"sprites/misc/lock_direction_indicator.png": -{ - "frame": {"x":112,"y":657,"w":5,"h":5}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":5,"h":5}, - "sourceSize": {"w":5,"h":5} -}, -"sprites/misc/slot_bad_arrow.png": -{ - "frame": {"x":85,"y":184,"w":10,"h":10}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":10,"h":10}, - "sourceSize": {"w":10,"h":10} -}, -"sprites/misc/slot_good_arrow.png": -{ - "frame": {"x":93,"y":394,"w":10,"h":10}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":10,"h":10}, - "sourceSize": {"w":10,"h":10} -}, -"sprites/misc/storage_overlay.png": -{ - "frame": {"x":102,"y":91,"w":18,"h":9}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":18,"h":9}, - "sourceSize": {"w":18,"h":9} -}, -"sprites/misc/waypoint.png": -{ - "frame": {"x":111,"y":673,"w":3,"h":3}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":3,"h":3}, - "sourceSize": {"w":3,"h":3} -}, -"sprites/misc/wires_overlay_tile.png": -{ - "frame": {"x":94,"y":680,"w":13,"h":13}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/wires/battery_empty.png": -{ - "frame": {"x":112,"y":597,"w":6,"h":6}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":6,"h":6}, - "sourceSize": {"w":6,"h":6} -}, -"sprites/wires/battery_full.png": -{ - "frame": {"x":112,"y":607,"w":6,"h":6}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":6,"h":6}, - "sourceSize": {"w":6,"h":6} -}, -"sprites/wires/battery_low.png": -{ - "frame": {"x":112,"y":617,"w":6,"h":6}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":6,"h":6}, - "sourceSize": {"w":6,"h":6} -}, -"sprites/wires/battery_medium.png": -{ - "frame": {"x":112,"y":627,"w":6,"h":6}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":6,"h":6}, - "sourceSize": {"w":6,"h":6} -}, -"sprites/wires/negative_energy.png": -{ - "frame": {"x":112,"y":637,"w":6,"h":6}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":6,"h":6}, - "sourceSize": {"w":6,"h":6} -}, -"sprites/wires/pin_negative_accept.png": -{ - "frame": {"x":42,"y":451,"w":11,"h":12}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":1,"y":0,"w":11,"h":12}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/wires/pin_negative_eject.png": -{ - "frame": {"x":114,"y":193,"w":9,"h":12}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":0,"w":9,"h":12}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/wires/pin_positive_accept.png": -{ - "frame": {"x":114,"y":209,"w":9,"h":12}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":0,"w":9,"h":12}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/wires/pin_positive_eject.png": -{ - "frame": {"x":112,"y":561,"w":11,"h":12}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":1,"y":0,"w":11,"h":12}, - "sourceSize": {"w":13,"h":13} -}, -"sprites/wires/positive_energy.png": -{ - "frame": {"x":112,"y":647,"w":6,"h":6}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":6,"h":6}, - "sourceSize": {"w":6,"h":6} -}, -"sprites/wires/waste_piled.png": -{ - "frame": {"x":60,"y":688,"w":6,"h":6}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":6,"h":6}, - "sourceSize": {"w":6,"h":6} -}}, -"meta": { - "app": "https://www.codeandweb.com/texturepacker", - "version": "1.0", - "image": "atlas0_10.png", - "format": "RGBA8888", - "size": {"w":126,"h":698}, - "scale": "0.1", - "smartupdate": "$TexturePacker:SmartUpdate:dfc84e4381978113df4ad0cd8a5aace9:4e9bd6f6c82aaaa8a4a583cab68dc719:f159918d23e5952766c6d23ab52278c6$" -} -} diff --git a/res_built/atlas/atlas0_10.png b/res_built/atlas/atlas0_10.png deleted file mode 100644 index 2fdd0720..00000000 Binary files a/res_built/atlas/atlas0_10.png and /dev/null differ diff --git a/res_built/atlas/atlas0_100.json b/res_built/atlas/atlas0_100.json deleted file mode 100644 index b5980771..00000000 --- a/res_built/atlas/atlas0_100.json +++ /dev/null @@ -1,1404 +0,0 @@ -{"frames": { - -"sprites/belt/forward_0.png": -{ - "frame": {"x":1515,"y":1539,"w":100,"h":126}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":0,"w":100,"h":126}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/forward_1.png": -{ - "frame": {"x":1436,"y":1712,"w":100,"h":126}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":0,"w":100,"h":126}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/forward_2.png": -{ - "frame": {"x":1671,"y":969,"w":100,"h":126}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":0,"w":100,"h":126}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/forward_3.png": -{ - "frame": {"x":1644,"y":1627,"w":100,"h":126}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":0,"w":100,"h":126}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/forward_4.png": -{ - "frame": {"x":1644,"y":1757,"w":100,"h":126}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":0,"w":100,"h":126}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/forward_5.png": -{ - "frame": {"x":1748,"y":1619,"w":100,"h":126}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":0,"w":100,"h":126}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/forward_6.png": -{ - "frame": {"x":1748,"y":1749,"w":100,"h":126}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":0,"w":100,"h":126}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/forward_7.png": -{ - "frame": {"x":1775,"y":1205,"w":100,"h":126}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":0,"w":100,"h":126}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/forward_8.png": -{ - "frame": {"x":1879,"y":1205,"w":100,"h":126}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":0,"w":100,"h":126}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/forward_9.png": -{ - "frame": {"x":1827,"y":1335,"w":100,"h":126}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":0,"w":100,"h":126}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/forward_10.png": -{ - "frame": {"x":1194,"y":1863,"w":100,"h":126}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":0,"w":100,"h":126}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/forward_11.png": -{ - "frame": {"x":1540,"y":1669,"w":100,"h":126}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":0,"w":100,"h":126}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/forward_12.png": -{ - "frame": {"x":1332,"y":1842,"w":100,"h":126}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":0,"w":100,"h":126}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/forward_13.png": -{ - "frame": {"x":1436,"y":1842,"w":100,"h":126}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":0,"w":100,"h":126}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/forward_14.png": -{ - "frame": {"x":1540,"y":1799,"w":100,"h":126}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":0,"w":100,"h":126}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/forward_15.png": -{ - "frame": {"x":2532,"y":589,"w":100,"h":126}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":0,"w":100,"h":126}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/forward_16.png": -{ - "frame": {"x":2533,"y":719,"w":100,"h":126}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":0,"w":100,"h":126}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/forward_17.png": -{ - "frame": {"x":2533,"y":849,"w":100,"h":126}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":0,"w":100,"h":126}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/forward_18.png": -{ - "frame": {"x":1463,"y":978,"w":100,"h":126}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":0,"w":100,"h":126}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/forward_19.png": -{ - "frame": {"x":1567,"y":977,"w":100,"h":126}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":0,"w":100,"h":126}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/forward_20.png": -{ - "frame": {"x":1567,"y":1107,"w":100,"h":126}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":0,"w":100,"h":126}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/forward_21.png": -{ - "frame": {"x":1671,"y":1099,"w":100,"h":126}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":0,"w":100,"h":126}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/forward_22.png": -{ - "frame": {"x":1567,"y":1237,"w":100,"h":126}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":0,"w":100,"h":126}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/forward_23.png": -{ - "frame": {"x":1671,"y":1229,"w":100,"h":126}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":0,"w":100,"h":126}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/forward_24.png": -{ - "frame": {"x":1619,"y":1367,"w":100,"h":126}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":0,"w":100,"h":126}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/forward_25.png": -{ - "frame": {"x":1619,"y":1497,"w":100,"h":126}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":0,"w":100,"h":126}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/forward_26.png": -{ - "frame": {"x":1723,"y":1359,"w":100,"h":126}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":0,"w":100,"h":126}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/forward_27.png": -{ - "frame": {"x":1723,"y":1489,"w":100,"h":126}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":0,"w":100,"h":126}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/left_0.png": -{ - "frame": {"x":1077,"y":1920,"w":113,"h":113}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":13,"w":113,"h":113}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/left_1.png": -{ - "frame": {"x":1842,"y":971,"w":113,"h":113}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":13,"w":113,"h":113}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/left_2.png": -{ - "frame": {"x":1959,"y":971,"w":113,"h":113}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":13,"w":113,"h":113}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/left_3.png": -{ - "frame": {"x":2310,"y":976,"w":113,"h":113}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":13,"w":113,"h":113}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/left_4.png": -{ - "frame": {"x":2334,"y":1210,"w":113,"h":113}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":13,"w":113,"h":113}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/left_5.png": -{ - "frame": {"x":2393,"y":1093,"w":113,"h":113}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":13,"w":113,"h":113}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/left_6.png": -{ - "frame": {"x":2451,"y":1210,"w":113,"h":113}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":13,"w":113,"h":113}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/left_7.png": -{ - "frame": {"x":2048,"y":1327,"w":113,"h":113}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":13,"w":113,"h":113}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/left_8.png": -{ - "frame": {"x":2165,"y":1327,"w":113,"h":113}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":13,"w":113,"h":113}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/left_9.png": -{ - "frame": {"x":2282,"y":1327,"w":113,"h":113}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":13,"w":113,"h":113}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/left_10.png": -{ - "frame": {"x":1842,"y":1088,"w":113,"h":113}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":13,"w":113,"h":113}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/left_11.png": -{ - "frame": {"x":1827,"y":1465,"w":113,"h":113}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":13,"w":113,"h":113}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/left_12.png": -{ - "frame": {"x":1852,"y":1582,"w":113,"h":113}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":13,"w":113,"h":113}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/left_13.png": -{ - "frame": {"x":1852,"y":1699,"w":113,"h":113}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":13,"w":113,"h":113}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/left_14.png": -{ - "frame": {"x":1852,"y":1816,"w":113,"h":113}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":13,"w":113,"h":113}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/left_15.png": -{ - "frame": {"x":1931,"y":1335,"w":113,"h":113}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":13,"w":113,"h":113}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/left_16.png": -{ - "frame": {"x":1944,"y":1452,"w":113,"h":113}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":13,"w":113,"h":113}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/left_17.png": -{ - "frame": {"x":1969,"y":1569,"w":113,"h":113}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":13,"w":113,"h":113}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/left_18.png": -{ - "frame": {"x":1969,"y":1686,"w":113,"h":113}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":13,"w":113,"h":113}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/left_19.png": -{ - "frame": {"x":1969,"y":1803,"w":113,"h":113}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":13,"w":113,"h":113}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/left_20.png": -{ - "frame": {"x":1959,"y":1088,"w":113,"h":113}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":13,"w":113,"h":113}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/left_21.png": -{ - "frame": {"x":1983,"y":1205,"w":113,"h":113}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":13,"w":113,"h":113}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/left_22.png": -{ - "frame": {"x":2076,"y":976,"w":113,"h":113}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":13,"w":113,"h":113}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/left_23.png": -{ - "frame": {"x":2193,"y":976,"w":113,"h":113}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":13,"w":113,"h":113}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/left_24.png": -{ - "frame": {"x":2159,"y":1093,"w":113,"h":113}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":13,"w":113,"h":113}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/left_25.png": -{ - "frame": {"x":2100,"y":1210,"w":113,"h":113}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":13,"w":113,"h":113}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/left_26.png": -{ - "frame": {"x":2217,"y":1210,"w":113,"h":113}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":13,"w":113,"h":113}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/left_27.png": -{ - "frame": {"x":2276,"y":1093,"w":113,"h":113}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":13,"w":113,"h":113}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/right_0.png": -{ - "frame": {"x":2399,"y":1327,"w":113,"h":113}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":13,"w":113,"h":113}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/right_1.png": -{ - "frame": {"x":2061,"y":1444,"w":113,"h":113}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":13,"w":113,"h":113}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/right_2.png": -{ - "frame": {"x":2320,"y":1678,"w":113,"h":113}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":13,"w":113,"h":113}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/right_3.png": -{ - "frame": {"x":2554,"y":1795,"w":113,"h":113}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":13,"w":113,"h":113}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/right_4.png": -{ - "frame": {"x":2510,"y":979,"w":113,"h":113}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":13,"w":113,"h":113}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/right_5.png": -{ - "frame": {"x":1644,"y":1887,"w":113,"h":113}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":13,"w":113,"h":113}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/right_6.png": -{ - "frame": {"x":1969,"y":1920,"w":113,"h":113}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":13,"w":113,"h":113}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/right_7.png": -{ - "frame": {"x":2086,"y":1912,"w":113,"h":113}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":13,"w":113,"h":113}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/right_8.png": -{ - "frame": {"x":2203,"y":1912,"w":113,"h":113}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":13,"w":113,"h":113}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/right_9.png": -{ - "frame": {"x":2320,"y":1912,"w":113,"h":113}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":13,"w":113,"h":113}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/right_10.png": -{ - "frame": {"x":2178,"y":1444,"w":113,"h":113}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":13,"w":113,"h":113}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/right_11.png": -{ - "frame": {"x":2295,"y":1444,"w":113,"h":113}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":13,"w":113,"h":113}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/right_12.png": -{ - "frame": {"x":2086,"y":1561,"w":113,"h":113}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":13,"w":113,"h":113}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/right_13.png": -{ - "frame": {"x":2086,"y":1678,"w":113,"h":113}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":13,"w":113,"h":113}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/right_14.png": -{ - "frame": {"x":2203,"y":1561,"w":113,"h":113}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":13,"w":113,"h":113}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/right_15.png": -{ - "frame": {"x":2086,"y":1795,"w":113,"h":113}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":13,"w":113,"h":113}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/right_16.png": -{ - "frame": {"x":2203,"y":1678,"w":113,"h":113}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":13,"w":113,"h":113}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/right_17.png": -{ - "frame": {"x":2203,"y":1795,"w":113,"h":113}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":13,"w":113,"h":113}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/right_18.png": -{ - "frame": {"x":2412,"y":1444,"w":113,"h":113}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":13,"w":113,"h":113}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/right_19.png": -{ - "frame": {"x":2320,"y":1561,"w":113,"h":113}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":13,"w":113,"h":113}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/right_20.png": -{ - "frame": {"x":2320,"y":1795,"w":113,"h":113}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":13,"w":113,"h":113}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/right_21.png": -{ - "frame": {"x":2437,"y":1561,"w":113,"h":113}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":13,"w":113,"h":113}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/right_22.png": -{ - "frame": {"x":2437,"y":1678,"w":113,"h":113}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":13,"w":113,"h":113}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/right_23.png": -{ - "frame": {"x":2437,"y":1795,"w":113,"h":113}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":13,"w":113,"h":113}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/right_24.png": -{ - "frame": {"x":2516,"y":1327,"w":113,"h":113}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":13,"w":113,"h":113}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/right_25.png": -{ - "frame": {"x":2529,"y":1444,"w":113,"h":113}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":13,"w":113,"h":113}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/right_26.png": -{ - "frame": {"x":2554,"y":1561,"w":113,"h":113}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":13,"w":113,"h":113}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/belt/right_27.png": -{ - "frame": {"x":2554,"y":1678,"w":113,"h":113}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":13,"w":113,"h":113}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/blueprints/advanced_processor.png": -{ - "frame": {"x":3,"y":1316,"w":374,"h":358}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":10,"y":12,"w":374,"h":358}, - "sourceSize": {"w":384,"h":384} -}, -"sprites/blueprints/belt_left.png": -{ - "frame": {"x":2607,"y":3,"w":114,"h":114}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":12,"w":114,"h":114}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/blueprints/belt_right.png": -{ - "frame": {"x":959,"y":1920,"w":114,"h":114}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":12,"y":12,"w":114,"h":114}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/blueprints/belt_top.png": -{ - "frame": {"x":1330,"y":1712,"w":102,"h":126}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":12,"y":0,"w":102,"h":126}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/blueprints/cutter-quad.png": -{ - "frame": {"x":1485,"y":3,"w":730,"h":191}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":23,"y":0,"w":730,"h":191}, - "sourceSize": {"w":768,"h":192} -}, -"sprites/blueprints/cutter.png": -{ - "frame": {"x":1485,"y":198,"w":341,"h":191}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":23,"y":0,"w":341,"h":191}, - "sourceSize": {"w":384,"h":192} -}, -"sprites/blueprints/energy_generator.png": -{ - "frame": {"x":381,"y":1319,"w":348,"h":364}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":20,"y":20,"w":348,"h":364}, - "sourceSize": {"w":384,"h":384} -}, -"sprites/blueprints/miner-chainable.png": -{ - "frame": {"x":2163,"y":588,"w":182,"h":190}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":0,"w":182,"h":190}, - "sourceSize": {"w":192,"h":192} -}, -"sprites/blueprints/miner.png": -{ - "frame": {"x":2128,"y":782,"w":182,"h":190}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":0,"w":182,"h":190}, - "sourceSize": {"w":192,"h":192} -}, -"sprites/blueprints/mixer.png": -{ - "frame": {"x":1123,"y":783,"w":347,"h":191}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":18,"y":0,"w":347,"h":191}, - "sourceSize": {"w":384,"h":192} -}, -"sprites/blueprints/painter-double.png": -{ - "frame": {"x":735,"y":395,"w":384,"h":382}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":0,"w":384,"h":382}, - "sourceSize": {"w":384,"h":384} -}, -"sprites/blueprints/painter-mirrored.png": -{ - "frame": {"x":2219,"y":3,"w":384,"h":192}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":384,"h":192}, - "sourceSize": {"w":384,"h":192} -}, -"sprites/blueprints/painter-quad.png": -{ - "frame": {"x":735,"y":3,"w":746,"h":192}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":7,"y":0,"w":746,"h":192}, - "sourceSize": {"w":768,"h":192} -}, -"sprites/blueprints/painter.png": -{ - "frame": {"x":380,"y":1687,"w":384,"h":192}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":384,"h":192}, - "sourceSize": {"w":384,"h":192} -}, -"sprites/blueprints/rotater-ccw.png": -{ - "frame": {"x":2218,"y":393,"w":189,"h":191}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":0,"w":189,"h":191}, - "sourceSize": {"w":192,"h":192} -}, -"sprites/blueprints/rotater-fl.png": -{ - "frame": {"x":1458,"y":587,"w":189,"h":191}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":0,"w":189,"h":191}, - "sourceSize": {"w":192,"h":192} -}, -"sprites/blueprints/rotater.png": -{ - "frame": {"x":1474,"y":782,"w":189,"h":191}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":0,"w":189,"h":191}, - "sourceSize": {"w":192,"h":192} -}, -"sprites/blueprints/splitter-compact-inverse.png": -{ - "frame": {"x":1783,"y":589,"w":188,"h":182}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":4,"w":188,"h":182}, - "sourceSize": {"w":192,"h":192} -}, -"sprites/blueprints/splitter-compact.png": -{ - "frame": {"x":2547,"y":393,"w":185,"h":182}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":7,"y":4,"w":185,"h":182}, - "sourceSize": {"w":192,"h":192} -}, -"sprites/blueprints/splitter.png": -{ - "frame": {"x":1830,"y":198,"w":340,"h":191}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":23,"y":0,"w":340,"h":191}, - "sourceSize": {"w":384,"h":192} -}, -"sprites/blueprints/stacker.png": -{ - "frame": {"x":1112,"y":978,"w":347,"h":191}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":18,"y":0,"w":347,"h":191}, - "sourceSize": {"w":384,"h":192} -}, -"sprites/blueprints/trash-storage.png": -{ - "frame": {"x":1123,"y":395,"w":331,"h":384}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":29,"y":0,"w":331,"h":384}, - "sourceSize": {"w":384,"h":384} -}, -"sprites/blueprints/trash.png": -{ - "frame": {"x":1826,"y":393,"w":192,"h":192}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":192,"h":192}, - "sourceSize": {"w":192,"h":192} -}, -"sprites/blueprints/underground_belt_entry-tier2.png": -{ - "frame": {"x":1432,"y":1369,"w":183,"h":166}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":5,"y":26,"w":183,"h":166}, - "sourceSize": {"w":192,"h":192} -}, -"sprites/blueprints/underground_belt_entry.png": -{ - "frame": {"x":569,"y":1883,"w":182,"h":148}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":44,"w":182,"h":148}, - "sourceSize": {"w":192,"h":192} -}, -"sprites/blueprints/underground_belt_exit-tier2.png": -{ - "frame": {"x":380,"y":1883,"w":185,"h":148}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":5,"y":0,"w":185,"h":148}, - "sourceSize": {"w":192,"h":192} -}, -"sprites/blueprints/underground_belt_exit.png": -{ - "frame": {"x":959,"y":1768,"w":182,"h":148}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":0,"w":182,"h":148}, - "sourceSize": {"w":192,"h":192} -}, -"sprites/blueprints/wire_crossings-merger.png": -{ - "frame": {"x":2411,"y":393,"w":132,"h":192}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":60,"y":0,"w":132,"h":192}, - "sourceSize": {"w":192,"h":192} -}, -"sprites/blueprints/wire_crossings.png": -{ - "frame": {"x":1857,"y":775,"w":132,"h":192}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":60,"y":0,"w":132,"h":192}, - "sourceSize": {"w":192,"h":192} -}, -"sprites/blueprints/wire_left.png": -{ - "frame": {"x":2427,"y":974,"w":79,"h":79}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":47,"w":79,"h":79}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/blueprints/wire_right.png": -{ - "frame": {"x":2076,"y":1093,"w":79,"h":80}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":47,"y":46,"w":79,"h":80}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/blueprints/wire_top.png": -{ - "frame": {"x":2497,"y":782,"w":32,"h":126}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":47,"y":0,"w":32,"h":126}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/buildings/advanced_processor.png": -{ - "frame": {"x":3,"y":1678,"w":373,"h":356}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":11,"y":13,"w":373,"h":356}, - "sourceSize": {"w":384,"h":384} -}, -"sprites/buildings/belt_left.png": -{ - "frame": {"x":2437,"y":1912,"w":113,"h":113}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":13,"w":113,"h":113}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/buildings/belt_right.png": -{ - "frame": {"x":2554,"y":1912,"w":113,"h":113}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":13,"w":113,"h":113}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/buildings/belt_top.png": -{ - "frame": {"x":1515,"y":1539,"w":100,"h":126}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":0,"w":100,"h":126}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/buildings/cutter-quad.png": -{ - "frame": {"x":3,"y":737,"w":728,"h":190}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":24,"y":0,"w":728,"h":190}, - "sourceSize": {"w":768,"h":192} -}, -"sprites/buildings/cutter.png": -{ - "frame": {"x":2174,"y":199,"w":339,"h":190}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":24,"y":0,"w":339,"h":190}, - "sourceSize": {"w":384,"h":192} -}, -"sprites/buildings/energy_generator.png": -{ - "frame": {"x":733,"y":1171,"w":346,"h":363}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":21,"y":21,"w":346,"h":363}, - "sourceSize": {"w":384,"h":384} -}, -"sprites/buildings/hub.png": -{ - "frame": {"x":3,"y":3,"w":728,"h":730}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":20,"y":22,"w":728,"h":730}, - "sourceSize": {"w":768,"h":768} -}, -"sprites/buildings/miner-chainable.png": -{ - "frame": {"x":2314,"y":782,"w":179,"h":188}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":8,"y":1,"w":179,"h":188}, - "sourceSize": {"w":192,"h":192} -}, -"sprites/buildings/miner.png": -{ - "frame": {"x":2349,"y":589,"w":179,"h":189}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":8,"y":0,"w":179,"h":189}, - "sourceSize": {"w":192,"h":192} -}, -"sprites/buildings/mixer.png": -{ - "frame": {"x":1083,"y":1173,"w":345,"h":190}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":19,"y":0,"w":345,"h":190}, - "sourceSize": {"w":384,"h":192} -}, -"sprites/buildings/painter-double.png": -{ - "frame": {"x":3,"y":931,"w":384,"h":381}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":0,"w":384,"h":381}, - "sourceSize": {"w":384,"h":384} -}, -"sprites/buildings/painter-mirrored.png": -{ - "frame": {"x":735,"y":781,"w":384,"h":191}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":0,"w":384,"h":191}, - "sourceSize": {"w":384,"h":192} -}, -"sprites/buildings/painter-quad.png": -{ - "frame": {"x":735,"y":199,"w":744,"h":192}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":8,"y":0,"w":744,"h":192}, - "sourceSize": {"w":768,"h":192} -}, -"sprites/buildings/painter.png": -{ - "frame": {"x":724,"y":976,"w":384,"h":191}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":0,"w":384,"h":191}, - "sourceSize": {"w":384,"h":192} -}, -"sprites/buildings/rotater-ccw.png": -{ - "frame": {"x":2517,"y":199,"w":187,"h":190}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":3,"y":0,"w":187,"h":190}, - "sourceSize": {"w":192,"h":192} -}, -"sprites/buildings/rotater-fl.png": -{ - "frame": {"x":1667,"y":775,"w":186,"h":190}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":0,"w":186,"h":190}, - "sourceSize": {"w":192,"h":192} -}, -"sprites/buildings/rotater.png": -{ - "frame": {"x":768,"y":1628,"w":187,"h":190}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":3,"y":0,"w":187,"h":190}, - "sourceSize": {"w":192,"h":192} -}, -"sprites/buildings/splitter-compact-inverse.png": -{ - "frame": {"x":768,"y":1822,"w":187,"h":180}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":5,"w":187,"h":180}, - "sourceSize": {"w":192,"h":192} -}, -"sprites/buildings/splitter-compact.png": -{ - "frame": {"x":1975,"y":589,"w":184,"h":180}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":8,"y":5,"w":184,"h":180}, - "sourceSize": {"w":192,"h":192} -}, -"sprites/buildings/splitter.png": -{ - "frame": {"x":1483,"y":393,"w":339,"h":190}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":24,"y":0,"w":339,"h":190}, - "sourceSize": {"w":384,"h":192} -}, -"sprites/buildings/stacker.png": -{ - "frame": {"x":1083,"y":1367,"w":345,"h":190}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":19,"y":0,"w":345,"h":190}, - "sourceSize": {"w":384,"h":192} -}, -"sprites/buildings/trash-storage.png": -{ - "frame": {"x":391,"y":931,"w":329,"h":384}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":30,"y":0,"w":329,"h":384}, - "sourceSize": {"w":384,"h":384} -}, -"sprites/buildings/trash.png": -{ - "frame": {"x":2022,"y":393,"w":192,"h":191}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":1,"w":192,"h":191}, - "sourceSize": {"w":192,"h":192} -}, -"sprites/buildings/underground_belt_entry-tier2.png": -{ - "frame": {"x":959,"y":1599,"w":181,"h":165}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":7,"y":27,"w":181,"h":165}, - "sourceSize": {"w":192,"h":192} -}, -"sprites/buildings/underground_belt_entry.png": -{ - "frame": {"x":1145,"y":1712,"w":181,"h":147}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":7,"y":45,"w":181,"h":147}, - "sourceSize": {"w":192,"h":192} -}, -"sprites/buildings/underground_belt_exit-tier2.png": -{ - "frame": {"x":1144,"y":1561,"w":182,"h":147}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":7,"y":0,"w":182,"h":147}, - "sourceSize": {"w":192,"h":192} -}, -"sprites/buildings/underground_belt_exit.png": -{ - "frame": {"x":1330,"y":1561,"w":181,"h":147}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":7,"y":0,"w":181,"h":147}, - "sourceSize": {"w":192,"h":192} -}, -"sprites/buildings/wire_crossings-merger.png": -{ - "frame": {"x":1993,"y":773,"w":131,"h":192}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":61,"y":0,"w":131,"h":192}, - "sourceSize": {"w":192,"h":192} -}, -"sprites/buildings/wire_crossings.png": -{ - "frame": {"x":1432,"y":1173,"w":131,"h":192}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":61,"y":0,"w":131,"h":192}, - "sourceSize": {"w":192,"h":192} -}, -"sprites/buildings/wire_left.png": -{ - "frame": {"x":2510,"y":1096,"w":78,"h":78}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":48,"w":78,"h":78}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/buildings/wire_right.png": -{ - "frame": {"x":2627,"y":983,"w":78,"h":78}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":48,"y":48,"w":78,"h":78}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/buildings/wire_top.png": -{ - "frame": {"x":1298,"y":1863,"w":30,"h":126}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":48,"y":0,"w":30,"h":126}, - "sourceSize": {"w":126,"h":126} -}, -"sprites/debug/acceptor_slot.png": -{ - "frame": {"x":2607,"y":121,"w":50,"h":64}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":7,"y":0,"w":50,"h":64}, - "sourceSize": {"w":64,"h":64} -}, -"sprites/debug/ejector_slot.png": -{ - "frame": {"x":2661,"y":121,"w":50,"h":64}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":7,"y":0,"w":50,"h":64}, - "sourceSize": {"w":64,"h":64} -}, -"sprites/map_overview/belt_forward.png": -{ - "frame": {"x":2427,"y":1057,"w":24,"h":32}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":4,"y":0,"w":24,"h":32}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/map_overview/belt_left.png": -{ - "frame": {"x":2510,"y":1178,"w":28,"h":28}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":4,"w":28,"h":28}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/map_overview/belt_right.png": -{ - "frame": {"x":2542,"y":1178,"w":28,"h":28}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":4,"y":4,"w":28,"h":28}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/misc/deletion_marker.png": -{ - "frame": {"x":2637,"y":897,"w":82,"h":82}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":7,"y":7,"w":82,"h":82}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/misc/energy_generator_overlay.png": -{ - "frame": {"x":913,"y":1538,"w":153,"h":57}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":183,"y":290,"w":153,"h":57}, - "sourceSize": {"w":384,"h":384} -}, -"sprites/misc/hub_direction_indicator.png": -{ - "frame": {"x":2497,"y":912,"w":32,"h":32}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":32,"h":32}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/misc/lock_direction_indicator.png": -{ - "frame": {"x":1256,"y":1993,"w":48,"h":30}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":9,"w":48,"h":30}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/misc/slot_bad_arrow.png": -{ - "frame": {"x":2637,"y":897,"w":82,"h":82}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":7,"y":7,"w":82,"h":82}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/misc/slot_good_arrow.png": -{ - "frame": {"x":2637,"y":797,"w":80,"h":96}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":8,"y":0,"w":80,"h":96}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/misc/storage_overlay.png": -{ - "frame": {"x":733,"y":1538,"w":176,"h":86}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":3,"y":4,"w":176,"h":86}, - "sourceSize": {"w":180,"h":90} -}, -"sprites/misc/waypoint.png": -{ - "frame": {"x":2455,"y":1057,"w":24,"h":32}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":4,"y":0,"w":24,"h":32}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/misc/wires_overlay_tile.png": -{ - "frame": {"x":1651,"y":587,"w":128,"h":128}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":128,"h":128}, - "sourceSize": {"w":128,"h":128} -}, -"sprites/wires/battery_empty.png": -{ - "frame": {"x":1525,"y":1108,"w":38,"h":60}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":2,"w":38,"h":60}, - "sourceSize": {"w":64,"h":64} -}, -"sprites/wires/battery_full.png": -{ - "frame": {"x":1651,"y":719,"w":58,"h":38}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":3,"y":14,"w":58,"h":38}, - "sourceSize": {"w":64,"h":64} -}, -"sprites/wires/battery_low.png": -{ - "frame": {"x":1194,"y":1993,"w":58,"h":38}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":3,"y":14,"w":58,"h":38}, - "sourceSize": {"w":64,"h":64} -}, -"sprites/wires/battery_medium.png": -{ - "frame": {"x":1540,"y":1929,"w":58,"h":38}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":3,"y":14,"w":58,"h":38}, - "sourceSize": {"w":64,"h":64} -}, -"sprites/wires/negative_energy.png": -{ - "frame": {"x":1145,"y":1863,"w":42,"h":42}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":11,"y":11,"w":42,"h":42}, - "sourceSize": {"w":64,"h":64} -}, -"sprites/wires/pin_negative_accept.png": -{ - "frame": {"x":2636,"y":579,"w":73,"h":105}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":27,"y":0,"w":73,"h":105}, - "sourceSize": {"w":128,"h":128} -}, -"sprites/wires/pin_negative_eject.png": -{ - "frame": {"x":1775,"y":969,"w":63,"h":100}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":32,"y":0,"w":63,"h":100}, - "sourceSize": {"w":128,"h":128} -}, -"sprites/wires/pin_positive_accept.png": -{ - "frame": {"x":1775,"y":1073,"w":63,"h":100}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":32,"y":0,"w":63,"h":100}, - "sourceSize": {"w":128,"h":128} -}, -"sprites/wires/pin_positive_eject.png": -{ - "frame": {"x":2637,"y":688,"w":73,"h":105}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":27,"y":0,"w":73,"h":105}, - "sourceSize": {"w":128,"h":128} -}, -"sprites/wires/positive_energy.png": -{ - "frame": {"x":1713,"y":719,"w":42,"h":42}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":11,"y":11,"w":42,"h":42}, - "sourceSize": {"w":64,"h":64} -}, -"sprites/wires/waste_piled.png": -{ - "frame": {"x":1463,"y":1108,"w":58,"h":55}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":3,"y":4,"w":58,"h":55}, - "sourceSize": {"w":64,"h":64} -}}, -"meta": { - "app": "https://www.codeandweb.com/texturepacker", - "version": "1.0", - "image": "atlas0_100.png", - "format": "RGBA8888", - "size": {"w":2735,"h":2037}, - "scale": "1", - "smartupdate": "$TexturePacker:SmartUpdate:dfc84e4381978113df4ad0cd8a5aace9:4e9bd6f6c82aaaa8a4a583cab68dc719:f159918d23e5952766c6d23ab52278c6$" -} -} diff --git a/res_built/atlas/atlas0_100.png b/res_built/atlas/atlas0_100.png deleted file mode 100644 index a072216d..00000000 Binary files a/res_built/atlas/atlas0_100.png and /dev/null differ diff --git a/res_built/atlas/atlas0_25.json b/res_built/atlas/atlas0_25.json deleted file mode 100644 index dee62306..00000000 --- a/res_built/atlas/atlas0_25.json +++ /dev/null @@ -1,1404 +0,0 @@ -{"frames": { - -"sprites/belt/forward_0.png": -{ - "frame": {"x":452,"y":459,"w":28,"h":32}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":0,"w":28,"h":32}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/forward_1.png": -{ - "frame": {"x":452,"y":495,"w":28,"h":32}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":0,"w":28,"h":32}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/forward_2.png": -{ - "frame": {"x":246,"y":697,"w":28,"h":32}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":0,"w":28,"h":32}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/forward_3.png": -{ - "frame": {"x":382,"y":624,"w":28,"h":32}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":0,"w":28,"h":32}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/forward_4.png": -{ - "frame": {"x":350,"y":628,"w":28,"h":32}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":0,"w":28,"h":32}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/forward_5.png": -{ - "frame": {"x":318,"y":640,"w":28,"h":32}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":0,"w":28,"h":32}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/forward_6.png": -{ - "frame": {"x":382,"y":660,"w":28,"h":32}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":0,"w":28,"h":32}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/forward_7.png": -{ - "frame": {"x":350,"y":664,"w":28,"h":32}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":0,"w":28,"h":32}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/forward_8.png": -{ - "frame": {"x":346,"y":802,"w":28,"h":32}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":0,"w":28,"h":32}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/forward_9.png": -{ - "frame": {"x":378,"y":802,"w":28,"h":32}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":0,"w":28,"h":32}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/forward_10.png": -{ - "frame": {"x":148,"y":723,"w":28,"h":32}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":0,"w":28,"h":32}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/forward_11.png": -{ - "frame": {"x":148,"y":759,"w":28,"h":32}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":0,"w":28,"h":32}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/forward_12.png": -{ - "frame": {"x":148,"y":795,"w":28,"h":32}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":0,"w":28,"h":32}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/forward_13.png": -{ - "frame": {"x":218,"y":536,"w":28,"h":32}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":0,"w":28,"h":32}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/forward_14.png": -{ - "frame": {"x":180,"y":712,"w":28,"h":32}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":0,"w":28,"h":32}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/forward_15.png": -{ - "frame": {"x":180,"y":748,"w":28,"h":32}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":0,"w":28,"h":32}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/forward_16.png": -{ - "frame": {"x":180,"y":784,"w":28,"h":32}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":0,"w":28,"h":32}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/forward_17.png": -{ - "frame": {"x":218,"y":572,"w":28,"h":32}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":0,"w":28,"h":32}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/forward_18.png": -{ - "frame": {"x":246,"y":625,"w":28,"h":32}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":0,"w":28,"h":32}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/forward_19.png": -{ - "frame": {"x":246,"y":661,"w":28,"h":32}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":0,"w":28,"h":32}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/forward_20.png": -{ - "frame": {"x":246,"y":733,"w":28,"h":32}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":0,"w":28,"h":32}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/forward_21.png": -{ - "frame": {"x":246,"y":769,"w":28,"h":32}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":0,"w":28,"h":32}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/forward_22.png": -{ - "frame": {"x":318,"y":568,"w":28,"h":32}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":0,"w":28,"h":32}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/forward_23.png": -{ - "frame": {"x":350,"y":556,"w":28,"h":32}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":0,"w":28,"h":32}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/forward_24.png": -{ - "frame": {"x":382,"y":552,"w":28,"h":32}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":0,"w":28,"h":32}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/forward_25.png": -{ - "frame": {"x":318,"y":604,"w":28,"h":32}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":0,"w":28,"h":32}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/forward_26.png": -{ - "frame": {"x":350,"y":592,"w":28,"h":32}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":0,"w":28,"h":32}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/forward_27.png": -{ - "frame": {"x":382,"y":588,"w":28,"h":32}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":0,"w":28,"h":32}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/left_0.png": -{ - "frame": {"x":452,"y":531,"w":30,"h":30}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":2,"w":30,"h":30}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/left_1.png": -{ - "frame": {"x":343,"y":522,"w":30,"h":30}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":2,"w":30,"h":30}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/left_2.png": -{ - "frame": {"x":178,"y":610,"w":30,"h":30}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":2,"w":30,"h":30}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/left_3.png": -{ - "frame": {"x":212,"y":744,"w":30,"h":30}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":2,"w":30,"h":30}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/left_4.png": -{ - "frame": {"x":212,"y":778,"w":30,"h":30}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":2,"w":30,"h":30}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/left_5.png": -{ - "frame": {"x":284,"y":543,"w":30,"h":30}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":2,"w":30,"h":30}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/left_6.png": -{ - "frame": {"x":250,"y":591,"w":30,"h":30}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":2,"w":30,"h":30}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/left_7.png": -{ - "frame": {"x":284,"y":577,"w":30,"h":30}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":2,"w":30,"h":30}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/left_8.png": -{ - "frame": {"x":414,"y":545,"w":30,"h":30}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":2,"w":30,"h":30}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/left_9.png": -{ - "frame": {"x":284,"y":611,"w":30,"h":30}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":2,"w":30,"h":30}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/left_10.png": -{ - "frame": {"x":150,"y":485,"w":30,"h":30}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":2,"w":30,"h":30}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/left_11.png": -{ - "frame": {"x":150,"y":519,"w":30,"h":30}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":2,"w":30,"h":30}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/left_12.png": -{ - "frame": {"x":144,"y":553,"w":30,"h":30}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":2,"w":30,"h":30}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/left_13.png": -{ - "frame": {"x":144,"y":587,"w":30,"h":30}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":2,"w":30,"h":30}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/left_14.png": -{ - "frame": {"x":144,"y":621,"w":30,"h":30}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":2,"w":30,"h":30}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/left_15.png": -{ - "frame": {"x":144,"y":655,"w":30,"h":30}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":2,"w":30,"h":30}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/left_16.png": -{ - "frame": {"x":144,"y":689,"w":30,"h":30}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":2,"w":30,"h":30}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/left_17.png": -{ - "frame": {"x":184,"y":508,"w":30,"h":30}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":2,"w":30,"h":30}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/left_18.png": -{ - "frame": {"x":184,"y":542,"w":30,"h":30}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":2,"w":30,"h":30}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/left_19.png": -{ - "frame": {"x":178,"y":576,"w":30,"h":30}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":2,"w":30,"h":30}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/left_20.png": -{ - "frame": {"x":178,"y":644,"w":30,"h":30}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":2,"w":30,"h":30}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/left_21.png": -{ - "frame": {"x":178,"y":678,"w":30,"h":30}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":2,"w":30,"h":30}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/left_22.png": -{ - "frame": {"x":250,"y":523,"w":30,"h":30}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":2,"w":30,"h":30}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/left_23.png": -{ - "frame": {"x":250,"y":557,"w":30,"h":30}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":2,"w":30,"h":30}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/left_24.png": -{ - "frame": {"x":212,"y":608,"w":30,"h":30}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":2,"w":30,"h":30}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/left_25.png": -{ - "frame": {"x":212,"y":642,"w":30,"h":30}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":2,"w":30,"h":30}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/left_26.png": -{ - "frame": {"x":212,"y":676,"w":30,"h":30}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":2,"w":30,"h":30}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/left_27.png": -{ - "frame": {"x":212,"y":710,"w":30,"h":30}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":2,"w":30,"h":30}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/right_0.png": -{ - "frame": {"x":414,"y":579,"w":30,"h":30}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":2,"w":30,"h":30}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/right_1.png": -{ - "frame": {"x":448,"y":565,"w":30,"h":30}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":2,"w":30,"h":30}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/right_2.png": -{ - "frame": {"x":312,"y":778,"w":30,"h":30}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":2,"w":30,"h":30}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/right_3.png": -{ - "frame": {"x":414,"y":715,"w":30,"h":30}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":2,"w":30,"h":30}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/right_4.png": -{ - "frame": {"x":448,"y":701,"w":30,"h":30}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":2,"w":30,"h":30}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/right_5.png": -{ - "frame": {"x":380,"y":766,"w":30,"h":30}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":2,"w":30,"h":30}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/right_6.png": -{ - "frame": {"x":414,"y":749,"w":30,"h":30}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":2,"w":30,"h":30}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/right_7.png": -{ - "frame": {"x":448,"y":735,"w":30,"h":30}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":2,"w":30,"h":30}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/right_8.png": -{ - "frame": {"x":414,"y":783,"w":30,"h":30}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":2,"w":30,"h":30}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/right_9.png": -{ - "frame": {"x":448,"y":769,"w":30,"h":30}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":2,"w":30,"h":30}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/right_10.png": -{ - "frame": {"x":278,"y":645,"w":30,"h":30}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":2,"w":30,"h":30}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/right_11.png": -{ - "frame": {"x":278,"y":679,"w":30,"h":30}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":2,"w":30,"h":30}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/right_12.png": -{ - "frame": {"x":278,"y":713,"w":30,"h":30}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":2,"w":30,"h":30}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/right_13.png": -{ - "frame": {"x":278,"y":747,"w":30,"h":30}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":2,"w":30,"h":30}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/right_14.png": -{ - "frame": {"x":278,"y":781,"w":30,"h":30}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":2,"w":30,"h":30}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/right_15.png": -{ - "frame": {"x":448,"y":599,"w":30,"h":30}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":2,"w":30,"h":30}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/right_16.png": -{ - "frame": {"x":414,"y":613,"w":30,"h":30}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":2,"w":30,"h":30}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/right_17.png": -{ - "frame": {"x":312,"y":676,"w":30,"h":30}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":2,"w":30,"h":30}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/right_18.png": -{ - "frame": {"x":312,"y":710,"w":30,"h":30}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":2,"w":30,"h":30}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/right_19.png": -{ - "frame": {"x":312,"y":744,"w":30,"h":30}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":2,"w":30,"h":30}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/right_20.png": -{ - "frame": {"x":448,"y":633,"w":30,"h":30}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":2,"w":30,"h":30}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/right_21.png": -{ - "frame": {"x":414,"y":647,"w":30,"h":30}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":2,"w":30,"h":30}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/right_22.png": -{ - "frame": {"x":346,"y":700,"w":30,"h":30}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":2,"w":30,"h":30}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/right_23.png": -{ - "frame": {"x":346,"y":734,"w":30,"h":30}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":2,"w":30,"h":30}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/right_24.png": -{ - "frame": {"x":346,"y":768,"w":30,"h":30}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":2,"w":30,"h":30}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/right_25.png": -{ - "frame": {"x":414,"y":681,"w":30,"h":30}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":2,"w":30,"h":30}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/right_26.png": -{ - "frame": {"x":448,"y":667,"w":30,"h":30}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":2,"w":30,"h":30}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/belt/right_27.png": -{ - "frame": {"x":380,"y":732,"w":30,"h":30}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":2,"w":30,"h":30}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/blueprints/advanced_processor.png": -{ - "frame": {"x":3,"y":344,"w":95,"h":92}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":1,"y":2,"w":95,"h":92}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/blueprints/belt_left.png": -{ - "frame": {"x":448,"y":803,"w":30,"h":30}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":2,"w":30,"h":30}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/blueprints/belt_right.png": -{ - "frame": {"x":103,"y":340,"w":30,"h":30}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":2,"w":30,"h":30}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/blueprints/belt_top.png": -{ - "frame": {"x":382,"y":696,"w":28,"h":32}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":0,"w":28,"h":32}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/blueprints/cutter-quad.png": -{ - "frame": {"x":3,"y":192,"w":184,"h":48}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":5,"y":0,"w":184,"h":48}, - "sourceSize": {"w":192,"h":48} -}, -"sprites/blueprints/cutter.png": -{ - "frame": {"x":196,"y":315,"w":87,"h":48}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":5,"y":0,"w":87,"h":48}, - "sourceSize": {"w":96,"h":48} -}, -"sprites/blueprints/energy_generator.png": -{ - "frame": {"x":3,"y":735,"w":89,"h":92}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":4,"y":4,"w":89,"h":92}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/blueprints/miner-chainable.png": -{ - "frame": {"x":248,"y":419,"w":47,"h":48}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":1,"y":0,"w":47,"h":48}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/blueprints/miner.png": -{ - "frame": {"x":299,"y":419,"w":47,"h":48}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":1,"y":0,"w":47,"h":48}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/blueprints/mixer.png": -{ - "frame": {"x":196,"y":211,"w":89,"h":48}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":3,"y":0,"w":89,"h":48}, - "sourceSize": {"w":96,"h":48} -}, -"sprites/blueprints/painter-double.png": -{ - "frame": {"x":383,"y":3,"w":96,"h":96}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":96,"h":96}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/blueprints/painter-mirrored.png": -{ - "frame": {"x":191,"y":159,"w":96,"h":48}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":96,"h":48}, - "sourceSize": {"w":96,"h":48} -}, -"sprites/blueprints/painter-quad.png": -{ - "frame": {"x":191,"y":3,"w":188,"h":48}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":1,"y":0,"w":188,"h":48}, - "sourceSize": {"w":192,"h":48} -}, -"sprites/blueprints/painter.png": -{ - "frame": {"x":291,"y":159,"w":96,"h":48}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":96,"h":48}, - "sourceSize": {"w":96,"h":48} -}, -"sprites/blueprints/rotater-ccw.png": -{ - "frame": {"x":92,"y":535,"w":48,"h":48}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":48,"h":48}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/blueprints/rotater-fl.png": -{ - "frame": {"x":92,"y":587,"w":48,"h":48}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":48,"h":48}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/blueprints/rotater.png": -{ - "frame": {"x":92,"y":639,"w":48,"h":48}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":48,"h":48}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/blueprints/splitter-compact-inverse.png": -{ - "frame": {"x":96,"y":733,"w":48,"h":48}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":48,"h":48}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/blueprints/splitter-compact.png": -{ - "frame": {"x":299,"y":471,"w":47,"h":47}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":1,"y":0,"w":47,"h":47}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/blueprints/splitter.png": -{ - "frame": {"x":287,"y":315,"w":87,"h":48}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":5,"y":0,"w":87,"h":48}, - "sourceSize": {"w":96,"h":48} -}, -"sprites/blueprints/stacker.png": -{ - "frame": {"x":196,"y":263,"w":89,"h":48}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":3,"y":0,"w":89,"h":48}, - "sourceSize": {"w":96,"h":48} -}, -"sprites/blueprints/trash-storage.png": -{ - "frame": {"x":3,"y":535,"w":85,"h":96}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":0,"w":85,"h":96}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/blueprints/trash.png": -{ - "frame": {"x":96,"y":785,"w":48,"h":48}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":48,"h":48}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/blueprints/underground_belt_entry-tier2.png": -{ - "frame": {"x":196,"y":419,"w":48,"h":43}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":5,"w":48,"h":43}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/blueprints/underground_belt_entry.png": -{ - "frame": {"x":92,"y":691,"w":48,"h":38}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":10,"w":48,"h":38}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/blueprints/underground_belt_exit-tier2.png": -{ - "frame": {"x":144,"y":443,"w":48,"h":38}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":0,"w":48,"h":38}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/blueprints/underground_belt_exit.png": -{ - "frame": {"x":196,"y":466,"w":48,"h":38}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":0,"w":48,"h":38}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/blueprints/wire_crossings-merger.png": -{ - "frame": {"x":352,"y":367,"w":34,"h":48}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":14,"y":0,"w":34,"h":48}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/blueprints/wire_crossings.png": -{ - "frame": {"x":378,"y":315,"w":34,"h":48}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":14,"y":0,"w":34,"h":48}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/blueprints/wire_left.png": -{ - "frame": {"x":466,"y":373,"w":21,"h":21}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":11,"w":21,"h":21}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/blueprints/wire_right.png": -{ - "frame": {"x":466,"y":398,"w":21,"h":21}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":11,"y":11,"w":21,"h":21}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/blueprints/wire_top.png": -{ - "frame": {"x":472,"y":259,"w":10,"h":32}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":11,"y":0,"w":10,"h":32}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/buildings/advanced_processor.png": -{ - "frame": {"x":3,"y":440,"w":94,"h":91}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":2,"w":94,"h":91}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/buildings/belt_left.png": -{ - "frame": {"x":102,"y":374,"w":30,"h":30}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":2,"w":30,"h":30}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/buildings/belt_right.png": -{ - "frame": {"x":102,"y":408,"w":30,"h":30}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":2,"w":30,"h":30}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/buildings/belt_top.png": -{ - "frame": {"x":452,"y":459,"w":28,"h":32}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":0,"w":28,"h":32}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/buildings/cutter-quad.png": -{ - "frame": {"x":191,"y":107,"w":184,"h":48}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":5,"y":0,"w":184,"h":48}, - "sourceSize": {"w":192,"h":48} -}, -"sprites/buildings/cutter.png": -{ - "frame": {"x":391,"y":207,"w":87,"h":48}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":5,"y":0,"w":87,"h":48}, - "sourceSize": {"w":96,"h":48} -}, -"sprites/buildings/energy_generator.png": -{ - "frame": {"x":103,"y":244,"w":89,"h":92}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":4,"y":4,"w":89,"h":92}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/buildings/hub.png": -{ - "frame": {"x":3,"y":3,"w":184,"h":185}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":4,"y":4,"w":184,"h":185}, - "sourceSize": {"w":192,"h":192} -}, -"sprites/buildings/miner-chainable.png": -{ - "frame": {"x":350,"y":419,"w":47,"h":48}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":1,"y":0,"w":47,"h":48}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/buildings/miner.png": -{ - "frame": {"x":248,"y":471,"w":47,"h":48}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":1,"y":0,"w":47,"h":48}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/buildings/mixer.png": -{ - "frame": {"x":289,"y":211,"w":88,"h":48}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":4,"y":0,"w":88,"h":48}, - "sourceSize": {"w":96,"h":48} -}, -"sprites/buildings/painter-double.png": -{ - "frame": {"x":3,"y":244,"w":96,"h":96}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":96,"h":96}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/buildings/painter-mirrored.png": -{ - "frame": {"x":391,"y":103,"w":96,"h":48}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":96,"h":48}, - "sourceSize": {"w":96,"h":48} -}, -"sprites/buildings/painter-quad.png": -{ - "frame": {"x":191,"y":55,"w":188,"h":48}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":1,"y":0,"w":188,"h":48}, - "sourceSize": {"w":192,"h":48} -}, -"sprites/buildings/painter.png": -{ - "frame": {"x":391,"y":155,"w":96,"h":48}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":96,"h":48}, - "sourceSize": {"w":96,"h":48} -}, -"sprites/buildings/rotater-ccw.png": -{ - "frame": {"x":144,"y":340,"w":48,"h":48}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":48,"h":48}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/buildings/rotater-fl.png": -{ - "frame": {"x":196,"y":367,"w":48,"h":48}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":48,"h":48}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/buildings/rotater.png": -{ - "frame": {"x":248,"y":367,"w":48,"h":48}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":48,"h":48}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/buildings/splitter-compact-inverse.png": -{ - "frame": {"x":144,"y":392,"w":48,"h":47}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":0,"w":48,"h":47}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/buildings/splitter-compact.png": -{ - "frame": {"x":350,"y":471,"w":47,"h":47}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":1,"y":0,"w":47,"h":47}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/buildings/splitter.png": -{ - "frame": {"x":381,"y":259,"w":87,"h":48}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":5,"y":0,"w":87,"h":48}, - "sourceSize": {"w":96,"h":48} -}, -"sprites/buildings/stacker.png": -{ - "frame": {"x":289,"y":263,"w":88,"h":48}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":4,"y":0,"w":88,"h":48}, - "sourceSize": {"w":96,"h":48} -}, -"sprites/buildings/trash-storage.png": -{ - "frame": {"x":3,"y":635,"w":85,"h":96}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":0,"w":85,"h":96}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/buildings/trash.png": -{ - "frame": {"x":300,"y":367,"w":48,"h":48}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":48,"h":48}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/buildings/underground_belt_entry-tier2.png": -{ - "frame": {"x":416,"y":311,"w":47,"h":42}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":1,"y":6,"w":47,"h":42}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/buildings/underground_belt_entry.png": -{ - "frame": {"x":401,"y":419,"w":47,"h":38}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":1,"y":10,"w":47,"h":38}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/buildings/underground_belt_exit-tier2.png": -{ - "frame": {"x":401,"y":461,"w":47,"h":38}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":1,"y":0,"w":47,"h":38}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/buildings/underground_belt_exit.png": -{ - "frame": {"x":401,"y":503,"w":47,"h":38}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":1,"y":0,"w":47,"h":38}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/buildings/wire_crossings-merger.png": -{ - "frame": {"x":390,"y":367,"w":34,"h":48}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":14,"y":0,"w":34,"h":48}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/buildings/wire_crossings.png": -{ - "frame": {"x":428,"y":357,"w":34,"h":48}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":14,"y":0,"w":34,"h":48}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/buildings/wire_left.png": -{ - "frame": {"x":318,"y":543,"w":21,"h":21}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":11,"w":21,"h":21}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/buildings/wire_right.png": -{ - "frame": {"x":238,"y":812,"w":21,"h":21}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":11,"y":11,"w":21,"h":21}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/buildings/wire_top.png": -{ - "frame": {"x":101,"y":472,"w":10,"h":32}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":11,"y":0,"w":10,"h":32}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/debug/acceptor_slot.png": -{ - "frame": {"x":430,"y":817,"w":14,"h":16}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":1,"y":0,"w":14,"h":16}, - "sourceSize": {"w":16,"h":16} -}, -"sprites/debug/ejector_slot.png": -{ - "frame": {"x":123,"y":442,"w":14,"h":16}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":1,"y":0,"w":14,"h":16}, - "sourceSize": {"w":16,"h":16} -}, -"sprites/map_overview/belt_forward.png": -{ - "frame": {"x":184,"y":485,"w":8,"h":8}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":8,"h":8}, - "sourceSize": {"w":8,"h":8} -}, -"sprites/map_overview/belt_left.png": -{ - "frame": {"x":200,"y":820,"w":8,"h":8}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":8,"h":8}, - "sourceSize": {"w":8,"h":8} -}, -"sprites/map_overview/belt_right.png": -{ - "frame": {"x":379,"y":107,"w":8,"h":8}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":8,"h":8}, - "sourceSize": {"w":8,"h":8} -}, -"sprites/misc/deletion_marker.png": -{ - "frame": {"x":212,"y":812,"w":22,"h":22}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":1,"y":1,"w":22,"h":22}, - "sourceSize": {"w":24,"h":24} -}, -"sprites/misc/energy_generator_overlay.png": -{ - "frame": {"x":299,"y":522,"w":40,"h":17}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":45,"y":71,"w":40,"h":17}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/misc/hub_direction_indicator.png": -{ - "frame": {"x":379,"y":119,"w":8,"h":8}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":8,"h":8}, - "sourceSize": {"w":8,"h":8} -}, -"sprites/misc/lock_direction_indicator.png": -{ - "frame": {"x":115,"y":494,"w":12,"h":10}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":1,"w":12,"h":10}, - "sourceSize": {"w":12,"h":12} -}, -"sprites/misc/slot_bad_arrow.png": -{ - "frame": {"x":212,"y":812,"w":22,"h":22}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":1,"y":1,"w":22,"h":22}, - "sourceSize": {"w":24,"h":24} -}, -"sprites/misc/slot_good_arrow.png": -{ - "frame": {"x":218,"y":508,"w":22,"h":24}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":1,"y":0,"w":22,"h":24}, - "sourceSize": {"w":24,"h":24} -}, -"sprites/misc/storage_overlay.png": -{ - "frame": {"x":101,"y":508,"w":45,"h":23}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":45,"h":23}, - "sourceSize": {"w":45,"h":23} -}, -"sprites/misc/waypoint.png": -{ - "frame": {"x":379,"y":131,"w":8,"h":8}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":8,"h":8}, - "sourceSize": {"w":8,"h":8} -}, -"sprites/misc/wires_overlay_tile.png": -{ - "frame": {"x":452,"y":423,"w":32,"h":32}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":32,"h":32}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/wires/battery_empty.png": -{ - "frame": {"x":263,"y":815,"w":12,"h":16}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":0,"w":12,"h":16}, - "sourceSize": {"w":16,"h":16} -}, -"sprites/wires/battery_full.png": -{ - "frame": {"x":180,"y":820,"w":16,"h":12}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":2,"w":16,"h":12}, - "sourceSize": {"w":16,"h":16} -}, -"sprites/wires/battery_low.png": -{ - "frame": {"x":123,"y":462,"w":16,"h":12}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":2,"w":16,"h":12}, - "sourceSize": {"w":16,"h":16} -}, -"sprites/wires/battery_medium.png": -{ - "frame": {"x":115,"y":478,"w":16,"h":12}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":2,"w":16,"h":12}, - "sourceSize": {"w":16,"h":16} -}, -"sprites/wires/negative_energy.png": -{ - "frame": {"x":472,"y":295,"w":12,"h":12}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":2,"w":12,"h":12}, - "sourceSize": {"w":16,"h":16} -}, -"sprites/wires/pin_negative_accept.png": -{ - "frame": {"x":467,"y":311,"w":20,"h":27}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":0,"w":20,"h":27}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/wires/pin_negative_eject.png": -{ - "frame": {"x":377,"y":522,"w":18,"h":26}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":7,"y":0,"w":18,"h":26}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/wires/pin_positive_accept.png": -{ - "frame": {"x":101,"y":442,"w":18,"h":26}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":7,"y":0,"w":18,"h":26}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/wires/pin_positive_eject.png": -{ - "frame": {"x":467,"y":342,"w":20,"h":27}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":0,"w":20,"h":27}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/wires/positive_energy.png": -{ - "frame": {"x":279,"y":815,"w":12,"h":12}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":2,"w":12,"h":12}, - "sourceSize": {"w":16,"h":16} -}, -"sprites/wires/waste_piled.png": -{ - "frame": {"x":410,"y":817,"w":16,"h":16}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, - "sourceSize": {"w":16,"h":16} -}}, -"meta": { - "app": "https://www.codeandweb.com/texturepacker", - "version": "1.0", - "image": "atlas0_25.png", - "format": "RGBA8888", - "size": {"w":490,"h":837}, - "scale": "0.25", - "smartupdate": "$TexturePacker:SmartUpdate:dfc84e4381978113df4ad0cd8a5aace9:4e9bd6f6c82aaaa8a4a583cab68dc719:f159918d23e5952766c6d23ab52278c6$" -} -} diff --git a/res_built/atlas/atlas0_25.png b/res_built/atlas/atlas0_25.png deleted file mode 100644 index c58d7738..00000000 Binary files a/res_built/atlas/atlas0_25.png and /dev/null differ diff --git a/res_built/atlas/atlas0_50.json b/res_built/atlas/atlas0_50.json deleted file mode 100644 index 07a7a7fc..00000000 --- a/res_built/atlas/atlas0_50.json +++ /dev/null @@ -1,1404 +0,0 @@ -{"frames": { - -"sprites/belt/forward_0.png": -{ - "frame": {"x":949,"y":270,"w":51,"h":63}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":0,"w":51,"h":63}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/forward_1.png": -{ - "frame": {"x":849,"y":469,"w":51,"h":63}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":0,"w":51,"h":63}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/forward_2.png": -{ - "frame": {"x":958,"y":731,"w":51,"h":63}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":0,"w":51,"h":63}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/forward_3.png": -{ - "frame": {"x":850,"y":859,"w":51,"h":63}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":0,"w":51,"h":63}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/forward_4.png": -{ - "frame": {"x":905,"y":859,"w":51,"h":63}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":0,"w":51,"h":63}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/forward_5.png": -{ - "frame": {"x":853,"y":926,"w":51,"h":63}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":0,"w":51,"h":63}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/forward_6.png": -{ - "frame": {"x":908,"y":926,"w":51,"h":63}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":0,"w":51,"h":63}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/forward_7.png": -{ - "frame": {"x":893,"y":1054,"w":51,"h":63}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":0,"w":51,"h":63}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/forward_8.png": -{ - "frame": {"x":948,"y":1048,"w":51,"h":63}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":0,"w":51,"h":63}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/forward_9.png": -{ - "frame": {"x":850,"y":1126,"w":51,"h":63}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":0,"w":51,"h":63}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/forward_10.png": -{ - "frame": {"x":848,"y":703,"w":51,"h":63}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":0,"w":51,"h":63}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/forward_11.png": -{ - "frame": {"x":467,"y":1057,"w":51,"h":63}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":0,"w":51,"h":63}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/forward_12.png": -{ - "frame": {"x":908,"y":408,"w":51,"h":63}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":0,"w":51,"h":63}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/forward_13.png": -{ - "frame": {"x":910,"y":536,"w":51,"h":63}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":0,"w":51,"h":63}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/forward_14.png": -{ - "frame": {"x":965,"y":469,"w":51,"h":63}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":0,"w":51,"h":63}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/forward_15.png": -{ - "frame": {"x":965,"y":536,"w":51,"h":63}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":0,"w":51,"h":63}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/forward_16.png": -{ - "frame": {"x":848,"y":770,"w":51,"h":63}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":0,"w":51,"h":63}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/forward_17.png": -{ - "frame": {"x":903,"y":664,"w":51,"h":63}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":0,"w":51,"h":63}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/forward_18.png": -{ - "frame": {"x":903,"y":731,"w":51,"h":63}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":0,"w":51,"h":63}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/forward_19.png": -{ - "frame": {"x":958,"y":664,"w":51,"h":63}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":0,"w":51,"h":63}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/forward_20.png": -{ - "frame": {"x":964,"y":798,"w":51,"h":63}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":0,"w":51,"h":63}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/forward_21.png": -{ - "frame": {"x":740,"y":803,"w":51,"h":63}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":0,"w":51,"h":63}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/forward_22.png": -{ - "frame": {"x":740,"y":870,"w":51,"h":63}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":0,"w":51,"h":63}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/forward_23.png": -{ - "frame": {"x":795,"y":859,"w":51,"h":63}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":0,"w":51,"h":63}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/forward_24.png": -{ - "frame": {"x":728,"y":1059,"w":51,"h":63}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":0,"w":51,"h":63}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/forward_25.png": -{ - "frame": {"x":798,"y":926,"w":51,"h":63}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":0,"w":51,"h":63}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/forward_26.png": -{ - "frame": {"x":783,"y":1059,"w":51,"h":63}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":0,"w":51,"h":63}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/forward_27.png": -{ - "frame": {"x":838,"y":1059,"w":51,"h":63}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":0,"w":51,"h":63}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/left_0.png": -{ - "frame": {"x":827,"y":286,"w":57,"h":57}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":6,"w":57,"h":57}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/left_1.png": -{ - "frame": {"x":888,"y":286,"w":57,"h":57}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":6,"w":57,"h":57}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/left_2.png": -{ - "frame": {"x":903,"y":798,"w":57,"h":57}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":6,"w":57,"h":57}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/left_3.png": -{ - "frame": {"x":789,"y":1126,"w":57,"h":57}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":6,"w":57,"h":57}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/left_4.png": -{ - "frame": {"x":905,"y":1121,"w":57,"h":57}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":6,"w":57,"h":57}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/left_5.png": -{ - "frame": {"x":905,"y":1182,"w":57,"h":57}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":6,"w":57,"h":57}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/left_6.png": -{ - "frame": {"x":372,"y":1261,"w":57,"h":57}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":6,"w":57,"h":57}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/left_7.png": -{ - "frame": {"x":372,"y":1322,"w":57,"h":57}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":6,"w":57,"h":57}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/left_8.png": -{ - "frame": {"x":433,"y":1260,"w":57,"h":57}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":6,"w":57,"h":57}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/left_9.png": -{ - "frame": {"x":433,"y":1321,"w":57,"h":57}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":6,"w":57,"h":57}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/left_10.png": -{ - "frame": {"x":873,"y":347,"w":57,"h":57}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":6,"w":57,"h":57}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/left_11.png": -{ - "frame": {"x":847,"y":408,"w":57,"h":57}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":6,"w":57,"h":57}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/left_12.png": -{ - "frame": {"x":849,"y":536,"w":57,"h":57}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":6,"w":57,"h":57}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/left_13.png": -{ - "frame": {"x":831,"y":597,"w":57,"h":57}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":6,"w":57,"h":57}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/left_14.png": -{ - "frame": {"x":522,"y":1077,"w":57,"h":57}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":6,"w":57,"h":57}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/left_15.png": -{ - "frame": {"x":904,"y":475,"w":57,"h":57}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":6,"w":57,"h":57}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/left_16.png": -{ - "frame": {"x":934,"y":347,"w":57,"h":57}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":6,"w":57,"h":57}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/left_17.png": -{ - "frame": {"x":963,"y":408,"w":57,"h":57}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":6,"w":57,"h":57}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/left_18.png": -{ - "frame": {"x":892,"y":603,"w":57,"h":57}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":6,"w":57,"h":57}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/left_19.png": -{ - "frame": {"x":953,"y":603,"w":57,"h":57}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":6,"w":57,"h":57}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/left_20.png": -{ - "frame": {"x":737,"y":937,"w":57,"h":57}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":6,"w":57,"h":57}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/left_21.png": -{ - "frame": {"x":731,"y":998,"w":57,"h":57}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":6,"w":57,"h":57}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/left_22.png": -{ - "frame": {"x":792,"y":998,"w":57,"h":57}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":6,"w":57,"h":57}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/left_23.png": -{ - "frame": {"x":960,"y":865,"w":57,"h":57}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":6,"w":57,"h":57}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/left_24.png": -{ - "frame": {"x":963,"y":926,"w":57,"h":57}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":6,"w":57,"h":57}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/left_25.png": -{ - "frame": {"x":963,"y":987,"w":57,"h":57}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":6,"w":57,"h":57}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/left_26.png": -{ - "frame": {"x":853,"y":993,"w":57,"h":57}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":6,"w":57,"h":57}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/left_27.png": -{ - "frame": {"x":728,"y":1126,"w":57,"h":57}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":6,"w":57,"h":57}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/right_0.png": -{ - "frame": {"x":469,"y":1187,"w":57,"h":57}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":6,"w":57,"h":57}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/right_1.png": -{ - "frame": {"x":494,"y":1248,"w":57,"h":57}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":6,"w":57,"h":57}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/right_2.png": -{ - "frame": {"x":774,"y":1187,"w":57,"h":57}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":6,"w":57,"h":57}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/right_3.png": -{ - "frame": {"x":921,"y":1243,"w":57,"h":57}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":6,"w":57,"h":57}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/right_4.png": -{ - "frame": {"x":921,"y":1304,"w":57,"h":57}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":6,"w":57,"h":57}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/right_5.png": -{ - "frame": {"x":494,"y":1370,"w":57,"h":57}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":6,"w":57,"h":57}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/right_6.png": -{ - "frame": {"x":555,"y":1370,"w":57,"h":57}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":6,"w":57,"h":57}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/right_7.png": -{ - "frame": {"x":616,"y":1370,"w":57,"h":57}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":6,"w":57,"h":57}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/right_8.png": -{ - "frame": {"x":677,"y":1370,"w":57,"h":57}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":6,"w":57,"h":57}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/right_9.png": -{ - "frame": {"x":738,"y":1370,"w":57,"h":57}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":6,"w":57,"h":57}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/right_10.png": -{ - "frame": {"x":494,"y":1309,"w":57,"h":57}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":6,"w":57,"h":57}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/right_11.png": -{ - "frame": {"x":530,"y":1187,"w":57,"h":57}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":6,"w":57,"h":57}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/right_12.png": -{ - "frame": {"x":555,"y":1248,"w":57,"h":57}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":6,"w":57,"h":57}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/right_13.png": -{ - "frame": {"x":555,"y":1309,"w":57,"h":57}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":6,"w":57,"h":57}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/right_14.png": -{ - "frame": {"x":591,"y":1187,"w":57,"h":57}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":6,"w":57,"h":57}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/right_15.png": -{ - "frame": {"x":616,"y":1248,"w":57,"h":57}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":6,"w":57,"h":57}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/right_16.png": -{ - "frame": {"x":616,"y":1309,"w":57,"h":57}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":6,"w":57,"h":57}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/right_17.png": -{ - "frame": {"x":652,"y":1187,"w":57,"h":57}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":6,"w":57,"h":57}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/right_18.png": -{ - "frame": {"x":713,"y":1187,"w":57,"h":57}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":6,"w":57,"h":57}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/right_19.png": -{ - "frame": {"x":677,"y":1248,"w":57,"h":57}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":6,"w":57,"h":57}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/right_20.png": -{ - "frame": {"x":677,"y":1309,"w":57,"h":57}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":6,"w":57,"h":57}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/right_21.png": -{ - "frame": {"x":738,"y":1248,"w":57,"h":57}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":6,"w":57,"h":57}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/right_22.png": -{ - "frame": {"x":738,"y":1309,"w":57,"h":57}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":6,"w":57,"h":57}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/right_23.png": -{ - "frame": {"x":835,"y":1193,"w":57,"h":57}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":6,"w":57,"h":57}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/right_24.png": -{ - "frame": {"x":799,"y":1254,"w":57,"h":57}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":6,"w":57,"h":57}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/right_25.png": -{ - "frame": {"x":799,"y":1315,"w":57,"h":57}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":6,"w":57,"h":57}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/right_26.png": -{ - "frame": {"x":860,"y":1254,"w":57,"h":57}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":6,"w":57,"h":57}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/belt/right_27.png": -{ - "frame": {"x":860,"y":1315,"w":57,"h":57}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":6,"w":57,"h":57}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/blueprints/advanced_processor.png": -{ - "frame": {"x":3,"y":669,"w":188,"h":181}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":4,"y":5,"w":188,"h":181}, - "sourceSize": {"w":192,"h":192} -}, -"sprites/blueprints/belt_left.png": -{ - "frame": {"x":765,"y":278,"w":58,"h":58}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":5,"w":58,"h":58}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/blueprints/belt_right.png": -{ - "frame": {"x":765,"y":340,"w":58,"h":58}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":5,"y":5,"w":58,"h":58}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/blueprints/belt_top.png": -{ - "frame": {"x":944,"y":203,"w":53,"h":63}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":5,"y":0,"w":53,"h":63}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/blueprints/cutter-quad.png": -{ - "frame": {"x":3,"y":374,"w":366,"h":96}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":11,"y":0,"w":366,"h":96}, - "sourceSize": {"w":384,"h":96} -}, -"sprites/blueprints/cutter.png": -{ - "frame": {"x":194,"y":861,"w":172,"h":96}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":11,"y":0,"w":172,"h":96}, - "sourceSize": {"w":192,"h":96} -}, -"sprites/blueprints/energy_generator.png": -{ - "frame": {"x":199,"y":474,"w":175,"h":183}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":9,"w":175,"h":183}, - "sourceSize": {"w":192,"h":192} -}, -"sprites/blueprints/miner-chainable.png": -{ - "frame": {"x":373,"y":1160,"w":92,"h":96}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":3,"y":0,"w":92,"h":96}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/blueprints/miner.png": -{ - "frame": {"x":735,"y":603,"w":92,"h":96}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":3,"y":0,"w":92,"h":96}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/blueprints/mixer.png": -{ - "frame": {"x":556,"y":603,"w":175,"h":96}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":8,"y":0,"w":175,"h":96}, - "sourceSize": {"w":192,"h":96} -}, -"sprites/blueprints/painter-double.png": -{ - "frame": {"x":751,"y":3,"w":192,"h":192}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":192,"h":192}, - "sourceSize": {"w":192,"h":192} -}, -"sprites/blueprints/painter-mirrored.png": -{ - "frame": {"x":373,"y":303,"w":192,"h":96}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":192,"h":96}, - "sourceSize": {"w":192,"h":96} -}, -"sprites/blueprints/painter-quad.png": -{ - "frame": {"x":373,"y":3,"w":374,"h":96}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":3,"y":0,"w":374,"h":96}, - "sourceSize": {"w":384,"h":96} -}, -"sprites/blueprints/painter.png": -{ - "frame": {"x":569,"y":303,"w":192,"h":96}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":192,"h":96}, - "sourceSize": {"w":192,"h":96} -}, -"sprites/blueprints/rotater-ccw.png": -{ - "frame": {"x":553,"y":703,"w":96,"h":96}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":96,"h":96}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/blueprints/rotater-fl.png": -{ - "frame": {"x":274,"y":1161,"w":95,"h":96}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":0,"w":95,"h":96}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/blueprints/rotater.png": -{ - "frame": {"x":653,"y":703,"w":96,"h":96}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":96,"h":96}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/blueprints/splitter-compact-inverse.png": -{ - "frame": {"x":641,"y":803,"w":95,"h":93}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":1,"w":95,"h":93}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/blueprints/splitter-compact.png": -{ - "frame": {"x":349,"y":1063,"w":93,"h":93}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":3,"y":1,"w":93,"h":93}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/blueprints/splitter.png": -{ - "frame": {"x":194,"y":961,"w":171,"h":96}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":11,"y":0,"w":171,"h":96}, - "sourceSize": {"w":192,"h":96} -}, -"sprites/blueprints/stacker.png": -{ - "frame": {"x":199,"y":661,"w":175,"h":96}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":8,"y":0,"w":175,"h":96}, - "sourceSize": {"w":192,"h":96} -}, -"sprites/blueprints/trash-storage.png": -{ - "frame": {"x":3,"y":1037,"w":167,"h":192}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":14,"y":0,"w":167,"h":192}, - "sourceSize": {"w":192,"h":192} -}, -"sprites/blueprints/trash.png": -{ - "frame": {"x":174,"y":1161,"w":96,"h":96}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":96,"h":96}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/blueprints/underground_belt_entry-tier2.png": -{ - "frame": {"x":752,"y":502,"w":93,"h":84}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":12,"w":93,"h":84}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/blueprints/underground_belt_entry.png": -{ - "frame": {"x":535,"y":998,"w":93,"h":75}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":21,"w":93,"h":75}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/blueprints/underground_belt_exit-tier2.png": -{ - "frame": {"x":369,"y":984,"w":94,"h":75}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":0,"w":94,"h":75}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/blueprints/underground_belt_exit.png": -{ - "frame": {"x":751,"y":199,"w":93,"h":75}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":0,"w":93,"h":75}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/blueprints/wire_crossings-merger.png": -{ - "frame": {"x":947,"y":3,"w":66,"h":96}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":30,"y":0,"w":66,"h":96}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/blueprints/wire_crossings.png": -{ - "frame": {"x":472,"y":789,"w":66,"h":96}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":30,"y":0,"w":66,"h":96}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/blueprints/wire_left.png": -{ - "frame": {"x":921,"y":1365,"w":40,"h":40}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":23,"w":40,"h":40}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/blueprints/wire_right.png": -{ - "frame": {"x":831,"y":658,"w":40,"h":41}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":23,"y":22,"w":40,"h":41}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/blueprints/wire_top.png": -{ - "frame": {"x":446,"y":1063,"w":17,"h":63}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":23,"y":0,"w":17,"h":63}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/buildings/advanced_processor.png": -{ - "frame": {"x":3,"y":854,"w":187,"h":179}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":5,"y":6,"w":187,"h":179}, - "sourceSize": {"w":192,"h":192} -}, -"sprites/buildings/belt_left.png": -{ - "frame": {"x":799,"y":1376,"w":57,"h":57}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":6,"w":57,"h":57}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/buildings/belt_right.png": -{ - "frame": {"x":860,"y":1376,"w":57,"h":57}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":6,"w":57,"h":57}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/buildings/belt_top.png": -{ - "frame": {"x":949,"y":270,"w":51,"h":63}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":0,"w":51,"h":63}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/buildings/cutter-quad.png": -{ - "frame": {"x":373,"y":203,"w":366,"h":96}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":11,"y":0,"w":366,"h":96}, - "sourceSize": {"w":384,"h":96} -}, -"sprites/buildings/cutter.png": -{ - "frame": {"x":174,"y":1061,"w":171,"h":96}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":11,"y":0,"w":171,"h":96}, - "sourceSize": {"w":192,"h":96} -}, -"sprites/buildings/energy_generator.png": -{ - "frame": {"x":378,"y":403,"w":174,"h":182}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":10,"y":10,"w":174,"h":182}, - "sourceSize": {"w":192,"h":192} -}, -"sprites/buildings/hub.png": -{ - "frame": {"x":3,"y":3,"w":366,"h":367}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":10,"w":366,"h":367}, - "sourceSize": {"w":384,"h":384} -}, -"sprites/buildings/miner-chainable.png": -{ - "frame": {"x":753,"y":703,"w":91,"h":95}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":3,"y":0,"w":91,"h":95}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/buildings/miner.png": -{ - "frame": {"x":752,"y":403,"w":91,"h":95}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":3,"y":0,"w":91,"h":95}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/buildings/mixer.png": -{ - "frame": {"x":378,"y":589,"w":174,"h":96}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":0,"w":174,"h":96}, - "sourceSize": {"w":192,"h":96} -}, -"sprites/buildings/painter-double.png": -{ - "frame": {"x":3,"y":474,"w":192,"h":191}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":0,"w":192,"h":191}, - "sourceSize": {"w":192,"h":192} -}, -"sprites/buildings/painter-mirrored.png": -{ - "frame": {"x":556,"y":403,"w":192,"h":96}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":192,"h":96}, - "sourceSize": {"w":192,"h":96} -}, -"sprites/buildings/painter-quad.png": -{ - "frame": {"x":373,"y":103,"w":374,"h":96}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":3,"y":0,"w":374,"h":96}, - "sourceSize": {"w":384,"h":96} -}, -"sprites/buildings/painter.png": -{ - "frame": {"x":556,"y":503,"w":192,"h":96}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":192,"h":96}, - "sourceSize": {"w":192,"h":96} -}, -"sprites/buildings/rotater-ccw.png": -{ - "frame": {"x":273,"y":1261,"w":95,"h":96}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":1,"y":0,"w":95,"h":96}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/buildings/rotater-fl.png": -{ - "frame": {"x":373,"y":789,"w":95,"h":96}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":0,"w":95,"h":96}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/buildings/rotater.png": -{ - "frame": {"x":542,"y":803,"w":95,"h":96}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":1,"y":0,"w":95,"h":96}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/buildings/splitter-compact-inverse.png": -{ - "frame": {"x":370,"y":889,"w":94,"h":91}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":2,"w":94,"h":91}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/buildings/splitter-compact.png": -{ - "frame": {"x":538,"y":903,"w":93,"h":91}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":3,"y":2,"w":93,"h":91}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/buildings/splitter.png": -{ - "frame": {"x":378,"y":689,"w":171,"h":96}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":11,"y":0,"w":171,"h":96}, - "sourceSize": {"w":192,"h":96} -}, -"sprites/buildings/stacker.png": -{ - "frame": {"x":195,"y":761,"w":174,"h":96}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":0,"w":174,"h":96}, - "sourceSize": {"w":192,"h":96} -}, -"sprites/buildings/trash-storage.png": -{ - "frame": {"x":3,"y":1233,"w":166,"h":192}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":14,"y":0,"w":166,"h":192}, - "sourceSize": {"w":192,"h":192} -}, -"sprites/buildings/trash.png": -{ - "frame": {"x":173,"y":1261,"w":96,"h":96}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":96,"h":96}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/buildings/underground_belt_entry-tier2.png": -{ - "frame": {"x":848,"y":199,"w":92,"h":83}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":3,"y":13,"w":92,"h":83}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/buildings/underground_belt_entry.png": -{ - "frame": {"x":641,"y":900,"w":92,"h":74}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":3,"y":22,"w":92,"h":74}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/buildings/underground_belt_exit-tier2.png": -{ - "frame": {"x":635,"y":978,"w":92,"h":74}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":3,"y":0,"w":92,"h":74}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/buildings/underground_belt_exit.png": -{ - "frame": {"x":632,"y":1056,"w":92,"h":74}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":3,"y":0,"w":92,"h":74}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/buildings/wire_crossings-merger.png": -{ - "frame": {"x":947,"y":103,"w":66,"h":96}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":30,"y":0,"w":66,"h":96}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/buildings/wire_crossings.png": -{ - "frame": {"x":468,"y":889,"w":66,"h":96}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":30,"y":0,"w":66,"h":96}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/buildings/wire_left.png": -{ - "frame": {"x":965,"y":1365,"w":40,"h":40}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":23,"w":40,"h":40}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/buildings/wire_right.png": -{ - "frame": {"x":372,"y":1383,"w":40,"h":40}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":23,"y":23,"w":40,"h":40}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/buildings/wire_top.png": -{ - "frame": {"x":1001,"y":203,"w":17,"h":63}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":23,"y":0,"w":17,"h":63}, - "sourceSize": {"w":63,"h":63} -}, -"sprites/debug/acceptor_slot.png": -{ - "frame": {"x":416,"y":1383,"w":26,"h":32}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":3,"y":0,"w":26,"h":32}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/debug/ejector_slot.png": -{ - "frame": {"x":266,"y":1395,"w":26,"h":32}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":3,"y":0,"w":26,"h":32}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/map_overview/belt_forward.png": -{ - "frame": {"x":446,"y":1130,"w":14,"h":16}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":1,"y":0,"w":14,"h":16}, - "sourceSize": {"w":16,"h":16} -}, -"sprites/map_overview/belt_left.png": -{ - "frame": {"x":875,"y":684,"w":15,"h":15}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":1,"w":15,"h":15}, - "sourceSize": {"w":16,"h":16} -}, -"sprites/map_overview/belt_right.png": -{ - "frame": {"x":416,"y":1419,"w":15,"h":15}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":1,"y":1,"w":15,"h":15}, - "sourceSize": {"w":16,"h":16} -}, -"sprites/misc/deletion_marker.png": -{ - "frame": {"x":914,"y":993,"w":42,"h":42}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":3,"y":3,"w":42,"h":42}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/misc/energy_generator_overlay.png": -{ - "frame": {"x":266,"y":1361,"w":78,"h":30}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":91,"y":144,"w":78,"h":30}, - "sourceSize": {"w":192,"h":192} -}, -"sprites/misc/hub_direction_indicator.png": -{ - "frame": {"x":174,"y":1037,"w":16,"h":16}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, - "sourceSize": {"w":16,"h":16} -}, -"sprites/misc/lock_direction_indicator.png": -{ - "frame": {"x":875,"y":664,"w":24,"h":16}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":4,"w":24,"h":16}, - "sourceSize": {"w":24,"h":24} -}, -"sprites/misc/slot_bad_arrow.png": -{ - "frame": {"x":914,"y":993,"w":42,"h":42}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":3,"y":3,"w":42,"h":42}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/misc/slot_good_arrow.png": -{ - "frame": {"x":827,"y":347,"w":42,"h":48}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":3,"y":0,"w":42,"h":48}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/misc/storage_overlay.png": -{ - "frame": {"x":173,"y":1361,"w":89,"h":44}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":1,"y":1,"w":89,"h":44}, - "sourceSize": {"w":90,"h":45} -}, -"sprites/misc/waypoint.png": -{ - "frame": {"x":1004,"y":270,"w":14,"h":16}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":1,"y":0,"w":14,"h":16}, - "sourceSize": {"w":16,"h":16} -}, -"sprites/misc/wires_overlay_tile.png": -{ - "frame": {"x":467,"y":989,"w":64,"h":64}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":64,"h":64}, - "sourceSize": {"w":64,"h":64} -}, -"sprites/wires/battery_empty.png": -{ - "frame": {"x":348,"y":1361,"w":20,"h":32}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":6,"y":0,"w":20,"h":32}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/wires/battery_full.png": -{ - "frame": {"x":921,"y":1409,"w":30,"h":21}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":1,"y":6,"w":30,"h":21}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/wires/battery_low.png": -{ - "frame": {"x":955,"y":1409,"w":30,"h":21}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":1,"y":6,"w":30,"h":21}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/wires/battery_medium.png": -{ - "frame": {"x":173,"y":1409,"w":30,"h":21}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":1,"y":6,"w":30,"h":21}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/wires/negative_energy.png": -{ - "frame": {"x":207,"y":1409,"w":22,"h":22}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":5,"y":5,"w":22,"h":22}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/wires/pin_negative_accept.png": -{ - "frame": {"x":583,"y":1077,"w":38,"h":53}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":0,"w":38,"h":53}, - "sourceSize": {"w":64,"h":64} -}, -"sprites/wires/pin_negative_eject.png": -{ - "frame": {"x":966,"y":1115,"w":33,"h":51}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":15,"y":0,"w":33,"h":51}, - "sourceSize": {"w":64,"h":64} -}, -"sprites/wires/pin_positive_accept.png": -{ - "frame": {"x":966,"y":1170,"w":33,"h":51}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":15,"y":0,"w":33,"h":51}, - "sourceSize": {"w":64,"h":64} -}, -"sprites/wires/pin_positive_eject.png": -{ - "frame": {"x":795,"y":802,"w":38,"h":53}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":0,"w":38,"h":53}, - "sourceSize": {"w":64,"h":64} -}, -"sprites/wires/positive_energy.png": -{ - "frame": {"x":233,"y":1409,"w":22,"h":22}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":5,"y":5,"w":22,"h":22}, - "sourceSize": {"w":32,"h":32} -}, -"sprites/wires/waste_piled.png": -{ - "frame": {"x":446,"y":1382,"w":30,"h":29}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":1,"y":1,"w":30,"h":29}, - "sourceSize": {"w":32,"h":32} -}}, -"meta": { - "app": "https://www.codeandweb.com/texturepacker", - "version": "1.0", - "image": "atlas0_50.png", - "format": "RGBA8888", - "size": {"w":1023,"h":1437}, - "scale": "0.5", - "smartupdate": "$TexturePacker:SmartUpdate:dfc84e4381978113df4ad0cd8a5aace9:4e9bd6f6c82aaaa8a4a583cab68dc719:f159918d23e5952766c6d23ab52278c6$" -} -} diff --git a/res_built/atlas/atlas0_50.png b/res_built/atlas/atlas0_50.png deleted file mode 100644 index 020e7ecf..00000000 Binary files a/res_built/atlas/atlas0_50.png and /dev/null differ diff --git a/res_built/atlas/atlas0_75.json b/res_built/atlas/atlas0_75.json deleted file mode 100644 index e03e4e6b..00000000 --- a/res_built/atlas/atlas0_75.json +++ /dev/null @@ -1,1404 +0,0 @@ -{"frames": { - -"sprites/belt/forward_0.png": -{ - "frame": {"x":1103,"y":739,"w":77,"h":95}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":0,"w":77,"h":95}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/forward_1.png": -{ - "frame": {"x":1184,"y":737,"w":77,"h":95}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":0,"w":77,"h":95}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/forward_2.png": -{ - "frame": {"x":1468,"y":1511,"w":77,"h":95}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":0,"w":77,"h":95}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/forward_3.png": -{ - "frame": {"x":1661,"y":1220,"w":77,"h":95}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":0,"w":77,"h":95}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/forward_4.png": -{ - "frame": {"x":1580,"y":1301,"w":77,"h":95}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":0,"w":77,"h":95}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/forward_5.png": -{ - "frame": {"x":1661,"y":1319,"w":77,"h":95}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":0,"w":77,"h":95}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/forward_6.png": -{ - "frame": {"x":1549,"y":1400,"w":77,"h":95}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":0,"w":77,"h":95}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/forward_7.png": -{ - "frame": {"x":1549,"y":1499,"w":77,"h":95}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":0,"w":77,"h":95}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/forward_8.png": -{ - "frame": {"x":1558,"y":1598,"w":77,"h":95}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":0,"w":77,"h":95}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/forward_9.png": -{ - "frame": {"x":1630,"y":1418,"w":77,"h":95}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":0,"w":77,"h":95}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/forward_10.png": -{ - "frame": {"x":1355,"y":683,"w":77,"h":95}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":0,"w":77,"h":95}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/forward_11.png": -{ - "frame": {"x":1445,"y":759,"w":77,"h":95}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":0,"w":77,"h":95}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/forward_12.png": -{ - "frame": {"x":1445,"y":858,"w":77,"h":95}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":0,"w":77,"h":95}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/forward_13.png": -{ - "frame": {"x":1184,"y":836,"w":77,"h":95}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":0,"w":77,"h":95}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/forward_14.png": -{ - "frame": {"x":1177,"y":935,"w":77,"h":95}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":0,"w":77,"h":95}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/forward_15.png": -{ - "frame": {"x":1238,"y":1180,"w":77,"h":95}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":0,"w":77,"h":95}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/forward_16.png": -{ - "frame": {"x":1238,"y":1279,"w":77,"h":95}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":0,"w":77,"h":95}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/forward_17.png": -{ - "frame": {"x":843,"y":1478,"w":77,"h":95}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":0,"w":77,"h":95}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/forward_18.png": -{ - "frame": {"x":847,"y":1330,"w":77,"h":95}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":0,"w":77,"h":95}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/forward_19.png": -{ - "frame": {"x":1468,"y":1412,"w":77,"h":95}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":0,"w":77,"h":95}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/forward_20.png": -{ - "frame": {"x":1588,"y":1004,"w":77,"h":95}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":0,"w":77,"h":95}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/forward_21.png": -{ - "frame": {"x":1669,"y":1022,"w":77,"h":95}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":0,"w":77,"h":95}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/forward_22.png": -{ - "frame": {"x":1499,"y":1074,"w":77,"h":95}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":0,"w":77,"h":95}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/forward_23.png": -{ - "frame": {"x":1499,"y":1173,"w":77,"h":95}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":0,"w":77,"h":95}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/forward_24.png": -{ - "frame": {"x":1499,"y":1272,"w":77,"h":95}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":0,"w":77,"h":95}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/forward_25.png": -{ - "frame": {"x":1580,"y":1103,"w":77,"h":95}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":0,"w":77,"h":95}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/forward_26.png": -{ - "frame": {"x":1580,"y":1202,"w":77,"h":95}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":0,"w":77,"h":95}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/forward_27.png": -{ - "frame": {"x":1661,"y":1121,"w":77,"h":95}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":0,"w":77,"h":95}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/left_0.png": -{ - "frame": {"x":1672,"y":554,"w":86,"h":86}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":9,"w":86,"h":86}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/left_1.png": -{ - "frame": {"x":1535,"y":624,"w":86,"h":86}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":9,"w":86,"h":86}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/left_2.png": -{ - "frame": {"x":1706,"y":842,"w":86,"h":86}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":9,"w":86,"h":86}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/left_3.png": -{ - "frame": {"x":1304,"y":1052,"w":86,"h":86}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":9,"w":86,"h":86}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/left_4.png": -{ - "frame": {"x":1394,"y":1052,"w":86,"h":86}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":9,"w":86,"h":86}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/left_5.png": -{ - "frame": {"x":1319,"y":1142,"w":86,"h":86}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":9,"w":86,"h":86}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/left_6.png": -{ - "frame": {"x":1409,"y":1142,"w":86,"h":86}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":9,"w":86,"h":86}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/left_7.png": -{ - "frame": {"x":1319,"y":1232,"w":86,"h":86}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":9,"w":86,"h":86}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/left_8.png": -{ - "frame": {"x":1409,"y":1232,"w":86,"h":86}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":9,"w":86,"h":86}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/left_9.png": -{ - "frame": {"x":1319,"y":1322,"w":86,"h":86}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":9,"w":86,"h":86}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/left_10.png": -{ - "frame": {"x":1625,"y":644,"w":86,"h":86}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":9,"w":86,"h":86}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/left_11.png": -{ - "frame": {"x":1265,"y":683,"w":86,"h":86}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":9,"w":86,"h":86}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/left_12.png": -{ - "frame": {"x":1265,"y":773,"w":86,"h":86}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":9,"w":86,"h":86}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/left_13.png": -{ - "frame": {"x":1436,"y":669,"w":86,"h":86}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":9,"w":86,"h":86}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/left_14.png": -{ - "frame": {"x":1355,"y":782,"w":86,"h":86}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":9,"w":86,"h":86}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/left_15.png": -{ - "frame": {"x":1526,"y":714,"w":86,"h":86}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":9,"w":86,"h":86}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/left_16.png": -{ - "frame": {"x":1616,"y":734,"w":86,"h":86}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":9,"w":86,"h":86}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/left_17.png": -{ - "frame": {"x":1526,"y":804,"w":86,"h":86}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":9,"w":86,"h":86}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/left_18.png": -{ - "frame": {"x":1616,"y":824,"w":86,"h":86}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":9,"w":86,"h":86}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/left_19.png": -{ - "frame": {"x":1706,"y":752,"w":86,"h":86}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":9,"w":86,"h":86}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/left_20.png": -{ - "frame": {"x":1526,"y":894,"w":86,"h":86}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":9,"w":86,"h":86}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/left_21.png": -{ - "frame": {"x":1616,"y":914,"w":86,"h":86}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":9,"w":86,"h":86}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/left_22.png": -{ - "frame": {"x":1706,"y":932,"w":86,"h":86}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":9,"w":86,"h":86}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/left_23.png": -{ - "frame": {"x":1265,"y":863,"w":86,"h":86}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":9,"w":86,"h":86}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/left_24.png": -{ - "frame": {"x":1355,"y":872,"w":86,"h":86}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":9,"w":86,"h":86}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/left_25.png": -{ - "frame": {"x":1258,"y":953,"w":86,"h":86}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":9,"w":86,"h":86}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/left_26.png": -{ - "frame": {"x":1348,"y":962,"w":86,"h":86}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":9,"w":86,"h":86}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/left_27.png": -{ - "frame": {"x":1214,"y":1043,"w":86,"h":86}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":9,"w":86,"h":86}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/right_0.png": -{ - "frame": {"x":1409,"y":1322,"w":86,"h":86}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":9,"w":86,"h":86}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/right_1.png": -{ - "frame": {"x":928,"y":1328,"w":86,"h":86}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":9,"w":86,"h":86}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/right_2.png": -{ - "frame": {"x":1015,"y":1688,"w":86,"h":86}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":9,"w":86,"h":86}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/right_3.png": -{ - "frame": {"x":1105,"y":1687,"w":86,"h":86}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":9,"w":86,"h":86}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/right_4.png": -{ - "frame": {"x":1198,"y":1558,"w":86,"h":86}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":9,"w":86,"h":86}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/right_5.png": -{ - "frame": {"x":1195,"y":1648,"w":86,"h":86}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":9,"w":86,"h":86}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/right_6.png": -{ - "frame": {"x":1288,"y":1592,"w":86,"h":86}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":9,"w":86,"h":86}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/right_7.png": -{ - "frame": {"x":1378,"y":1592,"w":86,"h":86}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":9,"w":86,"h":86}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/right_8.png": -{ - "frame": {"x":1285,"y":1682,"w":86,"h":86}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":9,"w":86,"h":86}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/right_9.png": -{ - "frame": {"x":1375,"y":1682,"w":86,"h":86}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":9,"w":86,"h":86}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/right_10.png": -{ - "frame": {"x":1018,"y":1328,"w":86,"h":86}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":9,"w":86,"h":86}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/right_11.png": -{ - "frame": {"x":1108,"y":1327,"w":86,"h":86}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":9,"w":86,"h":86}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/right_12.png": -{ - "frame": {"x":928,"y":1418,"w":86,"h":86}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":9,"w":86,"h":86}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/right_13.png": -{ - "frame": {"x":1018,"y":1418,"w":86,"h":86}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":9,"w":86,"h":86}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/right_14.png": -{ - "frame": {"x":1108,"y":1417,"w":86,"h":86}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":9,"w":86,"h":86}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/right_15.png": -{ - "frame": {"x":924,"y":1508,"w":86,"h":86}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":9,"w":86,"h":86}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/right_16.png": -{ - "frame": {"x":1014,"y":1508,"w":86,"h":86}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":9,"w":86,"h":86}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/right_17.png": -{ - "frame": {"x":925,"y":1598,"w":86,"h":86}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":9,"w":86,"h":86}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/right_18.png": -{ - "frame": {"x":1015,"y":1598,"w":86,"h":86}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":9,"w":86,"h":86}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/right_19.png": -{ - "frame": {"x":925,"y":1688,"w":86,"h":86}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":9,"w":86,"h":86}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/right_20.png": -{ - "frame": {"x":1198,"y":1378,"w":86,"h":86}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":9,"w":86,"h":86}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/right_21.png": -{ - "frame": {"x":1198,"y":1468,"w":86,"h":86}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":9,"w":86,"h":86}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/right_22.png": -{ - "frame": {"x":1288,"y":1412,"w":86,"h":86}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":9,"w":86,"h":86}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/right_23.png": -{ - "frame": {"x":1378,"y":1412,"w":86,"h":86}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":9,"w":86,"h":86}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/right_24.png": -{ - "frame": {"x":1288,"y":1502,"w":86,"h":86}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":9,"w":86,"h":86}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/right_25.png": -{ - "frame": {"x":1378,"y":1502,"w":86,"h":86}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":9,"w":86,"h":86}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/right_26.png": -{ - "frame": {"x":1108,"y":1507,"w":86,"h":86}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":9,"w":86,"h":86}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/belt/right_27.png": -{ - "frame": {"x":1105,"y":1597,"w":86,"h":86}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":9,"w":86,"h":86}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/blueprints/advanced_processor.png": -{ - "frame": {"x":3,"y":994,"w":281,"h":270}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":7,"y":8,"w":281,"h":270}, - "sourceSize": {"w":288,"h":288} -}, -"sprites/blueprints/belt_left.png": -{ - "frame": {"x":3,"y":1688,"w":87,"h":87}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":8,"w":87,"h":87}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/blueprints/belt_right.png": -{ - "frame": {"x":94,"y":1688,"w":87,"h":87}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":8,"y":8,"w":87,"h":87}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/blueprints/belt_top.png": -{ - "frame": {"x":1715,"y":653,"w":79,"h":95}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":8,"y":0,"w":79,"h":95}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/blueprints/cutter-quad.png": -{ - "frame": {"x":3,"y":556,"w":548,"h":144}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":17,"y":0,"w":548,"h":144}, - "sourceSize": {"w":576,"h":144} -}, -"sprites/blueprints/cutter.png": -{ - "frame": {"x":554,"y":886,"w":256,"h":144}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":17,"y":0,"w":256,"h":144}, - "sourceSize": {"w":288,"h":144} -}, -"sprites/blueprints/energy_generator.png": -{ - "frame": {"x":288,"y":996,"w":262,"h":274}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":14,"y":14,"w":262,"h":274}, - "sourceSize": {"w":288,"h":288} -}, -"sprites/blueprints/miner-chainable.png": -{ - "frame": {"x":1671,"y":3,"w":136,"h":143}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":5,"y":0,"w":136,"h":143}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/blueprints/miner.png": -{ - "frame": {"x":1098,"y":1180,"w":136,"h":143}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":5,"y":0,"w":136,"h":143}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/blueprints/mixer.png": -{ - "frame": {"x":3,"y":1540,"w":261,"h":144}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":0,"w":261,"h":144}, - "sourceSize": {"w":288,"h":144} -}, -"sprites/blueprints/painter-double.png": -{ - "frame": {"x":555,"y":299,"w":288,"h":287}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":0,"w":288,"h":287}, - "sourceSize": {"w":288,"h":288} -}, -"sprites/blueprints/painter-mirrored.png": -{ - "frame": {"x":1119,"y":150,"w":288,"h":144}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":288,"h":144}, - "sourceSize": {"w":288,"h":144} -}, -"sprites/blueprints/painter-quad.png": -{ - "frame": {"x":555,"y":3,"w":560,"h":144}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":5,"y":0,"w":560,"h":144}, - "sourceSize": {"w":576,"h":144} -}, -"sprites/blueprints/painter.png": -{ - "frame": {"x":1411,"y":150,"w":288,"h":144}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":288,"h":144}, - "sourceSize": {"w":288,"h":144} -}, -"sprites/blueprints/rotater-ccw.png": -{ - "frame": {"x":702,"y":1182,"w":143,"h":144}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":1,"y":0,"w":143,"h":144}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/blueprints/rotater-fl.png": -{ - "frame": {"x":849,"y":1180,"w":142,"h":144}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":0,"w":142,"h":144}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/blueprints/rotater.png": -{ - "frame": {"x":700,"y":1330,"w":143,"h":144}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":1,"y":0,"w":143,"h":144}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/blueprints/splitter-compact-inverse.png": -{ - "frame": {"x":552,"y":1478,"w":142,"h":138}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":2,"w":142,"h":138}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/blueprints/splitter-compact.png": -{ - "frame": {"x":1241,"y":298,"w":139,"h":138}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":5,"y":2,"w":139,"h":138}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/blueprints/splitter.png": -{ - "frame": {"x":554,"y":1034,"w":256,"h":144}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":17,"y":0,"w":256,"h":144}, - "sourceSize": {"w":288,"h":144} -}, -"sprites/blueprints/stacker.png": -{ - "frame": {"x":847,"y":591,"w":261,"h":144}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":13,"y":0,"w":261,"h":144}, - "sourceSize": {"w":288,"h":144} -}, -"sprites/blueprints/trash-storage.png": -{ - "frame": {"x":847,"y":299,"w":250,"h":288}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":21,"y":0,"w":250,"h":288}, - "sourceSize": {"w":288,"h":288} -}, -"sprites/blueprints/trash.png": -{ - "frame": {"x":554,"y":1182,"w":144,"h":144}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":144,"h":144}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/blueprints/underground_belt_entry-tier2.png": -{ - "frame": {"x":1101,"y":445,"w":138,"h":125}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":4,"y":19,"w":138,"h":125}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/blueprints/underground_belt_entry.png": -{ - "frame": {"x":1527,"y":438,"w":138,"h":112}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":4,"y":32,"w":138,"h":112}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/blueprints/underground_belt_exit-tier2.png": -{ - "frame": {"x":1384,"y":438,"w":139,"h":112}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":4,"y":0,"w":139,"h":112}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/blueprints/underground_belt_exit.png": -{ - "frame": {"x":1669,"y":438,"w":138,"h":112}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":4,"y":0,"w":138,"h":112}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/blueprints/wire_crossings-merger.png": -{ - "frame": {"x":1703,"y":150,"w":99,"h":144}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":45,"y":0,"w":99,"h":144}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/blueprints/wire_crossings.png": -{ - "frame": {"x":995,"y":1180,"w":99,"h":144}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":45,"y":0,"w":99,"h":144}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/blueprints/wire_left.png": -{ - "frame": {"x":441,"y":1698,"w":60,"h":60}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":35,"w":60,"h":60}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/blueprints/wire_right.png": -{ - "frame": {"x":377,"y":1698,"w":60,"h":61}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":35,"y":34,"w":60,"h":61}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/blueprints/wire_top.png": -{ - "frame": {"x":1772,"y":298,"w":25,"h":95}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":35,"y":0,"w":25,"h":95}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/buildings/advanced_processor.png": -{ - "frame": {"x":3,"y":1268,"w":280,"h":268}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":8,"y":9,"w":280,"h":268}, - "sourceSize": {"w":288,"h":288} -}, -"sprites/buildings/belt_left.png": -{ - "frame": {"x":1468,"y":1610,"w":86,"h":86}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":9,"w":86,"h":86}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/buildings/belt_right.png": -{ - "frame": {"x":1498,"y":984,"w":86,"h":86}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":9,"w":86,"h":86}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/buildings/belt_top.png": -{ - "frame": {"x":1103,"y":739,"w":77,"h":95}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":0,"w":77,"h":95}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/buildings/cutter-quad.png": -{ - "frame": {"x":1119,"y":3,"w":548,"h":143}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":17,"y":0,"w":548,"h":143}, - "sourceSize": {"w":576,"h":144} -}, -"sprites/buildings/cutter.png": -{ - "frame": {"x":814,"y":886,"w":256,"h":143}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":17,"y":0,"w":256,"h":143}, - "sourceSize": {"w":288,"h":144} -}, -"sprites/buildings/energy_generator.png": -{ - "frame": {"x":287,"y":1274,"w":261,"h":273}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":15,"y":15,"w":261,"h":273}, - "sourceSize": {"w":288,"h":288} -}, -"sprites/buildings/hub.png": -{ - "frame": {"x":3,"y":3,"w":548,"h":549}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":14,"y":16,"w":548,"h":549}, - "sourceSize": {"w":576,"h":576} -}, -"sprites/buildings/miner-chainable.png": -{ - "frame": {"x":1074,"y":1034,"w":136,"h":142}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":5,"y":0,"w":136,"h":142}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/buildings/miner.png": -{ - "frame": {"x":1101,"y":299,"w":136,"h":142}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":5,"y":0,"w":136,"h":142}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/buildings/mixer.png": -{ - "frame": {"x":839,"y":739,"w":260,"h":143}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":14,"y":0,"w":260,"h":143}, - "sourceSize": {"w":288,"h":144} -}, -"sprites/buildings/painter-double.png": -{ - "frame": {"x":3,"y":704,"w":288,"h":286}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":0,"w":288,"h":286}, - "sourceSize": {"w":288,"h":288} -}, -"sprites/buildings/painter-mirrored.png": -{ - "frame": {"x":555,"y":590,"w":288,"h":144}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":288,"h":144}, - "sourceSize": {"w":288,"h":144} -}, -"sprites/buildings/painter-quad.png": -{ - "frame": {"x":555,"y":151,"w":560,"h":144}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":5,"y":0,"w":560,"h":144}, - "sourceSize": {"w":576,"h":144} -}, -"sprites/buildings/painter.png": -{ - "frame": {"x":547,"y":738,"w":288,"h":144}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":288,"h":144}, - "sourceSize": {"w":288,"h":144} -}, -"sprites/buildings/rotater-ccw.png": -{ - "frame": {"x":698,"y":1478,"w":141,"h":143}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":0,"w":141,"h":143}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/buildings/rotater-fl.png": -{ - "frame": {"x":532,"y":1620,"w":141,"h":143}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":1,"y":0,"w":141,"h":143}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/buildings/rotater.png": -{ - "frame": {"x":677,"y":1625,"w":141,"h":143}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":0,"w":141,"h":143}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/buildings/splitter-compact-inverse.png": -{ - "frame": {"x":1384,"y":298,"w":141,"h":136}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":3,"w":141,"h":136}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/buildings/splitter-compact.png": -{ - "frame": {"x":1529,"y":298,"w":139,"h":136}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":5,"y":3,"w":139,"h":136}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/buildings/splitter.png": -{ - "frame": {"x":814,"y":1033,"w":256,"h":143}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":17,"y":0,"w":256,"h":143}, - "sourceSize": {"w":288,"h":144} -}, -"sprites/buildings/stacker.png": -{ - "frame": {"x":268,"y":1551,"w":260,"h":143}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":14,"y":0,"w":260,"h":143}, - "sourceSize": {"w":288,"h":144} -}, -"sprites/buildings/trash-storage.png": -{ - "frame": {"x":295,"y":704,"w":248,"h":288}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":22,"y":0,"w":248,"h":288}, - "sourceSize": {"w":288,"h":288} -}, -"sprites/buildings/trash.png": -{ - "frame": {"x":552,"y":1330,"w":144,"h":144}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":144,"h":144}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/buildings/underground_belt_entry-tier2.png": -{ - "frame": {"x":1243,"y":440,"w":137,"h":124}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":5,"y":20,"w":137,"h":124}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/buildings/underground_belt_entry.png": -{ - "frame": {"x":1112,"y":574,"w":137,"h":111}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":5,"y":33,"w":137,"h":111}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/buildings/underground_belt_exit-tier2.png": -{ - "frame": {"x":1253,"y":568,"w":137,"h":111}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":5,"y":0,"w":137,"h":111}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/buildings/underground_belt_exit.png": -{ - "frame": {"x":1394,"y":554,"w":137,"h":111}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":5,"y":0,"w":137,"h":111}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/buildings/wire_crossings-merger.png": -{ - "frame": {"x":1074,"y":886,"w":99,"h":144}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":45,"y":0,"w":99,"h":144}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/buildings/wire_crossings.png": -{ - "frame": {"x":822,"y":1625,"w":99,"h":144}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":45,"y":0,"w":99,"h":144}, - "sourceSize": {"w":144,"h":144} -}, -"sprites/buildings/wire_left.png": -{ - "frame": {"x":1465,"y":1700,"w":60,"h":60}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":35,"w":60,"h":60}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/buildings/wire_right.png": -{ - "frame": {"x":1529,"y":1700,"w":60,"h":60}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":35,"y":35,"w":60,"h":60}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/buildings/wire_top.png": -{ - "frame": {"x":1762,"y":554,"w":25,"h":95}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":35,"y":0,"w":25,"h":95}, - "sourceSize": {"w":95,"h":95} -}, -"sprites/debug/acceptor_slot.png": -{ - "frame": {"x":1639,"y":1597,"w":38,"h":48}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":5,"y":0,"w":38,"h":48}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/debug/ejector_slot.png": -{ - "frame": {"x":1593,"y":1697,"w":38,"h":48}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":5,"y":0,"w":38,"h":48}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/map_overview/belt_forward.png": -{ - "frame": {"x":1499,"y":1371,"w":20,"h":24}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":0,"w":20,"h":24}, - "sourceSize": {"w":24,"h":24} -}, -"sprites/map_overview/belt_left.png": -{ - "frame": {"x":505,"y":1698,"w":22,"h":22}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":2,"w":22,"h":22}, - "sourceSize": {"w":24,"h":24} -}, -"sprites/map_overview/belt_right.png": -{ - "frame": {"x":1195,"y":1738,"w":22,"h":22}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":2,"w":22,"h":22}, - "sourceSize": {"w":24,"h":24} -}, -"sprites/misc/deletion_marker.png": -{ - "frame": {"x":311,"y":1698,"w":62,"h":62}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":5,"y":5,"w":62,"h":62}, - "sourceSize": {"w":72,"h":72} -}, -"sprites/misc/energy_generator_overlay.png": -{ - "frame": {"x":1112,"y":689,"w":116,"h":44}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":137,"y":217,"w":116,"h":44}, - "sourceSize": {"w":288,"h":288} -}, -"sprites/misc/hub_direction_indicator.png": -{ - "frame": {"x":1288,"y":1378,"w":24,"h":24}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":24,"h":24}, - "sourceSize": {"w":24,"h":24} -}, -"sprites/misc/lock_direction_indicator.png": -{ - "frame": {"x":1198,"y":1327,"w":36,"h":24}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":0,"y":6,"w":36,"h":24}, - "sourceSize": {"w":36,"h":36} -}, -"sprites/misc/slot_bad_arrow.png": -{ - "frame": {"x":311,"y":1698,"w":62,"h":62}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":5,"y":5,"w":62,"h":62}, - "sourceSize": {"w":72,"h":72} -}, -"sprites/misc/slot_good_arrow.png": -{ - "frame": {"x":245,"y":1698,"w":62,"h":72}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":5,"y":0,"w":62,"h":72}, - "sourceSize": {"w":72,"h":72} -}, -"sprites/misc/storage_overlay.png": -{ - "frame": {"x":1535,"y":554,"w":133,"h":66}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":2,"w":133,"h":66}, - "sourceSize": {"w":135,"h":68} -}, -"sprites/misc/waypoint.png": -{ - "frame": {"x":1683,"y":1517,"w":20,"h":24}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":0,"w":20,"h":24}, - "sourceSize": {"w":24,"h":24} -}, -"sprites/misc/wires_overlay_tile.png": -{ - "frame": {"x":1672,"y":298,"w":96,"h":96}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":96,"h":96}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/wires/battery_empty.png": -{ - "frame": {"x":1711,"y":1418,"w":29,"h":46}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":9,"y":1,"w":29,"h":46}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/wires/battery_full.png": -{ - "frame": {"x":1672,"y":398,"w":44,"h":30}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":10,"w":44,"h":30}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/wires/battery_low.png": -{ - "frame": {"x":1103,"y":838,"w":44,"h":30}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":10,"w":44,"h":30}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/wires/battery_medium.png": -{ - "frame": {"x":847,"y":1429,"w":44,"h":30}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":10,"w":44,"h":30}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/wires/negative_energy.png": -{ - "frame": {"x":1262,"y":1133,"w":32,"h":32}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":8,"y":8,"w":32,"h":32}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/wires/pin_negative_accept.png": -{ - "frame": {"x":185,"y":1688,"w":56,"h":79}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":20,"y":0,"w":56,"h":79}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/wires/pin_negative_eject.png": -{ - "frame": {"x":1750,"y":1022,"w":49,"h":76}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":23,"y":0,"w":49,"h":76}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/wires/pin_positive_accept.png": -{ - "frame": {"x":1630,"y":1517,"w":49,"h":76}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":23,"y":0,"w":49,"h":76}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/wires/pin_positive_eject.png": -{ - "frame": {"x":1438,"y":962,"w":56,"h":79}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":20,"y":0,"w":56,"h":79}, - "sourceSize": {"w":96,"h":96} -}, -"sprites/wires/positive_energy.png": -{ - "frame": {"x":843,"y":1577,"w":32,"h":32}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":8,"y":8,"w":32,"h":32}, - "sourceSize": {"w":48,"h":48} -}, -"sprites/wires/waste_piled.png": -{ - "frame": {"x":1214,"y":1133,"w":44,"h":43}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":2,"w":44,"h":43}, - "sourceSize": {"w":48,"h":48} -}}, -"meta": { - "app": "https://www.codeandweb.com/texturepacker", - "version": "1.0", - "image": "atlas0_75.png", - "format": "RGBA8888", - "size": {"w":1810,"h":1778}, - "scale": "0.75", - "smartupdate": "$TexturePacker:SmartUpdate:dfc84e4381978113df4ad0cd8a5aace9:4e9bd6f6c82aaaa8a4a583cab68dc719:f159918d23e5952766c6d23ab52278c6$" -} -} diff --git a/res_built/atlas/atlas0_75.png b/res_built/atlas/atlas0_75.png deleted file mode 100644 index d865f650..00000000 Binary files a/res_built/atlas/atlas0_75.png and /dev/null differ diff --git a/res_built/atlas/atlas0_hq.json b/res_built/atlas/atlas0_hq.json new file mode 100644 index 00000000..2aa01927 --- /dev/null +++ b/res_built/atlas/atlas0_hq.json @@ -0,0 +1,1308 @@ +{"frames": { + +"sprites/belt/built/forward_0.png": +{ + "frame": {"x":440,"y":742,"w":116,"h":144}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":14,"y":0,"w":116,"h":144}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/belt/built/forward_1.png": +{ + "frame": {"x":1925,"y":1008,"w":116,"h":144}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":14,"y":0,"w":116,"h":144}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/belt/built/forward_2.png": +{ + "frame": {"x":1540,"y":1139,"w":116,"h":144}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":14,"y":0,"w":116,"h":144}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/belt/built/forward_3.png": +{ + "frame": {"x":1803,"y":1118,"w":116,"h":144}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":14,"y":0,"w":116,"h":144}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/belt/built/forward_4.png": +{ + "frame": {"x":1923,"y":1156,"w":116,"h":144}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":14,"y":0,"w":116,"h":144}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/belt/built/forward_5.png": +{ + "frame": {"x":1801,"y":1266,"w":116,"h":144}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":14,"y":0,"w":116,"h":144}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/belt/built/forward_6.png": +{ + "frame": {"x":1921,"y":1304,"w":116,"h":144}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":14,"y":0,"w":116,"h":144}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/belt/built/forward_7.png": +{ + "frame": {"x":432,"y":1334,"w":116,"h":144}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":14,"y":0,"w":116,"h":144}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/belt/built/forward_8.png": +{ + "frame": {"x":430,"y":1482,"w":116,"h":144}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":14,"y":0,"w":116,"h":144}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/belt/built/forward_9.png": +{ + "frame": {"x":141,"y":1877,"w":116,"h":144}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":14,"y":0,"w":116,"h":144}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/belt/built/forward_10.png": +{ + "frame": {"x":438,"y":890,"w":116,"h":144}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":14,"y":0,"w":116,"h":144}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/belt/built/forward_11.png": +{ + "frame": {"x":438,"y":1038,"w":116,"h":144}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":14,"y":0,"w":116,"h":144}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/belt/built/forward_12.png": +{ + "frame": {"x":1542,"y":991,"w":116,"h":144}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":14,"y":0,"w":116,"h":144}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/belt/built/forward_13.png": +{ + "frame": {"x":437,"y":1186,"w":116,"h":144}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":14,"y":0,"w":116,"h":144}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/belt/built/left_0.png": +{ + "frame": {"x":145,"y":1475,"w":130,"h":130}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":14,"w":130,"h":130}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/belt/built/left_1.png": +{ + "frame": {"x":3,"y":1575,"w":130,"h":130}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":14,"w":130,"h":130}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/belt/built/left_2.png": +{ + "frame": {"x":279,"y":1493,"w":130,"h":130}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":14,"w":130,"h":130}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/belt/built/left_3.png": +{ + "frame": {"x":137,"y":1609,"w":130,"h":130}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":14,"w":130,"h":130}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/belt/built/left_4.png": +{ + "frame": {"x":3,"y":1709,"w":130,"h":130}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":14,"w":130,"h":130}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/belt/built/left_5.png": +{ + "frame": {"x":271,"y":1627,"w":130,"h":130}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":14,"w":130,"h":130}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/belt/built/left_6.png": +{ + "frame": {"x":137,"y":1743,"w":130,"h":130}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":14,"w":130,"h":130}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/belt/built/left_7.png": +{ + "frame": {"x":3,"y":1843,"w":130,"h":130}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":14,"w":130,"h":130}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/belt/built/left_8.png": +{ + "frame": {"x":1379,"y":1274,"w":130,"h":130}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":14,"w":130,"h":130}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/belt/built/left_9.png": +{ + "frame": {"x":1513,"y":1287,"w":130,"h":130}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":14,"w":130,"h":130}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/belt/built/left_10.png": +{ + "frame": {"x":1076,"y":1288,"w":130,"h":130}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":14,"w":130,"h":130}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/belt/built/left_11.png": +{ + "frame": {"x":927,"y":1295,"w":130,"h":130}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":14,"w":130,"h":130}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/belt/built/left_12.png": +{ + "frame": {"x":786,"y":1363,"w":130,"h":130}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":14,"w":130,"h":130}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/belt/built/left_13.png": +{ + "frame": {"x":552,"y":1416,"w":130,"h":130}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":14,"w":130,"h":130}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/belt/built/right_0.png": +{ + "frame": {"x":1647,"y":1294,"w":130,"h":130}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":14,"y":14,"w":130,"h":130}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/belt/built/right_1.png": +{ + "frame": {"x":1781,"y":1414,"w":130,"h":130}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":14,"y":14,"w":130,"h":130}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/belt/built/right_2.png": +{ + "frame": {"x":1344,"y":1408,"w":130,"h":130}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":14,"y":14,"w":130,"h":130}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/belt/built/right_3.png": +{ + "frame": {"x":1195,"y":1520,"w":130,"h":130}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":14,"y":14,"w":130,"h":130}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/belt/built/right_4.png": +{ + "frame": {"x":1054,"y":1556,"w":130,"h":130}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":14,"y":14,"w":130,"h":130}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/belt/built/right_5.png": +{ + "frame": {"x":1478,"y":1421,"w":130,"h":130}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":14,"y":14,"w":130,"h":130}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/belt/built/right_6.png": +{ + "frame": {"x":1329,"y":1542,"w":130,"h":130}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":14,"y":14,"w":130,"h":130}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/belt/built/right_7.png": +{ + "frame": {"x":1188,"y":1654,"w":130,"h":130}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":14,"y":14,"w":130,"h":130}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/belt/built/right_8.png": +{ + "frame": {"x":1612,"y":1428,"w":130,"h":130}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":14,"y":14,"w":130,"h":130}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/belt/built/right_9.png": +{ + "frame": {"x":1463,"y":1555,"w":130,"h":130}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":14,"y":14,"w":130,"h":130}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/belt/built/right_10.png": +{ + "frame": {"x":1915,"y":1452,"w":130,"h":130}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":14,"y":14,"w":130,"h":130}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/belt/built/right_11.png": +{ + "frame": {"x":1210,"y":1386,"w":130,"h":130}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":14,"y":14,"w":130,"h":130}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/belt/built/right_12.png": +{ + "frame": {"x":1061,"y":1422,"w":130,"h":130}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":14,"y":14,"w":130,"h":130}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/belt/built/right_13.png": +{ + "frame": {"x":920,"y":1429,"w":130,"h":130}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":14,"y":14,"w":130,"h":130}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/blueprints/belt_left.png": +{ + "frame": {"x":1322,"y":1676,"w":130,"h":130}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":14,"w":130,"h":130}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/blueprints/belt_right.png": +{ + "frame": {"x":1746,"y":1548,"w":130,"h":130}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":14,"y":14,"w":130,"h":130}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/blueprints/belt_top.png": +{ + "frame": {"x":261,"y":1877,"w":116,"h":144}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":14,"y":0,"w":116,"h":144}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/blueprints/constant_signal.png": +{ + "frame": {"x":1937,"y":759,"w":105,"h":127}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":20,"y":0,"w":105,"h":127}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/blueprints/cutter-quad.png": +{ + "frame": {"x":3,"y":151,"w":548,"h":144}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":17,"y":0,"w":548,"h":144}, + "sourceSize": {"w":576,"h":144} +}, +"sprites/blueprints/cutter.png": +{ + "frame": {"x":847,"y":298,"w":256,"h":144}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":17,"y":0,"w":256,"h":144}, + "sourceSize": {"w":288,"h":144} +}, +"sprites/blueprints/display.png": +{ + "frame": {"x":1597,"y":1562,"w":128,"h":136}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":8,"y":8,"w":128,"h":136}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/blueprints/filter.png": +{ + "frame": {"x":1107,"y":556,"w":268,"h":144}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":16,"y":0,"w":268,"h":144}, + "sourceSize": {"w":288,"h":144} +}, +"sprites/blueprints/lever.png": +{ + "frame": {"x":1823,"y":732,"w":110,"h":116}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":17,"y":17,"w":110,"h":116}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/blueprints/logic_gate-not.png": +{ + "frame": {"x":1545,"y":843,"w":123,"h":144}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":11,"y":0,"w":123,"h":144}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/blueprints/logic_gate-or.png": +{ + "frame": {"x":560,"y":888,"w":144,"h":123}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":0,"w":144,"h":123}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/blueprints/logic_gate-transistor.png": +{ + "frame": {"x":1820,"y":970,"w":101,"h":144}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":0,"w":101,"h":144}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/blueprints/logic_gate-xor.png": +{ + "frame": {"x":1101,"y":852,"w":144,"h":143}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":0,"w":144,"h":143}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/blueprints/logic_gate.png": +{ + "frame": {"x":824,"y":885,"w":144,"h":133}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":0,"w":144,"h":133}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/blueprints/miner-chainable.png": +{ + "frame": {"x":150,"y":1035,"w":136,"h":143}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":5,"y":0,"w":136,"h":143}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/blueprints/miner.png": +{ + "frame": {"x":150,"y":1182,"w":136,"h":143}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":5,"y":0,"w":136,"h":143}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/blueprints/mixer.png": +{ + "frame": {"x":1676,"y":584,"w":261,"h":144}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":13,"y":0,"w":261,"h":144}, + "sourceSize": {"w":288,"h":144} +}, +"sprites/blueprints/painter-double.png": +{ + "frame": {"x":1683,"y":3,"w":288,"h":287}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":0,"w":288,"h":287}, + "sourceSize": {"w":288,"h":288} +}, +"sprites/blueprints/painter-mirrored.png": +{ + "frame": {"x":555,"y":298,"w":288,"h":144}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":288,"h":144}, + "sourceSize": {"w":288,"h":144} +}, +"sprites/blueprints/painter-quad.png": +{ + "frame": {"x":3,"y":3,"w":560,"h":144}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":5,"y":0,"w":560,"h":144}, + "sourceSize": {"w":576,"h":144} +}, +"sprites/blueprints/painter.png": +{ + "frame": {"x":3,"y":299,"w":288,"h":144}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":288,"h":144}, + "sourceSize": {"w":288,"h":144} +}, +"sprites/blueprints/rotater-ccw.png": +{ + "frame": {"x":3,"y":1035,"w":143,"h":144}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":1,"y":0,"w":143,"h":144}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/blueprints/rotater-fl.png": +{ + "frame": {"x":1396,"y":979,"w":142,"h":144}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":0,"w":142,"h":144}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/blueprints/rotater.png": +{ + "frame": {"x":290,"y":1060,"w":143,"h":144}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":1,"y":0,"w":143,"h":144}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/blueprints/splitter-compact-inverse.png": +{ + "frame": {"x":1249,"y":988,"w":142,"h":138}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":2,"w":142,"h":138}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/blueprints/splitter-compact.png": +{ + "frame": {"x":1094,"y":1146,"w":139,"h":138}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":5,"y":2,"w":139,"h":138}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/blueprints/splitter.png": +{ + "frame": {"x":295,"y":299,"w":256,"h":144}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":17,"y":0,"w":256,"h":144}, + "sourceSize": {"w":288,"h":144} +}, +"sprites/blueprints/stacker.png": +{ + "frame": {"x":295,"y":594,"w":261,"h":144}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":13,"y":0,"w":261,"h":144}, + "sourceSize": {"w":288,"h":144} +}, +"sprites/blueprints/trash-storage.png": +{ + "frame": {"x":847,"y":593,"w":250,"h":288}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":21,"y":0,"w":250,"h":288}, + "sourceSize": {"w":288,"h":288} +}, +"sprites/blueprints/trash.png": +{ + "frame": {"x":292,"y":742,"w":144,"h":144}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":144,"h":144}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/blueprints/underground_belt_entry-tier2.png": +{ + "frame": {"x":3,"y":1330,"w":138,"h":125}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":4,"y":19,"w":138,"h":125}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/blueprints/underground_belt_entry.png": +{ + "frame": {"x":3,"y":1459,"w":138,"h":112}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":4,"y":32,"w":138,"h":112}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/blueprints/underground_belt_exit-tier2.png": +{ + "frame": {"x":558,"y":1185,"w":139,"h":112}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":4,"y":0,"w":139,"h":112}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/blueprints/underground_belt_exit.png": +{ + "frame": {"x":1237,"y":1270,"w":138,"h":112}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":4,"y":0,"w":138,"h":112}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/blueprints/wire-cross.png": +{ + "frame": {"x":3,"y":887,"w":144,"h":144}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":144,"h":144}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/blueprints/wire-split.png": +{ + "frame": {"x":801,"y":1022,"w":144,"h":82}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":62,"w":144,"h":82}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/blueprints/wire-turn.png": +{ + "frame": {"x":706,"y":1036,"w":82,"h":82}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":62,"y":62,"w":82,"h":82}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/blueprints/wire.png": +{ + "frame": {"x":1107,"y":151,"w":20,"h":144}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":62,"y":0,"w":20,"h":144}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/blueprints/wire_tunnel-coating.png": +{ + "frame": {"x":255,"y":677,"w":33,"h":135}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":55,"y":4,"w":33,"h":135}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/blueprints/wire_tunnel.png": +{ + "frame": {"x":290,"y":1208,"w":138,"h":135}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":4,"y":4,"w":138,"h":135}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/buildings/belt_left.png": +{ + "frame": {"x":145,"y":1475,"w":130,"h":130}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":14,"w":130,"h":130}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/buildings/belt_right.png": +{ + "frame": {"x":1647,"y":1294,"w":130,"h":130}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":14,"y":14,"w":130,"h":130}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/buildings/belt_top.png": +{ + "frame": {"x":440,"y":742,"w":116,"h":144}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":14,"y":0,"w":116,"h":144}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/buildings/constant_signal.png": +{ + "frame": {"x":1941,"y":628,"w":104,"h":127}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":20,"y":0,"w":104,"h":127}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/buildings/cutter-quad.png": +{ + "frame": {"x":555,"y":151,"w":548,"h":143}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":17,"y":0,"w":548,"h":143}, + "sourceSize": {"w":576,"h":144} +}, +"sprites/buildings/cutter.png": +{ + "frame": {"x":847,"y":446,"w":256,"h":143}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":17,"y":0,"w":256,"h":143}, + "sourceSize": {"w":288,"h":144} +}, +"sprites/buildings/display.png": +{ + "frame": {"x":1545,"y":704,"w":126,"h":135}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":9,"w":126,"h":135}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/buildings/filter.png": +{ + "frame": {"x":1379,"y":556,"w":267,"h":144}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":17,"y":0,"w":267,"h":144}, + "sourceSize": {"w":288,"h":144} +}, +"sprites/buildings/hub.png": +{ + "frame": {"x":1131,"y":3,"w":548,"h":549}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":14,"y":16,"w":548,"h":549}, + "sourceSize": {"w":576,"h":576} +}, +"sprites/buildings/lever.png": +{ + "frame": {"x":1823,"y":852,"w":109,"h":114}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":18,"y":18,"w":109,"h":114}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/buildings/logic_gate-not.png": +{ + "frame": {"x":972,"y":885,"w":122,"h":144}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":12,"y":0,"w":122,"h":144}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/buildings/logic_gate-or.png": +{ + "frame": {"x":1396,"y":852,"w":143,"h":123}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":1,"y":0,"w":143,"h":123}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/buildings/logic_gate-transistor.png": +{ + "frame": {"x":151,"y":887,"w":100,"h":144}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":1,"y":0,"w":100,"h":144}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/buildings/logic_gate-xor.png": +{ + "frame": {"x":3,"y":1183,"w":143,"h":143}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":1,"y":0,"w":143,"h":143}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/buildings/logic_gate.png": +{ + "frame": {"x":1249,"y":852,"w":143,"h":132}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":1,"y":0,"w":143,"h":132}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/buildings/miner-chainable.png": +{ + "frame": {"x":150,"y":1329,"w":136,"h":142}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":5,"y":0,"w":136,"h":142}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/buildings/miner.png": +{ + "frame": {"x":290,"y":1347,"w":136,"h":142}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":5,"y":0,"w":136,"h":142}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/buildings/mixer.png": +{ + "frame": {"x":560,"y":594,"w":260,"h":143}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":14,"y":0,"w":260,"h":143}, + "sourceSize": {"w":288,"h":144} +}, +"sprites/buildings/painter-double.png": +{ + "frame": {"x":1683,"y":294,"w":288,"h":286}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":0,"w":288,"h":286}, + "sourceSize": {"w":288,"h":288} +}, +"sprites/buildings/painter-mirrored.png": +{ + "frame": {"x":555,"y":446,"w":288,"h":144}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":288,"h":144}, + "sourceSize": {"w":288,"h":144} +}, +"sprites/buildings/painter-quad.png": +{ + "frame": {"x":567,"y":3,"w":560,"h":144}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":5,"y":0,"w":560,"h":144}, + "sourceSize": {"w":576,"h":144} +}, +"sprites/buildings/painter.png": +{ + "frame": {"x":3,"y":447,"w":288,"h":144}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":288,"h":144}, + "sourceSize": {"w":288,"h":144} +}, +"sprites/buildings/rotater-ccw.png": +{ + "frame": {"x":1098,"y":999,"w":141,"h":143}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":2,"y":0,"w":141,"h":143}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/buildings/rotater-fl.png": +{ + "frame": {"x":949,"y":1033,"w":141,"h":143}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":1,"y":0,"w":141,"h":143}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/buildings/rotater.png": +{ + "frame": {"x":1395,"y":1127,"w":141,"h":143}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":2,"y":0,"w":141,"h":143}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/buildings/splitter-compact-inverse.png": +{ + "frame": {"x":1243,"y":1130,"w":141,"h":136}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":3,"w":141,"h":136}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/buildings/splitter-compact.png": +{ + "frame": {"x":792,"y":1108,"w":139,"h":136}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":5,"y":3,"w":139,"h":136}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/buildings/splitter.png": +{ + "frame": {"x":295,"y":447,"w":256,"h":143}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":17,"y":0,"w":256,"h":143}, + "sourceSize": {"w":288,"h":144} +}, +"sprites/buildings/stacker.png": +{ + "frame": {"x":560,"y":741,"w":260,"h":143}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":14,"y":0,"w":260,"h":143}, + "sourceSize": {"w":288,"h":144} +}, +"sprites/buildings/trash-storage.png": +{ + "frame": {"x":3,"y":595,"w":248,"h":288}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":22,"y":0,"w":248,"h":288}, + "sourceSize": {"w":288,"h":288} +}, +"sprites/buildings/trash.png": +{ + "frame": {"x":1101,"y":704,"w":144,"h":144}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":144,"h":144}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/buildings/underground_belt_entry-tier2.png": +{ + "frame": {"x":1660,"y":1166,"w":137,"h":124}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":5,"y":20,"w":137,"h":124}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/buildings/underground_belt_entry.png": +{ + "frame": {"x":935,"y":1180,"w":137,"h":111}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":5,"y":33,"w":137,"h":111}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/buildings/underground_belt_exit-tier2.png": +{ + "frame": {"x":786,"y":1248,"w":137,"h":111}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":5,"y":0,"w":137,"h":111}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/buildings/underground_belt_exit.png": +{ + "frame": {"x":557,"y":1301,"w":137,"h":111}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":5,"y":0,"w":137,"h":111}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/buildings/wire-cross.png": +{ + "frame": {"x":1249,"y":704,"w":144,"h":144}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":144,"h":144}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/buildings/wire-split.png": +{ + "frame": {"x":290,"y":890,"w":144,"h":81}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":63,"w":144,"h":81}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/buildings/wire-turn.png": +{ + "frame": {"x":706,"y":1122,"w":81,"h":81}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":63,"y":63,"w":81,"h":81}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/buildings/wire.png": +{ + "frame": {"x":2027,"y":184,"w":18,"h":144}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":63,"y":0,"w":18,"h":144}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/buildings/wire_tunnel-coating.png": +{ + "frame": {"x":255,"y":816,"w":31,"h":134}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":56,"y":5,"w":31,"h":134}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/buildings/wire_tunnel.png": +{ + "frame": {"x":1662,"y":1028,"w":137,"h":134}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":5,"y":5,"w":137,"h":134}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/debug/acceptor_slot.png": +{ + "frame": {"x":1107,"y":447,"w":12,"h":12}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":12,"h":12}, + "sourceSize": {"w":12,"h":12} +}, +"sprites/debug/ejector_slot.png": +{ + "frame": {"x":1107,"y":463,"w":12,"h":12}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":12,"h":12}, + "sourceSize": {"w":12,"h":12} +}, +"sprites/misc/hub_direction_indicator.png": +{ + "frame": {"x":1975,"y":184,"w":48,"h":48}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":48,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/misc/slot_bad_arrow.png": +{ + "frame": {"x":255,"y":638,"w":35,"h":35}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":2,"y":2,"w":35,"h":35}, + "sourceSize": {"w":39,"h":39} +}, +"sprites/misc/slot_good_arrow.png": +{ + "frame": {"x":255,"y":595,"w":35,"h":39}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":2,"y":0,"w":35,"h":39}, + "sourceSize": {"w":39,"h":39} +}, +"sprites/misc/storage_overlay.png": +{ + "frame": {"x":708,"y":988,"w":89,"h":44}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":1,"y":1,"w":89,"h":44}, + "sourceSize": {"w":90,"h":45} +}, +"sprites/misc/waypoint.png": +{ + "frame": {"x":48,"y":1977,"w":38,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":5,"y":0,"w":38,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/wires/boolean_false.png": +{ + "frame": {"x":255,"y":954,"w":31,"h":41}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":5,"w":31,"h":41}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/wires/boolean_true.png": +{ + "frame": {"x":1650,"y":556,"w":22,"h":41}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":11,"y":5,"w":22,"h":41}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/wires/display/blue.png": +{ + "frame": {"x":1975,"y":288,"w":47,"h":47}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":1,"y":1,"w":47,"h":47}, + "sourceSize": {"w":49,"h":49} +}, +"sprites/wires/display/cyan.png": +{ + "frame": {"x":1975,"y":339,"w":47,"h":47}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":1,"y":1,"w":47,"h":47}, + "sourceSize": {"w":49,"h":49} +}, +"sprites/wires/display/green.png": +{ + "frame": {"x":1975,"y":390,"w":47,"h":47}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":1,"y":1,"w":47,"h":47}, + "sourceSize": {"w":49,"h":49} +}, +"sprites/wires/display/purple.png": +{ + "frame": {"x":1975,"y":441,"w":47,"h":47}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":1,"y":1,"w":47,"h":47}, + "sourceSize": {"w":49,"h":49} +}, +"sprites/wires/display/red.png": +{ + "frame": {"x":1975,"y":492,"w":47,"h":47}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":1,"y":1,"w":47,"h":47}, + "sourceSize": {"w":49,"h":49} +}, +"sprites/wires/display/white.png": +{ + "frame": {"x":1975,"y":543,"w":47,"h":47}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":1,"y":1,"w":47,"h":47}, + "sourceSize": {"w":49,"h":49} +}, +"sprites/wires/display/yellow.png": +{ + "frame": {"x":90,"y":1977,"w":47,"h":47}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":1,"y":1,"w":47,"h":47}, + "sourceSize": {"w":49,"h":49} +}, +"sprites/wires/lever_on.png": +{ + "frame": {"x":1936,"y":890,"w":109,"h":114}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":18,"y":18,"w":109,"h":114}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/wires/logical_acceptor.png": +{ + "frame": {"x":1975,"y":3,"w":62,"h":106}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":43,"y":0,"w":62,"h":106}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/wires/logical_ejector.png": +{ + "frame": {"x":1975,"y":113,"w":60,"h":67}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":44,"y":0,"w":60,"h":67}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/wires/network_conflict.png": +{ + "frame": {"x":271,"y":1810,"w":47,"h":44}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":1,"y":2,"w":47,"h":44}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/wires/network_empty.png": +{ + "frame": {"x":3,"y":1977,"w":41,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":5,"y":0,"w":41,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/wires/overlay_tile.png": +{ + "frame": {"x":708,"y":888,"w":96,"h":96}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":96,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/wires/sets/color_cross.png": +{ + "frame": {"x":1397,"y":704,"w":144,"h":144}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":144,"h":144}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/wires/sets/color_forward.png": +{ + "frame": {"x":2026,"y":332,"w":18,"h":144}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":63,"y":0,"w":18,"h":144}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/wires/sets/color_split.png": +{ + "frame": {"x":290,"y":975,"w":144,"h":81}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":63,"w":144,"h":81}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/wires/sets/color_turn.png": +{ + "frame": {"x":701,"y":1207,"w":81,"h":81}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":63,"y":63,"w":81,"h":81}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/wires/sets/conflict_cross.png": +{ + "frame": {"x":1675,"y":732,"w":144,"h":144}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":144,"h":144}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/wires/sets/conflict_forward.png": +{ + "frame": {"x":2026,"y":480,"w":18,"h":144}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":63,"y":0,"w":18,"h":144}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/wires/sets/conflict_split.png": +{ + "frame": {"x":558,"y":1015,"w":144,"h":81}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":63,"w":144,"h":81}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/wires/sets/conflict_turn.png": +{ + "frame": {"x":701,"y":1292,"w":81,"h":81}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":63,"y":63,"w":81,"h":81}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/wires/sets/regular_cross.png": +{ + "frame": {"x":1249,"y":704,"w":144,"h":144}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":144,"h":144}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/wires/sets/regular_forward.png": +{ + "frame": {"x":2027,"y":184,"w":18,"h":144}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":63,"y":0,"w":18,"h":144}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/wires/sets/regular_split.png": +{ + "frame": {"x":290,"y":890,"w":144,"h":81}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":63,"w":144,"h":81}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/wires/sets/regular_turn.png": +{ + "frame": {"x":706,"y":1122,"w":81,"h":81}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":63,"y":63,"w":81,"h":81}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/wires/sets/shape_cross.png": +{ + "frame": {"x":1672,"y":880,"w":144,"h":144}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":144,"h":144}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/wires/sets/shape_forward.png": +{ + "frame": {"x":1107,"y":299,"w":18,"h":144}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":63,"y":0,"w":18,"h":144}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/wires/sets/shape_split.png": +{ + "frame": {"x":558,"y":1100,"w":144,"h":81}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":63,"w":144,"h":81}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/wires/sets/shape_turn.png": +{ + "frame": {"x":698,"y":1377,"w":81,"h":81}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":63,"y":63,"w":81,"h":81}, + "sourceSize": {"w":144,"h":144} +}, +"sprites/wires/wires_preview.png": +{ + "frame": {"x":1975,"y":236,"w":48,"h":48}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":48,"h":48}, + "sourceSize": {"w":48,"h":48} +}}, +"meta": { + "app": "https://www.codeandweb.com/texturepacker", + "version": "1.0", + "image": "atlas0_hq.png", + "format": "RGBA8888", + "size": {"w":2048,"h":2048}, + "scale": "0.75", + "smartupdate": "$TexturePacker:SmartUpdate:876f0711b44fa7bbab8d2539e9651766:ff01f850e086ef31c114b036c3a32e6d:908b89f5ca8ff73e331a35a3b14d0604$" +} +} diff --git a/res_built/atlas/atlas0_hq.png b/res_built/atlas/atlas0_hq.png new file mode 100644 index 00000000..ef9ab78b Binary files /dev/null and b/res_built/atlas/atlas0_hq.png differ diff --git a/res_built/atlas/atlas0_lq.json b/res_built/atlas/atlas0_lq.json new file mode 100644 index 00000000..3896c6fd --- /dev/null +++ b/res_built/atlas/atlas0_lq.json @@ -0,0 +1,1308 @@ +{"frames": { + +"sprites/belt/built/forward_0.png": +{ + "frame": {"x":415,"y":463,"w":40,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":4,"y":0,"w":40,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/belt/built/forward_1.png": +{ + "frame": {"x":195,"y":828,"w":40,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":4,"y":0,"w":40,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/belt/built/forward_2.png": +{ + "frame": {"x":3,"y":959,"w":40,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":4,"y":0,"w":40,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/belt/built/forward_3.png": +{ + "frame": {"x":448,"y":705,"w":40,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":4,"y":0,"w":40,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/belt/built/forward_4.png": +{ + "frame": {"x":394,"y":752,"w":40,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":4,"y":0,"w":40,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/belt/built/forward_5.png": +{ + "frame": {"x":342,"y":762,"w":40,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":4,"y":0,"w":40,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/belt/built/forward_6.png": +{ + "frame": {"x":289,"y":795,"w":40,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":4,"y":0,"w":40,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/belt/built/forward_7.png": +{ + "frame": {"x":239,"y":836,"w":40,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":4,"y":0,"w":40,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/belt/built/forward_8.png": +{ + "frame": {"x":191,"y":880,"w":40,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":4,"y":0,"w":40,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/belt/built/forward_9.png": +{ + "frame": {"x":143,"y":883,"w":40,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":4,"y":0,"w":40,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/belt/built/forward_10.png": +{ + "frame": {"x":147,"y":831,"w":40,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":4,"y":0,"w":40,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/belt/built/forward_11.png": +{ + "frame": {"x":99,"y":862,"w":40,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":4,"y":0,"w":40,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/belt/built/forward_12.png": +{ + "frame": {"x":51,"y":870,"w":40,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":4,"y":0,"w":40,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/belt/built/forward_13.png": +{ + "frame": {"x":3,"y":907,"w":40,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":4,"y":0,"w":40,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/belt/built/left_0.png": +{ + "frame": {"x":3,"y":667,"w":44,"h":44}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":4,"w":44,"h":44}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/belt/built/left_1.png": +{ + "frame": {"x":208,"y":636,"w":44,"h":44}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":4,"w":44,"h":44}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/belt/built/left_2.png": +{ + "frame": {"x":256,"y":640,"w":44,"h":44}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":4,"w":44,"h":44}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/belt/built/left_3.png": +{ + "frame": {"x":202,"y":684,"w":44,"h":44}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":4,"w":44,"h":44}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/belt/built/left_4.png": +{ + "frame": {"x":150,"y":687,"w":44,"h":44}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":4,"w":44,"h":44}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/belt/built/left_5.png": +{ + "frame": {"x":99,"y":718,"w":44,"h":44}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":4,"w":44,"h":44}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/belt/built/left_6.png": +{ + "frame": {"x":51,"y":726,"w":44,"h":44}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":4,"w":44,"h":44}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/belt/built/left_7.png": +{ + "frame": {"x":3,"y":763,"w":44,"h":44}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":4,"w":44,"h":44}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/belt/built/left_8.png": +{ + "frame": {"x":304,"y":651,"w":44,"h":44}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":4,"w":44,"h":44}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/belt/built/left_9.png": +{ + "frame": {"x":250,"y":688,"w":44,"h":44}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":4,"w":44,"h":44}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/belt/built/left_10.png": +{ + "frame": {"x":154,"y":639,"w":44,"h":44}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":4,"w":44,"h":44}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/belt/built/left_11.png": +{ + "frame": {"x":102,"y":670,"w":44,"h":44}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":4,"w":44,"h":44}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/belt/built/left_12.png": +{ + "frame": {"x":51,"y":678,"w":44,"h":44}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":4,"w":44,"h":44}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/belt/built/left_13.png": +{ + "frame": {"x":3,"y":715,"w":44,"h":44}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":4,"w":44,"h":44}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/belt/built/right_0.png": +{ + "frame": {"x":198,"y":732,"w":44,"h":44}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":4,"y":4,"w":44,"h":44}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/belt/built/right_1.png": +{ + "frame": {"x":147,"y":735,"w":44,"h":44}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":4,"y":4,"w":44,"h":44}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/belt/built/right_2.png": +{ + "frame": {"x":298,"y":699,"w":44,"h":44}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":4,"y":4,"w":44,"h":44}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/belt/built/right_3.png": +{ + "frame": {"x":246,"y":736,"w":44,"h":44}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":4,"y":4,"w":44,"h":44}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/belt/built/right_4.png": +{ + "frame": {"x":195,"y":780,"w":44,"h":44}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":4,"y":4,"w":44,"h":44}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/belt/built/right_5.png": +{ + "frame": {"x":147,"y":783,"w":44,"h":44}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":4,"y":4,"w":44,"h":44}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/belt/built/right_6.png": +{ + "frame": {"x":99,"y":814,"w":44,"h":44}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":4,"y":4,"w":44,"h":44}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/belt/built/right_7.png": +{ + "frame": {"x":51,"y":822,"w":44,"h":44}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":4,"y":4,"w":44,"h":44}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/belt/built/right_8.png": +{ + "frame": {"x":3,"y":859,"w":44,"h":44}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":4,"y":4,"w":44,"h":44}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/belt/built/right_9.png": +{ + "frame": {"x":400,"y":704,"w":44,"h":44}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":4,"y":4,"w":44,"h":44}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/belt/built/right_10.png": +{ + "frame": {"x":99,"y":766,"w":44,"h":44}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":4,"y":4,"w":44,"h":44}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/belt/built/right_11.png": +{ + "frame": {"x":51,"y":774,"w":44,"h":44}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":4,"y":4,"w":44,"h":44}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/belt/built/right_12.png": +{ + "frame": {"x":3,"y":811,"w":44,"h":44}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":4,"y":4,"w":44,"h":44}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/belt/built/right_13.png": +{ + "frame": {"x":352,"y":666,"w":44,"h":44}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":4,"y":4,"w":44,"h":44}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/blueprints/belt_left.png": +{ + "frame": {"x":346,"y":714,"w":44,"h":44}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":4,"w":44,"h":44}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/blueprints/belt_right.png": +{ + "frame": {"x":294,"y":747,"w":44,"h":44}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":4,"y":4,"w":44,"h":44}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/blueprints/belt_top.png": +{ + "frame": {"x":95,"y":914,"w":40,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":4,"y":0,"w":40,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/blueprints/constant_signal.png": +{ + "frame": {"x":329,"y":390,"w":36,"h":43}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":6,"y":0,"w":36,"h":43}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/blueprints/cutter-quad.png": +{ + "frame": {"x":191,"y":55,"w":184,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":5,"y":0,"w":184,"h":48}, + "sourceSize": {"w":192,"h":48} +}, +"sprites/blueprints/cutter.png": +{ + "frame": {"x":187,"y":315,"w":87,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":5,"y":0,"w":87,"h":48}, + "sourceSize": {"w":96,"h":48} +}, +"sprites/blueprints/display.png": +{ + "frame": {"x":106,"y":620,"w":44,"h":46}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":2,"y":2,"w":44,"h":46}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/blueprints/filter.png": +{ + "frame": {"x":3,"y":244,"w":91,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":4,"y":0,"w":91,"h":48}, + "sourceSize": {"w":96,"h":48} +}, +"sprites/blueprints/lever.png": +{ + "frame": {"x":470,"y":257,"w":38,"h":40}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":5,"y":5,"w":38,"h":40}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/blueprints/logic_gate-not.png": +{ + "frame": {"x":243,"y":784,"w":42,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":3,"y":0,"w":42,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/blueprints/logic_gate-or.png": +{ + "frame": {"x":55,"y":500,"w":48,"h":42}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":0,"w":48,"h":42}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/blueprints/logic_gate-transistor.png": +{ + "frame": {"x":144,"y":448,"w":35,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":0,"w":35,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/blueprints/logic_gate-xor.png": +{ + "frame": {"x":291,"y":159,"w":48,"h":48}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":48,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/blueprints/logic_gate.png": +{ + "frame": {"x":384,"y":566,"w":48,"h":45}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":0,"w":48,"h":45}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/blueprints/miner-chainable.png": +{ + "frame": {"x":462,"y":345,"w":47,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":1,"y":0,"w":47,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/blueprints/miner.png": +{ + "frame": {"x":211,"y":584,"w":47,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":1,"y":0,"w":47,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/blueprints/mixer.png": +{ + "frame": {"x":98,"y":244,"w":89,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":3,"y":0,"w":89,"h":48}, + "sourceSize": {"w":96,"h":48} +}, +"sprites/blueprints/painter-double.png": +{ + "frame": {"x":387,"y":3,"w":96,"h":96}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":96,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/blueprints/painter-mirrored.png": +{ + "frame": {"x":191,"y":159,"w":96,"h":48}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":96,"h":48}, + "sourceSize": {"w":96,"h":48} +}, +"sprites/blueprints/painter-quad.png": +{ + "frame": {"x":3,"y":3,"w":188,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":1,"y":0,"w":188,"h":48}, + "sourceSize": {"w":192,"h":48} +}, +"sprites/blueprints/painter.png": +{ + "frame": {"x":375,"y":203,"w":96,"h":48}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":96,"h":48}, + "sourceSize": {"w":96,"h":48} +}, +"sprites/blueprints/rotater-ccw.png": +{ + "frame": {"x":291,"y":211,"w":48,"h":48}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":48,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/blueprints/rotater-fl.png": +{ + "frame": {"x":285,"y":263,"w":48,"h":48}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":48,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/blueprints/rotater.png": +{ + "frame": {"x":460,"y":397,"w":48,"h":48}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":48,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/blueprints/splitter-compact-inverse.png": +{ + "frame": {"x":183,"y":367,"w":48,"h":48}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":48,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/blueprints/splitter-compact.png": +{ + "frame": {"x":364,"y":615,"w":47,"h":47}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":1,"y":0,"w":47,"h":47}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/blueprints/splitter.png": +{ + "frame": {"x":278,"y":338,"w":87,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":5,"y":0,"w":87,"h":48}, + "sourceSize": {"w":96,"h":48} +}, +"sprites/blueprints/stacker.png": +{ + "frame": {"x":369,"y":307,"w":89,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":3,"y":0,"w":89,"h":48}, + "sourceSize": {"w":96,"h":48} +}, +"sprites/blueprints/trash-storage.png": +{ + "frame": {"x":94,"y":348,"w":85,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":6,"y":0,"w":85,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/blueprints/trash.png": +{ + "frame": {"x":277,"y":390,"w":48,"h":48}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":48,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/blueprints/underground_belt_entry-tier2.png": +{ + "frame": {"x":3,"y":500,"w":48,"h":43}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":5,"w":48,"h":43}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/blueprints/underground_belt_entry.png": +{ + "frame": {"x":159,"y":523,"w":48,"h":38}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":10,"w":48,"h":38}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/blueprints/underground_belt_exit-tier2.png": +{ + "frame": {"x":211,"y":542,"w":48,"h":38}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":0,"w":48,"h":38}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/blueprints/underground_belt_exit.png": +{ + "frame": {"x":263,"y":546,"w":48,"h":38}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":0,"w":48,"h":38}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/blueprints/wire-cross.png": +{ + "frame": {"x":183,"y":419,"w":48,"h":48}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":48,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/blueprints/wire-split.png": +{ + "frame": {"x":315,"y":567,"w":48,"h":28}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":20,"w":48,"h":28}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/blueprints/wire-turn.png": +{ + "frame": {"x":479,"y":129,"w":28,"h":28}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":20,"y":20,"w":28,"h":28}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/blueprints/wire.png": +{ + "frame": {"x":357,"y":286,"w":8,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":20,"y":0,"w":8,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/blueprints/wire_tunnel-coating.png": +{ + "frame": {"x":235,"y":458,"w":13,"h":47}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":17,"y":0,"w":13,"h":47}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/blueprints/wire_tunnel.png": +{ + "frame": {"x":384,"y":515,"w":48,"h":47}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":0,"w":48,"h":47}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/buildings/belt_left.png": +{ + "frame": {"x":3,"y":667,"w":44,"h":44}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":4,"w":44,"h":44}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/buildings/belt_right.png": +{ + "frame": {"x":198,"y":732,"w":44,"h":44}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":4,"y":4,"w":44,"h":44}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/buildings/belt_top.png": +{ + "frame": {"x":415,"y":463,"w":40,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":4,"y":0,"w":40,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/buildings/constant_signal.png": +{ + "frame": {"x":235,"y":411,"w":36,"h":43}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":6,"y":0,"w":36,"h":43}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/buildings/cutter-quad.png": +{ + "frame": {"x":191,"y":107,"w":184,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":5,"y":0,"w":184,"h":48}, + "sourceSize": {"w":192,"h":48} +}, +"sprites/buildings/cutter.png": +{ + "frame": {"x":369,"y":359,"w":87,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":5,"y":0,"w":87,"h":48}, + "sourceSize": {"w":96,"h":48} +}, +"sprites/buildings/display.png": +{ + "frame": {"x":54,"y":628,"w":44,"h":46}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":2,"y":2,"w":44,"h":46}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/buildings/filter.png": +{ + "frame": {"x":191,"y":263,"w":90,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":5,"y":0,"w":90,"h":48}, + "sourceSize": {"w":96,"h":48} +}, +"sprites/buildings/hub.png": +{ + "frame": {"x":3,"y":55,"w":184,"h":185}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":4,"y":4,"w":184,"h":185}, + "sourceSize": {"w":192,"h":192} +}, +"sprites/buildings/lever.png": +{ + "frame": {"x":470,"y":301,"w":38,"h":40}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":5,"y":5,"w":38,"h":40}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/buildings/logic_gate-not.png": +{ + "frame": {"x":466,"y":653,"w":43,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":3,"y":0,"w":43,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/buildings/logic_gate-or.png": +{ + "frame": {"x":107,"y":500,"w":48,"h":42}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":0,"w":48,"h":42}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/buildings/logic_gate-transistor.png": +{ + "frame": {"x":421,"y":411,"w":35,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":0,"w":35,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/buildings/logic_gate-xor.png": +{ + "frame": {"x":92,"y":448,"w":48,"h":48}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":48,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/buildings/logic_gate.png": +{ + "frame": {"x":436,"y":604,"w":48,"h":45}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":0,"w":48,"h":45}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/buildings/miner-chainable.png": +{ + "frame": {"x":262,"y":588,"w":47,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":1,"y":0,"w":47,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/buildings/miner.png": +{ + "frame": {"x":313,"y":599,"w":47,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":1,"y":0,"w":47,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/buildings/mixer.png": +{ + "frame": {"x":3,"y":296,"w":88,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":4,"y":0,"w":88,"h":48}, + "sourceSize": {"w":96,"h":48} +}, +"sprites/buildings/painter-double.png": +{ + "frame": {"x":379,"y":103,"w":96,"h":96}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":96,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/buildings/painter-mirrored.png": +{ + "frame": {"x":191,"y":211,"w":96,"h":48}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":96,"h":48}, + "sourceSize": {"w":96,"h":48} +}, +"sprites/buildings/painter-quad.png": +{ + "frame": {"x":195,"y":3,"w":188,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":1,"y":0,"w":188,"h":48}, + "sourceSize": {"w":192,"h":48} +}, +"sprites/buildings/painter.png": +{ + "frame": {"x":370,"y":255,"w":96,"h":48}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":96,"h":48}, + "sourceSize": {"w":96,"h":48} +}, +"sprites/buildings/rotater-ccw.png": +{ + "frame": {"x":369,"y":411,"w":48,"h":48}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":48,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/buildings/rotater-fl.png": +{ + "frame": {"x":460,"y":449,"w":48,"h":48}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":48,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/buildings/rotater.png": +{ + "frame": {"x":275,"y":442,"w":48,"h":48}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":48,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/buildings/splitter-compact-inverse.png": +{ + "frame": {"x":436,"y":553,"w":48,"h":47}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":0,"w":48,"h":47}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/buildings/splitter-compact.png": +{ + "frame": {"x":415,"y":653,"w":47,"h":47}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":1,"y":0,"w":47,"h":47}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/buildings/splitter.png": +{ + "frame": {"x":3,"y":348,"w":87,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":5,"y":0,"w":87,"h":48}, + "sourceSize": {"w":96,"h":48} +}, +"sprites/buildings/stacker.png": +{ + "frame": {"x":95,"y":296,"w":88,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":4,"y":0,"w":88,"h":48}, + "sourceSize": {"w":96,"h":48} +}, +"sprites/buildings/trash-storage.png": +{ + "frame": {"x":3,"y":400,"w":85,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":6,"y":0,"w":85,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/buildings/trash.png": +{ + "frame": {"x":183,"y":471,"w":48,"h":48}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":48,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/buildings/underground_belt_entry-tier2.png": +{ + "frame": {"x":3,"y":579,"w":47,"h":42}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":1,"y":6,"w":47,"h":42}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/buildings/underground_belt_entry.png": +{ + "frame": {"x":3,"y":625,"w":47,"h":38}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":1,"y":10,"w":47,"h":38}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/buildings/underground_belt_exit-tier2.png": +{ + "frame": {"x":106,"y":578,"w":47,"h":38}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":1,"y":0,"w":47,"h":38}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/buildings/underground_belt_exit.png": +{ + "frame": {"x":157,"y":597,"w":47,"h":38}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":1,"y":0,"w":47,"h":38}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/buildings/wire-cross.png": +{ + "frame": {"x":268,"y":494,"w":48,"h":48}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":48,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/buildings/wire-split.png": +{ + "frame": {"x":55,"y":546,"w":48,"h":28}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":20,"w":48,"h":28}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/buildings/wire-turn.png": +{ + "frame": {"x":479,"y":161,"w":28,"h":28}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":20,"y":20,"w":28,"h":28}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/buildings/wire.png": +{ + "frame": {"x":327,"y":457,"w":8,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":20,"y":0,"w":8,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/buildings/wire_tunnel-coating.png": +{ + "frame": {"x":252,"y":492,"w":12,"h":46}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":18,"y":1,"w":12,"h":46}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/buildings/wire_tunnel.png": +{ + "frame": {"x":55,"y":578,"w":47,"h":46}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":1,"y":1,"w":47,"h":46}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/debug/acceptor_slot.png": +{ + "frame": {"x":379,"y":55,"w":4,"h":4}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":4,"h":4}, + "sourceSize": {"w":4,"h":4} +}, +"sprites/debug/ejector_slot.png": +{ + "frame": {"x":379,"y":63,"w":4,"h":4}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":4,"h":4}, + "sourceSize": {"w":4,"h":4} +}, +"sprites/misc/hub_direction_indicator.png": +{ + "frame": {"x":487,"y":30,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16} +}, +"sprites/misc/slot_bad_arrow.png": +{ + "frame": {"x":252,"y":458,"w":13,"h":13}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, + "sourceSize": {"w":13,"h":13} +}, +"sprites/misc/slot_good_arrow.png": +{ + "frame": {"x":252,"y":475,"w":13,"h":13}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, + "sourceSize": {"w":13,"h":13} +}, +"sprites/misc/storage_overlay.png": +{ + "frame": {"x":479,"y":110,"w":30,"h":15}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":30,"h":15}, + "sourceSize": {"w":30,"h":15} +}, +"sprites/misc/waypoint.png": +{ + "frame": {"x":349,"y":437,"w":14,"h":16}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":1,"y":0,"w":14,"h":16}, + "sourceSize": {"w":16,"h":16} +}, +"sprites/wires/boolean_false.png": +{ + "frame": {"x":235,"y":509,"w":12,"h":15}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":2,"y":1,"w":12,"h":15}, + "sourceSize": {"w":16,"h":16} +}, +"sprites/wires/boolean_true.png": +{ + "frame": {"x":357,"y":267,"w":9,"h":15}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":3,"y":1,"w":9,"h":15}, + "sourceSize": {"w":16,"h":16} +}, +"sprites/wires/display/blue.png": +{ + "frame": {"x":487,"y":50,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16} +}, +"sprites/wires/display/cyan.png": +{ + "frame": {"x":487,"y":70,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16} +}, +"sprites/wires/display/green.png": +{ + "frame": {"x":487,"y":90,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16} +}, +"sprites/wires/display/purple.png": +{ + "frame": {"x":337,"y":267,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16} +}, +"sprites/wires/display/red.png": +{ + "frame": {"x":337,"y":287,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16} +}, +"sprites/wires/display/white.png": +{ + "frame": {"x":337,"y":307,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16} +}, +"sprites/wires/display/yellow.png": +{ + "frame": {"x":278,"y":315,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16} +}, +"sprites/wires/lever_on.png": +{ + "frame": {"x":235,"y":367,"w":38,"h":40}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":5,"y":5,"w":38,"h":40}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/wires/logical_acceptor.png": +{ + "frame": {"x":343,"y":227,"w":23,"h":36}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":13,"y":0,"w":23,"h":36}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/wires/logical_ejector.png": +{ + "frame": {"x":487,"y":3,"w":22,"h":23}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":14,"y":0,"w":22,"h":23}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/wires/network_conflict.png": +{ + "frame": {"x":298,"y":315,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16} +}, +"sprites/wires/network_empty.png": +{ + "frame": {"x":318,"y":315,"w":15,"h":16}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":1,"y":0,"w":15,"h":16}, + "sourceSize": {"w":16,"h":16} +}, +"sprites/wires/overlay_tile.png": +{ + "frame": {"x":343,"y":159,"w":32,"h":32}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":32,"h":32}, + "sourceSize": {"w":32,"h":32} +}, +"sprites/wires/sets/color_cross.png": +{ + "frame": {"x":363,"y":463,"w":48,"h":48}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":48,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/wires/sets/color_forward.png": +{ + "frame": {"x":339,"y":457,"w":8,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":20,"y":0,"w":8,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/wires/sets/color_split.png": +{ + "frame": {"x":3,"y":547,"w":48,"h":28}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":20,"w":48,"h":28}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/wires/sets/color_turn.png": +{ + "frame": {"x":479,"y":193,"w":28,"h":28}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":20,"y":20,"w":28,"h":28}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/wires/sets/conflict_cross.png": +{ + "frame": {"x":459,"y":501,"w":48,"h":48}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":48,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/wires/sets/conflict_forward.png": +{ + "frame": {"x":351,"y":457,"w":8,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":20,"y":0,"w":8,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/wires/sets/conflict_split.png": +{ + "frame": {"x":107,"y":546,"w":48,"h":28}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":20,"w":48,"h":28}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/wires/sets/conflict_turn.png": +{ + "frame": {"x":343,"y":195,"w":28,"h":28}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":20,"y":20,"w":28,"h":28}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/wires/sets/regular_cross.png": +{ + "frame": {"x":268,"y":494,"w":48,"h":48}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":48,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/wires/sets/regular_forward.png": +{ + "frame": {"x":327,"y":457,"w":8,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":20,"y":0,"w":8,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/wires/sets/regular_split.png": +{ + "frame": {"x":55,"y":546,"w":48,"h":28}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":20,"w":48,"h":28}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/wires/sets/regular_turn.png": +{ + "frame": {"x":479,"y":161,"w":28,"h":28}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":20,"y":20,"w":28,"h":28}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/wires/sets/shape_cross.png": +{ + "frame": {"x":332,"y":515,"w":48,"h":48}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":48,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/wires/sets/shape_forward.png": +{ + "frame": {"x":320,"y":509,"w":8,"h":48}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":20,"y":0,"w":8,"h":48}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/wires/sets/shape_split.png": +{ + "frame": {"x":159,"y":565,"w":48,"h":28}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":20,"w":48,"h":28}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/wires/sets/shape_turn.png": +{ + "frame": {"x":475,"y":225,"w":28,"h":28}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":20,"y":20,"w":28,"h":28}, + "sourceSize": {"w":48,"h":48} +}, +"sprites/wires/wires_preview.png": +{ + "frame": {"x":329,"y":437,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16} +}}, +"meta": { + "app": "https://www.codeandweb.com/texturepacker", + "version": "1.0", + "image": "atlas0_lq.png", + "format": "RGBA8888", + "size": {"w":512,"h":1024}, + "scale": "0.25", + "smartupdate": "$TexturePacker:SmartUpdate:876f0711b44fa7bbab8d2539e9651766:ff01f850e086ef31c114b036c3a32e6d:908b89f5ca8ff73e331a35a3b14d0604$" +} +} diff --git a/res_built/atlas/atlas0_lq.png b/res_built/atlas/atlas0_lq.png new file mode 100644 index 00000000..c6b4be55 Binary files /dev/null and b/res_built/atlas/atlas0_lq.png differ diff --git a/res_built/atlas/atlas0_mq.json b/res_built/atlas/atlas0_mq.json new file mode 100644 index 00000000..89809854 --- /dev/null +++ b/res_built/atlas/atlas0_mq.json @@ -0,0 +1,1308 @@ +{"frames": { + +"sprites/belt/built/forward_0.png": +{ + "frame": {"x":943,"y":816,"w":78,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":0,"w":78,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/belt/built/forward_1.png": +{ + "frame": {"x":439,"y":803,"w":78,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":0,"w":78,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/belt/built/forward_2.png": +{ + "frame": {"x":850,"y":1402,"w":78,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":0,"w":78,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/belt/built/forward_3.png": +{ + "frame": {"x":932,"y":1402,"w":78,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":0,"w":78,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/belt/built/forward_4.png": +{ + "frame": {"x":751,"y":1431,"w":78,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":0,"w":78,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/belt/built/forward_5.png": +{ + "frame": {"x":650,"y":1480,"w":78,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":0,"w":78,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/belt/built/forward_6.png": +{ + "frame": {"x":551,"y":1494,"w":78,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":0,"w":78,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/belt/built/forward_7.png": +{ + "frame": {"x":454,"y":1522,"w":78,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":0,"w":78,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/belt/built/forward_8.png": +{ + "frame": {"x":358,"y":1553,"w":78,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":0,"w":78,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/belt/built/forward_9.png": +{ + "frame": {"x":267,"y":1554,"w":78,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":0,"w":78,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/belt/built/forward_10.png": +{ + "frame": {"x":276,"y":1454,"w":78,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":0,"w":78,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/belt/built/forward_11.png": +{ + "frame": {"x":185,"y":1499,"w":78,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":0,"w":78,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/belt/built/forward_12.png": +{ + "frame": {"x":94,"y":1514,"w":78,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":0,"w":78,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/belt/built/forward_13.png": +{ + "frame": {"x":3,"y":1585,"w":78,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":0,"w":78,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/belt/built/left_0.png": +{ + "frame": {"x":196,"y":1135,"w":87,"h":87}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":9,"w":87,"h":87}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/belt/built/left_1.png": +{ + "frame": {"x":99,"y":1150,"w":87,"h":87}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":9,"w":87,"h":87}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/belt/built/left_2.png": +{ + "frame": {"x":287,"y":1181,"w":87,"h":87}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":9,"w":87,"h":87}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/belt/built/left_3.png": +{ + "frame": {"x":190,"y":1226,"w":87,"h":87}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":9,"w":87,"h":87}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/belt/built/left_4.png": +{ + "frame": {"x":94,"y":1241,"w":87,"h":87}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":9,"w":87,"h":87}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/belt/built/left_5.png": +{ + "frame": {"x":3,"y":1312,"w":87,"h":87}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":9,"w":87,"h":87}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/belt/built/left_6.png": +{ + "frame": {"x":674,"y":1207,"w":87,"h":87}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":9,"w":87,"h":87}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/belt/built/left_7.png": +{ + "frame": {"x":577,"y":1217,"w":87,"h":87}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":9,"w":87,"h":87}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/belt/built/left_8.png": +{ + "frame": {"x":478,"y":1246,"w":87,"h":87}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":9,"w":87,"h":87}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/belt/built/left_9.png": +{ + "frame": {"x":378,"y":1271,"w":87,"h":87}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":9,"w":87,"h":87}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/belt/built/left_10.png": +{ + "frame": {"x":3,"y":1221,"w":87,"h":87}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":9,"w":87,"h":87}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/belt/built/left_11.png": +{ + "frame": {"x":583,"y":1126,"w":87,"h":87}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":9,"w":87,"h":87}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/belt/built/left_12.png": +{ + "frame": {"x":486,"y":1155,"w":87,"h":87}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":9,"w":87,"h":87}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/belt/built/left_13.png": +{ + "frame": {"x":387,"y":1180,"w":87,"h":87}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":9,"w":87,"h":87}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/belt/built/right_0.png": +{ + "frame": {"x":281,"y":1272,"w":87,"h":87}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":9,"w":87,"h":87}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/belt/built/right_1.png": +{ + "frame": {"x":185,"y":1317,"w":87,"h":87}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":9,"w":87,"h":87}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/belt/built/right_2.png": +{ + "frame": {"x":569,"y":1308,"w":87,"h":87}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":9,"w":87,"h":87}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/belt/built/right_3.png": +{ + "frame": {"x":469,"y":1337,"w":87,"h":87}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":9,"w":87,"h":87}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/belt/built/right_4.png": +{ + "frame": {"x":372,"y":1362,"w":87,"h":87}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":9,"w":87,"h":87}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/belt/built/right_5.png": +{ + "frame": {"x":276,"y":1363,"w":87,"h":87}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":9,"w":87,"h":87}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/belt/built/right_6.png": +{ + "frame": {"x":185,"y":1408,"w":87,"h":87}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":9,"w":87,"h":87}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/belt/built/right_7.png": +{ + "frame": {"x":94,"y":1423,"w":87,"h":87}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":9,"w":87,"h":87}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/belt/built/right_8.png": +{ + "frame": {"x":3,"y":1494,"w":87,"h":87}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":9,"w":87,"h":87}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/belt/built/right_9.png": +{ + "frame": {"x":856,"y":1311,"w":87,"h":87}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":9,"w":87,"h":87}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/belt/built/right_10.png": +{ + "frame": {"x":94,"y":1332,"w":87,"h":87}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":9,"w":87,"h":87}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/belt/built/right_11.png": +{ + "frame": {"x":3,"y":1403,"w":87,"h":87}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":9,"w":87,"h":87}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/belt/built/right_12.png": +{ + "frame": {"x":765,"y":1249,"w":87,"h":87}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":9,"w":87,"h":87}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/belt/built/right_13.png": +{ + "frame": {"x":668,"y":1298,"w":87,"h":87}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":9,"w":87,"h":87}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/blueprints/belt_left.png": +{ + "frame": {"x":759,"y":1340,"w":87,"h":87}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":9,"w":87,"h":87}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/blueprints/belt_right.png": +{ + "frame": {"x":660,"y":1389,"w":87,"h":87}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":9,"w":87,"h":87}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/blueprints/belt_top.png": +{ + "frame": {"x":176,"y":1599,"w":78,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":0,"w":78,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/blueprints/constant_signal.png": +{ + "frame": {"x":949,"y":396,"w":71,"h":85}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":13,"y":0,"w":71,"h":85}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/blueprints/cutter-quad.png": +{ + "frame": {"x":373,"y":103,"w":366,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":11,"y":0,"w":366,"h":96}, + "sourceSize": {"w":384,"h":96} +}, +"sprites/blueprints/cutter.png": +{ + "frame": {"x":745,"y":594,"w":172,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":11,"y":0,"w":172,"h":96}, + "sourceSize": {"w":192,"h":96} +}, +"sprites/blueprints/display.png": +{ + "frame": {"x":560,"y":1399,"w":86,"h":91}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":5,"y":5,"w":86,"h":91}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/blueprints/filter.png": +{ + "frame": {"x":569,"y":303,"w":180,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":10,"y":0,"w":180,"h":96}, + "sourceSize": {"w":192,"h":96} +}, +"sprites/blueprints/lever.png": +{ + "frame": {"x":946,"y":734,"w":74,"h":78}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":11,"y":11,"w":74,"h":78}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/blueprints/logic_gate-not.png": +{ + "frame": {"x":367,"y":1453,"w":83,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":7,"y":0,"w":83,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/blueprints/logic_gate-or.png": +{ + "frame": {"x":521,"y":991,"w":96,"h":82}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":0,"w":96,"h":82}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/blueprints/logic_gate-transistor.png": +{ + "frame": {"x":449,"y":703,"w":68,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":0,"w":68,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/blueprints/logic_gate-xor.png": +{ + "frame": {"x":3,"y":674,"w":96,"h":96}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":96,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/blueprints/logic_gate.png": +{ + "frame": {"x":335,"y":902,"w":96,"h":89}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":0,"w":96,"h":89}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/blueprints/miner-chainable.png": +{ + "frame": {"x":929,"y":916,"w":92,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":3,"y":0,"w":92,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/blueprints/miner.png": +{ + "frame": {"x":100,"y":1050,"w":92,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":3,"y":0,"w":92,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/blueprints/mixer.png": +{ + "frame": {"x":3,"y":474,"w":175,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":8,"y":0,"w":175,"h":96}, + "sourceSize": {"w":192,"h":96} +}, +"sprites/blueprints/painter-double.png": +{ + "frame": {"x":759,"y":3,"w":192,"h":192}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":192,"h":192}, + "sourceSize": {"w":192,"h":192} +}, +"sprites/blueprints/painter-mirrored.png": +{ + "frame": {"x":373,"y":303,"w":192,"h":96}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":192,"h":96}, + "sourceSize": {"w":192,"h":96} +}, +"sprites/blueprints/painter-quad.png": +{ + "frame": {"x":3,"y":3,"w":374,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":3,"y":0,"w":374,"h":96}, + "sourceSize": {"w":384,"h":96} +}, +"sprites/blueprints/painter.png": +{ + "frame": {"x":753,"y":394,"w":192,"h":96}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":192,"h":96}, + "sourceSize": {"w":192,"h":96} +}, +"sprites/blueprints/rotater-ccw.png": +{ + "frame": {"x":103,"y":674,"w":96,"h":96}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":96,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/blueprints/rotater-fl.png": +{ + "frame": {"x":921,"y":1016,"w":95,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":0,"w":95,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/blueprints/rotater.png": +{ + "frame": {"x":203,"y":674,"w":96,"h":96}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":96,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/blueprints/splitter-compact-inverse.png": +{ + "frame": {"x":820,"y":1152,"w":95,"h":93}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":1,"w":95,"h":93}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/blueprints/splitter-compact.png": +{ + "frame": {"x":101,"y":874,"w":93,"h":93}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":3,"y":1,"w":93,"h":93}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/blueprints/splitter.png": +{ + "frame": {"x":3,"y":574,"w":171,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":11,"y":0,"w":171,"h":96}, + "sourceSize": {"w":192,"h":96} +}, +"sprites/blueprints/stacker.png": +{ + "frame": {"x":182,"y":474,"w":175,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":8,"y":0,"w":175,"h":96}, + "sourceSize": {"w":192,"h":96} +}, +"sprites/blueprints/trash-storage.png": +{ + "frame": {"x":528,"y":603,"w":167,"h":192}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":14,"y":0,"w":167,"h":192}, + "sourceSize": {"w":192,"h":192} +}, +"sprites/blueprints/trash.png": +{ + "frame": {"x":349,"y":703,"w":96,"h":96}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":96,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/blueprints/underground_belt_entry-tier2.png": +{ + "frame": {"x":198,"y":969,"w":93,"h":84}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":2,"y":12,"w":93,"h":84}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/blueprints/underground_belt_entry.png": +{ + "frame": {"x":100,"y":971,"w":93,"h":75}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":2,"y":21,"w":93,"h":75}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/blueprints/underground_belt_exit-tier2.png": +{ + "frame": {"x":3,"y":874,"w":94,"h":75}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":2,"y":0,"w":94,"h":75}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/blueprints/underground_belt_exit.png": +{ + "frame": {"x":3,"y":1048,"w":93,"h":75}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":2,"y":0,"w":93,"h":75}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/blueprints/wire-cross.png": +{ + "frame": {"x":521,"y":799,"w":96,"h":96}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":96,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/blueprints/wire-split.png": +{ + "frame": {"x":721,"y":990,"w":96,"h":55}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":41,"w":96,"h":55}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/blueprints/wire-turn.png": +{ + "frame": {"x":955,"y":105,"w":55,"h":55}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":41,"y":41,"w":55,"h":55}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/blueprints/wire.png": +{ + "frame": {"x":699,"y":603,"w":14,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":41,"y":0,"w":14,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/blueprints/wire_tunnel-coating.png": +{ + "frame": {"x":921,"y":594,"w":23,"h":91}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":36,"y":2,"w":23,"h":91}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/blueprints/wire_tunnel.png": +{ + "frame": {"x":3,"y":953,"w":93,"h":91}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":2,"y":2,"w":93,"h":91}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/buildings/belt_left.png": +{ + "frame": {"x":196,"y":1135,"w":87,"h":87}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":9,"w":87,"h":87}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/buildings/belt_right.png": +{ + "frame": {"x":281,"y":1272,"w":87,"h":87}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":9,"w":87,"h":87}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/buildings/belt_top.png": +{ + "frame": {"x":943,"y":816,"w":78,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":0,"w":78,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/buildings/constant_signal.png": +{ + "frame": {"x":949,"y":485,"w":70,"h":85}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":13,"y":0,"w":70,"h":85}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/buildings/cutter-quad.png": +{ + "frame": {"x":373,"y":203,"w":366,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":11,"y":0,"w":366,"h":96}, + "sourceSize": {"w":384,"h":96} +}, +"sprites/buildings/cutter.png": +{ + "frame": {"x":178,"y":574,"w":171,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":11,"y":0,"w":171,"h":96}, + "sourceSize": {"w":192,"h":96} +}, +"sprites/buildings/display.png": +{ + "frame": {"x":463,"y":1428,"w":84,"h":90}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":6,"y":6,"w":84,"h":90}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/buildings/filter.png": +{ + "frame": {"x":569,"y":403,"w":179,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":11,"y":0,"w":179,"h":96}, + "sourceSize": {"w":192,"h":96} +}, +"sprites/buildings/hub.png": +{ + "frame": {"x":3,"y":103,"w":366,"h":367}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":10,"w":366,"h":367}, + "sourceSize": {"w":384,"h":384} +}, +"sprites/buildings/lever.png": +{ + "frame": {"x":948,"y":574,"w":73,"h":76}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":12,"y":12,"w":73,"h":76}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/buildings/logic_gate-not.png": +{ + "frame": {"x":435,"y":903,"w":82,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":8,"y":0,"w":82,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/buildings/logic_gate-or.png": +{ + "frame": {"x":621,"y":923,"w":96,"h":83}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":0,"w":96,"h":83}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/buildings/logic_gate-transistor.png": +{ + "frame": {"x":621,"y":799,"w":68,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":0,"w":68,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/buildings/logic_gate-xor.png": +{ + "frame": {"x":339,"y":803,"w":96,"h":95}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":0,"w":96,"h":95}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/buildings/logic_gate.png": +{ + "frame": {"x":521,"y":899,"w":96,"h":88}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":0,"w":96,"h":88}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/buildings/miner-chainable.png": +{ + "frame": {"x":391,"y":1081,"w":91,"h":95}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":3,"y":0,"w":91,"h":95}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/buildings/miner.png": +{ + "frame": {"x":292,"y":1082,"w":91,"h":95}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":3,"y":0,"w":91,"h":95}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/buildings/mixer.png": +{ + "frame": {"x":361,"y":503,"w":174,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":0,"w":174,"h":96}, + "sourceSize": {"w":192,"h":96} +}, +"sprites/buildings/painter-double.png": +{ + "frame": {"x":759,"y":199,"w":192,"h":191}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":0,"w":192,"h":191}, + "sourceSize": {"w":192,"h":192} +}, +"sprites/buildings/painter-mirrored.png": +{ + "frame": {"x":373,"y":403,"w":192,"h":96}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":192,"h":96}, + "sourceSize": {"w":192,"h":96} +}, +"sprites/buildings/painter-quad.png": +{ + "frame": {"x":381,"y":3,"w":374,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":3,"y":0,"w":374,"h":96}, + "sourceSize": {"w":384,"h":96} +}, +"sprites/buildings/painter.png": +{ + "frame": {"x":752,"y":494,"w":192,"h":96}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":192,"h":96}, + "sourceSize": {"w":192,"h":96} +}, +"sprites/buildings/rotater-ccw.png": +{ + "frame": {"x":821,"y":1052,"w":95,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":1,"y":0,"w":95,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/buildings/rotater-fl.png": +{ + "frame": {"x":721,"y":1107,"w":95,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":0,"w":95,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/buildings/rotater.png": +{ + "frame": {"x":920,"y":1116,"w":95,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":1,"y":0,"w":95,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/buildings/splitter-compact-inverse.png": +{ + "frame": {"x":919,"y":1216,"w":94,"h":91}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":2,"w":94,"h":91}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/buildings/splitter-compact.png": +{ + "frame": {"x":198,"y":874,"w":93,"h":91}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":3,"y":2,"w":93,"h":91}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/buildings/splitter.png": +{ + "frame": {"x":353,"y":603,"w":171,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":11,"y":0,"w":171,"h":96}, + "sourceSize": {"w":192,"h":96} +}, +"sprites/buildings/stacker.png": +{ + "frame": {"x":539,"y":503,"w":174,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":9,"y":0,"w":174,"h":96}, + "sourceSize": {"w":192,"h":96} +}, +"sprites/buildings/trash-storage.png": +{ + "frame": {"x":736,"y":694,"w":166,"h":192}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":14,"y":0,"w":166,"h":192}, + "sourceSize": {"w":192,"h":192} +}, +"sprites/buildings/trash.png": +{ + "frame": {"x":729,"y":890,"w":96,"h":96}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":96,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/buildings/underground_belt_entry-tier2.png": +{ + "frame": {"x":295,"y":995,"w":92,"h":83}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":3,"y":13,"w":92,"h":83}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/buildings/underground_belt_entry.png": +{ + "frame": {"x":196,"y":1057,"w":92,"h":74}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":3,"y":22,"w":92,"h":74}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/buildings/underground_belt_exit-tier2.png": +{ + "frame": {"x":391,"y":1003,"w":92,"h":74}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":3,"y":0,"w":92,"h":74}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/buildings/underground_belt_exit.png": +{ + "frame": {"x":487,"y":1077,"w":92,"h":74}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":3,"y":0,"w":92,"h":74}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/buildings/wire-cross.png": +{ + "frame": {"x":829,"y":894,"w":96,"h":96}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":96,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/buildings/wire-split.png": +{ + "frame": {"x":621,"y":1010,"w":96,"h":54}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":42,"w":96,"h":54}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/buildings/wire-turn.png": +{ + "frame": {"x":955,"y":164,"w":54,"h":54}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":42,"y":42,"w":54,"h":54}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/buildings/wire.png": +{ + "frame": {"x":743,"y":103,"w":12,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":42,"y":0,"w":12,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/buildings/wire_tunnel-coating.png": +{ + "frame": {"x":921,"y":689,"w":21,"h":90}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":37,"y":3,"w":21,"h":90}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/buildings/wire_tunnel.png": +{ + "frame": {"x":3,"y":1127,"w":92,"h":90}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":3,"y":3,"w":92,"h":90}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/debug/acceptor_slot.png": +{ + "frame": {"x":1013,"y":164,"w":8,"h":8}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":8,"h":8}, + "sourceSize": {"w":8,"h":8} +}, +"sprites/debug/ejector_slot.png": +{ + "frame": {"x":1013,"y":176,"w":8,"h":8}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":8,"h":8}, + "sourceSize": {"w":8,"h":8} +}, +"sprites/misc/hub_direction_indicator.png": +{ + "frame": {"x":693,"y":851,"w":32,"h":32}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":32,"h":32}, + "sourceSize": {"w":32,"h":32} +}, +"sprites/misc/slot_bad_arrow.png": +{ + "frame": {"x":717,"y":605,"w":24,"h":24}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":1,"y":1,"w":24,"h":24}, + "sourceSize": {"w":26,"h":26} +}, +"sprites/misc/slot_good_arrow.png": +{ + "frame": {"x":717,"y":575,"w":24,"h":26}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":1,"y":0,"w":24,"h":26}, + "sourceSize": {"w":26,"h":26} +}, +"sprites/misc/storage_overlay.png": +{ + "frame": {"x":955,"y":71,"w":60,"h":30}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":60,"h":30}, + "sourceSize": {"w":60,"h":30} +}, +"sprites/misc/waypoint.png": +{ + "frame": {"x":717,"y":539,"w":26,"h":32}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":3,"y":0,"w":26,"h":32}, + "sourceSize": {"w":32,"h":32} +}, +"sprites/wires/boolean_false.png": +{ + "frame": {"x":717,"y":633,"w":21,"h":28}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":6,"y":3,"w":21,"h":28}, + "sourceSize": {"w":32,"h":32} +}, +"sprites/wires/boolean_true.png": +{ + "frame": {"x":717,"y":665,"w":15,"h":28}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":7,"y":3,"w":15,"h":28}, + "sourceSize": {"w":32,"h":32} +}, +"sprites/wires/display/blue.png": +{ + "frame": {"x":699,"y":703,"w":33,"h":33}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":33,"h":33}, + "sourceSize": {"w":33,"h":33} +}, +"sprites/wires/display/cyan.png": +{ + "frame": {"x":699,"y":740,"w":33,"h":33}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":33,"h":33}, + "sourceSize": {"w":33,"h":33} +}, +"sprites/wires/display/green.png": +{ + "frame": {"x":699,"y":777,"w":33,"h":33}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":33,"h":33}, + "sourceSize": {"w":33,"h":33} +}, +"sprites/wires/display/purple.png": +{ + "frame": {"x":906,"y":783,"w":33,"h":33}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":33,"h":33}, + "sourceSize": {"w":33,"h":33} +}, +"sprites/wires/display/red.png": +{ + "frame": {"x":906,"y":820,"w":33,"h":33}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":33,"h":33}, + "sourceSize": {"w":33,"h":33} +}, +"sprites/wires/display/white.png": +{ + "frame": {"x":906,"y":857,"w":33,"h":33}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":33,"h":33}, + "sourceSize": {"w":33,"h":33} +}, +"sprites/wires/display/yellow.png": +{ + "frame": {"x":693,"y":814,"w":33,"h":33}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":33,"h":33}, + "sourceSize": {"w":33,"h":33} +}, +"sprites/wires/lever_on.png": +{ + "frame": {"x":948,"y":654,"w":73,"h":76}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":12,"y":12,"w":73,"h":76}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/wires/logical_acceptor.png": +{ + "frame": {"x":303,"y":674,"w":42,"h":71}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":28,"y":0,"w":42,"h":71}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/wires/logical_ejector.png": +{ + "frame": {"x":303,"y":749,"w":41,"h":45}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":29,"y":0,"w":41,"h":45}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/wires/network_conflict.png": +{ + "frame": {"x":303,"y":798,"w":32,"h":30}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":1,"w":32,"h":30}, + "sourceSize": {"w":32,"h":32} +}, +"sprites/wires/network_empty.png": +{ + "frame": {"x":717,"y":503,"w":28,"h":32}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":3,"y":0,"w":28,"h":32}, + "sourceSize": {"w":32,"h":32} +}, +"sprites/wires/overlay_tile.png": +{ + "frame": {"x":955,"y":3,"w":64,"h":64}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":64,"h":64}, + "sourceSize": {"w":64,"h":64} +}, +"sprites/wires/sets/color_cross.png": +{ + "frame": {"x":3,"y":774,"w":96,"h":96}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":96,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/wires/sets/color_forward.png": +{ + "frame": {"x":743,"y":203,"w":12,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":42,"y":0,"w":12,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/wires/sets/color_split.png": +{ + "frame": {"x":821,"y":994,"w":96,"h":54}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":42,"w":96,"h":54}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/wires/sets/color_turn.png": +{ + "frame": {"x":955,"y":222,"w":54,"h":54}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":42,"y":42,"w":54,"h":54}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/wires/sets/conflict_cross.png": +{ + "frame": {"x":103,"y":774,"w":96,"h":96}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":96,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/wires/sets/conflict_forward.png": +{ + "frame": {"x":303,"y":832,"w":12,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":42,"y":0,"w":12,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/wires/sets/conflict_split.png": +{ + "frame": {"x":721,"y":1049,"w":96,"h":54}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":42,"w":96,"h":54}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/wires/sets/conflict_turn.png": +{ + "frame": {"x":955,"y":280,"w":54,"h":54}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":42,"y":42,"w":54,"h":54}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/wires/sets/regular_cross.png": +{ + "frame": {"x":829,"y":894,"w":96,"h":96}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":96,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/wires/sets/regular_forward.png": +{ + "frame": {"x":743,"y":103,"w":12,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":42,"y":0,"w":12,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/wires/sets/regular_split.png": +{ + "frame": {"x":621,"y":1010,"w":96,"h":54}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":42,"w":96,"h":54}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/wires/sets/regular_turn.png": +{ + "frame": {"x":955,"y":164,"w":54,"h":54}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":42,"y":42,"w":54,"h":54}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/wires/sets/shape_cross.png": +{ + "frame": {"x":203,"y":774,"w":96,"h":96}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":96,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/wires/sets/shape_forward.png": +{ + "frame": {"x":319,"y":832,"w":12,"h":96}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":42,"y":0,"w":12,"h":96}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/wires/sets/shape_split.png": +{ + "frame": {"x":621,"y":1068,"w":96,"h":54}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":0,"y":42,"w":96,"h":54}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/wires/sets/shape_turn.png": +{ + "frame": {"x":955,"y":338,"w":54,"h":54}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":42,"y":42,"w":54,"h":54}, + "sourceSize": {"w":96,"h":96} +}, +"sprites/wires/wires_preview.png": +{ + "frame": {"x":693,"y":887,"w":32,"h":32}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":32,"h":32}, + "sourceSize": {"w":32,"h":32} +}}, +"meta": { + "app": "https://www.codeandweb.com/texturepacker", + "version": "1.0", + "image": "atlas0_mq.png", + "format": "RGBA8888", + "size": {"w":1024,"h":2048}, + "scale": "0.5", + "smartupdate": "$TexturePacker:SmartUpdate:876f0711b44fa7bbab8d2539e9651766:ff01f850e086ef31c114b036c3a32e6d:908b89f5ca8ff73e331a35a3b14d0604$" +} +} diff --git a/res_built/atlas/atlas0_mq.png b/res_built/atlas/atlas0_mq.png new file mode 100644 index 00000000..e05b73e3 Binary files /dev/null and b/res_built/atlas/atlas0_mq.png differ diff --git a/res_raw/atlas.tps b/res_raw/atlas.tps index a5a6abbd..28809d93 100644 --- a/res_raw/atlas.tps +++ b/res_raw/atlas.tps @@ -7,28 +7,11 @@ 5.4.0 autoSDSettings - - scale - 1 - extension - _100 - spriteFilter - - acceptFractionalValues - - maxTextureSize - - width - 4096 - height - 4096 - - scale 0.75 extension - _75 + _hq spriteFilter acceptFractionalValues @@ -45,7 +28,7 @@ scale 0.5 extension - _50 + _mq spriteFilter acceptFractionalValues @@ -62,7 +45,7 @@ scale 0.25 extension - _25 + _lq spriteFilter acceptFractionalValues @@ -70,26 +53,9 @@ maxTextureSize width - 1024 + 2048 height - 1024 - - - - scale - 0.1 - extension - _10 - spriteFilter - - acceptFractionalValues - - maxTextureSize - - width - -1 - height - -1 + 2048 @@ -174,7 +140,7 @@ freeSizeMode Best sizeConstraints - AnySize + POT forceSquared maxRects @@ -249,17 +215,104 @@ individualSpriteSettings - sprites/belt/forward_0.png - sprites/belt/forward_1.png - sprites/belt/forward_2.png - sprites/buildings/miner.png - sprites/buildings/rotater.png - sprites/buildings/trash.png - sprites/misc/wires_overlay_tile.png - sprites/wires/pin_negative_accept.png - sprites/wires/pin_negative_eject.png - sprites/wires/pin_positive_accept.png - sprites/wires/pin_positive_eject.png + sprites/belt/built/forward_0.png + sprites/belt/built/forward_1.png + sprites/belt/built/forward_10.png + sprites/belt/built/forward_11.png + sprites/belt/built/forward_12.png + sprites/belt/built/forward_13.png + sprites/belt/built/forward_2.png + sprites/belt/built/forward_3.png + sprites/belt/built/forward_4.png + sprites/belt/built/forward_5.png + sprites/belt/built/forward_6.png + sprites/belt/built/forward_7.png + sprites/belt/built/forward_8.png + sprites/belt/built/forward_9.png + sprites/belt/built/left_0.png + sprites/belt/built/left_1.png + sprites/belt/built/left_10.png + sprites/belt/built/left_11.png + sprites/belt/built/left_12.png + sprites/belt/built/left_13.png + sprites/belt/built/left_2.png + sprites/belt/built/left_3.png + sprites/belt/built/left_4.png + sprites/belt/built/left_5.png + sprites/belt/built/left_6.png + sprites/belt/built/left_7.png + sprites/belt/built/left_8.png + sprites/belt/built/left_9.png + sprites/belt/built/right_0.png + sprites/belt/built/right_1.png + sprites/belt/built/right_10.png + sprites/belt/built/right_11.png + sprites/belt/built/right_12.png + sprites/belt/built/right_13.png + sprites/belt/built/right_2.png + sprites/belt/built/right_3.png + sprites/belt/built/right_4.png + sprites/belt/built/right_5.png + sprites/belt/built/right_6.png + sprites/belt/built/right_7.png + sprites/belt/built/right_8.png + sprites/belt/built/right_9.png + sprites/blueprints/constant_signal.png + sprites/blueprints/display.png + sprites/blueprints/lever.png + sprites/blueprints/logic_gate-not.png + sprites/blueprints/logic_gate-or.png + sprites/blueprints/logic_gate-transistor.png + sprites/blueprints/logic_gate-xor.png + sprites/blueprints/logic_gate.png + sprites/blueprints/miner-chainable.png + sprites/blueprints/miner.png + sprites/blueprints/rotater-ccw.png + sprites/blueprints/rotater-fl.png + sprites/blueprints/rotater.png + sprites/blueprints/splitter-compact-inverse.png + sprites/blueprints/splitter-compact.png + sprites/blueprints/trash.png + sprites/blueprints/underground_belt_entry-tier2.png + sprites/blueprints/underground_belt_entry.png + sprites/blueprints/underground_belt_exit-tier2.png + sprites/blueprints/underground_belt_exit.png + sprites/blueprints/wire_tunnel.png + sprites/buildings/constant_signal.png + sprites/buildings/display.png + sprites/buildings/lever.png + sprites/buildings/logic_gate-not.png + sprites/buildings/logic_gate-or.png + sprites/buildings/logic_gate-transistor.png + sprites/buildings/logic_gate-xor.png + sprites/buildings/logic_gate.png + sprites/buildings/miner-chainable.png + sprites/buildings/rotater-ccw.png + sprites/buildings/rotater-fl.png + sprites/buildings/splitter-compact-inverse.png + sprites/buildings/splitter-compact.png + sprites/buildings/underground_belt_entry-tier2.png + sprites/buildings/underground_belt_entry.png + sprites/buildings/underground_belt_exit-tier2.png + sprites/buildings/underground_belt_exit.png + sprites/buildings/wire_tunnel.png + sprites/wires/lever_on.png + sprites/wires/sets/color_cross.png + sprites/wires/sets/color_forward.png + sprites/wires/sets/color_split.png + sprites/wires/sets/color_turn.png + sprites/wires/sets/conflict_cross.png + sprites/wires/sets/conflict_forward.png + sprites/wires/sets/conflict_split.png + sprites/wires/sets/conflict_turn.png + sprites/wires/sets/regular_cross.png + sprites/wires/sets/regular_forward.png + sprites/wires/sets/regular_split.png + sprites/wires/sets/regular_turn.png + sprites/wires/sets/shape_cross.png + sprites/wires/sets/shape_forward.png + sprites/wires/sets/shape_split.png + sprites/wires/sets/shape_turn.png pivotPoint 0.5,0.5 @@ -268,109 +321,26 @@ scale9Enabled scale9Borders - 32,32,64,64 + 48,48,96,96 scale9Paddings - 32,32,64,64 + 48,48,96,96 scale9FromFile - sprites/belt/forward_10.png - sprites/belt/forward_11.png - sprites/belt/forward_12.png - sprites/belt/forward_13.png - sprites/belt/forward_14.png - sprites/belt/forward_15.png - sprites/belt/forward_16.png - sprites/belt/forward_17.png - sprites/belt/forward_18.png - sprites/belt/forward_19.png - sprites/belt/forward_20.png - sprites/belt/forward_21.png - sprites/belt/forward_22.png - sprites/belt/forward_23.png - sprites/belt/forward_24.png - sprites/belt/forward_25.png - sprites/belt/forward_26.png - sprites/belt/forward_27.png - sprites/belt/forward_3.png - sprites/belt/forward_4.png - sprites/belt/forward_5.png - sprites/belt/forward_6.png - sprites/belt/forward_7.png - sprites/belt/forward_8.png - sprites/belt/forward_9.png - sprites/belt/left_0.png - sprites/belt/left_1.png - sprites/belt/left_10.png - sprites/belt/left_11.png - sprites/belt/left_12.png - sprites/belt/left_13.png - sprites/belt/left_14.png - sprites/belt/left_15.png - sprites/belt/left_16.png - sprites/belt/left_17.png - sprites/belt/left_18.png - sprites/belt/left_19.png - sprites/belt/left_2.png - sprites/belt/left_20.png - sprites/belt/left_21.png - sprites/belt/left_22.png - sprites/belt/left_23.png - sprites/belt/left_24.png - sprites/belt/left_25.png - sprites/belt/left_26.png - sprites/belt/left_27.png - sprites/belt/left_3.png - sprites/belt/left_4.png - sprites/belt/left_5.png - sprites/belt/left_6.png - sprites/belt/left_7.png - sprites/belt/left_8.png - sprites/belt/left_9.png - sprites/belt/right_0.png - sprites/belt/right_1.png - sprites/belt/right_10.png - sprites/belt/right_11.png - sprites/belt/right_12.png - sprites/belt/right_13.png - sprites/belt/right_14.png - sprites/belt/right_15.png - sprites/belt/right_16.png - sprites/belt/right_17.png - sprites/belt/right_18.png - sprites/belt/right_19.png - sprites/belt/right_2.png - sprites/belt/right_20.png - sprites/belt/right_21.png - sprites/belt/right_22.png - sprites/belt/right_23.png - sprites/belt/right_24.png - sprites/belt/right_25.png - sprites/belt/right_26.png - sprites/belt/right_27.png - sprites/belt/right_3.png - sprites/belt/right_4.png - sprites/belt/right_5.png - sprites/belt/right_6.png - sprites/belt/right_7.png - sprites/belt/right_8.png - sprites/belt/right_9.png sprites/blueprints/belt_left.png sprites/blueprints/belt_right.png sprites/blueprints/belt_top.png - sprites/blueprints/wire_crossings-merger.png - sprites/blueprints/wire_crossings.png - sprites/blueprints/wire_left.png - sprites/blueprints/wire_right.png - sprites/blueprints/wire_top.png + sprites/blueprints/wire-cross.png + sprites/blueprints/wire-split.png + sprites/blueprints/wire-turn.png + sprites/blueprints/wire.png sprites/buildings/belt_left.png sprites/buildings/belt_right.png sprites/buildings/belt_top.png - sprites/buildings/wire_crossings-merger.png - sprites/buildings/wire_crossings.png - sprites/buildings/wire_left.png - sprites/buildings/wire_right.png - sprites/buildings/wire_top.png + sprites/buildings/wire-cross.png + sprites/buildings/wire-split.png + sprites/buildings/wire-turn.png + sprites/buildings/wire.png pivotPoint 0.5,0.5 @@ -385,28 +355,6 @@ scale9FromFile - sprites/blueprints/advanced_processor.png - sprites/blueprints/energy_generator.png - sprites/blueprints/painter-double.png - sprites/blueprints/trash-storage.png - sprites/buildings/advanced_processor.png - sprites/buildings/energy_generator.png - sprites/buildings/painter-double.png - sprites/misc/energy_generator_overlay.png - - pivotPoint - 0.5,0.5 - spriteScale - 1 - scale9Enabled - - scale9Borders - 96,96,192,192 - scale9Paddings - 96,96,192,192 - scale9FromFile - - sprites/blueprints/cutter-quad.png sprites/blueprints/painter-quad.png sprites/buildings/cutter-quad.png @@ -426,11 +374,13 @@ sprites/blueprints/cutter.png + sprites/blueprints/filter.png sprites/blueprints/mixer.png sprites/blueprints/painter-mirrored.png sprites/blueprints/painter.png sprites/blueprints/splitter.png sprites/blueprints/stacker.png + sprites/buildings/filter.png sprites/buildings/painter-mirrored.png pivotPoint @@ -446,27 +396,9 @@ scale9FromFile - sprites/blueprints/miner-chainable.png - sprites/blueprints/miner.png - sprites/blueprints/rotater-ccw.png - sprites/blueprints/rotater-fl.png - sprites/blueprints/rotater.png - sprites/blueprints/splitter-compact-inverse.png - sprites/blueprints/splitter-compact.png - sprites/blueprints/trash.png - sprites/blueprints/underground_belt_entry-tier2.png - sprites/blueprints/underground_belt_entry.png - sprites/blueprints/underground_belt_exit-tier2.png - sprites/blueprints/underground_belt_exit.png - sprites/buildings/miner-chainable.png - sprites/buildings/rotater-ccw.png - sprites/buildings/rotater-fl.png - sprites/buildings/splitter-compact-inverse.png - sprites/buildings/splitter-compact.png - sprites/buildings/underground_belt_entry-tier2.png - sprites/buildings/underground_belt_entry.png - sprites/buildings/underground_belt_exit-tier2.png - sprites/buildings/underground_belt_exit.png + sprites/blueprints/painter-double.png + sprites/blueprints/trash-storage.png + sprites/buildings/painter-double.png pivotPoint 0.5,0.5 @@ -475,9 +407,9 @@ scale9Enabled scale9Borders - 48,48,96,96 + 96,96,192,192 scale9Paddings - 48,48,96,96 + 96,96,192,192 scale9FromFile @@ -515,6 +447,26 @@ scale9FromFile + sprites/buildings/miner.png + sprites/buildings/rotater.png + sprites/buildings/trash.png + sprites/wires/logical_acceptor.png + sprites/wires/logical_ejector.png + sprites/wires/overlay_tile.png + + pivotPoint + 0.5,0.5 + spriteScale + 1 + scale9Enabled + + scale9Borders + 32,32,64,64 + scale9Paddings + 32,32,64,64 + scale9FromFile + + sprites/buildings/trash-storage.png pivotPoint @@ -532,9 +484,6 @@ sprites/debug/acceptor_slot.png sprites/debug/ejector_slot.png - sprites/map_overview/belt_forward.png - sprites/map_overview/belt_left.png - sprites/map_overview/belt_right.png sprites/misc/hub_direction_indicator.png sprites/misc/waypoint.png @@ -551,7 +500,6 @@ scale9FromFile - sprites/misc/deletion_marker.png sprites/misc/slot_bad_arrow.png sprites/misc/slot_good_arrow.png @@ -568,21 +516,6 @@ scale9FromFile - sprites/misc/lock_direction_indicator.png - - pivotPoint - 0.5,0.5 - spriteScale - 1 - scale9Enabled - - scale9Borders - 12,12,24,24 - scale9Paddings - 12,12,24,24 - scale9FromFile - - sprites/misc/storage_overlay.png pivotPoint @@ -598,13 +531,9 @@ scale9FromFile - sprites/wires/battery_empty.png - sprites/wires/battery_full.png - sprites/wires/battery_low.png - sprites/wires/battery_medium.png - sprites/wires/negative_energy.png - sprites/wires/positive_energy.png - sprites/wires/waste_piled.png + sprites/wires/boolean_false.png + sprites/wires/boolean_true.png + sprites/wires/wires_preview.png pivotPoint 0.5,0.5 @@ -619,6 +548,27 @@ scale9FromFile + sprites/wires/display/blue.png + sprites/wires/display/cyan.png + sprites/wires/display/green.png + sprites/wires/display/purple.png + sprites/wires/display/red.png + sprites/wires/display/white.png + sprites/wires/display/yellow.png + + pivotPoint + 0.5,0.5 + spriteScale + 1 + scale9Enabled + + scale9Borders + 11,11,22,22 + scale9Paddings + 11,11,22,22 + scale9FromFile + + fileList diff --git a/res_raw/sounds/music/theme-full.mp3 b/res_raw/sounds/music/theme-full.mp3 new file mode 100644 index 00000000..be4f3a7b --- /dev/null +++ b/res_raw/sounds/music/theme-full.mp3 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4e6959df75e915fb1a8d55e3d0ab750349b27276788ded63178f2a117c2edcf5 +size 79441572 diff --git a/res_raw/sounds/music/theme.wav b/res_raw/sounds/music/theme-short.wav similarity index 100% rename from res_raw/sounds/music/theme.wav rename to res_raw/sounds/music/theme-short.wav diff --git a/res_raw/sprites/belt/built/forward_0.png b/res_raw/sprites/belt/built/forward_0.png new file mode 100644 index 00000000..67b47330 Binary files /dev/null and b/res_raw/sprites/belt/built/forward_0.png differ diff --git a/res_raw/sprites/belt/built/forward_1.png b/res_raw/sprites/belt/built/forward_1.png new file mode 100644 index 00000000..6e765f42 Binary files /dev/null and b/res_raw/sprites/belt/built/forward_1.png differ diff --git a/res_raw/sprites/belt/built/forward_10.png b/res_raw/sprites/belt/built/forward_10.png new file mode 100644 index 00000000..cb427231 Binary files /dev/null and b/res_raw/sprites/belt/built/forward_10.png differ diff --git a/res_raw/sprites/belt/built/forward_11.png b/res_raw/sprites/belt/built/forward_11.png new file mode 100644 index 00000000..b44a62ad Binary files /dev/null and b/res_raw/sprites/belt/built/forward_11.png differ diff --git a/res_raw/sprites/belt/built/forward_12.png b/res_raw/sprites/belt/built/forward_12.png new file mode 100644 index 00000000..b9c74030 Binary files /dev/null and b/res_raw/sprites/belt/built/forward_12.png differ diff --git a/res_raw/sprites/belt/built/forward_13.png b/res_raw/sprites/belt/built/forward_13.png new file mode 100644 index 00000000..29c64d5f Binary files /dev/null and b/res_raw/sprites/belt/built/forward_13.png differ diff --git a/res_raw/sprites/belt/built/forward_2.png b/res_raw/sprites/belt/built/forward_2.png new file mode 100644 index 00000000..e1bf428e Binary files /dev/null and b/res_raw/sprites/belt/built/forward_2.png differ diff --git a/res_raw/sprites/belt/built/forward_3.png b/res_raw/sprites/belt/built/forward_3.png new file mode 100644 index 00000000..11907e19 Binary files /dev/null and b/res_raw/sprites/belt/built/forward_3.png differ diff --git a/res_raw/sprites/belt/built/forward_4.png b/res_raw/sprites/belt/built/forward_4.png new file mode 100644 index 00000000..7b26e823 Binary files /dev/null and b/res_raw/sprites/belt/built/forward_4.png differ diff --git a/res_raw/sprites/belt/built/forward_5.png b/res_raw/sprites/belt/built/forward_5.png new file mode 100644 index 00000000..481f9362 Binary files /dev/null and b/res_raw/sprites/belt/built/forward_5.png differ diff --git a/res_raw/sprites/belt/built/forward_6.png b/res_raw/sprites/belt/built/forward_6.png new file mode 100644 index 00000000..95bc984c Binary files /dev/null and b/res_raw/sprites/belt/built/forward_6.png differ diff --git a/res_raw/sprites/belt/built/forward_7.png b/res_raw/sprites/belt/built/forward_7.png new file mode 100644 index 00000000..099368f1 Binary files /dev/null and b/res_raw/sprites/belt/built/forward_7.png differ diff --git a/res_raw/sprites/belt/built/forward_8.png b/res_raw/sprites/belt/built/forward_8.png new file mode 100644 index 00000000..d48f8560 Binary files /dev/null and b/res_raw/sprites/belt/built/forward_8.png differ diff --git a/res_raw/sprites/belt/built/forward_9.png b/res_raw/sprites/belt/built/forward_9.png new file mode 100644 index 00000000..34c41082 Binary files /dev/null and b/res_raw/sprites/belt/built/forward_9.png differ diff --git a/res_raw/sprites/belt/built/left_0.png b/res_raw/sprites/belt/built/left_0.png new file mode 100644 index 00000000..8575be67 Binary files /dev/null and b/res_raw/sprites/belt/built/left_0.png differ diff --git a/res_raw/sprites/belt/built/left_1.png b/res_raw/sprites/belt/built/left_1.png new file mode 100644 index 00000000..cfe14b9a Binary files /dev/null and b/res_raw/sprites/belt/built/left_1.png differ diff --git a/res_raw/sprites/belt/built/left_10.png b/res_raw/sprites/belt/built/left_10.png new file mode 100644 index 00000000..c1c82da1 Binary files /dev/null and b/res_raw/sprites/belt/built/left_10.png differ diff --git a/res_raw/sprites/belt/built/left_11.png b/res_raw/sprites/belt/built/left_11.png new file mode 100644 index 00000000..3a75ab79 Binary files /dev/null and b/res_raw/sprites/belt/built/left_11.png differ diff --git a/res_raw/sprites/belt/built/left_12.png b/res_raw/sprites/belt/built/left_12.png new file mode 100644 index 00000000..5a8abc35 Binary files /dev/null and b/res_raw/sprites/belt/built/left_12.png differ diff --git a/res_raw/sprites/belt/built/left_13.png b/res_raw/sprites/belt/built/left_13.png new file mode 100644 index 00000000..ea072a4d Binary files /dev/null and b/res_raw/sprites/belt/built/left_13.png differ diff --git a/res_raw/sprites/belt/built/left_2.png b/res_raw/sprites/belt/built/left_2.png new file mode 100644 index 00000000..263da5aa Binary files /dev/null and b/res_raw/sprites/belt/built/left_2.png differ diff --git a/res_raw/sprites/belt/built/left_3.png b/res_raw/sprites/belt/built/left_3.png new file mode 100644 index 00000000..92441c6e Binary files /dev/null and b/res_raw/sprites/belt/built/left_3.png differ diff --git a/res_raw/sprites/belt/built/left_4.png b/res_raw/sprites/belt/built/left_4.png new file mode 100644 index 00000000..816373da Binary files /dev/null and b/res_raw/sprites/belt/built/left_4.png differ diff --git a/res_raw/sprites/belt/built/left_5.png b/res_raw/sprites/belt/built/left_5.png new file mode 100644 index 00000000..d851b7db Binary files /dev/null and b/res_raw/sprites/belt/built/left_5.png differ diff --git a/res_raw/sprites/belt/built/left_6.png b/res_raw/sprites/belt/built/left_6.png new file mode 100644 index 00000000..bd126a41 Binary files /dev/null and b/res_raw/sprites/belt/built/left_6.png differ diff --git a/res_raw/sprites/belt/built/left_7.png b/res_raw/sprites/belt/built/left_7.png new file mode 100644 index 00000000..6e3de943 Binary files /dev/null and b/res_raw/sprites/belt/built/left_7.png differ diff --git a/res_raw/sprites/belt/built/left_8.png b/res_raw/sprites/belt/built/left_8.png new file mode 100644 index 00000000..ee95dc92 Binary files /dev/null and b/res_raw/sprites/belt/built/left_8.png differ diff --git a/res_raw/sprites/belt/built/left_9.png b/res_raw/sprites/belt/built/left_9.png new file mode 100644 index 00000000..7334bdf3 Binary files /dev/null and b/res_raw/sprites/belt/built/left_9.png differ diff --git a/res_raw/sprites/belt/built/right_0.png b/res_raw/sprites/belt/built/right_0.png new file mode 100644 index 00000000..51cb8c7c Binary files /dev/null and b/res_raw/sprites/belt/built/right_0.png differ diff --git a/res_raw/sprites/belt/built/right_1.png b/res_raw/sprites/belt/built/right_1.png new file mode 100644 index 00000000..199e5d1d Binary files /dev/null and b/res_raw/sprites/belt/built/right_1.png differ diff --git a/res_raw/sprites/belt/built/right_10.png b/res_raw/sprites/belt/built/right_10.png new file mode 100644 index 00000000..ca6e117d Binary files /dev/null and b/res_raw/sprites/belt/built/right_10.png differ diff --git a/res_raw/sprites/belt/built/right_11.png b/res_raw/sprites/belt/built/right_11.png new file mode 100644 index 00000000..19596a73 Binary files /dev/null and b/res_raw/sprites/belt/built/right_11.png differ diff --git a/res_raw/sprites/belt/built/right_12.png b/res_raw/sprites/belt/built/right_12.png new file mode 100644 index 00000000..0299e22d Binary files /dev/null and b/res_raw/sprites/belt/built/right_12.png differ diff --git a/res_raw/sprites/belt/built/right_13.png b/res_raw/sprites/belt/built/right_13.png new file mode 100644 index 00000000..e7e25ba7 Binary files /dev/null and b/res_raw/sprites/belt/built/right_13.png differ diff --git a/res_raw/sprites/belt/built/right_2.png b/res_raw/sprites/belt/built/right_2.png new file mode 100644 index 00000000..428649bb Binary files /dev/null and b/res_raw/sprites/belt/built/right_2.png differ diff --git a/res_raw/sprites/belt/built/right_3.png b/res_raw/sprites/belt/built/right_3.png new file mode 100644 index 00000000..91d419a4 Binary files /dev/null and b/res_raw/sprites/belt/built/right_3.png differ diff --git a/res_raw/sprites/belt/built/right_4.png b/res_raw/sprites/belt/built/right_4.png new file mode 100644 index 00000000..ff0782f3 Binary files /dev/null and b/res_raw/sprites/belt/built/right_4.png differ diff --git a/res_raw/sprites/belt/built/right_5.png b/res_raw/sprites/belt/built/right_5.png new file mode 100644 index 00000000..fd362c5f Binary files /dev/null and b/res_raw/sprites/belt/built/right_5.png differ diff --git a/res_raw/sprites/belt/built/right_6.png b/res_raw/sprites/belt/built/right_6.png new file mode 100644 index 00000000..f542f805 Binary files /dev/null and b/res_raw/sprites/belt/built/right_6.png differ diff --git a/res_raw/sprites/belt/built/right_7.png b/res_raw/sprites/belt/built/right_7.png new file mode 100644 index 00000000..521c110b Binary files /dev/null and b/res_raw/sprites/belt/built/right_7.png differ diff --git a/res_raw/sprites/belt/built/right_8.png b/res_raw/sprites/belt/built/right_8.png new file mode 100644 index 00000000..2591f537 Binary files /dev/null and b/res_raw/sprites/belt/built/right_8.png differ diff --git a/res_raw/sprites/belt/built/right_9.png b/res_raw/sprites/belt/built/right_9.png new file mode 100644 index 00000000..da54ea01 Binary files /dev/null and b/res_raw/sprites/belt/built/right_9.png differ diff --git a/res_raw/sprites/belt/forward_0.png b/res_raw/sprites/belt/forward_0.png deleted file mode 100644 index cf5b20d7..00000000 Binary files a/res_raw/sprites/belt/forward_0.png and /dev/null differ diff --git a/res_raw/sprites/belt/forward_1.png b/res_raw/sprites/belt/forward_1.png deleted file mode 100644 index 44e5b8c8..00000000 Binary files a/res_raw/sprites/belt/forward_1.png and /dev/null differ diff --git a/res_raw/sprites/belt/forward_10.png b/res_raw/sprites/belt/forward_10.png deleted file mode 100644 index d599463d..00000000 Binary files a/res_raw/sprites/belt/forward_10.png and /dev/null differ diff --git a/res_raw/sprites/belt/forward_11.png b/res_raw/sprites/belt/forward_11.png deleted file mode 100644 index 69fff65c..00000000 Binary files a/res_raw/sprites/belt/forward_11.png and /dev/null differ diff --git a/res_raw/sprites/belt/forward_12.png b/res_raw/sprites/belt/forward_12.png deleted file mode 100644 index a278e6f0..00000000 Binary files a/res_raw/sprites/belt/forward_12.png and /dev/null differ diff --git a/res_raw/sprites/belt/forward_13.png b/res_raw/sprites/belt/forward_13.png deleted file mode 100644 index 13630f42..00000000 Binary files a/res_raw/sprites/belt/forward_13.png and /dev/null differ diff --git a/res_raw/sprites/belt/forward_14.png b/res_raw/sprites/belt/forward_14.png deleted file mode 100644 index 1c6bdfb8..00000000 Binary files a/res_raw/sprites/belt/forward_14.png and /dev/null differ diff --git a/res_raw/sprites/belt/forward_15.png b/res_raw/sprites/belt/forward_15.png deleted file mode 100644 index be3daa82..00000000 Binary files a/res_raw/sprites/belt/forward_15.png and /dev/null differ diff --git a/res_raw/sprites/belt/forward_16.png b/res_raw/sprites/belt/forward_16.png deleted file mode 100644 index 7b9c9dcf..00000000 Binary files a/res_raw/sprites/belt/forward_16.png and /dev/null differ diff --git a/res_raw/sprites/belt/forward_17.png b/res_raw/sprites/belt/forward_17.png deleted file mode 100644 index cc37d11a..00000000 Binary files a/res_raw/sprites/belt/forward_17.png and /dev/null differ diff --git a/res_raw/sprites/belt/forward_18.png b/res_raw/sprites/belt/forward_18.png deleted file mode 100644 index 7a6460f3..00000000 Binary files a/res_raw/sprites/belt/forward_18.png and /dev/null differ diff --git a/res_raw/sprites/belt/forward_19.png b/res_raw/sprites/belt/forward_19.png deleted file mode 100644 index c18e2773..00000000 Binary files a/res_raw/sprites/belt/forward_19.png and /dev/null differ diff --git a/res_raw/sprites/belt/forward_2.png b/res_raw/sprites/belt/forward_2.png deleted file mode 100644 index 5a621fbb..00000000 Binary files a/res_raw/sprites/belt/forward_2.png and /dev/null differ diff --git a/res_raw/sprites/belt/forward_20.png b/res_raw/sprites/belt/forward_20.png deleted file mode 100644 index ac3f50db..00000000 Binary files a/res_raw/sprites/belt/forward_20.png and /dev/null differ diff --git a/res_raw/sprites/belt/forward_21.png b/res_raw/sprites/belt/forward_21.png deleted file mode 100644 index 67d63a4a..00000000 Binary files a/res_raw/sprites/belt/forward_21.png and /dev/null differ diff --git a/res_raw/sprites/belt/forward_22.png b/res_raw/sprites/belt/forward_22.png deleted file mode 100644 index f20ec8d3..00000000 Binary files a/res_raw/sprites/belt/forward_22.png and /dev/null differ diff --git a/res_raw/sprites/belt/forward_23.png b/res_raw/sprites/belt/forward_23.png deleted file mode 100644 index daa5d1d8..00000000 Binary files a/res_raw/sprites/belt/forward_23.png and /dev/null differ diff --git a/res_raw/sprites/belt/forward_24.png b/res_raw/sprites/belt/forward_24.png deleted file mode 100644 index c21bc67d..00000000 Binary files a/res_raw/sprites/belt/forward_24.png and /dev/null differ diff --git a/res_raw/sprites/belt/forward_25.png b/res_raw/sprites/belt/forward_25.png deleted file mode 100644 index 4e603e43..00000000 Binary files a/res_raw/sprites/belt/forward_25.png and /dev/null differ diff --git a/res_raw/sprites/belt/forward_26.png b/res_raw/sprites/belt/forward_26.png deleted file mode 100644 index 55ae0c96..00000000 Binary files a/res_raw/sprites/belt/forward_26.png and /dev/null differ diff --git a/res_raw/sprites/belt/forward_27.png b/res_raw/sprites/belt/forward_27.png deleted file mode 100644 index 816ac1c6..00000000 Binary files a/res_raw/sprites/belt/forward_27.png and /dev/null differ diff --git a/res_raw/sprites/belt/forward_3.png b/res_raw/sprites/belt/forward_3.png deleted file mode 100644 index cf2ef011..00000000 Binary files a/res_raw/sprites/belt/forward_3.png and /dev/null differ diff --git a/res_raw/sprites/belt/forward_4.png b/res_raw/sprites/belt/forward_4.png deleted file mode 100644 index b06fb99f..00000000 Binary files a/res_raw/sprites/belt/forward_4.png and /dev/null differ diff --git a/res_raw/sprites/belt/forward_5.png b/res_raw/sprites/belt/forward_5.png deleted file mode 100644 index 79354fbb..00000000 Binary files a/res_raw/sprites/belt/forward_5.png and /dev/null differ diff --git a/res_raw/sprites/belt/forward_6.png b/res_raw/sprites/belt/forward_6.png deleted file mode 100644 index 3df44015..00000000 Binary files a/res_raw/sprites/belt/forward_6.png and /dev/null differ diff --git a/res_raw/sprites/belt/forward_7.png b/res_raw/sprites/belt/forward_7.png deleted file mode 100644 index 72251706..00000000 Binary files a/res_raw/sprites/belt/forward_7.png and /dev/null differ diff --git a/res_raw/sprites/belt/forward_8.png b/res_raw/sprites/belt/forward_8.png deleted file mode 100644 index ad28047a..00000000 Binary files a/res_raw/sprites/belt/forward_8.png and /dev/null differ diff --git a/res_raw/sprites/belt/forward_9.png b/res_raw/sprites/belt/forward_9.png deleted file mode 100644 index daae565f..00000000 Binary files a/res_raw/sprites/belt/forward_9.png and /dev/null differ diff --git a/res_raw/sprites/belt/generate_belt_sprites.js b/res_raw/sprites/belt/generate_belt_sprites.js index f0bd4aa1..79c5d149 100644 --- a/res_raw/sprites/belt/generate_belt_sprites.js +++ b/res_raw/sprites/belt/generate_belt_sprites.js @@ -11,9 +11,10 @@ const { fileURLToPath } = require("url"); async function run() { console.log("Running"); - const fps = 28; - const dimensions = 126; - const beltBorder = 15.5; + const fps = 14; + const dimensions = 192; + const beltBorder = 23.5; + const lineSize = 5; const borderColor = "#91949e"; const fillColor = "#d2d4d9"; @@ -21,8 +22,8 @@ async function run() { // Generate arrow sprite - const arrowW = 40; - const arrowH = 20; + const arrowW = 60; + const arrowH = arrowW / 2; /** @type {HTMLCanvasElement} */ const arrowSprite = createCanvas(arrowW, arrowH); const arrowContext = arrowSprite.getContext("2d"); @@ -37,6 +38,8 @@ async function run() { arrowContext.closePath(); arrowContext.fill(); + const promises = []; + // First, generate the forward belt for (let i = 0; i < fps; ++i) { /** @type {HTMLCanvasElement} */ @@ -49,7 +52,7 @@ async function run() { context.fillStyle = fillColor; context.strokeStyle = borderColor; - context.lineWidth = 3; + context.lineWidth = lineSize; context.beginPath(); context.rect(beltBorder, -10, dimensions - 2 * beltBorder, dimensions + 20); @@ -64,9 +67,10 @@ async function run() { context.drawImage(arrowSprite, dimensions / 2 - arrowW / 2, y); } - const out = fs.createWriteStream(path.join(__dirname, "forward_" + i + ".png")); + const out = fs.createWriteStream(path.join(__dirname, "built", "forward_" + i + ".png")); const stream = canvas.createPNGStream(); stream.pipe(out); + promises.push(new Promise(resolve => stream.on("end", resolve))); } // Generate left and right side belt @@ -82,7 +86,7 @@ async function run() { context.fillStyle = fillColor; context.strokeStyle = borderColor; - context.lineWidth = 3; + context.lineWidth = lineSize; context.beginPath(); context.moveTo(beltBorder, dimensions + 10); @@ -160,14 +164,43 @@ async function run() { flippedContext.scale(-1, 1); flippedContext.drawImage(canvas, -dimensions, 0, dimensions, dimensions); - const out = fs.createWriteStream(path.join(__dirname, "right_" + i + ".png")); - const stream = canvas.createPNGStream(); - stream.pipe(out); + const outRight = fs.createWriteStream(path.join(__dirname, "built", "right_" + i + ".png")); + const streamRight = canvas.createPNGStream(); + streamRight.pipe(outRight); - const outLeft = fs.createWriteStream(path.join(__dirname, "left_" + i + ".png")); + const outLeft = fs.createWriteStream(path.join(__dirname, "built", "left_" + i + ".png")); const streamLeft = flippedCanvas.createPNGStream(); streamLeft.pipe(outLeft); + + promises.push(new Promise(resolve => streamRight.on("end", resolve))); + promises.push(new Promise(resolve => streamLeft.on("end", resolve))); } + + console.log("Waiting for completion"); + await Promise.all(promises); + + // Also wait a bit more + await new Promise(resolve => setTimeout(resolve, 1000)); + + console.log("Copying files to all locations"); + + // Copy other files + fs.copyFileSync( + path.join(__dirname, "built", "forward_0.png"), + path.join(__dirname, "..", "buildings", "belt_top.png") + ); + + fs.copyFileSync( + path.join(__dirname, "built", "right_0.png"), + path.join(__dirname, "..", "buildings", "belt_right.png") + ); + + fs.copyFileSync( + path.join(__dirname, "built", "left_0.png"), + path.join(__dirname, "..", "buildings", "belt_left.png") + ); + + console.log("Done!"); } run(); diff --git a/res_raw/sprites/belt/generate_wire_sprites.js b/res_raw/sprites/belt/generate_wire_sprites.js new file mode 100644 index 00000000..24ac319b --- /dev/null +++ b/res_raw/sprites/belt/generate_wire_sprites.js @@ -0,0 +1,226 @@ +/** + * + * Run `yarn global add canvas` first + */ + +const { createCanvas } = require("canvas"); +const fs = require("fs"); +const path = require("path"); + +const outputFolder = path.join(__dirname, "..", "wires", "sets"); + +const dimensions = 192; +const lineSize = 12; +const lowerLineSize = 20; + +function hexToRGB(h) { + let r = 0, + g = 0, + b = 0; + + // 3 digits + if (h.length == 4) { + r = "0x" + h[1] + h[1]; + g = "0x" + h[2] + h[2]; + b = "0x" + h[3] + h[3]; + + // 6 digits + } else if (h.length == 7) { + r = "0x" + h[1] + h[2]; + g = "0x" + h[3] + h[4]; + b = "0x" + h[5] + h[6]; + } + + return [+r, +g, +b]; +} + +function RGBToHSL(r, g, b) { + // Make r, g, and b fractions of 1 + r /= 255; + g /= 255; + b /= 255; + + // Find greatest and smallest channel values + let cmin = Math.min(r, g, b), + cmax = Math.max(r, g, b), + delta = cmax - cmin, + h = 0, + s = 0, + l = 0; + // Calculate hue + // No difference + if (delta == 0) h = 0; + // Red is max + else if (cmax == r) h = ((g - b) / delta) % 6; + // Green is max + else if (cmax == g) h = (b - r) / delta + 2; + // Blue is max + else h = (r - g) / delta + 4; + + h = Math.round(h * 60); + + // Make negative hues positive behind 360° + if (h < 0) h += 360; + + // Calculate lightness + l = (cmax + cmin) / 2; + + // Calculate saturation + s = delta == 0 ? 0 : delta / (1 - Math.abs(2 * l - 1)); + + // Multiply l and s by 100 + s = +(s * 100).toFixed(1); + l = +(l * 100).toFixed(1); + + return [h, s, l]; +} + +function HSLToRGB(h, s, l) { + // Must be fractions of 1 + s /= 100; + l /= 100; + + let c = (1 - Math.abs(2 * l - 1)) * s, + x = c * (1 - Math.abs(((h / 60) % 2) - 1)), + m = l - c / 2, + r = 0, + g = 0, + b = 0; + + if (0 <= h && h < 60) { + r = c; + g = x; + b = 0; + } else if (60 <= h && h < 120) { + r = x; + g = c; + b = 0; + } else if (120 <= h && h < 180) { + r = 0; + g = c; + b = x; + } else if (180 <= h && h < 240) { + r = 0; + g = x; + b = c; + } else if (240 <= h && h < 300) { + r = x; + g = 0; + b = c; + } else if (300 <= h && h < 360) { + r = c; + g = 0; + b = x; + } + r = Math.round((r + m) * 255); + g = Math.round((g + m) * 255); + b = Math.round((b + m) * 255); + + return [r, g, b]; +} + +async function run() { + console.log("Running"); + + const variants = { + regular: "#25fff2", + color: "#eba458", + shape: "#8858eb", + conflict: "#ff3e3e", + }; + + const promises = []; + + for (const variantId in variants) { + const variantColor = variants[variantId]; + const variantHSL = RGBToHSL(...hexToRGB(variantColor)); + const darkenedColor = HSLToRGB(variantHSL[0], variantHSL[1] - 15, variantHSL[2] - 20); + const hexDarkenedColor = "rgb(" + darkenedColor.join(",") + ")"; + + console.log(variantColor, "->", hexToRGB(variantColor), variantHSL, "->", darkenedColor); + + const parts = { + forward: [[0.5, 0, 0.5, 1]], + turn: [ + [0.5, 0.5, 0.5, 1], + [0.5, 0.5, 1, 0.5], + ], + split: [ + [0.5, 0.5, 0.5, 1], + [0, 0.5, 1, 0.5], + ], + cross: [ + [0, 0.5, 1, 0.5], + [0.5, 0, 0.5, 1], + ], + }; + + for (const partId in parts) { + const partLines = parts[partId]; + + const canvas = createCanvas(dimensions, dimensions); + const context = canvas.getContext("2d"); + context.quality = "best"; + context.clearRect(0, 0, dimensions, dimensions); + + context.strokeStyle = hexDarkenedColor; + context.lineWidth = lowerLineSize; + context.lineCap = "square"; + context.imageSmoothingEnabled = false; + + // Draw lower lines + partLines.forEach(([x1, y1, x2, y2]) => { + context.beginPath(); + context.moveTo(x1 * dimensions, y1 * dimensions); + context.lineTo(x2 * dimensions, y2 * dimensions); + context.stroke(); + }); + + context.strokeStyle = variantColor; + context.lineWidth = lineSize; + + // Draw upper lines + partLines.forEach(([x1, y1, x2, y2]) => { + context.beginPath(); + context.moveTo(x1 * dimensions, y1 * dimensions); + context.lineTo(x2 * dimensions, y2 * dimensions); + context.stroke(); + }); + + const out = fs.createWriteStream(path.join(outputFolder, variantId + "_" + partId + ".png")); + const stream = canvas.createPNGStream(); + stream.pipe(out); + promises.push(new Promise(resolve => stream.on("end", resolve))); + } + } + + console.log("Waiting for completion"); + await Promise.all(promises); + + // Also wait a bit more + await new Promise(resolve => setTimeout(resolve, 1000)); + + console.log("Copying files to all locations"); + + // // Copy other files + fs.copyFileSync( + path.join(outputFolder, "regular_forward.png"), + path.join(__dirname, "..", "buildings", "wire.png") + ); + fs.copyFileSync( + path.join(outputFolder, "regular_turn.png"), + path.join(__dirname, "..", "buildings", "wire-turn.png") + ); + fs.copyFileSync( + path.join(outputFolder, "regular_split.png"), + path.join(__dirname, "..", "buildings", "wire-split.png") + ); + fs.copyFileSync( + path.join(outputFolder, "regular_cross.png"), + path.join(__dirname, "..", "buildings", "wire-cross.png") + ); + + console.log("Done!"); +} + +run(); diff --git a/res_raw/sprites/belt/left_0.png b/res_raw/sprites/belt/left_0.png deleted file mode 100644 index 7da4c390..00000000 Binary files a/res_raw/sprites/belt/left_0.png and /dev/null differ diff --git a/res_raw/sprites/belt/left_1.png b/res_raw/sprites/belt/left_1.png deleted file mode 100644 index fa446ce4..00000000 Binary files a/res_raw/sprites/belt/left_1.png and /dev/null differ diff --git a/res_raw/sprites/belt/left_10.png b/res_raw/sprites/belt/left_10.png deleted file mode 100644 index 260a4c23..00000000 Binary files a/res_raw/sprites/belt/left_10.png and /dev/null differ diff --git a/res_raw/sprites/belt/left_11.png b/res_raw/sprites/belt/left_11.png deleted file mode 100644 index d0d70ab1..00000000 Binary files a/res_raw/sprites/belt/left_11.png and /dev/null differ diff --git a/res_raw/sprites/belt/left_12.png b/res_raw/sprites/belt/left_12.png deleted file mode 100644 index 3f916501..00000000 Binary files a/res_raw/sprites/belt/left_12.png and /dev/null differ diff --git a/res_raw/sprites/belt/left_13.png b/res_raw/sprites/belt/left_13.png deleted file mode 100644 index 71d9a634..00000000 Binary files a/res_raw/sprites/belt/left_13.png and /dev/null differ diff --git a/res_raw/sprites/belt/left_14.png b/res_raw/sprites/belt/left_14.png deleted file mode 100644 index 134b90af..00000000 Binary files a/res_raw/sprites/belt/left_14.png and /dev/null differ diff --git a/res_raw/sprites/belt/left_15.png b/res_raw/sprites/belt/left_15.png deleted file mode 100644 index 623069a1..00000000 Binary files a/res_raw/sprites/belt/left_15.png and /dev/null differ diff --git a/res_raw/sprites/belt/left_16.png b/res_raw/sprites/belt/left_16.png deleted file mode 100644 index 14b18b45..00000000 Binary files a/res_raw/sprites/belt/left_16.png and /dev/null differ diff --git a/res_raw/sprites/belt/left_17.png b/res_raw/sprites/belt/left_17.png deleted file mode 100644 index 5aa84e5c..00000000 Binary files a/res_raw/sprites/belt/left_17.png and /dev/null differ diff --git a/res_raw/sprites/belt/left_18.png b/res_raw/sprites/belt/left_18.png deleted file mode 100644 index 0fe1dedd..00000000 Binary files a/res_raw/sprites/belt/left_18.png and /dev/null differ diff --git a/res_raw/sprites/belt/left_19.png b/res_raw/sprites/belt/left_19.png deleted file mode 100644 index 46e1b2b3..00000000 Binary files a/res_raw/sprites/belt/left_19.png and /dev/null differ diff --git a/res_raw/sprites/belt/left_2.png b/res_raw/sprites/belt/left_2.png deleted file mode 100644 index 9a8d15c0..00000000 Binary files a/res_raw/sprites/belt/left_2.png and /dev/null differ diff --git a/res_raw/sprites/belt/left_20.png b/res_raw/sprites/belt/left_20.png deleted file mode 100644 index 1d6dd020..00000000 Binary files a/res_raw/sprites/belt/left_20.png and /dev/null differ diff --git a/res_raw/sprites/belt/left_21.png b/res_raw/sprites/belt/left_21.png deleted file mode 100644 index 413afb3c..00000000 Binary files a/res_raw/sprites/belt/left_21.png and /dev/null differ diff --git a/res_raw/sprites/belt/left_22.png b/res_raw/sprites/belt/left_22.png deleted file mode 100644 index c56c9607..00000000 Binary files a/res_raw/sprites/belt/left_22.png and /dev/null differ diff --git a/res_raw/sprites/belt/left_23.png b/res_raw/sprites/belt/left_23.png deleted file mode 100644 index 22c7e9d1..00000000 Binary files a/res_raw/sprites/belt/left_23.png and /dev/null differ diff --git a/res_raw/sprites/belt/left_24.png b/res_raw/sprites/belt/left_24.png deleted file mode 100644 index 1c15838a..00000000 Binary files a/res_raw/sprites/belt/left_24.png and /dev/null differ diff --git a/res_raw/sprites/belt/left_25.png b/res_raw/sprites/belt/left_25.png deleted file mode 100644 index 20120842..00000000 Binary files a/res_raw/sprites/belt/left_25.png and /dev/null differ diff --git a/res_raw/sprites/belt/left_26.png b/res_raw/sprites/belt/left_26.png deleted file mode 100644 index 1d4de05f..00000000 Binary files a/res_raw/sprites/belt/left_26.png and /dev/null differ diff --git a/res_raw/sprites/belt/left_27.png b/res_raw/sprites/belt/left_27.png deleted file mode 100644 index ba0d699a..00000000 Binary files a/res_raw/sprites/belt/left_27.png and /dev/null differ diff --git a/res_raw/sprites/belt/left_3.png b/res_raw/sprites/belt/left_3.png deleted file mode 100644 index 7fc8c6fc..00000000 Binary files a/res_raw/sprites/belt/left_3.png and /dev/null differ diff --git a/res_raw/sprites/belt/left_4.png b/res_raw/sprites/belt/left_4.png deleted file mode 100644 index e8da79fd..00000000 Binary files a/res_raw/sprites/belt/left_4.png and /dev/null differ diff --git a/res_raw/sprites/belt/left_5.png b/res_raw/sprites/belt/left_5.png deleted file mode 100644 index 1a26dc72..00000000 Binary files a/res_raw/sprites/belt/left_5.png and /dev/null differ diff --git a/res_raw/sprites/belt/left_6.png b/res_raw/sprites/belt/left_6.png deleted file mode 100644 index c2322d45..00000000 Binary files a/res_raw/sprites/belt/left_6.png and /dev/null differ diff --git a/res_raw/sprites/belt/left_7.png b/res_raw/sprites/belt/left_7.png deleted file mode 100644 index a85a31fc..00000000 Binary files a/res_raw/sprites/belt/left_7.png and /dev/null differ diff --git a/res_raw/sprites/belt/left_8.png b/res_raw/sprites/belt/left_8.png deleted file mode 100644 index 9ff9945b..00000000 Binary files a/res_raw/sprites/belt/left_8.png and /dev/null differ diff --git a/res_raw/sprites/belt/left_9.png b/res_raw/sprites/belt/left_9.png deleted file mode 100644 index bfe4360e..00000000 Binary files a/res_raw/sprites/belt/left_9.png and /dev/null differ diff --git a/res_raw/sprites/belt/right_0.png b/res_raw/sprites/belt/right_0.png deleted file mode 100644 index fca35eab..00000000 Binary files a/res_raw/sprites/belt/right_0.png and /dev/null differ diff --git a/res_raw/sprites/belt/right_1.png b/res_raw/sprites/belt/right_1.png deleted file mode 100644 index 101578e9..00000000 Binary files a/res_raw/sprites/belt/right_1.png and /dev/null differ diff --git a/res_raw/sprites/belt/right_10.png b/res_raw/sprites/belt/right_10.png deleted file mode 100644 index cd733017..00000000 Binary files a/res_raw/sprites/belt/right_10.png and /dev/null differ diff --git a/res_raw/sprites/belt/right_11.png b/res_raw/sprites/belt/right_11.png deleted file mode 100644 index 5d082ecc..00000000 Binary files a/res_raw/sprites/belt/right_11.png and /dev/null differ diff --git a/res_raw/sprites/belt/right_12.png b/res_raw/sprites/belt/right_12.png deleted file mode 100644 index 3c7f08bb..00000000 Binary files a/res_raw/sprites/belt/right_12.png and /dev/null differ diff --git a/res_raw/sprites/belt/right_13.png b/res_raw/sprites/belt/right_13.png deleted file mode 100644 index 71364d48..00000000 Binary files a/res_raw/sprites/belt/right_13.png and /dev/null differ diff --git a/res_raw/sprites/belt/right_14.png b/res_raw/sprites/belt/right_14.png deleted file mode 100644 index cf5df0a4..00000000 Binary files a/res_raw/sprites/belt/right_14.png and /dev/null differ diff --git a/res_raw/sprites/belt/right_15.png b/res_raw/sprites/belt/right_15.png deleted file mode 100644 index 1292ec67..00000000 Binary files a/res_raw/sprites/belt/right_15.png and /dev/null differ diff --git a/res_raw/sprites/belt/right_16.png b/res_raw/sprites/belt/right_16.png deleted file mode 100644 index 4dcc2c5f..00000000 Binary files a/res_raw/sprites/belt/right_16.png and /dev/null differ diff --git a/res_raw/sprites/belt/right_17.png b/res_raw/sprites/belt/right_17.png deleted file mode 100644 index 489f0e54..00000000 Binary files a/res_raw/sprites/belt/right_17.png and /dev/null differ diff --git a/res_raw/sprites/belt/right_18.png b/res_raw/sprites/belt/right_18.png deleted file mode 100644 index 208f402b..00000000 Binary files a/res_raw/sprites/belt/right_18.png and /dev/null differ diff --git a/res_raw/sprites/belt/right_19.png b/res_raw/sprites/belt/right_19.png deleted file mode 100644 index 5e4e376b..00000000 Binary files a/res_raw/sprites/belt/right_19.png and /dev/null differ diff --git a/res_raw/sprites/belt/right_2.png b/res_raw/sprites/belt/right_2.png deleted file mode 100644 index c9affce1..00000000 Binary files a/res_raw/sprites/belt/right_2.png and /dev/null differ diff --git a/res_raw/sprites/belt/right_20.png b/res_raw/sprites/belt/right_20.png deleted file mode 100644 index 77a4f43b..00000000 Binary files a/res_raw/sprites/belt/right_20.png and /dev/null differ diff --git a/res_raw/sprites/belt/right_21.png b/res_raw/sprites/belt/right_21.png deleted file mode 100644 index ca1d0f5f..00000000 Binary files a/res_raw/sprites/belt/right_21.png and /dev/null differ diff --git a/res_raw/sprites/belt/right_22.png b/res_raw/sprites/belt/right_22.png deleted file mode 100644 index d07bf72d..00000000 Binary files a/res_raw/sprites/belt/right_22.png and /dev/null differ diff --git a/res_raw/sprites/belt/right_23.png b/res_raw/sprites/belt/right_23.png deleted file mode 100644 index babfca3f..00000000 Binary files a/res_raw/sprites/belt/right_23.png and /dev/null differ diff --git a/res_raw/sprites/belt/right_24.png b/res_raw/sprites/belt/right_24.png deleted file mode 100644 index 1c614c85..00000000 Binary files a/res_raw/sprites/belt/right_24.png and /dev/null differ diff --git a/res_raw/sprites/belt/right_25.png b/res_raw/sprites/belt/right_25.png deleted file mode 100644 index d72a8615..00000000 Binary files a/res_raw/sprites/belt/right_25.png and /dev/null differ diff --git a/res_raw/sprites/belt/right_26.png b/res_raw/sprites/belt/right_26.png deleted file mode 100644 index ed37636f..00000000 Binary files a/res_raw/sprites/belt/right_26.png and /dev/null differ diff --git a/res_raw/sprites/belt/right_27.png b/res_raw/sprites/belt/right_27.png deleted file mode 100644 index fe9ffc10..00000000 Binary files a/res_raw/sprites/belt/right_27.png and /dev/null differ diff --git a/res_raw/sprites/belt/right_3.png b/res_raw/sprites/belt/right_3.png deleted file mode 100644 index feb7101b..00000000 Binary files a/res_raw/sprites/belt/right_3.png and /dev/null differ diff --git a/res_raw/sprites/belt/right_4.png b/res_raw/sprites/belt/right_4.png deleted file mode 100644 index 22c885a6..00000000 Binary files a/res_raw/sprites/belt/right_4.png and /dev/null differ diff --git a/res_raw/sprites/belt/right_5.png b/res_raw/sprites/belt/right_5.png deleted file mode 100644 index 27bb27aa..00000000 Binary files a/res_raw/sprites/belt/right_5.png and /dev/null differ diff --git a/res_raw/sprites/belt/right_6.png b/res_raw/sprites/belt/right_6.png deleted file mode 100644 index 5ca871b7..00000000 Binary files a/res_raw/sprites/belt/right_6.png and /dev/null differ diff --git a/res_raw/sprites/belt/right_7.png b/res_raw/sprites/belt/right_7.png deleted file mode 100644 index a9cde450..00000000 Binary files a/res_raw/sprites/belt/right_7.png and /dev/null differ diff --git a/res_raw/sprites/belt/right_8.png b/res_raw/sprites/belt/right_8.png deleted file mode 100644 index f09195fe..00000000 Binary files a/res_raw/sprites/belt/right_8.png and /dev/null differ diff --git a/res_raw/sprites/belt/right_9.png b/res_raw/sprites/belt/right_9.png deleted file mode 100644 index b6ca38c1..00000000 Binary files a/res_raw/sprites/belt/right_9.png and /dev/null differ diff --git a/res_raw/sprites/blueprints/advanced_processor.png b/res_raw/sprites/blueprints/advanced_processor.png deleted file mode 100644 index ab385816..00000000 Binary files a/res_raw/sprites/blueprints/advanced_processor.png and /dev/null differ diff --git a/res_raw/sprites/blueprints/belt_left.png b/res_raw/sprites/blueprints/belt_left.png index 594bb203..2046637c 100644 Binary files a/res_raw/sprites/blueprints/belt_left.png and b/res_raw/sprites/blueprints/belt_left.png differ diff --git a/res_raw/sprites/blueprints/belt_right.png b/res_raw/sprites/blueprints/belt_right.png index 9c33404b..48629eaa 100644 Binary files a/res_raw/sprites/blueprints/belt_right.png and b/res_raw/sprites/blueprints/belt_right.png differ diff --git a/res_raw/sprites/blueprints/belt_top.png b/res_raw/sprites/blueprints/belt_top.png index 881c443a..88d7917b 100644 Binary files a/res_raw/sprites/blueprints/belt_top.png and b/res_raw/sprites/blueprints/belt_top.png differ diff --git a/res_raw/sprites/blueprints/constant_signal.png b/res_raw/sprites/blueprints/constant_signal.png new file mode 100644 index 00000000..9acb86d2 Binary files /dev/null and b/res_raw/sprites/blueprints/constant_signal.png differ diff --git a/res_raw/sprites/blueprints/display.png b/res_raw/sprites/blueprints/display.png new file mode 100644 index 00000000..bb0319f2 Binary files /dev/null and b/res_raw/sprites/blueprints/display.png differ diff --git a/res_raw/sprites/blueprints/energy_generator.png b/res_raw/sprites/blueprints/energy_generator.png deleted file mode 100644 index 42258c63..00000000 Binary files a/res_raw/sprites/blueprints/energy_generator.png and /dev/null differ diff --git a/res_raw/sprites/blueprints/filter.png b/res_raw/sprites/blueprints/filter.png new file mode 100644 index 00000000..dd791666 Binary files /dev/null and b/res_raw/sprites/blueprints/filter.png differ diff --git a/res_raw/sprites/blueprints/lever.png b/res_raw/sprites/blueprints/lever.png new file mode 100644 index 00000000..7190b1f2 Binary files /dev/null and b/res_raw/sprites/blueprints/lever.png differ diff --git a/res_raw/sprites/blueprints/logic_gate-not.png b/res_raw/sprites/blueprints/logic_gate-not.png new file mode 100644 index 00000000..a45b6ce5 Binary files /dev/null and b/res_raw/sprites/blueprints/logic_gate-not.png differ diff --git a/res_raw/sprites/blueprints/logic_gate-or.png b/res_raw/sprites/blueprints/logic_gate-or.png new file mode 100644 index 00000000..f58c3656 Binary files /dev/null and b/res_raw/sprites/blueprints/logic_gate-or.png differ diff --git a/res_raw/sprites/blueprints/logic_gate-transistor.png b/res_raw/sprites/blueprints/logic_gate-transistor.png new file mode 100644 index 00000000..c3d3682d Binary files /dev/null and b/res_raw/sprites/blueprints/logic_gate-transistor.png differ diff --git a/res_raw/sprites/blueprints/logic_gate-xor.png b/res_raw/sprites/blueprints/logic_gate-xor.png new file mode 100644 index 00000000..97823a7a Binary files /dev/null and b/res_raw/sprites/blueprints/logic_gate-xor.png differ diff --git a/res_raw/sprites/blueprints/logic_gate.png b/res_raw/sprites/blueprints/logic_gate.png new file mode 100644 index 00000000..de59fa57 Binary files /dev/null and b/res_raw/sprites/blueprints/logic_gate.png differ diff --git a/res_raw/sprites/blueprints/wire-cross.png b/res_raw/sprites/blueprints/wire-cross.png new file mode 100644 index 00000000..c9aeb1c5 Binary files /dev/null and b/res_raw/sprites/blueprints/wire-cross.png differ diff --git a/res_raw/sprites/blueprints/wire-split.png b/res_raw/sprites/blueprints/wire-split.png new file mode 100644 index 00000000..f0cdfb11 Binary files /dev/null and b/res_raw/sprites/blueprints/wire-split.png differ diff --git a/res_raw/sprites/blueprints/wire-turn.png b/res_raw/sprites/blueprints/wire-turn.png new file mode 100644 index 00000000..becf6411 Binary files /dev/null and b/res_raw/sprites/blueprints/wire-turn.png differ diff --git a/res_raw/sprites/blueprints/wire.png b/res_raw/sprites/blueprints/wire.png new file mode 100644 index 00000000..15bfde22 Binary files /dev/null and b/res_raw/sprites/blueprints/wire.png differ diff --git a/res_raw/sprites/blueprints/wire_crossings-merger.png b/res_raw/sprites/blueprints/wire_crossings-merger.png deleted file mode 100644 index f58ae10e..00000000 Binary files a/res_raw/sprites/blueprints/wire_crossings-merger.png and /dev/null differ diff --git a/res_raw/sprites/blueprints/wire_crossings.png b/res_raw/sprites/blueprints/wire_crossings.png deleted file mode 100644 index a1d44678..00000000 Binary files a/res_raw/sprites/blueprints/wire_crossings.png and /dev/null differ diff --git a/res_raw/sprites/blueprints/wire_left.png b/res_raw/sprites/blueprints/wire_left.png deleted file mode 100644 index 232c13e9..00000000 Binary files a/res_raw/sprites/blueprints/wire_left.png and /dev/null differ diff --git a/res_raw/sprites/blueprints/wire_right.png b/res_raw/sprites/blueprints/wire_right.png deleted file mode 100644 index fba98482..00000000 Binary files a/res_raw/sprites/blueprints/wire_right.png and /dev/null differ diff --git a/res_raw/sprites/blueprints/wire_top.png b/res_raw/sprites/blueprints/wire_top.png deleted file mode 100644 index 52efcc01..00000000 Binary files a/res_raw/sprites/blueprints/wire_top.png and /dev/null differ diff --git a/res_raw/sprites/blueprints/wire_tunnel-coating.png b/res_raw/sprites/blueprints/wire_tunnel-coating.png new file mode 100644 index 00000000..381e628a Binary files /dev/null and b/res_raw/sprites/blueprints/wire_tunnel-coating.png differ diff --git a/res_raw/sprites/blueprints/wire_tunnel.png b/res_raw/sprites/blueprints/wire_tunnel.png new file mode 100644 index 00000000..9a7cdd2a Binary files /dev/null and b/res_raw/sprites/blueprints/wire_tunnel.png differ diff --git a/res_raw/sprites/buildings/advanced_processor.png b/res_raw/sprites/buildings/advanced_processor.png deleted file mode 100644 index 5402760b..00000000 Binary files a/res_raw/sprites/buildings/advanced_processor.png and /dev/null differ diff --git a/res_raw/sprites/buildings/belt_left.png b/res_raw/sprites/buildings/belt_left.png index 60bebd29..8575be67 100644 Binary files a/res_raw/sprites/buildings/belt_left.png and b/res_raw/sprites/buildings/belt_left.png differ diff --git a/res_raw/sprites/buildings/belt_right.png b/res_raw/sprites/buildings/belt_right.png index 547387b4..51cb8c7c 100644 Binary files a/res_raw/sprites/buildings/belt_right.png and b/res_raw/sprites/buildings/belt_right.png differ diff --git a/res_raw/sprites/buildings/belt_top.png b/res_raw/sprites/buildings/belt_top.png index cf5b20d7..67b47330 100644 Binary files a/res_raw/sprites/buildings/belt_top.png and b/res_raw/sprites/buildings/belt_top.png differ diff --git a/res_raw/sprites/buildings/constant_signal.png b/res_raw/sprites/buildings/constant_signal.png new file mode 100644 index 00000000..ae9329e0 Binary files /dev/null and b/res_raw/sprites/buildings/constant_signal.png differ diff --git a/res_raw/sprites/buildings/display.png b/res_raw/sprites/buildings/display.png new file mode 100644 index 00000000..ec7b95d9 Binary files /dev/null and b/res_raw/sprites/buildings/display.png differ diff --git a/res_raw/sprites/buildings/energy_generator.png b/res_raw/sprites/buildings/energy_generator.png deleted file mode 100644 index 5bd9f9a2..00000000 Binary files a/res_raw/sprites/buildings/energy_generator.png and /dev/null differ diff --git a/res_raw/sprites/buildings/filter.png b/res_raw/sprites/buildings/filter.png new file mode 100644 index 00000000..95b749c7 Binary files /dev/null and b/res_raw/sprites/buildings/filter.png differ diff --git a/res_raw/sprites/buildings/hub.png b/res_raw/sprites/buildings/hub.png index 8fdd5305..68283f09 100644 Binary files a/res_raw/sprites/buildings/hub.png and b/res_raw/sprites/buildings/hub.png differ diff --git a/res_raw/sprites/buildings/lever.png b/res_raw/sprites/buildings/lever.png new file mode 100644 index 00000000..eda46bfa Binary files /dev/null and b/res_raw/sprites/buildings/lever.png differ diff --git a/res_raw/sprites/buildings/logic_gate-not.png b/res_raw/sprites/buildings/logic_gate-not.png new file mode 100644 index 00000000..b5e8246c Binary files /dev/null and b/res_raw/sprites/buildings/logic_gate-not.png differ diff --git a/res_raw/sprites/buildings/logic_gate-or.png b/res_raw/sprites/buildings/logic_gate-or.png new file mode 100644 index 00000000..1b9c9e34 Binary files /dev/null and b/res_raw/sprites/buildings/logic_gate-or.png differ diff --git a/res_raw/sprites/buildings/logic_gate-transistor.png b/res_raw/sprites/buildings/logic_gate-transistor.png new file mode 100644 index 00000000..35952db4 Binary files /dev/null and b/res_raw/sprites/buildings/logic_gate-transistor.png differ diff --git a/res_raw/sprites/buildings/logic_gate-xor.png b/res_raw/sprites/buildings/logic_gate-xor.png new file mode 100644 index 00000000..c7d43a58 Binary files /dev/null and b/res_raw/sprites/buildings/logic_gate-xor.png differ diff --git a/res_raw/sprites/buildings/logic_gate.png b/res_raw/sprites/buildings/logic_gate.png new file mode 100644 index 00000000..2d206aa3 Binary files /dev/null and b/res_raw/sprites/buildings/logic_gate.png differ diff --git a/res_raw/sprites/buildings/wire-cross.png b/res_raw/sprites/buildings/wire-cross.png new file mode 100644 index 00000000..e9c71dac Binary files /dev/null and b/res_raw/sprites/buildings/wire-cross.png differ diff --git a/res_raw/sprites/buildings/wire-split.png b/res_raw/sprites/buildings/wire-split.png new file mode 100644 index 00000000..e26b552c Binary files /dev/null and b/res_raw/sprites/buildings/wire-split.png differ diff --git a/res_raw/sprites/buildings/wire-turn.png b/res_raw/sprites/buildings/wire-turn.png new file mode 100644 index 00000000..5b50bb09 Binary files /dev/null and b/res_raw/sprites/buildings/wire-turn.png differ diff --git a/res_raw/sprites/buildings/wire.png b/res_raw/sprites/buildings/wire.png new file mode 100644 index 00000000..8310be84 Binary files /dev/null and b/res_raw/sprites/buildings/wire.png differ diff --git a/res_raw/sprites/buildings/wire_crossings-merger.png b/res_raw/sprites/buildings/wire_crossings-merger.png deleted file mode 100644 index ee0db056..00000000 Binary files a/res_raw/sprites/buildings/wire_crossings-merger.png and /dev/null differ diff --git a/res_raw/sprites/buildings/wire_crossings.png b/res_raw/sprites/buildings/wire_crossings.png deleted file mode 100644 index 243fe45d..00000000 Binary files a/res_raw/sprites/buildings/wire_crossings.png and /dev/null differ diff --git a/res_raw/sprites/buildings/wire_left.png b/res_raw/sprites/buildings/wire_left.png deleted file mode 100644 index 5799ab5b..00000000 Binary files a/res_raw/sprites/buildings/wire_left.png and /dev/null differ diff --git a/res_raw/sprites/buildings/wire_right.png b/res_raw/sprites/buildings/wire_right.png deleted file mode 100644 index b3f2df5a..00000000 Binary files a/res_raw/sprites/buildings/wire_right.png and /dev/null differ diff --git a/res_raw/sprites/buildings/wire_top.png b/res_raw/sprites/buildings/wire_top.png deleted file mode 100644 index a9f90aaa..00000000 Binary files a/res_raw/sprites/buildings/wire_top.png and /dev/null differ diff --git a/res_raw/sprites/buildings/wire_tunnel-coating.png b/res_raw/sprites/buildings/wire_tunnel-coating.png new file mode 100644 index 00000000..aed6c8cb Binary files /dev/null and b/res_raw/sprites/buildings/wire_tunnel-coating.png differ diff --git a/res_raw/sprites/buildings/wire_tunnel.png b/res_raw/sprites/buildings/wire_tunnel.png new file mode 100644 index 00000000..8349e981 Binary files /dev/null and b/res_raw/sprites/buildings/wire_tunnel.png differ diff --git a/res_raw/sprites/debug/acceptor_slot.png b/res_raw/sprites/debug/acceptor_slot.png index 4ab91b5b..7d2f697e 100644 Binary files a/res_raw/sprites/debug/acceptor_slot.png and b/res_raw/sprites/debug/acceptor_slot.png differ diff --git a/res_raw/sprites/debug/ejector_slot.png b/res_raw/sprites/debug/ejector_slot.png index a1736a79..0b3f8fed 100644 Binary files a/res_raw/sprites/debug/ejector_slot.png and b/res_raw/sprites/debug/ejector_slot.png differ diff --git a/res_raw/sprites/map_overview/belt_forward.png b/res_raw/sprites/map_overview/belt_forward.png deleted file mode 100644 index e7fb900c..00000000 Binary files a/res_raw/sprites/map_overview/belt_forward.png and /dev/null differ diff --git a/res_raw/sprites/map_overview/belt_left.png b/res_raw/sprites/map_overview/belt_left.png deleted file mode 100644 index 9279c743..00000000 Binary files a/res_raw/sprites/map_overview/belt_left.png and /dev/null differ diff --git a/res_raw/sprites/map_overview/belt_right.png b/res_raw/sprites/map_overview/belt_right.png deleted file mode 100644 index 1f897cf5..00000000 Binary files a/res_raw/sprites/map_overview/belt_right.png and /dev/null differ diff --git a/res_raw/sprites/misc/deletion_marker.png b/res_raw/sprites/misc/deletion_marker.png deleted file mode 100644 index bb3a2b75..00000000 Binary files a/res_raw/sprites/misc/deletion_marker.png and /dev/null differ diff --git a/res_raw/sprites/misc/energy_generator_overlay.png b/res_raw/sprites/misc/energy_generator_overlay.png deleted file mode 100644 index 634c2e10..00000000 Binary files a/res_raw/sprites/misc/energy_generator_overlay.png and /dev/null differ diff --git a/res_raw/sprites/misc/hub_direction_indicator.png b/res_raw/sprites/misc/hub_direction_indicator.png index 006ba8fa..40414cc1 100644 Binary files a/res_raw/sprites/misc/hub_direction_indicator.png and b/res_raw/sprites/misc/hub_direction_indicator.png differ diff --git a/res_raw/sprites/misc/slot_bad_arrow.png b/res_raw/sprites/misc/slot_bad_arrow.png index 27c938ac..fe5c5d3b 100644 Binary files a/res_raw/sprites/misc/slot_bad_arrow.png and b/res_raw/sprites/misc/slot_bad_arrow.png differ diff --git a/res_raw/sprites/misc/slot_good_arrow.png b/res_raw/sprites/misc/slot_good_arrow.png index 3001e8b4..ffe9bbb4 100644 Binary files a/res_raw/sprites/misc/slot_good_arrow.png and b/res_raw/sprites/misc/slot_good_arrow.png differ diff --git a/res_raw/sprites/misc/storage_overlay.png b/res_raw/sprites/misc/storage_overlay.png index 92b2ecf8..cad98032 100644 Binary files a/res_raw/sprites/misc/storage_overlay.png and b/res_raw/sprites/misc/storage_overlay.png differ diff --git a/res_raw/sprites/misc/waypoint.png b/res_raw/sprites/misc/waypoint.png index 105f7cd5..889fb707 100644 Binary files a/res_raw/sprites/misc/waypoint.png and b/res_raw/sprites/misc/waypoint.png differ diff --git a/res_raw/sprites/misc/wires_overlay_tile.png b/res_raw/sprites/misc/wires_overlay_tile.png deleted file mode 100644 index b8ec3480..00000000 Binary files a/res_raw/sprites/misc/wires_overlay_tile.png and /dev/null differ diff --git a/res_raw/sprites/wires/battery_empty.png b/res_raw/sprites/wires/battery_empty.png deleted file mode 100644 index 78095666..00000000 Binary files a/res_raw/sprites/wires/battery_empty.png and /dev/null differ diff --git a/res_raw/sprites/wires/battery_full.png b/res_raw/sprites/wires/battery_full.png deleted file mode 100644 index 5256150f..00000000 Binary files a/res_raw/sprites/wires/battery_full.png and /dev/null differ diff --git a/res_raw/sprites/wires/battery_low.png b/res_raw/sprites/wires/battery_low.png deleted file mode 100644 index 79fbd8a4..00000000 Binary files a/res_raw/sprites/wires/battery_low.png and /dev/null differ diff --git a/res_raw/sprites/wires/battery_medium.png b/res_raw/sprites/wires/battery_medium.png deleted file mode 100644 index ba0151a0..00000000 Binary files a/res_raw/sprites/wires/battery_medium.png and /dev/null differ diff --git a/res_raw/sprites/wires/boolean_false.png b/res_raw/sprites/wires/boolean_false.png new file mode 100644 index 00000000..757b6cd9 Binary files /dev/null and b/res_raw/sprites/wires/boolean_false.png differ diff --git a/res_raw/sprites/wires/boolean_true.png b/res_raw/sprites/wires/boolean_true.png new file mode 100644 index 00000000..f63bae3f Binary files /dev/null and b/res_raw/sprites/wires/boolean_true.png differ diff --git a/res_raw/sprites/wires/display/blue.png b/res_raw/sprites/wires/display/blue.png new file mode 100644 index 00000000..c131ed84 Binary files /dev/null and b/res_raw/sprites/wires/display/blue.png differ diff --git a/res_raw/sprites/wires/display/cyan.png b/res_raw/sprites/wires/display/cyan.png new file mode 100644 index 00000000..9cc20690 Binary files /dev/null and b/res_raw/sprites/wires/display/cyan.png differ diff --git a/res_raw/sprites/wires/display/green.png b/res_raw/sprites/wires/display/green.png new file mode 100644 index 00000000..cf390a5b Binary files /dev/null and b/res_raw/sprites/wires/display/green.png differ diff --git a/res_raw/sprites/wires/display/purple.png b/res_raw/sprites/wires/display/purple.png new file mode 100644 index 00000000..1285a151 Binary files /dev/null and b/res_raw/sprites/wires/display/purple.png differ diff --git a/res_raw/sprites/wires/display/red.png b/res_raw/sprites/wires/display/red.png new file mode 100644 index 00000000..fabf484c Binary files /dev/null and b/res_raw/sprites/wires/display/red.png differ diff --git a/res_raw/sprites/wires/display/white.png b/res_raw/sprites/wires/display/white.png new file mode 100644 index 00000000..0430f042 Binary files /dev/null and b/res_raw/sprites/wires/display/white.png differ diff --git a/res_raw/sprites/wires/display/yellow.png b/res_raw/sprites/wires/display/yellow.png new file mode 100644 index 00000000..02018a71 Binary files /dev/null and b/res_raw/sprites/wires/display/yellow.png differ diff --git a/res_raw/sprites/wires/lever_on.png b/res_raw/sprites/wires/lever_on.png new file mode 100644 index 00000000..6e5101de Binary files /dev/null and b/res_raw/sprites/wires/lever_on.png differ diff --git a/res_raw/sprites/wires/logical_acceptor.png b/res_raw/sprites/wires/logical_acceptor.png new file mode 100644 index 00000000..74325565 Binary files /dev/null and b/res_raw/sprites/wires/logical_acceptor.png differ diff --git a/res_raw/sprites/wires/logical_ejector.png b/res_raw/sprites/wires/logical_ejector.png new file mode 100644 index 00000000..c1d002aa Binary files /dev/null and b/res_raw/sprites/wires/logical_ejector.png differ diff --git a/res_raw/sprites/wires/negative_energy.png b/res_raw/sprites/wires/negative_energy.png deleted file mode 100644 index cc372330..00000000 Binary files a/res_raw/sprites/wires/negative_energy.png and /dev/null differ diff --git a/res_raw/sprites/wires/network_conflict.png b/res_raw/sprites/wires/network_conflict.png new file mode 100644 index 00000000..4b941bc0 Binary files /dev/null and b/res_raw/sprites/wires/network_conflict.png differ diff --git a/res_raw/sprites/wires/network_empty.png b/res_raw/sprites/wires/network_empty.png new file mode 100644 index 00000000..1f8d1c36 Binary files /dev/null and b/res_raw/sprites/wires/network_empty.png differ diff --git a/res_raw/sprites/wires/overlay_tile.png b/res_raw/sprites/wires/overlay_tile.png new file mode 100644 index 00000000..0b62ebc9 Binary files /dev/null and b/res_raw/sprites/wires/overlay_tile.png differ diff --git a/res_raw/sprites/wires/pin_negative_accept.png b/res_raw/sprites/wires/pin_negative_accept.png deleted file mode 100644 index 82581abb..00000000 Binary files a/res_raw/sprites/wires/pin_negative_accept.png and /dev/null differ diff --git a/res_raw/sprites/wires/pin_negative_eject.png b/res_raw/sprites/wires/pin_negative_eject.png deleted file mode 100644 index e816bd83..00000000 Binary files a/res_raw/sprites/wires/pin_negative_eject.png and /dev/null differ diff --git a/res_raw/sprites/wires/pin_positive_accept.png b/res_raw/sprites/wires/pin_positive_accept.png deleted file mode 100644 index 57044532..00000000 Binary files a/res_raw/sprites/wires/pin_positive_accept.png and /dev/null differ diff --git a/res_raw/sprites/wires/pin_positive_eject.png b/res_raw/sprites/wires/pin_positive_eject.png deleted file mode 100644 index a7da6bc0..00000000 Binary files a/res_raw/sprites/wires/pin_positive_eject.png and /dev/null differ diff --git a/res_raw/sprites/wires/positive_energy.png b/res_raw/sprites/wires/positive_energy.png deleted file mode 100644 index c95c80c9..00000000 Binary files a/res_raw/sprites/wires/positive_energy.png and /dev/null differ diff --git a/res_raw/sprites/wires/sets/README.md b/res_raw/sprites/wires/sets/README.md new file mode 100644 index 00000000..6153c07a --- /dev/null +++ b/res_raw/sprites/wires/sets/README.md @@ -0,0 +1 @@ +Built automatically by sprites/belt/generate_wire_sprites.js diff --git a/res_raw/sprites/wires/sets/color_cross.png b/res_raw/sprites/wires/sets/color_cross.png new file mode 100644 index 00000000..c3b2a3c2 Binary files /dev/null and b/res_raw/sprites/wires/sets/color_cross.png differ diff --git a/res_raw/sprites/wires/sets/color_forward.png b/res_raw/sprites/wires/sets/color_forward.png new file mode 100644 index 00000000..f6584aaa Binary files /dev/null and b/res_raw/sprites/wires/sets/color_forward.png differ diff --git a/res_raw/sprites/wires/sets/color_split.png b/res_raw/sprites/wires/sets/color_split.png new file mode 100644 index 00000000..af9ddfb6 Binary files /dev/null and b/res_raw/sprites/wires/sets/color_split.png differ diff --git a/res_raw/sprites/wires/sets/color_turn.png b/res_raw/sprites/wires/sets/color_turn.png new file mode 100644 index 00000000..1cf4dcb0 Binary files /dev/null and b/res_raw/sprites/wires/sets/color_turn.png differ diff --git a/res_raw/sprites/wires/sets/conflict_cross.png b/res_raw/sprites/wires/sets/conflict_cross.png new file mode 100644 index 00000000..fee403a6 Binary files /dev/null and b/res_raw/sprites/wires/sets/conflict_cross.png differ diff --git a/res_raw/sprites/wires/sets/conflict_forward.png b/res_raw/sprites/wires/sets/conflict_forward.png new file mode 100644 index 00000000..8b9ab43a Binary files /dev/null and b/res_raw/sprites/wires/sets/conflict_forward.png differ diff --git a/res_raw/sprites/wires/sets/conflict_split.png b/res_raw/sprites/wires/sets/conflict_split.png new file mode 100644 index 00000000..6e22aaf0 Binary files /dev/null and b/res_raw/sprites/wires/sets/conflict_split.png differ diff --git a/res_raw/sprites/wires/sets/conflict_turn.png b/res_raw/sprites/wires/sets/conflict_turn.png new file mode 100644 index 00000000..93bd3250 Binary files /dev/null and b/res_raw/sprites/wires/sets/conflict_turn.png differ diff --git a/res_raw/sprites/wires/sets/regular_cross.png b/res_raw/sprites/wires/sets/regular_cross.png new file mode 100644 index 00000000..e9c71dac Binary files /dev/null and b/res_raw/sprites/wires/sets/regular_cross.png differ diff --git a/res_raw/sprites/wires/sets/regular_forward.png b/res_raw/sprites/wires/sets/regular_forward.png new file mode 100644 index 00000000..8310be84 Binary files /dev/null and b/res_raw/sprites/wires/sets/regular_forward.png differ diff --git a/res_raw/sprites/wires/sets/regular_split.png b/res_raw/sprites/wires/sets/regular_split.png new file mode 100644 index 00000000..e26b552c Binary files /dev/null and b/res_raw/sprites/wires/sets/regular_split.png differ diff --git a/res_raw/sprites/wires/sets/regular_turn.png b/res_raw/sprites/wires/sets/regular_turn.png new file mode 100644 index 00000000..5b50bb09 Binary files /dev/null and b/res_raw/sprites/wires/sets/regular_turn.png differ diff --git a/res_raw/sprites/wires/sets/shape_cross.png b/res_raw/sprites/wires/sets/shape_cross.png new file mode 100644 index 00000000..d04812aa Binary files /dev/null and b/res_raw/sprites/wires/sets/shape_cross.png differ diff --git a/res_raw/sprites/wires/sets/shape_forward.png b/res_raw/sprites/wires/sets/shape_forward.png new file mode 100644 index 00000000..15ec3b9c Binary files /dev/null and b/res_raw/sprites/wires/sets/shape_forward.png differ diff --git a/res_raw/sprites/wires/sets/shape_split.png b/res_raw/sprites/wires/sets/shape_split.png new file mode 100644 index 00000000..d19c9b71 Binary files /dev/null and b/res_raw/sprites/wires/sets/shape_split.png differ diff --git a/res_raw/sprites/wires/sets/shape_turn.png b/res_raw/sprites/wires/sets/shape_turn.png new file mode 100644 index 00000000..4f40caa7 Binary files /dev/null and b/res_raw/sprites/wires/sets/shape_turn.png differ diff --git a/res_raw/sprites/wires/waste_piled.png b/res_raw/sprites/wires/waste_piled.png deleted file mode 100644 index 062d0df6..00000000 Binary files a/res_raw/sprites/wires/waste_piled.png and /dev/null differ diff --git a/res_raw/sprites/wires/wires_preview.png b/res_raw/sprites/wires/wires_preview.png new file mode 100644 index 00000000..03c9d0ef Binary files /dev/null and b/res_raw/sprites/wires/wires_preview.png differ diff --git a/src/css/common.scss b/src/css/common.scss index 5f599716..368af699 100644 --- a/src/css/common.scss +++ b/src/css/common.scss @@ -318,9 +318,9 @@ input { canvas { pointer-events: all; - image-rendering: auto; + // image-rendering: pixelated; // &.smoothed { - // } + // }1 // &.unsmoothed { // } letter-spacing: 0 !important; diff --git a/src/css/icons.scss b/src/css/icons.scss index 6d10e2d7..38c32fd5 100644 --- a/src/css/icons.scss +++ b/src/css/icons.scss @@ -1,5 +1,5 @@ -$buildings: belt, cutter, miner, mixer, painter, rotater, splitter, stacker, trash, underground_belt, - energy_generator, wire, advanced_processor, wire_crossings; +$buildings: belt, cutter, miner, mixer, painter, rotater, splitter, stacker, trash, underground_belt, wire, + constant_signal, logic_gate, lever, filter, wire_tunnel, display; @each $building in $buildings { [data-icon="building_icons/#{$building}.png"] { diff --git a/src/js/application.js b/src/js/application.js index bf70239d..e5e22b60 100644 --- a/src/js/application.js +++ b/src/js/application.js @@ -14,13 +14,9 @@ import { AdProviderInterface } from "./platform/ad_provider"; import { NoAdProvider } from "./platform/ad_providers/no_ad_provider"; import { AnalyticsInterface } from "./platform/analytics"; import { GoogleAnalyticsImpl } from "./platform/browser/google_analytics"; -import { NoGameAnalytics } from "./platform/browser/no_game_analytics"; import { SoundImplBrowser } from "./platform/browser/sound"; import { PlatformWrapperImplBrowser } from "./platform/browser/wrapper"; import { PlatformWrapperImplElectron } from "./platform/electron/wrapper"; -import { GameAnalyticsInterface } from "./platform/game_analytics"; -import { SoundInterface } from "./platform/sound"; -import { StorageInterface } from "./platform/storage"; import { PlatformWrapperInterface } from "./platform/wrapper"; import { ApplicationSettings } from "./profile/application_settings"; import { SavegameManager } from "./savegame/savegame_manager"; @@ -34,6 +30,12 @@ import { PreloadState } from "./states/preload"; import { SettingsState } from "./states/settings"; import { ShapezGameAnalytics } from "./platform/browser/game_analytics"; +/** + * @typedef {import("./platform/game_analytics").GameAnalyticsInterface} GameAnalyticsInterface + * @typedef {import("./platform/sound").SoundInterface} SoundInterface + * @typedef {import("./platform/storage").StorageInterface} StorageInterface + */ + const logger = createLogger("application"); // Set the name of the hidden property and the change event for visibility diff --git a/src/js/changelog.js b/src/js/changelog.js index e908d062..07902b80 100644 --- a/src/js/changelog.js +++ b/src/js/changelog.js @@ -12,7 +12,8 @@ export const CHANGELOG = [ "Fix rare crash regarding the buildings toolbar (by isaisstillalive)", "Fixed some phrases (by EnderDoom77)", "Zoom towards mouse cursor (by Dimava)", - "Updated the soundtrack again, it is now 20 minutes in total!", + "Added multiple settings to optimize the performance", + "Updated the soundtrack again, it is now 40 minutes in total!", "Updated and added new translations (Thanks to all contributors!)", "Allow editing waypoints (by isaisstillalive)", "Show confirmation when cutting area which is too expensive to get pasted again (by isaisstillalive)", diff --git a/src/js/core/animation_frame.js b/src/js/core/animation_frame.js index 14147f7f..eeefb4b0 100644 --- a/src/js/core/animation_frame.js +++ b/src/js/core/animation_frame.js @@ -1,6 +1,7 @@ import { Signal } from "./signal"; -import BackgroundAnimationFrameEmitterWorker from "worker-loader?inline=true&fallback=false!../webworkers/background_animation_frame_emittter.worker"; +// @ts-ignore +import BackgroundAnimationFrameEmitterWorker from "../webworkers/background_animation_frame_emittter.worker"; import { createLogger } from "./logging"; const logger = createLogger("animation_frame"); diff --git a/src/js/core/async_compression.js b/src/js/core/async_compression.js index 9263cdab..ddc780cc 100644 --- a/src/js/core/async_compression.js +++ b/src/js/core/async_compression.js @@ -1,5 +1,8 @@ -import CompressionWorker from "worker-loader?inline=true&fallback=false!../webworkers/compression.worker"; +// @ts-ignore +import CompressionWorker from "../webworkers/compression.worker"; + import { createLogger } from "./logging"; +import { round2Digits } from "./utils"; const logger = createLogger("async_compression"); @@ -50,7 +53,15 @@ class AsynCompression { } const duration = performance.now() - jobData.startTime; - // log(this, "Got response from worker within", duration.toFixed(2), "ms"); + logger.log( + "Got job", + jobId, + "response within", + round2Digits(duration), + "ms: ", + result.length, + "bytes" + ); const resolver = jobData.resolver; delete this.currentJobs[jobId]; resolver(result); @@ -70,12 +81,13 @@ class AsynCompression { } /** - * Compresses file - * @param {string} text + * Compresses any object + * @param {any} obj */ - compressFileAsync(text) { - return this.internalQueueJob("compressFile", { - text, + compressObjectAsync(obj) { + logger.log("Compressing object async (optimized)"); + return this.internalQueueJob("compressObject", { + obj, compressionPrefix, }); } @@ -98,6 +110,8 @@ class AsynCompression { resolver: resolve, startTime: performance.now(), }; + + logger.log("Posting job", job, "/", jobId); this.worker.postMessage({ jobId, job, data }); }); } diff --git a/src/js/core/atlas_definitions.js b/src/js/core/atlas_definitions.js index 42cd2bce..38d36b59 100644 --- a/src/js/core/atlas_definitions.js +++ b/src/js/core/atlas_definitions.js @@ -1,20 +1,38 @@ /** + * @typedef {{ w: number, h: number }} Size + * @typedef {{ x: number, y: number }} Position * @typedef {{ - * frame: { x: number, y: number, w: number, h: number }, - * rotated: false, - * spriteSourceSize: { x: number, y: number, w: number, h: number }, - * sourceSize: { w: number, h: number}, - * trimmed: true + * frame: Position & Size, + * rotated: boolean, + * spriteSourceSize: Position & Size, + * sourceSize: Size, + * trimmed: boolean * }} SpriteDefinition + * + * @typedef {{ + * app: string, + * version: string, + * image: string, + * format: string, + * size: Size, + * scale: string, + * smartupdate: string + * }} AtlasMeta + * + * @typedef {{ + * frames: Object., + * meta: AtlasMeta + * }} SourceData */ export class AtlasDefinition { - constructor(sourceData) { - this.sourceFileName = sourceData.meta.image; - this.meta = sourceData.meta; - - /** @type {Object.} */ - this.sourceData = sourceData.frames; + /** + * @param {SourceData} sourceData + */ + constructor({ frames, meta }) { + this.meta = meta; + this.sourceData = frames; + this.sourceFileName = meta.image; } getFullSourcePath() { @@ -22,6 +40,7 @@ export class AtlasDefinition { } } +/** @type {AtlasDefinition[]} **/ export const atlasFiles = require // @ts-ignore .context("../../../res_built/atlas/", false, /.*\.json/i) diff --git a/src/js/core/background_resources_loader.js b/src/js/core/background_resources_loader.js index 213e5869..b3a7671b 100644 --- a/src/js/core/background_resources_loader.js +++ b/src/js/core/background_resources_loader.js @@ -115,7 +115,6 @@ export class BackgroundResourcesLoader { }) .then(() => { logger.log("⏰ Finish load: bare game"); - Loader.createAtlasLinks(); this.bareGameReady = true; initBuildingCodesAfterResourcesLoaded(); this.signalBareGameLoaded.dispatch(); diff --git a/src/js/core/buffer_maintainer.js b/src/js/core/buffer_maintainer.js index c92a92a5..c28c0ee5 100644 --- a/src/js/core/buffer_maintainer.js +++ b/src/js/core/buffer_maintainer.js @@ -95,15 +95,18 @@ export class BufferMaintainer { } /** - * - * @param {string} key - * @param {string} subKey - * @param {function(HTMLCanvasElement, CanvasRenderingContext2D, number, number, number, object?) : void} redrawMethod - * @param {object=} additionalParams + * @param {object} param0 + * @param {string} param0.key + * @param {string} param0.subKey + * @param {number} param0.w + * @param {number} param0.h + * @param {number} param0.dpi + * @param {function(HTMLCanvasElement, CanvasRenderingContext2D, number, number, number, object?) : void} param0.redrawMethod + * @param {object=} param0.additionalParams * @returns {HTMLCanvasElement} * */ - getForKey(key, subKey, w, h, dpi, redrawMethod, additionalParams) { + getForKey({ key, subKey, w, h, dpi, redrawMethod, additionalParams }) { // First, create parent key let parent = this.cache.get(key); if (!parent) { diff --git a/src/js/core/config.js b/src/js/core/config.js index 235904d9..3f6362c1 100644 --- a/src/js/core/config.js +++ b/src/js/core/config.js @@ -32,7 +32,7 @@ export const globalConfig = { // Which dpi the assets have assetsDpi: 192 / 32, - assetsSharpness: 1.2, + assetsSharpness: 1.5, shapesSharpness: 1.4, // Production analytics @@ -45,18 +45,15 @@ export const globalConfig = { // Map mapChunkSize: 16, - mapChunkPrerenderMinZoom: -1, - mapChunkOverviewMinZoom: 0.7, + mapChunkOverviewMinZoom: 0.9, + mapChunkWorldSize: null, // COMPUTED // Belt speeds // NOTICE: Update webpack.production.config too! beltSpeedItemsPerSecond: 2, minerSpeedItemsPerSecond: 0, // COMPUTED - beltItemSpacingByLayer: { - regular: 0.63, - wires: 0.4, - }, + itemSpacingOnBelts: 0.63, wiresSpeedItemsPerSecond: 6, @@ -74,6 +71,7 @@ export const globalConfig = { mixer: 1 / 5, stacker: 1 / 6, advancedProcessor: 1 / 3, + filter: 1, }, // Zooming @@ -113,17 +111,17 @@ export const IS_MOBILE = /iPhone|iPad|iPod|Android/i.test(navigator.userAgent); // Automatic calculations globalConfig.minerSpeedItemsPerSecond = globalConfig.beltSpeedItemsPerSecond / 5; +globalConfig.mapChunkWorldSize = globalConfig.mapChunkSize * globalConfig.tileSize; + // Dynamic calculations if (globalConfig.debug.disableMapOverview) { globalConfig.mapChunkOverviewMinZoom = 0; - globalConfig.mapChunkPrerenderMinZoom = 0; } // Stuff for making the trailer if (G_IS_DEV && globalConfig.debug.renderForTrailer) { globalConfig.debug.framePausesBetweenTicks = 32; // globalConfig.mapChunkOverviewMinZoom = 0.0; - // globalConfig.mapChunkPrerenderMinZoom = globalConfig.mapChunkOverviewMinZoom; // globalConfig.debug.instantBelts = true; // globalConfig.debug.instantProcessors = true; // globalConfig.debug.instantMiners = true; diff --git a/src/js/core/config.local.js b/src/js/core/config.local.js index 7bf9a002..ec62d3c1 100644 --- a/src/js/core/config.local.js +++ b/src/js/core/config.local.js @@ -95,5 +95,14 @@ export default { // Whether to items / s instead of items / m in stats // detailedStatistics: true, // ----------------------------------------------------------------------------------- + // Shows detailed information about which atlas is used + // showAtlasInfo: true, + // ----------------------------------------------------------------------------------- + // Renders the rotation of all wires + // renderWireRotations: true, + // ----------------------------------------------------------------------------------- + // Renders information about wire networks + // renderWireNetworkInfos: true, + // ----------------------------------------------------------------------------------- /* dev:end */ }; diff --git a/src/js/core/dpi_manager.js b/src/js/core/dpi_manager.js index 0388c5f9..b944d155 100644 --- a/src/js/core/dpi_manager.js +++ b/src/js/core/dpi_manager.js @@ -15,8 +15,8 @@ export function getDeviceDPI() { * @returns {number} Smoothed dpi */ export function smoothenDpi(dpi) { - if (dpi < 0.05) { - return 0.05; + if (dpi < 0.02) { + return 0.02; } else if (dpi < 0.1) { return round2Digits(dpi); } else if (dpi < 1) { diff --git a/src/js/core/draw_parameters.js b/src/js/core/draw_parameters.js index dcdf6d13..71971ed1 100644 --- a/src/js/core/draw_parameters.js +++ b/src/js/core/draw_parameters.js @@ -1,9 +1,9 @@ -import { Rectangle } from "./rectangle"; import { globalConfig } from "./config"; -/* typehints:start */ -import { GameRoot } from "../game/root"; -/* typehints:end */ +/** + * @typedef {import("../game/root").GameRoot} GameRoot + * @typedef {import("./rectangle").Rectangle} Rectangle + */ export class DrawParameters { constructor({ context, visibleRect, desiredAtlasScale, zoomLevel, root }) { @@ -13,7 +13,7 @@ export class DrawParameters { /** @type {Rectangle} */ this.visibleRect = visibleRect; - /** @type {number} */ + /** @type {string} */ this.desiredAtlasScale = desiredAtlasScale; /** @type {number} */ @@ -22,9 +22,5 @@ export class DrawParameters { // FIXME: Not really nice /** @type {GameRoot} */ this.root = root; - - if (G_IS_DEV && globalConfig.debug.testClipping) { - this.visibleRect = this.visibleRect.expandedInAllDirections(-100); - } } } diff --git a/src/js/core/draw_utils.js b/src/js/core/draw_utils.js index 1b37b929..d5183cfb 100644 --- a/src/js/core/draw_utils.js +++ b/src/js/core/draw_utils.js @@ -1,18 +1,19 @@ -/* typehints:start */ -import { AtlasSprite } from "./sprites"; -import { DrawParameters } from "./draw_parameters"; -/* typehints:end */ +/** + * @typedef {import("./sprites").AtlasSprite} AtlasSprite + * @typedef {import("./draw_parameters").DrawParameters} DrawParameters + */ -import { Vector } from "./vector"; -import { Rectangle } from "./rectangle"; +import { globalConfig } from "./config"; import { createLogger } from "./logging"; +import { Rectangle } from "./rectangle"; const logger = createLogger("draw_utils"); export function initDrawUtils() { CanvasRenderingContext2D.prototype.beginRoundedRect = function (x, y, w, h, r) { + this.beginPath(); + if (r < 0.05) { - this.beginPath(); this.rect(x, y, w, h); return; } @@ -20,25 +21,26 @@ export function initDrawUtils() { if (w < 2 * r) { r = w / 2; } + if (h < 2 * r) { r = h / 2; } - this.beginPath(); + this.moveTo(x + r, y); this.arcTo(x + w, y, x + w, y + h, r); this.arcTo(x + w, y + h, x, y + h, r); this.arcTo(x, y + h, x, y, r); this.arcTo(x, y, x + w, y, r); - // this.closePath(); }; CanvasRenderingContext2D.prototype.beginCircle = function (x, y, r) { + this.beginPath(); + if (r < 0.05) { - this.beginPath(); this.rect(x, y, 1, 1); return; } - this.beginPath(); + this.arc(x, y, r, 0, 2.0 * Math.PI); }; } @@ -56,6 +58,11 @@ export function initDrawUtils() { * @param {number=} param0.offsetY */ export function drawRotatedSprite({ parameters, sprite, x, y, angle, size, offsetX = 0, offsetY = 0 }) { + if (angle === 0) { + sprite.drawCachedCentered(parameters, x + offsetX, y + offsetY, size); + return; + } + parameters.context.translate(x, y); parameters.context.rotate(angle); sprite.drawCachedCentered(parameters, offsetX, offsetY, size, false); @@ -63,258 +70,52 @@ export function drawRotatedSprite({ parameters, sprite, x, y, angle, size, offse parameters.context.translate(-x, -y); } -export function drawLineFast(context, { x1, x2, y1, y2, color = null, lineSize = 1 }) { - const dX = x2 - x1; - const dY = y2 - y1; +let warningsShown = 0; - const angle = Math.atan2(dY, dX) + 0.0 * Math.PI; - const len = Math.hypot(dX, dY); - - context.translate(x1, y1); - context.rotate(angle); - - if (color) { - context.fillStyle = color; - } - - context.fillRect(0, -lineSize / 2, len, lineSize); - - context.rotate(-angle); - context.translate(-x1, -y1); -} - -const INSIDE = 0; -const LEFT = 1; -const RIGHT = 2; -const BOTTOM = 4; -const TOP = 8; - -// https://en.wikipedia.org/wiki/Cohen%E2%80%93Sutherland_algorithm - -function computeOutCode(x, y, xmin, xmax, ymin, ymax) { - let code = INSIDE; - - if (x < xmin) - // to the left of clip window - code |= LEFT; - else if (x > xmax) - // to the right of clip window - code |= RIGHT; - if (y < ymin) - // below the clip window - code |= BOTTOM; - else if (y > ymax) - // above the clip window - code |= TOP; - - return code; -} - -// Cohen–Sutherland clipping algorithm clips a line from -// P0 = (x0, y0) to P1 = (x1, y1) against a rectangle with -// diagonal from (xmin, ymin) to (xmax, ymax). /** - * - * @param {CanvasRenderingContext2D} context + * Draws a sprite with clipping + * @param {object} param0 + * @param {DrawParameters} param0.parameters + * @param {HTMLCanvasElement} param0.sprite + * @param {number} param0.x + * @param {number} param0.y + * @param {number} param0.w + * @param {number} param0.h + * @param {number} param0.originalW + * @param {number} param0.originalH */ -export function drawLineFastClipped(context, rect, { x0, y0, x1, y1, color = null, lineSize = 1 }) { - const xmin = rect.x; - const ymin = rect.y; - const xmax = rect.right(); - const ymax = rect.bottom(); - - // compute outcodes for P0, P1, and whatever point lies outside the clip rectangle - let outcode0 = computeOutCode(x0, y0, xmin, xmax, ymin, ymax); - let outcode1 = computeOutCode(x1, y1, xmin, xmax, ymin, ymax); - let accept = false; - - // eslint-disable-next-line no-constant-condition - while (true) { - if (!(outcode0 | outcode1)) { - // bitwise OR is 0: both points inside window; trivially accept and exit loop - accept = true; - break; - } else if (outcode0 & outcode1) { - // bitwise AND is not 0: both points share an outside zone (LEFT, RIGHT, TOP, - // or BOTTOM), so both must be outside window; exit loop (accept is false) - break; - } else { - // failed both tests, so calculate the line segment to clip - // from an outside point to an intersection with clip edge - let x, y; - - // At least one endpoint is outside the clip rectangle; pick it. - let outcodeOut = outcode0 ? outcode0 : outcode1; - - // Now find the intersection point; - // use formulas: - // slope = (y1 - y0) / (x1 - x0) - // x = x0 + (1 / slope) * (ym - y0), where ym is ymin or ymax - // y = y0 + slope * (xm - x0), where xm is xmin or xmax - // No need to worry about divide-by-zero because, in each case, the - // outcode bit being tested guarantees the denominator is non-zero - if (outcodeOut & TOP) { - // point is above the clip window - x = x0 + ((x1 - x0) * (ymax - y0)) / (y1 - y0); - y = ymax; - } else if (outcodeOut & BOTTOM) { - // point is below the clip window - x = x0 + ((x1 - x0) * (ymin - y0)) / (y1 - y0); - y = ymin; - } else if (outcodeOut & RIGHT) { - // point is to the right of clip window - y = y0 + ((y1 - y0) * (xmax - x0)) / (x1 - x0); - x = xmax; - } else if (outcodeOut & LEFT) { - // point is to the left of clip window - y = y0 + ((y1 - y0) * (xmin - x0)) / (x1 - x0); - x = xmin; - } - - // Now we move outside point to intersection point to clip - // and get ready for next pass. - if (outcodeOut == outcode0) { - x0 = x; - y0 = y; - outcode0 = computeOutCode(x0, y0, xmin, xmax, ymin, ymax); - } else { - x1 = x; - y1 = y; - outcode1 = computeOutCode(x1, y1, xmin, xmax, ymin, ymax); - } +export function drawSpriteClipped({ parameters, sprite, x, y, w, h, originalW, originalH }) { + const rect = new Rectangle(x, y, w, h); + const intersection = rect.getIntersection(parameters.visibleRect); + if (!intersection) { + // Clipped + if (++warningsShown % 200 === 1) { + logger.warn( + "Sprite drawn clipped but it's not on screen - perform culling before (", + warningsShown, + "warnings)" + ); } - } - if (accept) { - // Following functions are left for implementation by user based on - // their platform (OpenGL/graphics.h etc.) - // DrawRectangle(xmin, ymin, xmax, ymax); - // LineSegment(x0, y0, x1, y1); - drawLineFast(context, { - x1: x0, - y1: y0, - x2: x1, - y2: y1, - color, - lineSize, - }); - } -} - -/** - * Converts an HSL color value to RGB. Conversion formula - * adapted from http://en.wikipedia.org/wiki/HSL_color_space. - * Assumes h, s, and l are contained in the set [0, 1] and - * returns r, g, and b in the set [0, 255]. - * - * @param {number} h The hue - * @param {number} s The saturation - * @param {number} l The lightness - * @return {Array} The RGB representation - */ -export function hslToRgb(h, s, l) { - let r; - let g; - let b; - - if (s === 0) { - r = g = b = l; // achromatic - } else { - // tslint:disable-next-line:no-shadowed-variable - const hue2rgb = function (p, q, t) { - if (t < 0) { - t += 1; - } - if (t > 1) { - t -= 1; - } - if (t < 1 / 6) { - return p + (q - p) * 6 * t; - } - if (t < 1 / 2) { - return q; - } - if (t < 2 / 3) { - return p + (q - p) * (2 / 3 - t) * 6; - } - return p; - }; - - let q = l < 0.5 ? l * (1 + s) : l + s - l * s; - let p = 2 * l - q; - r = hue2rgb(p, q, h + 1 / 3); - g = hue2rgb(p, q, h); - b = hue2rgb(p, q, h - 1 / 3); - } - - return [Math.round(r * 255), Math.round(g * 255), Math.round(b * 255)]; -} - -export function wrapText(context, text, x, y, maxWidth, lineHeight, stroke = false) { - var words = text.split(" "); - var line = ""; - - for (var n = 0; n < words.length; n++) { - var testLine = line + words[n] + " "; - var metrics = context.measureText(testLine); - var testWidth = metrics.width; - if (testWidth > maxWidth && n > 0) { - if (stroke) { - context.strokeText(line, x, y); - } else { - context.fillText(line, x, y); - } - line = words[n] + " "; - y += lineHeight; - } else { - line = testLine; + if (G_IS_DEV && globalConfig.debug.testClipping) { + parameters.context.fillStyle = "yellow"; + parameters.context.fillRect(x, y, w, h); } + return; } - if (stroke) { - context.strokeText(line, x, y); - } else { - context.fillText(line, x, y); - } -} + parameters.context.drawImage( + sprite, -/** - * Returns a rotated trapez, used for spotlight culling - * @param {number} x - * @param {number} y - * @param {number} w - * @param {number} h - * @param {number} leftHeight - * @param {number} angle - */ -export function rotateTrapezRightFaced(x, y, w, h, leftHeight, angle) { - const halfY = y + h / 2; - const points = [ - new Vector(x, halfY - leftHeight / 2), - new Vector(x + w, y), - new Vector(x, halfY + leftHeight / 2), - new Vector(x + w, y + h), - ]; + // src pos and size + ((intersection.x - x) / w) * originalW, + ((intersection.y - y) / h) * originalH, + (originalW * intersection.w) / w, + (originalH * intersection.h) / h, - return Rectangle.getAroundPointsRotated(points, angle); -} - -/** - * Converts values from 0 .. 255 to values like 07, 7f, 5d etc - * @param {number} value - * @returns {string} - */ -export function mapClampedColorValueToHex(value) { - const hex = "0123456789abcdef"; - return hex[Math.floor(value / 16)] + hex[value % 16]; -} - -/** - * Converts rgb to a hex string - * @param {number} r - * @param {number} g - * @param {number} b - * @returns {string} - */ -export function rgbToHex(r, g, b) { - return mapClampedColorValueToHex(r) + mapClampedColorValueToHex(g) + mapClampedColorValueToHex(b); + // dest pos and size + intersection.x, + intersection.y, + intersection.w, + intersection.h + ); } diff --git a/src/js/core/global_registries.js b/src/js/core/global_registries.js index 321732e0..ad45850c 100644 --- a/src/js/core/global_registries.js +++ b/src/js/core/global_registries.js @@ -1,19 +1,19 @@ import { SingletonFactory } from "./singleton_factory"; import { Factory } from "./factory"; -/* typehints:start */ -import { BaseGameSpeed } from "../game/time/base_game_speed"; -import { Component } from "../game/component"; -import { BaseItem } from "../game/base_item"; -import { MetaBuilding } from "../game/meta_building"; -/* typehints:end */ +/** + * @typedef {import("../game/time/base_game_speed").BaseGameSpeed} BaseGameSpeed + * @typedef {import("../game/component").Component} Component + * @typedef {import("../game/base_item").BaseItem} BaseItem + * @typedef {import("../game/meta_building").MetaBuilding} MetaBuilding + // These factories are here to remove circular dependencies /** @type {SingletonFactoryTemplate} */ export let gMetaBuildingRegistry = new SingletonFactory(); -/** @type {Object.>} */ +/** @type {Object.>>} */ export let gBuildingsByCategory = null; /** @type {FactoryTemplate} */ @@ -28,7 +28,7 @@ export let gItemRegistry = new Factory("item"); // Helpers /** - * @param {Object.>} buildings + * @param {Object.>>} buildings */ export function initBuildingsByCategory(buildings) { gBuildingsByCategory = buildings; diff --git a/src/js/core/loader.js b/src/js/core/loader.js index 8888ecbf..d7f544e3 100644 --- a/src/js/core/loader.js +++ b/src/js/core/loader.js @@ -1,20 +1,19 @@ -/* typehints:start */ -import { Application } from "../application"; -/* typehints:end */ - -import { AtlasDefinition } from "./atlas_definitions"; import { makeOffscreenBuffer } from "./buffer_utils"; import { AtlasSprite, BaseSprite, RegularSprite, SpriteAtlasLink } from "./sprites"; import { cachebust } from "./cachebust"; import { createLogger } from "./logging"; +/** + * @typedef {import("../application").Application} Application + * @typedef {import("./atlas_definitions").AtlasDefinition} AtlasDefinition; + */ + const logger = createLogger("loader"); const missingSpriteIds = {}; class LoaderImpl { constructor() { - /** @type {Application} */ this.app = null; /** @type {Map} */ @@ -23,6 +22,9 @@ class LoaderImpl { this.rawImages = []; } + /** + * @param {Application} app + */ linkAppAfterBoot(app) { this.app = app; this.makeSpriteNotFoundCanvas(); @@ -58,7 +60,7 @@ class LoaderImpl { } /** - * Retursn a regular sprite from the cache + * Returns a regular sprite from the cache * @param {string} key * @returns {RegularSprite} */ @@ -155,44 +157,34 @@ class LoaderImpl { * @param {AtlasDefinition} atlas * @param {HTMLImageElement} loadedImage */ - internalParseAtlas(atlas, loadedImage) { + internalParseAtlas({ meta: { scale }, sourceData }, loadedImage) { this.rawImages.push(loadedImage); - for (const spriteKey in atlas.sourceData) { - const spriteData = atlas.sourceData[spriteKey]; + for (const spriteName in sourceData) { + const { frame, sourceSize, spriteSourceSize } = sourceData[spriteName]; - let sprite = /** @type {AtlasSprite} */ (this.sprites.get(spriteKey)); + let sprite = /** @type {AtlasSprite} */ (this.sprites.get(spriteName)); if (!sprite) { - sprite = new AtlasSprite({ - spriteName: spriteKey, - }); - this.sprites.set(spriteKey, sprite); + sprite = new AtlasSprite(spriteName); + this.sprites.set(spriteName, sprite); } const link = new SpriteAtlasLink({ - packedX: spriteData.frame.x, - packedY: spriteData.frame.y, - packedW: spriteData.frame.w, - packedH: spriteData.frame.h, - packOffsetX: spriteData.spriteSourceSize.x, - packOffsetY: spriteData.spriteSourceSize.y, + packedX: frame.x, + packedY: frame.y, + packedW: frame.w, + packedH: frame.h, + packOffsetX: spriteSourceSize.x, + packOffsetY: spriteSourceSize.y, atlas: loadedImage, - w: spriteData.sourceSize.w, - h: spriteData.sourceSize.h, + w: sourceSize.w, + h: sourceSize.h, }); - sprite.linksByResolution[atlas.meta.scale] = link; + sprite.linksByResolution[scale] = link; } } - /** - * Creates the links for the sprites after the atlas has been loaded. Used so we - * don't have to store duplicate sprites. - */ - createAtlasLinks() { - // NOT USED - } - /** * Makes the canvas which shows the question mark, shown when a sprite was not found */ @@ -216,14 +208,9 @@ class LoaderImpl { // @ts-ignore canvas.src = "not-found"; - const resolutions = ["0.1", "0.25", "0.5", "0.75", "1"]; - const sprite = new AtlasSprite({ - spriteName: "not-found", - }); - - for (let i = 0; i < resolutions.length; ++i) { - const res = resolutions[i]; - const link = new SpriteAtlasLink({ + const sprite = new AtlasSprite("not-found"); + ["0.1", "0.25", "0.5", "0.75", "1"].forEach(resolution => { + sprite.linksByResolution[resolution] = new SpriteAtlasLink({ packedX: 0, packedY: 0, w: dims, @@ -234,8 +221,8 @@ class LoaderImpl { packedH: dims, atlas: canvas, }); - sprite.linksByResolution[res] = link; - } + }); + this.spriteNotFoundSprite = sprite; } } diff --git a/src/js/core/read_write_proxy.js b/src/js/core/read_write_proxy.js index 3444057a..48e12b4c 100644 --- a/src/js/core/read_write_proxy.js +++ b/src/js/core/read_write_proxy.js @@ -2,7 +2,7 @@ import { Application } from "../application"; /* typehints:end */ -import { sha1 } from "./sensitive_utils.encrypt"; +import { sha1, CRC_PREFIX, computeCrc } from "./sensitive_utils.encrypt"; import { createLogger } from "./logging"; import { FILE_NOT_FOUND } from "../platform/storage"; import { accessNestedPropertyReverse } from "./utils"; @@ -84,7 +84,7 @@ export class ReadWriteProxy { */ static serializeObject(obj) { const jsonString = JSON.stringify(compressObject(obj)); - const checksum = sha1(jsonString + salt); + const checksum = computeCrc(jsonString + salt); return compressionPrefix + compressX64(checksum + jsonString); } @@ -106,7 +106,11 @@ export class ReadWriteProxy { // Compare stored checksum with actual checksum const checksum = decompressed.substring(0, 40); const jsonString = decompressed.substr(40); - const desiredChecksum = sha1(jsonString + salt); + + const desiredChecksum = checksum.startsWith(CRC_PREFIX) + ? computeCrc(jsonString + salt) + : sha1(jsonString + salt); + if (desiredChecksum !== checksum) { // Checksum mismatch throw new Error("bad-content / checksum-mismatch"); @@ -119,7 +123,7 @@ export class ReadWriteProxy { /** * Writes the data asychronously, fails if verify() fails - * @returns {Promise} + * @returns {Promise} */ writeAsync() { const verifyResult = this.internalVerifyEntry(this.currentData); @@ -128,35 +132,14 @@ export class ReadWriteProxy { logger.error("Tried to write invalid data to", this.filename, "reason:", verifyResult.reason); return Promise.reject(verifyResult.reason); } - const jsonString = JSON.stringify(compressObject(this.currentData)); - - // if (!this.app.pageVisible || this.app.unloaded) { - // logger.log("Saving file sync because in unload handler"); - // const checksum = sha1(jsonString + salt); - // let compressed = compressionPrefix + compressX64(checksum + jsonString); - // if (G_IS_DEV && IS_DEBUG) { - // compressed = jsonString; - // } - - // if (!this.app.storage.writeFileSyncIfSupported(this.filename, compressed)) { - // return Promise.reject("Failed to write " + this.filename + " sync!"); - // } else { - // logger.log("📄 Wrote (sync!)", this.filename); - // return Promise.resolve(compressed); - // } - // } return asyncCompressor - .compressFileAsync(jsonString) + .compressObjectAsync(this.currentData) .then(compressed => { - if (G_IS_DEV && IS_DEBUG) { - compressed = jsonString; - } return this.app.storage.writeFileAsync(this.filename, compressed); }) .then(() => { logger.log("📄 Wrote", this.filename); - return jsonString; }) .catch(err => { logger.error("Failed to write", this.filename, ":", err); @@ -205,10 +188,16 @@ export class ReadWriteProxy { // Compare stored checksum with actual checksum const checksum = decompressed.substring(0, 40); const jsonString = decompressed.substr(40); - const desiredChecksum = sha1(jsonString + salt); + + const desiredChecksum = checksum.startsWith(CRC_PREFIX) + ? computeCrc(jsonString + salt) + : sha1(jsonString + salt); + if (desiredChecksum !== checksum) { // Checksum mismatch - return Promise.reject("bad-content / checksum-mismatch"); + return Promise.reject( + "bad-content / checksum-mismatch: " + desiredChecksum + " vs " + checksum + ); } return jsonString; } else { diff --git a/src/js/core/rectangle.js b/src/js/core/rectangle.js index 75279e58..1cbfdc27 100644 --- a/src/js/core/rectangle.js +++ b/src/js/core/rectangle.js @@ -1,5 +1,5 @@ import { globalConfig } from "./config"; -import { clamp, epsilonCompare, round2Digits } from "./utils"; +import { epsilonCompare, round2Digits } from "./utils"; import { Vector } from "./vector"; export class Rectangle { @@ -376,24 +376,33 @@ export class Rectangle { ); } + /** + * Good for printing stuff + */ + toString() { + return ( + "[x:" + + round2Digits(this.x) + + "| y:" + + round2Digits(this.y) + + "| w:" + + round2Digits(this.w) + + "| h:" + + round2Digits(this.h) + + "]" + ); + } + /** * Returns a new recangle in tile space which includes all tiles which are visible in this rect - * @param {boolean=} includeHalfTiles * @returns {Rectangle} */ - toTileCullRectangle(includeHalfTiles = true) { - let scaled = this.allScaled(1.0 / globalConfig.tileSize); - - if (includeHalfTiles) { - // Increase rectangle size - scaled = Rectangle.fromTRBL( - Math.floor(scaled.y), - Math.ceil(scaled.right()), - Math.ceil(scaled.bottom()), - Math.floor(scaled.x) - ); - } - - return scaled; + toTileCullRectangle() { + return new Rectangle( + Math.floor(this.x / globalConfig.tileSize), + Math.floor(this.y / globalConfig.tileSize), + Math.ceil(this.w / globalConfig.tileSize), + Math.ceil(this.h / globalConfig.tileSize) + ); } } diff --git a/src/js/core/sensitive_utils.encrypt.js b/src/js/core/sensitive_utils.encrypt.js index 0a8906e7..5a83bf76 100644 --- a/src/js/core/sensitive_utils.encrypt.js +++ b/src/js/core/sensitive_utils.encrypt.js @@ -1,5 +1,5 @@ import { createHash } from "rusha"; - +import crc32 from "crc/crc32"; import { decompressX64 } from "./lzstring"; export function sha1(str) { @@ -10,3 +10,14 @@ export function sha1(str) { export function getNameOfProvider() { return window[decompressX64("DYewxghgLgliB2Q")][decompressX64("BYewzgLgdghgtgUyA")]; } + +// Distinguish legacy crc prefixes +export const CRC_PREFIX = "crc32".padEnd(32, "-"); + +/** + * Computes the crc for a given string + * @param {string} str + */ +export function computeCrc(str) { + return CRC_PREFIX + crc32(str).toString(16).padStart(8, "0"); +} diff --git a/src/js/core/sprites.js b/src/js/core/sprites.js index 8427f2ef..bdcc65b4 100644 --- a/src/js/core/sprites.js +++ b/src/js/core/sprites.js @@ -1,10 +1,10 @@ import { DrawParameters } from "./draw_parameters"; import { Rectangle } from "./rectangle"; -import { epsilonCompare, round3Digits } from "./utils"; +import { round3Digits } from "./utils"; const floorSpriteCoordinates = false; -const ORIGINAL_SCALE = "1"; +export const ORIGINAL_SPRITE_SCALE = "0.75"; export class BaseSprite { /** @@ -63,10 +63,9 @@ export class SpriteAtlasLink { export class AtlasSprite extends BaseSprite { /** * - * @param {object} param0 - * @param {string} param0.spriteName + * @param {string} spriteName */ - constructor({ spriteName = "sprite" }) { + constructor(spriteName = "sprite") { super(); /** @type {Object.} */ this.linksByResolution = {}; @@ -74,7 +73,7 @@ export class AtlasSprite extends BaseSprite { } getRawTexture() { - return this.linksByResolution[ORIGINAL_SCALE].atlas; + return this.linksByResolution[ORIGINAL_SPRITE_SCALE].atlas; } /** @@ -86,11 +85,15 @@ export class AtlasSprite extends BaseSprite { assert(context instanceof CanvasRenderingContext2D, "Not a valid context"); } - const link = this.linksByResolution[ORIGINAL_SCALE]; + const link = this.linksByResolution[ORIGINAL_SPRITE_SCALE]; assert( link, - "Link not known: " + ORIGINAL_SCALE + " (having " + Object.keys(this.linksByResolution) + ")" + "Link not known: " + + ORIGINAL_SPRITE_SCALE + + " (having " + + Object.keys(this.linksByResolution) + + ")" ); const width = w || link.w; @@ -197,8 +200,6 @@ export class AtlasSprite extends BaseSprite { destH = intersection.h; } - // assert(epsilonCompare(scaleW, scaleH), "Sprite should be square for cached rendering"); - if (floorSpriteCoordinates) { parameters.context.drawImage( link.atlas, diff --git a/src/js/core/stale_area_detector.js b/src/js/core/stale_area_detector.js new file mode 100644 index 00000000..f8e77f0c --- /dev/null +++ b/src/js/core/stale_area_detector.js @@ -0,0 +1,50 @@ +import { createLogger } from "./logging"; +import { Rectangle } from "./rectangle"; +import { globalConfig } from "./config"; + +const logger = createLogger("stale_areas"); + +export class StaleAreaDetector { + /** + * + * @param {object} param0 + * @param {import("../game/root").GameRoot} param0.root + * @param {string} param0.name The name for reference + * @param {(Rectangle) => void} param0.recomputeMethod Method which recomputes the given area + */ + constructor({ root, name, recomputeMethod }) { + this.root = root; + this.name = name; + this.recomputeMethod = recomputeMethod; + + /** @type {Rectangle} */ + this.staleArea = null; + } + + /** + * Invalidates the given area + * @param {Rectangle} area + */ + invalidate(area) { + // logger.log(this.name, "invalidated", area.toString()); + if (this.staleArea) { + this.staleArea = this.staleArea.getUnion(area); + } else { + this.staleArea = area.clone(); + } + } + + /** + * Updates the stale area + */ + update() { + if (this.staleArea) { + logger.log(this.name, "is recomputing", this.staleArea.toString()); + if (G_IS_DEV && globalConfig.debug.renderChanges) { + this.root.hud.parts.changesDebugger.renderChange(this.name, this.staleArea, "#fd145b"); + } + this.recomputeMethod(this.staleArea); + this.staleArea = null; + } + } +} diff --git a/src/js/core/utils.js b/src/js/core/utils.js index cb00e465..4cb41087 100644 --- a/src/js/core/utils.js +++ b/src/js/core/utils.js @@ -1,46 +1,7 @@ -import { globalConfig, IS_DEBUG } from "./config"; -import { Vector } from "./vector"; import { T } from "../translations"; -// Constants -export const TOP = new Vector(0, -1); -export const RIGHT = new Vector(1, 0); -export const BOTTOM = new Vector(0, 1); -export const LEFT = new Vector(-1, 0); -export const ALL_DIRECTIONS = [TOP, RIGHT, BOTTOM, LEFT]; - const bigNumberSuffixTranslationKeys = ["thousands", "millions", "billions", "trillions"]; -/** - * Returns the build id - * @returns {string} - */ -export function getBuildId() { - if (G_IS_DEV && IS_DEBUG) { - return "local-dev"; - } else if (G_IS_DEV) { - return "dev-" + getPlatformName() + "-" + G_BUILD_COMMIT_HASH; - } else { - return "prod-" + getPlatformName() + "-" + G_BUILD_COMMIT_HASH; - } -} - -/** - * Returns the environment id (dev, prod, etc) - * @returns {string} - */ -export function getEnvironmentId() { - if (G_IS_DEV && IS_DEBUG) { - return "local-dev"; - } else if (G_IS_DEV) { - return "dev-" + getPlatformName(); - } else if (G_IS_RELEASE) { - return "release-" + getPlatformName(); - } else { - return "staging-" + getPlatformName(); - } -} - /** * Returns if this platform is android * @returns {boolean} @@ -66,7 +27,7 @@ export function isIos() { /** * Returns a platform name - * @returns {string} + * @returns {"android" | "browser" | "ios" | "standalone" | "unknown"} */ export function getPlatformName() { if (G_IS_STANDALONE) { @@ -96,60 +57,13 @@ export function getIPCRenderer() { return ipcRenderer; } -/** - * Formats a sensitive token by only displaying the first digits of it. Use for - * stuff like savegame keys etc which should not appear in the log. - * @param {string} key - */ -export function formatSensitive(key) { - if (!key) { - return ""; - } - key = key || ""; - return "[" + key.substr(0, 8) + "...]"; -} - -/** - * Creates a new 2D array with the given fill method - * @param {number} w Width - * @param {number} h Height - * @param {(function(number, number) : any) | number | boolean | string | null | undefined} filler Either Fill method, which should return the content for each cell, or static content - * @param {string=} context Optional context for memory tracking - * @returns {Array>} - */ -export function make2DArray(w, h, filler, context = null) { - if (typeof filler === "function") { - const tiles = new Array(w); - for (let x = 0; x < w; ++x) { - const row = new Array(h); - for (let y = 0; y < h; ++y) { - row[y] = filler(x, y); - } - tiles[x] = row; - } - return tiles; - } else { - const tiles = new Array(w); - const row = new Array(h); - for (let y = 0; y < h; ++y) { - row[y] = filler; - } - - for (let x = 0; x < w; ++x) { - tiles[x] = row.slice(); - } - return tiles; - } -} - /** * Makes a new 2D array with undefined contents * @param {number} w * @param {number} h - * @param {string=} context * @returns {Array>} */ -export function make2DUndefinedArray(w, h, context = null) { +export function make2DUndefinedArray(w, h) { const result = new Array(w); for (let x = 0; x < w; ++x) { result[x] = new Array(h); @@ -157,33 +71,6 @@ export function make2DUndefinedArray(w, h, context = null) { return result; } -/** - * Clears a given 2D array with the given fill method - * @param {Array>} array - * @param {number} w Width - * @param {number} h Height - * @param {(function(number, number) : any) | number | boolean | string | null | undefined} filler Either Fill method, which should return the content for each cell, or static content - */ -export function clear2DArray(array, w, h, filler) { - assert(array.length === w, "Array dims mismatch w"); - assert(array[0].length === h, "Array dims mismatch h"); - if (typeof filler === "function") { - for (let x = 0; x < w; ++x) { - const row = array[x]; - for (let y = 0; y < h; ++y) { - row[y] = filler(x, y); - } - } - } else { - for (let x = 0; x < w; ++x) { - const row = array[x]; - for (let y = 0; y < h; ++y) { - row[y] = filler; - } - } - } -} - /** * Creates a new map (an empty object without any props) */ @@ -215,7 +102,9 @@ export function accessNestedPropertyReverse(obj, keys) { /** * Chooses a random entry of an array - * @param {Array | string} arr + * @template T + * @param {T[]} arr + * @returns {T} */ export function randomChoice(arr) { return arr[Math.floor(Math.random() * arr.length)]; @@ -304,23 +193,6 @@ export function arrayDeleteValue(array, value) { return arrayDelete(array, index); } -// Converts a direction into a 0 .. 7 index -/** - * Converts a direction into a index from 0 .. 7, used for miners, zombies etc which have 8 sprites - * @param {Vector} offset direction - * @param {boolean} inverse if inverse, the direction is reversed - * @returns {number} in range [0, 7] - */ -export function angleToSpriteIndex(offset, inverse = false) { - const twoPi = 2.0 * Math.PI; - const factor = inverse ? -1 : 1; - const offs = inverse ? 2.5 : 3.5; - const angle = (factor * Math.atan2(offset.y, offset.x) + offs * Math.PI) % twoPi; - - const index = Math.round((angle / twoPi) * 8) % 8; - return index; -} - /** * Compare two floats for epsilon equality * @param {number} a @@ -331,15 +203,6 @@ export function epsilonCompare(a, b, epsilon = 1e-5) { return Math.abs(a - b) < epsilon; } -/** - * Compare a float for epsilon equal to 0 - * @param {number} a - * @returns {boolean} - */ -export function epsilonIsZero(a) { - return epsilonCompare(a, 0); -} - /** * Interpolates two numbers * @param {number} a @@ -399,17 +262,6 @@ export function findNiceIntegerValue(num) { return Math.ceil(findNiceValue(num)); } -/** - * Smart rounding + fractional handling - * @param {number} n - */ -function roundSmart(n) { - if (n < 100) { - return n.toFixed(1); - } - return Math.round(n); -} - /** * Formats a big number * @param {number} num @@ -477,92 +329,12 @@ export function formatBigNumberFull(num, divider = T.global.thousandsDivider) { return out.substring(0, out.length - 1); } -/** - * Delayes a promise so that it will resolve after a *minimum* amount of time only - * @param {Promise} promise The promise to delay - * @param {number} minTimeMs The time to make it run at least - * @returns {Promise} The delayed promise - */ -export function artificialDelayedPromise(promise, minTimeMs = 500) { - if (G_IS_DEV && globalConfig.debug.noArtificialDelays) { - return promise; - } - - const startTime = performance.now(); - return promise.then( - result => { - const timeTaken = performance.now() - startTime; - const waitTime = Math.floor(minTimeMs - timeTaken); - if (waitTime > 0) { - return new Promise(resolve => { - setTimeout(() => { - resolve(result); - }, waitTime); - }); - } else { - return result; - } - }, - error => { - const timeTaken = performance.now() - startTime; - const waitTime = Math.floor(minTimeMs - timeTaken); - if (waitTime > 0) { - // @ts-ignore - return new Promise((resolve, reject) => { - setTimeout(() => { - reject(error); - }, waitTime); - }); - } else { - throw error; - } - } - ); -} - -/** - * Computes a sine-based animation which pulsates from 0 .. 1 .. 0 - * @param {number} time Current time in seconds - * @param {number} duration Duration of the full pulse in seconds - * @param {number} seed Seed to offset the animation - */ -export function pulseAnimation(time, duration = 1.0, seed = 0.0) { - return Math.sin((time * Math.PI * 2.0) / duration + seed * 5642.86729349) * 0.5 + 0.5; -} - -/** - * Returns the smallest angle between two angles - * @param {number} a - * @param {number} b - * @returns {number} 0 .. 2 PI - */ -export function smallestAngle(a, b) { - return safeMod(a - b + Math.PI, 2.0 * Math.PI) - Math.PI; -} - -/** - * Modulo which works for negative numbers - * @param {number} n - * @param {number} m - */ -export function safeMod(n, m) { - return ((n % m) + m) % m; -} - -/** - * Wraps an angle between 0 and 2 pi - * @param {number} angle - */ -export function wrapAngle(angle) { - return safeMod(angle, 2.0 * Math.PI); -} - /** * Waits two frames so the ui is updated * @returns {Promise} */ export function waitNextFrame() { - return new Promise(function (resolve, reject) { + return new Promise(function (resolve) { window.requestAnimationFrame(function () { window.requestAnimationFrame(function () { resolve(); @@ -617,27 +389,13 @@ export function clamp(v, minimum = 0, maximum = 1) { return Math.max(minimum, Math.min(maximum, v)); } -/** - * Measures how long a function took - * @param {string} name - * @param {function():void} target - */ -export function measure(name, target) { - const now = performance.now(); - for (let i = 0; i < 25; ++i) { - target(); - } - const dur = (performance.now() - now) / 25.0; - console.warn("->", name, "took", dur.toFixed(2), "ms"); -} - /** * Helper method to create a new div element * @param {string=} id * @param {Array=} classes * @param {string=} innerHTML */ -export function makeDivElement(id = null, classes = [], innerHTML = "") { +function makeDivElement(id = null, classes = [], innerHTML = "") { const div = document.createElement("div"); if (id) { div.id = id; @@ -662,20 +420,6 @@ export function makeDiv(parent, id = null, classes = [], innerHTML = "") { return div; } -/** - * Helper method to create a new div and place before reference Node - * @param {Element} parent - * @param {Element} referenceNode - * @param {string=} id - * @param {Array=} classes - * @param {string=} innerHTML - */ -export function makeDivBefore(parent, referenceNode, id = null, classes = [], innerHTML = "") { - const div = makeDivElement(id, classes, innerHTML); - parent.insertBefore(div, referenceNode); - return div; -} - /** * Helper method to create a new button element * @param {Array=} classes @@ -703,19 +447,6 @@ export function makeButton(parent, classes = [], innerHTML = "") { return element; } -/** - * Helper method to create a new button and place before reference Node - * @param {Element} parent - * @param {Element} referenceNode - * @param {Array=} classes - * @param {string=} innerHTML - */ -export function makeButtonBefore(parent, referenceNode, classes = [], innerHTML = "") { - const element = makeButtonElement(classes, innerHTML); - parent.insertBefore(element, referenceNode); - return element; -} - /** * Removes all children of the given element * @param {Element} elem @@ -728,20 +459,10 @@ export function removeAllChildren(elem) { } } -export function smartFadeNumber(current, newOne, minFade = 0.01, maxFade = 0.9) { - const tolerance = Math.min(current, newOne) * 0.5 + 10; - let fade = minFade; - if (Math.abs(current - newOne) < tolerance) { - fade = maxFade; - } - - return current * fade + newOne * (1 - fade); -} - /** * Fixes lockstep simulation by converting times like 34.0000000003 to 34.00. - * We use 3 digits of precision, this allows to store sufficient precision of 1 ms without - * the risk to simulation errors due to resync issues + * We use 3 digits of precision, this allows us to store precision of 1 ms without + * the risking simulation errors due to resync issues * @param {number} value */ export function quantizeFloat(value) { @@ -840,37 +561,6 @@ export function isSupportedBrowser() { } } -/** - * Helper function to create a json schema object - * @param {any} properties - */ -export function schemaObject(properties) { - return { - type: "object", - required: Object.keys(properties).slice(), - additionalProperties: false, - properties, - }; -} - -/** - * Quickly - * @param {number} x - * @param {number} y - * @param {number} deg - * @returns {Vector} - */ -export function fastRotateMultipleOf90(x, y, deg) { - switch (deg) { - case 0: { - return new Vector(x, y); - } - case 90: { - return new Vector(x, y); - } - } -} - /** * Formats an amount of seconds into something like "5s ago" * @param {number} secs Seconds @@ -928,31 +618,6 @@ export function formatSeconds(secs) { } } -/** - * Generates a file download - * @param {string} filename - * @param {string} text - */ -export function generateFileDownload(filename, text) { - var element = document.createElement("a"); - element.setAttribute("href", "data:text/plain;charset=utf-8," + encodeURIComponent(text)); - element.setAttribute("download", filename); - - element.style.display = "none"; - document.body.appendChild(element); - - element.click(); - document.body.removeChild(element); -} - -/** - * Capitalizes the first letter - * @param {string} str - */ -export function capitalizeFirstLetter(str) { - return str.substr(0, 1).toUpperCase() + str.substr(1).toLowerCase(); -} - /** * Formats a number like 2.5 to "2.5 items / s" * @param {number} speed @@ -967,3 +632,93 @@ export function formatItemsPerSecond(speed, double = false, separator = T.global round2Digits(speed).toString().replace(".", separator) ) + (double ? " " + T.ingame.buildingPlacement.infoTexts.itemsPerSecondDouble : ""); } + +/** + * Rotates a flat 3x3 matrix clockwise + * Entries: + * 0 lo + * 1 mo + * 2 ro + * 3 lm + * 4 mm + * 5 rm + * 6 lu + * 7 mu + * 8 ru + * @param {Array} flatMatrix + */ + +export function rotateFlatMatrix3x3(flatMatrix) { + return [ + flatMatrix[6], + flatMatrix[3], + flatMatrix[0], + flatMatrix[7], + flatMatrix[4], + flatMatrix[1], + flatMatrix[8], + flatMatrix[5], + flatMatrix[2], + ]; +} + +/** + * Generates rotated variants of the matrix + * @param {Array} originalMatrix + * @returns {Object>} + */ +export function generateMatrixRotations(originalMatrix) { + const result = { + 0: originalMatrix, + }; + + originalMatrix = rotateFlatMatrix3x3(originalMatrix); + result[90] = originalMatrix; + + originalMatrix = rotateFlatMatrix3x3(originalMatrix); + result[180] = originalMatrix; + + originalMatrix = rotateFlatMatrix3x3(originalMatrix); + result[270] = originalMatrix; + + return result; +} + +/** + * + * @typedef {{ + * top: any, + * right: any, + * bottom: any, + * left: any + * }} DirectionalObject + */ + +/** + * Rotates a directional object + * @param {DirectionalObject} obj + * @returns {DirectionalObject} + */ +export function rotateDirectionalObject(obj, rotation) { + const queue = [obj.top, obj.right, obj.bottom, obj.left]; + while (rotation !== 0) { + rotation -= 90; + queue.push(queue.shift()); + } + + return { + top: queue[0], + right: queue[1], + bottom: queue[2], + left: queue[3], + }; +} + +/** + * Modulo which works for negative numbers + * @param {number} n + * @param {number} m + */ +export function safeModulo(n, m) { + return ((n % m) + m) % m; +} diff --git a/src/js/core/vector.js b/src/js/core/vector.js index b0a2d3fa..50fa9433 100644 --- a/src/js/core/vector.js +++ b/src/js/core/vector.js @@ -1,4 +1,5 @@ import { globalConfig } from "./config"; +import { safeModulo } from "./utils"; const tileSize = globalConfig.tileSize; const halfTileSize = globalConfig.halfTileSize; @@ -43,6 +44,14 @@ export const enumAngleToDirection = { 270: enumDirection.left, }; +/** @type {Array} */ +export const arrayAllDirections = [ + enumDirection.top, + enumDirection.right, + enumDirection.bottom, + enumDirection.left, +]; + export class Vector { /** * @@ -279,6 +288,15 @@ export class Vector { return dx * dx + dy * dy; } + /** + * Returns x % f, y % f + * @param {number} f + * @returns {Vector} new vector + */ + modScalar(f) { + return new Vector(safeModulo(this.x, f), safeModulo(this.y, f)); + } + /** * Computes and returns the center between both points * @param {Vector} v diff --git a/src/js/game/base_item.js b/src/js/game/base_item.js index d0da5fa1..61dc3f34 100644 --- a/src/js/game/base_item.js +++ b/src/js/game/base_item.js @@ -1,26 +1,8 @@ import { DrawParameters } from "../core/draw_parameters"; import { BasicSerializableObject } from "../savegame/serialization"; -import { enumLayer } from "./root"; -/** @enum {string} */ -export const enumItemType = { - shape: "shape", - color: "color", - positiveEnergy: "positiveEnergy", - negativeEnergy: "negativeEnergy", - - // Can be used for filters - genericEnergy: "genericEnergy", -}; - -/** @enum {enumLayer} */ -export const enumItemTypeToLayer = { - [enumItemType.shape]: enumLayer.regular, - [enumItemType.color]: enumLayer.regular, - [enumItemType.positiveEnergy]: enumLayer.wires, - [enumItemType.negativeEnergy]: enumLayer.wires, - [enumItemType.genericEnergy]: enumLayer.wires, -}; +/** @type {ItemType[]} **/ +export const itemTypes = ["shape", "color", "boolean"]; /** * Class for items on belts etc. Not an entity for performance reasons @@ -39,10 +21,33 @@ export class BaseItem extends BasicSerializableObject { return {}; } - /** @returns {enumItemType} */ + /** @returns {ItemType} **/ getItemType() { abstract; - return ""; + return "shape"; + } + + /** + * Returns if the item equals the other itme + * @param {BaseItem} other + * @returns {boolean} + */ + equals(other) { + if (this.getItemType() !== other.getItemType()) { + return false; + } + return this.equalsImpl(other); + } + + /** + * Override for custom comparison + * @abstract + * @param {BaseItem} other + * @returns {boolean} + */ + equalsImpl(other) { + abstract; + return false; } /** @@ -50,9 +55,9 @@ export class BaseItem extends BasicSerializableObject { * @param {number} x * @param {number} y * @param {DrawParameters} parameters - * @param {number=} size + * @param {number=} diameter */ - draw(x, y, parameters, size) {} + drawCentered(x, y, parameters, diameter) {} getBackgroundColorAsResource() { abstract; diff --git a/src/js/game/belt_path.js b/src/js/game/belt_path.js index 0b6da48c..9e665487 100644 --- a/src/js/game/belt_path.js +++ b/src/js/game/belt_path.js @@ -1,14 +1,14 @@ import { globalConfig } from "../core/config"; import { DrawParameters } from "../core/draw_parameters"; import { createLogger } from "../core/logging"; +import { Rectangle } from "../core/rectangle"; import { epsilonCompare, round4Digits } from "../core/utils"; -import { Vector } from "../core/vector"; +import { enumDirection, enumDirectionToVector, enumInvertedDirections, Vector } from "../core/vector"; +import { BasicSerializableObject, types } from "../savegame/serialization"; import { BaseItem } from "./base_item"; import { Entity } from "./entity"; -import { GameRoot, enumLayer } from "./root"; -import { Rectangle } from "../core/rectangle"; -import { BasicSerializableObject, types } from "../savegame/serialization"; -import { gItemRegistry } from "../core/global_registries"; +import { typeItemSingleton } from "./item_resolver"; +import { GameRoot } from "./root"; const logger = createLogger("belt_path"); @@ -29,7 +29,7 @@ export class BeltPath extends BasicSerializableObject { static getSchema() { return { entityPath: types.array(types.entity), - items: types.array(types.pair(types.ufloat, types.obj(gItemRegistry))), + items: types.array(types.pair(types.ufloat, typeItemSingleton)), spacingToFirstItem: types.ufloat, }; } @@ -115,22 +115,7 @@ export class BeltPath extends BasicSerializableObject { * @returns {boolean} */ canAcceptItem() { - return this.spacingToFirstItem >= this.getItemSpacing(); - } - - /** - * Returns the spacing between items - */ - getItemSpacing() { - return globalConfig.beltItemSpacingByLayer[this.layer]; - } - - /** - * Returns the layer of the this path - * @returns {enumLayer} - */ - getLayer() { - return this.entityPath[0].layer; + return this.spacingToFirstItem >= globalConfig.itemSpacingOnBelts; } /** @@ -138,15 +123,15 @@ export class BeltPath extends BasicSerializableObject { * @param {BaseItem} item */ tryAcceptItem(item) { - if (this.spacingToFirstItem >= this.getItemSpacing()) { + if (this.spacingToFirstItem >= globalConfig.itemSpacingOnBelts) { // So, since we already need one tick to accept this item we will add this directly. const beltProgressPerTick = - this.root.hubGoals.getBeltBaseSpeed(this.layer) * + this.root.hubGoals.getBeltBaseSpeed() * this.root.dynamicTickrate.deltaSeconds * - this.getItemSpacing(); + globalConfig.itemSpacingOnBelts; // First, compute how much progress we can make *at max* - const maxProgress = Math.max(0, this.spacingToFirstItem - this.getItemSpacing()); + const maxProgress = Math.max(0, this.spacingToFirstItem - globalConfig.itemSpacingOnBelts); const initialProgress = Math.min(maxProgress, beltProgressPerTick); this.items.unshift([this.spacingToFirstItem - initialProgress, item]); @@ -167,7 +152,7 @@ export class BeltPath extends BasicSerializableObject { * @returns {BaseItem|null} */ findItemAtTile(tile) { - // TODO: This breaks color blind mode otherwise + // @TODO: This breaks color blind mode otherwise return null; } @@ -186,27 +171,81 @@ export class BeltPath extends BasicSerializableObject { } /** - * Updates all ejectors on the path, so that only the last ejector + * Recomputes cache variables once the path was changed */ onPathChanged() { - this.ejectorComp = this.entityPath[this.entityPath.length - 1].components.ItemEjector; - this.ejectorSlot = this.ejectorComp.slots[0]; + this.acceptorTarget = this.computeAcceptingEntityAndSlot(); + } - for (let i = 0; i < this.entityPath.length; ++i) { - const ejectorComp = this.entityPath[i].components.ItemEjector; - const isLast = i === this.entityPath.length - 1; - ejectorComp.enabled = isLast; + /** + * Called by the belt system when the surroundings changed + */ + onSurroundingsChanged() { + this.onPathChanged(); + } - // Clear all slots of non-end entities - if (!isLast) { - for (let k = 0; k < ejectorComp.slots.length; ++k) { - ejectorComp.slots[k].item = null; - ejectorComp.slots[k].progress = 0.0; + /** + * Finds the entity which accepts our items + * @return {{ entity: Entity, slot: number, direction?: enumDirection }} + */ + computeAcceptingEntityAndSlot() { + const lastEntity = this.entityPath[this.entityPath.length - 1]; + const lastStatic = lastEntity.components.StaticMapEntity; + const lastBeltComp = lastEntity.components.Belt; + + // Figure out where and into which direction we eject items + const ejectSlotWsTile = lastStatic.localTileToWorld(new Vector(0, 0)); + const ejectSlotWsDirection = lastStatic.localDirectionToWorld(lastBeltComp.direction); + const ejectSlotWsDirectionVector = enumDirectionToVector[ejectSlotWsDirection]; + const ejectSlotTargetWsTile = ejectSlotWsTile.add(ejectSlotWsDirectionVector); + + // Try to find the given acceptor component to take the item + const targetEntity = this.root.map.getLayerContentXY( + ejectSlotTargetWsTile.x, + ejectSlotTargetWsTile.y, + "regular" + ); + + if (targetEntity) { + const targetStaticComp = targetEntity.components.StaticMapEntity; + const targetBeltComp = targetEntity.components.Belt; + + // Check for belts (special case) + if (targetBeltComp) { + const beltAcceptingDirection = targetStaticComp.localDirectionToWorld(enumDirection.top); + if (ejectSlotWsDirection === beltAcceptingDirection) { + return { + entity: targetEntity, + direction: null, + slot: 0, + }; } } - } - this.layer = this.entityPath[0].layer; + // Check for item acceptors + const targetAcceptorComp = targetEntity.components.ItemAcceptor; + if (!targetAcceptorComp) { + // Entity doesn't accept items + return; + } + + const ejectingDirection = targetStaticComp.worldDirectionToLocal(ejectSlotWsDirection); + const matchingSlot = targetAcceptorComp.findMatchingSlot( + targetStaticComp.worldToLocalTile(ejectSlotTargetWsTile), + ejectingDirection + ); + + if (!matchingSlot) { + // No matching slot found + return; + } + + return { + entity: targetEntity, + slot: matchingSlot.index, + direction: enumInvertedDirections[ejectingDirection], + }; + } } // Following code will be compiled out outside of dev versions @@ -251,11 +290,6 @@ export class BeltPath extends BasicSerializableObject { return fail("Reference to destroyed entity " + entity.uid); } - const enabledState = i === this.entityPath.length - 1; - if (entity.components.ItemEjector.enabled !== enabledState) { - return fail("Item ejector enabled state is not synchronized (index =" + i + ")"); - } - const followUp = this.root.systemMgr.systems.belt.findFollowUpEntity(entity); if (!followUp) { return fail( @@ -283,20 +317,6 @@ export class BeltPath extends BasicSerializableObject { } } - // Check for right ejector component and slot - if (this.ejectorComp !== this.entityPath[this.entityPath.length - 1].components.ItemEjector) { - return fail("Stale ejectorComp handle"); - } - if (this.ejectorSlot !== this.ejectorComp.slots[0]) { - return fail("Stale ejector slot handle"); - } - if (!this.ejectorComp) { - return fail("Ejector comp not set"); - } - if (!this.ejectorSlot) { - return fail("Ejector slot not set"); - } - // Check spacing if (this.spacingToFirstItem > this.totalLength + 0.005) { return fail( @@ -370,20 +390,12 @@ export class BeltPath extends BasicSerializableObject { const beltComp = entity.components.Belt; - // If the last belt has something on its ejector, put that into the path first - const pendingItem = this.ejectorComp.takeSlotItem(0); - if (pendingItem) { - // Ok, so we have a pending item - DEBUG && logger.log("Taking pending item and putting it back on the path"); - this.items.push([0, pendingItem]); - } - // Append the entity this.entityPath.push(entity); this.onPathChanged(); // Extend the path length - const additionalLength = beltComp.getEffectiveLengthTiles(entity.layer); + const additionalLength = beltComp.getEffectiveLengthTiles(); this.totalLength += additionalLength; DEBUG && logger.log(" Extended total length by", additionalLength, "to", this.totalLength); @@ -426,7 +438,7 @@ export class BeltPath extends BasicSerializableObject { // All items on that belt are simply lost (for now) - const length = beltComp.getEffectiveLengthTiles(entity.layer); + const length = beltComp.getEffectiveLengthTiles(); // Extend the length of this path this.totalLength += length; @@ -478,7 +490,7 @@ export class BeltPath extends BasicSerializableObject { const beltComp = entity.components.Belt; beltComp.assignedPath = null; - const entityLength = beltComp.getEffectiveLengthTiles(entity.layer); + const entityLength = beltComp.getEffectiveLengthTiles(); assert(this.entityPath.indexOf(entity) >= 0, "Entity not contained for split"); assert(this.entityPath.indexOf(entity) !== 0, "Entity is first"); assert(this.entityPath.indexOf(entity) !== this.entityPath.length - 1, "Entity is last"); @@ -496,7 +508,7 @@ export class BeltPath extends BasicSerializableObject { ++firstPathEntityCount; firstPathEndEntity = otherEntity; - firstPathLength += otherEntity.components.Belt.getEffectiveLengthTiles(otherEntity.layer); + firstPathLength += otherEntity.components.Belt.getEffectiveLengthTiles(); } DEBUG && @@ -640,7 +652,7 @@ export class BeltPath extends BasicSerializableObject { // Ok, first remove the entity const beltComp = entity.components.Belt; - const beltLength = beltComp.getEffectiveLengthTiles(entity.layer); + const beltLength = beltComp.getEffectiveLengthTiles(); DEBUG && logger.log( @@ -749,7 +761,7 @@ export class BeltPath extends BasicSerializableObject { // Ok, first remove the entity const beltComp = entity.components.Belt; - const beltLength = beltComp.getEffectiveLengthTiles(entity.layer); + const beltLength = beltComp.getEffectiveLengthTiles(); DEBUG && logger.log( @@ -889,7 +901,7 @@ export class BeltPath extends BasicSerializableObject { beltComp.assignedPath = this; // Update our length - const additionalLength = beltComp.getEffectiveLengthTiles(entity.layer); + const additionalLength = beltComp.getEffectiveLengthTiles(); this.totalLength += additionalLength; } @@ -947,7 +959,7 @@ export class BeltPath extends BasicSerializableObject { let length = 0; for (let i = 0; i < this.entityPath.length; ++i) { const entity = this.entityPath[i]; - length += entity.components.Belt.getEffectiveLengthTiles(this.layer); + length += entity.components.Belt.getEffectiveLengthTiles(); } return length; } @@ -962,15 +974,15 @@ export class BeltPath extends BasicSerializableObject { // Divide by item spacing on belts since we use throughput and not speed let beltSpeed = - this.root.hubGoals.getBeltBaseSpeed(this.layer) * + this.root.hubGoals.getBeltBaseSpeed() * this.root.dynamicTickrate.deltaSeconds * - this.getItemSpacing(); + globalConfig.itemSpacingOnBelts; if (G_IS_DEV && globalConfig.debug.instantBelts) { beltSpeed *= 100; } - let minimumDistance = this.ejectorSlot.item ? this.getItemSpacing() : 0; + let minimumDistance = 0; // Try to reduce spacing let remainingAmount = beltSpeed; @@ -991,13 +1003,13 @@ export class BeltPath extends BasicSerializableObject { break; } - minimumDistance = this.getItemSpacing(); + minimumDistance = globalConfig.itemSpacingOnBelts; } + // Check if we have an item which is ready to be emitted const lastItem = this.items[this.items.length - 1]; - if (lastItem && lastItem[_nextDistance] === 0) { - // Take over - if (this.ejectorComp.tryEject(0, lastItem[_item])) { + if (lastItem && lastItem[_nextDistance] === 0 && this.acceptorTarget) { + if (this.tryHandOverItem(lastItem[_item])) { this.items.pop(); } } @@ -1007,6 +1019,47 @@ export class BeltPath extends BasicSerializableObject { } } + /** + * Tries to hand over the item to the end entity + * @param {BaseItem} item + */ + tryHandOverItem(item) { + if (!this.acceptorTarget) { + return; + } + + const targetAcceptorComp = this.acceptorTarget.entity.components.ItemAcceptor; + + // Check if the acceptor has a filter for example + if (targetAcceptorComp && !targetAcceptorComp.canAcceptItem(this.acceptorTarget.slot, item)) { + // Well, this item is not accepted + return false; + } + + // Try to pass over + if ( + this.root.systemMgr.systems.itemEjector.tryPassOverItem( + item, + this.acceptorTarget.entity, + this.acceptorTarget.slot + ) + ) { + // Trigger animation on the acceptor comp + const targetAcceptorComp = this.acceptorTarget.entity.components.ItemAcceptor; + if (targetAcceptorComp) { + targetAcceptorComp.onItemAccepted( + this.acceptorTarget.slot, + this.acceptorTarget.direction, + item + ); + } + + return true; + } + + return false; + } + /** * Computes a world space position from the given progress * @param {number} progress @@ -1020,14 +1073,14 @@ export class BeltPath extends BasicSerializableObject { for (let i = 0; i < this.entityPath.length; ++i) { const beltComp = this.entityPath[i].components.Belt; - const localLength = beltComp.getEffectiveLengthTiles(this.layer); + const localLength = beltComp.getEffectiveLengthTiles(); if (currentLength + localLength >= progress || i === this.entityPath.length - 1) { // Min required here due to floating point issues const localProgress = Math.min(1.0, progress - currentLength); assert(localProgress >= 0.0, "Invalid local progress: " + localProgress); - const localSpace = beltComp.transformBeltToLocalSpace(localProgress, this.layer); + const localSpace = beltComp.transformBeltToLocalSpace(localProgress); return this.entityPath[i].components.StaticMapEntity.localTileToWorld(localSpace); } currentLength += localLength; @@ -1045,11 +1098,6 @@ export class BeltPath extends BasicSerializableObject { return; } - if (this.entityPath[0].layer !== this.root.currentLayer) { - // Don't draw - return; - } - parameters.context.fillStyle = "#d79a25"; parameters.context.strokeStyle = "#d79a25"; parameters.context.beginPath(); @@ -1131,10 +1179,10 @@ export class BeltPath extends BasicSerializableObject { for (let i = 0; i < this.entityPath.length; ++i) { const entity = this.entityPath[i]; const beltComp = entity.components.Belt; - const beltLength = beltComp.getEffectiveLengthTiles(this.layer); + const beltLength = beltComp.getEffectiveLengthTiles(); // Check if the current items are on the belt - while (trackPos + beltLength >= currentItemPos) { + while (trackPos + beltLength >= currentItemPos - 1e-5) { // Its on the belt, render it now const staticComp = entity.components.StaticMapEntity; assert( @@ -1142,12 +1190,12 @@ export class BeltPath extends BasicSerializableObject { "invalid track pos: " + currentItemPos + " vs " + trackPos + " (l =" + beltLength + ")" ); - const localPos = beltComp.transformBeltToLocalSpace(currentItemPos - trackPos, this.layer); + const localPos = beltComp.transformBeltToLocalSpace(currentItemPos - trackPos); const worldPos = staticComp.localTileToWorld(localPos).toWorldSpaceCenterOfTile(); const distanceAndItem = this.items[currentItemIndex]; if (parameters.visibleRect.containsCircle(worldPos.x, worldPos.y, 10)) { - distanceAndItem[_item].draw(worldPos.x, worldPos.y, parameters); + distanceAndItem[_item].drawCentered(worldPos.x, worldPos.y, parameters); } // Check for the next item diff --git a/src/js/game/blueprint.js b/src/js/game/blueprint.js index e1ac2dec..dc30554d 100644 --- a/src/js/game/blueprint.js +++ b/src/js/game/blueprint.js @@ -3,7 +3,7 @@ import { Loader } from "../core/loader"; import { createLogger } from "../core/logging"; import { Vector } from "../core/vector"; import { Entity } from "./entity"; -import { GameRoot, enumLayer } from "./root"; +import { GameRoot } from "./root"; import { findNiceIntegerValue } from "../core/utils"; import { blueprintShape } from "./upgrades"; import { globalConfig } from "../core/config"; @@ -20,11 +20,11 @@ export class Blueprint { /** * Returns the layer of this blueprint - * @returns {enumLayer} + * @returns {Layer} */ get layer() { if (this.entities.length === 0) { - return enumLayer.regular; + return "regular"; } return this.entities[0].layer; } @@ -92,13 +92,7 @@ export class Blueprint { parameters.context.globalAlpha = 1; } - staticComp.drawSpriteOnFullEntityBounds( - parameters, - staticComp.getBlueprintSprite(), - 0, - true, - newPos - ); + staticComp.drawSpriteOnFullEntityBounds(parameters, staticComp.getBlueprintSprite(), 0, newPos); } parameters.context.globalAlpha = 1; } diff --git a/src/js/game/building_codes.js b/src/js/game/building_codes.js index ea331272..05c27f57 100644 --- a/src/js/game/building_codes.js +++ b/src/js/game/building_codes.js @@ -1,5 +1,8 @@ -import { MetaBuilding, defaultBuildingVariant } from "./meta_building"; +/* typehints:start */ +import { MetaBuilding } from "./meta_building"; import { AtlasSprite } from "../core/sprites"; +import { Vector } from "../core/vector"; +/* typehints:end */ /** * @typedef {{ @@ -7,6 +10,7 @@ import { AtlasSprite } from "../core/sprites"; * metaInstance?: MetaBuilding, * variant?: string, * rotationVariant?: number, + * tileSize?: Vector, * sprite?: AtlasSprite, * blueprintSprite?: AtlasSprite, * silhouetteColor?: string @@ -22,18 +26,25 @@ export const gBuildingVariants = { }; /** - * - * @param {*} id - * @param {*} meta - * @param {*} variant - * @param {*} rotationVariant + * Registers a new variant + * @param {number} id + * @param {typeof MetaBuilding} meta + * @param {string} variant + * @param {number} rotationVariant */ -export function registerBuildingVariant(id, meta, variant = defaultBuildingVariant, rotationVariant = 0) { +export function registerBuildingVariant( + id, + meta, + variant = "default" /* FIXME: Circular dependency, actually its defaultBuildingVariant */, + rotationVariant = 0 +) { assert(!gBuildingVariants[id], "Duplicate id: " + id); gBuildingVariants[id] = { metaClass: meta, variant, rotationVariant, + // @ts-ignore + tileSize: new meta().getDimensions(variant), }; } diff --git a/src/js/game/buildings/advanced_processor.js b/src/js/game/buildings/advanced_processor.js deleted file mode 100644 index a688c878..00000000 --- a/src/js/game/buildings/advanced_processor.js +++ /dev/null @@ -1,108 +0,0 @@ -import { formatItemsPerSecond } from "../../core/utils"; -import { enumDirection, Vector } from "../../core/vector"; -import { T } from "../../translations"; -import { enumItemType } from "../base_item"; -import { EnergyConsumerComponent } from "../components/energy_consumer"; -import { ItemAcceptorComponent } from "../components/item_acceptor"; -import { ItemEjectorComponent } from "../components/item_ejector"; -import { enumItemProcessorTypes, ItemProcessorComponent } from "../components/item_processor"; -import { enumPinSlotType, WiredPinsComponent } from "../components/wired_pins"; -import { Entity } from "../entity"; -import { MetaBuilding } from "../meta_building"; -import { enumLayer, GameRoot } from "../root"; - -export class MetaAdvancedProcessorBuilding extends MetaBuilding { - constructor() { - super("advanced_processor"); - } - - getSilhouetteColor() { - return "#25d7b8"; - } - - getDimensions(variant) { - return new Vector(2, 2); - } - - /** - * @param {GameRoot} root - * @param {string} variant - * @returns {Array<[string, string]>} - */ - getAdditionalStatistics(root, variant) { - const speed = root.hubGoals.getProcessorBaseSpeed(enumItemProcessorTypes.advancedProcessor); - return [[T.ingame.buildingPlacement.infoTexts.speed, formatItemsPerSecond(speed)]]; - } - - /** - * @param {GameRoot} root - */ - getIsUnlocked(root) { - // TODO - return true; - // return root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_cutter_and_trash); - } - - /** - * Creates the entity at the given location - * @param {Entity} entity - */ - setupEntityComponents(entity) { - entity.addComponent( - new ItemProcessorComponent({ - inputsPerCharge: 1, - processorType: enumItemProcessorTypes.advancedProcessor, - }) - ); - entity.addComponent( - new ItemEjectorComponent({ - slots: [ - { pos: new Vector(1, 0), direction: enumDirection.right }, - { pos: new Vector(1, 0), direction: enumDirection.top, layer: enumLayer.wires }, - ], - }) - ); - entity.addComponent( - new EnergyConsumerComponent({ - bufferSize: 3, - perCharge: 1, - batteryPosition: new Vector(0.63, 0.7), - acceptorSlotIndex: 1, - ejectorSlotIndex: 1, - }) - ); - - entity.addComponent( - new WiredPinsComponent({ - slots: [ - { - pos: new Vector(0, 0), - direction: enumDirection.top, - type: enumPinSlotType.positiveEnergyAcceptor, - }, - { - pos: new Vector(1, 0), - direction: enumDirection.top, - type: enumPinSlotType.negativeEnergyEjector, - }, - ], - }) - ); - entity.addComponent( - new ItemAcceptorComponent({ - slots: [ - { - pos: new Vector(0, 1), - directions: [enumDirection.left], - }, - { - pos: new Vector(0, 0), - directions: [enumDirection.top], - filter: enumItemType.positiveEnergy, - layer: enumLayer.wires, - }, - ], - }) - ); - } -} diff --git a/src/js/game/buildings/belt_base.js b/src/js/game/buildings/belt_base.js index a87589a3..1aafa9e1 100644 --- a/src/js/game/buildings/belt_base.js +++ b/src/js/game/buildings/belt_base.js @@ -1,17 +1,20 @@ -import { formatItemsPerSecond } from "../../core/utils"; +import { formatItemsPerSecond, generateMatrixRotations } from "../../core/utils"; import { enumAngleToDirection, enumDirection, Vector } from "../../core/vector"; import { SOUNDS } from "../../platform/sound"; import { T } from "../../translations"; import { BeltComponent } from "../components/belt"; -import { ItemAcceptorComponent } from "../components/item_acceptor"; -import { ItemEjectorComponent } from "../components/item_ejector"; -import { ReplaceableMapEntityComponent } from "../components/replaceable_map_entity"; import { Entity } from "../entity"; import { MetaBuilding } from "../meta_building"; -import { GameRoot, enumLayer } from "../root"; +import { GameRoot } from "../root"; export const arrayBeltVariantToRotation = [enumDirection.top, enumDirection.left, enumDirection.right]; +export const beltOverlayMatrices = { + [enumDirection.top]: generateMatrixRotations([0, 1, 0, 0, 1, 0, 0, 1, 0]), + [enumDirection.left]: generateMatrixRotations([0, 0, 0, 1, 1, 0, 0, 1, 0]), + [enumDirection.right]: generateMatrixRotations([0, 0, 0, 0, 1, 1, 0, 1, 0]), +}; + export class MetaBeltBaseBuilding extends MetaBuilding { getHasDirectionLockAvailable() { return true; @@ -23,7 +26,7 @@ export class MetaBeltBaseBuilding extends MetaBuilding { * @returns {Array<[string, string]>} */ getAdditionalStatistics(root, variant) { - const beltSpeed = root.hubGoals.getBeltBaseSpeed(enumLayer.regular); + const beltSpeed = root.hubGoals.getBeltBaseSpeed(); return [[T.ingame.buildingPlacement.infoTexts.speed, formatItemsPerSecond(beltSpeed)]]; } @@ -43,6 +46,21 @@ export class MetaBeltBaseBuilding extends MetaBuilding { return null; } + getIsReplaceable() { + return true; + } + + /** + * + * @param {number} rotation + * @param {number} rotationVariant + * @param {string} variant + * @param {Entity} entity + */ + getSpecialOverlayRenderMatrix(rotation, rotationVariant, variant, entity) { + return beltOverlayMatrices[entity.components.Belt.direction][rotation]; + } + /** * Creates the entity at the given location * @param {Entity} entity @@ -53,34 +71,6 @@ export class MetaBeltBaseBuilding extends MetaBuilding { direction: enumDirection.top, // updated later }) ); - // Make this entity replaceabel - entity.addComponent(new ReplaceableMapEntityComponent()); - - entity.addComponent( - new ItemAcceptorComponent({ - slots: [ - { - pos: new Vector(0, 0), - directions: [enumDirection.bottom], - layer: this.getLayer(), - }, - ], - animated: false, - }) - ); - - entity.addComponent( - new ItemEjectorComponent({ - slots: [ - { - pos: new Vector(0, 0), - direction: enumDirection.top, // updated later - layer: this.getLayer(), - }, - ], - instantEject: true, - }) - ); } /** @@ -90,7 +80,6 @@ export class MetaBeltBaseBuilding extends MetaBuilding { */ updateVariants(entity, rotationVariant) { entity.components.Belt.direction = arrayBeltVariantToRotation[rotationVariant]; - entity.components.ItemEjector.slots[0].direction = arrayBeltVariantToRotation[rotationVariant]; } /** @@ -100,7 +89,7 @@ export class MetaBeltBaseBuilding extends MetaBuilding { * @param {Vector} param0.tile * @param {number} param0.rotation * @param {string} param0.variant - * @param {string} param0.layer + * @param {Layer} param0.layer * @return {{ rotation: number, rotationVariant: number, connectedEntities?: Array }} */ computeOptimalDirectionAndRotationVariantAtTile({ root, tile, rotation, variant, layer }) { @@ -109,7 +98,7 @@ export class MetaBeltBaseBuilding extends MetaBuilding { const bottomDirection = enumAngleToDirection[(rotation + 180) % 360]; const leftDirection = enumAngleToDirection[(rotation + 270) % 360]; - const { ejectors, acceptors } = root.logic.getEjectorsAndAcceptorsAtTile(tile, layer); + const { ejectors, acceptors } = root.logic.getEjectorsAndAcceptorsAtTile(tile); let hasBottomEjector = false; let hasRightEjector = false; diff --git a/src/js/game/buildings/constant_signal.js b/src/js/game/buildings/constant_signal.js new file mode 100644 index 00000000..93e0ab36 --- /dev/null +++ b/src/js/game/buildings/constant_signal.js @@ -0,0 +1,52 @@ +import { enumDirection, Vector } from "../../core/vector"; +import { enumPinSlotType, WiredPinsComponent } from "../components/wired_pins"; +import { Entity } from "../entity"; +import { MetaBuilding } from "../meta_building"; +import { GameRoot } from "../root"; +import { ConstantSignalComponent } from "../components/constant_signal"; + +export class MetaConstantSignalBuilding extends MetaBuilding { + constructor() { + super("constant_signal"); + } + + getSilhouetteColor() { + return "#2bafda"; + } + + /** + * @param {GameRoot} root + */ + getIsUnlocked(root) { + // @todo + return true; + } + + /** @returns {"wires"} **/ + getLayer() { + return "wires"; + } + + getDimensions() { + return new Vector(1, 1); + } + + /** + * Creates the entity at the given location + * @param {Entity} entity + */ + setupEntityComponents(entity) { + entity.addComponent( + new WiredPinsComponent({ + slots: [ + { + pos: new Vector(0, 0), + direction: enumDirection.top, + type: enumPinSlotType.logicalEjector, + }, + ], + }) + ); + entity.addComponent(new ConstantSignalComponent({})); + } +} diff --git a/src/js/game/buildings/cutter.js b/src/js/game/buildings/cutter.js index bfe142d5..739f4a05 100644 --- a/src/js/game/buildings/cutter.js +++ b/src/js/game/buildings/cutter.js @@ -8,7 +8,6 @@ import { Entity } from "../entity"; import { defaultBuildingVariant, MetaBuilding } from "../meta_building"; import { GameRoot } from "../root"; import { enumHubGoalRewards } from "../tutorial_goals"; -import { enumItemType } from "../base_item"; /** @enum {string} */ export const enumCutterVariants = { quad: "quad" }; @@ -82,7 +81,7 @@ export class MetaCutterBuilding extends MetaBuilding { { pos: new Vector(0, 0), directions: [enumDirection.bottom], - filter: enumItemType.shape, + filter: "shape", }, ], }) diff --git a/src/js/game/buildings/display.js b/src/js/game/buildings/display.js new file mode 100644 index 00000000..9c072af9 --- /dev/null +++ b/src/js/game/buildings/display.js @@ -0,0 +1,51 @@ +import { enumDirection, Vector } from "../../core/vector"; +import { enumPinSlotType, WiredPinsComponent } from "../components/wired_pins"; +import { Entity } from "../entity"; +import { MetaBuilding } from "../meta_building"; +import { GameRoot } from "../root"; +import { DisplayComponent } from "../components/display"; + +export class MetaDisplayBuilding extends MetaBuilding { + constructor() { + super("display"); + } + + getSilhouetteColor() { + return "#aaaaaa"; + } + + /** + * @param {GameRoot} root + */ + getIsUnlocked(root) { + // @todo + return true; + } + + getDimensions() { + return new Vector(1, 1); + } + + getShowWiresLayerPreview() { + return true; + } + + /** + * Creates the entity at the given location + * @param {Entity} entity + */ + setupEntityComponents(entity) { + entity.addComponent( + new WiredPinsComponent({ + slots: [ + { + pos: new Vector(0, 0), + direction: enumDirection.bottom, + type: enumPinSlotType.logicalAcceptor, + }, + ], + }) + ); + entity.addComponent(new DisplayComponent()); + } +} diff --git a/src/js/game/buildings/energy_generator.js b/src/js/game/buildings/energy_generator.js deleted file mode 100644 index 1d7ac18b..00000000 --- a/src/js/game/buildings/energy_generator.js +++ /dev/null @@ -1,109 +0,0 @@ -import { enumDirection, Vector } from "../../core/vector"; -import { enumItemType } from "../base_item"; -import { EnergyGeneratorComponent } from "../components/energy_generator"; -import { ItemAcceptorComponent } from "../components/item_acceptor"; -import { ItemEjectorComponent } from "../components/item_ejector"; -import { enumPinSlotType, WiredPinsComponent } from "../components/wired_pins"; -import { Entity } from "../entity"; -import { MetaBuilding } from "../meta_building"; -import { enumLayer, GameRoot } from "../root"; -import { enumHubGoalRewards } from "../tutorial_goals"; - -export class MetaEnergyGenerator extends MetaBuilding { - constructor() { - super("energy_generator"); - } - - getSilhouetteColor() { - return "#c425d7"; - } - - /** - * @param {GameRoot} root - * @param {string} variant - * @returns {Array<[string, string]>} - */ - getAdditionalStatistics(root, variant) { - // TODO - return []; - } - - getDimensions(variant) { - return new Vector(2, 2); - } - - /** - * @param {GameRoot} root - */ - getIsUnlocked(root) { - return true; - // return root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_cutter_and_trash); - } - - /** - * Creates the entity at the given location - * @param {Entity} entity - */ - setupEntityComponents(entity) { - entity.addComponent( - new ItemAcceptorComponent({ - slots: [ - { - pos: new Vector(0, 1), - directions: [enumDirection.bottom], - filter: enumItemType.shape, - }, - { - pos: new Vector(1, 1), - directions: [enumDirection.bottom], - filter: enumItemType.shape, - }, - { - pos: new Vector(1, 0), - directions: [enumDirection.top], - layer: enumLayer.wires, - filter: enumItemType.negativeEnergy, - }, - ], - }) - ); - - entity.addComponent( - new ItemEjectorComponent({ - slots: [ - { - pos: new Vector(0, 0), - direction: enumDirection.top, - layer: enumLayer.wires, - }, - ], - instantEject: true, - }) - ); - - entity.addComponent( - new EnergyGeneratorComponent({ - // Set by the energy generator system later - requiredKey: null, - wasteAcceptorSlotIndex: 2, - }) - ); - - entity.addComponent( - new WiredPinsComponent({ - slots: [ - { - pos: new Vector(0, 0), - type: enumPinSlotType.positiveEnergyEjector, - direction: enumDirection.top, - }, - { - pos: new Vector(1, 0), - type: enumPinSlotType.negativeEnergyAcceptor, - direction: enumDirection.top, - }, - ], - }) - ); - } -} diff --git a/src/js/game/buildings/filter.js b/src/js/game/buildings/filter.js new file mode 100644 index 00000000..5637a21a --- /dev/null +++ b/src/js/game/buildings/filter.js @@ -0,0 +1,86 @@ +import { enumDirection, Vector } from "../../core/vector"; +import { enumPinSlotType, WiredPinsComponent } from "../components/wired_pins"; +import { Entity } from "../entity"; +import { MetaBuilding } from "../meta_building"; +import { GameRoot } from "../root"; +import { LeverComponent } from "../components/lever"; +import { ItemAcceptorComponent } from "../components/item_acceptor"; +import { ItemEjectorComponent } from "../components/item_ejector"; +import { ItemProcessorComponent, enumItemProcessorTypes } from "../components/item_processor"; + +export class MetaFilterBuilding extends MetaBuilding { + constructor() { + super("filter"); + } + + getSilhouetteColor() { + return "#c45c2e"; + } + + /** + * @param {GameRoot} root + */ + getIsUnlocked(root) { + // @todo + return true; + } + + getDimensions() { + return new Vector(2, 1); + } + + getShowWiresLayerPreview() { + return true; + } + + /** + * Creates the entity at the given location + * @param {Entity} entity + */ + setupEntityComponents(entity) { + entity.addComponent( + new WiredPinsComponent({ + slots: [ + { + pos: new Vector(0, 0), + direction: enumDirection.left, + type: enumPinSlotType.logicalAcceptor, + }, + ], + }) + ); + + entity.addComponent( + new ItemAcceptorComponent({ + slots: [ + { + pos: new Vector(0, 0), + directions: [enumDirection.bottom], + }, + ], + }) + ); + + entity.addComponent( + new ItemEjectorComponent({ + slots: [ + { + pos: new Vector(0, 0), + direction: enumDirection.top, + }, + { + pos: new Vector(1, 0), + direction: enumDirection.right, + }, + ], + }) + ); + + entity.addComponent( + new ItemProcessorComponent({ + processorType: enumItemProcessorTypes.filter, + inputsPerCharge: 1, + }) + ); + } +} diff --git a/src/js/game/buildings/hub.js b/src/js/game/buildings/hub.js index 4f0e0d80..b9929b31 100644 --- a/src/js/game/buildings/hub.js +++ b/src/js/game/buildings/hub.js @@ -1,11 +1,10 @@ import { enumDirection, Vector } from "../../core/vector"; -import { enumItemType } from "../base_item"; import { HubComponent } from "../components/hub"; import { ItemAcceptorComponent } from "../components/item_acceptor"; import { enumItemProcessorTypes, ItemProcessorComponent } from "../components/item_processor"; -import { UnremovableComponent } from "../components/unremovable"; import { Entity } from "../entity"; import { MetaBuilding } from "../meta_building"; +import { WiredPinsComponent, enumPinSlotType } from "../components/wired_pins"; export class MetaHubBuilding extends MetaBuilding { constructor() { @@ -20,7 +19,7 @@ export class MetaHubBuilding extends MetaBuilding { return "#eb5555"; } - isRotateable() { + getIsRotateable() { return false; } @@ -33,6 +32,10 @@ export class MetaHubBuilding extends MetaBuilding { return null; } + getIsRemovable() { + return false; + } + /** * Creates the entity at the given location * @param {Entity} entity @@ -46,79 +49,90 @@ export class MetaHubBuilding extends MetaBuilding { }) ); - entity.addComponent(new UnremovableComponent()); + entity.addComponent( + new WiredPinsComponent({ + slots: [ + { + pos: new Vector(0, 2), + type: enumPinSlotType.logicalEjector, + direction: enumDirection.left, + }, + ], + }) + ); + entity.addComponent( new ItemAcceptorComponent({ slots: [ { pos: new Vector(0, 0), directions: [enumDirection.top, enumDirection.left], - filter: enumItemType.shape, + filter: "shape", }, { pos: new Vector(1, 0), directions: [enumDirection.top], - filter: enumItemType.shape, + filter: "shape", }, { pos: new Vector(2, 0), directions: [enumDirection.top], - filter: enumItemType.shape, + filter: "shape", }, { pos: new Vector(3, 0), directions: [enumDirection.top, enumDirection.right], - filter: enumItemType.shape, + filter: "shape", }, { pos: new Vector(0, 3), directions: [enumDirection.bottom, enumDirection.left], - filter: enumItemType.shape, + filter: "shape", }, { pos: new Vector(1, 3), directions: [enumDirection.bottom], - filter: enumItemType.shape, + filter: "shape", }, { pos: new Vector(2, 3), directions: [enumDirection.bottom], - filter: enumItemType.shape, + filter: "shape", }, { pos: new Vector(3, 3), directions: [enumDirection.bottom, enumDirection.right], - filter: enumItemType.shape, + filter: "shape", }, { pos: new Vector(0, 1), directions: [enumDirection.left], - filter: enumItemType.shape, + filter: "shape", }, { pos: new Vector(0, 2), directions: [enumDirection.left], - filter: enumItemType.shape, + filter: "shape", }, { pos: new Vector(0, 3), directions: [enumDirection.left], - filter: enumItemType.shape, + filter: "shape", }, { pos: new Vector(3, 1), directions: [enumDirection.right], - filter: enumItemType.shape, + filter: "shape", }, { pos: new Vector(3, 2), directions: [enumDirection.right], - filter: enumItemType.shape, + filter: "shape", }, { pos: new Vector(3, 3), directions: [enumDirection.right], - filter: enumItemType.shape, + filter: "shape", }, ], }) diff --git a/src/js/game/buildings/lever.js b/src/js/game/buildings/lever.js new file mode 100644 index 00000000..e7e35888 --- /dev/null +++ b/src/js/game/buildings/lever.js @@ -0,0 +1,61 @@ +import { enumDirection, Vector } from "../../core/vector"; +import { enumPinSlotType, WiredPinsComponent } from "../components/wired_pins"; +import { Entity } from "../entity"; +import { MetaBuilding } from "../meta_building"; +import { GameRoot } from "../root"; +import { LeverComponent } from "../components/lever"; + +export class MetaLeverBuilding extends MetaBuilding { + constructor() { + super("lever"); + } + + getSilhouetteColor() { + // @todo: Render differently based on if its activated or not + return "#1a678b"; + } + + /** + * @param {GameRoot} root + */ + getIsUnlocked(root) { + // @todo + return true; + } + + getIsRotateable() { + return false; + } + + getDimensions() { + return new Vector(1, 1); + } + + getSprite() { + return null; + } + + getShowWiresLayerPreview() { + return true; + } + + /** + * Creates the entity at the given location + * @param {Entity} entity + */ + setupEntityComponents(entity) { + entity.addComponent( + new WiredPinsComponent({ + slots: [ + { + pos: new Vector(0, 0), + direction: enumDirection.top, + type: enumPinSlotType.logicalEjector, + }, + ], + }) + ); + + entity.addComponent(new LeverComponent({})); + } +} diff --git a/src/js/game/buildings/logic_gate.js b/src/js/game/buildings/logic_gate.js new file mode 100644 index 00000000..e07db3ea --- /dev/null +++ b/src/js/game/buildings/logic_gate.js @@ -0,0 +1,155 @@ +import { enumDirection, Vector } from "../../core/vector"; +import { enumPinSlotType, WiredPinsComponent } from "../components/wired_pins"; +import { Entity } from "../entity"; +import { MetaBuilding, defaultBuildingVariant } from "../meta_building"; +import { GameRoot } from "../root"; +import { enumLogicGateType, LogicGateComponent } from "../components/logic_gate"; + +/** @enum {string} */ +export const enumLogicGateVariants = { + not: "not", + xor: "xor", + or: "or", + transistor: "transistor", +}; + +/** @enum {string} */ +export const enumVariantToGate = { + [defaultBuildingVariant]: enumLogicGateType.and, + [enumLogicGateVariants.not]: enumLogicGateType.not, + [enumLogicGateVariants.xor]: enumLogicGateType.xor, + [enumLogicGateVariants.or]: enumLogicGateType.or, + [enumLogicGateVariants.transistor]: enumLogicGateType.transistor, +}; + +export class MetaLogicGateBuilding extends MetaBuilding { + constructor() { + super("logic_gate"); + } + + getSilhouetteColor() { + return "#89dc60"; + } + + /** + * @param {GameRoot} root + */ + getIsUnlocked(root) { + // @todo + return true; + } + + /** @returns {"wires"} **/ + getLayer() { + return "wires"; + } + + getDimensions() { + return new Vector(1, 1); + } + + getAvailableVariants() { + return [ + defaultBuildingVariant, + enumLogicGateVariants.not, + enumLogicGateVariants.xor, + enumLogicGateVariants.or, + enumLogicGateVariants.transistor, + ]; + } + + getRenderPins() { + // We already have it included + return false; + } + + /** + * + * @param {Entity} entity + * @param {number} rotationVariant + */ + updateVariants(entity, rotationVariant, variant) { + const gateType = enumVariantToGate[variant]; + entity.components.LogicGate.type = gateType; + + const pinComp = entity.components.WiredPins; + + switch (gateType) { + case enumLogicGateType.and: + case enumLogicGateType.xor: + case enumLogicGateType.or: { + pinComp.setSlots([ + { + pos: new Vector(0, 0), + direction: enumDirection.top, + type: enumPinSlotType.logicalEjector, + }, + { + pos: new Vector(0, 0), + direction: enumDirection.left, + type: enumPinSlotType.logicalAcceptor, + }, + { + pos: new Vector(0, 0), + direction: enumDirection.right, + type: enumPinSlotType.logicalAcceptor, + }, + ]); + break; + } + case enumLogicGateType.transistor: { + pinComp.setSlots([ + { + pos: new Vector(0, 0), + direction: enumDirection.top, + type: enumPinSlotType.logicalEjector, + }, + { + pos: new Vector(0, 0), + direction: enumDirection.left, + type: enumPinSlotType.logicalAcceptor, + }, + { + pos: new Vector(0, 0), + direction: enumDirection.bottom, + type: enumPinSlotType.logicalAcceptor, + }, + ]); + break; + } + + case enumLogicGateType.not: { + pinComp.setSlots([ + { + pos: new Vector(0, 0), + direction: enumDirection.top, + type: enumPinSlotType.logicalEjector, + }, + { + pos: new Vector(0, 0), + direction: enumDirection.bottom, + type: enumPinSlotType.logicalAcceptor, + }, + ]); + break; + } + + default: + assertAlways("unknown logic gate type: " + gateType); + } + } + + /** + * Creates the entity at the given location + * @param {Entity} entity + */ + setupEntityComponents(entity) { + entity.addComponent( + new WiredPinsComponent({ + slots: [], + }) + ); + + entity.addComponent(new LogicGateComponent({})); + } +} diff --git a/src/js/game/buildings/miner.js b/src/js/game/buildings/miner.js index ed87bc85..1a9c97ff 100644 --- a/src/js/game/buildings/miner.js +++ b/src/js/game/buildings/miner.js @@ -6,11 +6,13 @@ import { MetaBuilding, defaultBuildingVariant } from "../meta_building"; import { GameRoot } from "../root"; import { enumHubGoalRewards } from "../tutorial_goals"; import { T } from "../../translations"; -import { round1Digit, round2Digits, formatItemsPerSecond } from "../../core/utils"; +import { formatItemsPerSecond } from "../../core/utils"; /** @enum {string} */ export const enumMinerVariants = { chainable: "chainable" }; +const overlayMatrix = [1, 1, 1, 1, 0, 1, 1, 1, 1]; + export class MetaMinerBuilding extends MetaBuilding { constructor() { super("miner"); @@ -41,6 +43,16 @@ export class MetaMinerBuilding extends MetaBuilding { return super.getAvailableVariants(root); } + /** + * @param {number} rotation + * @param {number} rotationVariant + * @param {string} variant + * @param {Entity} entity + */ + getSpecialOverlayRenderMatrix(rotation, rotationVariant, variant, entity) { + return overlayMatrix; + } + /** * Creates the entity at the given location * @param {Entity} entity diff --git a/src/js/game/buildings/mixer.js b/src/js/game/buildings/mixer.js index a2b35280..cbde309e 100644 --- a/src/js/game/buildings/mixer.js +++ b/src/js/game/buildings/mixer.js @@ -1,7 +1,6 @@ import { formatItemsPerSecond } from "../../core/utils"; import { enumDirection, Vector } from "../../core/vector"; import { T } from "../../translations"; -import { enumItemType } from "../base_item"; import { ItemAcceptorComponent } from "../components/item_acceptor"; import { ItemEjectorComponent } from "../components/item_ejector"; import { enumItemProcessorTypes, ItemProcessorComponent } from "../components/item_processor"; @@ -63,12 +62,12 @@ export class MetaMixerBuilding extends MetaBuilding { { pos: new Vector(0, 0), directions: [enumDirection.bottom], - filter: enumItemType.color, + filter: "color", }, { pos: new Vector(1, 0), directions: [enumDirection.bottom], - filter: enumItemType.color, + filter: "color", }, ], }) diff --git a/src/js/game/buildings/painter.js b/src/js/game/buildings/painter.js index 61e77a7c..49c2ff69 100644 --- a/src/js/game/buildings/painter.js +++ b/src/js/game/buildings/painter.js @@ -8,7 +8,6 @@ import { Entity } from "../entity"; import { defaultBuildingVariant, MetaBuilding } from "../meta_building"; import { GameRoot } from "../root"; import { enumHubGoalRewards } from "../tutorial_goals"; -import { enumItemType } from "../base_item"; /** @enum {string} */ export const enumPainterVariants = { mirrored: "mirrored", double: "double", quad: "quad" }; @@ -98,12 +97,12 @@ export class MetaPainterBuilding extends MetaBuilding { { pos: new Vector(0, 0), directions: [enumDirection.left], - filter: enumItemType.shape, + filter: "shape", }, { pos: new Vector(1, 0), directions: [enumDirection.top], - filter: enumItemType.color, + filter: "color", }, ], }) @@ -124,14 +123,14 @@ export class MetaPainterBuilding extends MetaBuilding { { pos: new Vector(0, 0), directions: [enumDirection.left], - filter: enumItemType.shape, + filter: "shape", }, { pos: new Vector(1, 0), directions: [ variant === defaultBuildingVariant ? enumDirection.top : enumDirection.bottom, ], - filter: enumItemType.color, + filter: "color", }, ]); @@ -147,17 +146,17 @@ export class MetaPainterBuilding extends MetaBuilding { { pos: new Vector(0, 0), directions: [enumDirection.left], - filter: enumItemType.shape, + filter: "shape", }, { pos: new Vector(0, 1), directions: [enumDirection.left], - filter: enumItemType.shape, + filter: "shape", }, { pos: new Vector(1, 0), directions: [enumDirection.top], - filter: enumItemType.color, + filter: "color", }, ]); @@ -174,27 +173,27 @@ export class MetaPainterBuilding extends MetaBuilding { { pos: new Vector(0, 0), directions: [enumDirection.left], - filter: enumItemType.shape, + filter: "shape", }, { pos: new Vector(0, 0), directions: [enumDirection.bottom], - filter: enumItemType.color, + filter: "color", }, { pos: new Vector(1, 0), directions: [enumDirection.bottom], - filter: enumItemType.color, + filter: "color", }, { pos: new Vector(2, 0), directions: [enumDirection.bottom], - filter: enumItemType.color, + filter: "color", }, { pos: new Vector(3, 0), directions: [enumDirection.bottom], - filter: enumItemType.color, + filter: "color", }, ]); diff --git a/src/js/game/buildings/rotater.js b/src/js/game/buildings/rotater.js index 45bb97b9..c278ef0d 100644 --- a/src/js/game/buildings/rotater.js +++ b/src/js/game/buildings/rotater.js @@ -8,7 +8,6 @@ import { Entity } from "../entity"; import { defaultBuildingVariant, MetaBuilding } from "../meta_building"; import { GameRoot } from "../root"; import { enumHubGoalRewards } from "../tutorial_goals"; -import { enumItemType } from "../base_item"; /** @enum {string} */ export const enumRotaterVariants = { ccw: "ccw", fl: "fl" }; @@ -89,7 +88,7 @@ export class MetaRotaterBuilding extends MetaBuilding { { pos: new Vector(0, 0), directions: [enumDirection.bottom], - filter: enumItemType.shape, + filter: "shape", }, ], }) diff --git a/src/js/game/buildings/splitter.js b/src/js/game/buildings/splitter.js index 12f0e6e7..219f02cf 100644 --- a/src/js/game/buildings/splitter.js +++ b/src/js/game/buildings/splitter.js @@ -1,14 +1,14 @@ -import { globalConfig } from "../../core/config"; import { enumDirection, Vector } from "../../core/vector"; import { ItemAcceptorComponent } from "../components/item_acceptor"; import { ItemEjectorComponent } from "../components/item_ejector"; import { enumItemProcessorTypes, ItemProcessorComponent } from "../components/item_processor"; import { Entity } from "../entity"; import { MetaBuilding, defaultBuildingVariant } from "../meta_building"; -import { GameRoot, enumLayer } from "../root"; +import { GameRoot } from "../root"; import { enumHubGoalRewards } from "../tutorial_goals"; import { T } from "../../translations"; import { formatItemsPerSecond } from "../../core/utils"; +import { BeltUnderlaysComponent } from "../components/belt_underlays"; /** @enum {string} */ export const enumSplitterVariants = { compact: "compact", compactInverse: "compact-inverse" }; @@ -88,6 +88,8 @@ export class MetaSplitterBuilding extends MetaBuilding { slots: [], // set later }) ); + + entity.addComponent(new BeltUnderlaysComponent({ underlays: [] })); } /** @@ -115,9 +117,9 @@ export class MetaSplitterBuilding extends MetaBuilding { { pos: new Vector(1, 0), direction: enumDirection.top }, ]); - entity.components.ItemAcceptor.beltUnderlays = [ - { pos: new Vector(0, 0), direction: enumDirection.top, layer: enumLayer.regular }, - { pos: new Vector(1, 0), direction: enumDirection.top, layer: enumLayer.regular }, + entity.components.BeltUnderlays.underlays = [ + { pos: new Vector(0, 0), direction: enumDirection.top }, + { pos: new Vector(1, 0), direction: enumDirection.top }, ]; break; @@ -143,8 +145,8 @@ export class MetaSplitterBuilding extends MetaBuilding { { pos: new Vector(0, 0), direction: enumDirection.top }, ]); - entity.components.ItemAcceptor.beltUnderlays = [ - { pos: new Vector(0, 0), direction: enumDirection.top, layer: enumLayer.regular }, + entity.components.BeltUnderlays.underlays = [ + { pos: new Vector(0, 0), direction: enumDirection.top }, ]; break; diff --git a/src/js/game/buildings/stacker.js b/src/js/game/buildings/stacker.js index 91ac3f62..40a9c5ae 100644 --- a/src/js/game/buildings/stacker.js +++ b/src/js/game/buildings/stacker.js @@ -8,7 +8,6 @@ import { Entity } from "../entity"; import { MetaBuilding } from "../meta_building"; import { GameRoot } from "../root"; import { enumHubGoalRewards } from "../tutorial_goals"; -import { enumItemType } from "../base_item"; export class MetaStackerBuilding extends MetaBuilding { constructor() { @@ -63,12 +62,12 @@ export class MetaStackerBuilding extends MetaBuilding { { pos: new Vector(0, 0), directions: [enumDirection.bottom], - filter: enumItemType.shape, + filter: "shape", }, { pos: new Vector(1, 0), directions: [enumDirection.bottom], - filter: enumItemType.shape, + filter: "shape", }, ], }) diff --git a/src/js/game/buildings/trash.js b/src/js/game/buildings/trash.js index 8ae36b8d..dfd47dfe 100644 --- a/src/js/game/buildings/trash.js +++ b/src/js/game/buildings/trash.js @@ -1,14 +1,15 @@ +import { formatBigNumber } from "../../core/utils"; import { enumDirection, Vector } from "../../core/vector"; +import { T } from "../../translations"; import { ItemAcceptorComponent } from "../components/item_acceptor"; import { ItemEjectorComponent } from "../components/item_ejector"; import { enumItemProcessorTypes, ItemProcessorComponent } from "../components/item_processor"; -import { Entity } from "../entity"; -import { MetaBuilding, defaultBuildingVariant } from "../meta_building"; -import { enumHubGoalRewards } from "../tutorial_goals"; -import { GameRoot } from "../root"; import { StorageComponent } from "../components/storage"; -import { T } from "../../translations"; -import { formatBigNumber } from "../../core/utils"; +import { enumPinSlotType, WiredPinsComponent } from "../components/wired_pins"; +import { Entity } from "../entity"; +import { defaultBuildingVariant, MetaBuilding } from "../meta_building"; +import { GameRoot } from "../root"; +import { enumHubGoalRewards } from "../tutorial_goals"; /** @enum {string} */ export const enumTrashVariants = { storage: "storage" }; @@ -20,7 +21,7 @@ export class MetaTrashBuilding extends MetaBuilding { super("trash"); } - isRotateable(variant) { + getIsRotateable(variant) { return variant !== defaultBuildingVariant; } @@ -117,6 +118,9 @@ export class MetaTrashBuilding extends MetaBuilding { if (entity.components.Storage) { entity.removeComponent(StorageComponent); } + if (entity.components.WiredPins) { + entity.removeComponent(WiredPinsComponent); + } entity.components.ItemAcceptor.setSlots([ { @@ -140,6 +144,24 @@ export class MetaTrashBuilding extends MetaBuilding { if (!entity.components.Storage) { entity.addComponent(new StorageComponent({})); } + if (!entity.components.WiredPins) { + entity.addComponent( + new WiredPinsComponent({ + slots: [ + { + pos: new Vector(1, 1), + direction: enumDirection.right, + type: enumPinSlotType.logicalEjector, + }, + { + pos: new Vector(0, 1), + direction: enumDirection.left, + type: enumPinSlotType.logicalEjector, + }, + ], + }) + ); + } entity.components.Storage.maximumStorage = trashSize; entity.components.ItemAcceptor.setSlots([ diff --git a/src/js/game/buildings/underground_belt.js b/src/js/game/buildings/underground_belt.js index 2c4f6a1d..155b69e2 100644 --- a/src/js/game/buildings/underground_belt.js +++ b/src/js/game/buildings/underground_belt.js @@ -5,10 +5,10 @@ import { ItemEjectorComponent } from "../components/item_ejector"; import { enumUndergroundBeltMode, UndergroundBeltComponent } from "../components/underground_belt"; import { Entity } from "../entity"; import { MetaBuilding, defaultBuildingVariant } from "../meta_building"; -import { GameRoot, enumLayer } from "../root"; +import { GameRoot } from "../root"; import { globalConfig } from "../../core/config"; import { enumHubGoalRewards } from "../tutorial_goals"; -import { formatItemsPerSecond } from "../../core/utils"; +import { formatItemsPerSecond, generateMatrixRotations } from "../../core/utils"; import { T } from "../../translations"; /** @enum {string} */ @@ -25,13 +25,21 @@ export const enumUndergroundBeltVariantToTier = { [enumUndergroundBeltVariants.tier2]: 1, }; +const overlayMatrices = [ + // Sender + generateMatrixRotations([1, 1, 1, 0, 1, 0, 0, 1, 0]), + + // Receiver + generateMatrixRotations([0, 1, 0, 0, 1, 0, 1, 1, 1]), +]; + export class MetaUndergroundBeltBuilding extends MetaBuilding { constructor() { super("underground_belt"); } getSilhouetteColor() { - return "#555"; + return "#222"; } getFlipOrientationAfterPlacement() { @@ -42,6 +50,16 @@ export class MetaUndergroundBeltBuilding extends MetaBuilding { return true; } + /** + * @param {number} rotation + * @param {number} rotationVariant + * @param {string} variant + * @param {Entity} entity + */ + getSpecialOverlayRenderMatrix(rotation, rotationVariant, variant, entity) { + return overlayMatrices[rotationVariant][rotation]; + } + /** * @param {GameRoot} root * @param {string} variant @@ -153,7 +171,7 @@ export class MetaUndergroundBeltBuilding extends MetaBuilding { * @param {Vector} param0.tile * @param {number} param0.rotation * @param {string} param0.variant - * @param {string} param0.layer + * @param {Layer} param0.layer * @return {{ rotation: number, rotationVariant: number, connectedEntities?: Array }} */ computeOptimalDirectionAndRotationVariantAtTile({ root, tile, rotation, variant, layer }) { @@ -172,7 +190,7 @@ export class MetaUndergroundBeltBuilding extends MetaBuilding { tile = tile.addScalars(searchVector.x, searchVector.y); /* WIRES: FIXME */ - const contents = root.map.getTileContent(tile, enumLayer.regular); + const contents = root.map.getTileContent(tile, "regular"); if (contents) { const undergroundComp = contents.components.UndergroundBelt; if (undergroundComp && undergroundComp.tier === tier) { diff --git a/src/js/game/buildings/wire.js b/src/js/game/buildings/wire.js new file mode 100644 index 00000000..59c9cb7d --- /dev/null +++ b/src/js/game/buildings/wire.js @@ -0,0 +1,263 @@ +import { Loader } from "../../core/loader"; +import { generateMatrixRotations } from "../../core/utils"; +import { enumDirection, enumDirectionToAngle, enumDirectionToVector, Vector } from "../../core/vector"; +import { SOUNDS } from "../../platform/sound"; +import { enumWireType, WireComponent } from "../components/wire"; +import { Entity } from "../entity"; +import { MetaBuilding } from "../meta_building"; +import { GameRoot } from "../root"; + +export const arrayWireRotationVariantToType = [ + enumWireType.regular, + enumWireType.turn, + enumWireType.split, + enumWireType.cross, +]; + +export const wireOverlayMatrices = { + [enumWireType.regular]: generateMatrixRotations([0, 1, 0, 0, 1, 0, 0, 1, 0]), + [enumWireType.split]: generateMatrixRotations([0, 0, 0, 1, 1, 1, 0, 1, 0]), + [enumWireType.turn]: generateMatrixRotations([0, 0, 0, 0, 1, 1, 0, 1, 0]), + [enumWireType.cross]: generateMatrixRotations([0, 1, 0, 1, 1, 1, 0, 1, 0]), +}; + +export class MetaWireBuilding extends MetaBuilding { + constructor() { + super("wire"); + } + + getHasDirectionLockAvailable() { + return true; + } + + getSilhouetteColor() { + return "#25fff2"; + } + + getDimensions() { + return new Vector(1, 1); + } + + getStayInPlacementMode() { + return true; + } + + getPlacementSound() { + return SOUNDS.placeBelt; + } + + getRotateAutomaticallyWhilePlacing() { + return true; + } + + /** @returns {"wires"} **/ + getLayer() { + return "wires"; + } + + getSprite() { + return null; + } + + getIsReplaceable() { + return true; + } + + /** + * @param {GameRoot} root + */ + getIsUnlocked(root) { + // @todo + return true; + } + + /** + * Creates the entity at the given location + * @param {Entity} entity + */ + setupEntityComponents(entity) { + // @todo + entity.addComponent(new WireComponent({})); + } + + /** + * + * @param {Entity} entity + * @param {number} rotationVariant + */ + updateVariants(entity, rotationVariant) { + entity.components.Wire.type = arrayWireRotationVariantToType[rotationVariant]; + } + + /** + * + * @param {number} rotation + * @param {number} rotationVariant + * @param {string} variant + * @param {Entity} entity + */ + getSpecialOverlayRenderMatrix(rotation, rotationVariant, variant, entity) { + return wireOverlayMatrices[entity.components.Wire.type][rotation]; + } + + getPreviewSprite(rotationVariant) { + switch (arrayWireRotationVariantToType[rotationVariant]) { + case enumWireType.regular: { + return Loader.getSprite("sprites/buildings/wire.png"); + } + case enumWireType.turn: { + return Loader.getSprite("sprites/buildings/wire-turn.png"); + } + case enumWireType.split: { + return Loader.getSprite("sprites/buildings/wire-split.png"); + } + case enumWireType.cross: { + return Loader.getSprite("sprites/buildings/wire-cross.png"); + } + default: { + assertAlways(false, "Invalid wire rotation variant"); + } + } + } + + getBlueprintSprite(rotationVariant) { + switch (arrayWireRotationVariantToType[rotationVariant]) { + case enumWireType.regular: { + return Loader.getSprite("sprites/blueprints/wire.png"); + } + case enumWireType.turn: { + return Loader.getSprite("sprites/blueprints/wire-turn.png"); + } + case enumWireType.split: { + return Loader.getSprite("sprites/blueprints/wire-split.png"); + } + case enumWireType.cross: { + return Loader.getSprite("sprites/blueprints/wire-cross.png"); + } + default: { + assertAlways(false, "Invalid wire rotation variant"); + } + } + } + + /** + * Should compute the optimal rotation variant on the given tile + * @param {object} param0 + * @param {GameRoot} param0.root + * @param {Vector} param0.tile + * @param {number} param0.rotation + * @param {string} param0.variant + * @param {string} param0.layer + * @return {{ rotation: number, rotationVariant: number, connectedEntities?: Array }} + */ + computeOptimalDirectionAndRotationVariantAtTile({ root, tile, rotation, variant, layer }) { + const connections = { + top: root.logic.computeWireEdgeStatus({ tile, rotation, edge: enumDirection.top }), + right: root.logic.computeWireEdgeStatus({ tile, rotation, edge: enumDirection.right }), + bottom: root.logic.computeWireEdgeStatus({ tile, rotation, edge: enumDirection.bottom }), + left: root.logic.computeWireEdgeStatus({ tile, rotation, edge: enumDirection.left }), + }; + + let flag = 0; + flag |= connections.top ? 0x1000 : 0; + flag |= connections.right ? 0x100 : 0; + flag |= connections.bottom ? 0x10 : 0; + flag |= connections.left ? 0x1 : 0; + + let targetType = enumWireType.regular; + + // First, reset rotation + rotation = 0; + + switch (flag) { + case 0x0000: + // Nothing + break; + + case 0x0001: + // Left + rotation += 90; + break; + + case 0x0010: + // Bottom + // END + break; + + case 0x0011: + // Bottom | Left + targetType = enumWireType.turn; + rotation += 90; + break; + + case 0x0100: + // Right + rotation += 90; + break; + + case 0x0101: + // Right | Left + rotation += 90; + break; + + case 0x0110: + // Right | Bottom + targetType = enumWireType.turn; + break; + + case 0x0111: + // Right | Bottom | Left + targetType = enumWireType.split; + break; + + case 0x1000: + // Top + break; + + case 0x1001: + // Top | Left + targetType = enumWireType.turn; + rotation += 180; + break; + + case 0x1010: + // Top | Bottom + break; + + case 0x1011: + // Top | Bottom | Left + targetType = enumWireType.split; + rotation += 90; + break; + + case 0x1100: + // Top | Right + targetType = enumWireType.turn; + rotation -= 90; + break; + + case 0x1101: + // Top | Right | Left + targetType = enumWireType.split; + rotation += 180; + break; + + case 0x1110: + // Top | Right | Bottom + targetType = enumWireType.split; + rotation -= 90; + break; + + case 0x1111: + // Top | Right | Bottom | Left + targetType = enumWireType.cross; + break; + } + + return { + // Clamp rotation + rotation: (rotation + 360 * 10) % 360, + rotationVariant: arrayWireRotationVariantToType.indexOf(targetType), + }; + } +} diff --git a/src/js/game/buildings/wire_base.js b/src/js/game/buildings/wire_base.js deleted file mode 100644 index 6f3ffec8..00000000 --- a/src/js/game/buildings/wire_base.js +++ /dev/null @@ -1,52 +0,0 @@ -import { Loader } from "../../core/loader"; -import { enumDirection } from "../../core/vector"; -import { enumLayer } from "../root"; -import { arrayBeltVariantToRotation, MetaBeltBaseBuilding } from "./belt_base"; - -export class MetaWireBaseBuilding extends MetaBeltBaseBuilding { - constructor() { - super("wire"); - } - - getSilhouetteColor() { - return "#c425d7"; - } - - getLayer() { - return enumLayer.wires; - } - - getPreviewSprite(rotationVariant) { - switch (arrayBeltVariantToRotation[rotationVariant]) { - case enumDirection.top: { - return Loader.getSprite("sprites/buildings/wire_top.png"); - } - case enumDirection.left: { - return Loader.getSprite("sprites/buildings/wire_left.png"); - } - case enumDirection.right: { - return Loader.getSprite("sprites/buildings/wire_right.png"); - } - default: { - assertAlways(false, "Invalid belt rotation variant"); - } - } - } - - getBlueprintSprite(rotationVariant) { - switch (arrayBeltVariantToRotation[rotationVariant]) { - case enumDirection.top: { - return Loader.getSprite("sprites/blueprints/wire_top.png"); - } - case enumDirection.left: { - return Loader.getSprite("sprites/blueprints/wire_left.png"); - } - case enumDirection.right: { - return Loader.getSprite("sprites/blueprints/wire_right.png"); - } - default: { - assertAlways(false, "Invalid belt rotation variant"); - } - } - } -} diff --git a/src/js/game/buildings/wire_crossings.js b/src/js/game/buildings/wire_crossings.js deleted file mode 100644 index cb3c933a..00000000 --- a/src/js/game/buildings/wire_crossings.js +++ /dev/null @@ -1,120 +0,0 @@ -import { enumDirection, Vector } from "../../core/vector"; -import { enumItemType } from "../base_item"; -import { ItemAcceptorComponent } from "../components/item_acceptor"; -import { ItemEjectorComponent } from "../components/item_ejector"; -import { enumItemProcessorTypes, ItemProcessorComponent } from "../components/item_processor"; -import { Entity } from "../entity"; -import { defaultBuildingVariant, MetaBuilding } from "../meta_building"; -import { enumLayer, GameRoot } from "../root"; - -/** @enum {string} */ -export const enumWireCrossingVariants = { - // Default = splitter - merger: "merger", -}; - -export class MetaWireCrossingsBuilding extends MetaBuilding { - constructor() { - super("wire_crossings"); - } - - getDimensions(variant) { - return new Vector(1, 1); - } - - getSilhouetteColor() { - return "#c425d7"; - } - - getLayer() { - return enumLayer.wires; - } - - /** - * @param {GameRoot} root - */ - getAvailableVariants(root) { - return [defaultBuildingVariant, enumWireCrossingVariants.merger]; - } - - /** - * @param {GameRoot} root - */ - getIsUnlocked(root) { - return true; - } - - /** - * Creates the entity at the given location - * @param {Entity} entity - */ - setupEntityComponents(entity) { - entity.addComponent( - new ItemAcceptorComponent({ - slots: [], // set later - }) - ); - - entity.addComponent( - new ItemProcessorComponent({ - inputsPerCharge: 1, - processorType: enumItemProcessorTypes.splitterWires, - }) - ); - - entity.addComponent( - new ItemEjectorComponent({ - slots: [], // set later - instantEject: true, - }) - ); - } - - /** - * - * @param {Entity} entity - * @param {number} rotationVariant - * @param {string} variant - */ - updateVariants(entity, rotationVariant, variant) { - switch (variant) { - case defaultBuildingVariant: { - entity.components.ItemAcceptor.setSlots([ - { - pos: new Vector(0, 0), - directions: [enumDirection.bottom], - layer: enumLayer.wires, - }, - ]); - - entity.components.ItemEjector.setSlots([ - { pos: new Vector(0, 0), direction: enumDirection.top, layer: enumLayer.wires }, - { pos: new Vector(0, 0), direction: enumDirection.right, layer: enumLayer.wires }, - ]); - - break; - } - case enumWireCrossingVariants.merger: { - entity.components.ItemAcceptor.setSlots([ - { - pos: new Vector(0, 0), - directions: [enumDirection.top], - layer: enumLayer.wires, - }, - { - pos: new Vector(0, 0), - directions: [enumDirection.right], - layer: enumLayer.wires, - }, - ]); - - entity.components.ItemEjector.setSlots([ - { pos: new Vector(0, 0), direction: enumDirection.bottom, layer: enumLayer.wires }, - ]); - break; - } - default: - assertAlways(false, "Unknown painter variant: " + variant); - } - } -} diff --git a/src/js/game/buildings/wire_tunnel.js b/src/js/game/buildings/wire_tunnel.js new file mode 100644 index 00000000..f885abc6 --- /dev/null +++ b/src/js/game/buildings/wire_tunnel.js @@ -0,0 +1,87 @@ +import { Vector } from "../../core/vector"; +import { Entity } from "../entity"; +import { MetaBuilding, defaultBuildingVariant } from "../meta_building"; +import { GameRoot } from "../root"; +import { WireTunnelComponent } from "../components/wire_tunnel"; +import { generateMatrixRotations } from "../../core/utils"; + +/** @enum {string} */ +export const enumWireTunnelVariants = { + coating: "coating", +}; + +const wireTunnelOverlayMatrices = { + [defaultBuildingVariant]: generateMatrixRotations([0, 1, 0, 1, 1, 1, 0, 1, 0]), + [enumWireTunnelVariants.coating]: generateMatrixRotations([0, 1, 0, 0, 1, 0, 0, 1, 0]), +}; + +export class MetaWireTunnelBuilding extends MetaBuilding { + constructor() { + super("wire_tunnel"); + } + + getSilhouetteColor() { + return "#777a86"; + } + + /** + * @param {GameRoot} root + */ + getIsUnlocked(root) { + // @todo + return true; + } + + /** + * + * @param {number} rotation + * @param {number} rotationVariant + * @param {string} variant + * @param {Entity} entity + */ + getSpecialOverlayRenderMatrix(rotation, rotationVariant, variant, entity) { + return wireTunnelOverlayMatrices[variant][rotation]; + } + + getIsRotateable(variant) { + return variant !== defaultBuildingVariant; + } + + getDimensions() { + return new Vector(1, 1); + } + + getAvailableVariants() { + return [defaultBuildingVariant, enumWireTunnelVariants.coating]; + } + + /** @returns {"wires"} **/ + getLayer() { + return "wires"; + } + + getRotateAutomaticallyWhilePlacing() { + return true; + } + + getStayInPlacementMode() { + return true; + } + + /** + * Creates the entity at the given location + * @param {Entity} entity + */ + setupEntityComponents(entity) { + entity.addComponent(new WireTunnelComponent({})); + } + + /** + * @param {Entity} entity + * @param {number} rotationVariant + * @param {string} variant + */ + updateVariants(entity, rotationVariant, variant) { + entity.components.WireTunnel.multipleDirections = variant === defaultBuildingVariant; + } +} diff --git a/src/js/game/colors.js b/src/js/game/colors.js index 9c7d0d2d..e7219175 100644 --- a/src/js/game/colors.js +++ b/src/js/game/colors.js @@ -10,8 +10,6 @@ export const enumColors = { white: "white", uncolored: "uncolored", - - black: "black", }; /** @enum {string} */ @@ -26,8 +24,6 @@ export const enumColorToShortcode = { [enumColors.white]: "w", [enumColors.uncolored]: "u", - - [enumColors.black]: "0", }; /** @enum {enumColors} */ @@ -54,27 +50,9 @@ export const enumColorsToHexCode = { // blue + green + red [enumColors.white]: "#ffffff", - [enumColors.black]: "#31383a", - [enumColors.uncolored]: "#aaaaaa", }; -/** @enum {enumColors} */ -export const enumInvertedColors = { - [enumColors.red]: enumColors.cyan, - [enumColors.green]: enumColors.purple, - [enumColors.blue]: enumColors.yellow, - - [enumColors.yellow]: enumColors.blue, - [enumColors.purple]: enumColors.green, - [enumColors.cyan]: enumColors.red, - - [enumColors.white]: enumColors.black, - [enumColors.black]: enumColors.white, - - [enumColors.uncolored]: enumColors.uncolored, -}; - const c = enumColors; /** @enum {Object.} */ export const enumColorMixingResults = { @@ -88,7 +66,6 @@ export const enumColorMixingResults = { [c.cyan]: c.white, [c.white]: c.white, - [c.black]: c.red, }, // 0, 255, 0 @@ -100,7 +77,6 @@ export const enumColorMixingResults = { [c.cyan]: c.cyan, [c.white]: c.white, - [c.black]: c.green, }, // 0, 255, 0 @@ -110,20 +86,17 @@ export const enumColorMixingResults = { [c.cyan]: c.cyan, [c.white]: c.white, - [c.black]: c.blue, }, // 255, 255, 0 [c.yellow]: { [c.purple]: c.white, [c.cyan]: c.white, - [c.black]: c.yellow, }, // 255, 0, 255 [c.purple]: { [c.cyan]: c.white, - [c.black]: c.purple, }, // 0, 255, 255 @@ -140,24 +113,12 @@ export const enumColorMixingResults = { [c.uncolored]: { // auto }, - - [c.black]: { - // auto - [c.white]: c.uncolored, - [c.cyan]: c.cyan, - [c.uncolored]: c.uncolored, - }, }; // Create same color lookups for (const color in enumColors) { enumColorMixingResults[color][color] = color; - - // Anything with white is white again, except for black which creates gray - if (color !== enumColors.black) { - enumColorMixingResults[color][c.white] = c.white; - } - + enumColorMixingResults[color][c.white] = c.white; // Anything with uncolored is the same color enumColorMixingResults[color][c.uncolored] = color; } diff --git a/src/js/game/component.js b/src/js/game/component.js index 1d44d60f..7d30faff 100644 --- a/src/js/game/component.js +++ b/src/js/game/component.js @@ -44,3 +44,9 @@ export class Component extends BasicSerializableObject { } /* dev:end */ } + +/** + * TypeScript does not support Abstract Static methods (https://github.com/microsoft/TypeScript/issues/34516) + * One workaround is to declare the type of the component and reference that for static methods + * @typedef {typeof Component} StaticComponent + */ diff --git a/src/js/game/component_registry.js b/src/js/game/component_registry.js index d3398937..84e6307a 100644 --- a/src/js/game/component_registry.js +++ b/src/js/game/component_registry.js @@ -5,14 +5,17 @@ import { ItemEjectorComponent } from "./components/item_ejector"; import { ItemAcceptorComponent } from "./components/item_acceptor"; import { MinerComponent } from "./components/miner"; import { ItemProcessorComponent } from "./components/item_processor"; -import { ReplaceableMapEntityComponent } from "./components/replaceable_map_entity"; import { UndergroundBeltComponent } from "./components/underground_belt"; -import { UnremovableComponent } from "./components/unremovable"; import { HubComponent } from "./components/hub"; import { StorageComponent } from "./components/storage"; -import { EnergyGeneratorComponent } from "./components/energy_generator"; import { WiredPinsComponent } from "./components/wired_pins"; -import { EnergyConsumerComponent } from "./components/energy_consumer"; +import { BeltUnderlaysComponent } from "./components/belt_underlays"; +import { WireComponent } from "./components/wire"; +import { ConstantSignalComponent } from "./components/constant_signal"; +import { LogicGateComponent } from "./components/logic_gate"; +import { LeverComponent } from "./components/lever"; +import { WireTunnelComponent } from "./components/wire_tunnel"; +import { DisplayComponent } from "./components/display"; export function initComponentRegistry() { gComponentRegistry.register(StaticMapEntityComponent); @@ -21,14 +24,17 @@ export function initComponentRegistry() { gComponentRegistry.register(ItemAcceptorComponent); gComponentRegistry.register(MinerComponent); gComponentRegistry.register(ItemProcessorComponent); - gComponentRegistry.register(ReplaceableMapEntityComponent); gComponentRegistry.register(UndergroundBeltComponent); - gComponentRegistry.register(UnremovableComponent); gComponentRegistry.register(HubComponent); gComponentRegistry.register(StorageComponent); - gComponentRegistry.register(EnergyGeneratorComponent); gComponentRegistry.register(WiredPinsComponent); - gComponentRegistry.register(EnergyConsumerComponent); + gComponentRegistry.register(BeltUnderlaysComponent); + gComponentRegistry.register(WireComponent); + gComponentRegistry.register(ConstantSignalComponent); + gComponentRegistry.register(LogicGateComponent); + gComponentRegistry.register(LeverComponent); + gComponentRegistry.register(WireTunnelComponent); + gComponentRegistry.register(DisplayComponent); // IMPORTANT ^^^^^ UPDATE ENTITY COMPONENT STORAGE AFTERWARDS diff --git a/src/js/game/components/belt.js b/src/js/game/components/belt.js index e9a0cd80..02197822 100644 --- a/src/js/game/components/belt.js +++ b/src/js/game/components/belt.js @@ -2,23 +2,44 @@ import { enumDirection, Vector } from "../../core/vector"; import { types } from "../../savegame/serialization"; import { BeltPath } from "../belt_path"; import { Component } from "../component"; -import { Entity } from "../entity"; -import { enumLayer } from "../root"; export const curvedBeltLength = /* Math.PI / 4 */ 0.78; +/** @type {import("./item_acceptor").ItemAcceptorSlot} */ +export const FAKE_BELT_ACCEPTOR_SLOT = { + pos: new Vector(0, 0), + directions: [enumDirection.bottom], +}; + +/** @type {Object} */ +export const FAKE_BELT_EJECTOR_SLOT_BY_DIRECTION = { + [enumDirection.top]: { + pos: new Vector(0, 0), + direction: enumDirection.top, + item: null, + progress: 0, + }, + + [enumDirection.right]: { + pos: new Vector(0, 0), + direction: enumDirection.right, + item: null, + progress: 0, + }, + + [enumDirection.left]: { + pos: new Vector(0, 0), + direction: enumDirection.left, + item: null, + progress: 0, + }, +}; + export class BeltComponent extends Component { static getId() { return "Belt"; } - static getSchema() { - // The followUpCache field is not serialized. - return { - direction: types.string, - }; - } - duplicateWithoutContents() { return new BeltComponent({ direction: this.direction }); } @@ -33,9 +54,6 @@ export class BeltComponent extends Component { this.direction = direction; - /** @type {Entity} */ - this.followUpCache = null; - /** * The path this belt is contained in, not serialized * @type {BeltPath} @@ -45,77 +63,59 @@ export class BeltComponent extends Component { /** * Returns the effective length of this belt in tile space - * @param {enumLayer} layer * @returns {number} */ - getEffectiveLengthTiles(layer) { - assert(layer, "no layer given"); - if (layer === enumLayer.wires) { - return 1.0; - } + getEffectiveLengthTiles() { return this.direction === enumDirection.top ? 1.0 : curvedBeltLength; } + /** + * Returns fake acceptor slot used for matching + * @returns {import("./item_acceptor").ItemAcceptorSlot} + */ + getFakeAcceptorSlot() { + return FAKE_BELT_ACCEPTOR_SLOT; + } + + /** + * Returns fake acceptor slot used for matching + * @returns {import("./item_ejector").ItemEjectorSlot} + */ + getFakeEjectorSlot() { + assert( + FAKE_BELT_EJECTOR_SLOT_BY_DIRECTION[this.direction], + "Invalid belt direction: ", + this.direction + ); + return FAKE_BELT_EJECTOR_SLOT_BY_DIRECTION[this.direction]; + } + /** * Converts from belt space (0 = start of belt ... 1 = end of belt) to the local * belt coordinates (-0.5|-0.5 to 0.5|0.5) * @param {number} progress - * @param {enumLayer} layer * @returns {Vector} */ - transformBeltToLocalSpace(progress, layer) { + transformBeltToLocalSpace(progress) { assert(progress >= 0.0, "Invalid progress ( < 0): " + progress); + switch (this.direction) { + case enumDirection.top: + assert(progress <= 1.02, "Invalid progress: " + progress); + return new Vector(0, 0.5 - progress); - switch (layer) { - case enumLayer.regular: { - switch (this.direction) { - case enumDirection.top: - assert(progress <= 1.02, "Invalid progress: " + progress); - return new Vector(0, 0.5 - progress); - - case enumDirection.right: { - assert(progress <= curvedBeltLength + 0.02, "Invalid progress 2: " + progress); - const arcProgress = (progress / curvedBeltLength) * 0.5 * Math.PI; - return new Vector( - 0.5 - 0.5 * Math.cos(arcProgress), - 0.5 - 0.5 * Math.sin(arcProgress) - ); - } - case enumDirection.left: { - assert(progress <= curvedBeltLength + 0.02, "Invalid progress 3: " + progress); - const arcProgress = (progress / curvedBeltLength) * 0.5 * Math.PI; - return new Vector( - -0.5 + 0.5 * Math.cos(arcProgress), - 0.5 - 0.5 * Math.sin(arcProgress) - ); - } - default: - assertAlways(false, "Invalid belt direction: " + this.direction); - return new Vector(0, 0); - } + case enumDirection.right: { + assert(progress <= curvedBeltLength + 0.02, "Invalid progress 2: " + progress); + const arcProgress = (progress / curvedBeltLength) * 0.5 * Math.PI; + return new Vector(0.5 - 0.5 * Math.cos(arcProgress), 0.5 - 0.5 * Math.sin(arcProgress)); } - case enumLayer.wires: { - const pow = 0.5; - switch (this.direction) { - case enumDirection.top: - assert(progress <= 1.02, "Invalid progress: " + progress); - return new Vector(0, 0.5 - progress); - - case enumDirection.right: { - assert(progress <= 1.02, "Invalid progress 2: " + progress); - return progress > 0.5 ? new Vector(progress - 0.5, 0) : new Vector(0, 0.5 - progress); - } - case enumDirection.left: { - assert(progress <= 1.02, "Invalid progress 3: " + progress); - return progress > 0.5 - ? new Vector(-progress + 0.5, 0) - : new Vector(0, 0.5 - progress); - } - default: - assertAlways(false, "Invalid belt direction: " + this.direction); - return new Vector(0, 0); - } + case enumDirection.left: { + assert(progress <= curvedBeltLength + 0.02, "Invalid progress 3: " + progress); + const arcProgress = (progress / curvedBeltLength) * 0.5 * Math.PI; + return new Vector(-0.5 + 0.5 * Math.cos(arcProgress), 0.5 - 0.5 * Math.sin(arcProgress)); } + default: + assertAlways(false, "Invalid belt direction: " + this.direction); + return new Vector(0, 0); } } } diff --git a/src/js/game/components/belt_underlays.js b/src/js/game/components/belt_underlays.js new file mode 100644 index 00000000..cb516b1a --- /dev/null +++ b/src/js/game/components/belt_underlays.js @@ -0,0 +1,33 @@ +import { Component } from "../component"; +import { types } from "../../savegame/serialization"; +import { enumDirection, Vector } from "../../core/vector"; + +export class BeltUnderlaysComponent extends Component { + static getId() { + return "BeltUnderlays"; + } + + duplicateWithoutContents() { + const beltUnderlaysCopy = []; + for (let i = 0; i < this.underlays.length; ++i) { + const underlay = this.underlays[i]; + beltUnderlaysCopy.push({ + pos: underlay.pos.copy(), + direction: underlay.direction, + }); + } + + return new BeltUnderlaysComponent({ + underlays: beltUnderlaysCopy, + }); + } + + /** + * @param {object} param0 + * @param {Array<{pos: Vector, direction: enumDirection}>=} param0.underlays Where to render belt underlays + */ + constructor({ underlays }) { + super(); + this.underlays = underlays; + } +} diff --git a/src/js/game/components/constant_signal.js b/src/js/game/components/constant_signal.js new file mode 100644 index 00000000..b51277a1 --- /dev/null +++ b/src/js/game/components/constant_signal.js @@ -0,0 +1,31 @@ +import { gItemRegistry } from "../../core/global_registries"; +import { types } from "../../savegame/serialization"; +import { Component } from "../component"; +import { BaseItem } from "../base_item"; +import { typeItemSingleton } from "../item_resolver"; + +export class ConstantSignalComponent extends Component { + static getId() { + return "ConstantSignal"; + } + + static getSchema() { + return { + signal: types.nullable(typeItemSingleton), + }; + } + + duplicateWithoutContents() { + return new ConstantSignalComponent({ signal: this.signal }); + } + + /** + * + * @param {object} param0 + * @param {BaseItem=} param0.signal The signal to store + */ + constructor({ signal = null }) { + super(); + this.signal = signal; + } +} diff --git a/src/js/game/components/display.js b/src/js/game/components/display.js new file mode 100644 index 00000000..720bf8c7 --- /dev/null +++ b/src/js/game/components/display.js @@ -0,0 +1,11 @@ +import { Component } from "../component"; + +export class DisplayComponent extends Component { + static getId() { + return "Display"; + } + + duplicateWithoutContents() { + return new DisplayComponent(); + } +} diff --git a/src/js/game/components/energy_consumer.js b/src/js/game/components/energy_consumer.js deleted file mode 100644 index 6e54af86..00000000 --- a/src/js/game/components/energy_consumer.js +++ /dev/null @@ -1,133 +0,0 @@ -import { Component } from "../component"; -import { types } from "../../savegame/serialization"; -import { Vector } from "../../core/vector"; -import { BaseItem, enumItemTypeToLayer, enumItemType } from "../base_item"; - -export class EnergyConsumerComponent extends Component { - static getId() { - return "EnergyConsumer"; - } - - static getSchema() { - return { - bufferSize: types.float, - perCharge: types.float, - batteryPosition: types.vector, - energyType: types.enum(enumItemType), - wasteType: types.enum(enumItemType), - acceptorSlotIndex: types.uint, - ejectorSlotIndex: types.uint, - - stored: types.float, - piledOutput: types.float, - }; - } - - duplicateWithoutContents() { - return new EnergyConsumerComponent({ - bufferSize: this.bufferSize, - perCharge: this.perCharge, - batteryPosition: this.batteryPosition.copy(), - acceptorSlotIndex: this.acceptorSlotIndex, - ejectorSlotIndex: this.ejectorSlotIndex, - }); - } - - /** - * - * @param {object} param0 - * @param {number} param0.bufferSize How much energy this consumer can store - * @param {number} param0.perCharge How much energy this consumer needs per charge - * @param {Vector} param0.batteryPosition world space render offset of the battery icon - * @param {number} param0.acceptorSlotIndex Which slot to accept energy on - * @param {number} param0.ejectorSlotIndex Which slot to eject energy off - * - */ - constructor({ - bufferSize = 3, - perCharge = 1, - batteryPosition = new Vector(), - acceptorSlotIndex = 0, - ejectorSlotIndex = 0, - }) { - super(); - this.bufferSize = bufferSize; - this.perCharge = perCharge; - this.batteryPosition = batteryPosition; - this.energyType = enumItemType.positiveEnergy; - this.wasteType = enumItemType.negativeEnergy; - this.acceptorSlotIndex = acceptorSlotIndex; - this.ejectorSlotIndex = ejectorSlotIndex; - - /** - * How much energy we have stored right now - */ - this.stored = 0; - - /** - * How much waste we have piled up so far - */ - this.piledOutput = 0; - } - - /** - * Tries to accept a given item - * @param {BaseItem} item - * @param {number} slotIndex - */ - tryAcceptItem(item, slotIndex) { - if (slotIndex !== this.acceptorSlotIndex) { - // Wrong slot - return false; - } - - if (item.getItemType() !== this.energyType) { - // Not the right type - return false; - } - - if (this.stored >= this.bufferSize) { - // We are full - return false; - } - - // All good, consume - this.stored = Math.min(this.stored + 1, this.bufferSize); - - return true; - } - - /** - * Tries to start the next charge - */ - tryStartNextCharge() { - if (this.hasTooMuchWastePiled()) { - // Too much waste remaining - return false; - } - - if (this.stored < this.perCharge) { - // Not enough energy stored - return false; - } - - this.stored -= this.perCharge; - this.piledOutput += this.perCharge; - return true; - } - - /** - * Returns if there is too much waste piled - */ - hasTooMuchWastePiled() { - return this.piledOutput >= 1.0; - } - - /** - * Reduces the waste by the given amount - * @param {number} amount - */ - reduceWaste(amount) { - this.piledOutput = Math.max(0, this.piledOutput - amount); - } -} diff --git a/src/js/game/components/energy_generator.js b/src/js/game/components/energy_generator.js deleted file mode 100644 index a45492d7..00000000 --- a/src/js/game/components/energy_generator.js +++ /dev/null @@ -1,93 +0,0 @@ -import { types } from "../../savegame/serialization"; -import { BaseItem, enumItemType } from "../base_item"; -import { Component } from "../component"; -import { ShapeItem } from "../items/shape_item"; - -const maxQueueSize = 4; - -export class EnergyGeneratorComponent extends Component { - static getId() { - return "EnergyGenerator"; - } - - static getSchema() { - return { - requiredKey: types.nullable(types.string), - itemsInQueue: types.uint, - wasteAcceptorSlotIndex: types.uint, - }; - } - - duplicateWithoutContents() { - return new EnergyGeneratorComponent({ - requiredKey: null, - wasteAcceptorSlotIndex: this.wasteAcceptorSlotIndex, - }); - } - - /** - * - * @param {object} param0 - * @param {string=} param0.requiredKey Which shape this generator needs, can be null if not computed yet - * @param {number} param0.wasteAcceptorSlotIndex Which slot accepts the waste - */ - constructor({ requiredKey, wasteAcceptorSlotIndex = 0 }) { - super(); - this.requiredKey = requiredKey; - - /** - * Stores how many items are ready to be converted to energy - * @type {number} - */ - this.itemsInQueue = 0; - - /** - * Stores which slot accepts the waste - * @type {number} - */ - this.wasteAcceptorSlotIndex = wasteAcceptorSlotIndex; - } - - /** - * - * @param {BaseItem} item - * @param {number} slot - */ - tryTakeItem(item, slot) { - if (slot === this.wasteAcceptorSlotIndex) { - // this is the acceptor slot on the wires layer - // just destroy it - return true; - } else { - if (item.getItemType() !== enumItemType.shape) { - // This shouldn't happen since we have a filter - still, it doesn't hurt - // to check either - assertAlways( - false, - "Energy generator took wrong item: " + - item.getItemType() + - " on slot " + - slot + - " (waste slot = " + - this.wasteAcceptorSlotIndex + - ")" - ); - return false; - } - - if (/** @type {ShapeItem} */ (item).definition.getHash() !== this.requiredKey) { - // Not our shape - return false; - } - - if (this.itemsInQueue >= maxQueueSize) { - // Queue is full - return false; - } - - // Take item and put it into the queue - ++this.itemsInQueue; - return true; - } - } -} diff --git a/src/js/game/components/hub.js b/src/js/game/components/hub.js index f9c13dc3..fb88d6f6 100644 --- a/src/js/game/components/hub.js +++ b/src/js/game/components/hub.js @@ -1,32 +1,7 @@ import { Component } from "../component"; -import { ShapeDefinition } from "../shape_definition"; -import { types } from "../../savegame/serialization"; export class HubComponent extends Component { static getId() { return "Hub"; } - - static getSchema() { - return { - definitionsToAnalyze: types.array(types.knownType(ShapeDefinition)), - }; - } - - constructor() { - super(); - - /** - * Shape definitions in queue to be analyzed and counted towards the goal - * @type {Array} - */ - this.definitionsToAnalyze = []; - } - - /** - * @param {ShapeDefinition} definition - */ - queueShapeDefinition(definition) { - this.definitionsToAnalyze.push(definition); - } } diff --git a/src/js/game/components/item_acceptor.js b/src/js/game/components/item_acceptor.js index a5676119..ebd7ae5f 100644 --- a/src/js/game/components/item_acceptor.js +++ b/src/js/game/components/item_acceptor.js @@ -1,14 +1,12 @@ import { enumDirection, enumInvertedDirections, Vector } from "../../core/vector"; import { types } from "../../savegame/serialization"; -import { BaseItem, enumItemType } from "../base_item"; +import { BaseItem } from "../base_item"; import { Component } from "../component"; -import { enumLayer } from "../root"; /** @typedef {{ * pos: Vector, * directions: enumDirection[], - * layer: enumLayer, - * filter?: enumItemType + * filter?: ItemType * }} ItemAcceptorSlot */ /** @@ -22,8 +20,7 @@ import { enumLayer } from "../root"; /** @typedef {{ * pos: Vector, * directions: enumDirection[], - * layer?: enumLayer, - * filter?: enumItemType + * filter?: ItemType * }} ItemAcceptorSlotConfig */ export class ItemAcceptorComponent extends Component { @@ -31,31 +28,6 @@ export class ItemAcceptorComponent extends Component { return "ItemAcceptor"; } - static getSchema() { - return { - slots: types.array( - types.structured({ - pos: types.vector, - directions: types.array(types.enum(enumDirection)), - filter: types.nullable(types.enum(enumItemType)), - - // TODO: MIGRATE - layer: types.enum(enumLayer), - }) - ), - animated: types.bool, - beltUnderlays: types.array( - types.structured({ - pos: types.vector, - direction: types.enum(enumDirection), - - // TODO: MIGRATE - layer: types.enum(enumLayer), - }) - ), - }; - } - duplicateWithoutContents() { const slotsCopy = []; for (let i = 0; i < this.slots.length; ++i) { @@ -64,24 +36,11 @@ export class ItemAcceptorComponent extends Component { pos: slot.pos.copy(), directions: slot.directions.slice(), filter: slot.filter, - layer: slot.layer, - }); - } - - const beltUnderlaysCopy = []; - for (let i = 0; i < this.beltUnderlays.length; ++i) { - const underlay = this.beltUnderlays[i]; - beltUnderlaysCopy.push({ - pos: underlay.pos.copy(), - direction: underlay.direction, - layer: underlay.layer, }); } return new ItemAcceptorComponent({ slots: slotsCopy, - beltUnderlays: beltUnderlaysCopy, - animated: this.animated, }); } @@ -89,23 +48,16 @@ export class ItemAcceptorComponent extends Component { * * @param {object} param0 * @param {Array} param0.slots The slots from which we accept items - * @param {boolean=} param0.animated Whether to animate item consumption - * @param {Array<{pos: Vector, direction: enumDirection, layer: enumLayer}>=} param0.beltUnderlays Where to render belt underlays */ - constructor({ slots = [], beltUnderlays = [], animated = true }) { + constructor({ slots = [] }) { super(); - this.animated = animated; - /** * Fixes belt animations * @type {Array<{ item: BaseItem, slotIndex: number, animProgress: number, direction: enumDirection }>} */ this.itemConsumptionAnimations = []; - /* Which belt underlays to render */ - this.beltUnderlays = beltUnderlays; - this.setSlots(slots); } @@ -121,9 +73,8 @@ export class ItemAcceptorComponent extends Component { this.slots.push({ pos: slot.pos, directions: slot.directions, - layer: slot.layer || enumLayer.regular, - // Which type of item to accept (shape | color | all) @see enumItemType + // Which type of item to accept (shape | color | all) @see ItemType filter: slot.filter, }); } @@ -136,25 +87,7 @@ export class ItemAcceptorComponent extends Component { */ canAcceptItem(slotIndex, item) { const slot = this.slots[slotIndex]; - return this.filterMatches(slot.filter, item); - } - - /** - * Returns if the given filter matches - * @param {enumItemType|null} filter - * @param {BaseItem} item - */ - filterMatches(filter, item) { - if (!filter) { - return true; - } - - const itemType = item.getItemType(); - if (filter === enumItemType.genericEnergy) { - return itemType === enumItemType.positiveEnergy || itemType === enumItemType.negativeEnergy; - } - - return itemType === filter; + return !slot.filter || slot.filter === item.getItemType(); } /** @@ -164,24 +97,21 @@ export class ItemAcceptorComponent extends Component { * @param {BaseItem} item */ onItemAccepted(slotIndex, direction, item) { - if (this.animated) { - this.itemConsumptionAnimations.push({ - item, - slotIndex, - direction, - animProgress: 0.0, - }); - } + this.itemConsumptionAnimations.push({ + item, + slotIndex, + direction, + animProgress: 0.0, + }); } /** * Tries to find a slot which accepts the current item * @param {Vector} targetLocalTile * @param {enumDirection} fromLocalDirection - * @param {enumLayer} layer * @returns {ItemAcceptorLocatedSlot|null} */ - findMatchingSlot(targetLocalTile, fromLocalDirection, layer) { + findMatchingSlot(targetLocalTile, fromLocalDirection) { // We need to invert our direction since the acceptor specifies *from* which direction // it accepts items, but the ejector specifies *into* which direction it ejects items. // E.g.: Ejector ejects into "right" direction but acceptor accepts from "left" direction. @@ -196,11 +126,6 @@ export class ItemAcceptorComponent extends Component { continue; } - // Make sure the layer matches - if (slot.layer !== layer) { - continue; - } - // Check if the acceptor slot accepts items from our direction for (let i = 0; i < slot.directions.length; ++i) { // const localDirection = targetStaticComp.localDirectionToWorld(slot.directions[l]); diff --git a/src/js/game/components/item_ejector.js b/src/js/game/components/item_ejector.js index ee661078..b9a23c38 100644 --- a/src/js/game/components/item_ejector.js +++ b/src/js/game/components/item_ejector.js @@ -1,19 +1,19 @@ -import { Vector, enumDirection, enumDirectionToVector } from "../../core/vector"; -import { BaseItem } from "../base_item"; -import { Component } from "../component"; +import { enumDirection, enumDirectionToVector, Vector } from "../../core/vector"; import { types } from "../../savegame/serialization"; -import { gItemRegistry } from "../../core/global_registries"; +import { BaseItem } from "../base_item"; +import { BeltPath } from "../belt_path"; +import { Component } from "../component"; import { Entity } from "../entity"; -import { enumLayer } from "../root"; +import { typeItemSingleton } from "../item_resolver"; /** * @typedef {{ * pos: Vector, * direction: enumDirection, * item: BaseItem, - * layer: enumLayer, * progress: number?, * cachedDestSlot?: import("./item_acceptor").ItemAcceptorLocatedSlot, + * cachedBeltPath?: BeltPath, * cachedTargetEntity?: Entity * }} ItemEjectorSlot */ @@ -24,19 +24,12 @@ export class ItemEjectorComponent extends Component { } static getSchema() { - // The cachedDestSlot, cachedTargetEntity, and cachedConnectedSlots fields - // are not serialized. + // The cachedDestSlot, cachedTargetEntity fields are not serialized. return { - instantEject: types.bool, slots: types.array( types.structured({ - pos: types.vector, - direction: types.enum(enumDirection), - item: types.nullable(types.obj(gItemRegistry)), + item: types.nullable(typeItemSingleton), progress: types.float, - - // TODO: Migrate - layer: types.enum(enumLayer), }) ), }; @@ -49,33 +42,24 @@ export class ItemEjectorComponent extends Component { slotsCopy.push({ pos: slot.pos.copy(), direction: slot.direction, - layer: slot.layer, }); } return new ItemEjectorComponent({ slots: slotsCopy, - instantEject: this.instantEject, }); } /** * * @param {object} param0 - * @param {Array<{pos: Vector, direction: enumDirection, layer?: enumLayer}>=} param0.slots The slots to eject on - * @param {boolean=} param0.instantEject If the ejection is instant + * @param {Array<{pos: Vector, direction: enumDirection }>=} param0.slots The slots to eject on */ - constructor({ slots = [], instantEject = false }) { + constructor({ slots = [] }) { super(); - // How long items take to eject - this.instantEject = instantEject; - this.setSlots(slots); - /** @type {ItemEjectorSlot[]} */ - this.cachedConnectedSlots = null; - /** * Whether this ejector slot is enabled */ @@ -83,7 +67,7 @@ export class ItemEjectorComponent extends Component { } /** - * @param {Array<{pos: Vector, direction: enumDirection, layer?: enumLayer}>} slots The slots to eject on + * @param {Array<{pos: Vector, direction: enumDirection }>} slots The slots to eject on */ setSlots(slots) { /** @type {Array} */ @@ -95,7 +79,6 @@ export class ItemEjectorComponent extends Component { direction: slot.direction, item: null, progress: 0, - layer: slot.layer || enumLayer.regular, cachedDestSlot: null, cachedTargetEntity: null, }); @@ -104,11 +87,10 @@ export class ItemEjectorComponent extends Component { /** * Returns where this slot ejects to - * @param {number} index + * @param {ItemEjectorSlot} slot * @returns {Vector} */ - getSlotTargetLocalTile(index) { - const slot = this.slots[index]; + getSlotTargetLocalTile(slot) { const directionVector = enumDirectionToVector[slot.direction]; return slot.pos.add(directionVector); } @@ -116,11 +98,10 @@ export class ItemEjectorComponent extends Component { /** * Returns whether any slot ejects to the given local tile * @param {Vector} tile - * @param {enumLayer} layer */ - anySlotEjectsToLocalTile(tile, layer) { + anySlotEjectsToLocalTile(tile) { for (let i = 0; i < this.slots.length; ++i) { - if (this.getSlotTargetLocalTile(i).equals(tile) && this.slots[i].layer === layer) { + if (this.getSlotTargetLocalTile(this.slots[i]).equals(tile)) { return true; } } @@ -139,12 +120,11 @@ export class ItemEjectorComponent extends Component { /** * Returns the first free slot on this ejector or null if there is none - * @param {enumLayer} layer * @returns {number?} */ - getFirstFreeSlot(layer) { + getFirstFreeSlot() { for (let i = 0; i < this.slots.length; ++i) { - if (this.canEjectOnSlot(i) && this.slots[i].layer === layer) { + if (this.canEjectOnSlot(i)) { return i; } } @@ -162,7 +142,7 @@ export class ItemEjectorComponent extends Component { return false; } this.slots[slotIndex].item = item; - this.slots[slotIndex].progress = this.instantEject ? 1 : 0; + this.slots[slotIndex].progress = 0; return true; } diff --git a/src/js/game/components/item_processor.js b/src/js/game/components/item_processor.js index 806ec7c8..02b742d4 100644 --- a/src/js/game/components/item_processor.js +++ b/src/js/game/components/item_processor.js @@ -1,7 +1,7 @@ -import { gItemRegistry } from "../../core/global_registries"; import { types } from "../../savegame/serialization"; import { BaseItem } from "../base_item"; import { Component } from "../component"; +import { typeItemSingleton } from "../item_resolver"; /** @enum {string} */ export const enumItemProcessorTypes = { @@ -18,8 +18,8 @@ export const enumItemProcessorTypes = { painter: "painter", painterDouble: "painterDouble", painterQuad: "painterQuad", - advancedProcessor: "advancedProcessor", hub: "hub", + filter: "filter", }; export class ItemProcessorComponent extends Component { @@ -30,18 +30,15 @@ export class ItemProcessorComponent extends Component { static getSchema() { return { nextOutputSlot: types.uint, - type: types.enum(enumItemProcessorTypes), - inputsPerCharge: types.uint, - inputSlots: types.array( types.structured({ - item: types.obj(gItemRegistry), + item: typeItemSingleton, sourceSlot: types.uint, }) ), itemsToEject: types.array( types.structured({ - item: types.obj(gItemRegistry), + item: typeItemSingleton, requiredSlot: types.nullable(types.uint), preferredSlot: types.nullable(types.uint), }) diff --git a/src/js/game/components/lever.js b/src/js/game/components/lever.js new file mode 100644 index 00000000..73cf0143 --- /dev/null +++ b/src/js/game/components/lever.js @@ -0,0 +1,20 @@ +import { Component } from "../component"; + +export class LeverComponent extends Component { + static getId() { + return "Lever"; + } + + duplicateWithoutContents() { + return new LeverComponent({ toggled: this.toggled }); + } + + /** + * @param {object} param0 + * @param {boolean=} param0.toggled + */ + constructor({ toggled = false }) { + super(); + this.toggled = toggled; + } +} diff --git a/src/js/game/components/logic_gate.js b/src/js/game/components/logic_gate.js new file mode 100644 index 00000000..bf3f3477 --- /dev/null +++ b/src/js/game/components/logic_gate.js @@ -0,0 +1,30 @@ +import { Component } from "../component"; + +/** @enum {string} */ +export const enumLogicGateType = { + and: "and", + not: "not", + xor: "xor", + or: "or", + transistor: "transistor", +}; + +export class LogicGateComponent extends Component { + static getId() { + return "LogicGate"; + } + + duplicateWithoutContents() { + return new LogicGateComponent({ type: this.type }); + } + + /** + * + * @param {object} param0 + * @param {enumLogicGateType=} param0.type + */ + constructor({ type = enumLogicGateType.and }) { + super(); + this.type = type; + } +} diff --git a/src/js/game/components/miner.js b/src/js/game/components/miner.js index 74a4b616..a7515678 100644 --- a/src/js/game/components/miner.js +++ b/src/js/game/components/miner.js @@ -1,8 +1,7 @@ -import { globalConfig } from "../../core/config"; import { types } from "../../savegame/serialization"; -import { Component } from "../component"; import { BaseItem } from "../base_item"; -import { gItemRegistry } from "../../core/global_registries"; +import { Component } from "../component"; +import { typeItemSingleton } from "../item_resolver"; const chainBufferSize = 3; @@ -15,8 +14,7 @@ export class MinerComponent extends Component { // cachedMinedItem is not serialized. return { lastMiningTime: types.ufloat, - chainable: types.bool, - itemChainBuffer: types.array(types.obj(gItemRegistry)), + itemChainBuffer: types.array(typeItemSingleton), }; } diff --git a/src/js/game/components/replaceable_map_entity.js b/src/js/game/components/replaceable_map_entity.js deleted file mode 100644 index 78861caf..00000000 --- a/src/js/game/components/replaceable_map_entity.js +++ /dev/null @@ -1,15 +0,0 @@ -import { Component } from "../component"; - -/** - * Marks an entity as replaceable, so that when other buildings are placed above him it - * simply gets deleted - */ -export class ReplaceableMapEntityComponent extends Component { - static getId() { - return "ReplaceableMapEntity"; - } - - duplicateWithoutContents() { - return new ReplaceableMapEntityComponent(); - } -} diff --git a/src/js/game/components/static_map_entity.js b/src/js/game/components/static_map_entity.js index 6494aba1..db4c834e 100644 --- a/src/js/game/components/static_map_entity.js +++ b/src/js/game/components/static_map_entity.js @@ -4,8 +4,8 @@ import { Rectangle } from "../../core/rectangle"; import { AtlasSprite } from "../../core/sprites"; import { enumDirection, Vector } from "../../core/vector"; import { types } from "../../savegame/serialization"; -import { Component } from "../component"; import { getBuildingDataFromCode } from "../building_codes"; +import { Component } from "../component"; export class StaticMapEntityComponent extends Component { static getId() { @@ -15,7 +15,6 @@ export class StaticMapEntityComponent extends Component { static getSchema() { return { origin: types.tileVector, - tileSize: types.tileVector, rotation: types.float, originalRotation: types.float, @@ -24,6 +23,14 @@ export class StaticMapEntityComponent extends Component { }; } + /** + * Returns the effective tile size + * @returns {Vector} + */ + getTileSize() { + return getBuildingDataFromCode(this.code).tileSize; + } + /** * Returns the sprite * @returns {AtlasSprite} @@ -48,10 +55,17 @@ export class StaticMapEntityComponent extends Component { return getBuildingDataFromCode(this.code).silhouetteColor; } + /** + * Returns the meta building + * @returns {import("../meta_building").MetaBuilding} + */ + getMetaBuilding() { + return getBuildingDataFromCode(this.code).metaInstance; + } + duplicateWithoutContents() { return new StaticMapEntityComponent({ origin: this.origin.copy(), - tileSize: this.tileSize.copy(), rotation: this.rotation, originalRotation: this.originalRotation, code: this.code, @@ -81,7 +95,6 @@ export class StaticMapEntityComponent extends Component { ); this.origin = origin; - this.tileSize = tileSize; this.rotation = rotation; this.code = code; this.originalRotation = originalRotation; @@ -92,30 +105,16 @@ export class StaticMapEntityComponent extends Component { * @returns {Rectangle} */ getTileSpaceBounds() { + const size = this.getTileSize(); switch (this.rotation) { case 0: - return new Rectangle(this.origin.x, this.origin.y, this.tileSize.x, this.tileSize.y); + return new Rectangle(this.origin.x, this.origin.y, size.x, size.y); case 90: - return new Rectangle( - this.origin.x - this.tileSize.y + 1, - this.origin.y, - this.tileSize.y, - this.tileSize.x - ); + return new Rectangle(this.origin.x - size.y + 1, this.origin.y, size.y, size.x); case 180: - return new Rectangle( - this.origin.x - this.tileSize.x + 1, - this.origin.y - this.tileSize.y + 1, - this.tileSize.x, - this.tileSize.y - ); + return new Rectangle(this.origin.x - size.x + 1, this.origin.y - size.y + 1, size.x, size.y); case 270: - return new Rectangle( - this.origin.x, - this.origin.y - this.tileSize.x + 1, - this.tileSize.y, - this.tileSize.x - ); + return new Rectangle(this.origin.x, this.origin.y - size.x + 1, size.y, size.x); default: assert(false, "Invalid rotation"); } @@ -186,34 +185,35 @@ export class StaticMapEntityComponent extends Component { let y = 0; let w = 0; let h = 0; + const size = this.getTileSize(); switch (this.rotation) { case 0: { x = this.origin.x; y = this.origin.y; - w = this.tileSize.x; - h = this.tileSize.y; + w = size.x; + h = size.y; break; } case 90: { - x = this.origin.x - this.tileSize.y + 1; + x = this.origin.x - size.y + 1; y = this.origin.y; - w = this.tileSize.y; - h = this.tileSize.x; + w = size.y; + h = size.x; break; } case 180: { - x = this.origin.x - this.tileSize.x + 1; - y = this.origin.y - this.tileSize.y + 1; - w = this.tileSize.x; - h = this.tileSize.y; + x = this.origin.x - size.x + 1; + y = this.origin.y - size.y + 1; + w = size.x; + h = size.y; break; } case 270: { x = this.origin.x; - y = this.origin.y - this.tileSize.x + 1; - w = this.tileSize.y; - h = this.tileSize.x; + y = this.origin.y - size.x + 1; + w = size.y; + h = size.x; break; } default: @@ -233,19 +233,13 @@ export class StaticMapEntityComponent extends Component { * @param {DrawParameters} parameters * @param {AtlasSprite} sprite * @param {number=} extrudePixels How many pixels to extrude the sprite - * @param {boolean=} clipping Whether to clip * @param {Vector=} overridePosition Whether to drwa the entity at a different location */ - drawSpriteOnFullEntityBounds( - parameters, - sprite, - extrudePixels = 0, - clipping = true, - overridePosition = null - ) { + drawSpriteOnFullEntityBounds(parameters, sprite, extrudePixels = 0, overridePosition = null) { if (!this.shouldBeDrawn(parameters) && !overridePosition) { return; } + const size = this.getTileSize(); let worldX = this.origin.x * globalConfig.tileSize; let worldY = this.origin.y * globalConfig.tileSize; @@ -258,11 +252,10 @@ export class StaticMapEntityComponent extends Component { // Early out, is faster sprite.drawCached( parameters, - worldX - extrudePixels * this.tileSize.x, - worldY - extrudePixels * this.tileSize.y, - globalConfig.tileSize * this.tileSize.x + 2 * extrudePixels * this.tileSize.x, - globalConfig.tileSize * this.tileSize.y + 2 * extrudePixels * this.tileSize.y, - false + worldX - extrudePixels * size.x, + worldY - extrudePixels * size.y, + globalConfig.tileSize * size.x + 2 * extrudePixels * size.x, + globalConfig.tileSize * size.y + 2 * extrudePixels * size.y ); } else { const rotationCenterX = worldX + globalConfig.halfTileSize; @@ -270,16 +263,14 @@ export class StaticMapEntityComponent extends Component { parameters.context.translate(rotationCenterX, rotationCenterY); parameters.context.rotate(Math.radians(this.rotation)); - sprite.drawCached( parameters, - -globalConfig.halfTileSize - extrudePixels * this.tileSize.x, - -globalConfig.halfTileSize - extrudePixels * this.tileSize.y, - globalConfig.tileSize * this.tileSize.x + 2 * extrudePixels * this.tileSize.x, - globalConfig.tileSize * this.tileSize.y + 2 * extrudePixels * this.tileSize.y, - false + -globalConfig.halfTileSize - extrudePixels * size.x, + -globalConfig.halfTileSize - extrudePixels * size.y, + globalConfig.tileSize * size.x + 2 * extrudePixels * size.x, + globalConfig.tileSize * size.y + 2 * extrudePixels * size.y, + false // no clipping possible here ); - parameters.context.rotate(-Math.radians(this.rotation)); parameters.context.translate(-rotationCenterX, -rotationCenterY); } diff --git a/src/js/game/components/storage.js b/src/js/game/components/storage.js index e7b40a77..3b32f6a3 100644 --- a/src/js/game/components/storage.js +++ b/src/js/game/components/storage.js @@ -1,7 +1,7 @@ -import { Component } from "../component"; import { types } from "../../savegame/serialization"; -import { gItemRegistry } from "../../core/global_registries"; -import { BaseItem, enumItemType } from "../base_item"; +import { BaseItem } from "../base_item"; +import { Component } from "../component"; +import { typeItemSingleton } from "../item_resolver"; import { ColorItem } from "../items/color_item"; import { ShapeItem } from "../items/shape_item"; @@ -12,10 +12,8 @@ export class StorageComponent extends Component { static getSchema() { return { - maximumStorage: types.uint, storedCount: types.uint, - storedItem: types.nullable(types.obj(gItemRegistry)), - overlayOpacity: types.ufloat, + storedItem: types.nullable(typeItemSingleton), }; } @@ -67,11 +65,11 @@ export class StorageComponent extends Component { return false; } - if (itemType === enumItemType.color) { + if (itemType === "color") { return /** @type {ColorItem} */ (this.storedItem).color === /** @type {ColorItem} */ (item).color; } - if (itemType === enumItemType.shape) { + if (itemType === "shape") { return ( /** @type {ShapeItem} */ (this.storedItem).definition.getHash() === /** @type {ShapeItem} */ (item).definition.getHash() @@ -80,6 +78,14 @@ export class StorageComponent extends Component { return false; } + /** + * Returns whether the storage is full + * @returns {boolean} + */ + getIsFull() { + return this.storedCount >= this.maximumStorage; + } + /** * @param {BaseItem} item */ diff --git a/src/js/game/components/underground_belt.js b/src/js/game/components/underground_belt.js index e94b7cb1..74351aac 100644 --- a/src/js/game/components/underground_belt.js +++ b/src/js/game/components/underground_belt.js @@ -1,10 +1,9 @@ -import { BaseItem } from "../base_item"; -import { Component } from "../component"; import { globalConfig } from "../../core/config"; import { types } from "../../savegame/serialization"; -import { gItemRegistry } from "../../core/global_registries"; +import { BaseItem } from "../base_item"; +import { Component } from "../component"; import { Entity } from "../entity"; -import { enumLayer } from "../root"; +import { typeItemSingleton } from "../item_resolver"; /** @enum {string} */ export const enumUndergroundBeltMode = { @@ -26,9 +25,7 @@ export class UndergroundBeltComponent extends Component { static getSchema() { return { - mode: types.enum(enumUndergroundBeltMode), - pendingItems: types.array(types.pair(types.obj(gItemRegistry), types.float)), - tier: types.uint, + pendingItems: types.array(types.pair(typeItemSingleton, types.float)), }; } @@ -103,8 +100,7 @@ export class UndergroundBeltComponent extends Component { } // Notice: We assume that for all items the travel distance is the same - const maxItemsInTunnel = - (2 + travelDistance) / globalConfig.beltItemSpacingByLayer[enumLayer.regular]; + const maxItemsInTunnel = (2 + travelDistance) / globalConfig.itemSpacingOnBelts; if (this.pendingItems.length >= maxItemsInTunnel) { // Simulate a real belt which gets full at some point return false; @@ -114,8 +110,7 @@ export class UndergroundBeltComponent extends Component { // This corresponds to the item ejector - it needs 0.5 additional tiles to eject the item. // So instead of adding 1 we add 0.5 only. // Additionally it takes 1 tile for the acceptor which we just add on top. - const travelDuration = - (travelDistance + 1.5) / beltSpeed / globalConfig.beltItemSpacingByLayer[enumLayer.regular]; + const travelDuration = (travelDistance + 1.5) / beltSpeed / globalConfig.itemSpacingOnBelts; this.pendingItems.push([item, travelDuration]); diff --git a/src/js/game/components/unremovable.js b/src/js/game/components/unremovable.js deleted file mode 100644 index f3864cf8..00000000 --- a/src/js/game/components/unremovable.js +++ /dev/null @@ -1,15 +0,0 @@ -import { Component } from "../component"; - -export class UnremovableComponent extends Component { - static getId() { - return "Unremovable"; - } - - static getSchema() { - return {}; - } - - duplicateWithoutContents() { - return new UnremovableComponent(); - } -} diff --git a/src/js/game/components/wire.js b/src/js/game/components/wire.js new file mode 100644 index 00000000..88c56249 --- /dev/null +++ b/src/js/game/components/wire.js @@ -0,0 +1,73 @@ +import { Component } from "../component"; + +/** @enum {string} */ +export const enumWireType = { + regular: "regular", + turn: "turn", + split: "split", + cross: "cross", +}; + +export class WireComponent extends Component { + static getId() { + return "Wire"; + } + + duplicateWithoutContents() { + return new WireComponent({ type: this.type }); + } + + /** + * @param {object} param0 + * @param {enumWireType=} param0.type + */ + constructor({ type = enumWireType.regular }) { + super(); + this.type = type; + + /** + * @type {import("../systems/wire").WireNetwork} + */ + this.linkedNetwork = null; + } + + /** + * Returns the local connections + * @returns {import("../../core/utils").DirectionalObject} + */ + getLocalConnections() { + return { + top: true, + right: false, + bottom: true, + left: false, + }; + + // switch (this.type) { + // case enumWireType.regular: + // return { + // top: true, + // right: false, + // bottom: true, + // left: false, + // }; + // case enumWireType.turn: + // return { + // top: false, + // right: true, + // bottom: true, + // left: false, + // }; + // case enumWireType.split: + // return { + // top: false, + // right: true, + // bottom: true, + // left: true, + // }; + + // default: + // assertAlways(false, "Invalid wire type: " + this.type); + // } + } +} diff --git a/src/js/game/components/wire_tunnel.js b/src/js/game/components/wire_tunnel.js new file mode 100644 index 00000000..dfb38f1f --- /dev/null +++ b/src/js/game/components/wire_tunnel.js @@ -0,0 +1,26 @@ +import { Component } from "../component"; + +export class WireTunnelComponent extends Component { + static getId() { + return "WireTunnel"; + } + + duplicateWithoutContents() { + return new WireTunnelComponent({ multipleDirections: this.multipleDirections }); + } + + /** + * @param {object} param0 + * @param {boolean=} param0.multipleDirections + */ + constructor({ multipleDirections = true }) { + super(); + this.multipleDirections = multipleDirections; + + /** + * Linked network, only if its not multiple directions + * @type {Array} + */ + this.linkedNetworks = []; + } +} diff --git a/src/js/game/components/wired_pins.js b/src/js/game/components/wired_pins.js index 0d331a68..2822ab57 100644 --- a/src/js/game/components/wired_pins.js +++ b/src/js/game/components/wired_pins.js @@ -1,13 +1,11 @@ +import { enumDirection, Vector } from "../../core/vector"; +import { BaseItem } from "../base_item"; import { Component } from "../component"; -import { Vector, enumDirection } from "../../core/vector"; -import { types } from "../../savegame/serialization"; /** @enum {string} */ export const enumPinSlotType = { - positiveEnergyEjector: "positiveEnergyEjector", - negativeEnergyEjector: "negativeEnergyEjector", - positiveEnergyAcceptor: "positiveEnergyAcceptor", - negativeEnergyAcceptor: "negativeEnergyAcceptor", + logicalEjector: "logicalEjector", + logicalAcceptor: "logicalAcceptor", }; /** @typedef {{ @@ -19,7 +17,9 @@ export const enumPinSlotType = { /** @typedef {{ * pos: Vector, * type: enumPinSlotType, - * direction: enumDirection + * direction: enumDirection, + * value: BaseItem, + * linkedNetwork: import("../systems/wire").WireNetwork * }} WirePinSlot */ export class WiredPinsComponent extends Component { @@ -27,17 +27,6 @@ export class WiredPinsComponent extends Component { return "WiredPins"; } - static getSchema() { - return { - slots: types.array( - types.structured({ - pos: types.vector, - type: types.enum(enumPinSlotType), - }) - ), - }; - } - /** * * @param {object} param0 @@ -76,6 +65,8 @@ export class WiredPinsComponent extends Component { pos: slotData.pos, type: slotData.type, direction: slotData.direction, + value: null, + linkedNetwork: null, }); } } diff --git a/src/js/game/core.js b/src/js/game/core.js index 960a83e3..70d69c2c 100644 --- a/src/js/game/core.js +++ b/src/js/game/core.js @@ -1,8 +1,6 @@ /* typehints:start */ -import { InGameState } from "../states/ingame"; import { Application } from "../application"; /* typehints:end */ - import { BufferMaintainer } from "../core/buffer_maintainer"; import { disableImageSmoothing, enableImageSmoothing, registerCanvas } from "../core/buffer_utils"; import { globalConfig } from "../core/config"; @@ -10,12 +8,15 @@ import { getDeviceDPI, resizeHighDPICanvas } from "../core/dpi_manager"; import { DrawParameters } from "../core/draw_parameters"; import { gMetaBuildingRegistry } from "../core/global_registries"; import { createLogger } from "../core/logging"; +import { Rectangle } from "../core/rectangle"; +import { randomInt, round2Digits } from "../core/utils"; import { Vector } from "../core/vector"; import { Savegame } from "../savegame/savegame"; import { SavegameSerializer } from "../savegame/savegame_serializer"; import { AutomaticSave } from "./automatic_save"; import { MetaHubBuilding } from "./buildings/hub"; import { Camera } from "./camera"; +import { DynamicTickrate } from "./dynamic_tickrate"; import { EntityManager } from "./entity_manager"; import { GameSystemManager } from "./game_system_manager"; import { HubGoals } from "./hub_goals"; @@ -23,14 +24,13 @@ import { GameHUD } from "./hud/hud"; import { KeyActionMapper } from "./key_action_mapper"; import { GameLogic } from "./logic"; import { MapView } from "./map_view"; -import { GameRoot, enumLayer } from "./root"; +import { defaultBuildingVariant } from "./meta_building"; +import { ProductionAnalytics } from "./production_analytics"; +import { GameRoot } from "./root"; import { ShapeDefinitionManager } from "./shape_definition_manager"; import { SoundProxy } from "./sound_proxy"; import { GameTime } from "./time/game_time"; -import { ProductionAnalytics } from "./production_analytics"; -import { randomInt } from "../core/utils"; -import { defaultBuildingVariant } from "./meta_building"; -import { DynamicTickrate } from "./dynamic_tickrate"; +import { ORIGINAL_SPRITE_SCALE } from "../core/sprites"; const logger = createLogger("ingame/core"); @@ -66,7 +66,7 @@ export class GameCore { /** * Initializes the root object which stores all game related data. The state * is required as a back reference (used sometimes) - * @param {InGameState} parentState + * @param {import("../states/ingame").InGameState} parentState * @param {Savegame} savegame */ initializeRoot(parentState, savegame) { @@ -232,10 +232,6 @@ export class GameCore { tick(deltaMs) { const root = this.root; - if (root.hud.parts.processingOverlay.hasTasks() || root.hud.parts.processingOverlay.isRunning()) { - return true; - } - // Extract current real time root.time.updateRealtimeNow(); @@ -325,14 +321,6 @@ export class GameCore { const root = this.root; const systems = root.systemMgr.systems; - const taskRunner = root.hud.parts.processingOverlay; - if (taskRunner.hasTasks()) { - if (!taskRunner.isRunning()) { - taskRunner.process(); - } - return; - } - this.root.dynamicTickrate.onFrameRendered(); if (!this.shouldRender()) { @@ -349,24 +337,22 @@ export class GameCore { // Gather context and save all state const context = root.context; context.save(); - if (G_IS_DEV && globalConfig.debug.testClipping) { - context.clearRect(0, 0, window.innerWidth * 3, window.innerHeight * 3); + if (G_IS_DEV) { + context.fillStyle = "#a10000"; + context.fillRect(0, 0, window.innerWidth * 3, window.innerHeight * 3); } // Compute optimal zoom level and atlas scale const zoomLevel = root.camera.zoomLevel; + const lowQuality = root.app.settings.getAllSettings().lowQualityTextures; const effectiveZoomLevel = (zoomLevel / globalConfig.assetsDpi) * getDeviceDPI() * globalConfig.assetsSharpness; - let desiredAtlasScale = "0.1"; - if (effectiveZoomLevel > 0.75) { - desiredAtlasScale = "1"; - } else if (effectiveZoomLevel > 0.5) { - desiredAtlasScale = "0.75"; - } else if (effectiveZoomLevel > 0.25) { + let desiredAtlasScale = "0.25"; + if (effectiveZoomLevel > 0.8 && !lowQuality) { + desiredAtlasScale = ORIGINAL_SPRITE_SCALE; + } else if (effectiveZoomLevel > 0.4 && !lowQuality) { desiredAtlasScale = "0.5"; - } else if (effectiveZoomLevel > 0.1) { - desiredAtlasScale = "0.25"; } // Construct parameters required for drawing @@ -378,11 +364,18 @@ export class GameCore { root: root, }); - if (G_IS_DEV && (globalConfig.debug.testCulling || globalConfig.debug.hideFog)) { + if (G_IS_DEV && globalConfig.debug.testCulling) { context.clearRect(0, 0, root.gameWidth, root.gameHeight); } // Transform to world space + + if (G_IS_DEV && globalConfig.debug.testClipping) { + params.visibleRect = params.visibleRect.expandedInAllDirections( + -200 / this.root.camera.zoomLevel + ); + } + root.camera.transform(context); assert(context.globalAlpha === 1.0, "Global alpha not 1 on frame start"); @@ -393,54 +386,38 @@ export class GameCore { // Main rendering order // ----- - // BG / Map Resources / Belt Backgrounds - root.map.drawBackground(params); - - if (!this.root.camera.getIsMapOverlayActive()) { - // Underlays for splitters / balancers - systems.itemAcceptor.drawUnderlays(params, enumLayer.regular); + if (this.root.camera.getIsMapOverlayActive()) { + // Map overview + root.map.drawOverlay(params); + } else { + root.map.drawBackground(params); // Belt items - systems.belt.drawLayerBeltItems(params, enumLayer.regular); + systems.belt.drawBeltItems(params); // Items being ejected / accepted currently (animations) - systems.itemEjector.drawLayer(params, enumLayer.regular); - systems.itemAcceptor.drawLayer(params, enumLayer.regular); - } + systems.itemEjector.draw(params); + systems.itemAcceptor.draw(params); - // Miner & Static map entities - root.map.drawForeground(params); + // Miner & Static map entities + root.map.drawForeground(params); - if (!this.root.camera.getIsMapOverlayActive()) { // HUB Overlay systems.hub.draw(params); - // Energy generator overlay - systems.energyGenerator.draw(params); - // Storage items systems.storage.draw(params); - // Energy consumer (Battery icons) - systems.energyConsumer.draw(params); - } + // Green wires overlay + root.hud.parts.wiresOverlay.draw(params); - // Green wires overlay (not within the if because it can fade) - root.hud.parts.wiresOverlay.draw(params); + if (this.root.currentLayer === "wires") { + // Static map entities + root.map.drawWiresForegroundLayer(params); - if (this.root.currentLayer === enumLayer.wires && !this.root.camera.getIsMapOverlayActive()) { - // Belt sprites & Static map entities - root.map.drawWiresLayer(params); - - // Belt items as well as accepted / ejected items - systems.belt.drawLayerBeltItems(params, enumLayer.wires); - systems.itemEjector.drawLayer(params, enumLayer.wires); - systems.itemAcceptor.drawLayer(params, enumLayer.wires); - - root.map.drawWiresForegroundLayer(params); - - // pins - systems.wiredPins.draw(params); + // pins + systems.wiredPins.draw(params); + } } if (G_IS_DEV) { @@ -462,6 +439,14 @@ export class GameCore { // Restore to screen space context.restore(); + // Restore parameters + params.zoomLevel = 1; + params.desiredAtlasScale = ORIGINAL_SPRITE_SCALE; + params.visibleRect = new Rectangle(0, 0, this.root.gameWidth, this.root.gameHeight); + if (G_IS_DEV && globalConfig.debug.testClipping) { + params.visibleRect = params.visibleRect.expandedInAllDirections(-200); + } + // Draw overlays, those are screen space root.hud.drawOverlays(params); @@ -476,5 +461,28 @@ export class GameCore { console.log(sum); } } + + if (G_IS_DEV && globalConfig.debug.showAtlasInfo) { + context.font = "13px GameFont"; + context.fillStyle = "yellow"; + context.fillText( + "Atlas: " + + desiredAtlasScale + + " / Zoom: " + + round2Digits(zoomLevel) + + " / Effective Zoom: " + + round2Digits(effectiveZoomLevel), + 200, + 20 + ); + } + + if (G_IS_DEV && globalConfig.debug.testClipping) { + context.strokeStyle = "red"; + context.lineWidth = 1; + context.beginPath(); + context.rect(200, 200, this.root.gameWidth - 400, this.root.gameHeight - 400); + context.stroke(); + } } } diff --git a/src/js/game/dynamic_tickrate.js b/src/js/game/dynamic_tickrate.js index f289e2c1..a5033acf 100644 --- a/src/js/game/dynamic_tickrate.js +++ b/src/js/game/dynamic_tickrate.js @@ -1,7 +1,6 @@ import { GameRoot } from "./root"; import { createLogger } from "../core/logging"; import { globalConfig } from "../core/config"; -import { round3Digits } from "../core/utils"; const logger = createLogger("dynamic_tickrate"); diff --git a/src/js/game/entity.js b/src/js/game/entity.js index c86aa3b7..ca21a16d 100644 --- a/src/js/game/entity.js +++ b/src/js/game/entity.js @@ -3,7 +3,7 @@ import { DrawParameters } from "../core/draw_parameters"; import { Component } from "./component"; /* typehints:end */ -import { GameRoot, enumLayer } from "./root"; +import { GameRoot } from "./root"; import { globalConfig } from "../core/config"; import { enumDirectionToVector, enumDirectionToAngle } from "../core/vector"; import { BasicSerializableObject, types } from "../savegame/serialization"; @@ -36,8 +36,9 @@ export class Entity extends BasicSerializableObject { /** * On which layer this entity is + * @type {Layer} */ - this.layer = enumLayer.regular; + this.layer = "regular"; /** * Internal entity unique id, set by the @see EntityManager @@ -76,8 +77,7 @@ export class Entity extends BasicSerializableObject { static getSchema() { return { uid: types.uint, - components: types.keyValueMap(types.objData(gComponentRegistry)), - layer: types.enum(enumLayer), + components: types.keyValueMap(types.objData(gComponentRegistry), false), }; } @@ -162,6 +162,7 @@ export class Entity extends BasicSerializableObject { context.stroke(); } } + if (G_IS_DEV && staticComp && globalConfig.debug.showAcceptorEjectors) { const ejectorComp = this.components.ItemEjector; @@ -169,9 +170,6 @@ export class Entity extends BasicSerializableObject { const ejectorSprite = Loader.getSprite("sprites/debug/ejector_slot.png"); for (let i = 0; i < ejectorComp.slots.length; ++i) { const slot = ejectorComp.slots[i]; - if (slot.layer !== this.root.currentLayer) { - continue; - } const slotTile = staticComp.localTileToWorld(slot.pos); const direction = staticComp.localDirectionToWorld(slot.direction); const directionVector = enumDirectionToVector[direction]; @@ -191,12 +189,9 @@ export class Entity extends BasicSerializableObject { const acceptorComp = this.components.ItemAcceptor; if (acceptorComp) { - const acceptorSprite = Loader.getSprite("sprites/debug/acceptor_slot.png"); + const acceptorSprite = Loader.getSprite("sprites/misc/acceptor_slot.png"); for (let i = 0; i < acceptorComp.slots.length; ++i) { const slot = acceptorComp.slots[i]; - if (slot.layer !== this.root.currentLayer) { - continue; - } const slotTile = staticComp.localTileToWorld(slot.pos); for (let k = 0; k < slot.directions.length; ++k) { const direction = staticComp.localDirectionToWorld(slot.directions[k]); diff --git a/src/js/game/entity_components.js b/src/js/game/entity_components.js index 24430dd2..8d8b56c4 100644 --- a/src/js/game/entity_components.js +++ b/src/js/game/entity_components.js @@ -1,18 +1,21 @@ /* typehints:start */ -import { StaticMapEntityComponent } from "./components/static_map_entity"; import { BeltComponent } from "./components/belt"; -import { ItemEjectorComponent } from "./components/item_ejector"; -import { ItemAcceptorComponent } from "./components/item_acceptor"; -import { MinerComponent } from "./components/miner"; -import { ItemProcessorComponent } from "./components/item_processor"; -import { ReplaceableMapEntityComponent } from "./components/replaceable_map_entity"; -import { UndergroundBeltComponent } from "./components/underground_belt"; -import { UnremovableComponent } from "./components/unremovable"; +import { BeltUnderlaysComponent } from "./components/belt_underlays"; import { HubComponent } from "./components/hub"; +import { ItemAcceptorComponent } from "./components/item_acceptor"; +import { ItemEjectorComponent } from "./components/item_ejector"; +import { ItemProcessorComponent } from "./components/item_processor"; +import { MinerComponent } from "./components/miner"; +import { StaticMapEntityComponent } from "./components/static_map_entity"; import { StorageComponent } from "./components/storage"; -import { EnergyGeneratorComponent } from "./components/energy_generator"; +import { UndergroundBeltComponent } from "./components/underground_belt"; import { WiredPinsComponent } from "./components/wired_pins"; -import { EnergyConsumerComponent } from "./components/energy_consumer"; +import { WireComponent } from "./components/wire"; +import { ConstantSignalComponent } from "./components/constant_signal"; +import { LogicGateComponent } from "./components/logic_gate"; +import { LeverComponent } from "./components/lever"; +import { WireTunnelComponent } from "./components/wire_tunnel"; +import { DisplayComponent } from "./components/display"; /* typehints:end */ /** @@ -41,29 +44,38 @@ export class EntityComponentStorage { /** @type {ItemProcessorComponent} */ this.ItemProcessor; - /** @type {ReplaceableMapEntityComponent} */ - this.ReplaceableMapEntity; - /** @type {UndergroundBeltComponent} */ this.UndergroundBelt; - /** @type {UnremovableComponent} */ - this.Unremovable; - /** @type {HubComponent} */ this.Hub; /** @type {StorageComponent} */ this.Storage; - /** @type {EnergyGeneratorComponent} */ - this.EnergyGenerator; - /** @type {WiredPinsComponent} */ this.WiredPins; - /** @type {EnergyConsumerComponent} */ - this.EnergyConsumer; + /** @type {BeltUnderlaysComponent} */ + this.BeltUnderlays; + + /** @type {WireComponent} */ + this.Wire; + + /** @type {ConstantSignalComponent} */ + this.ConstantSignal; + + /** @type {LogicGateComponent} */ + this.LogicGate; + + /** @type {LeverComponent} */ + this.Lever; + + /** @type {WireTunnelComponent} */ + this.WireTunnel; + + /** @type {DisplayComponent} */ + this.Display; /* typehints:end */ } diff --git a/src/js/game/game_system_manager.js b/src/js/game/game_system_manager.js index ed9d1155..afcaf194 100644 --- a/src/js/game/game_system_manager.js +++ b/src/js/game/game_system_manager.js @@ -13,9 +13,13 @@ import { HubSystem } from "./systems/hub"; import { StaticMapEntitySystem } from "./systems/static_map_entity"; import { ItemAcceptorSystem } from "./systems/item_acceptor"; import { StorageSystem } from "./systems/storage"; -import { EnergyGeneratorSystem } from "./systems/energy_generator"; import { WiredPinsSystem } from "./systems/wired_pins"; -import { EnergyConsumerSystem } from "./systems/energy_consumer"; +import { BeltUnderlaysSystem } from "./systems/belt_underlays"; +import { WireSystem } from "./systems/wire"; +import { ConstantSignalSystem } from "./systems/constant_signal"; +import { LogicGateSystem } from "./systems/logic_gate"; +import { LeverSystem } from "./systems/lever"; +import { DisplaySystem } from "./systems/display"; const logger = createLogger("game_system_manager"); @@ -59,14 +63,26 @@ export class GameSystemManager { /** @type {StorageSystem} */ storage: null, - /** @type {EnergyGeneratorSystem} */ - energyGenerator: null, - /** @type {WiredPinsSystem} */ wiredPins: null, - /** @type {EnergyConsumerSystem} */ - energyConsumer: null, + /** @type {BeltUnderlaysSystem} */ + beltUnderlays: null, + + /** @type {WireSystem} */ + wire: null, + + /** @type {ConstantSignalSystem} */ + constantSignal: null, + + /** @type {LogicGateSystem} */ + logicGate: null, + + /** @type {LeverSystem} */ + lever: null, + + /** @type {DisplaySystem} */ + display: null, /* typehints:end */ }; @@ -102,19 +118,31 @@ export class GameSystemManager { add("hub", HubSystem); - add("energyGenerator", EnergyGeneratorSystem); - add("staticMapEntities", StaticMapEntitySystem); add("wiredPins", WiredPinsSystem); - add("energyConsumer", EnergyConsumerSystem); + add("beltUnderlays", BeltUnderlaysSystem); + + add("constantSignal", ConstantSignalSystem); // IMPORTANT: Must be after belt system since belt system can change the // orientation of an entity after it is placed -> the item acceptor cache // then would be invalid add("itemAcceptor", ItemAcceptorSystem); + // WIRES section + add("lever", LeverSystem); + + // IMPORTANT: We have 2 phases: In phase 1 we compute the output values of all gates, + // processors etc. In phase 2 we propagate it through the wires network + add("logicGate", LogicGateSystem); + + // Wires must be after all gate, signal etc logic! + add("wire", WireSystem); + + add("display", DisplaySystem); + logger.log("📦 There are", this.systemUpdateOrder.length, "game systems"); } diff --git a/src/js/game/game_system_with_filter.js b/src/js/game/game_system_with_filter.js index 82ab4c22..ef6dfd52 100644 --- a/src/js/game/game_system_with_filter.js +++ b/src/js/game/game_system_with_filter.js @@ -3,7 +3,7 @@ import { Component } from "./component"; import { Entity } from "./entity"; /* typehints:end */ -import { GameRoot, enumLayer } from "./root"; +import { GameRoot } from "./root"; import { GameSystem } from "./game_system"; import { arrayDelete, arrayDeleteValue } from "../core/utils"; import { DrawParameters } from "../core/draw_parameters"; @@ -39,9 +39,8 @@ export class GameSystemWithFilter extends GameSystem { * Calls a function for each matching entity on the screen, useful for drawing them * @param {DrawParameters} parameters * @param {function} callback - * @param {enumLayer=} layerFilter Can be null for no filter */ - forEachMatchingEntityOnScreen(parameters, callback, layerFilter = null) { + forEachMatchingEntityOnScreen(parameters, callback) { const cullRange = parameters.visibleRect.toTileCullRectangle(); if (this.allEntities.length < 100) { // So, its much quicker to simply perform per-entity checking @@ -49,9 +48,7 @@ export class GameSystemWithFilter extends GameSystem { for (let i = 0; i < this.allEntities.length; ++i) { const entity = this.allEntities[i]; if (cullRange.containsRect(entity.components.StaticMapEntity.getTileSpaceBounds())) { - if (!layerFilter || entity.layer === layerFilter) { - callback(parameters, entity); - } + callback(parameters, entity); } } return; @@ -94,11 +91,6 @@ export class GameSystemWithFilter extends GameSystem { entityLoop: for (let i = 0; i < entities.length; ++i) { const entity = entities[i]; - // Avoid drawing non-layer contents - if (layerFilter && entity.layer !== layerFilter) { - continue; - } - // Avoid drawing twice if (seenUids.has(entity.uid)) { continue; diff --git a/src/js/game/hub_goals.js b/src/js/game/hub_goals.js index 36f8f107..8adee905 100644 --- a/src/js/game/hub_goals.js +++ b/src/js/game/hub_goals.js @@ -1,13 +1,12 @@ import { globalConfig } from "../core/config"; -import { queryParamOptions } from "../core/query_parameters"; import { clamp, findNiceIntegerValue, randomChoice, randomInt } from "../core/utils"; import { BasicSerializableObject, types } from "../savegame/serialization"; import { enumColors } from "./colors"; import { enumItemProcessorTypes } from "./components/item_processor"; -import { GameRoot, enumLayer } from "./root"; +import { GameRoot } from "./root"; import { enumSubShape, ShapeDefinition } from "./shape_definition"; import { enumHubGoalRewards, tutorialGoals } from "./tutorial_goals"; -import { UPGRADES, blueprintShape } from "./upgrades"; +import { UPGRADES } from "./upgrades"; export class HubGoals extends BasicSerializableObject { static getId() { @@ -328,9 +327,7 @@ export class HubGoals extends BasicSerializableObject { /** @type {Array} */ let layers = []; - // @ts-ignore const randomColor = () => randomChoice(Object.values(enumColors)); - // @ts-ignore const randomShape = () => randomChoice(Object.values(enumSubShape)); let anyIsMissingTwo = false; @@ -370,13 +367,9 @@ export class HubGoals extends BasicSerializableObject { /** * Belt speed - * @param {enumLayer} layer * @returns {number} items / sec */ - getBeltBaseSpeed(layer) { - if (layer === enumLayer.wires) { - return globalConfig.wiresSpeedItemsPerSecond; - } + getBeltBaseSpeed() { return globalConfig.beltSpeedItemsPerSecond * this.upgradeImprovements.belt; } @@ -411,6 +404,8 @@ export class HubGoals extends BasicSerializableObject { return 1e30; case enumItemProcessorTypes.splitter: return globalConfig.beltSpeedItemsPerSecond * this.upgradeImprovements.belt * 2; + case enumItemProcessorTypes.filter: + return globalConfig.beltSpeedItemsPerSecond * this.upgradeImprovements.belt; case enumItemProcessorTypes.mixer: case enumItemProcessorTypes.painter: @@ -443,9 +438,6 @@ export class HubGoals extends BasicSerializableObject { globalConfig.buildingSpeeds[processorType] ); } - case enumItemProcessorTypes.advancedProcessor: { - return globalConfig.beltSpeedItemsPerSecond * globalConfig.buildingSpeeds[processorType]; - } default: assertAlways(false, "invalid processor type: " + processorType); } diff --git a/src/js/game/hud/hud.js b/src/js/game/hud/hud.js index 1d72deb5..c1aa146e 100644 --- a/src/js/game/hud/hud.js +++ b/src/js/game/hud/hud.js @@ -8,7 +8,6 @@ import { TrailerMaker } from "./trailer_maker"; import { Signal } from "../../core/signal"; import { DrawParameters } from "../../core/draw_parameters"; -import { HUDProcessingOverlay } from "./parts/processing_overlay"; import { HUDBuildingsToolbar } from "./parts/buildings_toolbar"; import { HUDBuildingPlacer } from "./parts/building_placer"; import { HUDBlueprintPlacer } from "./parts/blueprint_placer"; @@ -41,6 +40,9 @@ import { HUDChangesDebugger } from "./parts/debug_changes"; import { queryParamOptions } from "../../core/query_parameters"; import { HUDSandboxController } from "./parts/sandbox_controller"; import { HUDWiresToolbar } from "./parts/wires_toolbar"; +import { HUDWireInfo } from "./parts/wire_info"; +import { HUDLeverToggle } from "./parts/lever_toggle"; +import { HUDLayerPreview } from "./parts/layer_preview"; export class GameHUD { /** @@ -55,7 +57,6 @@ export class GameHUD { */ initialize() { this.parts = { - processingOverlay: new HUDProcessingOverlay(this.root), buildingsToolbar: new HUDBuildingsToolbar(this.root), wiresToolbar: new HUDWiresToolbar(this.root), blueprintPlacer: new HUDBlueprintPlacer(this.root), @@ -66,6 +67,8 @@ export class GameHUD { shop: new HUDShop(this.root), statistics: new HUDStatistics(this.root), waypoints: new HUDWaypoints(this.root), + wireInfo: new HUDWireInfo(this.root), + leverToggle: new HUDLeverToggle(this.root), // Must always exist pinnedShapes: new HUDPinnedShapes(this.root), @@ -78,6 +81,7 @@ export class GameHUD { shapeViewer: new HUDShapeViewer(this.root), wiresOverlay: new HUDWiresOverlay(this.root), + layerPreview: new HUDLayerPreview(this.root), // Typing hints /* typehints:start */ @@ -230,7 +234,6 @@ export class GameHUD { */ draw(parameters) { const partsOrder = [ - "waypoints", "massSelector", "buildingPlacer", "blueprintPlacer", @@ -250,7 +253,7 @@ export class GameHUD { * @param {DrawParameters} parameters */ drawOverlays(parameters) { - const partsOrder = ["watermark"]; + const partsOrder = ["waypoints", "watermark", "wireInfo"]; for (let i = 0; i < partsOrder.length; ++i) { if (this.parts[partsOrder[i]]) { diff --git a/src/js/game/hud/parts/blueprint_placer.js b/src/js/game/hud/parts/blueprint_placer.js index 38341395..47bf1363 100644 --- a/src/js/game/hud/parts/blueprint_placer.js +++ b/src/js/game/hud/parts/blueprint_placer.js @@ -11,7 +11,6 @@ import { BaseHUDPart } from "../base_hud_part"; import { DynamicDomAttach } from "../dynamic_dom_attach"; import { Blueprint } from "../../blueprint"; import { SOUNDS } from "../../../platform/sound"; -import { enumLayer } from "../../root"; export class HUDBlueprintPlacer extends BaseHUDPart { createElements(parent) { @@ -60,7 +59,7 @@ export class HUDBlueprintPlacer extends BaseHUDPart { /** * Called when the layer was changed - * @param {enumLayer} layer + * @param {Layer} layer */ onEditModeChanged(layer) { // Check if the layer of the blueprint differs and thus we have to deselect it diff --git a/src/js/game/hud/parts/building_placer.js b/src/js/game/hud/parts/building_placer.js index d5770d0a..013fcde4 100644 --- a/src/js/game/hud/parts/building_placer.js +++ b/src/js/game/hud/parts/building_placer.js @@ -1,7 +1,7 @@ import { ClickDetector } from "../../../core/click_detector"; -import { globalConfig, THIRDPARTY_URLS } from "../../../core/config"; +import { globalConfig } from "../../../core/config"; import { DrawParameters } from "../../../core/draw_parameters"; -import { drawRotatedSprite, rotateTrapezRightFaced } from "../../../core/draw_utils"; +import { drawRotatedSprite } from "../../../core/draw_utils"; import { Loader } from "../../../core/loader"; import { clamp, makeDiv, removeAllChildren } from "../../../core/utils"; import { @@ -9,6 +9,7 @@ import { enumDirectionToVector, enumInvertedDirections, Vector, + enumDirection, } from "../../../core/vector"; import { T } from "../../../translations"; import { KEYMAPPINGS } from "../../key_action_mapper"; @@ -17,7 +18,7 @@ import { THEME } from "../../theme"; import { DynamicDomAttach } from "../dynamic_dom_attach"; import { HUDBuildingPlacerLogic } from "./building_placer_logic"; import { makeOffscreenBuffer } from "../../../core/buffer_utils"; -import { enumLayer } from "../../root"; +import { layers } from "../../root"; import { getCodeFromBuildingData } from "../../building_codes"; export class HUDBuildingPlacer extends HUDBuildingPlacerLogic { @@ -60,9 +61,9 @@ export class HUDBuildingPlacer extends HUDBuildingPlacerLogic { this.currentInterpolatedCornerTile = new Vector(); this.lockIndicatorSprites = {}; - for (const layerId in enumLayer) { - this.lockIndicatorSprites[layerId] = this.makeLockIndicatorSprite(layerId); - } + layers.forEach(layer => { + this.lockIndicatorSprites[layer] = this.makeLockIndicatorSprite(layer); + }); // @@ -75,7 +76,7 @@ export class HUDBuildingPlacer extends HUDBuildingPlacerLogic { /** * Makes the lock indicator sprite for the given layer - * @param {enumLayer} layer + * @param {Layer} layer */ makeLockIndicatorSprite(layer) { const dims = 48; @@ -246,6 +247,31 @@ export class HUDBuildingPlacer extends HUDBuildingPlacerLogic { } else { this.drawRegularPlacement(parameters); } + + if (metaBuilding.getShowWiresLayerPreview()) { + this.drawLayerPeek(parameters); + } + } + + /** + * + * @param {DrawParameters} parameters + */ + drawLayerPeek(parameters) { + const mousePosition = this.root.app.mousePosition; + if (!mousePosition) { + // Not on screen + return; + } + + const worldPosition = this.root.camera.screenToWorld(mousePosition); + + // Draw peeker + this.root.hud.parts.layerPreview.renderPreview( + parameters, + worldPosition, + 1 / this.root.camera.zoomLevel + ); } /** @@ -311,7 +337,6 @@ export class HUDBuildingPlacer extends HUDBuildingPlacerLogic { const staticComp = this.fakeEntity.components.StaticMapEntity; staticComp.origin = mouseTile; staticComp.rotation = rotation; - staticComp.tileSize = metaBuilding.getDimensions(this.currentVariant.get()); metaBuilding.updateVariants(this.fakeEntity, rotationVariant, this.currentVariant.get()); staticComp.code = getCodeFromBuildingData( this.currentMetaBuilding.get(), @@ -323,7 +348,6 @@ export class HUDBuildingPlacer extends HUDBuildingPlacerLogic { // Fade in / out parameters.context.lineWidth = 1; - // parameters.context.globalAlpha = 0.3 + pulseAnimation(this.root.time.realtimeNow(), 0.9) * 0.7; // Determine the bounds and visualize them const entityBounds = staticComp.getTileSpaceBounds(); @@ -428,6 +452,7 @@ export class HUDBuildingPlacer extends HUDBuildingPlacerLogic { const acceptorComp = this.fakeEntity.components.ItemAcceptor; const ejectorComp = this.fakeEntity.components.ItemEjector; const staticComp = this.fakeEntity.components.StaticMapEntity; + const beltComp = this.fakeEntity.components.Belt; const goodArrowSprite = Loader.getSprite("sprites/misc/slot_good_arrow.png"); const badArrowSprite = Loader.getSprite("sprites/misc/slot_bad_arrow.png"); @@ -436,132 +461,71 @@ export class HUDBuildingPlacer extends HUDBuildingPlacerLogic { const offsetShift = 10; - if (acceptorComp) { - const slots = acceptorComp.slots; - for (let acceptorSlotIndex = 0; acceptorSlotIndex < slots.length; ++acceptorSlotIndex) { - const slot = slots[acceptorSlotIndex]; - - // Only draw same layer slots - if (slot.layer !== this.root.currentLayer) { - continue; - } - - const acceptorSlotWsTile = staticComp.localTileToWorld(slot.pos); - const acceptorSlotWsPos = acceptorSlotWsTile.toWorldSpaceCenterOfTile(); - - // Go over all slots - for ( - let acceptorDirectionIndex = 0; - acceptorDirectionIndex < slot.directions.length; - ++acceptorDirectionIndex - ) { - const direction = slot.directions[acceptorDirectionIndex]; - const worldDirection = staticComp.localDirectionToWorld(direction); - - // Figure out which tile ejects to this slot - const sourceTile = acceptorSlotWsTile.add(enumDirectionToVector[worldDirection]); - - let isBlocked = false; - let isConnected = false; - - // Find all entities which are on that tile - const sourceEntities = this.root.map.getLayersContentsMultipleXY( - sourceTile.x, - sourceTile.y - ); - - // Check for every entity: - for (let i = 0; i < sourceEntities.length; ++i) { - const sourceEntity = sourceEntities[i]; - const sourceEjector = sourceEntity.components.ItemEjector; - const sourceStaticComp = sourceEntity.components.StaticMapEntity; - const ejectorAcceptLocalTile = sourceStaticComp.worldToLocalTile(acceptorSlotWsTile); - - // If this entity is on the same layer as the slot - if so, it can either be - // connected, or it can not be connected and thus block the input - if (sourceEntity.layer === slot.layer) { - if ( - sourceEjector && - sourceEjector.anySlotEjectsToLocalTile( - ejectorAcceptLocalTile, - this.root.currentLayer - ) - ) { - // This one is connected, all good - isConnected = true; - } else { - // This one is blocked - isBlocked = true; - } - } - } - - const alpha = isConnected || isBlocked ? 1.0 : 0.3; - const sprite = isBlocked ? badArrowSprite : goodArrowSprite; - - parameters.context.globalAlpha = alpha; - drawRotatedSprite({ - parameters, - sprite, - x: acceptorSlotWsPos.x, - y: acceptorSlotWsPos.y, - angle: Math.radians(enumDirectionToAngle[enumInvertedDirections[worldDirection]]), - size: 13, - offsetY: offsetShift + 13, - }); - parameters.context.globalAlpha = 1; - } - } - } + let acceptorSlots = []; + let ejectorSlots = []; if (ejectorComp) { - const slots = ejectorComp.slots; + ejectorSlots = ejectorComp.slots.slice(); + } + + if (acceptorComp) { + acceptorSlots = acceptorComp.slots.slice(); + } + + if (beltComp) { + const fakeEjectorSlot = beltComp.getFakeEjectorSlot(); + const fakeAcceptorSlot = beltComp.getFakeAcceptorSlot(); + ejectorSlots.push(fakeEjectorSlot); + acceptorSlots.push(fakeAcceptorSlot); + } + + for (let acceptorSlotIndex = 0; acceptorSlotIndex < acceptorSlots.length; ++acceptorSlotIndex) { + const slot = acceptorSlots[acceptorSlotIndex]; + + const acceptorSlotWsTile = staticComp.localTileToWorld(slot.pos); + const acceptorSlotWsPos = acceptorSlotWsTile.toWorldSpaceCenterOfTile(); // Go over all slots - for (let ejectorSlotIndex = 0; ejectorSlotIndex < slots.length; ++ejectorSlotIndex) { - const slot = slots[ejectorSlotIndex]; + for ( + let acceptorDirectionIndex = 0; + acceptorDirectionIndex < slot.directions.length; + ++acceptorDirectionIndex + ) { + const direction = slot.directions[acceptorDirectionIndex]; + const worldDirection = staticComp.localDirectionToWorld(direction); - // Only draw same layer slots - if (slot.layer !== this.root.currentLayer) { - continue; - } - - const ejectorSlotWsTile = staticComp.localTileToWorld( - ejectorComp.getSlotTargetLocalTile(ejectorSlotIndex) - ); - const ejectorSLotWsPos = ejectorSlotWsTile.toWorldSpaceCenterOfTile(); - const ejectorSlotWsDirection = staticComp.localDirectionToWorld(slot.direction); + // Figure out which tile ejects to this slot + const sourceTile = acceptorSlotWsTile.add(enumDirectionToVector[worldDirection]); let isBlocked = false; let isConnected = false; // Find all entities which are on that tile - const destEntities = this.root.map.getLayersContentsMultipleXY( - ejectorSlotWsTile.x, - ejectorSlotWsTile.y - ); + const sourceEntities = this.root.map.getLayersContentsMultipleXY(sourceTile.x, sourceTile.y); // Check for every entity: - for (let i = 0; i < destEntities.length; ++i) { - const destEntity = destEntities[i]; - const destAcceptor = destEntity.components.ItemAcceptor; - const destStaticComp = destEntity.components.StaticMapEntity; + for (let i = 0; i < sourceEntities.length; ++i) { + const sourceEntity = sourceEntities[i]; + const sourceEjector = sourceEntity.components.ItemEjector; + const sourceBeltComp = sourceEntity.components.Belt; + const sourceStaticComp = sourceEntity.components.StaticMapEntity; + const ejectorAcceptLocalTile = sourceStaticComp.worldToLocalTile(acceptorSlotWsTile); // If this entity is on the same layer as the slot - if so, it can either be // connected, or it can not be connected and thus block the input - if (destEntity.layer === slot.layer) { - const destLocalTile = destStaticComp.worldToLocalTile(ejectorSlotWsTile); - const destLocalDir = destStaticComp.worldDirectionToLocal(ejectorSlotWsDirection); - if ( - destAcceptor && - destAcceptor.findMatchingSlot(destLocalTile, destLocalDir, this.root.currentLayer) - ) { - // This one is connected, all good - isConnected = true; - } else { - // This one is blocked - isBlocked = true; - } + if (sourceEjector && sourceEjector.anySlotEjectsToLocalTile(ejectorAcceptLocalTile)) { + // This one is connected, all good + isConnected = true; + } else if ( + sourceBeltComp && + sourceStaticComp.localDirectionToWorld(sourceBeltComp.direction) === + enumInvertedDirections[worldDirection] + ) { + // Belt connected + isConnected = true; + } else { + // This one is blocked + isBlocked = true; } } @@ -572,14 +536,69 @@ export class HUDBuildingPlacer extends HUDBuildingPlacerLogic { drawRotatedSprite({ parameters, sprite, - x: ejectorSLotWsPos.x, - y: ejectorSLotWsPos.y, - angle: Math.radians(enumDirectionToAngle[ejectorSlotWsDirection]), + x: acceptorSlotWsPos.x, + y: acceptorSlotWsPos.y, + angle: Math.radians(enumDirectionToAngle[enumInvertedDirections[worldDirection]]), size: 13, - offsetY: offsetShift, + offsetY: offsetShift + 13, }); parameters.context.globalAlpha = 1; } } + + // Go over all slots + for (let ejectorSlotIndex = 0; ejectorSlotIndex < ejectorSlots.length; ++ejectorSlotIndex) { + const slot = ejectorSlots[ejectorSlotIndex]; + + const ejectorSlotLocalTile = slot.pos.add(enumDirectionToVector[slot.direction]); + const ejectorSlotWsTile = staticComp.localTileToWorld(ejectorSlotLocalTile); + + const ejectorSLotWsPos = ejectorSlotWsTile.toWorldSpaceCenterOfTile(); + const ejectorSlotWsDirection = staticComp.localDirectionToWorld(slot.direction); + + let isBlocked = false; + let isConnected = false; + + // Find all entities which are on that tile + const destEntities = this.root.map.getLayersContentsMultipleXY( + ejectorSlotWsTile.x, + ejectorSlotWsTile.y + ); + + // Check for every entity: + for (let i = 0; i < destEntities.length; ++i) { + const destEntity = destEntities[i]; + const destAcceptor = destEntity.components.ItemAcceptor; + const destStaticComp = destEntity.components.StaticMapEntity; + + const destLocalTile = destStaticComp.worldToLocalTile(ejectorSlotWsTile); + const destLocalDir = destStaticComp.worldDirectionToLocal(ejectorSlotWsDirection); + if (destAcceptor && destAcceptor.findMatchingSlot(destLocalTile, destLocalDir)) { + // This one is connected, all good + isConnected = true; + } else if (destEntity.components.Belt && destLocalDir === enumDirection.top) { + // Connected to a belt + isConnected = true; + } else { + // This one is blocked + isBlocked = true; + } + } + + const alpha = isConnected || isBlocked ? 1.0 : 0.3; + const sprite = isBlocked ? badArrowSprite : goodArrowSprite; + + parameters.context.globalAlpha = alpha; + drawRotatedSprite({ + parameters, + sprite, + x: ejectorSLotWsPos.x, + y: ejectorSLotWsPos.y, + angle: Math.radians(enumDirectionToAngle[ejectorSlotWsDirection]), + size: 13, + offsetY: offsetShift, + }); + parameters.context.globalAlpha = 1; + } } } diff --git a/src/js/game/hud/parts/building_placer_logic.js b/src/js/game/hud/parts/building_placer_logic.js index 97a635a6..898801c0 100644 --- a/src/js/game/hud/parts/building_placer_logic.js +++ b/src/js/game/hud/parts/building_placer_logic.js @@ -12,8 +12,8 @@ import { BaseHUDPart } from "../base_hud_part"; import { SOUNDS } from "../../../platform/sound"; import { MetaMinerBuilding, enumMinerVariants } from "../../buildings/miner"; import { enumHubGoalRewards } from "../../tutorial_goals"; -import { enumLayer } from "../../root"; import { getBuildingDataFromCode, getCodeFromBuildingData } from "../../building_codes"; +import { MetaHubBuilding } from "../../buildings/hub"; /** * Contains all logic for the building placer - this doesn't include the rendering @@ -132,12 +132,12 @@ export class HUDBuildingPlacerLogic extends BaseHUDPart { /** * Called when the edit mode got changed - * @param {enumLayer} editMode + * @param {Layer} layer */ - onEditModeChanged(editMode) { + onEditModeChanged(layer) { const metaBuilding = this.currentMetaBuilding.get(); if (metaBuilding) { - if (metaBuilding.getLayer() !== editMode) { + if (metaBuilding.getLayer() !== layer) { // This layer doesn't fit the edit mode anymore this.currentMetaBuilding.set(null); } @@ -289,7 +289,7 @@ export class HUDBuildingPlacerLogic extends BaseHUDPart { const mousePosition = this.root.app.mousePosition; if (!mousePosition) { // Not on screen - return; + return false; } const worldPos = this.root.camera.screenToWorld(mousePosition); @@ -298,8 +298,10 @@ export class HUDBuildingPlacerLogic extends BaseHUDPart { if (contents) { if (this.root.logic.tryDeleteBuilding(contents)) { this.root.soundProxy.playUi(SOUNDS.destroyBuilding); + return true; } } + return false; } /** @@ -342,6 +344,12 @@ export class HUDBuildingPlacerLogic extends BaseHUDPart { const buildingCode = contents.components.StaticMapEntity.code; const extracted = getBuildingDataFromCode(buildingCode); + // Disable pipetting the hub + if (extracted.metaInstance.getId() === gMetaBuildingRegistry.findByClass(MetaHubBuilding).getId()) { + this.currentMetaBuilding.set(null); + return; + } + // If the building we are picking is the same as the one we have, clear the cursor. if ( this.currentMetaBuilding.get() && @@ -637,8 +645,9 @@ export class HUDBuildingPlacerLogic extends BaseHUDPart { this.currentlyDragging = true; this.currentlyDeleting = true; this.lastDragTile = this.root.camera.screenToWorld(pos).toTileSpace(); - this.deleteBelowCursor(); - return STOP_PROPAGATION; + if (this.deleteBelowCursor()) { + return STOP_PROPAGATION; + } } // Cancel placement diff --git a/src/js/game/hud/parts/buildings_toolbar.js b/src/js/game/hud/parts/buildings_toolbar.js index c46a5c98..8c05ab70 100644 --- a/src/js/game/hud/parts/buildings_toolbar.js +++ b/src/js/game/hud/parts/buildings_toolbar.js @@ -1,6 +1,5 @@ import { MetaBeltBaseBuilding } from "../../buildings/belt_base"; import { MetaCutterBuilding } from "../../buildings/cutter"; -import { MetaEnergyGenerator } from "../../buildings/energy_generator"; import { MetaMinerBuilding } from "../../buildings/miner"; import { MetaMixerBuilding } from "../../buildings/mixer"; import { MetaPainterBuilding } from "../../buildings/painter"; @@ -9,9 +8,10 @@ import { MetaSplitterBuilding } from "../../buildings/splitter"; import { MetaStackerBuilding } from "../../buildings/stacker"; import { MetaTrashBuilding } from "../../buildings/trash"; import { MetaUndergroundBeltBuilding } from "../../buildings/underground_belt"; -import { enumLayer } from "../../root"; import { HUDBaseToolbar } from "./base_toolbar"; -import { MetaAdvancedProcessorBuilding } from "../../buildings/advanced_processor"; +import { MetaLeverBuilding } from "../../buildings/lever"; +import { MetaFilterBuilding } from "../../buildings/filter"; +import { MetaDisplayBuilding } from "../../buildings/display"; const supportedBuildings = [ MetaBeltBaseBuilding, @@ -24,9 +24,9 @@ const supportedBuildings = [ MetaMixerBuilding, MetaPainterBuilding, MetaTrashBuilding, - - MetaEnergyGenerator, - MetaAdvancedProcessorBuilding, + MetaLeverBuilding, + MetaFilterBuilding, + MetaDisplayBuilding, ]; export class HUDBuildingsToolbar extends HUDBaseToolbar { @@ -34,7 +34,7 @@ export class HUDBuildingsToolbar extends HUDBaseToolbar { super(root, { supportedBuildings, visibilityCondition: () => - !this.root.camera.getIsMapOverlayActive() && this.root.currentLayer === enumLayer.regular, + !this.root.camera.getIsMapOverlayActive() && this.root.currentLayer === "regular", htmlElementId: "ingame_HUD_buildings_toolbar", }); } diff --git a/src/js/game/hud/parts/color_blind_helper.js b/src/js/game/hud/parts/color_blind_helper.js index c7dd6288..e5572228 100644 --- a/src/js/game/hud/parts/color_blind_helper.js +++ b/src/js/game/hud/parts/color_blind_helper.js @@ -7,8 +7,6 @@ import { DrawParameters } from "../../../core/draw_parameters"; import { THEME } from "../../theme"; import { globalConfig } from "../../../core/config"; import { T } from "../../../translations"; -import { enumItemType } from "../../base_item"; -import { enumLayer } from "../../root"; export class HUDColorBlindHelper extends BaseHUDPart { createElements(parent) { @@ -41,7 +39,7 @@ export class HUDColorBlindHelper extends BaseHUDPart { return null; } - if (this.root.currentLayer !== enumLayer.regular) { + if (this.root.currentLayer !== "regular") { // Not in regular mode return null; } @@ -56,7 +54,7 @@ export class HUDColorBlindHelper extends BaseHUDPart { // Check if the belt has a color item if (beltComp) { const item = beltComp.assignedPath.findItemAtTile(tile); - if (item && item.getItemType() === enumItemType.color) { + if (item && item.getItemType() === "color") { return /** @type {ColorItem} */ (item).color; } } @@ -66,10 +64,7 @@ export class HUDColorBlindHelper extends BaseHUDPart { if (ejectorComp) { for (let i = 0; i < ejectorComp.slots.length; ++i) { const slot = ejectorComp.slots[i]; - if (slot.layer !== this.root.currentLayer) { - continue; - } - if (slot.item && slot.item.getItemType() === enumItemType.color) { + if (slot.item && slot.item.getItemType() === "color") { return /** @type {ColorItem} */ (slot.item).color; } } @@ -77,7 +72,7 @@ export class HUDColorBlindHelper extends BaseHUDPart { } else { // We hovered a lower layer, show the color there const lowerLayer = this.root.map.getLowerLayerContentXY(tile.x, tile.y); - if (lowerLayer && lowerLayer.getItemType() === enumItemType.color) { + if (lowerLayer && lowerLayer.getItemType() === "color") { return /** @type {ColorItem} */ (lowerLayer).color; } } diff --git a/src/js/game/hud/parts/debug_changes.js b/src/js/game/hud/parts/debug_changes.js index 1502afa2..88de84fe 100644 --- a/src/js/game/hud/parts/debug_changes.js +++ b/src/js/game/hud/parts/debug_changes.js @@ -57,7 +57,7 @@ export class HUDChangesDebugger extends BaseHUDPart { for (let i = 0; i < this.changes.length; ++i) { const change = this.changes[i]; parameters.context.fillStyle = change.fillColor; - parameters.context.globalAlpha = 0.5; + parameters.context.globalAlpha = 0.2; parameters.context.fillRect( change.area.x * globalConfig.tileSize, change.area.y * globalConfig.tileSize, diff --git a/src/js/game/hud/parts/game_menu.js b/src/js/game/hud/parts/game_menu.js index 64285624..2f820f7a 100644 --- a/src/js/game/hud/parts/game_menu.js +++ b/src/js/game/hud/parts/game_menu.js @@ -1,10 +1,9 @@ import { BaseHUDPart } from "../base_hud_part"; -import { makeDiv, randomInt } from "../../../core/utils"; +import { makeDiv } from "../../../core/utils"; import { SOUNDS } from "../../../platform/sound"; import { enumNotificationType } from "./notifications"; import { T } from "../../../translations"; import { KEYMAPPINGS } from "../../key_action_mapper"; -import { IS_DEMO } from "../../../core/config"; import { DynamicDomAttach } from "../dynamic_dom_attach"; export class HUDGameMenu extends BaseHUDPart { diff --git a/src/js/game/hud/parts/layer_preview.js b/src/js/game/hud/parts/layer_preview.js new file mode 100644 index 00000000..36e0ea58 --- /dev/null +++ b/src/js/game/hud/parts/layer_preview.js @@ -0,0 +1,123 @@ +import { freeCanvas, makeOffscreenBuffer } from "../../../core/buffer_utils"; +import { globalConfig } from "../../../core/config"; +import { Loader } from "../../../core/loader"; +import { Vector } from "../../../core/vector"; +import { MapChunkView } from "../../map_chunk_view"; +import { THEME } from "../../theme"; +import { BaseHUDPart } from "../base_hud_part"; + +/** + * Helper class which allows peaking through to the wires layer + */ +export class HUDLayerPreview extends BaseHUDPart { + initialize() { + this.initializeCanvas(); + this.root.signals.aboutToDestruct.add(() => freeCanvas(this.canvas)); + this.root.signals.resized.add(this.initializeCanvas, this); + this.previewOverlay = Loader.getSprite("sprites/wires/wires_preview.png"); + } + + /** + * (re) initializes the canvas + */ + initializeCanvas() { + if (this.canvas) { + freeCanvas(this.canvas); + delete this.canvas; + delete this.context; + } + + // Compute how big the preview should be + this.previewSize = Math.round( + Math.min(1024, Math.min(this.root.gameWidth, this.root.gameHeight) * 0.8) + ); + + const [canvas, context] = makeOffscreenBuffer(this.previewSize, this.previewSize, { + smooth: true, + label: "layerPeeker", + reusable: true, + }); + + context.clearRect(0, 0, this.previewSize, this.previewSize); + this.canvas = canvas; + this.context = context; + } + + /** + * Prepares the canvas to render at the given worldPos and the given camera scale + * + * @param {Vector} worldPos + * @param {number} scale 1 / zoomLevel + */ + prepareCanvasForPreview(worldPos, scale) { + this.context.clearRect(0, 0, this.previewSize, this.previewSize); + this.context.fillStyle = THEME.map.wires.previewColor; + this.context.fillRect(0, 0, this.previewSize, this.previewSize); + + const dimensions = scale * this.previewSize; + + const startWorldX = worldPos.x - dimensions / 2; + const startWorldY = worldPos.y - dimensions / 2; + + const startTileX = Math.floor(startWorldX / globalConfig.tileSize); + const startTileY = Math.floor(startWorldY / globalConfig.tileSize); + const tileDimensions = Math.ceil(dimensions / globalConfig.tileSize); + + this.context.save(); + this.context.scale(1 / scale, 1 / scale); + this.context.translate( + startTileX * globalConfig.tileSize - startWorldX, + startTileY * globalConfig.tileSize - startWorldY + ); + + for (let dx = 0; dx < tileDimensions; ++dx) { + for (let dy = 0; dy < tileDimensions; ++dy) { + const tileX = dx + startTileX; + const tileY = dy + startTileY; + + const content = this.root.map.getLayerContentXY(tileX, tileY, "wires"); + if (content) { + MapChunkView.drawSingleWiresOverviewTile({ + context: this.context, + x: dx * globalConfig.tileSize, + y: dy * globalConfig.tileSize, + entity: content, + tileSizePixels: globalConfig.tileSize, + }); + } + } + } + + this.context.restore(); + this.context.globalCompositeOperation = "destination-in"; + this.previewOverlay.draw(this.context, 0, 0, this.previewSize, this.previewSize); + this.context.globalCompositeOperation = "source-over"; + + return this.canvas; + } + + /** + * Renders the preview at the given position + * @param {import("../../../core/draw_utils").DrawParameters} parameters + * @param {Vector} worldPos + * @param {number} scale 1 / zoomLevel + */ + renderPreview(parameters, worldPos, scale) { + if (this.root.currentLayer !== "regular") { + // Only supporting wires right now + return; + } + + const canvas = this.prepareCanvasForPreview(worldPos, scale); + + parameters.context.globalAlpha = 0.3; + parameters.context.drawImage( + canvas, + worldPos.x - (scale * this.previewSize) / 2, + worldPos.y - (scale * this.previewSize) / 2, + scale * this.previewSize, + scale * this.previewSize + ); + parameters.context.globalAlpha = 1; + } +} diff --git a/src/js/game/hud/parts/lever_toggle.js b/src/js/game/hud/parts/lever_toggle.js new file mode 100644 index 00000000..1859f7ab --- /dev/null +++ b/src/js/game/hud/parts/lever_toggle.js @@ -0,0 +1,31 @@ +import { STOP_PROPAGATION } from "../../../core/signal"; +import { Vector } from "../../../core/vector"; +import { enumMouseButton } from "../../camera"; +import { BaseHUDPart } from "../base_hud_part"; + +export class HUDLeverToggle extends BaseHUDPart { + initialize() { + this.root.camera.downPreHandler.add(this.downPreHandler, this); + } + + /** + * @param {Vector} pos + * @param {enumMouseButton} button + */ + downPreHandler(pos, button) { + const tile = this.root.camera.screenToWorld(pos).toTileSpace(); + const contents = this.root.map.getLayerContentXY(tile.x, tile.y, "regular"); + if (contents) { + const leverComp = contents.components.Lever; + if (leverComp) { + if (button === enumMouseButton.left) { + leverComp.toggled = !leverComp.toggled; + return STOP_PROPAGATION; + } else if (button === enumMouseButton.right) { + this.root.logic.tryDeleteBuilding(contents); + return STOP_PROPAGATION; + } + } + } + } +} diff --git a/src/js/game/hud/parts/mass_selector.js b/src/js/game/hud/parts/mass_selector.js index 68d480e4..8d5c2e76 100644 --- a/src/js/game/hud/parts/mass_selector.js +++ b/src/js/game/hud/parts/mass_selector.js @@ -21,8 +21,6 @@ export class HUDMassSelector extends BaseHUDPart { createElements(parent) {} initialize() { - this.deletionMarker = Loader.getSprite("sprites/misc/deletion_marker.png"); - this.currentSelectionStartWorld = null; this.currentSelectionEnd = null; this.selectedUids = new Set(); diff --git a/src/js/game/hud/parts/pinned_shapes.js b/src/js/game/hud/parts/pinned_shapes.js index bda49f1e..2f7dd11e 100644 --- a/src/js/game/hud/parts/pinned_shapes.js +++ b/src/js/game/hud/parts/pinned_shapes.js @@ -1,5 +1,5 @@ import { ClickDetector } from "../../../core/click_detector"; -import { formatBigNumber, makeDiv, arrayDelete, arrayDeleteValue } from "../../../core/utils"; +import { formatBigNumber, makeDiv, arrayDeleteValue } from "../../../core/utils"; import { ShapeDefinition } from "../../shape_definition"; import { BaseHUDPart } from "../base_hud_part"; import { blueprintShape, UPGRADES } from "../../upgrades"; diff --git a/src/js/game/hud/parts/processing_overlay.js b/src/js/game/hud/parts/processing_overlay.js deleted file mode 100644 index 95383dfd..00000000 --- a/src/js/game/hud/parts/processing_overlay.js +++ /dev/null @@ -1,112 +0,0 @@ -import { DynamicDomAttach } from "../dynamic_dom_attach"; -import { BaseHUDPart } from "../base_hud_part"; -import { makeDiv } from "../../../core/utils"; -import { Signal } from "../../../core/signal"; -import { InputReceiver } from "../../../core/input_receiver"; -import { createLogger } from "../../../core/logging"; - -const logger = createLogger("hud/processing_overlay"); - -export class HUDProcessingOverlay extends BaseHUDPart { - constructor(root) { - super(root); - this.tasks = []; - this.computeTimeout = null; - - this.root.signals.performAsync.add(this.queueTask, this); - - this.allTasksFinished = new Signal(); - this.inputReceiver = new InputReceiver("processing-overlay"); - - this.root.signals.aboutToDestruct.add(() => - this.root.app.inputMgr.destroyReceiver(this.inputReceiver) - ); - } - - createElements(parent) { - this.element = makeDiv( - parent, - "rg_HUD_ProcessingOverlay", - ["hudElement"], - ` - - Computing - - ` - ); - } - - initialize() { - this.domWatcher = new DynamicDomAttach(this.root, this.element, { - timeToKeepSeconds: 0, - }); - } - - queueTask(task, name) { - if (!this.root.gameInitialized) { - // Tasks before the game started can be done directlry - task(); - return; - } - task.__name = name; - this.tasks.push(task); - } - - hasTasks() { - return this.tasks.length > 0; - } - - isRunning() { - return this.computeTimeout !== null; - } - - processSync() { - const now = performance.now(); - while (this.tasks.length > 0) { - const workload = this.tasks[0]; - workload.call(); - this.tasks.shift(); - } - const duration = performance.now() - now; - if (duration > 100) { - logger.log("Tasks done slow (SYNC!) within", (performance.now() - now).toFixed(2), "ms"); - } - } - - process() { - this.root.app.inputMgr.makeSureAttachedAndOnTop(this.inputReceiver); - - this.domWatcher.update(true); - if (this.tasks.length === 0) { - logger.warn("No tasks but still called process"); - return; - } - - if (this.computeTimeout) { - assert(false, "Double compute queued"); - clearTimeout(this.computeTimeout); - } - - this.computeTimeout = setTimeout(() => { - const now = performance.now(); - while (this.tasks.length > 0) { - const workload = this.tasks[0]; - workload.call(); - this.tasks.shift(); - } - const duration = performance.now() - now; - if (duration > 100) { - logger.log("Tasks done slow within", (performance.now() - now).toFixed(2), "ms"); - } - - this.domWatcher.update(false); - - this.root.app.inputMgr.makeSureDetached(this.inputReceiver); - - clearTimeout(this.computeTimeout); - this.computeTimeout = null; - - this.allTasksFinished.dispatch(); - }); - } -} diff --git a/src/js/game/hud/parts/screenshot_exporter.js b/src/js/game/hud/parts/screenshot_exporter.js index 19c644e9..a3310204 100644 --- a/src/js/game/hud/parts/screenshot_exporter.js +++ b/src/js/game/hud/parts/screenshot_exporter.js @@ -63,7 +63,7 @@ export class HUDScreenshotExporter extends BaseHUDPart { } logger.log("ChunkSizePixels:", chunkSizePixels); - const chunkScale = chunkSizePixels / (globalConfig.mapChunkSize * globalConfig.tileSize); + const chunkScale = chunkSizePixels / globalConfig.mapChunkWorldSize; logger.log("Scale:", chunkScale); logger.log("Allocating buffer, if the factory grew too big it will crash here"); @@ -79,10 +79,10 @@ export class HUDScreenshotExporter extends BaseHUDPart { logger.log("Got buffer, rendering now ..."); const visibleRect = new Rectangle( - minChunk.x * globalConfig.mapChunkSize * globalConfig.tileSize, - minChunk.y * globalConfig.mapChunkSize * globalConfig.tileSize, - dimensions.x * globalConfig.mapChunkSize * globalConfig.tileSize, - dimensions.y * globalConfig.mapChunkSize * globalConfig.tileSize + minChunk.x * globalConfig.mapChunkWorldSize, + minChunk.y * globalConfig.mapChunkWorldSize, + dimensions.x * globalConfig.mapChunkWorldSize, + dimensions.y * globalConfig.mapChunkWorldSize ); const parameters = new DrawParameters({ context, diff --git a/src/js/game/hud/parts/settings_menu.js b/src/js/game/hud/parts/settings_menu.js index 6034ab9d..391fde01 100644 --- a/src/js/game/hud/parts/settings_menu.js +++ b/src/js/game/hud/parts/settings_menu.js @@ -1,13 +1,11 @@ import { BaseHUDPart } from "../base_hud_part"; -import { makeDiv, formatSeconds, formatBigNumberFull } from "../../../core/utils"; +import { makeDiv, formatBigNumberFull } from "../../../core/utils"; import { DynamicDomAttach } from "../dynamic_dom_attach"; import { InputReceiver } from "../../../core/input_receiver"; import { KeyActionMapper, KEYMAPPINGS } from "../../key_action_mapper"; import { T } from "../../../translations"; import { StaticMapEntityComponent } from "../../components/static_map_entity"; -import { ItemProcessorComponent } from "../../components/item_processor"; import { BeltComponent } from "../../components/belt"; -import { IS_DEMO } from "../../../core/config"; export class HUDSettingsMenu extends BaseHUDPart { createElements(parent) { @@ -57,16 +55,7 @@ export class HUDSettingsMenu extends BaseHUDPart { } returnToMenu() { - // if (IS_DEMO) { - // const { cancel, deleteGame } = this.root.hud.parts.dialogs.showWarning( - // T.dialogs.leaveNotPossibleInDemo.title, - // T.dialogs.leaveNotPossibleInDemo.desc, - // ["cancel:good", "deleteGame:bad"] - // ); - // deleteGame.add(() => this.root.gameState.goBackToMenu()); - // } else { this.root.gameState.goBackToMenu(); - // } } goToSettings() { @@ -102,7 +91,6 @@ export class HUDSettingsMenu extends BaseHUDPart { show() { this.visible = true; document.body.classList.add("ingameDialogOpen"); - // this.background.classList.add("visible"); this.root.app.inputMgr.makeSureAttachedAndOnTop(this.inputReciever); const totalMinutesPlayed = Math.ceil(this.root.time.now() / 60); diff --git a/src/js/game/hud/parts/statistics.js b/src/js/game/hud/parts/statistics.js index e1a747a2..e15af4fb 100644 --- a/src/js/game/hud/parts/statistics.js +++ b/src/js/game/hud/parts/statistics.js @@ -1,5 +1,5 @@ import { InputReceiver } from "../../../core/input_receiver"; -import { makeButton, makeDiv, removeAllChildren, capitalizeFirstLetter } from "../../../core/utils"; +import { makeButton, makeDiv, removeAllChildren } from "../../../core/utils"; import { KeyActionMapper, KEYMAPPINGS } from "../../key_action_mapper"; import { enumAnalyticsDataSource } from "../../production_analytics"; import { BaseHUDPart } from "../base_hud_part"; @@ -7,6 +7,14 @@ import { DynamicDomAttach } from "../dynamic_dom_attach"; import { enumDisplayMode, HUDShapeStatisticsHandle } from "./statistics_handle"; import { T } from "../../../translations"; +/** + * Capitalizes the first letter + * @param {string} str + */ +function capitalizeFirstLetter(str) { + return str.substr(0, 1).toUpperCase() + str.substr(1).toLowerCase(); +} + export class HUDStatistics extends BaseHUDPart { createElements(parent) { this.background = makeDiv(parent, "ingame_HUD_Statistics", ["ingameDialog"]); diff --git a/src/js/game/hud/parts/waypoints.js b/src/js/game/hud/parts/waypoints.js index 8cab85c5..abf05b1f 100644 --- a/src/js/game/hud/parts/waypoints.js +++ b/src/js/game/hud/parts/waypoints.js @@ -15,6 +15,8 @@ import { BaseHUDPart } from "../base_hud_part"; import { DynamicDomAttach } from "../dynamic_dom_attach"; import { enumNotificationType } from "./notifications"; import { ShapeDefinition } from "../../shape_definition"; +import { BaseItem } from "../../base_item"; +import { ShapeItem } from "../../items/shape_item"; /** @typedef {{ * label: string | null, @@ -25,8 +27,6 @@ import { ShapeDefinition } from "../../shape_definition"; /** * Used when a shape icon is rendered instead */ -const SHAPE_LABEL_PLACEHOLDER = " "; - const MAX_LABEL_LENGTH = 71; export class HUDWaypoints extends BaseHUDPart { @@ -133,10 +133,44 @@ export class HUDWaypoints extends BaseHUDPart { */ this.cachedKeyToCanvas = {}; + /** + * Store cached text widths + * @type {Object} + */ + this.cachedTextWidths = {}; + // Initial render this.rerenderWaypointList(); } + /** + * Returns how long a text will be rendered + * @param {string} text + * @returns {number} + */ + getTextWidth(text) { + if (this.cachedTextWidths[text]) { + return this.cachedTextWidths[text]; + } + + this.dummyBuffer.font = "bold " + this.getTextScale() + "px GameFont"; + return (this.cachedTextWidths[text] = this.dummyBuffer.measureText(text).width); + } + + /** + * Returns how big the text should be rendered + */ + getTextScale() { + return this.getWaypointUiScale() * 12; + } + + /** + * Returns the scale for rendering waypoints + */ + getWaypointUiScale() { + return this.root.app.getEffectiveUiScale(); + } + /** * Re-renders the waypoint list to account for changes */ @@ -214,7 +248,7 @@ export class HUDWaypoints extends BaseHUDPart { } assert(ShapeDefinition.isValidShortKey(key), "Invalid short key: " + key); - const definition = ShapeDefinition.fromShortKey(key); + const definition = this.root.shapeDefinitionMgr.getShapeFromShortKey(key); const preRendered = definition.generateAsCanvas(48); return (this.cachedKeyToCanvas[key] = preRendered); } @@ -367,6 +401,51 @@ export class HUDWaypoints extends BaseHUDPart { return waypoint.label !== null; } + /** + * Returns the screen space bounds of the given waypoint or null + * if it couldn't be determined. Also returns wheter its a shape or not + * @param {Waypoint} waypoint + * @return {{ + * screenBounds: Rectangle + * item: BaseItem|null, + * text: string + * }} + */ + getWaypointScreenParams(waypoint) { + if (!this.root.camera.getIsMapOverlayActive()) { + return null; + } + + // Find parameters + const scale = this.getWaypointUiScale(); + const screenPos = this.root.camera.worldToScreen(new Vector(waypoint.center.x, waypoint.center.y)); + + // Distinguish between text and item waypoints -> Figure out parameters + const originalLabel = this.getWaypointLabel(waypoint); + let text, item, textWidth; + + if (ShapeDefinition.isValidShortKey(originalLabel)) { + // If the label is actually a key, render the shape icon + item = this.root.shapeDefinitionMgr.getShapeItemFromShortKey(originalLabel); + textWidth = 40; + } else { + // Otherwise render a regular waypoint + text = originalLabel; + textWidth = this.getTextWidth(text); + } + + return { + screenBounds: new Rectangle( + screenPos.x - 7 * scale, + screenPos.y - 12 * scale, + 15 * scale + textWidth, + 15 * scale + ), + item, + text, + }; + } + /** * Finds the currently intersected waypoint on the map overview under * the cursor. @@ -379,34 +458,10 @@ export class HUDWaypoints extends BaseHUDPart { return; } - if (!this.root.camera.getIsMapOverlayActive()) { - return; - } - - const scale = this.root.app.getEffectiveUiScale(); - - this.dummyBuffer.font = "bold " + 12 * scale + "px GameFont"; - for (let i = 0; i < this.waypoints.length; ++i) { const waypoint = this.waypoints[i]; - const screenPos = this.root.camera.worldToScreen( - new Vector(waypoint.center.x, waypoint.center.y) - ); - - let label = this.getWaypointLabel(waypoint); - - // Special case for icons - if (ShapeDefinition.isValidShortKey(label)) { - label = SHAPE_LABEL_PLACEHOLDER; - } - - const intersectionRect = new Rectangle( - screenPos.x - 7 * scale, - screenPos.y - 12 * scale, - 15 * scale + this.dummyBuffer.measureText(label).width, - 15 * scale - ); - if (intersectionRect.containsPoint(mousePos.x, mousePos.y)) { + const params = this.getWaypointScreenParams(waypoint); + if (params && params.screenBounds.containsPoint(mousePos.x, mousePos.y)) { return waypoint; } } @@ -449,18 +504,21 @@ export class HUDWaypoints extends BaseHUDPart { * Rerenders the compass */ rerenderWaypointsCompass() { - const context = this.compassBuffer.context; const dims = 48; - context.clearRect(0, 0, dims, dims); const indicatorSize = 30; - const cameraPos = this.root.camera.center; + const context = this.compassBuffer.context; + context.clearRect(0, 0, dims, dims); + const distanceToHub = cameraPos.length(); const compassVisible = distanceToHub > (10 * globalConfig.tileSize) / this.root.camera.zoomLevel; const targetCompassAlpha = compassVisible ? 1 : 0; + + // Fade the compas in / out this.currentCompassOpacity = lerp(this.currentCompassOpacity, targetCompassAlpha, 0.08); + // Render the compass if (this.currentCompassOpacity > 0.01) { context.globalAlpha = this.currentCompassOpacity; const angle = cameraPos.angle() + Math.radians(45) + Math.PI / 2; @@ -472,9 +530,9 @@ export class HUDWaypoints extends BaseHUDPart { context.globalAlpha = 1; } + // Render the regualr icon const iconOpacity = 1 - this.currentCompassOpacity; if (iconOpacity > 0.01) { - // Draw icon context.globalAlpha = iconOpacity; this.waypointSprite.drawCentered(context, dims / 2, dims / 2, dims * 0.7); context.globalAlpha = 1; @@ -485,7 +543,8 @@ export class HUDWaypoints extends BaseHUDPart { * Draws the waypoints on the map * @param {DrawParameters} parameters */ - draw(parameters) { + drawOverlays(parameters) { + const mousePos = this.root.app.mousePosition; const desiredOpacity = this.root.camera.getIsMapOverlayActive() ? 1 : 0; this.currentMarkerOpacity = lerp(this.currentMarkerOpacity, desiredOpacity, 0.08); @@ -496,61 +555,73 @@ export class HUDWaypoints extends BaseHUDPart { return; } - // Find waypoint below cursor - const selected = this.findCurrentIntersectedWaypoint(); - // Determine rendering scale - const scale = (1 / this.root.camera.zoomLevel) * this.root.app.getEffectiveUiScale(); + const scale = this.getWaypointUiScale(); - // Render all of 'em + // Set the font size + const textSize = this.getTextScale(); + parameters.context.font = "bold " + textSize + "px GameFont"; + parameters.context.textBaseline = "middle"; + + // Loop over all waypoints for (let i = 0; i < this.waypoints.length; ++i) { const waypoint = this.waypoints[i]; - const pos = waypoint.center; - parameters.context.globalAlpha = this.currentMarkerOpacity * (selected === waypoint ? 1 : 0.7); - - const yOffset = -5 * scale; - const originalLabel = this.getWaypointLabel(waypoint); - let renderLabel = originalLabel; - let isShapeIcon = false; - - if (ShapeDefinition.isValidShortKey(originalLabel)) { - renderLabel = SHAPE_LABEL_PLACEHOLDER; - isShapeIcon = true; + const waypointData = this.getWaypointScreenParams(waypoint); + if (!waypointData) { + // Not relevant + continue; } + if (!parameters.visibleRect.containsRect(waypointData.screenBounds)) { + // Out of screen + continue; + } + + const bounds = waypointData.screenBounds; + const contentPaddingX = 7 * scale; + const isSelected = mousePos && bounds.containsPoint(mousePos.x, mousePos.y); + // Render the background rectangle - parameters.context.font = "bold " + 12 * scale + "px GameFont"; + parameters.context.globalAlpha = this.currentMarkerOpacity * (isSelected ? 1 : 0.7); parameters.context.fillStyle = "rgba(255, 255, 255, 0.7)"; - parameters.context.fillRect( - pos.x - 7 * scale, - pos.y - 12 * scale, - 15 * scale + this.dummyBuffer.measureText(renderLabel).width / this.root.camera.zoomLevel, - 15 * scale - ); + parameters.context.fillRect(bounds.x, bounds.y, bounds.w, bounds.h); // Render the text - if (isShapeIcon) { + if (waypointData.item) { const canvas = this.getWaypointCanvas(waypoint); + const itemSize = 14 * scale; parameters.context.drawImage( canvas, - pos.x + 6 * scale, - pos.y - 11.5 * scale, - 14 * scale, - 14 * scale + bounds.x + contentPaddingX + 6 * scale, + bounds.y + bounds.h / 2 - itemSize / 2, + itemSize, + itemSize ); - } else { + } else if (waypointData.text) { // Render the text parameters.context.fillStyle = "#000"; parameters.context.textBaseline = "middle"; - parameters.context.fillText(renderLabel, pos.x + 6 * scale, pos.y + 0.5 * scale + yOffset); + parameters.context.fillText( + waypointData.text, + bounds.x + contentPaddingX + 6 * scale, + bounds.y + bounds.h / 2 + ); parameters.context.textBaseline = "alphabetic"; + } else { + assertAlways(false, "Waypoint has no item and text"); } // Render the small icon on the left - this.waypointSprite.drawCentered(parameters.context, pos.x, pos.y + yOffset, 10 * scale); + this.waypointSprite.drawCentered( + parameters.context, + bounds.x + contentPaddingX, + bounds.y + bounds.h / 2, + bounds.h * 0.7 + ); } + parameters.context.textBaseline = "alphabetic"; parameters.context.globalAlpha = 1; } } diff --git a/src/js/game/hud/parts/wire_info.js b/src/js/game/hud/parts/wire_info.js new file mode 100644 index 00000000..f73d53d7 --- /dev/null +++ b/src/js/game/hud/parts/wire_info.js @@ -0,0 +1,114 @@ +import { globalConfig } from "../../../core/config"; +import { MapChunkView } from "../../map_chunk_view"; +import { WireNetwork } from "../../systems/wire"; +import { THEME } from "../../theme"; +import { BaseHUDPart } from "../base_hud_part"; +import { Loader } from "../../../core/loader"; + +export class HUDWireInfo extends BaseHUDPart { + initialize() { + this.spriteEmpty = Loader.getSprite("sprites/wires/network_empty.png"); + this.spriteConflict = Loader.getSprite("sprites/wires/network_conflict.png"); + } + + /** + * + * @param {import("../../../core/draw_utils").DrawParameters} parameters + */ + drawOverlays(parameters) { + if (this.root.currentLayer !== "wires") { + // Not in the wires layer + return; + } + + const mousePos = this.root.app.mousePosition; + if (!mousePos) { + // No mouse + return; + } + + const worldPos = this.root.camera.screenToWorld(mousePos); + const tile = worldPos.toTileSpace(); + const entity = this.root.map.getLayerContentXY(tile.x, tile.y, "wires"); + + if (!entity) { + // No entity + return; + } + + if ( + !this.root.camera.getIsMapOverlayActive() && + !this.root.logic.getIsEntityIntersectedWithMatrix(entity, worldPos) + ) { + // Detailed intersection check + return; + } + + const networks = this.root.logic.getEntityWireNetworks(entity, tile); + if (networks === null) { + // This entity will never be able to be connected + return; + } + + if (networks.length === 0) { + // No network at all + return; + } + + for (let i = 0; i < networks.length; ++i) { + const network = networks[i]; + this.drawHighlightedNetwork(parameters, network); + } + + if (networks.length === 1) { + const network = networks[0]; + + if (network.valueConflict) { + this.spriteConflict.draw(parameters.context, mousePos.x + 10, mousePos.y - 10, 40, 40); + } else if (!network.currentValue) { + this.spriteEmpty.draw(parameters.context, mousePos.x + 10, mousePos.y - 10, 40, 40); + } else { + network.currentValue.drawCentered(mousePos.x + 20, mousePos.y, parameters, 40); + } + } + } + + /** + * + * + * @param {import("../../../core/draw_utils").DrawParameters} parameters + * @param {WireNetwork} network + */ + drawHighlightedNetwork(parameters, network) { + parameters.context.globalAlpha = 0.5; + + for (let i = 0; i < network.wires.length; ++i) { + const wire = network.wires[i]; + const staticComp = wire.components.StaticMapEntity; + const screenTile = this.root.camera.worldToScreen(staticComp.origin.toWorldSpace()); + MapChunkView.drawSingleWiresOverviewTile({ + context: parameters.context, + x: screenTile.x, + y: screenTile.y, + entity: wire, + tileSizePixels: globalConfig.tileSize * this.root.camera.zoomLevel, + overrideColor: THEME.map.wires.highlightColor, + }); + } + + for (let i = 0; i < network.tunnels.length; ++i) { + const tunnel = network.tunnels[i]; + const staticComp = tunnel.components.StaticMapEntity; + const screenTile = this.root.camera.worldToScreen(staticComp.origin.toWorldSpace()); + MapChunkView.drawSingleWiresOverviewTile({ + context: parameters.context, + x: screenTile.x, + y: screenTile.y, + entity: tunnel, + tileSizePixels: globalConfig.tileSize * this.root.camera.zoomLevel, + overrideColor: THEME.map.wires.highlightColor, + }); + } + parameters.context.globalAlpha = 1; + } +} diff --git a/src/js/game/hud/parts/wires_overlay.js b/src/js/game/hud/parts/wires_overlay.js index 8bda5d0d..364002fd 100644 --- a/src/js/game/hud/parts/wires_overlay.js +++ b/src/js/game/hud/parts/wires_overlay.js @@ -2,7 +2,6 @@ import { makeOffscreenBuffer } from "../../../core/buffer_utils"; import { globalConfig } from "../../../core/config"; import { DrawParameters } from "../../../core/draw_parameters"; import { KEYMAPPINGS } from "../../key_action_mapper"; -import { enumLayer } from "../../root"; import { THEME } from "../../theme"; import { BaseHUDPart } from "../base_hud_part"; import { Loader } from "../../../core/loader"; @@ -26,10 +25,10 @@ export class HUDWiresOverlay extends BaseHUDPart { * Switches between layers */ switchLayers() { - if (this.root.currentLayer === enumLayer.regular) { - this.root.currentLayer = enumLayer.wires; + if (this.root.currentLayer === "regular") { + this.root.currentLayer = "wires"; } else { - this.root.currentLayer = enumLayer.regular; + this.root.currentLayer = "regular"; } this.root.signals.editModeChanged.dispatch(this.root.currentLayer); } @@ -38,19 +37,20 @@ export class HUDWiresOverlay extends BaseHUDPart { * Generates the background pattern for the wires overlay */ generateTilePattern() { - const overlayTile = Loader.getSprite("sprites/misc/wires_overlay_tile.png"); + const overlayTile = Loader.getSprite("sprites/wires/overlay_tile.png"); const dims = globalConfig.tileSize * wiresBackgroundDpi; const [canvas, context] = makeOffscreenBuffer(dims, dims, { smooth: false, reusable: false, label: "wires-tile-pattern", }); + context.clearRect(0, 0, dims, dims); overlayTile.draw(context, 0, 0, dims, dims); this.tilePatternCanvas = canvas; } update() { - const desiredAlpha = this.root.currentLayer === enumLayer.wires ? 1.0 : 0.0; + const desiredAlpha = this.root.currentLayer === "wires" ? 1.0 : 0.0; this.currentAlpha = lerp(this.currentAlpha, desiredAlpha, 0.12); } @@ -73,10 +73,14 @@ export class HUDWiresOverlay extends BaseHUDPart { const bounds = parameters.visibleRect; - const scaleFactor = 1 / wiresBackgroundDpi; + parameters.context.globalAlpha = this.currentAlpha; + + const scaleFactor = 1 / wiresBackgroundDpi; + parameters.context.globalCompositeOperation = "overlay"; + parameters.context.fillStyle = "rgba(50, 200, 150, 1)"; + parameters.context.fillRect(bounds.x, bounds.y, bounds.w, bounds.h); + parameters.context.globalCompositeOperation = "source-over"; - parameters.context.globalAlpha = 0.9 * this.currentAlpha; - parameters.context.globalCompositeOperation = "darken"; parameters.context.scale(scaleFactor, scaleFactor); parameters.context.fillStyle = this.cachedPatternBackground; parameters.context.fillRect( @@ -86,12 +90,7 @@ export class HUDWiresOverlay extends BaseHUDPart { bounds.h / scaleFactor ); parameters.context.scale(1 / scaleFactor, 1 / scaleFactor); - parameters.context.globalCompositeOperation = "source-over"; - parameters.context.globalAlpha = 1; - // parameters.context.fillStyle = "#3a85bf"; - // parameters.context.globalAlpha = 0.0 * this.currentAlpha; - // parameters.context.fillRect(bounds.x, bounds.y, bounds.w, bounds.h); - // parameters.context.globalAlpha = 1; + parameters.context.globalAlpha = 1; } } diff --git a/src/js/game/hud/parts/wires_toolbar.js b/src/js/game/hud/parts/wires_toolbar.js index 6ebc0a98..542218e2 100644 --- a/src/js/game/hud/parts/wires_toolbar.js +++ b/src/js/game/hud/parts/wires_toolbar.js @@ -1,16 +1,24 @@ -import { MetaWireBaseBuilding } from "../../buildings/wire_base"; -import { enumLayer } from "../../root"; import { HUDBaseToolbar } from "./base_toolbar"; -import { MetaWireCrossingsBuilding } from "../../buildings/wire_crossings"; +import { MetaWireBuilding } from "../../buildings/wire"; +import { MetaConstantSignalBuilding } from "../../buildings/constant_signal"; +import { MetaLogicGateBuilding } from "../../buildings/logic_gate"; +import { MetaLeverBuilding } from "../../buildings/lever"; +import { MetaWireTunnelBuilding } from "../../buildings/wire_tunnel"; -const supportedBuildings = [MetaWireBaseBuilding, MetaWireCrossingsBuilding]; +const supportedBuildings = [ + MetaWireBuilding, + MetaWireTunnelBuilding, + MetaConstantSignalBuilding, + MetaLogicGateBuilding, + MetaLeverBuilding, +]; export class HUDWiresToolbar extends HUDBaseToolbar { constructor(root) { super(root, { supportedBuildings, visibilityCondition: () => - !this.root.camera.getIsMapOverlayActive() && this.root.currentLayer === enumLayer.wires, + !this.root.camera.getIsMapOverlayActive() && this.root.currentLayer === "wires", htmlElementId: "ingame_HUD_wires_toolbar", }); } diff --git a/src/js/game/hud/trailer_maker.js b/src/js/game/hud/trailer_maker.js index 2834b40d..8655def4 100644 --- a/src/js/game/hud/trailer_maker.js +++ b/src/js/game/hud/trailer_maker.js @@ -1,4 +1,4 @@ -import { GameRoot, enumLayer } from "../root"; +import { GameRoot } from "../root"; import { globalConfig } from "../../core/config"; import { Vector, mixVector } from "../../core/vector"; import { lerp } from "../../core/utils"; @@ -92,7 +92,7 @@ export class TrailerMaker { const speed = globalConfig.tileSize * globalConfig.beltSpeedItemsPerSecond * - globalConfig.beltItemSpacingByLayer[enumLayer.regular]; + globalConfig.itemSpacingOnBelts; // let time = // this.currentPlaybackOrigin.distance(Vector.fromSerializedObject(nextMarker.pos)) / speed; const time = nextMarker.time; diff --git a/src/js/game/item_registry.js b/src/js/game/item_registry.js index d483119f..e6207ea3 100644 --- a/src/js/game/item_registry.js +++ b/src/js/game/item_registry.js @@ -1,12 +1,10 @@ import { gItemRegistry } from "../core/global_registries"; import { ShapeItem } from "./items/shape_item"; import { ColorItem } from "./items/color_item"; -import { PositiveEnergyItem } from "./items/positive_energy_item"; -import { NegativeEnergyItem } from "./items/negative_energy_item"; +import { BooleanItem } from "./items/boolean_item"; export function initItemRegistry() { gItemRegistry.register(ShapeItem); gItemRegistry.register(ColorItem); - gItemRegistry.register(PositiveEnergyItem); - gItemRegistry.register(NegativeEnergyItem); + gItemRegistry.register(BooleanItem); } diff --git a/src/js/game/item_resolver.js b/src/js/game/item_resolver.js new file mode 100644 index 00000000..da15fa0c --- /dev/null +++ b/src/js/game/item_resolver.js @@ -0,0 +1,33 @@ +import { types } from "../savegame/serialization"; +import { gItemRegistry } from "../core/global_registries"; +import { BooleanItem, BOOL_TRUE_SINGLETON, BOOL_FALSE_SINGLETON } from "./items/boolean_item"; +import { ShapeItem } from "./items/shape_item"; +import { ColorItem, COLOR_ITEM_SINGLETONS } from "./items/color_item"; + +/** + * Resolves items so we share instances + * @param {import("../savegame/savegame_serializer").GameRoot} root + * @param {{$: string, data: any }} data + */ +export function itemResolverSingleton(root, data) { + const itemType = data.$; + const itemData = data.data; + + switch (itemType) { + case BooleanItem.getId(): { + return itemData ? BOOL_TRUE_SINGLETON : BOOL_FALSE_SINGLETON; + } + case ShapeItem.getId(): { + return root.shapeDefinitionMgr.getShapeItemFromShortKey(itemData); + } + case ColorItem.getId(): { + return COLOR_ITEM_SINGLETONS[itemData]; + } + + default: { + assertAlways(false, "Unknown item type: " + itemType); + } + } +} + +export const typeItemSingleton = types.obj(gItemRegistry, itemResolverSingleton); diff --git a/src/js/game/items/boolean_item.js b/src/js/game/items/boolean_item.js new file mode 100644 index 00000000..57342bde --- /dev/null +++ b/src/js/game/items/boolean_item.js @@ -0,0 +1,61 @@ +import { DrawParameters } from "../../core/draw_parameters"; +import { Loader } from "../../core/loader"; +import { types } from "../../savegame/serialization"; +import { BaseItem } from "../base_item"; + +export class BooleanItem extends BaseItem { + static getId() { + return "boolean_item"; + } + + static getSchema() { + return types.uint; + } + + serialize() { + return this.value; + } + + deserialize(data) { + this.value = data; + } + + /** @returns {"boolean"} **/ + getItemType() { + return "boolean"; + } + + /** + * @param {number} value + */ + constructor(value) { + super(); + this.value = value ? 1 : 0; + } + + /** + * @param {BaseItem} other + */ + equalsImpl(other) { + return this.value === /** @type {BooleanItem} */ (other).value; + } + + /** + * @param {number} x + * @param {number} y + * @param {number} diameter + * @param {DrawParameters} parameters + */ + drawCentered(x, y, parameters, diameter = 12) { + let sprite; + if (this.value) { + sprite = Loader.getSprite("sprites/wires/boolean_true.png"); + } else { + sprite = Loader.getSprite("sprites/wires/boolean_false.png"); + } + sprite.drawCachedCentered(parameters, x, y, diameter); + } +} + +export const BOOL_FALSE_SINGLETON = new BooleanItem(0); +export const BOOL_TRUE_SINGLETON = new BooleanItem(1); diff --git a/src/js/game/items/color_item.js b/src/js/game/items/color_item.js index d1b9a217..76a1e1d0 100644 --- a/src/js/game/items/color_item.js +++ b/src/js/game/items/color_item.js @@ -2,7 +2,7 @@ import { globalConfig } from "../../core/config"; import { smoothenDpi } from "../../core/dpi_manager"; import { DrawParameters } from "../../core/draw_parameters"; import { types } from "../../savegame/serialization"; -import { BaseItem, enumItemType } from "../base_item"; +import { BaseItem } from "../base_item"; import { enumColors, enumColorsToHexCode } from "../colors"; import { THEME } from "../theme"; @@ -23,8 +23,16 @@ export class ColorItem extends BaseItem { this.color = data; } + /** @returns {"color"} **/ getItemType() { - return enumItemType.color; + return "color"; + } + + /** + * @param {BaseItem} other + */ + equalsImpl(other) { + return this.color === /** @type {ColorItem} */ (other).color; } /** @@ -43,26 +51,26 @@ export class ColorItem extends BaseItem { /** * @param {number} x * @param {number} y - * @param {number} size + * @param {number} diameter * @param {DrawParameters} parameters */ - draw(x, y, parameters, size = 12) { + drawCentered(x, y, parameters, diameter = 12) { if (!this.bufferGenerator) { this.bufferGenerator = this.internalGenerateColorBuffer.bind(this); } const dpi = smoothenDpi(globalConfig.shapesSharpness * parameters.zoomLevel); - const key = size + "/" + dpi; - const canvas = parameters.root.buffers.getForKey( + const key = diameter + "/" + dpi; + const canvas = parameters.root.buffers.getForKey({ key, - this.color, - size, - size, + subKey: this.color, + w: diameter, + h: diameter, dpi, - this.bufferGenerator - ); - parameters.context.drawImage(canvas, x - size / 2, y - size / 2, size, size); + redrawMethod: this.bufferGenerator, + }); + parameters.context.drawImage(canvas, x - diameter / 2, y - diameter / 2, diameter, diameter); } /** * @@ -91,3 +99,13 @@ export class ColorItem extends BaseItem { context.fill(); } } + +/** + * Singleton instances + * @type {Object} + */ +export const COLOR_ITEM_SINGLETONS = {}; + +for (const color in enumColors) { + COLOR_ITEM_SINGLETONS[color] = new ColorItem(color); +} diff --git a/src/js/game/items/negative_energy_item.js b/src/js/game/items/negative_energy_item.js deleted file mode 100644 index 99e2cd06..00000000 --- a/src/js/game/items/negative_energy_item.js +++ /dev/null @@ -1,37 +0,0 @@ -import { DrawParameters } from "../../core/draw_parameters"; -import { Loader } from "../../core/loader"; -import { types } from "../../savegame/serialization"; -import { BaseItem, enumItemType } from "../base_item"; - -export class NegativeEnergyItem extends BaseItem { - static getId() { - return "negative_energy"; - } - - static getSchema() { - return types.uint; - } - - serialize() { - return 0; - } - - deserialize(data) {} - - getItemType() { - return enumItemType.negativeEnergy; - } - - /** - * @param {number} x - * @param {number} y - * @param {number} size - * @param {DrawParameters} parameters - */ - draw(x, y, parameters, size = 12) { - const sprite = Loader.getSprite("sprites/wires/negative_energy.png"); - sprite.drawCachedCentered(parameters, x, y, size * 1.5); - } -} - -export const NEGATIVE_ENERGY_ITEM_SINGLETON = new NegativeEnergyItem(); diff --git a/src/js/game/items/positive_energy_item.js b/src/js/game/items/positive_energy_item.js deleted file mode 100644 index 260ae149..00000000 --- a/src/js/game/items/positive_energy_item.js +++ /dev/null @@ -1,37 +0,0 @@ -import { DrawParameters } from "../../core/draw_parameters"; -import { Loader } from "../../core/loader"; -import { types } from "../../savegame/serialization"; -import { BaseItem, enumItemType } from "../base_item"; - -export class PositiveEnergyItem extends BaseItem { - static getId() { - return "positive_energy"; - } - - static getSchema() { - return types.uint; - } - - serialize() { - return 0; - } - - deserialize(data) {} - - getItemType() { - return enumItemType.positiveEnergy; - } - - /** - * @param {number} x - * @param {number} y - * @param {number} size - * @param {DrawParameters} parameters - */ - draw(x, y, parameters, size = 12) { - const sprite = Loader.getSprite("sprites/wires/positive_energy.png"); - sprite.drawCachedCentered(parameters, x, y, size * 1.5); - } -} - -export const POSITIVE_ENERGY_ITEM_SINGLETON = new PositiveEnergyItem(); diff --git a/src/js/game/items/shape_item.js b/src/js/game/items/shape_item.js index 2aca63f6..44081cab 100644 --- a/src/js/game/items/shape_item.js +++ b/src/js/game/items/shape_item.js @@ -1,6 +1,6 @@ import { DrawParameters } from "../../core/draw_parameters"; import { types } from "../../savegame/serialization"; -import { BaseItem, enumItemType } from "../base_item"; +import { BaseItem } from "../base_item"; import { ShapeDefinition } from "../shape_definition"; import { THEME } from "../theme"; @@ -21,8 +21,16 @@ export class ShapeItem extends BaseItem { this.definition = ShapeDefinition.fromShortKey(data); } + /** @returns {"shape"} **/ getItemType() { - return enumItemType.shape; + return "shape"; + } + + /** + * @param {BaseItem} other + */ + equalsImpl(other) { + return this.definition.getHash() === /** @type {ShapeItem} */ (other).definition.getHash(); } /** @@ -30,7 +38,6 @@ export class ShapeItem extends BaseItem { */ constructor(definition) { super(); - // logger.log("New shape item for shape definition", definition.generateId(), "created"); /** * This property must not be modified on runtime, you have to clone the class in order to change the definition @@ -46,9 +53,9 @@ export class ShapeItem extends BaseItem { * @param {number} x * @param {number} y * @param {DrawParameters} parameters - * @param {number=} size + * @param {number=} diameter */ - draw(x, y, parameters, size) { - this.definition.draw(x, y, parameters, size); + drawCentered(x, y, parameters, diameter) { + this.definition.drawCentered(x, y, parameters, diameter); } } diff --git a/src/js/game/key_action_mapper.js b/src/js/game/key_action_mapper.js index 2dfc5bb1..f88e5a22 100644 --- a/src/js/game/key_action_mapper.js +++ b/src/js/game/key_action_mapper.js @@ -54,12 +54,15 @@ export const KEYMAPPINGS = { mixer: { keyCode: key("8") }, painter: { keyCode: key("9") }, trash: { keyCode: key("0") }, - energy_generator: { keyCode: key("O") }, - advanced_processor: { keyCode: key("P") }, - // Wires layer + lever: { keyCode: key("L") }, + filter: { keyCode: key("B") }, + display: { keyCode: key("N") }, + wire: { keyCode: key("1") }, - wire_crossings: { keyCode: key("2") }, + wire_tunnel: { keyCode: key("2") }, + constant_signal: { keyCode: key("3") }, + logic_gate: { keyCode: key("4") }, }, placement: { diff --git a/src/js/game/logic.js b/src/js/game/logic.js index 403fa15b..ce4d18a5 100644 --- a/src/js/game/logic.js +++ b/src/js/game/logic.js @@ -1,13 +1,23 @@ import { createLogger } from "../core/logging"; +import { STOP_PROPAGATION } from "../core/signal"; import { round2Digits } from "../core/utils"; -import { enumDirection, enumDirectionToVector, Vector } from "../core/vector"; +import { enumDirection, enumDirectionToVector, enumInvertedDirections, Vector } from "../core/vector"; +import { getBuildingDataFromCode } from "./building_codes"; import { Entity } from "./entity"; import { MetaBuilding } from "./meta_building"; -import { enumLayer, GameRoot } from "./root"; -import { STOP_PROPAGATION } from "../core/signal"; +import { GameRoot } from "./root"; +import { WireNetwork } from "./systems/wire"; +import { globalConfig } from "../core/config"; +import { CHUNK_OVERLAY_RES } from "./map_chunk_view"; const logger = createLogger("ingame/logic"); +/** @enum {number} */ +export const enumWireEdgeFlag = { + empty: 0, + connected: 2, +}; + /** * Typing helper * @typedef {Array<{ @@ -63,9 +73,12 @@ export class GameLogic { for (let y = rect.y; y < rect.y + rect.h; ++y) { // Check if there is any direct collision const otherEntity = this.root.map.getLayerContentXY(x, y, entity.layer); - if (otherEntity && !otherEntity.components.ReplaceableMapEntity) { - // This one is a direct blocker - return false; + if (otherEntity) { + const metaClass = otherEntity.components.StaticMapEntity.getMetaBuilding(); + if (!metaClass.getIsReplaceable()) { + // This one is a direct blocker + return false; + } } } } @@ -121,7 +134,7 @@ export class GameLogic { const contents = this.root.map.getLayerContentXY(x, y, entity.layer); if (contents) { assertAlways( - contents.components.ReplaceableMapEntity, + contents.components.StaticMapEntity.getMetaBuilding().getIsReplaceable(), "Tried to replace non-repleaceable entity" ); if (!this.tryDeleteBuilding(contents)) { @@ -158,7 +171,8 @@ export class GameLogic { * @param {Entity} building */ canDeleteBuilding(building) { - return building.components.StaticMapEntity && !building.components.Unremovable; + const staticComp = building.components.StaticMapEntity; + return staticComp.getMetaBuilding().getIsRemovable(); } /** @@ -175,13 +189,206 @@ export class GameLogic { return true; } + /** + * + * Computes the flag for a given tile + * @param {object} param0 + * @param {Vector} param0.tile The tile to check at + * @param {enumDirection} param0.edge The edge to check for + * @param {number} param0.rotation The local tiles base rotation + */ + computeWireEdgeStatus({ tile, edge, rotation }) { + const offset = enumDirectionToVector[edge]; + const refTile = tile.add(offset); + // const angle = enumDirectionToAngle[edge]; + + // // First, check if this edge can be connected from locally + // const canConnectLocally = rotation === angle || (rotation + 180) % 360 === angle; + + const neighbourStatus = this.getWireEdgeFlag(refTile, edge); + + if (neighbourStatus === enumWireEdgeFlag.empty) { + // It's empty, no point in connecting + return false; + } + + if (neighbourStatus === enumWireEdgeFlag.connected) { + return true; + } + } + + /** + * Returns all wire networks this entity participates in on the given tile + * @param {Entity} entity + * @param {Vector} tile + * @returns {Array|null} Null if the entity is never able to be connected at the given tile + */ + getEntityWireNetworks(entity, tile) { + let canConnectAtAll = false; + + /** @type {Set} */ + const networks = new Set(); + + const staticComp = entity.components.StaticMapEntity; + const wireComp = entity.components.Wire; + if (wireComp) { + canConnectAtAll = true; + if (wireComp.linkedNetwork) { + networks.add(wireComp.linkedNetwork); + } + } + + const tunnelComp = entity.components.WireTunnel; + if (tunnelComp) { + canConnectAtAll = true; + for (let i = 0; i < tunnelComp.linkedNetworks.length; ++i) { + networks.add(tunnelComp.linkedNetworks[i]); + } + } + + const pinsComp = entity.components.WiredPins; + if (pinsComp) { + const slots = pinsComp.slots; + for (let i = 0; i < slots.length; ++i) { + const slot = slots[i]; + const slotLocalPos = staticComp.localTileToWorld(slot.pos); + if (slotLocalPos.equals(tile)) { + canConnectAtAll = true; + if (slot.linkedNetwork) { + networks.add(slot.linkedNetwork); + } + } + } + } + + if (!canConnectAtAll) { + return null; + } + + return Array.from(networks); + } + + /** + * Returns if the entities tile *and* his overlay matrix is intersected + * @param {Entity} entity + * @param {Vector} worldPos + */ + getIsEntityIntersectedWithMatrix(entity, worldPos) { + const staticComp = entity.components.StaticMapEntity; + const tile = worldPos.toTileSpace(); + + if (!staticComp.getTileSpaceBounds().containsPoint(tile.x, tile.y)) { + // No intersection at all + return; + } + + const data = getBuildingDataFromCode(staticComp.code); + const overlayMatrix = data.metaInstance.getSpecialOverlayRenderMatrix( + staticComp.rotation, + data.rotationVariant, + data.variant, + entity + ); + // Always the same + if (!overlayMatrix) { + return true; + } + + const localPosition = worldPos + .divideScalar(globalConfig.tileSize) + .modScalar(1) + .multiplyScalar(CHUNK_OVERLAY_RES) + .floor(); + + return !!overlayMatrix[localPosition.x + localPosition.y * 3]; + } + + /** + * Gets the flag at the given tile + * @param {Vector} tile + * @param {enumDirection} edge + * @returns {enumWireEdgeFlag} + */ + getWireEdgeFlag(tile, edge) { + // Search for relevant pins + const pinEntities = this.root.map.getLayersContentsMultipleXY(tile.x, tile.y); + + // Go over all entities which could have a pin + for (let i = 0; i < pinEntities.length; ++i) { + const pinEntity = pinEntities[i]; + const pinComp = pinEntity.components.WiredPins; + const staticComp = pinEntity.components.StaticMapEntity; + + // Skip those who don't have pins + if (!pinComp) { + continue; + } + + // Go over all pins + const pins = pinComp.slots; + for (let k = 0; k < pinComp.slots.length; ++k) { + const pinSlot = pins[k]; + const pinLocation = staticComp.localTileToWorld(pinSlot.pos); + const pinDirection = staticComp.localDirectionToWorld(pinSlot.direction); + + // Check if the pin has the right location + if (!pinLocation.equals(tile)) { + continue; + } + + // Check if the pin has the right direction + if (pinDirection !== enumInvertedDirections[edge]) { + continue; + } + + // Found a pin! + return enumWireEdgeFlag.connected; + } + } + + // Now check if there's a connectable wire + const targetEntity = this.root.map.getTileContent(tile, "wires"); + if (!targetEntity) { + return enumWireEdgeFlag.empty; + } + + const targetStaticComp = targetEntity.components.StaticMapEntity; + + // Check if its a crossing + const wireTunnelComp = targetEntity.components.WireTunnel; + if (wireTunnelComp) { + // Check if the crossing is connected + if (wireTunnelComp.multipleDirections) { + return enumWireEdgeFlag.connected; + } else { + // Its a coating, check if it matches the direction + const referenceDirection = targetStaticComp.localDirectionToWorld(enumDirection.top); + return referenceDirection === edge || enumInvertedDirections[referenceDirection] === edge + ? enumWireEdgeFlag.connected + : enumWireEdgeFlag.empty; + } + } + + // Check if its a wire + const wiresComp = targetEntity.components.Wire; + if (!wiresComp) { + return enumWireEdgeFlag.empty; + } + + // const refAngle = enumDirectionToAngle[edge]; + // const refRotation = targetEntity.components.StaticMapEntity.originalRotation; + // const canConnectRemotely = refRotation === refAngle || (refRotation + 180) % 360 === refAngle; + + // Actually connected + return enumWireEdgeFlag.connected; + } + /** * Returns the acceptors and ejectors which affect the current tile * @param {Vector} tile - * @param {enumLayer} layer * @returns {AcceptorsAndEjectorsAffectingTile} */ - getEjectorsAndAcceptorsAtTile(tile, layer) { + getEjectorsAndAcceptorsAtTile(tile) { /** @type {EjectorsAffectingTile} */ let ejectors = []; /** @type {AcceptorsAffectingTile} */ @@ -194,54 +401,61 @@ export class GameLogic { continue; } - const entities = this.root.map.getLayersContentsMultipleXY(tile.x + dx, tile.y + dy); - for (let i = 0; i < entities.length; ++i) { - const entity = entities[i]; + const entity = this.root.map.getLayerContentXY(tile.x + dx, tile.y + dy, "regular"); + if (entity) { + let ejectorSlots = []; + let acceptorSlots = []; const staticComp = entity.components.StaticMapEntity; const itemEjector = entity.components.ItemEjector; + const itemAcceptor = entity.components.ItemAcceptor; + const beltComp = entity.components.Belt; + if (itemEjector) { - for (let ejectorSlot = 0; ejectorSlot < itemEjector.slots.length; ++ejectorSlot) { - const slot = itemEjector.slots[ejectorSlot]; - if (slot.layer !== layer) { - continue; - } - const wsTile = staticComp.localTileToWorld(slot.pos); - const wsDirection = staticComp.localDirectionToWorld(slot.direction); - const targetTile = wsTile.add(enumDirectionToVector[wsDirection]); - if (targetTile.equals(tile)) { - ejectors.push({ - entity, - slot, - fromTile: wsTile, - toDirection: wsDirection, - }); - } + ejectorSlots = itemEjector.slots.slice(); + } + + if (itemAcceptor) { + acceptorSlots = itemAcceptor.slots.slice(); + } + + if (beltComp) { + const fakeEjectorSlot = beltComp.getFakeEjectorSlot(); + const fakeAcceptorSlot = beltComp.getFakeAcceptorSlot(); + ejectorSlots.push(fakeEjectorSlot); + acceptorSlots.push(fakeAcceptorSlot); + } + + for (let ejectorSlot = 0; ejectorSlot < ejectorSlots.length; ++ejectorSlot) { + const slot = ejectorSlots[ejectorSlot]; + const wsTile = staticComp.localTileToWorld(slot.pos); + const wsDirection = staticComp.localDirectionToWorld(slot.direction); + const targetTile = wsTile.add(enumDirectionToVector[wsDirection]); + if (targetTile.equals(tile)) { + ejectors.push({ + entity, + slot, + fromTile: wsTile, + toDirection: wsDirection, + }); } } - const itemAcceptor = entity.components.ItemAcceptor; - if (itemAcceptor) { - for (let acceptorSlot = 0; acceptorSlot < itemAcceptor.slots.length; ++acceptorSlot) { - const slot = itemAcceptor.slots[acceptorSlot]; - if (slot.layer !== layer) { - continue; - } + for (let acceptorSlot = 0; acceptorSlot < acceptorSlots.length; ++acceptorSlot) { + const slot = acceptorSlots[acceptorSlot]; + const wsTile = staticComp.localTileToWorld(slot.pos); + for (let k = 0; k < slot.directions.length; ++k) { + const direction = slot.directions[k]; + const wsDirection = staticComp.localDirectionToWorld(direction); - const wsTile = staticComp.localTileToWorld(slot.pos); - for (let k = 0; k < slot.directions.length; ++k) { - const direction = slot.directions[k]; - const wsDirection = staticComp.localDirectionToWorld(direction); - - const sourceTile = wsTile.add(enumDirectionToVector[wsDirection]); - if (sourceTile.equals(tile)) { - acceptors.push({ - entity, - slot, - toTile: wsTile, - fromDirection: wsDirection, - }); - } + const sourceTile = wsTile.add(enumDirectionToVector[wsDirection]); + if (sourceTile.equals(tile)) { + acceptors.push({ + entity, + slot, + toTile: wsTile, + fromDirection: wsDirection, + }); } } } diff --git a/src/js/game/map.js b/src/js/game/map.js index 3f8a16f8..5ff51ce8 100644 --- a/src/js/game/map.js +++ b/src/js/game/map.js @@ -1,14 +1,10 @@ -import { GameRoot, enumLayer } from "./root"; import { globalConfig } from "../core/config"; import { Vector } from "../core/vector"; -import { Entity } from "./entity"; -import { createLogger } from "../core/logging"; -import { BaseItem } from "./base_item"; -import { MapChunkView } from "./map_chunk_view"; -import { randomInt } from "../core/utils"; import { BasicSerializableObject, types } from "../savegame/serialization"; - -const logger = createLogger("map"); +import { BaseItem } from "./base_item"; +import { Entity } from "./entity"; +import { MapChunkView } from "./map_chunk_view"; +import { GameRoot } from "./root"; export class BaseMap extends BasicSerializableObject { static getId() { @@ -98,7 +94,7 @@ export class BaseMap extends BasicSerializableObject { /** * Returns the tile content of a given tile * @param {Vector} tile - * @param {enumLayer} layer + * @param {Layer} layer * @returns {Entity} Entity or null */ getTileContent(tile, layer) { @@ -123,7 +119,7 @@ export class BaseMap extends BasicSerializableObject { * Returns the tile content of a given tile * @param {number} x * @param {number} y - * @param {enumLayer} layer + * @param {Layer} layer * @returns {Entity} Entity or null */ getLayerContentXY(x, y, layer) { @@ -148,7 +144,7 @@ export class BaseMap extends BasicSerializableObject { /** * Checks if the tile is used * @param {Vector} tile - * @param {enumLayer} layer + * @param {Layer} layer * @returns {boolean} */ isTileUsed(tile, layer) { @@ -163,7 +159,7 @@ export class BaseMap extends BasicSerializableObject { * Checks if the tile is used * @param {number} x * @param {number} y - * @param {enumLayer} layer + * @param {Layer} layer * @returns {boolean} */ isTileUsedXY(x, y, layer) { diff --git a/src/js/game/map_chunk.js b/src/js/game/map_chunk.js index dd9ba81d..54af1125 100644 --- a/src/js/game/map_chunk.js +++ b/src/js/game/map_chunk.js @@ -1,15 +1,15 @@ -import { GameRoot, enumLayer } from "./root"; import { globalConfig } from "../core/config"; import { createLogger } from "../core/logging"; +import { RandomNumberGenerator } from "../core/rng"; import { clamp, fastArrayDeleteValueIfContained, make2DUndefinedArray } from "../core/utils"; import { Vector } from "../core/vector"; import { BaseItem } from "./base_item"; import { enumColors } from "./colors"; import { Entity } from "./entity"; -import { ColorItem } from "./items/color_item"; -import { ShapeItem } from "./items/shape_item"; +import { COLOR_ITEM_SINGLETONS } from "./items/color_item"; +import { GameRoot } from "./root"; import { enumSubShape } from "./shape_definition"; -import { RandomNumberGenerator } from "../core/rng"; +import { Rectangle } from "../core/rectangle"; const logger = createLogger("map_chunk"); @@ -27,30 +27,56 @@ export class MapChunk { this.tileX = x * globalConfig.mapChunkSize; this.tileY = y * globalConfig.mapChunkSize; - /** @type {Array>} */ - this.contents = make2DUndefinedArray( - globalConfig.mapChunkSize, - globalConfig.mapChunkSize, - "map-chunk@" + this.x + "|" + this.y - ); + /** + * Stores the contents of the lower (= map resources) layer + * @type {Array>} + */ + this.lowerLayer = make2DUndefinedArray(globalConfig.mapChunkSize, globalConfig.mapChunkSize); - /** @type {Array>} */ - this.wireContents = make2DUndefinedArray( - globalConfig.mapChunkSize, - globalConfig.mapChunkSize, - "map-chunk-wires@" + this.x + "|" + this.y - ); + /** + * Stores the contents of the regular layer + * @type {Array>} + */ + this.contents = make2DUndefinedArray(globalConfig.mapChunkSize, globalConfig.mapChunkSize); - /** @type {Array>} */ - this.lowerLayer = make2DUndefinedArray( - globalConfig.mapChunkSize, - globalConfig.mapChunkSize, - "map-chunk-lower@" + this.x + "|" + this.y - ); + /** + * Stores the contents of the wires layer + * @type {Array>} + */ + this.wireContents = make2DUndefinedArray(globalConfig.mapChunkSize, globalConfig.mapChunkSize); /** @type {Array} */ this.containedEntities = []; + /** + * World space rectangle, can be used for culling + */ + this.worldSpaceRectangle = new Rectangle( + this.tileX * globalConfig.tileSize, + this.tileY * globalConfig.tileSize, + globalConfig.mapChunkWorldSize, + globalConfig.mapChunkWorldSize + ); + + /** + * Tile space rectangle, can be used for culling + */ + this.tileSpaceRectangle = new Rectangle( + this.tileX, + this.tileY, + globalConfig.mapChunkSize, + globalConfig.mapChunkSize + ); + + /** + * Which entities this chunk contains, sorted by layer + * @type {Record>} + */ + this.containedEntitiesByLayer = { + regular: [], + wires: [], + }; + /** * Store which patches we have so we can render them in the overview * @type {Array<{pos: Vector, item: BaseItem, size: number }>} @@ -143,7 +169,7 @@ export class MapChunk { if (distanceToOriginInChunks > 2) { availableColors.push(enumColors.blue); } - this.internalGeneratePatch(rng, colorPatchSize, new ColorItem(rng.choice(availableColors))); + this.internalGeneratePatch(rng, colorPatchSize, COLOR_ITEM_SINGLETONS[rng.choice(availableColors)]); } /** @@ -204,7 +230,11 @@ export class MapChunk { } const definition = this.root.shapeDefinitionMgr.getDefinitionFromSimpleShapes(subShapes); - this.internalGeneratePatch(rng, shapePatchSize, new ShapeItem(definition)); + this.internalGeneratePatch( + rng, + shapePatchSize, + this.root.shapeDefinitionMgr.getShapeItemFromDefinition(definition) + ); } /** @@ -268,28 +298,28 @@ export class MapChunk { */ generatePredefined(rng) { if (this.x === 0 && this.y === 0) { - this.internalGeneratePatch(rng, 2, new ColorItem(enumColors.red), 7, 7); + this.internalGeneratePatch(rng, 2, COLOR_ITEM_SINGLETONS[enumColors.red], 7, 7); return true; } if (this.x === -1 && this.y === 0) { - const definition = this.root.shapeDefinitionMgr.getShapeFromShortKey("CuCuCuCu"); - this.internalGeneratePatch(rng, 2, new ShapeItem(definition), globalConfig.mapChunkSize - 9, 7); + const item = this.root.shapeDefinitionMgr.getShapeItemFromShortKey("CuCuCuCu"); + this.internalGeneratePatch(rng, 2, item, globalConfig.mapChunkSize - 9, 7); return true; } if (this.x === 0 && this.y === -1) { - const definition = this.root.shapeDefinitionMgr.getShapeFromShortKey("RuRuRuRu"); - this.internalGeneratePatch(rng, 2, new ShapeItem(definition), 5, globalConfig.mapChunkSize - 7); + const item = this.root.shapeDefinitionMgr.getShapeItemFromShortKey("RuRuRuRu"); + this.internalGeneratePatch(rng, 2, item, 5, globalConfig.mapChunkSize - 7); return true; } if (this.x === -1 && this.y === -1) { - this.internalGeneratePatch(rng, 2, new ColorItem(enumColors.green)); + this.internalGeneratePatch(rng, 2, COLOR_ITEM_SINGLETONS[enumColors.green]); return true; } if (this.x === 5 && this.y === -2) { - const definition = this.root.shapeDefinitionMgr.getShapeFromShortKey("SuSuSuSu"); - this.internalGeneratePatch(rng, 2, new ShapeItem(definition), 5, globalConfig.mapChunkSize - 7); + const item = this.root.shapeDefinitionMgr.getShapeItemFromShortKey("SuSuSuSu"); + this.internalGeneratePatch(rng, 2, item, 5, globalConfig.mapChunkSize - 7); return true; } @@ -332,7 +362,7 @@ export class MapChunk { * Returns the contents of this chunk from the given world space coordinates * @param {number} worldX * @param {number} worldY - * @param {enumLayer} layer + * @param {Layer} layer * @returns {Entity=} */ getLayerContentFromWorldCoords(worldX, worldY, layer) { @@ -342,7 +372,7 @@ export class MapChunk { assert(localY >= 0, "Local Y is < 0"); assert(localX < globalConfig.mapChunkSize, "Local X is >= chunk size"); assert(localY < globalConfig.mapChunkSize, "Local Y is >= chunk size"); - if (layer === enumLayer.regular) { + if (layer === "regular") { return this.contents[localX][localY] || null; } else { return this.wireContents[localX][localY] || null; @@ -395,7 +425,7 @@ export class MapChunk { * @param {number} tileX * @param {number} tileY * @param {Entity=} contents - * @param {enumLayer} layer + * @param {Layer} layer */ setLayerContentFromWorldCords(tileX, tileY, contents, layer) { const localX = tileX - this.tileX; @@ -406,7 +436,7 @@ export class MapChunk { assert(localY < globalConfig.mapChunkSize, "Local Y is >= chunk size"); let oldContents; - if (layer === enumLayer.regular) { + if (layer === "regular") { oldContents = this.contents[localX][localY]; } else { oldContents = this.wireContents[localX][localY]; @@ -415,11 +445,12 @@ export class MapChunk { assert(contents === null || !oldContents, "Tile already used: " + tileX + " / " + tileY); if (oldContents) { - // Remove from list + // Remove from list (the old contents must be reigstered) fastArrayDeleteValueIfContained(this.containedEntities, oldContents); + fastArrayDeleteValueIfContained(this.containedEntitiesByLayer[layer], oldContents); } - if (layer === enumLayer.regular) { + if (layer === "regular") { this.contents[localX][localY] = contents; } else { this.wireContents[localX][localY] = contents; @@ -429,6 +460,10 @@ export class MapChunk { if (this.containedEntities.indexOf(contents) < 0) { this.containedEntities.push(contents); } + + if (this.containedEntitiesByLayer[layer].indexOf(contents) < 0) { + this.containedEntitiesByLayer[layer].push(contents); + } } } } diff --git a/src/js/game/map_chunk_view.js b/src/js/game/map_chunk_view.js index c3f09b39..c62a3401 100644 --- a/src/js/game/map_chunk_view.js +++ b/src/js/game/map_chunk_view.js @@ -1,15 +1,13 @@ -import { MapChunk } from "./map_chunk"; -import { GameRoot } from "./root"; import { globalConfig } from "../core/config"; import { DrawParameters } from "../core/draw_parameters"; -import { round1Digit } from "../core/utils"; -import { Rectangle } from "../core/rectangle"; -import { createLogger } from "../core/logging"; -import { smoothenDpi } from "../core/dpi_manager"; +import { getBuildingDataFromCode } from "./building_codes"; +import { Entity } from "./entity"; +import { MapChunk } from "./map_chunk"; +import { GameRoot } from "./root"; import { THEME } from "./theme"; +import { drawSpriteClipped } from "../core/draw_utils"; -const logger = createLogger("chunk"); -const chunkSizePixels = globalConfig.mapChunkSize * globalConfig.tileSize; +export const CHUNK_OVERLAY_RES = 3; export class MapChunkView extends MapChunk { /** @@ -44,6 +42,7 @@ export class MapChunkView extends MapChunk { drawBackgroundLayer(parameters) { const systems = this.root.systemMgr.systems; systems.mapResources.drawChunk(parameters, this); + systems.beltUnderlays.drawChunk(parameters, this); systems.belt.drawChunk(parameters, this); } @@ -55,15 +54,207 @@ export class MapChunkView extends MapChunk { const systems = this.root.systemMgr.systems; systems.miner.drawChunk(parameters, this); systems.staticMapEntities.drawChunk(parameters, this); + systems.lever.drawChunk(parameters, this); + systems.display.drawChunk(parameters, this); } /** - * Draws the wires layer + * Overlay * @param {DrawParameters} parameters */ - drawWiresLayer(parameters) { - const systems = this.root.systemMgr.systems; - systems.belt.drawWiresChunk(parameters, this); + drawOverlay(parameters) { + const overlaySize = globalConfig.mapChunkSize * CHUNK_OVERLAY_RES; + const sprite = this.root.buffers.getForKey({ + key: "chunk@" + this.root.currentLayer, + subKey: this.renderKey, + w: overlaySize, + h: overlaySize, + dpi: 1, + redrawMethod: this.generateOverlayBuffer.bind(this), + }); + + const dims = globalConfig.mapChunkWorldSize; + + // Draw chunk "pixel" art + parameters.context.imageSmoothingEnabled = false; + drawSpriteClipped({ + parameters, + sprite, + x: this.x * dims, + y: this.y * dims, + w: dims, + h: dims, + originalW: overlaySize, + originalH: overlaySize, + }); + + parameters.context.imageSmoothingEnabled = true; + + // Draw patch items + if (this.root.currentLayer === "regular") { + for (let i = 0; i < this.patches.length; ++i) { + const patch = this.patches[i]; + + const destX = this.x * dims + patch.pos.x * globalConfig.tileSize; + const destY = this.y * dims + patch.pos.y * globalConfig.tileSize; + const destSize = Math.min(80, 30 / parameters.zoomLevel); + + if (parameters.visibleRect.containsCircle(destX, destY, destSize)) { + patch.item.drawCentered(destX, destY, parameters, destSize); + } + } + } + } + + /** + * + * @param {HTMLCanvasElement} canvas + * @param {CanvasRenderingContext2D} context + * @param {number} w + * @param {number} h + * @param {number} dpi + */ + generateOverlayBuffer(canvas, context, w, h, dpi) { + context.fillStyle = + this.containedEntities.length > 0 + ? THEME.map.chunkOverview.filled + : THEME.map.chunkOverview.empty; + context.fillRect(0, 0, w, h); + + for (let x = 0; x < globalConfig.mapChunkSize; ++x) { + const lowerArray = this.lowerLayer[x]; + const upperArray = this.contents[x]; + for (let y = 0; y < globalConfig.mapChunkSize; ++y) { + const upperContent = upperArray[y]; + if (upperContent) { + const staticComp = upperContent.components.StaticMapEntity; + const data = getBuildingDataFromCode(staticComp.code); + const metaBuilding = data.metaInstance; + + const overlayMatrix = metaBuilding.getSpecialOverlayRenderMatrix( + staticComp.rotation, + data.rotationVariant, + data.variant, + upperContent + ); + + if (overlayMatrix) { + // Draw lower content first since it "shines" through + const lowerContent = lowerArray[y]; + if (lowerContent) { + context.fillStyle = lowerContent.getBackgroundColorAsResource(); + context.fillRect( + x * CHUNK_OVERLAY_RES, + y * CHUNK_OVERLAY_RES, + CHUNK_OVERLAY_RES, + CHUNK_OVERLAY_RES + ); + } + + context.fillStyle = metaBuilding.getSilhouetteColor(); + for (let dx = 0; dx < 3; ++dx) { + for (let dy = 0; dy < 3; ++dy) { + const isFilled = overlayMatrix[dx + dy * 3]; + if (isFilled) { + context.fillRect( + x * CHUNK_OVERLAY_RES + dx, + y * CHUNK_OVERLAY_RES + dy, + 1, + 1 + ); + } + } + } + + continue; + } else { + context.fillStyle = metaBuilding.getSilhouetteColor(); + context.fillRect( + x * CHUNK_OVERLAY_RES, + y * CHUNK_OVERLAY_RES, + CHUNK_OVERLAY_RES, + CHUNK_OVERLAY_RES + ); + + continue; + } + } + + const lowerContent = lowerArray[y]; + if (lowerContent) { + context.fillStyle = lowerContent.getBackgroundColorAsResource(); + context.fillRect( + x * CHUNK_OVERLAY_RES, + y * CHUNK_OVERLAY_RES, + CHUNK_OVERLAY_RES, + CHUNK_OVERLAY_RES + ); + } + } + } + + if (this.root.currentLayer === "wires") { + // Draw wires overlay + + context.fillStyle = THEME.map.wires.overlayColor; + context.fillRect(0, 0, w, h); + + for (let x = 0; x < globalConfig.mapChunkSize; ++x) { + const wiresArray = this.wireContents[x]; + for (let y = 0; y < globalConfig.mapChunkSize; ++y) { + const content = wiresArray[y]; + if (!content) { + continue; + } + MapChunkView.drawSingleWiresOverviewTile({ + context, + x: x * CHUNK_OVERLAY_RES, + y: y * CHUNK_OVERLAY_RES, + entity: content, + tileSizePixels: CHUNK_OVERLAY_RES, + }); + } + } + } + } + + /** + * @param {object} param0 + * @param {CanvasRenderingContext2D} param0.context + * @param {number} param0.x + * @param {number} param0.y + * @param {Entity} param0.entity + * @param {number} param0.tileSizePixels + * @param {string=} param0.overrideColor Optionally override the color to be rendered + */ + static drawSingleWiresOverviewTile({ context, x, y, entity, tileSizePixels, overrideColor = null }) { + const staticComp = entity.components.StaticMapEntity; + const data = getBuildingDataFromCode(staticComp.code); + const metaBuilding = data.metaInstance; + const overlayMatrix = metaBuilding.getSpecialOverlayRenderMatrix( + staticComp.rotation, + data.rotationVariant, + data.variant, + entity + ); + context.fillStyle = overrideColor || metaBuilding.getSilhouetteColor(); + if (overlayMatrix) { + for (let dx = 0; dx < 3; ++dx) { + for (let dy = 0; dy < 3; ++dy) { + const isFilled = overlayMatrix[dx + dy * 3]; + if (isFilled) { + context.fillRect( + x + (dx * tileSizePixels) / CHUNK_OVERLAY_RES, + y + (dy * tileSizePixels) / CHUNK_OVERLAY_RES, + tileSizePixels / CHUNK_OVERLAY_RES, + tileSizePixels / CHUNK_OVERLAY_RES + ); + } + } + } + } else { + context.fillRect(x, y, tileSizePixels, tileSizePixels); + } } /** @@ -72,6 +263,7 @@ export class MapChunkView extends MapChunk { */ drawWiresForegroundLayer(parameters) { const systems = this.root.systemMgr.systems; + systems.wire.drawChunk(parameters, this); systems.staticMapEntities.drawWiresChunk(parameters, this); } } diff --git a/src/js/game/map_view.js b/src/js/game/map_view.js index bd10755c..178344a7 100644 --- a/src/js/game/map_view.js +++ b/src/js/game/map_view.js @@ -140,23 +140,23 @@ export class MapView extends BaseMap { * @param {function} method */ drawVisibleChunks(parameters, method) { - const cullRange = parameters.visibleRect.toTileCullRectangle(); + const cullRange = parameters.visibleRect.allScaled(1 / globalConfig.tileSize); const top = cullRange.top(); const right = cullRange.right(); const bottom = cullRange.bottom(); const left = cullRange.left(); - const border = 1; + const border = 0; const minY = top - border; const maxY = bottom + border; const minX = left - border; - const maxX = right + border - 1; + const maxX = right + border; const chunkStartX = Math.floor(minX / globalConfig.mapChunkSize); const chunkStartY = Math.floor(minY / globalConfig.mapChunkSize); - const chunkEndX = Math.ceil(maxX / globalConfig.mapChunkSize); - const chunkEndY = Math.ceil(maxY / globalConfig.mapChunkSize); + const chunkEndX = Math.floor(maxX / globalConfig.mapChunkSize); + const chunkEndY = Math.floor(maxY / globalConfig.mapChunkSize); // Render y from top down for proper blending for (let chunkX = chunkStartX; chunkX <= chunkEndX; ++chunkX) { @@ -167,14 +167,6 @@ export class MapView extends BaseMap { } } - /** - * Draws the wires background - * @param {DrawParameters} parameters - */ - drawWiresLayer(parameters) { - this.drawVisibleChunks(parameters, MapChunkView.prototype.drawWiresLayer); - } - /** * Draws the wires foreground * @param {DrawParameters} parameters @@ -183,20 +175,27 @@ export class MapView extends BaseMap { this.drawVisibleChunks(parameters, MapChunkView.prototype.drawWiresForegroundLayer); } + /** + * Draws the map overlay + * @param {DrawParameters} parameters + */ + drawOverlay(parameters) { + this.drawVisibleChunks(parameters, MapChunkView.prototype.drawOverlay); + } + /** * Draws the map background * @param {DrawParameters} parameters */ drawBackground(parameters) { - // If not using prerendered, draw background - if (parameters.zoomLevel > globalConfig.mapChunkPrerenderMinZoom) { - if (!this.cachedBackgroundPattern) { - this.cachedBackgroundPattern = parameters.context.createPattern( - this.cachedBackgroundCanvas, - "repeat" - ); - } + if (!this.cachedBackgroundPattern) { + this.cachedBackgroundPattern = parameters.context.createPattern( + this.cachedBackgroundCanvas, + "repeat" + ); + } + if (!this.root.app.settings.getAllSettings().disableTileGrid) { const dpi = this.backgroundCacheDPI; parameters.context.scale(1 / dpi, 1 / dpi); @@ -231,21 +230,20 @@ export class MapView extends BaseMap { const chunkEndX = Math.ceil(maxX / globalConfig.mapChunkSize); const chunkEndY = Math.ceil(maxY / globalConfig.mapChunkSize); - // Render y from top down for proper blending for (let chunkX = chunkStartX; chunkX <= chunkEndX; ++chunkX) { for (let chunkY = chunkStartY; chunkY <= chunkEndY; ++chunkY) { parameters.context.fillStyle = "#ffaaaa"; parameters.context.fillRect( - chunkX * globalConfig.mapChunkSize * globalConfig.tileSize, - chunkY * globalConfig.mapChunkSize * globalConfig.tileSize, - globalConfig.mapChunkSize * globalConfig.tileSize, + chunkX * globalConfig.mapChunkWorldSize, + chunkY * globalConfig.mapChunkWorldSize, + globalConfig.mapChunkWorldSize, 3 ); parameters.context.fillRect( - chunkX * globalConfig.mapChunkSize * globalConfig.tileSize, - chunkY * globalConfig.mapChunkSize * globalConfig.tileSize, + chunkX * globalConfig.mapChunkWorldSize, + chunkY * globalConfig.mapChunkWorldSize, 3, - globalConfig.mapChunkSize * globalConfig.tileSize + globalConfig.mapChunkWorldSize ); } } diff --git a/src/js/game/meta_building.js b/src/js/game/meta_building.js index 722dca13..b09e901e 100644 --- a/src/js/game/meta_building.js +++ b/src/js/game/meta_building.js @@ -4,7 +4,7 @@ import { Vector } from "../core/vector"; import { SOUNDS } from "../platform/sound"; import { StaticMapEntityComponent } from "./components/static_map_entity"; import { Entity } from "./entity"; -import { enumLayer, GameRoot } from "./root"; +import { GameRoot } from "./root"; import { getCodeFromBuildingData } from "./building_codes"; export const defaultBuildingVariant = "default"; @@ -27,10 +27,10 @@ export class MetaBuilding { /** * Returns the edit layer of the building - * @returns {enumLayer} + * @returns {Layer} */ getLayer() { - return enumLayer.regular; + return "regular"; } /** @@ -54,6 +54,18 @@ export class MetaBuilding { return false; } + /** + * Can return a special interlaved 9 elements overlay matrix for rendering + * @param {number} rotation + * @param {number} rotationVariant + * @param {string} variant + * @param {Entity} entity + * @returns {Array|null} + */ + getSpecialOverlayRenderMatrix(rotation, rotationVariant, variant, entity) { + return null; + } + /** * Should return additional statistics about this building * @param {GameRoot} root @@ -64,6 +76,13 @@ export class MetaBuilding { return []; } + /** + * Returns whether this building can get replaced + */ + getIsReplaceable() { + return false; + } + /** * Whether to flip the orientation after a building has been placed - useful * for tunnels. @@ -72,6 +91,13 @@ export class MetaBuilding { return false; } + /** + * Whether to show a preview of the wires layer when placing the building + */ + getShowWiresLayerPreview() { + return false; + } + /** * Whether to rotate automatically in the dragging direction while placing * @param {string} variant @@ -80,6 +106,14 @@ export class MetaBuilding { return false; } + /** + * Returns whether this building is removable + * @returns {boolean} + */ + getIsRemovable() { + return true; + } + /** * Returns the placement sound * @returns {string} @@ -126,7 +160,7 @@ export class MetaBuilding { * @param {string} variant * @returns {boolean} */ - isRotateable(variant) { + getIsRotateable(variant) { return true; } @@ -145,6 +179,14 @@ export class MetaBuilding { return null; } + /** + * Should return false if the pins are already included in the sprite of the building + * @returns {boolean} + */ + getRenderPins() { + return true; + } + /** * Creates the entity without placing it * @param {object} param0 @@ -194,11 +236,11 @@ export class MetaBuilding { * @param {Vector} param0.tile * @param {number} param0.rotation * @param {string} param0.variant - * @param {string} param0.layer + * @param {Layer} param0.layer * @return {{ rotation: number, rotationVariant: number, connectedEntities?: Array }} */ computeOptimalDirectionAndRotationVariantAtTile({ root, tile, rotation, variant, layer }) { - if (!this.isRotateable(variant)) { + if (!this.getIsRotateable(variant)) { return { rotation: 0, rotationVariant: 0, diff --git a/src/js/game/meta_building_registry.js b/src/js/game/meta_building_registry.js index 20ca6f41..7bf3b097 100644 --- a/src/js/game/meta_building_registry.js +++ b/src/js/game/meta_building_registry.js @@ -1,10 +1,8 @@ import { gMetaBuildingRegistry } from "../core/global_registries"; import { createLogger } from "../core/logging"; -import { MetaAdvancedProcessorBuilding } from "./buildings/advanced_processor"; import { MetaBeltBuilding } from "./buildings/belt"; import { MetaBeltBaseBuilding } from "./buildings/belt_base"; import { enumCutterVariants, MetaCutterBuilding } from "./buildings/cutter"; -import { MetaEnergyGenerator } from "./buildings/energy_generator"; import { MetaHubBuilding } from "./buildings/hub"; import { enumMinerVariants, MetaMinerBuilding } from "./buildings/miner"; import { MetaMixerBuilding } from "./buildings/mixer"; @@ -14,10 +12,15 @@ import { enumSplitterVariants, MetaSplitterBuilding } from "./buildings/splitter import { MetaStackerBuilding } from "./buildings/stacker"; import { enumTrashVariants, MetaTrashBuilding } from "./buildings/trash"; import { enumUndergroundBeltVariants, MetaUndergroundBeltBuilding } from "./buildings/underground_belt"; -import { MetaWireBaseBuilding } from "./buildings/wire_base"; -import { enumWireCrossingVariants, MetaWireCrossingsBuilding } from "./buildings/wire_crossings"; +import { MetaWireBuilding } from "./buildings/wire"; import { gBuildingVariants, registerBuildingVariant } from "./building_codes"; import { defaultBuildingVariant } from "./meta_building"; +import { MetaConstantSignalBuilding } from "./buildings/constant_signal"; +import { MetaLogicGateBuilding, enumLogicGateVariants } from "./buildings/logic_gate"; +import { MetaLeverBuilding } from "./buildings/lever"; +import { MetaFilterBuilding } from "./buildings/filter"; +import { MetaWireTunnelBuilding, enumWireTunnelVariants } from "./buildings/wire_tunnel"; +import { MetaDisplayBuilding } from "./buildings/display"; const logger = createLogger("building_registry"); @@ -33,10 +36,13 @@ export function initMetaBuildingRegistry() { gMetaBuildingRegistry.register(MetaBeltBuilding); gMetaBuildingRegistry.register(MetaUndergroundBeltBuilding); gMetaBuildingRegistry.register(MetaHubBuilding); - gMetaBuildingRegistry.register(MetaEnergyGenerator); - gMetaBuildingRegistry.register(MetaWireBaseBuilding); - gMetaBuildingRegistry.register(MetaAdvancedProcessorBuilding); - gMetaBuildingRegistry.register(MetaWireCrossingsBuilding); + gMetaBuildingRegistry.register(MetaWireBuilding); + gMetaBuildingRegistry.register(MetaConstantSignalBuilding); + gMetaBuildingRegistry.register(MetaLogicGateBuilding); + gMetaBuildingRegistry.register(MetaLeverBuilding); + gMetaBuildingRegistry.register(MetaFilterBuilding); + gMetaBuildingRegistry.register(MetaWireTunnelBuilding); + gMetaBuildingRegistry.register(MetaDisplayBuilding); // Belt registerBuildingVariant(1, MetaBeltBaseBuilding, defaultBuildingVariant, 0); @@ -86,20 +92,34 @@ export function initMetaBuildingRegistry() { // Hub registerBuildingVariant(26, MetaHubBuilding); - // Energy generator - registerBuildingVariant(27, MetaEnergyGenerator); - // Wire - registerBuildingVariant(28, MetaWireBaseBuilding, defaultBuildingVariant, 0); - registerBuildingVariant(29, MetaWireBaseBuilding, defaultBuildingVariant, 1); - registerBuildingVariant(30, MetaWireBaseBuilding, defaultBuildingVariant, 2); + registerBuildingVariant(27, MetaWireBuilding, defaultBuildingVariant, 0); + registerBuildingVariant(28, MetaWireBuilding, defaultBuildingVariant, 1); + registerBuildingVariant(29, MetaWireBuilding, defaultBuildingVariant, 2); + registerBuildingVariant(30, MetaWireBuilding, defaultBuildingVariant, 3); - // Advanced processor - registerBuildingVariant(31, MetaAdvancedProcessorBuilding); + // Constant signal + registerBuildingVariant(31, MetaConstantSignalBuilding); - // Wire crossing - registerBuildingVariant(32, MetaWireCrossingsBuilding); - registerBuildingVariant(33, MetaWireCrossingsBuilding, enumWireCrossingVariants.merger); + // Logic gate + registerBuildingVariant(32, MetaLogicGateBuilding); + registerBuildingVariant(34, MetaLogicGateBuilding, enumLogicGateVariants.not); + registerBuildingVariant(35, MetaLogicGateBuilding, enumLogicGateVariants.xor); + registerBuildingVariant(36, MetaLogicGateBuilding, enumLogicGateVariants.or); + registerBuildingVariant(38, MetaLogicGateBuilding, enumLogicGateVariants.transistor); + + // Lever + registerBuildingVariant(33, MetaLeverBuilding); + + // Filter + registerBuildingVariant(37, MetaFilterBuilding); + + // Wire tunnel + registerBuildingVariant(39, MetaWireTunnelBuilding); + registerBuildingVariant(41, MetaWireTunnelBuilding, enumWireTunnelVariants.coating); + + // Display + registerBuildingVariant(40, MetaDisplayBuilding); // Propagate instances for (const key in gBuildingVariants) { diff --git a/src/js/game/production_analytics.js b/src/js/game/production_analytics.js index 41ec31ae..eda79c83 100644 --- a/src/js/game/production_analytics.js +++ b/src/js/game/production_analytics.js @@ -1,7 +1,7 @@ import { GameRoot } from "./root"; import { ShapeDefinition } from "./shape_definition"; import { globalConfig } from "../core/config"; -import { BaseItem, enumItemType } from "./base_item"; +import { BaseItem } from "./base_item"; import { ShapeItem } from "./items/shape_item"; import { BasicSerializableObject } from "../savegame/serialization"; @@ -53,7 +53,7 @@ export class ProductionAnalytics extends BasicSerializableObject { * @param {BaseItem} item */ onItemProduced(item) { - if (item.getItemType() === enumItemType.shape) { + if (item.getItemType() === "shape") { const definition = /** @type {ShapeItem} */ (item).definition; const key = definition.getHash(); const entry = this.history[enumAnalyticsDataSource.produced]; diff --git a/src/js/game/root.js b/src/js/game/root.js index df0db09e..dfb8025a 100644 --- a/src/js/game/root.js +++ b/src/js/game/root.js @@ -1,5 +1,4 @@ /* eslint-disable no-unused-vars */ - import { Signal } from "../core/signal"; import { RandomNumberGenerator } from "../core/rng"; import { createLogger } from "../core/logging"; @@ -32,14 +31,8 @@ import { Vector } from "../core/vector"; const logger = createLogger("game/root"); -/** @enum {string} */ -export const enumLayer = { - regular: "regular", - wires: "wires", -}; - -/** @type {Array} */ -export const arrayLayers = [enumLayer.regular, enumLayer.wires]; +/** @type {Array} */ +export const layers = ["regular", "wires"]; /** * The game root is basically the whole game state at a given point, @@ -134,8 +127,8 @@ export class GameRoot { /** @type {DynamicTickrate} */ this.dynamicTickrate = null; - /** @type {enumLayer} */ - this.currentLayer = enumLayer.regular; + /** @type {Layer} */ + this.currentLayer = "regular"; this.signals = { // Entities @@ -162,15 +155,12 @@ export class GameRoot { // Called right after game is initialized postLoadHook: /** @type {TypedSignal<[]>} */ (new Signal()), - // Can be used to trigger an async task - performAsync: /** @type {TypedSignal<[function]>} */ (new Signal()), - shapeDelivered: /** @type {TypedSignal<[ShapeDefinition]>} */ (new Signal()), itemProduced: /** @type {TypedSignal<[BaseItem]>} */ (new Signal()), bulkOperationFinished: /** @type {TypedSignal<[]>} */ (new Signal()), - editModeChanged: /** @type {TypedSignal<[enumLayer]>} */ (new Signal()), + editModeChanged: /** @type {TypedSignal<[Layer]>} */ (new Signal()), // Called to check if an entity can be placed, second parameter is an additional offset. // Use to introduce additional placement checks diff --git a/src/js/game/shape_definition.js b/src/js/game/shape_definition.js index f6117a52..7ddb029c 100644 --- a/src/js/game/shape_definition.js +++ b/src/js/game/shape_definition.js @@ -5,19 +5,9 @@ import { DrawParameters } from "../core/draw_parameters"; import { createLogger } from "../core/logging"; import { Vector } from "../core/vector"; import { BasicSerializableObject, types } from "../savegame/serialization"; -import { - enumColors, - enumColorsToHexCode, - enumColorToShortcode, - enumShortcodeToColor, - enumInvertedColors, -} from "./colors"; +import { enumColors, enumColorsToHexCode, enumColorToShortcode, enumShortcodeToColor } from "./colors"; import { THEME } from "./theme"; -const rusha = require("rusha"); - -const logger = createLogger("shape_definition"); - /** * @typedef {{ * subShape: enumSubShape, @@ -286,24 +276,25 @@ export class ShapeDefinition extends BasicSerializableObject { * @param {number} x * @param {number} y * @param {DrawParameters} parameters + * @param {number=} diameter */ - draw(x, y, parameters, size = 20) { + drawCentered(x, y, parameters, diameter = 20) { const dpi = smoothenDpi(globalConfig.shapesSharpness * parameters.zoomLevel); if (!this.bufferGenerator) { this.bufferGenerator = this.internalGenerateShapeBuffer.bind(this); } - const key = size + "/" + dpi; - const canvas = parameters.root.buffers.getForKey( + const key = diameter + "/" + dpi; + const canvas = parameters.root.buffers.getForKey({ key, - this.cachedHash, - size, - size, + subKey: this.cachedHash, + w: diameter, + h: diameter, dpi, - this.bufferGenerator - ); - parameters.context.drawImage(canvas, x - size / 2, y - size / 2, size, size); + redrawMethod: this.bufferGenerator, + }); + parameters.context.drawImage(canvas, x - diameter / 2, y - diameter / 2, diameter, diameter); } /** @@ -598,23 +589,6 @@ export class ShapeDefinition extends BasicSerializableObject { return new ShapeDefinition({ layers: newLayers }); } - /** - * Clones the shape and inverts all colors - */ - cloneAndInvertColors() { - const newLayers = this.internalCloneLayers(); - for (let layerIndex = 0; layerIndex < newLayers.length; ++layerIndex) { - const quadrants = newLayers[layerIndex]; - for (let quadrantIndex = 0; quadrantIndex < 4; ++quadrantIndex) { - const item = quadrants[quadrantIndex]; - if (item) { - item.color = enumInvertedColors[item.color]; - } - } - } - return new ShapeDefinition({ layers: newLayers }); - } - /** * Clones the shape and colors everything in the given colors * @param {[enumColors, enumColors, enumColors, enumColors]} colors diff --git a/src/js/game/shape_definition_manager.js b/src/js/game/shape_definition_manager.js index a3b8c841..ef0d592f 100644 --- a/src/js/game/shape_definition_manager.js +++ b/src/js/game/shape_definition_manager.js @@ -1,8 +1,9 @@ -import { BasicSerializableObject } from "../savegame/serialization"; -import { GameRoot } from "./root"; -import { ShapeDefinition, enumSubShape } from "./shape_definition"; import { createLogger } from "../core/logging"; +import { BasicSerializableObject } from "../savegame/serialization"; import { enumColors } from "./colors"; +import { ShapeItem } from "./items/shape_item"; +import { GameRoot } from "./root"; +import { enumSubShape, ShapeDefinition } from "./shape_definition"; const logger = createLogger("shape_definition_manager"); @@ -19,15 +20,24 @@ export class ShapeDefinitionManager extends BasicSerializableObject { super(); this.root = root; + /** + * Store a cache from key -> definition + * @type {Object} + */ this.shapeKeyToDefinition = {}; + /** + * Store a cache from key -> item + */ + this.shapeKeyToItem = {}; + // Caches operations in the form of 'operation:def1[:def2]' /** @type {Object.|ShapeDefinition>} */ this.operationCache = {}; } /** - * + * Returns a shape instance from a given short key * @param {string} hash * @returns {ShapeDefinition} */ @@ -39,6 +49,29 @@ export class ShapeDefinitionManager extends BasicSerializableObject { return (this.shapeKeyToDefinition[hash] = ShapeDefinition.fromShortKey(hash)); } + /** + * Returns a item instance from a given short key + * @param {string} hash + * @returns {ShapeItem} + */ + getShapeItemFromShortKey(hash) { + const cached = this.shapeKeyToItem[hash]; + if (cached) { + return cached; + } + const definition = this.getShapeFromShortKey(hash); + return (this.shapeKeyToItem[hash] = new ShapeItem(definition)); + } + + /** + * Returns a shape item for a given definition + * @param {ShapeDefinition} definition + * @returns {ShapeItem} + */ + getShapeItemFromDefinition(definition) { + return this.getShapeItemFromShortKey(definition.getHash()); + } + /** * Registers a new shape definition * @param {ShapeDefinition} definition @@ -179,22 +212,6 @@ export class ShapeDefinitionManager extends BasicSerializableObject { )); } - /** - * Generates a definition for inverting all colors on that shape - * @param {ShapeDefinition} definition - * @returns {ShapeDefinition} - */ - shapeActionInvertColors(definition) { - const key = "invert:" + definition.getHash(); - if (this.operationCache[key]) { - return /** @type {ShapeDefinition} */ (this.operationCache[key]); - } - const inverted = definition.cloneAndInvertColors(); - return /** @type {ShapeDefinition} */ (this.operationCache[key] = this.registerOrReturnHandle( - inverted - )); - } - /** * Generates a definition for painting it with the 4 colors * @param {ShapeDefinition} definition diff --git a/src/js/game/systems/belt.js b/src/js/game/systems/belt.js index db538a56..d968e6e1 100644 --- a/src/js/game/systems/belt.js +++ b/src/js/game/systems/belt.js @@ -13,11 +13,9 @@ import { Entity } from "../entity"; import { GameSystemWithFilter } from "../game_system_with_filter"; import { MapChunkView } from "../map_chunk_view"; import { defaultBuildingVariant } from "../meta_building"; -import { enumLayer } from "../root"; -import { MetaWireBaseBuilding } from "../buildings/wire_base"; -import { enumItemType } from "../base_item"; +import { getCodeFromBuildingData } from "../building_codes"; -export const BELT_ANIM_COUNT = 28; +export const BELT_ANIM_COUNT = 14; const logger = createLogger("belt"); @@ -31,18 +29,9 @@ export class BeltSystem extends GameSystemWithFilter { * @type {Object.>} */ this.beltSprites = { - [enumDirection.top]: Loader.getSprite("sprites/belt/forward_0.png"), - [enumDirection.left]: Loader.getSprite("sprites/belt/left_0.png"), - [enumDirection.right]: Loader.getSprite("sprites/belt/right_0.png"), - }; - - /** - * @type {Object.>} - */ - this.wireSprites = { - [enumDirection.top]: Loader.getSprite("sprites/buildings/wire_top.png"), - [enumDirection.left]: Loader.getSprite("sprites/buildings/wire_left.png"), - [enumDirection.right]: Loader.getSprite("sprites/buildings/wire_right.png"), + [enumDirection.top]: Loader.getSprite("sprites/belt/built/forward_0.png"), + [enumDirection.left]: Loader.getSprite("sprites/belt/built/left_0.png"), + [enumDirection.right]: Loader.getSprite("sprites/belt/built/right_0.png"), }; /** @@ -56,11 +45,13 @@ export class BeltSystem extends GameSystemWithFilter { for (let i = 0; i < BELT_ANIM_COUNT; ++i) { this.beltAnimations[enumDirection.top].push( - Loader.getSprite("sprites/belt/forward_" + i + ".png") + Loader.getSprite("sprites/belt/built/forward_" + i + ".png") + ); + this.beltAnimations[enumDirection.left].push( + Loader.getSprite("sprites/belt/built/left_" + i + ".png") ); - this.beltAnimations[enumDirection.left].push(Loader.getSprite("sprites/belt/left_" + i + ".png")); this.beltAnimations[enumDirection.right].push( - Loader.getSprite("sprites/belt/right_" + i + ".png") + Loader.getSprite("sprites/belt/built/right_" + i + ".png") ); } @@ -137,6 +128,9 @@ export class BeltSystem extends GameSystemWithFilter { const originalRect = staticComp.getTileSpaceBounds(); const affectedArea = originalRect.expandedInAllDirections(1); + /** @type {Set} */ + const changedPaths = new Set(); + for (let x = affectedArea.x; x < affectedArea.right(); ++x) { for (let y = affectedArea.y; y < affectedArea.bottom(); ++y) { if (originalRect.containsPoint(x, y)) { @@ -178,6 +172,13 @@ export class BeltSystem extends GameSystemWithFilter { targetStaticComp.rotation = rotation; metaBelt.updateVariants(targetEntity, rotationVariant, defaultBuildingVariant); + // Update code as well + targetStaticComp.code = getCodeFromBuildingData( + metaBelt, + defaultBuildingVariant, + rotationVariant + ); + // Now add it again this.addEntityToPaths(targetEntity); @@ -189,10 +190,17 @@ export class BeltSystem extends GameSystemWithFilter { // Make sure the chunks know about the update this.root.signals.entityChanged.dispatch(targetEntity); } + + if (targetBeltComp.assignedPath) { + changedPaths.add(targetBeltComp.assignedPath); + } } } } + // notify all paths *afterwards* to avoid multi-updates + changedPaths.forEach(path => path.onSurroundingsChanged()); + if (G_IS_DEV && globalConfig.debug.checkBeltPaths) { this.debug_verifyBeltPaths(); } @@ -310,14 +318,10 @@ export class BeltSystem extends GameSystemWithFilter { /** * Draws all belt paths * @param {DrawParameters} parameters - * @param {enumLayer} layer */ - drawLayerBeltItems(parameters, layer) { + drawBeltItems(parameters) { for (let i = 0; i < this.beltPaths.length; ++i) { - const path = this.beltPaths[i]; - if (path.layer === layer) { - path.draw(parameters); - } + this.beltPaths[i].draw(parameters); } } @@ -361,24 +365,10 @@ export class BeltSystem extends GameSystemWithFilter { const followUpBeltComp = followUpEntity.components.Belt; if (followUpBeltComp) { const followUpStatic = followUpEntity.components.StaticMapEntity; - const followUpAcceptor = followUpEntity.components.ItemAcceptor; - // Check if the belt accepts items from our direction - const acceptorSlots = followUpAcceptor.slots; - for (let i = 0; i < acceptorSlots.length; ++i) { - const slot = acceptorSlots[i]; - - // Make sure the acceptor slot is on the same layer - if (slot.layer !== entity.layer) { - continue; - } - - for (let k = 0; k < slot.directions.length; ++k) { - const localDirection = followUpStatic.localDirectionToWorld(slot.directions[k]); - if (enumInvertedDirections[localDirection] === followUpDirection) { - return followUpEntity; - } - } + const acceptedDirection = followUpStatic.localDirectionToWorld(enumDirection.top); + if (acceptedDirection === followUpDirection) { + return followUpEntity; } } } @@ -405,21 +395,12 @@ export class BeltSystem extends GameSystemWithFilter { const supplyBeltComp = supplyEntity.components.Belt; if (supplyBeltComp) { const supplyStatic = supplyEntity.components.StaticMapEntity; - const supplyEjector = supplyEntity.components.ItemEjector; + const otherDirection = supplyStatic.localDirectionToWorld( + enumInvertedDirections[supplyBeltComp.direction] + ); - // Check if the belt accepts items from our direction - const ejectorSlots = supplyEjector.slots; - for (let i = 0; i < ejectorSlots.length; ++i) { - const slot = ejectorSlots[i]; - - // Make sure the ejector slot is on the same layer - if (slot.layer !== entity.layer) { - continue; - } - const localDirection = supplyStatic.localDirectionToWorld(slot.direction); - if (enumInvertedDirections[localDirection] === supplyDirection) { - return supplyEntity; - } + if (otherDirection === supplyDirection) { + return supplyEntity; } } } @@ -505,65 +486,22 @@ export class BeltSystem extends GameSystemWithFilter { * @param {MapChunkView} chunk */ drawChunk(parameters, chunk) { - if (parameters.zoomLevel < globalConfig.mapChunkOverviewMinZoom) { - return; - } - // Limit speed to avoid belts going backwards - const speedMultiplier = Math.min(this.root.hubGoals.getBeltBaseSpeed(enumLayer.regular), 10); + const speedMultiplier = Math.min(this.root.hubGoals.getBeltBaseSpeed(), 10); // SYNC with systems/item_acceptor.js:drawEntityUnderlays! // 126 / 42 is the exact animation speed of the png animation const animationIndex = Math.floor( ((this.root.time.realtimeNow() * speedMultiplier * BELT_ANIM_COUNT * 126) / 42) * - globalConfig.beltItemSpacingByLayer[enumLayer.regular] + globalConfig.itemSpacingOnBelts ); - const contents = chunk.contents; - for (let y = 0; y < globalConfig.mapChunkSize; ++y) { - for (let x = 0; x < globalConfig.mapChunkSize; ++x) { - const entity = contents[x][y]; - - if (entity && entity.components.Belt) { - const direction = entity.components.Belt.direction; - const sprite = this.beltAnimations[direction][animationIndex % BELT_ANIM_COUNT]; - - entity.components.StaticMapEntity.drawSpriteOnFullEntityBounds( - parameters, - sprite, - 0, - false - ); - } - } - } - 1; - } - - /** - * Draws a given chunk - * @param {DrawParameters} parameters - * @param {MapChunkView} chunk - */ - drawWiresChunk(parameters, chunk) { - if (parameters.zoomLevel < globalConfig.mapChunkOverviewMinZoom) { - return; - } - - const contents = chunk.wireContents; - for (let y = 0; y < globalConfig.mapChunkSize; ++y) { - for (let x = 0; x < globalConfig.mapChunkSize; ++x) { - const entity = contents[x][y]; - - if (entity && entity.components.Belt) { - const direction = entity.components.Belt.direction; - const sprite = this.wireSprites[direction]; - entity.components.StaticMapEntity.drawSpriteOnFullEntityBounds( - parameters, - sprite, - 0, - false - ); - } + const contents = chunk.containedEntitiesByLayer.regular; + for (let i = 0; i < contents.length; ++i) { + const entity = contents[i]; + if (entity.components.Belt) { + const direction = entity.components.Belt.direction; + const sprite = this.beltAnimations[direction][animationIndex % BELT_ANIM_COUNT]; + entity.components.StaticMapEntity.drawSpriteOnFullEntityBounds(parameters, sprite, 0); } } } diff --git a/src/js/game/systems/belt_underlays.js b/src/js/game/systems/belt_underlays.js new file mode 100644 index 00000000..26c3e92c --- /dev/null +++ b/src/js/game/systems/belt_underlays.js @@ -0,0 +1,66 @@ +import { globalConfig } from "../../core/config"; +import { drawRotatedSprite } from "../../core/draw_utils"; +import { Loader } from "../../core/loader"; +import { enumDirectionToAngle } from "../../core/vector"; +import { BeltUnderlaysComponent } from "../components/belt_underlays"; +import { GameSystemWithFilter } from "../game_system_with_filter"; +import { BELT_ANIM_COUNT } from "./belt"; +import { MapChunkView } from "../map_chunk_view"; +import { DrawParameters } from "../../core/draw_parameters"; + +export class BeltUnderlaysSystem extends GameSystemWithFilter { + constructor(root) { + super(root, [BeltUnderlaysComponent]); + + this.underlayBeltSprites = []; + + for (let i = 0; i < BELT_ANIM_COUNT; ++i) { + this.underlayBeltSprites.push(Loader.getSprite("sprites/belt/built/forward_" + i + ".png")); + } + } + + /** + * Draws a given chunk + * @param {DrawParameters} parameters + * @param {MapChunkView} chunk + */ + drawChunk(parameters, chunk) { + // Limit speed to avoid belts going backwards + const speedMultiplier = Math.min(this.root.hubGoals.getBeltBaseSpeed(), 10); + + const contents = chunk.containedEntitiesByLayer.regular; + for (let i = 0; i < contents.length; ++i) { + const entity = contents[i]; + const underlayComp = entity.components.BeltUnderlays; + if (underlayComp) { + const staticComp = entity.components.StaticMapEntity; + const underlays = underlayComp.underlays; + for (let i = 0; i < underlays.length; ++i) { + const { pos, direction } = underlays[i]; + const transformedPos = staticComp.localTileToWorld(pos); + + if (!chunk.tileSpaceRectangle.containsPoint(transformedPos.x, transformedPos.y)) { + continue; + } + + const angle = enumDirectionToAngle[staticComp.localDirectionToWorld(direction)]; + + // SYNC with systems/belt.js:drawSingleEntity! + const animationIndex = Math.floor( + ((this.root.time.realtimeNow() * speedMultiplier * BELT_ANIM_COUNT * 126) / 42) * + globalConfig.itemSpacingOnBelts + ); + + drawRotatedSprite({ + parameters, + sprite: this.underlayBeltSprites[animationIndex % this.underlayBeltSprites.length], + x: (transformedPos.x + 0.5) * globalConfig.tileSize, + y: (transformedPos.y + 0.5) * globalConfig.tileSize, + angle: Math.radians(angle), + size: globalConfig.tileSize, + }); + } + } + } + } +} diff --git a/src/js/game/systems/constant_signal.js b/src/js/game/systems/constant_signal.js new file mode 100644 index 00000000..f1ea9f48 --- /dev/null +++ b/src/js/game/systems/constant_signal.js @@ -0,0 +1,129 @@ +import trim from "trim"; +import { DialogWithForm } from "../../core/modal_dialog_elements"; +import { FormElementInput } from "../../core/modal_dialog_forms"; +import { BaseItem } from "../base_item"; +import { enumColors } from "../colors"; +import { ConstantSignalComponent } from "../components/constant_signal"; +import { Entity } from "../entity"; +import { GameSystemWithFilter } from "../game_system_with_filter"; +import { BOOL_FALSE_SINGLETON, BOOL_TRUE_SINGLETON } from "../items/boolean_item"; +import { COLOR_ITEM_SINGLETONS } from "../items/color_item"; +import { ShapeDefinition } from "../shape_definition"; + +export class ConstantSignalSystem extends GameSystemWithFilter { + constructor(root) { + super(root, [ConstantSignalComponent]); + + this.root.signals.entityManuallyPlaced.add(this.querySigalValue, this); + } + + update() { + // Set signals + for (let i = 0; i < this.allEntities.length; ++i) { + const entity = this.allEntities[i]; + const pinsComp = entity.components.WiredPins; + const signalComp = entity.components.ConstantSignal; + pinsComp.slots[0].value = signalComp.signal; + } + } + + /** + * Asks the entity to enter a valid signal code + * @param {Entity} entity + */ + querySigalValue(entity) { + if (!entity.components.ConstantSignal) { + return; + } + + // Ok, query, but also save the uid because it could get stale + const uid = entity.uid; + + const signalValueInput = new FormElementInput({ + id: "signalValue", + label: null, + placeholder: "", + defaultValue: "", + validator: val => this.parseSignalCode(val), + }); + const dialog = new DialogWithForm({ + app: this.root.app, + title: "Set Signal", + desc: "Enter a shape code, color or '0' or '1'", + formElements: [signalValueInput], + buttons: ["cancel:bad:escape", "ok:good:enter"], + }); + this.root.hud.parts.dialogs.internalShowDialog(dialog); + + // When confirmed, set the signal + dialog.buttonSignals.ok.add(() => { + if (!this.root || !this.root.entityMgr) { + // Game got stopped + return; + } + + const entityRef = this.root.entityMgr.findByUid(uid, false); + if (!entityRef) { + // outdated + return; + } + + const constantComp = entityRef.components.ConstantSignal; + if (!constantComp) { + // no longer interesting + return; + } + + constantComp.signal = this.parseSignalCode(signalValueInput.getValue()); + }); + + // When cancelled, destroy the entity again + dialog.buttonSignals.cancel.add(() => { + if (!this.root || !this.root.entityMgr) { + // Game got stopped + return; + } + + const entityRef = this.root.entityMgr.findByUid(uid, false); + if (!entityRef) { + // outdated + return; + } + + const constantComp = entityRef.components.ConstantSignal; + if (!constantComp) { + // no longer interesting + return; + } + + this.root.logic.tryDeleteBuilding(entityRef); + }); + } + + /** + * Tries to parse a signal code + * @param {string} code + * @returns {BaseItem} + */ + parseSignalCode(code) { + code = trim(code); + const codeLower = code.toLowerCase(); + + if (enumColors[codeLower]) { + return COLOR_ITEM_SINGLETONS[codeLower]; + } + if (code === "1" || codeLower === "true") { + return BOOL_TRUE_SINGLETON; + } + + if (code === "0" || codeLower === "false") { + return BOOL_FALSE_SINGLETON; + } + + if (ShapeDefinition.isValidShortKey(code)) { + return this.root.shapeDefinitionMgr.getShapeItemFromShortKey(code); + } + + return null; + } +} diff --git a/src/js/game/systems/display.js b/src/js/game/systems/display.js new file mode 100644 index 00000000..85ce804c --- /dev/null +++ b/src/js/game/systems/display.js @@ -0,0 +1,97 @@ +import { globalConfig } from "../../core/config"; +import { Loader } from "../../core/loader"; +import { BaseItem } from "../base_item"; +import { enumColors } from "../colors"; +import { DisplayComponent } from "../components/display"; +import { GameSystemWithFilter } from "../game_system_with_filter"; +import { ColorItem, COLOR_ITEM_SINGLETONS } from "../items/color_item"; +import { MapChunkView } from "../map_chunk_view"; +import { BooleanItem } from "../items/boolean_item"; + +export class DisplaySystem extends GameSystemWithFilter { + constructor(root) { + super(root, [DisplayComponent]); + + /** @type {Object} */ + this.displaySprites = {}; + + for (const colorId in enumColors) { + if (colorId === enumColors.uncolored) { + continue; + } + this.displaySprites[colorId] = Loader.getSprite("sprites/wires/display/" + colorId + ".png"); + } + } + + /** + * Returns the color / value a display should show + * @param {BaseItem} value + * @returns {BaseItem} + */ + getDisplayItem(value) { + if (!value) { + return null; + } + + switch (value.getItemType()) { + case "boolean": { + return /** @type {BooleanItem} */ (value).value + ? COLOR_ITEM_SINGLETONS[enumColors.white] + : null; + } + + case "color": { + const item = /**@type {ColorItem} */ (value); + return item.color === enumColors.uncolored ? null : item; + } + + case "shape": { + return value; + } + + default: + assertAlways(false, "Unknown item type: " + value.getItemType()); + } + } + + /** + * Draws a given chunk + * @param {import("../../core/draw_utils").DrawParameters} parameters + * @param {MapChunkView} chunk + */ + drawChunk(parameters, chunk) { + const contents = chunk.containedEntitiesByLayer.regular; + for (let i = 0; i < contents.length; ++i) { + const entity = contents[i]; + if (entity && entity.components.Display) { + const pinsComp = entity.components.WiredPins; + const network = pinsComp.slots[0].linkedNetwork; + if (!network || !network.currentValue) { + continue; + } + const value = this.getDisplayItem(network.currentValue); + + if (!value) { + continue; + } + + const origin = entity.components.StaticMapEntity.origin; + if (value.getItemType() === "color") { + this.displaySprites[/** @type {ColorItem} */ (value).color].drawCachedCentered( + parameters, + (origin.x + 0.5) * globalConfig.tileSize, + (origin.y + 0.5) * globalConfig.tileSize, + globalConfig.tileSize + ); + } else if (value.getItemType() === "shape") { + value.drawCentered( + (origin.x + 0.5) * globalConfig.tileSize, + (origin.y + 0.5) * globalConfig.tileSize, + parameters, + 30 + ); + } + } + } + } +} diff --git a/src/js/game/systems/energy_consumer.js b/src/js/game/systems/energy_consumer.js deleted file mode 100644 index 6552fb9a..00000000 --- a/src/js/game/systems/energy_consumer.js +++ /dev/null @@ -1,90 +0,0 @@ -import { DrawParameters } from "../../core/draw_parameters"; -import { Loader } from "../../core/loader"; -import { clamp } from "../../core/utils"; -import { enumItemType } from "../base_item"; -import { EnergyConsumerComponent } from "../components/energy_consumer"; -import { Entity } from "../entity"; -import { GameSystemWithFilter } from "../game_system_with_filter"; -import { NEGATIVE_ENERGY_ITEM_SINGLETON } from "../items/negative_energy_item"; -import { POSITIVE_ENERGY_ITEM_SINGLETON } from "../items/positive_energy_item"; - -export class EnergyConsumerSystem extends GameSystemWithFilter { - constructor(root) { - super(root, [EnergyConsumerComponent]); - - this.batterySprites = [ - Loader.getSprite("sprites/wires/battery_empty.png"), - Loader.getSprite("sprites/wires/battery_low.png"), - Loader.getSprite("sprites/wires/battery_medium.png"), - Loader.getSprite("sprites/wires/battery_full.png"), - ]; - - this.piledWasteSprite = Loader.getSprite("sprites/wires/waste_piled.png"); - } - - update() { - for (let i = 0; i < this.allEntities.length; ++i) { - const entity = this.allEntities[i]; - const energyConsumerComp = entity.components.EnergyConsumer; - - if (energyConsumerComp.piledOutput >= 1.0) { - // Try to get rid of waste - - const ejectorComp = entity.components.ItemEjector; - const item = this.getItemSingletonByType(energyConsumerComp.wasteType); - if (ejectorComp.tryEject(energyConsumerComp.ejectorSlotIndex, item)) { - // Got rid of waste - energyConsumerComp.reduceWaste(1.0); - } - } - } - } - - /** - * - * @param {enumItemType} itemType - */ - getItemSingletonByType(itemType) { - switch (itemType) { - case enumItemType.positiveEnergy: - return POSITIVE_ENERGY_ITEM_SINGLETON; - case enumItemType.negativeEnergy: - return NEGATIVE_ENERGY_ITEM_SINGLETON; - default: - assertAlways(false, "Bad item type: " + itemType); - } - } - - /** - * Draws everything - * @param {DrawParameters} parameters - */ - draw(parameters) { - this.forEachMatchingEntityOnScreen(parameters, this.drawSingleEntity.bind(this)); - } - - /** - * Draws a given entity - * @param {DrawParameters} parameters - * @param {Entity} entity - */ - drawSingleEntity(parameters, entity) { - const staticComp = entity.components.StaticMapEntity; - const consumerComp = entity.components.EnergyConsumer; - - const position = staticComp.localTileToWorld(consumerComp.batteryPosition).toWorldSpaceCenterOfTile(); - - if (consumerComp.hasTooMuchWastePiled()) { - this.piledWasteSprite.drawCachedCentered(parameters, position.x, position.y, 12); - } else { - const percentage = consumerComp.stored / consumerComp.bufferSize; - const index = clamp( - Math.round(percentage * this.batterySprites.length), - 0, - this.batterySprites.length - 1 - ); - - this.batterySprites[index].drawCachedCentered(parameters, position.x, position.y, 12); - } - } -} diff --git a/src/js/game/systems/energy_generator.js b/src/js/game/systems/energy_generator.js deleted file mode 100644 index 76e14c01..00000000 --- a/src/js/game/systems/energy_generator.js +++ /dev/null @@ -1,97 +0,0 @@ -import { DrawParameters } from "../../core/draw_parameters"; -import { formatBigNumber } from "../../core/utils"; -import { T } from "../../translations"; -import { EnergyGeneratorComponent } from "../components/energy_generator"; -import { Entity } from "../entity"; -import { GameSystemWithFilter } from "../game_system_with_filter"; -import { POSITIVE_ENERGY_ITEM_SINGLETON } from "../items/positive_energy_item"; -import { ShapeDefinition } from "../shape_definition"; -import { Loader } from "../../core/loader"; -import { globalConfig } from "../../core/config"; - -export class EnergyGeneratorSystem extends GameSystemWithFilter { - constructor(root) { - super(root, [EnergyGeneratorComponent]); - - this.energyGeneratorOverlay = Loader.getSprite("sprites/misc/energy_generator_overlay.png"); - } - - draw(parameters) { - this.forEachMatchingEntityOnScreen(parameters, this.drawEntity.bind(this)); - } - - /** - * Returns which shape is required for a given generator - * @param {Entity} entity - */ - getShapeRequiredForGenerator(entity) { - return "CuCuCuCu"; - } - - update() { - for (let i = 0; i < this.allEntities.length; ++i) { - const entity = this.allEntities[i]; - const energyGenComp = entity.components.EnergyGenerator; - const ejectorComp = entity.components.ItemEjector; - - if (!energyGenComp.requiredKey) { - // Compute required key for this generator - energyGenComp.requiredKey = this.getShapeRequiredForGenerator(entity); - } - - if (energyGenComp.itemsInQueue > 0) { - // FIXME: Find slot dynamically - if (ejectorComp.tryEject(0, POSITIVE_ENERGY_ITEM_SINGLETON)) { - energyGenComp.itemsInQueue -= 1; - } - } - } - } - - /** - * @param {DrawParameters} parameters - * @param {Entity} entity - */ - drawEntity(parameters, entity) { - const context = parameters.context; - const staticComp = entity.components.StaticMapEntity; - - if (!staticComp.shouldBeDrawn(parameters)) { - return; - } - - const energyGenComp = entity.components.EnergyGenerator; - if (!energyGenComp.requiredKey) { - // Not initialized yet - return; - } - - const pos = staticComp.getTileSpaceBounds().getCenter().toWorldSpace(); - - const definition = ShapeDefinition.fromShortKey(energyGenComp.requiredKey); - definition.draw(pos.x, pos.y, parameters, 30); - - // Draw background - this.energyGeneratorOverlay.drawCachedCentered( - parameters, - pos.x, - pos.y, - globalConfig.tileSize * 2 + 8 - ); - - // TODO - const energyGenerated = 5; - - // deliver: Deliver - // toGenerateEnergy: For energy - context.font = "bold 9px GameFont"; - context.fillStyle = "#64666e"; - context.textAlign = "left"; - context.fillText(T.buildings.energy_generator.deliver.toUpperCase(), pos.x - 25, pos.y - 18); - context.fillText(T.buildings.energy_generator.toGenerateEnergy.toUpperCase(), pos.x - 25, pos.y + 27); - - context.font = "700 9px GameFont"; - context.fillStyle = "#dee1ea"; - context.fillText("" + formatBigNumber(energyGenerated), pos.x + 1, pos.y + 27); - } -} diff --git a/src/js/game/systems/hub.js b/src/js/game/systems/hub.js index f1d4ee28..3641d9d6 100644 --- a/src/js/game/systems/hub.js +++ b/src/js/game/systems/hub.js @@ -1,10 +1,10 @@ -import { GameSystemWithFilter } from "../game_system_with_filter"; -import { HubComponent } from "../components/hub"; import { DrawParameters } from "../../core/draw_parameters"; -import { Entity } from "../entity"; -import { formatBigNumber } from "../../core/utils"; import { Loader } from "../../core/loader"; +import { formatBigNumber } from "../../core/utils"; import { T } from "../../translations"; +import { HubComponent } from "../components/hub"; +import { Entity } from "../entity"; +import { GameSystemWithFilter } from "../game_system_with_filter"; export class HubSystem extends GameSystemWithFilter { constructor(root) { @@ -19,17 +19,12 @@ export class HubSystem extends GameSystemWithFilter { update() { for (let i = 0; i < this.allEntities.length; ++i) { + // Set hub goal const entity = this.allEntities[i]; - - const hubComponent = entity.components.Hub; - - const queue = hubComponent.definitionsToAnalyze; - for (let k = 0; k < queue.length; ++k) { - const definition = queue[k]; - this.root.hubGoals.handleDefinitionDelivered(definition); - } - - hubComponent.definitionsToAnalyze = []; + const pinsComp = entity.components.WiredPins; + pinsComp.slots[0].value = this.root.shapeDefinitionMgr.getShapeItemFromDefinition( + this.root.hubGoals.currentGoal.definition + ); } } @@ -52,7 +47,7 @@ export class HubSystem extends GameSystemWithFilter { const definition = this.root.hubGoals.currentGoal.definition; - definition.draw(pos.x - 25, pos.y - 10, parameters, 40); + definition.drawCentered(pos.x - 25, pos.y - 10, parameters, 40); const goals = this.root.hubGoals.currentGoal; diff --git a/src/js/game/systems/item_acceptor.js b/src/js/game/systems/item_acceptor.js index 2c0f1686..b67bd867 100644 --- a/src/js/game/systems/item_acceptor.js +++ b/src/js/game/systems/item_acceptor.js @@ -1,24 +1,14 @@ -import { GameSystemWithFilter } from "../game_system_with_filter"; import { globalConfig } from "../../core/config"; import { DrawParameters } from "../../core/draw_parameters"; -import { Entity } from "../entity"; -import { enumDirectionToVector, enumDirectionToAngle } from "../../core/vector"; -import { ItemAcceptorComponent } from "../components/item_acceptor"; -import { Loader } from "../../core/loader"; -import { drawRotatedSprite } from "../../core/draw_utils"; -import { BELT_ANIM_COUNT } from "./belt"; import { fastArrayDelete } from "../../core/utils"; -import { enumLayer } from "../root"; +import { enumDirectionToVector } from "../../core/vector"; +import { ItemAcceptorComponent } from "../components/item_acceptor"; +import { Entity } from "../entity"; +import { GameSystemWithFilter } from "../game_system_with_filter"; export class ItemAcceptorSystem extends GameSystemWithFilter { constructor(root) { super(root, [ItemAcceptorComponent]); - - this.underlayBeltSprites = []; - - for (let i = 0; i < BELT_ANIM_COUNT; ++i) { - this.underlayBeltSprites.push(Loader.getSprite("sprites/belt/forward_" + i + ".png")); - } } update() { @@ -32,11 +22,8 @@ export class ItemAcceptorSystem extends GameSystemWithFilter { // Process item consumption animations to avoid items popping from the belts for (let animIndex = 0; animIndex < animations.length; ++animIndex) { const anim = animations[animIndex]; - const layer = aceptorComp.slots[anim.slotIndex].layer; anim.animProgress += - progress * - this.root.hubGoals.getBeltBaseSpeed(layer) * - globalConfig.beltItemSpacingByLayer[layer]; + progress * this.root.hubGoals.getBeltBaseSpeed() * globalConfig.itemSpacingOnBelts; if (anim.animProgress > 1) { // Original // animations.splice(animIndex, 1); @@ -53,27 +40,16 @@ export class ItemAcceptorSystem extends GameSystemWithFilter { /** * Draws the acceptor items * @param {DrawParameters} parameters - * @param {enumLayer} layer */ - drawLayer(parameters, layer) { - this.forEachMatchingEntityOnScreen(parameters, this.drawEntityRegularLayer.bind(this, layer)); + draw(parameters) { + this.forEachMatchingEntityOnScreen(parameters, this.drawEntityRegularLayer.bind(this)); } /** - * Draws the acceptor underlays - * @param {DrawParameters} parameters - * @param {enumLayer} layer - */ - drawUnderlays(parameters, layer) { - this.forEachMatchingEntityOnScreen(parameters, this.drawEntityUnderlays.bind(this, layer)); - } - - /** - * @param {enumLayer} layer * @param {DrawParameters} parameters * @param {Entity} entity */ - drawEntityRegularLayer(layer, parameters, entity) { + drawEntityRegularLayer(parameters, entity) { const staticComp = entity.components.StaticMapEntity; const acceptorComp = entity.components.ItemAcceptor; @@ -87,10 +63,6 @@ export class ItemAcceptorSystem extends GameSystemWithFilter { ]; const slotData = acceptorComp.slots[slotIndex]; - if (slotData.layer !== layer) { - // Don't draw non-regular slots for now - continue; - } const slotWorldPos = staticComp.applyRotationToVector(slotData.pos).add(staticComp.origin); const fadeOutDirection = enumDirectionToVector[staticComp.localDirectionToWorld(direction)]; @@ -98,55 +70,11 @@ export class ItemAcceptorSystem extends GameSystemWithFilter { fadeOutDirection.x * (animProgress / 2 - 0.5), fadeOutDirection.y * (animProgress / 2 - 0.5) ); - item.draw( + item.drawCentered( (finalTile.x + 0.5) * globalConfig.tileSize, (finalTile.y + 0.5) * globalConfig.tileSize, parameters ); } } - - /** - * @param {enumLayer} layer - * @param {DrawParameters} parameters - * @param {Entity} entity - */ - drawEntityUnderlays(layer, parameters, entity) { - const staticComp = entity.components.StaticMapEntity; - const acceptorComp = entity.components.ItemAcceptor; - - if (!staticComp.shouldBeDrawn(parameters)) { - return; - } - - // Limit speed to avoid belts going backwards - const speedMultiplier = Math.min(this.root.hubGoals.getBeltBaseSpeed(layer), 10); - - const underlays = acceptorComp.beltUnderlays; - for (let i = 0; i < underlays.length; ++i) { - const { pos, direction, layer: underlayLayer } = underlays[i]; - if (underlayLayer !== layer) { - // Not our layer - continue; - } - - const transformedPos = staticComp.localTileToWorld(pos); - const angle = enumDirectionToAngle[staticComp.localDirectionToWorld(direction)]; - - // SYNC with systems/belt.js:drawSingleEntity! - const animationIndex = Math.floor( - ((this.root.time.realtimeNow() * speedMultiplier * BELT_ANIM_COUNT * 126) / 42) * - globalConfig.beltItemSpacingByLayer[layer] - ); - - drawRotatedSprite({ - parameters, - sprite: this.underlayBeltSprites[animationIndex % this.underlayBeltSprites.length], - x: (transformedPos.x + 0.5) * globalConfig.tileSize, - y: (transformedPos.y + 0.5) * globalConfig.tileSize, - angle: Math.radians(angle), - size: globalConfig.tileSize, - }); - } - } } diff --git a/src/js/game/systems/item_ejector.js b/src/js/game/systems/item_ejector.js index 316dc053..130c87f0 100644 --- a/src/js/game/systems/item_ejector.js +++ b/src/js/game/systems/item_ejector.js @@ -2,12 +2,12 @@ import { globalConfig } from "../../core/config"; import { DrawParameters } from "../../core/draw_parameters"; import { createLogger } from "../../core/logging"; import { Rectangle } from "../../core/rectangle"; -import { enumDirectionToVector, Vector } from "../../core/vector"; -import { BaseItem, enumItemType, enumItemTypeToLayer } from "../base_item"; +import { enumDirection, enumDirectionToVector, Vector } from "../../core/vector"; +import { BaseItem } from "../base_item"; import { ItemEjectorComponent } from "../components/item_ejector"; import { Entity } from "../entity"; import { GameSystemWithFilter } from "../game_system_with_filter"; -import { enumLayer } from "../root"; +import { enumItemProcessorTypes } from "../components/item_processor"; const logger = createLogger("systems/ejector"); @@ -120,15 +120,13 @@ export class ItemEjectorSystem extends GameSystemWithFilter { const ejectorComp = entity.components.ItemEjector; const staticComp = entity.components.StaticMapEntity; - // Clear the old cache. - ejectorComp.cachedConnectedSlots = null; - - for (let ejectorSlotIndex = 0; ejectorSlotIndex < ejectorComp.slots.length; ++ejectorSlotIndex) { - const ejectorSlot = ejectorComp.slots[ejectorSlotIndex]; + for (let slotIndex = 0; slotIndex < ejectorComp.slots.length; ++slotIndex) { + const ejectorSlot = ejectorComp.slots[slotIndex]; // Clear the old cache. ejectorSlot.cachedDestSlot = null; ejectorSlot.cachedTargetEntity = null; + ejectorSlot.cachedBeltPath = null; // Figure out where and into which direction we eject items const ejectSlotWsTile = staticComp.localTileToWorld(ejectorSlot.pos); @@ -146,8 +144,21 @@ export class ItemEjectorSystem extends GameSystemWithFilter { for (let i = 0; i < targetEntities.length; ++i) { const targetEntity = targetEntities[i]; - const targetAcceptorComp = targetEntity.components.ItemAcceptor; const targetStaticComp = targetEntity.components.StaticMapEntity; + const targetBeltComp = targetEntity.components.Belt; + + // Check for belts (special case) + if (targetBeltComp) { + const beltAcceptingDirection = targetStaticComp.localDirectionToWorld(enumDirection.top); + if (ejectSlotWsDirection === beltAcceptingDirection) { + ejectorSlot.cachedTargetEntity = targetEntity; + ejectorSlot.cachedBeltPath = targetBeltComp.assignedPath; + break; + } + } + + // Check for item acceptors + const targetAcceptorComp = targetEntity.components.ItemAcceptor; if (!targetAcceptorComp) { // Entity doesn't accept items continue; @@ -155,8 +166,7 @@ export class ItemEjectorSystem extends GameSystemWithFilter { const matchingSlot = targetAcceptorComp.findMatchingSlot( targetStaticComp.worldToLocalTile(ejectSlotTargetWsTile), - targetStaticComp.worldDirectionToLocal(ejectSlotWsDirection), - ejectorSlot.layer + targetStaticComp.worldDirectionToLocal(ejectSlotWsDirection) ); if (!matchingSlot) { @@ -164,13 +174,6 @@ export class ItemEjectorSystem extends GameSystemWithFilter { continue; } - // Ok we found a connection - if (ejectorComp.cachedConnectedSlots) { - ejectorComp.cachedConnectedSlots.push(ejectorSlot); - } else { - ejectorComp.cachedConnectedSlots = [ejectorSlot]; - } - // A slot can always be connected to one other slot only ejectorSlot.cachedTargetEntity = targetEntity; ejectorSlot.cachedDestSlot = matchingSlot; @@ -199,11 +202,7 @@ export class ItemEjectorSystem extends GameSystemWithFilter { continue; } - if (!sourceEjectorComp.cachedConnectedSlots) { - continue; - } - - const slots = sourceEjectorComp.cachedConnectedSlots; + const slots = sourceEjectorComp.slots; for (let j = 0; j < slots.length; ++j) { const sourceSlot = slots[j]; const item = sourceSlot.item; @@ -212,7 +211,6 @@ export class ItemEjectorSystem extends GameSystemWithFilter { continue; } - const destSlot = sourceSlot.cachedDestSlot; const targetEntity = sourceSlot.cachedTargetEntity; // Advance items on the slot @@ -220,8 +218,8 @@ export class ItemEjectorSystem extends GameSystemWithFilter { 1, sourceSlot.progress + progressGrowth * - this.root.hubGoals.getBeltBaseSpeed(sourceSlot.layer) * - globalConfig.beltItemSpacingByLayer[sourceSlot.layer] + this.root.hubGoals.getBeltBaseSpeed() * + globalConfig.itemSpacingOnBelts ); // Check if we are still in the process of ejecting, can't proceed then @@ -229,18 +227,34 @@ export class ItemEjectorSystem extends GameSystemWithFilter { continue; } - // Check if the target acceptor can actually accept this item - const targetAcceptorComp = targetEntity.components.ItemAcceptor; - if (!targetAcceptorComp.canAcceptItem(destSlot.index, item)) { + // Check if we are ejecting to a belt path + const destPath = sourceSlot.cachedBeltPath; + if (destPath) { + // Try passing the item over + if (destPath.tryAcceptItem(item)) { + sourceSlot.item = null; + } + + // Always stop here, since there can *either* be a belt path *or* + // a slot continue; } - // Try to hand over the item - if (this.tryPassOverItem(item, targetEntity, destSlot.index)) { - // Handover successful, clear slot - targetAcceptorComp.onItemAccepted(destSlot.index, destSlot.acceptedDirection, item); - sourceSlot.item = null; - continue; + // Check if the target acceptor can actually accept this item + const destSlot = sourceSlot.cachedDestSlot; + if (destSlot) { + const targetAcceptorComp = targetEntity.components.ItemAcceptor; + if (!targetAcceptorComp.canAcceptItem(destSlot.index, item)) { + continue; + } + + // Try to hand over the item + if (this.tryPassOverItem(item, targetEntity, destSlot.index)) { + // Handover successful, clear slot + targetAcceptorComp.onItemAccepted(destSlot.index, destSlot.acceptedDirection, item); + sourceSlot.item = null; + continue; + } } } } @@ -257,8 +271,6 @@ export class ItemEjectorSystem extends GameSystemWithFilter { // TODO: Kinda hacky. How to solve this properly? Don't want to go through inheritance hell. // Also its just a few cases (hope it stays like this .. :x). - const itemLayer = enumItemTypeToLayer[item.getItemType()]; - const beltComp = receiver.components.Belt; if (beltComp) { const path = beltComp.assignedPath; @@ -270,27 +282,26 @@ export class ItemEjectorSystem extends GameSystemWithFilter { return false; } - const energyConsumerComp = receiver.components.EnergyConsumer; - if (energyConsumerComp) { - if (energyConsumerComp.tryAcceptItem(item, slotIndex)) { - // All good - return true; - } - - // Energy consumer can have more components - } - const itemProcessorComp = receiver.components.ItemProcessor; if (itemProcessorComp) { - // Make sure its the same layer - if (itemLayer === receiver.layer) { - // Its an item processor .. - if (itemProcessorComp.tryTakeItem(item, slotIndex)) { - return true; + // @todo HACK + // Check if there are pins, and if so if they are connected + if (itemProcessorComp.type === enumItemProcessorTypes.filter) { + const pinsComp = receiver.components.WiredPins; + if (pinsComp && pinsComp.slots.length === 1) { + const network = pinsComp.slots[0].linkedNetwork; + if (!network || !network.currentValue) { + return false; + } } - // Item processor can have nothing else - return false; } + + // Its an item processor .. + if (itemProcessorComp.tryTakeItem(item, slotIndex)) { + return true; + } + // Item processor can have nothing else + return false; } const undergroundBeltComp = receiver.components.UndergroundBelt; @@ -321,35 +332,22 @@ export class ItemEjectorSystem extends GameSystemWithFilter { return false; } - const energyGeneratorComp = receiver.components.EnergyGenerator; - if (energyGeneratorComp) { - if (energyGeneratorComp.tryTakeItem(item, slotIndex)) { - // Passed it over - return true; - } - - // Energy generator comp can't have anything else - return false; - } - return false; } /** - * Draws the given layer + * Draws everything * @param {DrawParameters} parameters - * @param {enumLayer} layer */ - drawLayer(parameters, layer) { - this.forEachMatchingEntityOnScreen(parameters, this.drawSingleEntity.bind(this, layer)); + draw(parameters) { + this.forEachMatchingEntityOnScreen(parameters, this.drawSingleEntity.bind(this)); } /** - * @param {enumLayer} layer * @param {DrawParameters} parameters * @param {Entity} entity */ - drawSingleEntity(layer, parameters, entity) { + drawSingleEntity(parameters, entity) { const ejectorComp = entity.components.ItemEjector; const staticComp = entity.components.StaticMapEntity; @@ -366,11 +364,6 @@ export class ItemEjectorSystem extends GameSystemWithFilter { continue; } - if (slot.layer !== layer) { - // Not our layer - continue; - } - const realPosition = slot.pos.rotateFastMultipleOf90(staticComp.rotation); const realDirection = Vector.transformDirectionFromMultipleOf90( slot.direction, @@ -386,7 +379,7 @@ export class ItemEjectorSystem extends GameSystemWithFilter { const worldX = tileX * globalConfig.tileSize; const worldY = tileY * globalConfig.tileSize; - ejectedItem.draw(worldX, worldY, parameters); + ejectedItem.drawCentered(worldX, worldY, parameters); } } } diff --git a/src/js/game/systems/item_processor.js b/src/js/game/systems/item_processor.js index 5bebfed7..9943594c 100644 --- a/src/js/game/systems/item_processor.js +++ b/src/js/game/systems/item_processor.js @@ -1,10 +1,11 @@ import { globalConfig } from "../../core/config"; -import { BaseItem, enumItemType } from "../base_item"; -import { enumColorMixingResults, enumInvertedColors } from "../colors"; +import { BaseItem } from "../base_item"; +import { enumColorMixingResults } from "../colors"; import { enumItemProcessorTypes, ItemProcessorComponent } from "../components/item_processor"; import { Entity } from "../entity"; import { GameSystemWithFilter } from "../game_system_with_filter"; -import { ColorItem } from "../items/color_item"; +import { BOOL_TRUE_SINGLETON } from "../items/boolean_item"; +import { ColorItem, COLOR_ITEM_SINGLETONS } from "../items/color_item"; import { ShapeItem } from "../items/shape_item"; export class ItemProcessorSystem extends GameSystemWithFilter { @@ -48,11 +49,11 @@ export class ItemProcessorSystem extends GameSystemWithFilter { if (ejectorComp.canEjectOnSlot(preferredSlot)) { slot = preferredSlot; } else { - slot = ejectorComp.getFirstFreeSlot(entity.layer); + slot = ejectorComp.getFirstFreeSlot(); } } else { // We can eject on any slot - slot = ejectorComp.getFirstFreeSlot(entity.layer); + slot = ejectorComp.getFirstFreeSlot(); } if (slot !== null) { @@ -70,16 +71,7 @@ export class ItemProcessorSystem extends GameSystemWithFilter { // Check if we have an empty queue and can start a new charge if (processorComp.itemsToEject.length === 0) { if (processorComp.inputSlots.length >= processorComp.inputsPerCharge) { - const energyConsumerComp = entity.components.EnergyConsumer; - if (energyConsumerComp) { - // Check if we have enough energy - if (energyConsumerComp.tryStartNextCharge()) { - this.startNewCharge(entity); - } - } else { - // No further checks required - this.startNewCharge(entity); - } + this.startNewCharge(entity); } } } @@ -142,7 +134,7 @@ export class ItemProcessorSystem extends GameSystemWithFilter { const definition = cutDefinitions[i]; if (!definition.isEntirelyEmpty()) { outItems.push({ - item: new ShapeItem(definition), + item: this.root.shapeDefinitionMgr.getShapeItemFromDefinition(definition), requiredSlot: i, }); } @@ -163,7 +155,7 @@ export class ItemProcessorSystem extends GameSystemWithFilter { const definition = cutDefinitions[i]; if (!definition.isEntirelyEmpty()) { outItems.push({ - item: new ShapeItem(definition), + item: this.root.shapeDefinitionMgr.getShapeItemFromDefinition(definition), requiredSlot: i, }); } @@ -180,7 +172,7 @@ export class ItemProcessorSystem extends GameSystemWithFilter { const rotatedDefinition = this.root.shapeDefinitionMgr.shapeActionRotateCW(inputDefinition); outItems.push({ - item: new ShapeItem(rotatedDefinition), + item: this.root.shapeDefinitionMgr.getShapeItemFromDefinition(rotatedDefinition), }); break; } @@ -193,7 +185,7 @@ export class ItemProcessorSystem extends GameSystemWithFilter { const rotatedDefinition = this.root.shapeDefinitionMgr.shapeActionRotateCCW(inputDefinition); outItems.push({ - item: new ShapeItem(rotatedDefinition), + item: this.root.shapeDefinitionMgr.getShapeItemFromDefinition(rotatedDefinition), }); break; } @@ -206,7 +198,7 @@ export class ItemProcessorSystem extends GameSystemWithFilter { const rotatedDefinition = this.root.shapeDefinitionMgr.shapeActionRotateFL(inputDefinition); outItems.push({ - item: new ShapeItem(rotatedDefinition), + item: this.root.shapeDefinitionMgr.getShapeItemFromDefinition(rotatedDefinition), }); break; } @@ -225,7 +217,7 @@ export class ItemProcessorSystem extends GameSystemWithFilter { upperItem.definition ); outItems.push({ - item: new ShapeItem(stackedDefinition), + item: this.root.shapeDefinitionMgr.getShapeItemFromDefinition(stackedDefinition), }); break; } @@ -256,7 +248,7 @@ export class ItemProcessorSystem extends GameSystemWithFilter { resultColor = mixedColor; } outItems.push({ - item: new ColorItem(resultColor), + item: COLOR_ITEM_SINGLETONS[resultColor], }); break; @@ -274,7 +266,7 @@ export class ItemProcessorSystem extends GameSystemWithFilter { ); outItems.push({ - item: new ShapeItem(colorizedDefinition), + item: this.root.shapeDefinitionMgr.getShapeItemFromDefinition(colorizedDefinition), }); break; @@ -301,11 +293,11 @@ export class ItemProcessorSystem extends GameSystemWithFilter { colorItem.color ); outItems.push({ - item: new ShapeItem(colorizedDefinition1), + item: this.root.shapeDefinitionMgr.getShapeItemFromDefinition(colorizedDefinition1), }); outItems.push({ - item: new ShapeItem(colorizedDefinition2), + item: this.root.shapeDefinitionMgr.getShapeItemFromDefinition(colorizedDefinition2), }); break; @@ -332,12 +324,44 @@ export class ItemProcessorSystem extends GameSystemWithFilter { ); outItems.push({ - item: new ShapeItem(colorizedDefinition), + item: this.root.shapeDefinitionMgr.getShapeItemFromDefinition(colorizedDefinition), }); break; } + // FILTER + case enumItemProcessorTypes.filter: { + // TODO + trackProduction = false; + + const item = itemsBySlot[0].item; + + const network = entity.components.WiredPins.slots[0].linkedNetwork; + if (!network || !network.currentValue) { + outItems.push({ + item, + requiredSlot: 1, + }); + break; + } + + const value = network.currentValue; + if (value.equals(BOOL_TRUE_SINGLETON) || value.equals(item)) { + outItems.push({ + item, + requiredSlot: 0, + }); + } else { + outItems.push({ + item, + requiredSlot: 1, + }); + } + + break; + } + // HUB case enumItemProcessorTypes.hub: { @@ -347,37 +371,8 @@ export class ItemProcessorSystem extends GameSystemWithFilter { assert(hubComponent, "Hub item processor has no hub component"); for (let i = 0; i < items.length; ++i) { - const shapeItem = /** @type {ShapeItem} */ (items[i].item); - hubComponent.queueShapeDefinition(shapeItem.definition); - } - - break; - } - - // ADVANCED PROCESSING - - case enumItemProcessorTypes.advancedProcessor: { - const item = items[0].item; - - if (item.getItemType() === enumItemType.color) { - const colorItem = /** @type {ColorItem} */ (items[0].item); - const newColor = enumInvertedColors[colorItem.color]; - outItems.push({ - item: new ColorItem(newColor), - requiredSlot: 0, - }); - } else if (item.getItemType() === enumItemType.shape) { - const shapeItem = /** @type {ShapeItem} */ (items[0].item); - const newItem = this.root.shapeDefinitionMgr.shapeActionInvertColors( - shapeItem.definition - ); - - outItems.push({ - item: new ShapeItem(newItem), - requiredSlot: 0, - }); - } else { - assertAlways(false, "Bad item type: " + item.getItemType() + " for advanced processor."); + const item = /** @type {ShapeItem} */ (items[i].item); + this.root.hubGoals.handleDefinitionDelivered(item.definition); } break; diff --git a/src/js/game/systems/lever.js b/src/js/game/systems/lever.js new file mode 100644 index 00000000..fa727535 --- /dev/null +++ b/src/js/game/systems/lever.js @@ -0,0 +1,50 @@ +import { GameSystemWithFilter } from "../game_system_with_filter"; +import { LeverComponent } from "../components/lever"; +import { BOOL_TRUE_SINGLETON, BOOL_FALSE_SINGLETON } from "../items/boolean_item"; +import { MapChunkView } from "../map_chunk_view"; +import { globalConfig } from "../../core/config"; +import { Loader } from "../../core/loader"; + +export class LeverSystem extends GameSystemWithFilter { + constructor(root) { + super(root, [LeverComponent]); + + this.spriteOn = Loader.getSprite("sprites/wires/lever_on.png"); + this.spriteOff = Loader.getSprite("sprites/buildings/lever.png"); + } + + update() { + for (let i = 0; i < this.allEntities.length; ++i) { + const entity = this.allEntities[i]; + + const leverComp = entity.components.Lever; + const pinsComp = entity.components.WiredPins; + + // Simply sync the status to the first slot + pinsComp.slots[0].value = leverComp.toggled ? BOOL_TRUE_SINGLETON : BOOL_FALSE_SINGLETON; + } + } + + /** + * Draws a given chunk + * @param {import("../../core/draw_utils").DrawParameters} parameters + * @param {MapChunkView} chunk + */ + drawChunk(parameters, chunk) { + const contents = chunk.containedEntitiesByLayer.regular; + for (let i = 0; i < contents.length; ++i) { + const entity = contents[i]; + if (entity && entity.components.Lever) { + const sprite = entity.components.Lever.toggled ? this.spriteOn : this.spriteOff; + const origin = entity.components.StaticMapEntity.origin; + sprite.drawCached( + parameters, + origin.x * globalConfig.tileSize, + origin.y * globalConfig.tileSize, + globalConfig.tileSize, + globalConfig.tileSize + ); + } + } + } +} diff --git a/src/js/game/systems/logic_gate.js b/src/js/game/systems/logic_gate.js new file mode 100644 index 00000000..9fe41250 --- /dev/null +++ b/src/js/game/systems/logic_gate.js @@ -0,0 +1,180 @@ +import { LogicGateComponent, enumLogicGateType } from "../components/logic_gate"; +import { GameSystemWithFilter } from "../game_system_with_filter"; +import { BaseItem } from "../base_item"; +import { enumPinSlotType } from "../components/wired_pins"; +import { BOOL_TRUE_SINGLETON, BOOL_FALSE_SINGLETON, BooleanItem } from "../items/boolean_item"; +import { enumItemProcessorTypes } from "../components/item_processor"; + +export class LogicGateSystem extends GameSystemWithFilter { + constructor(root) { + super(root, [LogicGateComponent]); + + this.boundOperations = { + [enumLogicGateType.and]: this.compute_AND.bind(this), + [enumLogicGateType.not]: this.compute_NOT.bind(this), + [enumLogicGateType.xor]: this.compute_XOR.bind(this), + [enumLogicGateType.or]: this.compute_OR.bind(this), + [enumLogicGateType.transistor]: this.compute_IF.bind(this), + }; + } + + update() { + for (let i = 0; i < this.allEntities.length; ++i) { + const entity = this.allEntities[i]; + const logicComp = entity.components.LogicGate; + const slotComp = entity.components.WiredPins; + + const slotValues = []; + + for (let i = 0; i < slotComp.slots.length; ++i) { + const slot = slotComp.slots[i]; + if (slot.type !== enumPinSlotType.logicalAcceptor) { + continue; + } + if (slot.linkedNetwork) { + slotValues.push(slot.linkedNetwork.currentValue); + } else { + slotValues.push(null); + } + } + + const result = this.boundOperations[logicComp.type](slotValues); + + // @TODO: For now we hardcode the value to always be slot 0 + assert( + slotValues.length === slotComp.slots.length - 1, + "Bad slot config, should have N acceptor slots and 1 ejector" + ); + assert(slotComp.slots[0].type === enumPinSlotType.logicalEjector, "Slot 0 should be ejector"); + + slotComp.slots[0].value = result; + } + } + + /** + * @param {Array} parameters + * @returns {BaseItem} + */ + compute_AND(parameters) { + assert(parameters.length === 2, "bad parameter count for AND"); + + const param1 = parameters[0]; + const param2 = parameters[1]; + if (!param1 || !param2) { + // Not enough params + return BOOL_FALSE_SINGLETON; + } + + const itemType = param1.getItemType(); + + if (itemType !== param2.getItemType()) { + // Differing type + return BOOL_FALSE_SINGLETON; + } + + if (itemType === "boolean") { + return /** @type {BooleanItem} */ (param1).value && /** @type {BooleanItem} */ (param2).value + ? BOOL_TRUE_SINGLETON + : BOOL_FALSE_SINGLETON; + } + + return BOOL_FALSE_SINGLETON; + } + + /** + * @param {Array} parameters + * @returns {BaseItem} + */ + compute_NOT(parameters) { + const item = parameters[0]; + if (!item) { + return BOOL_TRUE_SINGLETON; + } + + if (item.getItemType() !== "boolean") { + // Not a boolean actually + return BOOL_FALSE_SINGLETON; + } + + const value = /** @type {BooleanItem} */ (item).value; + return value ? BOOL_FALSE_SINGLETON : BOOL_TRUE_SINGLETON; + } + + /** + * @param {Array} parameters + * @returns {BaseItem} + */ + compute_XOR(parameters) { + assert(parameters.length === 2, "bad parameter count for XOR"); + + const param1 = parameters[0]; + const param2 = parameters[1]; + if (!param1 && !param2) { + // Not enough params + return BOOL_FALSE_SINGLETON; + } + + // Check for the right types + if (param1 && param1.getItemType() !== "boolean") { + return BOOL_FALSE_SINGLETON; + } + + if (param2 && param2.getItemType() !== "boolean") { + return BOOL_FALSE_SINGLETON; + } + + const valueParam1 = param1 ? /** @type {BooleanItem} */ (param1).value : 0; + const valueParam2 = param2 ? /** @type {BooleanItem} */ (param2).value : 0; + + return valueParam1 ^ valueParam2 ? BOOL_TRUE_SINGLETON : BOOL_FALSE_SINGLETON; + } + + /** + * @param {Array} parameters + * @returns {BaseItem} + */ + compute_OR(parameters) { + assert(parameters.length === 2, "bad parameter count for OR"); + + const param1 = parameters[0]; + const param2 = parameters[1]; + if (!param1 && !param2) { + // Not enough params + return BOOL_FALSE_SINGLETON; + } + + const valueParam1 = + param1 && param1.getItemType() === "boolean" ? /** @type {BooleanItem} */ (param1).value : 0; + const valueParam2 = + param2 && param2.getItemType() === "boolean" ? /** @type {BooleanItem} */ (param2).value : 0; + + return valueParam1 || valueParam2 ? BOOL_TRUE_SINGLETON : BOOL_FALSE_SINGLETON; + } + + /** + * @param {Array} parameters + * @returns {BaseItem} + */ + compute_IF(parameters) { + assert(parameters.length === 2, "bad parameter count for IF"); + + const flag = parameters[0]; + const value = parameters[1]; + if (!flag || !value) { + // Not enough params + return null; + } + + if (flag.getItemType() !== "boolean") { + // Flag is not a boolean + return null; + } + + // pass through item + if (/** @type {BooleanItem} */ (flag).value) { + return value; + } + + return null; + } +} diff --git a/src/js/game/systems/map_resources.js b/src/js/game/systems/map_resources.js index 6504d457..8a005a21 100644 --- a/src/js/game/systems/map_resources.js +++ b/src/js/game/systems/map_resources.js @@ -1,7 +1,9 @@ -import { GameSystem } from "../game_system"; -import { DrawParameters } from "../../core/draw_parameters"; import { globalConfig } from "../../core/config"; +import { DrawParameters } from "../../core/draw_parameters"; +import { GameSystem } from "../game_system"; import { MapChunkView } from "../map_chunk_view"; +import { THEME } from "../theme"; +import { drawSpriteClipped } from "../../core/draw_utils"; export class MapResourcesSystem extends GameSystem { /** @@ -10,57 +12,93 @@ export class MapResourcesSystem extends GameSystem { * @param {MapChunkView} chunk */ drawChunk(parameters, chunk) { - const renderItems = parameters.zoomLevel >= globalConfig.mapChunkOverviewMinZoom; + const basicChunkBackground = this.root.buffers.getForKey({ + key: "chunkres", + subKey: chunk.renderKey, + w: globalConfig.mapChunkSize, + h: globalConfig.mapChunkSize, + dpi: 1, + redrawMethod: this.generateChunkBackground.bind(this, chunk), + }); + + parameters.context.imageSmoothingEnabled = false; + drawSpriteClipped({ + parameters, + sprite: basicChunkBackground, + x: chunk.tileX * globalConfig.tileSize, + y: chunk.tileY * globalConfig.tileSize, + w: globalConfig.mapChunkWorldSize, + h: globalConfig.mapChunkWorldSize, + originalW: globalConfig.mapChunkSize, + originalH: globalConfig.mapChunkSize, + }); + parameters.context.imageSmoothingEnabled = true; parameters.context.globalAlpha = 0.5; - const layer = chunk.lowerLayer; - for (let x = 0; x < globalConfig.mapChunkSize; ++x) { - const row = layer[x]; - const worldX = (chunk.tileX + x) * globalConfig.tileSize; - for (let y = 0; y < globalConfig.mapChunkSize; ++y) { - const lowerItem = row[y]; - if (lowerItem) { - const worldY = (chunk.tileY + y) * globalConfig.tileSize; + if (this.root.app.settings.getAllSettings().lowQualityMapResources) { + // LOW QUALITY: Draw patch items only + for (let i = 0; i < chunk.patches.length; ++i) { + const patch = chunk.patches[i]; + const destX = chunk.x * globalConfig.mapChunkWorldSize + patch.pos.x * globalConfig.tileSize; + const destY = chunk.y * globalConfig.mapChunkWorldSize + patch.pos.y * globalConfig.tileSize; + const destSize = Math.min(80, 40 / parameters.zoomLevel); + if (parameters.visibleRect.containsCircle(destX, destY, destSize / 2)) { + patch.item.drawCentered(destX, destY, parameters, destSize); + } + } + } else { + // HIGH QUALITY: Draw all items + const layer = chunk.lowerLayer; + for (let x = 0; x < globalConfig.mapChunkSize; ++x) { + const row = layer[x]; + const worldX = (chunk.tileX + x) * globalConfig.tileSize; + for (let y = 0; y < globalConfig.mapChunkSize; ++y) { + const lowerItem = row[y]; + if (lowerItem) { + const worldY = (chunk.tileY + y) * globalConfig.tileSize; - if ( - !parameters.visibleRect.containsRect4Params( - worldX, - worldY, - globalConfig.tileSize, - globalConfig.tileSize - ) - ) { - // Clipped - continue; - } + const destX = worldX + globalConfig.halfTileSize; + const destY = worldY + globalConfig.halfTileSize; - parameters.context.fillStyle = lowerItem.getBackgroundColorAsResource(); - parameters.context.fillRect(worldX, worldY, globalConfig.tileSize, globalConfig.tileSize); - if (renderItems) { - lowerItem.draw( - worldX + globalConfig.halfTileSize, - worldY + globalConfig.halfTileSize, - parameters - ); + if (parameters.visibleRect.containsCircle(destX, destY, globalConfig.tileSize / 2)) { + lowerItem.drawCentered(destX, destY, parameters); + } } } } } parameters.context.globalAlpha = 1; + } - if (!renderItems) { - // Render patches instead - const patches = chunk.patches; - for (let i = 0; i < patches.length; ++i) { - const { pos, item, size } = patches[i]; + /** + * + * @param {MapChunkView} chunk + * @param {HTMLCanvasElement} canvas + * @param {CanvasRenderingContext2D} context + * @param {number} w + * @param {number} h + * @param {number} dpi + */ + generateChunkBackground(chunk, canvas, context, w, h, dpi) { + if (this.root.app.settings.getAllSettings().disableTileGrid) { + // The map doesn't draw a background, so we have to + context.fillStyle = THEME.map.background; + context.fillRect(0, 0, w, h); + } else { + context.clearRect(0, 0, w, h); + } - item.draw( - (chunk.tileX + pos.x + 0.5) * globalConfig.tileSize, - (chunk.tileY + pos.y + 0.5) * globalConfig.tileSize, - parameters, - 80 - ); + context.globalAlpha = 0.5; + const layer = chunk.lowerLayer; + for (let x = 0; x < globalConfig.mapChunkSize; ++x) { + const row = layer[x]; + for (let y = 0; y < globalConfig.mapChunkSize; ++y) { + const item = row[y]; + if (item) { + context.fillStyle = item.getBackgroundColorAsResource(); + context.fillRect(x, y, 1, 1); + } } } } diff --git a/src/js/game/systems/miner.js b/src/js/game/systems/miner.js index f317d0d1..0f1fbc45 100644 --- a/src/js/game/systems/miner.js +++ b/src/js/game/systems/miner.js @@ -6,7 +6,6 @@ import { MinerComponent } from "../components/miner"; import { Entity } from "../entity"; import { GameSystemWithFilter } from "../game_system_with_filter"; import { MapChunkView } from "../map_chunk_view"; -import { enumLayer } from "../root"; export class MinerSystem extends GameSystemWithFilter { constructor(root) { @@ -75,7 +74,7 @@ export class MinerSystem extends GameSystemWithFilter { const ejectingDirection = staticComp.localDirectionToWorld(ejectingSlot.direction); const targetTile = ejectingPos.add(enumDirectionToVector[ejectingDirection]); - const targetContents = this.root.map.getTileContent(targetTile, enumLayer.regular); + const targetContents = this.root.map.getTileContent(targetTile, "regular"); // Check if we are connected to another miner and thus do not eject directly if (targetContents) { @@ -130,7 +129,7 @@ export class MinerSystem extends GameSystemWithFilter { } if (minerComp.cachedMinedItem) { - minerComp.cachedMinedItem.draw( + minerComp.cachedMinedItem.drawCentered( (0.5 + staticComp.origin.x) * globalConfig.tileSize, (0.5 + staticComp.origin.y) * globalConfig.tileSize, parameters diff --git a/src/js/game/systems/static_map_entity.js b/src/js/game/systems/static_map_entity.js index 886291a6..00de6b5a 100644 --- a/src/js/game/systems/static_map_entity.js +++ b/src/js/game/systems/static_map_entity.js @@ -1,20 +1,11 @@ -import { GameSystem } from "../game_system"; -import { DrawParameters } from "../../core/draw_parameters"; import { globalConfig } from "../../core/config"; +import { DrawParameters } from "../../core/draw_parameters"; +import { GameSystem } from "../game_system"; import { MapChunkView } from "../map_chunk_view"; -import { Loader } from "../../core/loader"; -import { enumDirection } from "../../core/vector"; -import { enumLayer } from "../root"; export class StaticMapEntitySystem extends GameSystem { constructor(root) { super(root); - - this.beltOverviewSprites = { - [enumDirection.top]: Loader.getSprite("sprites/map_overview/belt_forward.png"), - [enumDirection.right]: Loader.getSprite("sprites/map_overview/belt_right.png"), - [enumDirection.left]: Loader.getSprite("sprites/map_overview/belt_left.png"), - }; } /** @@ -27,8 +18,6 @@ export class StaticMapEntitySystem extends GameSystem { return; } - const drawOutlinesOnly = parameters.zoomLevel < globalConfig.mapChunkOverviewMinZoom; - const drawnUids = new Set(); const contents = chunk.contents; @@ -42,26 +31,10 @@ export class StaticMapEntitySystem extends GameSystem { } drawnUids.add(entity.uid); const staticComp = entity.components.StaticMapEntity; - if (drawOutlinesOnly) { - const rect = staticComp.getTileSpaceBounds(); - parameters.context.fillStyle = staticComp.getSilhouetteColor() || "#aaa"; - const beltComp = entity.components.Belt; - if (beltComp) { - const sprite = this.beltOverviewSprites[beltComp.direction]; - staticComp.drawSpriteOnFullEntityBounds(parameters, sprite, 0, false); - } else { - parameters.context.fillRect( - rect.x * globalConfig.tileSize, - rect.y * globalConfig.tileSize, - rect.w * globalConfig.tileSize, - rect.h * globalConfig.tileSize - ); - } - } else { - const sprite = staticComp.getSprite(); - if (sprite) { - staticComp.drawSpriteOnFullEntityBounds(parameters, sprite, 2, false); - } + + const sprite = staticComp.getSprite(); + if (sprite) { + staticComp.drawSpriteOnFullEntityBounds(parameters, sprite, 2); } } } @@ -92,7 +65,7 @@ export class StaticMapEntitySystem extends GameSystem { const sprite = staticComp.getSprite(); if (sprite) { - staticComp.drawSpriteOnFullEntityBounds(parameters, sprite, 2, false); + staticComp.drawSpriteOnFullEntityBounds(parameters, sprite, 2); } } } diff --git a/src/js/game/systems/storage.js b/src/js/game/systems/storage.js index 7f946e5b..5da8c9a4 100644 --- a/src/js/game/systems/storage.js +++ b/src/js/game/systems/storage.js @@ -4,7 +4,7 @@ import { Entity } from "../entity"; import { DrawParameters } from "../../core/draw_parameters"; import { formatBigNumber, lerp } from "../../core/utils"; import { Loader } from "../../core/loader"; -import { enumLayer } from "../root"; +import { BOOL_TRUE_SINGLETON, BOOL_FALSE_SINGLETON } from "../items/boolean_item"; export class StorageSystem extends GameSystemWithFilter { constructor(root) { @@ -17,13 +17,13 @@ export class StorageSystem extends GameSystemWithFilter { for (let i = 0; i < this.allEntities.length; ++i) { const entity = this.allEntities[i]; const storageComp = entity.components.Storage; + const pinsComp = entity.components.WiredPins; // Eject from storage if (storageComp.storedItem && storageComp.storedCount > 0) { const ejectorComp = entity.components.ItemEjector; - /* FIXME: WIRES */ - const nextSlot = ejectorComp.getFirstFreeSlot(enumLayer.regular); + const nextSlot = ejectorComp.getFirstFreeSlot(); if (nextSlot !== null) { if (ejectorComp.tryEject(nextSlot, storageComp.storedItem)) { storageComp.storedCount--; @@ -37,6 +37,9 @@ export class StorageSystem extends GameSystemWithFilter { let targetAlpha = storageComp.storedCount > 0 ? 1 : 0; storageComp.overlayOpacity = lerp(storageComp.overlayOpacity, targetAlpha, 0.05); + + pinsComp.slots[0].value = storageComp.storedItem; + pinsComp.slots[1].value = storageComp.getIsFull() ? BOOL_TRUE_SINGLETON : BOOL_FALSE_SINGLETON; } } @@ -62,7 +65,7 @@ export class StorageSystem extends GameSystemWithFilter { if (storedItem !== null) { context.globalAlpha = storageComp.overlayOpacity; const center = staticComp.getTileSpaceBounds().getCenter().toWorldSpace(); - storedItem.draw(center.x, center.y, parameters, 30); + storedItem.drawCentered(center.x, center.y, parameters, 30); this.storageOverlaySprite.drawCached(parameters, center.x - 15, center.y + 15, 30, 15); diff --git a/src/js/game/systems/underground_belt.js b/src/js/game/systems/underground_belt.js index f5e1b0ab..90d29e50 100644 --- a/src/js/game/systems/underground_belt.js +++ b/src/js/game/systems/underground_belt.js @@ -13,7 +13,6 @@ import { enumUndergroundBeltMode, UndergroundBeltComponent } from "../components import { Entity } from "../entity"; import { GameSystemWithFilter } from "../game_system_with_filter"; import { fastArrayDelete } from "../../core/utils"; -import { enumLayer } from "../root"; const logger = createLogger("tunnels"); @@ -298,7 +297,7 @@ export class UndergroundBeltSystem extends GameSystemWithFilter { ) { currentTile = currentTile.add(searchVector); - const potentialReceiver = this.root.map.getTileContent(currentTile, enumLayer.regular); + const potentialReceiver = this.root.map.getTileContent(currentTile, "regular"); if (!potentialReceiver) { // Empty tile continue; @@ -395,7 +394,7 @@ export class UndergroundBeltSystem extends GameSystemWithFilter { if (remainingTime <= 0) { const ejectorComp = entity.components.ItemEjector; - const nextSlotIndex = ejectorComp.getFirstFreeSlot(entity.layer); + const nextSlotIndex = ejectorComp.getFirstFreeSlot(); if (nextSlotIndex !== null) { if (ejectorComp.tryEject(nextSlotIndex, nextItem)) { items.shift(); diff --git a/src/js/game/systems/wire.js b/src/js/game/systems/wire.js new file mode 100644 index 00000000..19a2d8be --- /dev/null +++ b/src/js/game/systems/wire.js @@ -0,0 +1,766 @@ +import { globalConfig } from "../../core/config"; +import { gMetaBuildingRegistry } from "../../core/global_registries"; +import { Loader } from "../../core/loader"; +import { createLogger } from "../../core/logging"; +import { Rectangle } from "../../core/rectangle"; +import { StaleAreaDetector } from "../../core/stale_area_detector"; +import { fastArrayDeleteValueIfContained } from "../../core/utils"; +import { + arrayAllDirections, + enumDirection, + enumDirectionToVector, + enumInvertedDirections, + Vector, +} from "../../core/vector"; +import { BaseItem } from "../base_item"; +import { BooleanItem } from "../items/boolean_item"; +import { arrayWireRotationVariantToType, MetaWireBuilding } from "../buildings/wire"; +import { getCodeFromBuildingData } from "../building_codes"; +import { enumWireType, WireComponent } from "../components/wire"; +import { enumPinSlotType, WiredPinsComponent } from "../components/wired_pins"; +import { WireTunnelComponent } from "../components/wire_tunnel"; +import { Entity } from "../entity"; +import { GameSystemWithFilter } from "../game_system_with_filter"; +import { MapChunkView } from "../map_chunk_view"; +import { defaultBuildingVariant } from "../meta_building"; + +const logger = createLogger("wires"); + +let networkUidCounter = 0; + +const VERBOSE_WIRES = G_IS_DEV && false; + +export class WireNetwork { + constructor() { + /** + * Who contributes to this network + * @type {Array<{ entity: Entity, slot: import("../components/wired_pins").WirePinSlot }>} */ + this.providers = []; + + /** + * Who takes values from this network + * @type {Array<{ entity: Entity, slot: import("../components/wired_pins").WirePinSlot }>} */ + this.receivers = []; + + /** + * All connected slots + * @type {Array<{ entity: Entity, slot: import("../components/wired_pins").WirePinSlot }>} + */ + this.allSlots = []; + + /** + * All connected tunnels + * @type {Array} + */ + this.tunnels = []; + + /** + * Which wires are in this network + * @type {Array} + */ + this.wires = []; + + /** + * The current value of this network + * @type {BaseItem} + */ + this.currentValue = null; + + /** + * Whether this network has a value conflict, that is, more than one + * sender has sent a value + * @type {boolean} + */ + this.valueConflict = false; + + /** + * Unique network identifier + * @type {number} + */ + this.uid = ++networkUidCounter; + } +} + +export class WireSystem extends GameSystemWithFilter { + constructor(root) { + super(root, [WireComponent]); + + this.wireSprites = { + regular: { + [enumWireType.regular]: Loader.getSprite("sprites/wires/sets/regular_forward.png"), + [enumWireType.turn]: Loader.getSprite("sprites/wires/sets/regular_turn.png"), + [enumWireType.split]: Loader.getSprite("sprites/wires/sets/regular_split.png"), + [enumWireType.cross]: Loader.getSprite("sprites/wires/sets/regular_cross.png"), + }, + conflict: { + [enumWireType.regular]: Loader.getSprite("sprites/wires/sets/conflict_forward.png"), + [enumWireType.turn]: Loader.getSprite("sprites/wires/sets/conflict_turn.png"), + [enumWireType.split]: Loader.getSprite("sprites/wires/sets/conflict_split.png"), + [enumWireType.cross]: Loader.getSprite("sprites/wires/sets/conflict_cross.png"), + }, + shape: { + [enumWireType.regular]: Loader.getSprite("sprites/wires/sets/shape_forward.png"), + [enumWireType.turn]: Loader.getSprite("sprites/wires/sets/shape_turn.png"), + [enumWireType.split]: Loader.getSprite("sprites/wires/sets/shape_split.png"), + [enumWireType.cross]: Loader.getSprite("sprites/wires/sets/shape_cross.png"), + }, + color: { + [enumWireType.regular]: Loader.getSprite("sprites/wires/sets/color_forward.png"), + [enumWireType.turn]: Loader.getSprite("sprites/wires/sets/color_turn.png"), + [enumWireType.split]: Loader.getSprite("sprites/wires/sets/color_split.png"), + [enumWireType.cross]: Loader.getSprite("sprites/wires/sets/color_cross.png"), + }, + }; + + this.root.signals.entityDestroyed.add(this.queuePlacementUpdate, this); + this.root.signals.entityAdded.add(this.queuePlacementUpdate, this); + + this.root.signals.entityDestroyed.add(this.queueRecomputeIfWire, this); + this.root.signals.entityChanged.add(this.queueRecomputeIfWire, this); + this.root.signals.entityAdded.add(this.queueRecomputeIfWire, this); + + this.needsRecompute = true; + + this.staleArea = new StaleAreaDetector({ + root: this.root, + name: "wires", + recomputeMethod: this.updateSurroundingWirePlacement.bind(this), + }); + + /** + * @type {Array} + */ + this.networks = []; + } + + /** + * Invalidates the wires network if the given entity is relevant for it + * @param {Entity} entity + */ + queueRecomputeIfWire(entity) { + if (!this.root.gameInitialized) { + return; + } + + if (this.isEntityRelevantForWires(entity)) { + this.needsRecompute = true; + this.networks = []; + } + } + + /** + * Recomputes the whole wires network + */ + recomputeWiresNetwork() { + this.needsRecompute = false; + logger.log("Recomputing wires network"); + + this.networks = []; + + // Clear all network references + const wireEntities = this.root.entityMgr.getAllWithComponent(WireComponent); + for (let i = 0; i < wireEntities.length; ++i) { + wireEntities[i].components.Wire.linkedNetwork = null; + } + + const tunnelEntities = this.root.entityMgr.getAllWithComponent(WireTunnelComponent); + for (let i = 0; i < tunnelEntities.length; ++i) { + tunnelEntities[i].components.WireTunnel.linkedNetworks = []; + } + + const pinEntities = this.root.entityMgr.getAllWithComponent(WiredPinsComponent); + for (let i = 0; i < pinEntities.length; ++i) { + const slots = pinEntities[i].components.WiredPins.slots; + for (let k = 0; k < slots.length; ++k) { + slots[k].linkedNetwork = null; + } + } + + VERBOSE_WIRES && logger.log("Recomputing slots"); + + // Iterate over all ejector slots + for (let i = 0; i < pinEntities.length; ++i) { + const entity = pinEntities[i]; + const slots = entity.components.WiredPins.slots; + for (let k = 0; k < slots.length; ++k) { + const slot = slots[k]; + + // Ejectors are computed directly, acceptors are just set + if (slot.type === enumPinSlotType.logicalEjector && !slot.linkedNetwork) { + this.findNetworkForEjector(entity, slot); + } + } + } + } + + /** + * Finds the network for the given slot + * @param {Entity} initialEntity + * @param {import("../components/wired_pins").WirePinSlot} slot + */ + findNetworkForEjector(initialEntity, slot) { + let currentNetwork = new WireNetwork(); + VERBOSE_WIRES && + logger.log( + "Finding network for entity", + initialEntity.uid, + initialEntity.components.StaticMapEntity.origin.toString(), + "(nw-id:", + currentNetwork.uid, + ")" + ); + const entitiesToVisit = [ + { + entity: initialEntity, + slot, + }, + ]; + + while (entitiesToVisit.length > 0) { + const nextData = entitiesToVisit.pop(); + const nextEntity = nextData.entity; + + const wireComp = nextEntity.components.Wire; + const staticComp = nextEntity.components.StaticMapEntity; + + VERBOSE_WIRES && logger.log("Visiting", staticComp.origin.toString(), "(", nextEntity.uid, ")"); + + // Where to search for neighbours + let newSearchDirections = []; + let newSearchTile = null; + + //// WIRE + if (wireComp) { + // Sanity check + assert( + !wireComp.linkedNetwork || wireComp.linkedNetwork === currentNetwork, + "Mismatching wire network on wire entity " + + (wireComp.linkedNetwork ? wireComp.linkedNetwork.uid : "") + + " vs " + + currentNetwork.uid + + " @ " + + staticComp.origin.toString() + ); + + if (!wireComp.linkedNetwork) { + // This one is new! :D + VERBOSE_WIRES && logger.log(" Visited new wire:", staticComp.origin.toString()); + wireComp.linkedNetwork = currentNetwork; + currentNetwork.wires.push(nextEntity); + + newSearchDirections = arrayAllDirections; + newSearchTile = nextEntity.components.StaticMapEntity.origin; + } + } + + //// PINS + const pinsComp = nextEntity.components.WiredPins; + if (pinsComp) { + const slot = nextData.slot; + assert(slot, "No slot set for next entity"); + + if (slot.type === enumPinSlotType.logicalEjector) { + VERBOSE_WIRES && + logger.log(" Visiting ejector slot", staticComp.origin.toString(), "->", slot.type); + } else if (slot.type === enumPinSlotType.logicalAcceptor) { + VERBOSE_WIRES && + logger.log(" Visiting acceptor slot", staticComp.origin.toString(), "->", slot.type); + } else { + assertAlways(false, "Bad slot type: " + slot.type); + } + + // Sanity check + assert( + !slot.linkedNetwork || slot.linkedNetwork === currentNetwork, + "Mismatching wire network on pin slot entity " + + (slot.linkedNetwork ? slot.linkedNetwork.uid : "") + + " vs " + + currentNetwork.uid + ); + if (!slot.linkedNetwork) { + // This one is new + VERBOSE_WIRES && logger.log(" Visited new slot:", staticComp.origin.toString()); + + // Add to the right list + if (slot.type === enumPinSlotType.logicalEjector) { + currentNetwork.providers.push({ entity: nextEntity, slot }); + } else if (slot.type === enumPinSlotType.logicalAcceptor) { + currentNetwork.receivers.push({ entity: nextEntity, slot }); + } else { + assertAlways(false, "unknown slot type:" + slot.type); + } + + // Register on the network + currentNetwork.allSlots.push({ entity: nextEntity, slot }); + slot.linkedNetwork = currentNetwork; + + // Specify where to search next + newSearchDirections = [staticComp.localDirectionToWorld(slot.direction)]; + newSearchTile = staticComp.localTileToWorld(slot.pos); + } + } + + if (newSearchTile) { + // Find new surrounding wire targets + const newTargets = this.findSurroundingWireTargets( + newSearchTile, + newSearchDirections, + currentNetwork + ); + + VERBOSE_WIRES && logger.log(" Found", newTargets, "new targets to visit!"); + for (let i = 0; i < newTargets.length; ++i) { + entitiesToVisit.push(newTargets[i]); + } + } + } + + if ( + currentNetwork.providers.length > 0 && + (currentNetwork.wires.length > 0 || currentNetwork.receivers.length > 0) + ) { + this.networks.push(currentNetwork); + VERBOSE_WIRES && logger.log("Attached new network with uid", currentNetwork); + } else { + // Unregister network again + for (let i = 0; i < currentNetwork.wires.length; ++i) { + currentNetwork.wires[i].components.Wire.linkedNetwork = null; + } + + for (let i = 0; i < currentNetwork.tunnels.length; ++i) { + fastArrayDeleteValueIfContained( + currentNetwork.tunnels[i].components.WireTunnel.linkedNetworks, + currentNetwork + ); + } + + for (let i = 0; i < currentNetwork.allSlots.length; ++i) { + currentNetwork.allSlots[i].slot.linkedNetwork = null; + } + } + } + + /** + * Finds surrounding entities which are not yet assigned to a network + * @param {Vector} initialTile + * @param {Array} directions + * @param {WireNetwork} network + * @returns {Array} + */ + findSurroundingWireTargets(initialTile, directions, network) { + let result = []; + + VERBOSE_WIRES && + logger.log(" Searching for new targets at", initialTile.toString(), "and d=", directions); + + // Go over all directions we should search for + for (let i = 0; i < directions.length; ++i) { + const direction = directions[i]; + const offset = enumDirectionToVector[direction]; + const initialSearchTile = initialTile.add(offset); + + // Store which tunnels we already visited to avoid infinite loops + const visitedTunnels = new Set(); + + // First, find the initial connected entities + const initialContents = this.root.map.getLayersContentsMultipleXY( + initialSearchTile.x, + initialSearchTile.y + ); + + // Link the initial tile to the initial entities, since it may change + /** @type {Array<{entity: Entity, tile: Vector}>} */ + const contents = []; + for (let j = 0; j < initialContents.length; ++j) { + contents.push({ + entity: initialContents[j], + tile: initialSearchTile, + }); + } + + for (let k = 0; k < contents.length; ++k) { + const { entity, tile } = contents[k]; + const wireComp = entity.components.Wire; + + // Check for wire + if (wireComp && !wireComp.linkedNetwork) { + // Wires accept connections from everywhere + result.push({ + entity, + }); + } + + // Check for connected slots + const pinComp = entity.components.WiredPins; + if (pinComp) { + const staticComp = entity.components.StaticMapEntity; + + // Go over all slots and see if they are connected + const pinSlots = pinComp.slots; + for (let j = 0; j < pinSlots.length; ++j) { + const slot = pinSlots[j]; + + // Check if the position matches + const pinPos = staticComp.localTileToWorld(slot.pos); + if (!pinPos.equals(tile)) { + continue; + } + + // Check if the direction (inverted) matches + const pinDirection = staticComp.localDirectionToWorld(slot.direction); + if (pinDirection !== enumInvertedDirections[direction]) { + continue; + } + + if (!slot.linkedNetwork) { + result.push({ + entity, + slot, + }); + } + } + + // Pin slots mean it can be nothing else + continue; + } + + // Check if its a tunnel, if so, go to the forwarded item + const tunnelComp = entity.components.WireTunnel; + if (tunnelComp) { + if (visitedTunnels.has(entity.uid)) { + continue; + } + + const staticComp = entity.components.StaticMapEntity; + + if ( + !tunnelComp.multipleDirections && + !( + direction === staticComp.localDirectionToWorld(enumDirection.top) || + direction === staticComp.localDirectionToWorld(enumDirection.bottom) + ) + ) { + // It's a coating, and it doesn't connect here + continue; + } + + // Compute where this tunnel connects to + const forwardedTile = staticComp.origin.add(offset); + VERBOSE_WIRES && + logger.log( + " Found tunnel", + entity.uid, + "at", + tile, + "-> forwarding to", + forwardedTile + ); + + // Figure out which entities are connected + const connectedContents = this.root.map.getLayersContentsMultipleXY( + forwardedTile.x, + forwardedTile.y + ); + + // Attach the entities and the tile we search at, because it may change + for (let h = 0; h < connectedContents.length; ++h) { + contents.push({ + entity: connectedContents[h], + tile: forwardedTile, + }); + } + + // Add the tunnel to the network + if (tunnelComp.linkedNetworks.indexOf(network) < 0) { + tunnelComp.linkedNetworks.push(network); + } + if (network.tunnels.indexOf(entity) < 0) { + network.tunnels.push(entity); + } + + // Remember this tunnel + visitedTunnels.add(entity.uid); + } + } + } + + VERBOSE_WIRES && logger.log(" -> Found", result.length); + + return result; + } + + /** + * Updates the wires network + */ + update() { + this.staleArea.update(); + + if (this.needsRecompute) { + this.recomputeWiresNetwork(); + } + + // Re-compute values of all networks + for (let i = 0; i < this.networks.length; ++i) { + const network = this.networks[i]; + + // Reset conflicts + network.valueConflict = false; + + // Aggregate values of all senders + const senders = network.providers; + let value = null; + for (let k = 0; k < senders.length; ++k) { + const senderSlot = senders[k]; + const slotValue = senderSlot.slot.value; + + // The first sender can just put in his value + if (!value) { + value = slotValue; + continue; + } + + // If the slot is empty itself, just skip it + if (!slotValue) { + continue; + } + + // If there is already an value, compare if it matches -> + // otherwise there is a conflict + if (value.equals(slotValue)) { + // All good + continue; + } + + // There is a conflict, this means the value will be null anyways + network.valueConflict = true; + break; + } + + // Assign value + if (network.valueConflict) { + network.currentValue = null; + } else { + network.currentValue = value; + } + } + } + + /** + * Returns the given tileset and opacity + * @param {WireComponent} wireComp + * @returns {{ spriteSet: Object, opacity: number}} + */ + getSpriteSetAndOpacityForWire(wireComp) { + if (!wireComp.linkedNetwork) { + // There is no network, it's empty + return { + spriteSet: this.wireSprites.regular, + opacity: 0.3, + }; + } + + const network = wireComp.linkedNetwork; + if (network.valueConflict) { + // There is a conflict + return { + spriteSet: this.wireSprites.conflict, + opacity: 1, + }; + } + + const value = network.currentValue; + if (!value) { + // There is no value stored + return { + spriteSet: this.wireSprites.regular, + opacity: 0.3, + }; + } + + const valueType = value.getItemType(); + if (valueType === "shape") { + return { + spriteSet: this.wireSprites.shape, + opacity: 1, + }; + } else if (valueType === "color") { + return { + spriteSet: this.wireSprites.color, + opacity: 1, + }; + } else if (valueType === "boolean") { + return { + spriteSet: this.wireSprites.regular, + opacity: /** @type {BooleanItem} */ (value).value ? 1 : 0.5, + }; + } else { + assertAlways(false, "Unknown item type: " + valueType); + } + + return { + spriteSet: this.wireSprites.regular, + opacity: 1, + }; + } + + /** + * Draws a given chunk + * @param {import("../../core/draw_utils").DrawParameters} parameters + * @param {MapChunkView} chunk + */ + drawChunk(parameters, chunk) { + const contents = chunk.wireContents; + for (let y = 0; y < globalConfig.mapChunkSize; ++y) { + for (let x = 0; x < globalConfig.mapChunkSize; ++x) { + const entity = contents[x][y]; + if (entity && entity.components.Wire) { + const wireComp = entity.components.Wire; + const wireType = wireComp.type; + + const { opacity, spriteSet } = this.getSpriteSetAndOpacityForWire(wireComp); + + const sprite = spriteSet[wireType]; + + assert(sprite, "Unknown wire type: " + wireType); + const staticComp = entity.components.StaticMapEntity; + parameters.context.globalAlpha = opacity; + staticComp.drawSpriteOnFullEntityBounds(parameters, sprite, 0); + parameters.context.globalAlpha = 1; + + if (G_IS_DEV && globalConfig.debug.renderWireRotations) { + parameters.context.fillStyle = "red"; + parameters.context.font = "5px Tahoma"; + parameters.context.fillText( + "" + staticComp.originalRotation, + staticComp.origin.x * globalConfig.tileSize, + staticComp.origin.y * globalConfig.tileSize + 5 + ); + + parameters.context.fillStyle = "rgba(255, 0, 0, 0.2)"; + if (staticComp.originalRotation % 180 === 0) { + parameters.context.fillRect( + (staticComp.origin.x + 0.5) * globalConfig.tileSize, + staticComp.origin.y * globalConfig.tileSize, + 3, + globalConfig.tileSize + ); + } else { + parameters.context.fillRect( + staticComp.origin.x * globalConfig.tileSize, + (staticComp.origin.y + 0.5) * globalConfig.tileSize, + globalConfig.tileSize, + 3 + ); + } + } + } + + // DEBUG Rendering + if (G_IS_DEV && globalConfig.debug.renderWireNetworkInfos) { + if (entity) { + const staticComp = entity.components.StaticMapEntity; + const wireComp = entity.components.Wire; + + // Draw network info for wires + if (wireComp && wireComp.linkedNetwork) { + parameters.context.fillStyle = "red"; + parameters.context.font = "5px Tahoma"; + parameters.context.fillText( + "W" + wireComp.linkedNetwork.uid, + (staticComp.origin.x + 0.5) * globalConfig.tileSize, + (staticComp.origin.y + 0.5) * globalConfig.tileSize + ); + } + } + } + } + } + } + + /** + * Returns whether this entity is relevant for the wires network + * @param {Entity} entity + */ + isEntityRelevantForWires(entity) { + return entity.components.Wire || entity.components.WiredPins || entity.components.WireTunnel; + } + + /** + * + * @param {Entity} entity + */ + queuePlacementUpdate(entity) { + if (!this.root.gameInitialized) { + return; + } + + if (!this.isEntityRelevantForWires(entity)) { + return; + } + + const staticComp = entity.components.StaticMapEntity; + if (!staticComp) { + return; + } + + // Invalidate affected area + const originalRect = staticComp.getTileSpaceBounds(); + const affectedArea = originalRect.expandedInAllDirections(1); + this.staleArea.invalidate(affectedArea); + } + + /** + * Updates the wire placement after an entity has been added / deleted + * @param {Rectangle} affectedArea + */ + updateSurroundingWirePlacement(affectedArea) { + const metaWire = gMetaBuildingRegistry.findByClass(MetaWireBuilding); + + for (let x = affectedArea.x; x < affectedArea.right(); ++x) { + for (let y = affectedArea.y; y < affectedArea.bottom(); ++y) { + const targetEntities = this.root.map.getLayersContentsMultipleXY(x, y); + for (let i = 0; i < targetEntities.length; ++i) { + const targetEntity = targetEntities[i]; + + const targetWireComp = targetEntity.components.Wire; + const targetStaticComp = targetEntity.components.StaticMapEntity; + + if (!targetWireComp) { + // Not a wire + continue; + } + + const { + rotation, + rotationVariant, + } = metaWire.computeOptimalDirectionAndRotationVariantAtTile({ + root: this.root, + tile: new Vector(x, y), + rotation: targetStaticComp.originalRotation, + variant: defaultBuildingVariant, + layer: targetEntity.layer, + }); + + // Compute delta to see if anything changed + const newType = arrayWireRotationVariantToType[rotationVariant]; + + if (targetStaticComp.rotation !== rotation || newType !== targetWireComp.type) { + // Change stuff + targetStaticComp.rotation = rotation; + metaWire.updateVariants(targetEntity, rotationVariant, defaultBuildingVariant); + + // Update code as well + targetStaticComp.code = getCodeFromBuildingData( + metaWire, + defaultBuildingVariant, + rotationVariant + ); + + // Make sure the chunks know about the update + this.root.signals.entityChanged.dispatch(targetEntity); + } + } + } + } + } +} diff --git a/src/js/game/systems/wired_pins.js b/src/js/game/systems/wired_pins.js index 853568ef..02e84372 100644 --- a/src/js/game/systems/wired_pins.js +++ b/src/js/game/systems/wired_pins.js @@ -1,27 +1,21 @@ import { globalConfig } from "../../core/config"; import { DrawParameters } from "../../core/draw_parameters"; import { Loader } from "../../core/loader"; -import { Vector } from "../../core/vector"; +import { Vector, enumDirectionToAngle } from "../../core/vector"; import { enumPinSlotType, WiredPinsComponent } from "../components/wired_pins"; import { Entity } from "../entity"; import { GameSystemWithFilter } from "../game_system_with_filter"; -import { enumLayer } from "../root"; import { STOP_PROPAGATION } from "../../core/signal"; import { drawRotatedSprite } from "../../core/draw_utils"; +import { GLOBAL_APP } from "../../core/globals"; export class WiredPinsSystem extends GameSystemWithFilter { constructor(root) { super(root, [WiredPinsComponent]); this.pinSprites = { - [enumPinSlotType.positiveEnergyEjector]: Loader.getSprite("sprites/wires/pin_positive_eject.png"), - [enumPinSlotType.positiveEnergyAcceptor]: Loader.getSprite( - "sprites/wires/pin_positive_accept.png" - ), - [enumPinSlotType.negativeEnergyEjector]: Loader.getSprite("sprites/wires/pin_negative_eject.png"), - [enumPinSlotType.negativeEnergyAcceptor]: Loader.getSprite( - "sprites/wires/pin_negative_accept.png" - ), + [enumPinSlotType.logicalEjector]: Loader.getSprite("sprites/wires/logical_ejector.png"), + [enumPinSlotType.logicalAcceptor]: Loader.getSprite("sprites/wires/logical_acceptor.png"), }; this.root.signals.prePlacementCheck.add(this.prePlacementCheck, this); @@ -43,7 +37,7 @@ export class WiredPinsSystem extends GameSystemWithFilter { // If this entity is placed on the wires layer, make sure we don't // place it above a pin - if (entity.layer === enumLayer.wires) { + if (entity.layer === "wires") { for (let x = rect.x; x < rect.x + rect.w; ++x) { for (let y = rect.y; y < rect.y + rect.h; ++y) { // Find which entities are in same tiles of both layers @@ -58,7 +52,7 @@ export class WiredPinsSystem extends GameSystemWithFilter { continue; } - if (otherEntity.components.ReplaceableMapEntity) { + if (staticComp.getMetaBuilding().getIsReplaceable()) { // Don't mind here, even if there would be a collision we // could replace it continue; @@ -108,11 +102,13 @@ export class WiredPinsSystem extends GameSystemWithFilter { } // Check if there is any entity on that tile (Wired pins are always on the wires layer) - const collidingEntity = this.root.map.getLayerContentXY(worldPos.x, worldPos.y, enumLayer.wires); + const collidingEntity = this.root.map.getLayerContentXY(worldPos.x, worldPos.y, "wires"); // If there's an entity, and it can't get removed -> That's a collision - if (collidingEntity && !collidingEntity.components.ReplaceableMapEntity) { - return true; + if (collidingEntity) { + if (!collidingEntity.components.StaticMapEntity.getMetaBuilding().getIsReplaceable()) { + return true; + } } } return false; @@ -133,10 +129,10 @@ export class WiredPinsSystem extends GameSystemWithFilter { for (let i = 0; i < pinsComp.slots.length; ++i) { const slot = pinsComp.slots[i]; const worldPos = entity.components.StaticMapEntity.localTileToWorld(slot.pos); - const collidingEntity = this.root.map.getLayerContentXY(worldPos.x, worldPos.y, enumLayer.wires); + const collidingEntity = this.root.map.getLayerContentXY(worldPos.x, worldPos.y, "wires"); if (collidingEntity) { assertAlways( - collidingEntity.components.ReplaceableMapEntity, + collidingEntity.components.StaticMapEntity.getMetaBuilding().getIsReplaceable(), "Tried to replace non-repleaceable entity for pins" ); if (!this.root.logic.tryDeleteBuilding(collidingEntity)) { @@ -172,17 +168,44 @@ export class WiredPinsSystem extends GameSystemWithFilter { const tile = staticComp.localTileToWorld(slot.pos); const worldPos = tile.toWorldSpaceCenterOfTile(); + const effectiveRotation = Math.radians( + staticComp.rotation + enumDirectionToAngle[slot.direction] + ); - drawRotatedSprite({ - parameters, - sprite: this.pinSprites[slot.type], - x: worldPos.x, - y: worldPos.y, - angle: Math.radians(staticComp.rotation), - size: globalConfig.tileSize, - offsetX: 0, - offsetY: 0, - }); + if (staticComp.getMetaBuilding().getRenderPins()) { + drawRotatedSprite({ + parameters, + sprite: this.pinSprites[slot.type], + x: worldPos.x, + y: worldPos.y, + angle: effectiveRotation, + size: globalConfig.tileSize + 2, + offsetX: 0, + offsetY: 0, + }); + } + + // Draw contained item to visualize whats emitted + const value = slot.value; + if (value) { + const offset = new Vector(0, -9).rotated(effectiveRotation); + value.drawCentered(worldPos.x + offset.x, worldPos.y + offset.y, parameters, 9); + } + + // Debug view + if (G_IS_DEV && globalConfig.debug.renderWireNetworkInfos) { + const offset = new Vector(0, -10).rotated(effectiveRotation); + const network = slot.linkedNetwork; + parameters.context.fillStyle = "blue"; + parameters.context.font = "5px Tahoma"; + parameters.context.textAlign = "center"; + parameters.context.fillText( + network ? "S" + network.uid : "???", + (tile.x + 0.5) * globalConfig.tileSize + offset.x, + (tile.y + 0.5) * globalConfig.tileSize + offset.y + ); + parameters.context.textAlign = "left"; + } } } } diff --git a/src/js/game/themes/dark.json b/src/js/game/themes/dark.json index 626efa19..39debd98 100644 --- a/src/js/game/themes/dark.json +++ b/src/js/game/themes/dark.json @@ -34,9 +34,9 @@ }, "wires": { - "pins": { - "energyEjector": "#c425d7" - } + "overlayColor": "rgba(97, 161, 152, 0.75)", + "previewColor": "rgb(97, 161, 152, 0.5)", + "highlightColor": "rgba(0, 0, 255, 0.5)" } }, diff --git a/src/js/game/themes/light.json b/src/js/game/themes/light.json index 21599585..28742282 100644 --- a/src/js/game/themes/light.json +++ b/src/js/game/themes/light.json @@ -35,9 +35,9 @@ }, "wires": { - "pins": { - "energyEjector": "#c425d7" - } + "overlayColor": "rgba(97, 161, 152, 0.75)", + "previewColor": "rgb(97, 161, 152, 0.4)", + "highlightColor": "rgba(72, 137, 255, 0.8)" } }, diff --git a/src/js/game/time/game_time.js b/src/js/game/time/game_time.js index 7d0c310d..9b418d4c 100644 --- a/src/js/game/time/game_time.js +++ b/src/js/game/time/game_time.js @@ -153,11 +153,6 @@ export class GameTime extends BasicSerializableObject { ); break; } - - // If we queued async tasks, perform them next frame and do not update anymore - if (this.root.hud.parts.processingOverlay.hasTasks()) { - break; - } } } diff --git a/src/js/globals.d.ts b/src/js/globals.d.ts index cc6118ca..51e4a2c3 100644 --- a/src/js/globals.d.ts +++ b/src/js/globals.d.ts @@ -131,22 +131,24 @@ declare interface Math { degrees(number): number; } +declare type Class = new (...args: any[]) => T; + declare interface String { padStart(size: number, fill?: string): string; padEnd(size: number, fill: string): string; } declare interface FactoryTemplate { - entries: Array T>; + entries: Array>; entryIds: Array; idToEntry: any; getId(): string; getAllIds(): Array; - register(entry: new (...args: any[]) => T): void; + register(entry: Class): void; hasId(id: string): boolean; - findById(id: string): new (...args: any[]) => T; - getEntries(): Array T>; + findById(id: string): Class; + getEntries(): Array>; getNumEntries(): number; } @@ -156,10 +158,10 @@ declare interface SingletonFactoryTemplate { getId(): string; getAllIds(): Array; - register(classHandle: new (...args: any[]) => T): void; + register(classHandle: Class): void; hasId(id: string): boolean; findById(id: string): T; - findByClass(classHandle: new (...args: any[]) => T): T; + findByClass(classHandle: Class): T; getEntries(): Array; getNumEntries(): number; } @@ -191,6 +193,9 @@ declare interface TypedSignal> { removeAll(); } +declare type Layer = "regular" | "wires"; +declare type ItemType = "shape" | "color" | "boolean"; + declare module "worker-loader?inline=true&fallback=false!*" { class WebpackWorker extends Worker { constructor(); diff --git a/src/js/platform/browser/game_analytics.js b/src/js/platform/browser/game_analytics.js index 73da3696..7336ffd9 100644 --- a/src/js/platform/browser/game_analytics.js +++ b/src/js/platform/browser/game_analytics.js @@ -85,10 +85,9 @@ export class ShapezGameAnalytics extends GameAnalyticsInterface { * @returns {Promise} */ sendToApi(endpoint, data) { - return Promise.race([ - new Promise((resolve, reject) => { - setTimeout(() => reject("Request to " + endpoint + " timed out"), 20000); - }), + return new Promise((resolve, reject) => { + const timeout = setTimeout(() => reject("Request to " + endpoint + " timed out"), 20000); + fetch(analyticsUrl + endpoint, { method: "POST", mode: "cors", @@ -103,13 +102,19 @@ export class ShapezGameAnalytics extends GameAnalyticsInterface { body: JSON.stringify(data), }) .then(res => { + clearTimeout(timeout); if (!res.ok || res.status !== 200) { - throw new Error("Fetch error: Bad status " + res.status); + reject("Fetch error: Bad status " + res.status); + } else { + return res.json(); } - return res; }) - .then(res => res.json()), - ]); + .then(resolve) + .catch(reason => { + clearTimeout(timeout); + reject(reason); + }); + }); } /** diff --git a/src/js/platform/browser/wrapper.js b/src/js/platform/browser/wrapper.js index 726f843b..56705025 100644 --- a/src/js/platform/browser/wrapper.js +++ b/src/js/platform/browser/wrapper.js @@ -82,7 +82,7 @@ export class PlatformWrapperImplBrowser extends PlatformWrapperInterface { return new Promise(resolve => { logger.log("Detecting storage"); - if (!window.indexedDB || G_IS_DEV) { + if (!window.indexedDB) { logger.log("Indexed DB not supported"); this.app.storage = new StorageImplBrowser(this.app); resolve(); diff --git a/src/js/platform/game_analytics.js b/src/js/platform/game_analytics.js index ea6aa293..765b2d67 100644 --- a/src/js/platform/game_analytics.js +++ b/src/js/platform/game_analytics.js @@ -1,8 +1,6 @@ -/* typehints:start */ -import { Application } from "../application"; -import { ShapeDefinition } from "../game/shape_definition"; -import { Savegame } from "../savegame/savegame"; -/* typehints:end */ +/** + * @typedef {import("../application").Application} Application + */ export class GameAnalyticsInterface { constructor(app) { diff --git a/src/js/platform/sound.js b/src/js/platform/sound.js index 60d472f8..0d509bee 100644 --- a/src/js/platform/sound.js +++ b/src/js/platform/sound.js @@ -28,7 +28,7 @@ export const SOUNDS = { }; export const MUSIC = { - theme: "theme", + theme: G_IS_STANDALONE ? "theme-full" : "theme-short", menu: "menu", }; diff --git a/src/js/platform/wrapper.js b/src/js/platform/wrapper.js index 9fee5b3a..9c35a8e4 100644 --- a/src/js/platform/wrapper.js +++ b/src/js/platform/wrapper.js @@ -66,7 +66,7 @@ export class PlatformWrapperInterface { * @returns {number} */ getMinimumZoom() { - return 0.2 * this.getScreenScale(); + return 0.1 * this.getScreenScale(); } /** @@ -74,7 +74,7 @@ export class PlatformWrapperInterface { * @returns {number} */ getMaximumZoom() { - return 4 * this.getScreenScale(); + return 3.5 * this.getScreenScale(); } getScreenScale() { diff --git a/src/js/profile/application_settings.js b/src/js/profile/application_settings.js index 50c34e0e..f3f61c4a 100644 --- a/src/js/profile/application_settings.js +++ b/src/js/profile/application_settings.js @@ -19,6 +19,7 @@ const logger = createLogger("application_settings"); export const enumCategories = { general: "general", userInterface: "userInterface", + performance: "performance", advanced: "advanced", }; @@ -147,20 +148,6 @@ export const allApplicationSettings = [ (app, id) => app.updateAfterUiScaleChanged(), }), - new BoolSetting( - "fullscreen", - enumCategories.general, - /** - * @param {Application} app - */ - (app, value) => { - if (app.platformWrapper.getSupportsFullscreen()) { - app.platformWrapper.setFullscreen(value); - } - }, - !IS_DEMO - ), - new BoolSetting( "soundsMuted", enumCategories.general, @@ -178,6 +165,20 @@ export const allApplicationSettings = [ (app, value) => app.sound.setMusicMuted(value) ), + new BoolSetting( + "fullscreen", + enumCategories.general, + /** + * @param {Application} app + */ + (app, value) => { + if (app.platformWrapper.getSupportsFullscreen()) { + app.platformWrapper.setFullscreen(value); + } + }, + !IS_DEMO + ), + new BoolSetting( "enableColorBlindHelper", enumCategories.general, @@ -187,7 +188,6 @@ export const allApplicationSettings = [ (app, value) => null ), - // GAME new BoolSetting("offerHints", enumCategories.userInterface, (app, value) => {}), new EnumSetting("theme", { @@ -220,16 +220,6 @@ export const allApplicationSettings = [ (app, id) => null, }), - new EnumSetting("refreshRate", { - options: ["60", "100", "120", "144", "165", "250", G_IS_DEV ? "10" : "500"], - valueGetter: rate => rate, - textGetter: rate => rate + " Hz", - category: enumCategories.advanced, - restartRequired: false, - changeCb: (app, id) => {}, - enabled: !IS_DEMO, - }), - new EnumSetting("scrollWheelSensitivity", { options: scrollWheelSensitivities.sort((a, b) => a.scale - b.scale), valueGetter: scale => scale.id, @@ -258,6 +248,20 @@ export const allApplicationSettings = [ new BoolSetting("compactBuildingInfo", enumCategories.userInterface, (app, value) => {}), new BoolSetting("disableCutDeleteWarnings", enumCategories.advanced, (app, value) => {}), new BoolSetting("rotationByBuilding", enumCategories.advanced, (app, value) => {}), + + new EnumSetting("refreshRate", { + options: ["60", "75", "100", "120", "144", "165", "250", "500"], + valueGetter: rate => rate, + textGetter: rate => rate + " Hz", + category: enumCategories.performance, + restartRequired: false, + changeCb: (app, id) => {}, + enabled: !IS_DEMO, + }), + + new BoolSetting("lowQualityMapResources", enumCategories.performance, (app, value) => {}), + new BoolSetting("disableTileGrid", enumCategories.performance, (app, value) => {}), + new BoolSetting("lowQualityTextures", enumCategories.performance, (app, value) => {}), ]; export function getApplicationSettingById(id) { @@ -288,6 +292,10 @@ class SettingsStorage { this.enableColorBlindHelper = false; + this.lowQualityMapResources = false; + this.disableTileGrid = false; + this.lowQualityTextures = false; + /** * @type {Object.} */ @@ -487,7 +495,7 @@ export class ApplicationSettings extends ReadWriteProxy { } getCurrentVersion() { - return 18; + return 21; } /** @param {{settings: SettingsStorage, version: number}} data */ @@ -565,6 +573,21 @@ export class ApplicationSettings extends ReadWriteProxy { data.version = 18; } + if (data.version < 19) { + data.settings.lowQualityMapResources = false; + data.version = 19; + } + + if (data.version < 20) { + data.settings.disableTileGrid = false; + data.version = 20; + } + + if (data.version < 21) { + data.settings.lowQualityTextures = false; + data.version = 21; + } + return ExplainedResult.good(); } } diff --git a/src/js/savegame/savegame.js b/src/js/savegame/savegame.js index 1db813d7..2a7102a9 100644 --- a/src/js/savegame/savegame.js +++ b/src/js/savegame/savegame.js @@ -1,8 +1,3 @@ -/* typehints:start */ -import { Application } from "../application"; -import { GameRoot } from "../game/root"; -/* typehints:end */ - import { ReadWriteProxy } from "../core/read_write_proxy"; import { ExplainedResult } from "../core/explained_result"; import { SavegameSerializer } from "./savegame_serializer"; @@ -18,20 +13,29 @@ import { SavegameInterface_V1005 } from "./schemas/1005"; const logger = createLogger("savegame"); +/** + * @typedef {import("../application").Application} Application + * @typedef {import("../game/root").GameRoot} GameRoot + * @typedef {import("./savegame_typedefs").SavegameData} SavegameData + * @typedef {import("./savegame_typedefs").SavegameMetadata} SavegameMetadata + * @typedef {import("./savegame_typedefs").SavegameStats} SavegameStats + * @typedef {import("./savegame_typedefs").SerializedGame} SerializedGame + */ + export class Savegame extends ReadWriteProxy { /** * * @param {Application} app * @param {object} param0 * @param {string} param0.internalId - * @param {import("./savegame_manager").SavegameMetadata} param0.metaDataRef Handle to the meta data + * @param {SavegameMetadata} param0.metaDataRef Handle to the meta data */ constructor(app, { internalId, metaDataRef }) { super(app, "savegame-" + internalId + ".bin"); this.internalId = internalId; this.metaDataRef = metaDataRef; - /** @type {import("./savegame_typedefs").SavegameData} */ + /** @type {SavegameData} */ this.currentData = this.getDefaultData(); assert( @@ -65,7 +69,7 @@ export class Savegame extends ReadWriteProxy { /** * Returns the savegames default data - * @returns {import("./savegame_typedefs").SavegameData} + * @returns {SavegameData} */ getDefaultData() { return { @@ -78,7 +82,7 @@ export class Savegame extends ReadWriteProxy { /** * Migrates the savegames data - * @param {import("./savegame_typedefs").SavegameData} data + * @param {SavegameData} data */ migrate(data) { if (data.version < 1000) { @@ -115,7 +119,7 @@ export class Savegame extends ReadWriteProxy { /** * Verifies the savegames data - * @param {import("./savegame_typedefs").SavegameData} data + * @param {SavegameData} data */ verify(data) { if (!data.dump) { @@ -140,7 +144,7 @@ export class Savegame extends ReadWriteProxy { } /** * Returns the statistics of the savegame - * @returns {import("./savegame_typedefs").SavegameStats} + * @returns {SavegameStats} */ getStatistics() { return this.currentData.stats; @@ -163,7 +167,7 @@ export class Savegame extends ReadWriteProxy { /** * Returns the current game dump - * @returns {import("./savegame_typedefs").SerializedGame} + * @returns {SerializedGame} */ getCurrentDump() { return this.currentData.dump; diff --git a/src/js/savegame/savegame_compressor.js b/src/js/savegame/savegame_compressor.js index 30c28879..bc14baf7 100644 --- a/src/js/savegame/savegame_compressor.js +++ b/src/js/savegame/savegame_compressor.js @@ -90,9 +90,6 @@ function compressObjectInternal(obj, keys = [], values = []) { } export function compressObject(obj) { - if (G_IS_DEV) { - return obj; - } const keys = []; const values = []; const data = compressObjectInternal(obj, keys, values); diff --git a/src/js/savegame/savegame_manager.js b/src/js/savegame/savegame_manager.js index e3052806..42e56734 100644 --- a/src/js/savegame/savegame_manager.js +++ b/src/js/savegame/savegame_manager.js @@ -7,31 +7,21 @@ const logger = createLogger("savegame_manager"); const Rusha = require("rusha"); +/** + * @typedef {import("./savegame_typedefs").SavegamesData} SavegamesData + * @typedef {import("./savegame_typedefs").SavegameMetadata} SavegameMetadata + */ + /** @enum {string} */ export const enumLocalSavegameStatus = { offline: "offline", synced: "synced", }; -/** - * @typedef {{ - * lastUpdate: number, - * version: number, - * internalId: string, - * level: number - * }} SavegameMetadata - * - * @typedef {{ - * version: number, - * savegames: Array - * }} SavegamesData - */ - export class SavegameManager extends ReadWriteProxy { constructor(app) { super(app, "savegames.bin"); - /** @type {SavegamesData} */ this.currentData = this.getDefaultData(); } diff --git a/src/js/savegame/savegame_serializer.js b/src/js/savegame/savegame_serializer.js index eff802a0..92db738b 100644 --- a/src/js/savegame/savegame_serializer.js +++ b/src/js/savegame/savegame_serializer.js @@ -1,18 +1,20 @@ -/* typehints:start */ -import { Component } from "../game/component"; -import { GameRoot } from "../game/root"; -/* typehints:end */ - import { ExplainedResult } from "../core/explained_result"; import { createLogger } from "../core/logging"; -// import { BuildingComponent } from "../components/impl/building"; import { gComponentRegistry } from "../core/global_registries"; import { SerializerInternal } from "./serializer_internal"; +/** + * @typedef {import("../game/component").Component} Component + * @typedef {import("../game/component").StaticComponent} StaticComponent + * @typedef {import("../game/entity").Entity} Entity + * @typedef {import("../game/root").GameRoot} GameRoot + * @typedef {import("../savegame/savegame_typedefs").SerializedGame} SerializedGame + */ + const logger = createLogger("savegame_serializer"); /** - * Allows to serialize a savegame + * Serializes a savegame */ export class SavegameSerializer { constructor() { @@ -26,7 +28,7 @@ export class SavegameSerializer { * @returns {object} */ generateDumpFromGameRoot(root, sanityChecks = true) { - // Now store generic savegame payload + /** @type {SerializedGame} */ const data = { camera: root.camera.serialize(), time: root.time.serialize(), @@ -35,11 +37,10 @@ export class SavegameSerializer { hubGoals: root.hubGoals.serialize(), pinnedShapes: root.hud.parts.pinnedShapes.serialize(), waypoints: root.hud.parts.waypoints.serialize(), + entities: this.internal.serializeEntityArray(root.entityMgr.entities), beltPaths: root.systemMgr.systems.belt.serializePaths(), }; - data.entities = this.internal.serializeEntityArray(root.entityMgr.entities); - if (!G_IS_RELEASE) { if (sanityChecks) { // Sanity check @@ -55,7 +56,7 @@ export class SavegameSerializer { /** * Verifies if there are logical errors in the savegame - * @param {object} savegame + * @param {SerializedGame} savegame * @returns {ExplainedResult} */ verifyLogicalErrors(savegame) { @@ -66,47 +67,44 @@ export class SavegameSerializer { const seenUids = []; // Check for duplicate UIDS - for (const entityListId in savegame.entities) { - for (let i = 0; i < savegame.entities[entityListId].length; ++i) { - const list = savegame.entities[entityListId][i]; - for (let k = 0; k < list.length; ++k) { - const entity = list[k]; - const uid = entity.uid; - if (!Number.isInteger(uid)) { - return ExplainedResult.bad("Entity has invalid uid: " + uid); - } - if (seenUids.indexOf(uid) >= 0) { - return ExplainedResult.bad("Duplicate uid " + uid); - } - seenUids.push(uid); + for (let i = 0; i < savegame.entities.length; ++i) { + /** @type {Entity} */ + const entity = savegame.entities[i]; - // Verify components - if (!entity.components) { - return ExplainedResult.bad( - "Entity is missing key 'components': " + JSON.stringify(entity) - ); - } - const components = entity.components; - for (const componentId in components) { - // Verify component data - const componentData = components[componentId]; - const componentClass = gComponentRegistry.findById(componentId); + const uid = entity.uid; + if (!Number.isInteger(uid)) { + return ExplainedResult.bad("Entity has invalid uid: " + uid); + } + if (seenUids.indexOf(uid) >= 0) { + return ExplainedResult.bad("Duplicate uid " + uid); + } + seenUids.push(uid); - // Check component id is known - if (!componentClass) { - return ExplainedResult.bad("Unknown component id: " + componentId); - } + // Verify components + if (!entity.components) { + return ExplainedResult.bad("Entity is missing key 'components': " + JSON.stringify(entity)); + } - // Check component data is ok - const componentVerifyError = /** @type {typeof Component} */ (componentClass).verify( - componentData - ); - if (componentVerifyError) { - return ExplainedResult.bad( - "Component " + componentId + " has invalid data: " + componentVerifyError - ); - } - } + const components = entity.components; + for (const componentId in components) { + const componentClass = gComponentRegistry.findById(componentId); + + // Check component id is known + if (!componentClass) { + return ExplainedResult.bad("Unknown component id: " + componentId); + } + + // Verify component data + const componentData = components[componentId]; + const componentVerifyError = /** @type {StaticComponent} */ (componentClass).verify( + componentData + ); + + // Check component data is ok + if (componentVerifyError) { + return ExplainedResult.bad( + "Component " + componentId + " has invalid data: " + componentVerifyError + ); } } } @@ -116,7 +114,7 @@ export class SavegameSerializer { /** * Tries to load the savegame from a given dump - * @param {import("./savegame_typedefs").SerializedGame} savegame + * @param {SerializedGame} savegame * @param {GameRoot} root * @returns {ExplainedResult} */ diff --git a/src/js/savegame/savegame_typedefs.js b/src/js/savegame/savegame_typedefs.js index 642865cd..f5bb08c2 100644 --- a/src/js/savegame/savegame_typedefs.js +++ b/src/js/savegame/savegame_typedefs.js @@ -1,15 +1,8 @@ -import { Entity } from "../game/entity"; - -/** - * @typedef {{ - * }} SavegameStats - */ - /** + * @typedef {import("../game/entity").Entity} Entity + * + * @typedef {{}} SavegameStats * - */ - -/** * @typedef {{ * camera: any, * time: any, @@ -21,13 +14,25 @@ import { Entity } from "../game/entity"; * entities: Array, * beltPaths: Array * }} SerializedGame - */ - -/** + * * @typedef {{ * version: number, * dump: SerializedGame, * stats: SavegameStats, * lastUpdate: number, * }} SavegameData + * + * @typedef {{ + * lastUpdate: number, + * version: number, + * internalId: string, + * level: number + * }} SavegameMetadata + * + * @typedef {{ + * version: number, + * savegames: Array + * }} SavegamesData */ + +export default {}; diff --git a/src/js/savegame/schemas/1001.js b/src/js/savegame/schemas/1001.js index 3af5eebe..af86b09d 100644 --- a/src/js/savegame/schemas/1001.js +++ b/src/js/savegame/schemas/1001.js @@ -1,6 +1,7 @@ import { SavegameInterface_V1000 } from "./1000.js"; import { createLogger } from "../../core/logging.js"; import { T } from "../../translations.js"; +import { TypeVector, TypeNumber, TypeString, TypeNullable } from "../serialization_data_types.js"; const schema = require("./1001.json"); @@ -43,6 +44,25 @@ export class SavegameInterface_V1001 extends SavegameInterface_V1000 { for (let i = 0; i < entities.length; ++i) { const entity = entities[i]; + /** + * @typedef {{ + * origin: TypeVector, + * tileSize: TypeVector, + * rotation: TypeNumber, + * originalRotation: TypeNumber, + * spriteKey?: string, + * blueprintSpriteKey: string, + * silhouetteColor: string + * }} OldStaticMapEntity + */ + + // Here we mock the old type of the StaticMapEntity before the change to using + // a building ID based system (see building_codes.js) to stop the linter from + // complaining that the type doesn't have the properties. + // The ignored error is the error that the types do not overlap. In the case + // of a v1000 save though, the data will match the mocked type above. + /** @type OldStaticMapEntity **/ + // @ts-ignore const staticComp = entity.components.StaticMapEntity; const beltComp = entity.components.Belt; if (staticComp) { diff --git a/src/js/savegame/schemas/1002.js b/src/js/savegame/schemas/1002.js index 92dadfc1..866bc1e8 100644 --- a/src/js/savegame/schemas/1002.js +++ b/src/js/savegame/schemas/1002.js @@ -29,7 +29,9 @@ export class SavegameInterface_V1002 extends SavegameInterface_V1001 { const entity = entities[i]; const beltComp = entity.components.Belt; const ejectorComp = entity.components.ItemEjector; + if (beltComp && ejectorComp) { + // @ts-ignore ejectorComp.instantEject = true; } } diff --git a/src/js/savegame/serialization.js b/src/js/savegame/serialization.js index aea2f944..9f998a0f 100644 --- a/src/js/savegame/serialization.js +++ b/src/js/savegame/serialization.js @@ -1,8 +1,11 @@ +import { createLogger } from "../core/logging"; import { BaseDataType, TypeArray, TypeBoolean, TypeClass, + TypeClassData, + TypeClassFromMetaclass, TypeClassId, TypeEntity, TypeEntityWeakref, @@ -17,12 +20,9 @@ import { TypePositiveInteger, TypePositiveNumber, TypeString, - TypeVector, - TypeClassFromMetaclass, - TypeClassData, TypeStructuredObject, + TypeVector, } from "./serialization_data_types"; -import { createLogger } from "../core/logging"; const logger = createLogger("serialization"); @@ -69,9 +69,10 @@ export const types = { /** * @param {FactoryTemplate<*>} registry + * @param {(GameRoot, any) => object=} resolver */ - obj(registry) { - return new TypeClass(registry); + obj(registry, resolver = null) { + return new TypeClass(registry, resolver); }, /** @@ -190,12 +191,18 @@ export class BasicSerializableObject { ); } - /** @returns {string|void} */ - deserialize(data) { + /** + * @param {any} data + * @param {import("./savegame_serializer").GameRoot} root + * @returns {string|void} + */ + deserialize(data, root = null) { return deserializeSchema( this, /** @type {typeof BasicSerializableObject} */ (this.constructor).getCachedSchema(), - data + data, + null, + root ); } @@ -253,9 +260,10 @@ export function serializeSchema(obj, schema, mergeWith = {}) { * @param {Schema} schema The schema to use * @param {object} data The serialized data * @param {string|void|null=} baseclassErrorResult Convenience, if this is a string error code, do nothing and return it + * @param {import("../game/root").GameRoot=} root Optional game root reference * @returns {string|void} String error code or nothing on success */ -export function deserializeSchema(obj, schema, data, baseclassErrorResult = null) { +export function deserializeSchema(obj, schema, data, baseclassErrorResult = null, root) { if (baseclassErrorResult) { return baseclassErrorResult; } @@ -275,7 +283,7 @@ export function deserializeSchema(obj, schema, data, baseclassErrorResult = null return "Non-nullable entry is null: " + key + " of class " + obj.constructor.name; } - const errorStatus = schema[key].deserializeWithVerify(data[key], obj, key, obj.root); + const errorStatus = schema[key].deserializeWithVerify(data[key], obj, key, obj.root || root); if (errorStatus) { logger.error( "Deserialization failed with error '" + errorStatus + "' on object", diff --git a/src/js/savegame/serialization_data_types.js b/src/js/savegame/serialization_data_types.js index 86b177c1..9fb53bb8 100644 --- a/src/js/savegame/serialization_data_types.js +++ b/src/js/savegame/serialization_data_types.js @@ -4,7 +4,7 @@ import { BasicSerializableObject } from "./serialization"; /* typehints:end */ import { Vector } from "../core/vector"; -import { round4Digits, schemaObject, accessNestedPropertyReverse } from "../core/utils"; +import { round4Digits } from "../core/utils"; export const globalJsonSchemaDefs = {}; /** @@ -28,6 +28,19 @@ export function schemaToJsonSchema(schema) { return jsonSchema; } +/** + * Helper function to create a json schema object + * @param {any} properties + */ +function schemaObject(properties) { + return { + type: "object", + required: Object.keys(properties).slice(), + additionalProperties: false, + properties, + }; +} + /** * Base serialization data type */ @@ -75,23 +88,6 @@ export class BaseDataType { return { $ref: "#/definitions/" + key, }; - - // return this.getAsJsonSchemaUncached(); - // if (!globalJsonSchemaDefs[key]) { - // // schema.$id = key; - // globalJsonSchemaDefs[key] = { - // $id: key, - // definitions: { - // ["d-" + key]: schema - // } - // }; - // } - - // return { - // $ref: key + "#/definitions/d-" + key - // } - - // // return this.getAsJsonSchemaUncached(); } /** @@ -460,7 +456,7 @@ export class TypeEnum extends BaseDataType { */ constructor(enumeration = {}) { super(); - this.availableValues = Object.keys(enumeration); + this.availableValues = Object.values(enumeration); } serialize(value) { @@ -599,10 +595,12 @@ export class TypeClass extends BaseDataType { /** * * @param {FactoryTemplate<*>} registry + * @param {(GameRoot, object) => object} customResolver */ - constructor(registry) { + constructor(registry, customResolver = null) { super(); this.registry = registry; + this.customResolver = customResolver; } serialize(value) { @@ -644,14 +642,23 @@ export class TypeClass extends BaseDataType { * @returns {string|void} String error code or null on success */ deserialize(value, targetObject, targetKey, root) { - const instanceClass = this.registry.findById(value.$); - if (!instanceClass || !instanceClass.prototype) { - return "Invalid class id (runtime-err): " + value.$ + "->" + instanceClass; - } - const instance = Object.create(instanceClass.prototype); - const errorState = instance.deserialize(value.data); - if (errorState) { - return errorState; + let instance; + + if (this.customResolver) { + instance = this.customResolver(root, value); + if (!instance) { + return "Failed to call custom resolver"; + } + } else { + const instanceClass = this.registry.findById(value.$); + if (!instanceClass || !instanceClass.prototype) { + return "Invalid class id (runtime-err): " + value.$ + "->" + instanceClass; + } + instance = Object.create(instanceClass.prototype); + const errorState = instance.deserialize(value.data); + if (errorState) { + return errorState; + } } targetObject[targetKey] = instance; } @@ -875,14 +882,17 @@ export class TypeArray extends BaseDataType { * @returns {string|void} String error code or null on success */ deserialize(value, targetObject, targetKey, root) { - const result = new Array(value.length); + let destination = targetObject[targetKey]; + if (!destination) { + targetObject[targetKey] = destination = new Array(value.length); + } + for (let i = 0; i < value.length; ++i) { - const errorStatus = this.innerType.deserializeWithVerify(value[i], result, i, root); + const errorStatus = this.innerType.deserializeWithVerify(value[i], destination, i, root); if (errorStatus) { return errorStatus; } } - targetObject[targetKey] = result; } getAsJsonSchemaUncached() { @@ -1230,15 +1240,18 @@ export class TypeStructuredObject extends BaseDataType { * @returns {string|void} String error code or null on success */ deserialize(value, targetObject, targetKey, root) { - let result = {}; + let target = targetObject[targetKey]; + if (!target) { + targetObject[targetKey] = target = {}; + } + for (const key in value) { const valueType = this.descriptor[key]; - const errorCode = valueType.deserializeWithVerify(value[key], result, key, root); + const errorCode = valueType.deserializeWithVerify(value[key], target, key, root); if (errorCode) { return errorCode; } } - targetObject[targetKey] = result; } getAsJsonSchemaUncached() { diff --git a/src/js/savegame/serializer_internal.js b/src/js/savegame/serializer_internal.js index 8df6f6e4..ee32dff6 100644 --- a/src/js/savegame/serializer_internal.js +++ b/src/js/savegame/serializer_internal.js @@ -1,6 +1,10 @@ -import { gComponentRegistry } from "../core/global_registries"; +import { createLogger } from "../core/logging"; +import { Vector } from "../core/vector"; +import { getBuildingDataFromCode } from "../game/building_codes"; import { Entity } from "../game/entity"; -import { enumLayer, GameRoot } from "../game/root"; +import { GameRoot } from "../game/root"; + +const logger = createLogger("serializer_internal"); // Internal serializer methods export class SerializerInternal { @@ -37,35 +41,48 @@ export class SerializerInternal { * @param {Entity} payload */ deserializeEntity(root, payload) { - const entity = new Entity(root); - this.deserializeComponents(entity, payload.components); - entity.layer = payload.layer; + const staticData = payload.components.StaticMapEntity; + assert(staticData, "entity has no static data"); - if (!enumLayer[payload.layer]) { - assert(false, "Invalid layer: " + payload.layer); - } + const code = staticData.code; + const data = getBuildingDataFromCode(code); + + const metaBuilding = data.metaInstance; + + const entity = metaBuilding.createEntity({ + root, + origin: Vector.fromSerializedObject(staticData.origin), + rotation: staticData.rotation, + originalRotation: staticData.originalRotation, + rotationVariant: data.rotationVariant, + variant: data.variant, + }); + + entity.uid = payload.uid; + + this.deserializeComponents(root, entity, payload.components); root.entityMgr.registerEntity(entity, payload.uid); - - if (entity.components.StaticMapEntity) { - root.map.placeStaticEntity(entity); - } + root.map.placeStaticEntity(entity); } /////// COMPONENTS //// /** * Deserializes components of an entity + * @param {GameRoot} root * @param {Entity} entity * @param {Object.} data * @returns {string|void} */ - deserializeComponents(entity, data) { + deserializeComponents(root, entity, data) { for (const componentId in data) { - const componentClass = gComponentRegistry.findById(componentId); - const componentHandle = new componentClass({}); - entity.addComponent(componentHandle); - const errorStatus = componentHandle.deserialize(data[componentId]); + if (!entity.components[componentId]) { + logger.warn("Entity no longer has component:", componentId); + continue; + } + + const errorStatus = entity.components[componentId].deserialize(data[componentId], root); if (errorStatus) { return errorStatus; } diff --git a/src/js/states/ingame.js b/src/js/states/ingame.js index 33d7e15b..3eea38b7 100644 --- a/src/js/states/ingame.js +++ b/src/js/states/ingame.js @@ -381,17 +381,6 @@ export class InGameState extends GameState { } } - // // Check if we can show an ad - // // DISABLED - // if (this.stage === stages.s10_gameRunning && !this.core.root.hud.parts.processingOverlay.hasTasks()) { - // if (this.app.isRenderable() && this.app.adProvider.getCanShowVideoAd()) { - // this.saveThenGoToState("WatchAdState", { - // nextStateId: "RunningGameState", - // nextStatePayload: this.creationPayload, - // }); - // } - // } - if (this.stage === stages.s10_gameRunning) { this.core.tick(dt); } diff --git a/src/js/states/main_menu.js b/src/js/states/main_menu.js index 927f02f6..3d39e826 100644 --- a/src/js/states/main_menu.js +++ b/src/js/states/main_menu.js @@ -1,11 +1,10 @@ import { GameState } from "../core/game_state"; import { cachebust } from "../core/cachebust"; -import { globalConfig, IS_DEBUG, IS_DEMO, THIRDPARTY_URLS } from "../core/config"; +import { globalConfig, IS_DEMO, THIRDPARTY_URLS } from "../core/config"; import { makeDiv, makeButtonElement, formatSecondsToTimeAgo, - generateFileDownload, waitNextFrame, isSupportedBrowser, makeButton, @@ -14,9 +13,29 @@ import { import { ReadWriteProxy } from "../core/read_write_proxy"; import { HUDModalDialogs } from "../game/hud/parts/modal_dialogs"; import { T } from "../translations"; -import { PlatformWrapperImplBrowser } from "../platform/browser/wrapper"; import { getApplicationSettingById } from "../profile/application_settings"; -import { EnumSetting } from "../profile/setting_types"; + +/** + * @typedef {import("../savegame/savegame_typedefs").SavegameMetadata} SavegameMetadata + * @typedef {import("../profile/setting_types").EnumSetting} EnumSetting + */ + +/** + * Generates a file download + * @param {string} filename + * @param {string} text + */ +function generateFileDownload(filename, text) { + var element = document.createElement("a"); + element.setAttribute("href", "data:text/plain;charset=utf-8," + encodeURIComponent(text)); + element.setAttribute("download", filename); + + element.style.display = "none"; + document.body.appendChild(element); + + element.click(); + document.body.removeChild(element); +} export class MainMenuState extends GameState { constructor() { @@ -128,7 +147,6 @@ export class MainMenuState extends GameState { const closeLoader = this.dialogs.showLoadingDialog(); const reader = new FileReader(); reader.addEventListener("load", event => { - // @ts-ignore const contents = event.target.result; let realContent; @@ -394,7 +412,7 @@ export class MainMenuState extends GameState { } /** - * @param {object} game + * @param {SavegameMetadata} game */ resumeGame(game) { this.app.analytics.trackUiClick("resume_game"); @@ -419,7 +437,7 @@ export class MainMenuState extends GameState { } /** - * @param {object} game + * @param {SavegameMetadata} game */ deleteGame(game) { this.app.analytics.trackUiClick("delete_game"); @@ -447,7 +465,7 @@ export class MainMenuState extends GameState { } /** - * @param {object} game + * @param {SavegameMetadata} game */ downloadGame(game) { this.app.analytics.trackUiClick("download_game"); diff --git a/src/js/states/preload.js b/src/js/states/preload.js index f1551893..0f47e8d6 100644 --- a/src/js/states/preload.js +++ b/src/js/states/preload.js @@ -1,6 +1,6 @@ import { GameState } from "../core/game_state"; import { createLogger } from "../core/logging"; -import { findNiceValue, waitNextFrame } from "../core/utils"; +import { findNiceValue } from "../core/utils"; import { cachebust } from "../core/cachebust"; import { PlatformWrapperImplBrowser } from "../platform/browser/wrapper"; import { T, autoDetectLanguageId, updateApplicationLanguage } from "../translations"; @@ -228,11 +228,7 @@ export class PreloadState extends GameState { this.statusBar.style.width = percentage + "%"; this.statusBarText.innerText = findNiceValue(percentage) + "%"; - if (G_IS_DEV) { - return Promise.resolve(); - } return Promise.resolve(); - // return waitNextFrame(); } showFailMessage(text) { @@ -279,11 +275,6 @@ export class PreloadState extends GameState { if (confirm("Are you sure you want to reset the app? This will delete all your savegames")) { this.resetApp(); } - // const signals = this.dialogs.showWarning(T.preload.reset_app_warning.title, T.preload.reset_app_warning.desc, [ - // "delete:bad:timeout", - // "cancel:good", - // ]); - // signals.delete.add(this.resetApp, this); } resetApp() { diff --git a/src/js/webworkers/background_animation_frame_emittter.worker.js b/src/js/webworkers/background_animation_frame_emittter.worker.js index 5469f7aa..3941e0dd 100644 --- a/src/js/webworkers/background_animation_frame_emittter.worker.js +++ b/src/js/webworkers/background_animation_frame_emittter.worker.js @@ -9,7 +9,8 @@ function tick() { const delta = now - lastTick; lastTick = now; - postMessage({ delta }); + // @ts-ignore + self.postMessage({ delta }); } setInterval(tick, desiredMsDelay); diff --git a/src/js/webworkers/compression.worker.js b/src/js/webworkers/compression.worker.js index 5820a4a1..1e567c05 100644 --- a/src/js/webworkers/compression.worker.js +++ b/src/js/webworkers/compression.worker.js @@ -1,6 +1,7 @@ -import { compressX64 } from "../core/lzstring"; import { globalConfig } from "../core/config"; -import { sha1 } from "../core/sensitive_utils.encrypt"; +import { compressX64 } from "../core/lzstring"; +import { computeCrc } from "../core/sensitive_utils.encrypt"; +import { compressObject } from "../savegame/savegame_compressor"; function accessNestedPropertyReverse(obj, keys) { let result = obj; @@ -12,19 +13,27 @@ function accessNestedPropertyReverse(obj, keys) { const salt = accessNestedPropertyReverse(globalConfig, ["file", "info"]); -onmessage = function ({ data: { jobId, job, data } }) { +self.addEventListener("message", event => { + // @ts-ignore + const { jobId, job, data } = event.data; const result = performJob(job, data); - postMessage({ jobId, result }); -}; + + // @ts-ignore + self.postMessage({ jobId, result }); +}); function performJob(job, data) { switch (job) { case "compressX64": { return compressX64(data); } - case "compressFile": { - const checksum = sha1(data.text + salt); - return data.compressionPrefix + compressX64(checksum + data.text); + + case "compressObject": { + const optimized = compressObject(data.obj); + const stringified = JSON.stringify(optimized); + + const checksum = computeCrc(stringified + salt); + return data.compressionPrefix + compressX64(checksum + stringified); } default: throw new Error("Webworker: Unknown job: " + job); diff --git a/translations/base-ar.yaml b/translations/base-ar.yaml index 31c5c2c1..17d822d9 100644 --- a/translations/base-ar.yaml +++ b/translations/base-ar.yaml @@ -19,9 +19,13 @@ # the basic structure so the game also detects it. # +--- steamPage: # This is the short text appearing on the steam page - shortText: shapez.io is a game about building factories to automate the creation and combination of increasingly complex shapes within an infinite map. + shortText: shapez.io is a game about building factories to automate the creation and processing of increasingly complex shapes across an infinitely expanding map. + + # This is the text shown above the Discord link + discordLink: Official Discord - Chat with me! # This is the long description for the steam page - It is contained here so you can help to translate it, and I will regulary update the store page. # NOTICE: @@ -31,15 +35,16 @@ steamPage: [img]{STEAM_APP_IMAGE}/extras/store_page_gif.gif[/img] shapez.io is a game about building factories to automate the creation and processing of increasingly complex shapes across an infinitely expanding map. - Upon delivering the requested shapes you will progress within the game and unlock upgrades to speed up your factory. - As the demand for shapes increases, you will have to scale up your factory to meet the demand - Don't forget about resources though, you will have to expand across the [b]infinite map[/b]! + Upon delivering the requested shapes you'll progress within the game and unlock upgrades to speed up your factory. - Soon you will have to mix colors and paint your shapes with them - Combine red, green and blue color resources to produce different colors and paint shapes with it to satisfy the demand. + As the demand for shapes increases, you'll have to scale up your factory to meet the demand - Don't forget about resources though, you'll have to expand across the [b]infinite map[/b]! - This game features 18 progressive levels (Which should keep you busy for hours already!) but I'm constantly adding new content - There is a lot planned! + Soon you'll have to mix colors and paint your shapes with them - Combine red, green and blue color resources to produce different colors and paint shapes with them to satisfy the demand. - Purchasing the game gives you access to the standalone version which has additional features and you'll also receive access to newly developed features. + This game features 18 progressive levels (Which should already keep you busy for hours!) but I'm constantly adding new content - There's a lot planned! + + Purchasing the game gives you access to the standalone version which has additional features, and you'll also receive access to newly developed features. [b]Standalone Advantages[/b] @@ -55,7 +60,7 @@ steamPage: [b]Future Updates[/b] - I am updating the game very often and trying to push an update at least every week! + I am updating the game often and trying to push an update at least once every week! [list] [*] Different maps and challenges (e.g. maps with obstacles) @@ -82,8 +87,6 @@ steamPage: [*] [url=https://github.com/tobspr/shapez.io/blob/master/translations/README.md]Help translate[/url] [/list] - discordLink: Official Discord - Chat with me! - global: loading: Loading error: Error @@ -138,11 +141,15 @@ demoBanners: mainMenu: play: Play + continue: Continue + newGame: New Game changelog: Changelog + subreddit: Reddit importSavegame: Import openSourceHint: This game is open source! discordLink: Official Discord Server helpTranslate: Help translate! + madeBy: Made by # This is shown when using firefox and other browsers which are not supported. browserWarning: >- @@ -151,11 +158,6 @@ mainMenu: savegameLevel: Level savegameLevelUnknown: Unknown Level - continue: Continue - newGame: New Game - madeBy: Made by - subreddit: Reddit - dialogs: buttons: ok: OK @@ -165,7 +167,7 @@ dialogs: restart: Restart reset: Reset getStandalone: Get Standalone - deleteGame: I know what I do + deleteGame: I know what I am doing viewUpdate: View Update showUpgrades: Show Upgrades showKeybindings: Show Keybindings @@ -214,11 +216,11 @@ dialogs: featureRestriction: title: Demo Version - desc: You tried to access a feature () which is not available in the demo. Consider to get the standalone for the full experience! + desc: You tried to access a feature () which is not available in the demo. Consider getting the standalone version for the full experience! oneSavegameLimit: title: Limited savegames - desc: You can only have one savegame at a time in the demo version. Please remove the existing one or get the standalone! + desc: You can only have one savegame at a time in the demo version. Please remove the existing one or get the standalone version! updateSummary: title: New update! @@ -236,6 +238,16 @@ dialogs: desc: >- You are deleting a lot of buildings ( to be exact)! Are you sure you want to do this? + massCutConfirm: + title: Confirm cut + desc: >- + You are cutting a lot of buildings ( to be exact)! Are you sure you want to do this? + + massCutInsufficientConfirm: + title: Confirm cut + desc: >- + You can not afford to paste this area! Are you sure you want to cut it? + blueprintsNotUnlocked: title: Not unlocked yet desc: >- @@ -252,26 +264,15 @@ dialogs: createMarker: title: New Marker - desc: Give it a meaningful name, you can also include a short key of a shape (Which you can generate here) titleEdit: Edit Marker + desc: Give it a meaningful name, you can also include a short key of a shape (Which you can generate here) markerDemoLimit: desc: You can only create two custom markers in the demo. Get the standalone for unlimited markers! - massCutConfirm: - title: Confirm cut - desc: >- - You are cutting a lot of buildings ( to be exact)! Are you sure you - want to do this? exportScreenshotWarning: title: Export screenshot - desc: >- - You requested to export your base as a screenshot. Please note that this can - be quite slow for a big base and even crash your game! - - massCutInsufficientConfirm: - title: Confirm cut - desc: You can not afford to paste this area! Are you sure you want to cut it? + desc: You requested to export your base as a screenshot. Please note that this can be quite slow for a big base and even crash your game! ingame: # This is shown in the top left corner and displays useful keybindings in @@ -283,20 +284,32 @@ ingame: rotateBuilding: Rotate building placeMultiple: Place multiple reverseOrientation: Reverse orientation - disableAutoOrientation: Disable auto orientation + disableAutoOrientation: Disable auto-orientation toggleHud: Toggle HUD placeBuilding: Place building - createMarker: Create Marker - delete: Destroy + createMarker: Create marker + delete: Delete pasteLastBlueprint: Paste last blueprint lockBeltDirection: Enable belt planner plannerSwitchSide: Flip planner side cutSelection: Cut copySelection: Copy - clearSelection: Clear Selection + clearSelection: Clear selection pipette: Pipette switchLayers: Switch layers + # Names of the colors, used for the color blind mode + colors: + red: Red + green: Green + blue: Blue + yellow: Yellow + purple: Purple + cyan: Cyan + white: White + black: Black + uncolored: Gray + # Everything related to placing buildings (I.e. as soon as you selected a building # from the toolbar) buildingPlacement: @@ -391,6 +404,12 @@ ingame: description: Left-click a marker to jump to it, right-click to delete it.

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

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

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

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

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

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

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

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

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

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

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

- Finally, huge thanks to my best friend Niklas - Without our - factorio sessions this game would never have existed. + Finally, huge thanks to my best friend Niklas - Without our Factorio sessions, this game would never have existed. changelog: title: Changelog diff --git a/translations/base-cat.yaml b/translations/base-cat.yaml index 4871f0ce..79623047 100644 --- a/translations/base-cat.yaml +++ b/translations/base-cat.yaml @@ -19,10 +19,14 @@ # the basic structure so the game also detects it. # +--- steamPage: # This is the short text appearing on the steam page shortText: shapez.io és un joc que té com a objectiu construir i automatitzar fàbriques per tal de produir figures cada cop més complexes en un mapa infinit. + # This is the text shown above the Discord link + discordLink: Official Discord - Chat with me! + # This is the long description for the steam page - It is contained here so you can help to translate it, and I will regulary update the store page. # NOTICE: # - Do not translate the first line (This is the gif image at the start of the store) @@ -31,15 +35,16 @@ steamPage: [img]{STEAM_APP_IMAGE}/extras/store_page_gif.gif[/img] shapez.io is a game about building factories to automate the creation and processing of increasingly complex shapes across an infinitely expanding map. - Upon delivering the requested shapes you will progress within the game and unlock upgrades to speed up your factory. - As the demand for shapes increases, you will have to scale up your factory to meet the demand - Don't forget about resources though, you will have to expand across the [b]infinite map[/b]! + Upon delivering the requested shapes you'll progress within the game and unlock upgrades to speed up your factory. - Soon you will have to mix colors and paint your shapes with them - Combine red, green and blue color resources to produce different colors and paint shapes with it to satisfy the demand. + As the demand for shapes increases, you'll have to scale up your factory to meet the demand - Don't forget about resources though, you'll have to expand across the [b]infinite map[/b]! - This game features 18 progressive levels (Which should keep you busy for hours already!) but I'm constantly adding new content - There is a lot planned! + Soon you'll have to mix colors and paint your shapes with them - Combine red, green and blue color resources to produce different colors and paint shapes with them to satisfy the demand. - Purchasing the game gives you access to the standalone version which has additional features and you'll also receive access to newly developed features. + This game features 18 progressive levels (Which should already keep you busy for hours!) but I'm constantly adding new content - There's a lot planned! + + Purchasing the game gives you access to the standalone version which has additional features, and you'll also receive access to newly developed features. [b]Standalone Advantages[/b] @@ -55,7 +60,7 @@ steamPage: [b]Future Updates[/b] - I am updating the game very often and trying to push an update at least every week! + I am updating the game often and trying to push an update at least once every week! [list] [*] Different maps and challenges (e.g. maps with obstacles) @@ -82,8 +87,6 @@ steamPage: [*] [url=https://github.com/tobspr/shapez.io/blob/master/translations/README.md]Help translate[/url] [/list] - discordLink: Official Discord - Chat with me! - global: loading: Carregant error: Error @@ -239,6 +242,11 @@ dialogs: desc: >- Estàs esborrant molts edificis de cop ( per ser exactes)! Estàs segur que vols seguir? + massCutInsufficientConfirm: + title: Confirm cut + desc: >- + You can not afford to paste this area! Are you sure you want to cut it? + blueprintsNotUnlocked: title: Encara no s'ha desbloquejat desc: >- @@ -265,9 +273,6 @@ dialogs: exportScreenshotWarning: title: Export screenshot desc: Has demanat exportar la teva/teua base com una captura de pantalla. Tin en conte que aquest procés pot ser molt lent i inclús crashear el teu joc! - massCutInsufficientConfirm: - title: Confirm cut - desc: You can not afford to paste this area! Are you sure you want to cut it? ingame: # This is shown in the top left corner and displays useful keybindings in @@ -302,8 +307,8 @@ ingame: purple: Morat cyan: Cian white: Blanc - uncolored: Sense color black: Black + uncolored: Sense color # Everything related to placing buildings (I.e. as soon as you selected a building # from the toolbar) @@ -315,6 +320,7 @@ ingame: # Shows the hotkey in the ui, e.g. "Hotkey: Q" hotkeyLabel: >- Hotkey: + infoTexts: speed: Velocitat range: Distància @@ -411,8 +417,10 @@ ingame: 1_1_extractor: Col·loca un extractor damunt d'una figura circular per extraure-la! 1_2_conveyor: >- Connecta l'extractor a la cinta transportadora cap al teu nexe!

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

Pista: Manté pressionat SHIFT per a col·locar més extractors, i utilitza R per a rotar-los. + # All shop upgrades shopUpgrades: belt: @@ -445,7 +453,8 @@ buildings: name: &wire Cable description: Permet transportar energia. - miner: # Internal name for the Extractor + # Internal name for the Extractor + miner: default: name: &miner Extractor description: Posa-ho damunt d'una font de figures o colors per extraure'ls. @@ -454,7 +463,8 @@ buildings: name: Extractor (Cadena) description: Posa-ho damunt d'una font de figures o colors per extraure'ls. Pot ser encadenat! - underground_belt: # Internal name for the Tunnel + # Internal name for the Tunnel + underground_belt: default: name: &underground_belt Túnel description: Permet transportar recursos per sota d'edificis i cintes. @@ -463,7 +473,8 @@ buildings: name: Túnel de Nivell II description: Permet transportar recursos per sota d'edificis i cintes. - splitter: # Internal name for the Balancer + # Internal name for the Balancer + splitter: default: name: &splitter Distribuïdor description: Multifuncional - Distribueix les entrades i sortides equitativament. @@ -544,10 +555,12 @@ buildings: default: name: &energy_generator Generador d'energia description: Genera energia consumint figures. Cada generador requereix una figura diferent. + wire_crossings: default: - name: Wire Splitter + name: &wire_crossings Wire Splitter description: Splits a energy wire into two. + merger: name: Wire Merger description: Merges two energy wires into one. @@ -599,6 +612,7 @@ storyRewards: title: Distribuïdor compacte desc: >- Has desbloquejat una variant compacta del distribuïdor - Acepta dues entrades i les fusiona en una sola! + reward_cutter_quad: title: Cisalla quàdruple desc: Has desbloquejat una variant de la cisalla - Et permet tallar figures en quatre parts en lloc de sols en dos! @@ -663,6 +677,7 @@ settings: title: Interval de guardat automàtic description: >- Controla el temps entre guardats automàtics que fa el joc, pots deshabilitar-ho des d'aquí + intervals: one_minute: 1 Minut two_minutes: 2 Minuts @@ -697,23 +712,28 @@ settings: language: title: Language description: >- - Change the language. All translations are user contributed and might be incomplete! + Change the language. All translations are user-contributed and might be incomplete! + enableColorBlindHelper: title: Color Blind Mode description: >- - Enables various tools which allow to play the game if you are color blind. + Enables various tools which allow you to play the game if you are color blind. + fullscreen: title: Fullscreen description: >- It is recommended to play the game in fullscreen to get the best experience. Only available in the standalone. + soundsMuted: title: Mute Sounds description: >- If enabled, mutes all sound effects. + musicMuted: title: Mute Music description: >- If enabled, mutes all music. + theme: title: Game theme description: >- @@ -726,38 +746,47 @@ settings: title: Simulation Target description: >- If you have a 144hz monitor, change the refresh rate here so the game will properly simulate at higher refresh rates. This might actually decrease the FPS if your computer is too slow. + alwaysMultiplace: title: Multiplace description: >- If enabled, all buildings will stay selected after placement until you cancel it. This is equivalent to holding SHIFT permanently. + offerHints: title: Hints & Tutorials description: >- - Whether to offer hints and tutorials while playing. Also hides certain UI elements onto a given level to make it easier to get into the game. + Whether to offer hints and tutorials while playing. Also hides certain UI elements up to a given level to make it easier to get into the game. + enableTunnelSmartplace: title: Smart Tunnels description: >- - When enabled, placing tunnels will automatically remove unnecessary belts. This also enables to drag tunnels and excess tunnels will get removed. + When enabled, placing tunnels will automatically remove unnecessary belts. This also enables you to drag tunnels and excess tunnels will get removed. + vignette: title: Vignette description: >- - Enables the vignette which darkens the screen corners and makes text easier to read. + Enables the vignette, which darkens the screen corners and makes text easier to read. + rotationByBuilding: title: Rotation by building type description: >- Each building type remembers the rotation you last set it to individually. This may be more comfortable if you frequently switch between placing different building types. + compactBuildingInfo: title: Compact Building Infos description: >- Shortens info boxes for buildings by only showing their ratios. Otherwise a description and image is shown. + disableCutDeleteWarnings: title: Disable Cut/Delete Warnings description: >- - Disable the warning dialogs brought up when cutting/deleting more than 100 entities. + Disables the warning dialogs brought up when cutting/deleting more than 100 entities. + keybindings: title: Keybindings hint: >- Tip: Be sure to make use of CTRL, SHIFT and ALT! They enable different placement options. + resetKeybindings: Reset Keybindings categoryLabels: @@ -785,6 +814,7 @@ keybindings: menuOpenShop: Upgrades menuOpenStats: Statistics + menuClose: Close Menu toggleHud: Toggle HUD toggleFPSInfo: Toggle FPS and Debug Info @@ -815,6 +845,7 @@ keybindings: lockBeltDirection: Enable belt planner switchDirectionLockSide: >- Planner: Switch side + massSelectStart: Hold and drag to start massSelectSelectMultiple: Select multiple areas massSelectCopy: Copy area @@ -823,16 +854,20 @@ keybindings: placementDisableAutoOrientation: Disable automatic orientation placeMultiple: Stay in placement mode placeInverse: Invert automatic belt orientation - menuClose: Close Menu about: title: About this Game body: >- This game is open source and developed by Tobias Springer (this is me).

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

+ Lydsporet er lavet af Peppsen - Han er fantastisk.

- Finally, huge thanks to my best friend Niklas - Without our factorio sessions this game would never have existed. + Endelig, tusind tak til min bedste ven Niklas - Uden vi havde spillet factorio sammen ville dette spil aldrig have eksisteret. changelog: title: Changelog demo: features: - restoringGames: Restoring savegames - importingGames: Importing savegames - oneGameLimit: Limited to one savegame - customizeKeybindings: Customizing Keybindings - exportingBase: Exporting whole Base as Image + restoringGames: Genopretter gem + importingGames: Importerer gem + oneGameLimit: Afgrænset til et gem + customizeKeybindings: Tilpasser Keybindings + exportingBase: Eksportere hele basen som et billede - settingNotAvailable: Not available in the demo. + settingNotAvailable: Ikke tilgængelig i demoen. diff --git a/translations/base-de.yaml b/translations/base-de.yaml index 42c89d2b..18cd4648 100644 --- a/translations/base-de.yaml +++ b/translations/base-de.yaml @@ -19,6 +19,7 @@ # the basic structure so the game also detects it. # +--- steamPage: # This is the short text appearing on the steam page shortText: In shapez.io nutzt du die vorhandenen Ressourcen, um mit deinen Maschinen durch Kombination immer komplexere Formen zu erschaffen. @@ -33,57 +34,60 @@ steamPage: longText: >- [img]{STEAM_APP_IMAGE}/extras/store_page_gif.gif[/img] - shapez.io is a game about building factories to automate the creation and processing of increasingly complex shapes across an infinitely expanding map. - Upon delivering the requested shapes you will progress within the game and unlock upgrades to speed up your factory. + In shapez.io musst du Maschinen geschickt verbinden, damit Formen automatisiert erstellt, bearbeitet und kombiniert werden. - As the demand for shapes increases, you will have to scale up your factory to meet the demand - Don't forget about resources though, you will have to expand across the [b]infinite map[/b]! + Liefere die gewünschten, stetig komplexer werdenden Formen an dein Hauptgebäude, um im Spiel voranzukommen. Schalte mit ihnen außerdem Upgrades frei, die deine Maschinen und somit auch deine Fabriken beschleunigen! - Soon you will have to mix colors and paint your shapes with them - Combine red, green and blue color resources to produce different colors and paint shapes with it to satisfy the demand. + Da die Nachfrage sowohl in der Komplexität, als auch der Menge steigt, wirst du deine Fabriken erweitern müssen. Vergiss nicht, dass du die dafür benötigten Ressourcen beschaffen musst und expandiere auf der [b]unendlichen Karte[/b]! - This game features 18 progressive levels (Which should keep you busy for hours already!) but I'm constantly adding new content - There is a lot planned! + Bald wirst du Farben mischen und deine Formen damit bemalen lassen. Staple dann deine fertigen Formen aufeinander und lasse so die wildesten Kreationen entstehen. - Purchasing the game gives you access to the standalone version which has additional features and you'll also receive access to newly developed features. + Nutze dein gesammeltes Wissen über die Maschinen und lasse deine Fabriken die gewünschten Formen der 18 verschiedenen Level abliefern. Schalte mit jedem Level neue Arbeitsschritte oder Gebäude frei. Das sollte dich schon für Stunden beschäftigt halten! Danach werden im Freispielmodus zufällige Formen generiert, die du ebenfalls abliefern kannst. Ich füge regelmäßig neue Funktionen hinzu und davon sind eine ganze Menge geplant! - [b]Vorteile der Standalone-Version[/b] + + Wenn du das Spiel erwirbst, erhälst du Zugriff auf die zusätzlichen Features der Standalone-Version. Das bedeutet, du kannst unter anderem die neuesten Updates zuerst spielen! + + [b]Vorteile der Standalone[/b] [list] - [*] Dark Mode - [*] Unbegrenzt viele Wegpunkte - [*] Unbegrenzt viele Savegames - [*] Zusätzliche Einstellungen - [*] Coming soon: Kabel & Energie! Geplant für (ungefähr) ende Juli 2020. - [*] Coming soon: Mehr Level - [*] Erlaubt mir shapez.io weiter zu entwickeln ❤️ + [*] Dark-Mode + [*] Unbegrenzte Wegpunkte + [*] Unbegrenzte Anzahl von Spielständen + [*] Weitere Einstellungen + [*] Es kommen: Mehr Levels + [*] Es kommen: Kabel & Energie! Voraussichtlich gegen Ende Juli 2020. + [*] Unterstütze die Entwicklung von shapez.io ❤️ [/list] - [b]Zukünftige Updates[/b] + [b]Geplante Funktionen[/b] - Ich update das Spiel sehr oft und versuche mindestens einmal pro Woche ein Update zu veröffentlichen! + Ich bin aktiv mit der Entwicklung beschäftigt und versuche jede Woche ein Update oder den aktuellen Stand der Entwicklung zu veröffentlichen. [list] [*] Verschiedene Karten und Herausforderungen (z.B. Karten mit Hindernissen) - [*] Puzzles (Liefere eine Angeforderte Form mit limitiertem Platz/Gebäuden) - [*] Einen Story-Modus in welchem Gebäude etwas kosten - [*] Einstellbarer Kartengenerator (Stelle Ressourcen/Formen, größe und Dichte von Vorkommen, Weltseed und mehr ein) - [*] Zusätzliche neue Formen - [*] Performanceverbesserungen (Das Spiel läuft bereits ziemlich gut!) + [*] Puzzle (Liefere die gewünschten Formen mit begrenztem Platz / limitierten Gebäuden) + [*] Story-Modus mit Gebäudekosten + [*] Einstellbare Kartengenerierung (Ändere die Grösse/Anzahl/Dichte der Ressourcenflecken, den Seed und mehr) + [*] Mehr Formentypen + [*] Performanceverbesserungen (Das Spiel läuft bereits ganz gut!) [*] Und vieles mehr! [/list] - [b]Dieses Spiel ist open source![/b] + [b] Dieses Spiel ist Open Source[/b] - Jeder kann etwas dazu beitragen. Ich bin aktiv in der Community beteiligt und versuche alle Vorschläge und Rückmeldungen in betracht zu ziehen, wo dies möglich ist. Schaut euch - mein Trello-board an um die ganze Roadmap zu sehen! + Jeder kann dazu beitragen! Ich bin aktiv in die Community involviert, versuche alle Vorschläge zu lesen und beziehe so viel Feedback wie möglich mit in die Entwicklung ein. + Die komplette Roadmap gibt es auf dem Trello-Board zum Nachlesen! - [b]Links[/b] + [b]Links [/b] [list] - [*] [url=https://discord.com/invite/HN7EVzV]Official Discord[/url] + [*] [url=https://discord.com/invite/HN7EVzV]Offizieller Discord[/url] [*] [url=https://trello.com/b/ISQncpJP/shapezio]Roadmap[/url] [*] [url=https://www.reddit.com/r/shapezio]Subreddit[/url] - [*] [url=https://github.com/tobspr/shapez.io]Source code (GitHub)[/url] - [*] [url=https://github.com/tobspr/shapez.io/blob/master/translations/README.md]Help translate[/url] + [*] [url=https://github.com/tobspr/shapez.io]Quelltext (GitHub)[/url] + [*] [url=https://github.com/tobspr/shapez.io/blob/master/translations/README.md]Hilf beim Übersetzen[/url] [/list] + global: loading: Laden error: Fehler @@ -138,10 +142,15 @@ demoBanners: mainMenu: play: Spielen + continue: Fortsetzen + newGame: Neues Spiel changelog: Änderungshistorie + subreddit: Reddit importSavegame: Importieren openSourceHint: Dieses Spiel ist Open Source! discordLink: Offizieller Discord Server + helpTranslate: Hilf beim Übersetzen! + madeBy: Ein Spiel von # This is shown when using firefox and other browsers which are not supported. browserWarning: >- @@ -150,12 +159,6 @@ mainMenu: savegameLevel: Level savegameLevelUnknown: Unbekanntes Level - helpTranslate: Hilf beim Übersetzen! - continue: Fortsetzen - newGame: Neues Spiel - madeBy: Ein Spiel von - subreddit: Reddit - dialogs: buttons: ok: OK @@ -236,6 +239,16 @@ dialogs: desc: >- Du löscht sehr viele Gebäude ( um genau zu sein)! Bist du dir sicher? + massCutConfirm: + title: Ausschneiden bestätigen + desc: >- + Du schneidest sehr viele Gebäude aus ( um genau zu sein)! Bist du dir sicher? + + massCutInsufficientConfirm: + title: Ausschneiden bestätigen + desc: >- + Du hast aktuell nicht genug Blaupausenformen, um die Auswahl einzufügen! Möchtest du sie trotzdem ausschneiden? + blueprintsNotUnlocked: title: Noch nicht freigeschaltet desc: >- @@ -252,24 +265,15 @@ dialogs: createMarker: title: Neuer Marker - desc: Gib ihm einen griffigen Namen. Du kannst sogar die Abkürzung einer Form eingeben (Diese kann hier generiert werden). titleEdit: Edit Marker + desc: Gib ihm einen griffigen Namen. Du kannst sogar die Abkürzung einer Form eingeben (Diese kann hier generiert werden). markerDemoLimit: desc: Du kannst nur 2 benutzerdefinierte Marker in der Demo benutzen. Hol dir die Standalone, um unendlich viele Marker zu erstellen! - massCutConfirm: - title: Ausschneiden bestätigen - desc: >- - Du schneidest sehr viele Gebäude aus ( um genau zu sein)! Bist du dir sicher? exportScreenshotWarning: title: Bildschirmfoto exportieren - desc: >- - Hier kannst du ein Bildschirmfoto von deiner ganzen Fabrik erstellen. Für extrem große Fabriken kann das jedoch sehr lange dauern und ggf. zum Spielabsturz führen! - - massCutInsufficientConfirm: - title: Confirm cut - desc: You can not afford to paste this area! Are you sure you want to cut it? + desc: Hier kannst du ein Bildschirmfoto von deiner ganzen Fabrik erstellen. Für extrem große Fabriken kann das jedoch sehr lange dauern und ggf. zum Spielabsturz führen! ingame: # This is shown in the top left corner and displays useful keybindings in @@ -293,7 +297,21 @@ ingame: copySelection: Kopieren clearSelection: Auswahl aufheben pipette: Pipette - switchLayers: Ändere Ebenenansicht + + switchLayers: Ebenen wechseln + + # Names of the colors, used for the color blind mode + colors: + red: Rot + green: Grün + blue: Blau + yellow: Gelb + purple: Violett + cyan: Cyan + white: Weiß + black: Schwarz + uncolored: Farblos + # Everything related to placing buildings (I.e. as soon as you selected a building # from the toolbar) @@ -389,6 +407,12 @@ ingame: description: Linksklick auf einen Marker, um dort hinzugelangen, Rechtsklick, um ihn zu löschen.

Drücke um einen Marker aus deinem Blickwinkel, oder rechtsklicke, um einen Marker auf der ausgewählten Position zu erschaffen. creationSuccessNotification: Marker wurde erstellt. + # Shape viewer + shapeViewer: + title: Ebenen + empty: Leer + copyKey: Schlüssel kopieren + # Interactive tutorial interactiveTutorial: title: Tutorial @@ -400,20 +424,6 @@ ingame: 1_3_expand: >- Dies ist KEIN Idle-Game! Baue mehr Extrahierer und Förderbänder, um das Ziel schneller zu erreichen.

Tipp: Halte UMSCH, um mehrere Gebäude zu platzieren und nutze R um sie zu rotieren. - colors: - red: Rot - green: Grün - blue: Blau - yellow: Gelb - purple: Violett - cyan: Cyan - white: Weiß - uncolored: Farblos - black: Schwarz - shapeViewer: - title: Ebenen - empty: Leer - copyKey: Copy Key # All shop upgrades shopUpgrades: @@ -432,12 +442,19 @@ shopUpgrades: # Buildings and their name / description buildings: + hub: + deliver: Liefere + toUnlock: >- + Für folgende Belohnung: + levelShortcut: LVL + belt: default: name: &belt Förderband description: Transportiert Items. Halte und ziehe um mehrere zu platzieren. - miner: # Internal name for the Extractor + # Internal name for the Extractor + miner: default: name: &miner Extrahierer description: Platziere ihn auf einer Form oder Farbe um sie zu extrahieren. @@ -446,7 +463,8 @@ buildings: name: Extrahierer (Kette) description: Platziere ihn auf einer Form oder Farbe um sie zu extrahieren. Kann verkettet werden. - underground_belt: # Internal name for the Tunnel + # Internal name for the Tunnel + underground_belt: default: name: &underground_belt Tunnel description: Erlaubt dir, Formen und Farbe unter Gebäuden und Förderbändern durchzuleiten. @@ -455,7 +473,8 @@ buildings: name: Tunnel Stufe II description: Erlaubt dir, Formen und Farbe unter Gebäuden und Förderbändern durchzuleiten. Höhere Reichweite. - splitter: # Internal name for the Balancer + # Internal name for the Balancer + splitter: default: name: &splitter Verteiler description: Multifunktional - Verteilt gleichmäßig vom Eingang auf den Ausgang. @@ -480,7 +499,6 @@ buildings: default: name: &rotater Rotierer description: Rotiert Formen im Uhrzeigersinn um 90 Grad. - ccw: name: Rotierer (CCW) description: Rotiert Formen gegen den Uhrzeigersinn um 90 Grad. @@ -503,6 +521,10 @@ buildings: name: &painter Färber description: &painter_desc Färbt die ganze Form aus dem linken Eingang mit der Farbe aus dem oberen Eingang. + mirrored: + name: *painter + description: *painter_desc + double: name: Färber (2-Fach) description: Färbt beide Formen aus dem linken Eingang mit der Farbe aus dem oberen Eingang. @@ -510,9 +532,6 @@ buildings: quad: name: Färber (4-Fach) description: Erlaubt jedes einzelne Viertel einer Form beliebig einzufärben. - mirrored: - name: *painter - description: *painter_desc trash: default: @@ -523,32 +542,28 @@ buildings: name: Lager description: Lagert den Überschuss bis zu einer gegebenen Kapazität. Kann als Überlauftor agieren. - hub: - deliver: Liefere - toUnlock: >- - Für folgende Belohnung: - levelShortcut: LVL wire: default: - name: Energie Kabel - description: Erlaubt dir den Transport von Energie. + name: Energiekabel + description: Transportiert Energie. advanced_processor: default: name: Farbinvertierer - description: Akzeptiert Farben und Formen und invertiert die Farben. + description: Akzeptiert Farben und Formen und invertiert sie. energy_generator: deliver: Liefere - toGenerateEnergy: Für + toGenerateEnergy: für default: - name: Energie Generator - description: Generiert Energie durch das Konsumieren von Formen. + name: Energiegenerator + description: Generiert Energie, indem die Formen verbraucht werden. wire_crossings: default: name: Kabelverteiler - description: Spaltet ein Energie Kabel in zwei. + description: Teilt ein Energiekabel in zwei Ausgänge. merger: - name: Kabelkombinierer - description: Verbindet zwei Energie Kabel zu einem. + name: Kabelverbinder + description: Verbindet zwei Energiekabel zu einem. + storyRewards: # Those are the rewards gained from completing the store @@ -636,9 +651,9 @@ storyRewards: settings: title: Einstellungen categories: - general: General - userInterface: User Interface - advanced: Advanced + general: Allgemein + userInterface: Benutzeroberfläche + advanced: Erweitert versionBadges: dev: Entwicklung @@ -658,6 +673,19 @@ settings: large: Groß huge: Riesig + autosaveInterval: + title: Intervall für automatisches Speichern + description: >- + Ändert das Intervall, in dem der Spielstand automatisch gespeichert wird. Die Funktion kann hier auch deaktiviert werden. + + intervals: + one_minute: 1 Minute + two_minutes: 2 Minuten + five_minutes: 5 Minuten + ten_minutes: 10 Minuten + twenty_minutes: 20 Minuten + disabled: Deaktiviert + scrollWheelSensitivity: title: Zoomempfindlichkeit description: >- @@ -669,6 +697,28 @@ settings: fast: Schnell super_fast: Sehr schnell + movementSpeed: + title: Bewegungsgeschwindigkeit + description: >- + Ändert die Geschwindigkeit, mit der der Bildschirm durch die Pfeiltasten bewegt wird. + speeds: + super_slow: Sehr langsam + slow: Langsam + regular: Normal + fast: Schnell + super_fast: Sehr schnell + extremely_fast: Extrem schnell + + language: + title: Sprache + description: >- + Ändere die Sprache. Alle Übersetzungen werden von Nutzern erstellt und sind möglicherweise unvollständig! + + enableColorBlindHelper: + title: Modus für Farbenblinde + description: >- + Aktiviert verschiedene Werkzeuge, die dir das Spielen trotz Farbenblindheit ermöglichen. + fullscreen: title: Vollbild description: >- @@ -688,10 +738,10 @@ settings: title: Farbmodus description: >- Wähle zwischen dunklem und hellem Farbmodus. - themes: dark: Dunkel light: Hell + refreshRate: title: Zielbildwiederholrate description: >- @@ -707,21 +757,6 @@ settings: description: >- Schaltet Hinweise und das Tutorial beim Spielen an und aus. Außerdem werden zu den Levels bestimmte Textfelder versteckt, die den Einstieg erleichtern sollen. - language: - title: Sprache - description: >- - Ändere die Sprache. Alle Übersetzungen werden von Nutzern erstellt und sind möglicherweise unvollständig! - - movementSpeed: - title: Bewegungsgeschwindigkeit - description: Ändert die Geschwindigkeit, mit der der Bildschirm durch die Pfeiltasten bewegt wird. - speeds: - super_slow: Sehr langsam - slow: Langsam - regular: Normal - fast: Schnell - super_fast: Sehr schnell - extremely_fast: Extrem schnell enableTunnelSmartplace: title: Intelligente Tunnel description: >- @@ -730,43 +765,23 @@ settings: vignette: title: Vignette description: >- - Aktiviert den Vignetteneffekt, der den Rand des Bildschirms zunehmend verdunkelt - und das Lesen der Textfelder vereinfacht. + Aktiviert den Vignetteneffekt, der den Rand des Bildschirms zunehmend verdunkelt und das Lesen der Textfelder vereinfacht. - autosaveInterval: - title: Intervall für automatisches Speichern + rotationByBuilding: + title: Rotation pro Gebäudetyp description: >- - Ändert das Intervall, in dem der Spielstand automatisch gespeichert wird. - Die Funktion kann hier auch deaktiviert werden. - intervals: - one_minute: 1 Minute - two_minutes: 2 Minuten - five_minutes: 5 Minuten - ten_minutes: 10 Minuten - twenty_minutes: 20 Minuten - disabled: Deaktiviert + Jeder Gebäudetyp merkt sich einzeln, welche Rotation ausgewählt ist. Das fühlt sich möglicherweise besser an, wenn du häufig zwischen verschiedenen Gebäudetypen wechselst. compactBuildingInfo: title: Kompakte Gebäudeinformationen description: >- - Reduziert die Infoboxen der Gebäude auf ihre Arbeitsgeschwindigkeit. Anderenfalls wird ein - Bild mit Beschreibung angezeigt. + Reduziert die Infoboxen der Gebäude auf ihre Arbeitsgeschwindigkeit. Anderenfalls wird ein Bild mit Beschreibung angezeigt. disableCutDeleteWarnings: title: Deaktiviere Warnungsdialog beim Löschen description: >- Deaktiviert die Warnung, die beim Löschen und Ausschneiden von mehr als 100 Feldern angezeigt wird. - enableColorBlindHelper: - title: Modus für Farbenblinde - description: Aktiviert verschiedene Werkzeuge, die dir das Spielen trotz Farbenblindheit ermöglichen. - rotationByBuilding: - title: Rotation pro Gebäudetyp - description: >- - Jeder Gebäudetyp merkt sich einzeln, welche Rotation ausgewählt ist. - Das fühlt sich möglicherweise besser an, wenn du häufig zwischen verschiedenen - Gebäudetypen wechselst. - keybindings: title: Tastenbelegung hint: >- @@ -790,6 +805,7 @@ keybindings: mapMoveRight: Nach rechts bewegen mapMoveDown: Nach unten bewegen mapMoveLeft: Nach links bewegen + mapMoveFaster: Schneller bewegen centerMap: Karte zentrieren mapZoomIn: Hineinzoomen @@ -798,9 +814,12 @@ keybindings: menuOpenShop: Upgrades menuOpenStats: Statistiken + menuClose: Menü schließen toggleHud: HUD an/aus toggleFPSInfo: FPS und Debug-Info an/aus + switchLayers: Ebenen wechseln + exportScreenshot: Ganze Fabrik als Foto exportieren belt: *belt splitter: *splitter underground_belt: *underground_belt @@ -812,16 +831,22 @@ keybindings: painter: *painter trash: *trash + pipette: Pipette rotateWhilePlacing: Rotieren rotateInverseModifier: >- Modifikator: stattdessen gegen den UZS rotieren cycleBuildingVariants: Variante wählen confirmMassDelete: Massenlöschung bestätigen + pasteLastBlueprint: Letzte Blaupause einfügen cycleBuildings: Gebäude rotieren + lockBeltDirection: Bandplaner aktivieren + switchDirectionLockSide: >- + Planer: Seite wechseln massSelectStart: Halten und ziehen zum Beginnen massSelectSelectMultiple: Mehrere Areale markieren massSelectCopy: Areal kopieren + massSelectCut: Areal ausschneiden placementDisableAutoOrientation: Automatische Orientierung deaktivieren placeMultiple: Im Platziermodus bleiben @@ -836,8 +861,8 @@ keybindings: menuClose: Close Menu switchLayers: Switch layers advanced_processor: Farbinvertierer - energy_generator: Energie Generator - wire: Energie Kabel + energy_generator: Energiegenerator + wire: Energiekabel about: title: Über dieses Spiel diff --git a/translations/base-el.yaml b/translations/base-el.yaml index f42ea24f..a8c8b241 100644 --- a/translations/base-el.yaml +++ b/translations/base-el.yaml @@ -19,6 +19,7 @@ # the basic structure so the game also detects it. # +--- steamPage: # This is the short text appearing on the steam page shortText: shapez.io is a game about building factories to automate the creation and combination of increasingly complex shapes within an infinite map. diff --git a/translations/base-en.yaml b/translations/base-en.yaml index 38196d52..edc304b9 100644 --- a/translations/base-en.yaml +++ b/translations/base-en.yaml @@ -19,6 +19,7 @@ # the basic structure so the game also detects it. # +--- steamPage: # This is the short text appearing on the steam page shortText: shapez.io is a game about building factories to automate the creation and processing of increasingly complex shapes across an infinitely expanding map. @@ -447,12 +448,8 @@ buildings: name: &belt Conveyor Belt description: Transports items, hold and drag to place multiple. - wire: - default: - name: &wire Energy Wire - description: Allows you to transport energy. - - miner: # Internal name for the Extractor + # Internal name for the Extractor + miner: default: name: &miner Extractor description: Place over a shape or color to extract it. @@ -461,7 +458,8 @@ buildings: name: Extractor (Chain) description: Place over a shape or color to extract it. Can be chained. - underground_belt: # Internal name for the Tunnel + # Internal name for the Tunnel + underground_belt: default: name: &underground_belt Tunnel description: Allows you to tunnel resources under buildings and belts. @@ -470,7 +468,8 @@ buildings: name: Tunnel Tier II description: Allows you to tunnel resources under buildings and belts. - splitter: # Internal name for the Balancer + # Internal name for the Balancer + splitter: default: name: &splitter Balancer description: Multifunctional - Evenly distributes all inputs onto all outputs. @@ -491,11 +490,6 @@ buildings: name: Cutter (Quad) description: Cuts shapes into four parts. If you use only one part, be sure to destroy the other parts or it will stall! - advanced_processor: - default: - name: &advanced_processor Color Inverter - description: Accepts a color or shape and inverts it. - rotater: default: name: &rotater Rotate @@ -529,6 +523,7 @@ buildings: double: name: Painter (Double) description: Colors the shapes on the left inputs with the color from the top input. + quad: name: Painter (Quad) description: Allows you to color each quadrant of the shape with a different color. @@ -542,24 +537,59 @@ buildings: name: Storage description: Stores excess items, up to a given capacity. Can be used as an overflow gate. - energy_generator: - deliver: Deliver - - # This will be shown before the amount, so for example 'For 123 Energy' - toGenerateEnergy: For - + wire: default: - name: &energy_generator Energy Generator - description: Generates energy by consuming shapes. + name: &wire Wire + description: &wire_desc Allows to connect logical components and can transfer items, colors or boolean signals. - wire_crossings: + wire_tunnel: default: - name: &wire_crossings Wire Splitter - description: Splits a energy wire into two. + name: &wire_tunnel Wire Tunnel + description: Allows to cross two wires without connecting them. - merger: - name: Wire Merger - description: Merges two energy wires into one. + coating: + name: Wire Insulation + description: Allows to pass through signals without connecting to other wires on the sides. + + constant_signal: + default: + name: &constant_signal Constant Signal + description: Emits a constant signal (shape, color or boolean). + + lever: + default: + name: &lever Button + description: Can be toggled to emit 1 / 0 + + logic_gate: + default: + name: &logic_gate AND Gate + description: Emits a truthy boolean signal if both inputs are truthy. + not: + name: NOT + description: Inverts the given signal. + xor: + name: XOR + description: Emits a truthy signal if one of the inputs is truthy, but not both. + or: + name: OR + description: Emits a truthy signal if one of the inputs is truthy. + + transistor: + name: Gate + description: Only forwards the bottom input if the left input is true. + + filter: + default: + name: &filter Filter + # TEMP + description: Only leaves through items who match exactly the provided shape / color. If you put in a boolean 1, it leaves everything through, if you put in a 0 it will leave nothing through. + + display: + default: + name: &display Display + # TEMP + description: Can be connected on the wires layer to show a color or shape. When inputting a boolean item, the display will be white if the value is 1. storyRewards: # Those are the rewards gained from completing the store @@ -637,7 +667,7 @@ storyRewards: no_reward: title: Next level desc: >- - This level gave you no reward, but the next one will!

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

PS: Better not destroy your existing factory - You'll need all those shapes later to unlock upgrades! no_reward_freeplay: title: Next level @@ -650,6 +680,7 @@ settings: general: General userInterface: User Interface advanced: Advanced + performance: Performance versionBadges: dev: Development @@ -739,9 +770,9 @@ settings: light: Light refreshRate: - title: Simulation Target + title: Tick Rate description: >- - If you have a 144hz monitor, change the refresh rate here so the game will properly simulate at higher refresh rates. This might actually decrease the FPS if your computer is too slow. + The game will automatically adjust the tickrate to be between this target tickrate and half of it. For example, with a tickrate of 60hz, the game will try to stay at 60hz, and if your computer can't handle it it will go down until it eventually reaches 30hz. alwaysMultiplace: title: Multiplace @@ -778,6 +809,22 @@ settings: description: >- Disables the warning dialogs brought up when cutting/deleting more than 100 entities. + lowQualityMapResources: + title: Low Quality Map Resources + description: >- + Simplifies the rendering of resources on the map when zoomed in to improve performance. + It even looks cleaner, so be sure to try it out! + + disableTileGrid: + title: Disable Grid + description: >- + Disabling the tile grid can help with the performance. This also makes the game look cleaner! + + lowQualityTextures: + title: Low quality textures (Ugly) + description: >- + Uses low quality textures to save performance. This will make the game look very ugly! + keybindings: title: Keybindings hint: >- @@ -816,19 +863,26 @@ keybindings: toggleFPSInfo: Toggle FPS and Debug Info switchLayers: Switch layers exportScreenshot: Export whole Base as Image + + # --- Do not translate the values in this section belt: *belt splitter: *splitter underground_belt: *underground_belt miner: *miner cutter: *cutter - advanced_processor: *advanced_processor rotater: *rotater stacker: *stacker mixer: *mixer - energy_generator: *energy_generator painter: *painter trash: *trash wire: *wire + constant_signal: *constant_signal + logic_gate: *logic_gate + lever: *lever + filter: *filter + wire_tunnel: *wire_tunnel + display: *display + # --- pipette: Pipette rotateWhilePlacing: Rotate diff --git a/translations/base-es.yaml b/translations/base-es.yaml index f5dbd619..765970d6 100644 --- a/translations/base-es.yaml +++ b/translations/base-es.yaml @@ -19,6 +19,7 @@ # the basic structure so the game also detects it. # +--- steamPage: # This is the short text appearing on the steam page shortText: shapez.io es un juego sobre construir fábricas para automatizar la creación y combinación de figuras cada vez más complejas en un mapa infinito. diff --git a/translations/base-fi.yaml b/translations/base-fi.yaml index 7014c733..5acc58cf 100644 --- a/translations/base-fi.yaml +++ b/translations/base-fi.yaml @@ -19,6 +19,7 @@ # the basic structure so the game also detects it. # +--- steamPage: # This is the short text appearing on the steam page shortText: shapez.io on peli tehtaiden rakentamisesta, joiden avulla automatisoidaan yhä monimutkaisempien muotojen luonti and yhdisteleminen loputtomassa maailmassa. diff --git a/translations/base-fr.yaml b/translations/base-fr.yaml index 34ce2944..8eb4f0ef 100644 --- a/translations/base-fr.yaml +++ b/translations/base-fr.yaml @@ -19,6 +19,7 @@ # the basic structure so the game also detects it. # +--- steamPage: # This is the short text appearing on the steam page shortText: shapez.io est un jeu qui consiste à construire des usines pour automatiser la création et la combinaison de formes de plus en plus complexes sur une carte infinie. @@ -33,13 +34,13 @@ steamPage: shapez.io est un jeu dans lequel vous devrez construire des usines pour automatiser la création et la combinaison de formes de plus en plus complexes sur une carte infinie. Lors de la livraison des formes requises vous progresserez et débloquerez des améliorations pour accélerer votre usine. - Au vu de l'augmantation des demandes de formes, vous devrez agrandir votre usine pour répondre à la forte demande - Mais n'oubliez pas les ressources, vous drevrez vous étendre au milieu de cette [b]carte infinie[/b] ! + Au vu de l'augmentation des demandes de formes, vous devrez agrandir votre usine pour répondre à la forte demande - Mais n'oubliez pas les ressources, vous drevrez vous étendre au milieu de cette [b]carte infinie[/b] ! Bientôt vous devrez mixer les couleurs et peindre vos formes avec - Combinez les ressources de couleurs rouge, verte et bleue pour produire différentes couleurs et peindre les formes avec pour satisfaire la demande. - Ce jeu propose 18 niveaux progressifs (qui devraient déjà vous occuper des heures!) mais j'ajoute constamment de nouveau contenus - Il y en a beaucoup de prévus ! + Ce jeu propose 18 niveaux progressifs (qui devraient déjà vous occuper quelques heures !) mais j'ajoute constamment de nouveau contenus - Il y en a beaucoup de prévus ! - Acheter le jeu vous donne accès à la version complète qui a des fonctionnalitées additionnelles et vous recevrez aussi un accès à des fonctionnalitées fraîchement développées. + Acheter le jeu vous donne accès à la version complète qui a des fonctionnalités additionnelles et vous recevrez aussi un accès à des fonctionnalités fraîchement développées. [b]Avantages de la version complète (standalone)[/b] @@ -59,11 +60,11 @@ steamPage: [list] [*] Différentes cartes et challenges (e.g. carte avec obstacles) - [*] Puzzles (Délivrer la forme requise avec une zone limitée/jeu de batîments) - [*] Un mode histoire où les batîments ont un coût - [*] Générateur de carte configurable (configuration des ressources/formes taille/densitée, graine et plus) + [*] Puzzles (Délivrer la forme requise avec une zone limitée/jeu de bâtiments) + [*] Un mode histoire où les bâtiments ont un coût + [*] Générateur de carte configurable (configuration des ressources/formes/taille/densitée, seed et plus) [*] Plus de formes - [*] Amélioration des performances (Le jeu tourne déjà plutot bien!) + [*] Amélioration des performances (Le jeu tourne déjà plutot bien !) [*] Et bien plus ! [/list] @@ -127,7 +128,7 @@ global: control: CTRL alt: ALT escape: ESC - shift: SHIFT + shift: MAJ space: ESPACE demoBanners: @@ -140,13 +141,13 @@ mainMenu: play: Jouer changelog: Historique importSavegame: Importer - openSourceHint: Ce jeu est open source! + openSourceHint: Ce jeu est open source ! discordLink: Serveur Discord officiel - helpTranslate: Contribuez à la traduction! + helpTranslate: Contribuez à la traduction ! # This is shown when using firefox and other browsers which are not supported. browserWarning: >- - Désolé, mais ce jeu est connu pour tourner lentement sur votre navigateur web ! Procurez-vous la version complète ou téléchargez Chrome pour une meilleure expérience. + Désolé, ce jeu est connu pour tourner lentement sur votre navigateur web ! Procurez-vous la version complète ou téléchargez Chrome pour une meilleure expérience. savegameLevel: Niveau savegameLevelUnknown: Niveau inconnu @@ -234,12 +235,12 @@ dialogs: massDeleteConfirm: title: Confirmation de suppression desc: >- - Vous allez supprimer pas mal de bâtiments ( pour être exact) ! Êtes vous certains de vouloir faire cela ? + Vous allez supprimer pas mal de bâtiments ( pour être exact) ! Êtes vous certains de vouloir faire ça ? massCutConfirm: title: Confirmer la coupure desc: >- - Vous vous apprêtez à couper beaucoup de bâtiments ( pour être précis) ! Êtes-vous certains de vouloir faire cela ? + Vous vous apprêtez à couper beaucoup de bâtiments ( pour être précis) ! Êtes-vous certains de vouloir faire ça ? blueprintsNotUnlocked: title: Pas encore débloqué @@ -351,10 +352,10 @@ ingame: description: Affiche le nombre de formes stockées dans votre bâtiment central. produced: title: Produit - description: Affiche tous les formes que votre usine entière produit, en incluant les formes intermédiaires. + description: Affiche tous les formes que votre usine produit, en incluant les formes intermédiaires. delivered: title: Délivré - description: Affiche les formes qui ont été livrées dans votre centre. + description: Affiche les formes qui ont été livrées dans votre bâtiment central. noShapesProduced: Aucune forme n'a été produite jusqu'à présent. # Displays the shapes per minute, e.g. '523 / m' @@ -398,7 +399,7 @@ ingame: Connectez l'extracteur avec un convoyeur vers votre centre !

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

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

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

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

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

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

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

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

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

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

Tipp: Tartsd lenyomva a SHIFT-et, hogy egyszerre több bányát helyezz le, és nyomj R-t a forgatáshoz. # All shop upgrades shopUpgrades: belt: - name: Belts, Distributor & Tunnels - description: Speed x → x + name: Futószalagok, Elosztók & Alagutak + description: x → x Sebesség miner: - name: Extraction - description: Speed x → x + name: Bányászat + description: x → x Sebesség processors: - name: Cutting, Rotating & Stacking - description: Speed x → x + name: Vágás, Forgatás & Összeillesztés + description: x → x Sebesség painting: - name: Mixing & Painting - description: Speed x → x + name: Keverés & Festés + description: x → x Sebesség # Buildings and their name / description buildings: - belt: - default: - name: &belt Conveyor Belt - description: Transports items, hold and drag to place multiple. - - miner: # Internal name for the Extractor - default: - name: &miner Extractor - description: Place over a shape or color to extract it. - - chainable: - name: Extractor (Chain) - description: Place over a shape or color to extract it. Can be chained. - - underground_belt: # Internal name for the Tunnel - default: - name: &underground_belt Tunnel - description: Allows to tunnel resources under buildings and belts. - - tier2: - name: Tunnel Tier II - description: Allows to tunnel resources under buildings and belts. - - splitter: # Internal name for the Balancer - default: - name: &splitter Balancer - description: Multifunctional - Evenly distributes all inputs onto all outputs. - - compact: - name: Merger (compact) - description: Merges two conveyor belts into one. - - compact-inverse: - name: Merger (compact) - description: Merges two conveyor belts into one. - - cutter: - default: - name: &cutter Cutter - description: Cuts shapes from top to bottom and outputs both halfs. If you use only one part, be sure to destroy the other part or it will stall! - quad: - name: Cutter (Quad) - description: Cuts shapes into four parts. If you use only one part, be sure to destroy the other part or it will stall! - - rotater: - default: - name: &rotater Rotate - description: Rotates shapes clockwise by 90 degrees. - ccw: - name: Rotate (CCW) - description: Rotates shapes counter clockwise by 90 degrees. - fl: - name: Rotate (180) - description: Rotates shapes by 180 degrees. - - stacker: - default: - name: &stacker Stacker - description: Stacks both items. If they can not be merged, the right item is placed above the left item. - - mixer: - default: - name: &mixer Color Mixer - description: Mixes two colors using additive blending. - - painter: - default: - name: &painter Painter - description: &painter_desc Colors the whole shape on the left input with the color from the right input. - double: - name: Painter (Double) - description: Colors the shapes on the left inputs with the color from the top input. - quad: - name: Painter (Quad) - description: Allows to color each quadrant of the shape with a different color. - mirrored: - name: *painter - description: *painter_desc - - trash: - default: - name: &trash Trash - description: Accepts inputs from all sides and destroys them. Forever. - - storage: - name: Storage - description: Stores excess items, up to a given capacity. Can be used as an overflow gate. hub: deliver: Deliver toUnlock: to unlock levelShortcut: LVL + + belt: + default: + name: &belt Futószalag + description: Elemeket szállít, tartsd nyomva az egérgombot egyszerre több lerakásához. + wire: default: - name: Energy Wire + name: &wire Energy Wire description: Allows you to transport energy. + + # Internal name for the Extractor + miner: + default: + name: &miner Bányász + description: Tedd egy alakzatra vagy színre a kibányászásához. + + chainable: + name: Bányász (összekapcsolható) + description: Tedd egy alakzatra vagy színre a kibányászásához. Több egymáshoz kapcsolható. + + # Internal name for the Tunnel + underground_belt: + default: + name: &underground_belt Alagút + description: Segítségével futószalagok és épületek alatt átvezethetők az elemek. + + tier2: + name: Alagút II + description: Segítségével futószalagok és épületek alatt átvezethetők az elemek. + + # Internal name for the Balancer + splitter: + default: + name: &splitter Elosztó + description: Többfunkciós - Egyenletesen szétosztja a bementeket a kimenetekre. + + compact: + name: Egyesítő (kompakt) + description: Két futószalagot egyesít. + + compact-inverse: + name: Egyesítő (kompakt) + description: Két futószalagot egyesít. + + cutter: + default: + name: &cutter Vágó + description: Függőlegesen félbevágja az alakzatokat. Ha csak az egyik felet akarod használni, ne felejtsd el a másikat kukába küldeni, különben eldugítja! + quad: + name: Vágó (negyedelő) + description: Négyfelé vágja az alakzatokat. Cuts shapes into four parts. Ha csak az egyik felet akarod használni, ne felejtsd el a többit a kukába küldeni, különben eldugítja! + advanced_processor: default: - name: Color Inverter + name: &advanced_processor Color Inverter description: Accepts a color or shape and inverts it. + + rotater: + default: + name: &rotater Forgató + description: Elforgatja az alakzatot óramutató irányában 90 fokkal. + ccw: + name: Forgató (fordított) + description: Elforgatja az alakzatot óramutatóval ellentétesen 90 fokkal. + fl: + name: Forgató (180) + description: Elforgatja az alakzatot 180 fokkal. + + stacker: + default: + name: &stacker Egyesítő + description: Egyesít két elemet. Ha nem lehet összeilleszteni őket, a jobboldali elem a baloldali tetejére kerül. + + mixer: + default: + name: &mixer Színkeverő + description: Összekever két színt összeadó színkeveréssel. + + painter: + default: + name: &painter Festő + description: &painter_desc Beszínezi az alakzatot a baloldali bemeneten a jobboldali bemeneten érkező színnel. + + mirrored: + name: *painter + description: *painter_desc + + double: + name: Festő (Dupla) + description: Beszínezi az alakzatokat a baloldali bemeneteken a fenti bemeneten érkező színnel. + + quad: + name: Festő (Négyszeres) + description: Az alakzat négy negyedét különböző színekkel lehet vele színezni. + + trash: + default: + name: &trash Kuka + description: Bármelyik irányból lehet hozzá csatlakozni, és megsemmisíti a beleküldött elemeket. Örökre. + + storage: + name: Tároló + description: Tárolja a fölös elemeket egy bizonyos kapacitásig. + energy_generator: deliver: Deliver + + # This will be shown before the amount, so for example 'For 123 Energy' toGenerateEnergy: For + default: - name: Energy Generator + name: &energy_generator Energy Generator description: Generates energy by consuming shapes. + wire_crossings: default: - name: Wire Splitter + name: &wire_crossings Wire Splitter description: Splits a energy wire into two. + merger: name: Wire Merger description: Merges two energy wires into one. diff --git a/translations/base-ind.yaml b/translations/base-ind.yaml index 781e55a9..80e1238a 100644 --- a/translations/base-ind.yaml +++ b/translations/base-ind.yaml @@ -19,13 +19,13 @@ # the basic structure so the game also detects it. # +--- steamPage: # This is the short text appearing on the steam page - shortText: shapez.io is a game about building factories to automate the creation and processing of increasingly complex shapes across an infinitely expanding map. - - # This is the text shown above the Discord link - discordLink: Official Discord - Chat with me! + shortText: shapez.io adalah permainan membangun pabrik-pabrik dengan tujuan untuk mengautomatiskan pembentukan dan pemrosesan bentuk-bentuk yang bertambah semakin kompleks di dalam area permainan yang meluas secara tak terhingga. + # This is the text shown above the discord link + discordLink: Tautan Resmi Discord – Obrol dengan saya! # This is the long description for the steam page - It is contained here so you can help to translate it, and I will regulary update the store page. # NOTICE: # - Do not translate the first line (This is the gif image at the start of the store) @@ -33,50 +33,50 @@ steamPage: longText: >- [img]{STEAM_APP_IMAGE}/extras/store_page_gif.gif[/img] - shapez.io is a game about building factories to automate the creation and processing of increasingly complex shapes across an infinitely expanding map. + shapez.io adalah permainan membangun pabrik-pabrik dengan tujuan untuk mengautomatiskan pembentukan dan pemrosesan bentuk-bentuk yang bertambah semakin kompleks di dalam area permainan yang meluas secara tak terhingga. - Upon delivering the requested shapes you'll progress within the game and unlock upgrades to speed up your factory. + Setelah pengiriman bentuk-bentuk yang diminta, Anda akan maju dalam permainan dan membuka tingkatan versi-versi mesin selanjutnya untuk mempercepat pabrik Anda. - As the demand for shapes increases, you'll have to scale up your factory to meet the demand - Don't forget about resources though, you'll have to expand across the [b]infinite map[/b]! + Seiring meningkatnya kesulitan dari bentuk-bentuk yang diminta, Anda harus meningkatkan pabrik Anda untuk mengatasi kesulitan tersebut – Jangan lupa dengan sumber-sumber daya, Anda harus memperluas ke seluruh [b]area yang tidak terbatas[/b]! - Soon you'll have to mix colors and paint your shapes with them - Combine red, green and blue color resources to produce different colors and paint shapes with them to satisfy the demand. + Kemudian Anda harus mencampurkan warna-warna dan mencat bentuk-bentuk dengannya – Campurkan merah, hijau, dan biru untuk memproduksi warna-warna lain dan mencat bentuk-bentuk dengannya untuk memenuhi permintaan. - This game features 18 progressive levels (Which should already keep you busy for hours!) but I'm constantly adding new content - There's a lot planned! + Permainan ini mempunyai 18 level-level progresif (yang mana akan membuat Anda sibuk berjam-jam!), akan tetapi saya akan terus menambahkan konten-konten baru – Ada banyak yang direncanakan! - Purchasing the game gives you access to the standalone version which has additional features, and you'll also receive access to newly developed features. + Membeli permainan ini akan memberikan Anda akses ke versi penuh yang memiliki fitur-fitur tambahan, dan Anda juga akan menerima akses ke fitur-fitur yang baru dikembangkan. - [b]Standalone Advantages[/b] + [b]Keuntungan Versi Penuh[/b] [list] - [*] Dark Mode - [*] Unlimited Waypoints - [*] Unlimited Savegames - [*] Additional settings - [*] Coming soon: Wires & Energy! Aiming for (roughly) end of July 2020. - [*] Coming soon: More Levels - [*] Allows me to further develop shapez.io ❤️ + [*] Versi Permainan Gelap + [*] Titik Arah Tak Terhingga + [*] Penyimpanan Permainan Tak Terhingga + [*] Pengaturan-pengaturan Tambahan + [*] Akan datang: Kawat & Energi! Akan dicoba untuk dicapai untuk (kira-kira) akhir Juli 2020. + [*] Akan datang: Level-level tambahan + [*] Memperkenankan saya untuk terus mengembangkan shapez.io ❤️ [/list] - [b]Future Updates[/b] + [b]Pembaruan di Masa Depan[/b] - I am updating the game often and trying to push an update at least once every week! + Saya seringkali membarui permainan ini dan terus mencoba untuk menciptakan pembaruan paling sedikit sekali seminggu! [list] - [*] Different maps and challenges (e.g. maps with obstacles) - [*] Puzzles (Deliver the requested shape with a restricted area / set of buildings) - [*] A story mode where buildings have a cost - [*] Configurable map generator (Configure resource/shape size/density, seed and more) - [*] Additional types of shapes - [*] Performance improvements (The game already runs pretty well!) - [*] And much more! + [*] Peta-peta dan tantangan-tantangan berbeda (contohnya, peta-peta dengan berbagai rintangan) + [*] Berbagai teka-teki (Kirim bentuk yang diminta dengan area terbatas atau sekelompok bangunan tertentu) + [*] Modus cerita dimana bangunan-bangunan memiliki biaya. + [*] Generator peta yang dapat dikonfigurasi (Konfigurasikan sumber daya/ukuran bentuk/kepadatan, benih dan lainnya) + [*] Tipe-tipe bentuk tambahan + [*] Peningkatan kinerja (Permainannya sudah bekerja cukup baik!) + [*] Dan masih banyak lagi! [/list] - [b]This game is open source![/b] + [b]Permainan ini bekerja secara open source![/b] - Anybody can contribute, I'm actively involved in the community and attempt to review all suggestions and take feedback into consideration where possible. - Be sure to check out my trello board for the full roadmap! + Siapa saja dapat berkontribusi, saya terlibat aktif di dalam komunitas dan akan mencoba untuk meninjau dan menerima semua saran untuk dipertimbangkan dimana memungkinkan. + Pastikan Anda periksa papan trello saya untuk peta perencanaan yang lengkap! - [b]Links[/b] + [b]Tautan-tautan[/b] [list] [*] [url=https://discord.com/invite/HN7EVzV]Official Discord[/url] @@ -87,8 +87,8 @@ steamPage: [/list] global: - loading: Loading - error: Error + loading: Memuat + error: Terdapat kesalahan # How big numbers are rendered, e.g. "10,000" thousandsDivider: "," @@ -104,25 +104,25 @@ global: trillions: T # Shown for infinitely big numbers - infinite: inf + infinite: tak terhingga time: # Used for formatting past time dates - oneSecondAgo: one second ago - xSecondsAgo: seconds ago - oneMinuteAgo: one minute ago - xMinutesAgo: minutes ago - oneHourAgo: one hour ago - xHoursAgo: hours ago - oneDayAgo: one day ago - xDaysAgo: days ago + oneSecondAgo: satu detik yang lalu + xSecondsAgo: detik yang lalu + oneMinuteAgo: satu menit yang lalu + xMinutesAgo: menit yang lalu + oneHourAgo: satu jam yang lalu + xHoursAgo: jam yang lalu + oneDayAgo: satu hari yang lalu + xDaysAgo: hari yang lalu # Short formats for times, e.g. '5h 23m' - secondsShort: s - minutesAndSecondsShort: m s - hoursAndMinutesShort: h m + secondsShort: det + minutesAndSecondsShort: m det + hoursAndMinutesShort: j m - xMinutes: minutes + xMinutes: menit keys: tab: TAB @@ -134,688 +134,686 @@ global: demoBanners: # This is the "advertisement" shown in the main menu and other various places - title: Demo Version + title: Versi Demo intro: >- - Get the standalone to unlock all features! + Dapatkan versi penuh untuk membuka semua fitur! mainMenu: - play: Play - continue: Continue - newGame: New Game - changelog: Changelog + play: Mulai Permainan + continue: Lanjutkan Permainan + newGame: Permainan Baru + changelog: Ganti Data Log subreddit: Reddit - importSavegame: Import - openSourceHint: This game is open source! - discordLink: Official Discord Server - helpTranslate: Help translate! - madeBy: Made by + importSavegame: Impor Data Simpanan + openSourceHint: Permainan ini bekerja secara open source! + discordLink: Server Discord Resmi + helpTranslate: Bantu Terjemahkan! + madeBy: Dibuat oleh # This is shown when using firefox and other browsers which are not supported. browserWarning: >- - Sorry, but the game is known to run slow on your browser! Get the standalone version or download chrome for the full experience. + Maaf, tetapi permainan ini biasanya lambat pada perambah (browser) Anda! Dapatkan versi penuh atau unduh Chrome untuk pengalaman sepenuhnya. savegameLevel: Level - savegameLevelUnknown: Unknown Level + savegameLevelUnknown: Level tidak diketahui dialogs: buttons: ok: OK - delete: Delete - cancel: Cancel - later: Later - restart: Restart - reset: Reset - getStandalone: Get Standalone - deleteGame: I know what I am doing - viewUpdate: View Update - showUpgrades: Show Upgrades - showKeybindings: Show Keybindings + delete: Hapus + cancel: Batal + later: Nanti + restart: Mulai Ulang + reset: Setel Ulang + getStandalone: Dapatkan Versi Penuh + deleteGame: Saya tahu apa yang saya kerjakan + viewUpdate: Tampilkan Pembaruan + showUpgrades: Tunjukkan Tingkatan + showKeybindings: Tunjukan Tombol Pintas importSavegameError: - title: Import Error + title: Kesalahan pada Impor text: >- - Failed to import your savegame: + Gagal memasukkan data simpanan Anda: importSavegameSuccess: - title: Savegame Imported + title: Impor Berhasil text: >- - Your savegame has been successfully imported. + Data simpanan Anda berhasil dimasukkan. gameLoadFailure: - title: Game is broken + title: Permainan Rusak text: >- - Failed to load your savegame: + Gagal memuat data simpanan Anda: confirmSavegameDelete: - title: Confirm deletion + title: Konfirmasi Penghapusan text: >- - Are you sure you want to delete the game? + Apakah Anda yakin untuk menghapus data permainan? savegameDeletionError: - title: Failed to delete + title: Gagal Menghapus text: >- - Failed to delete the savegame: + Gagal untuk menghapus data simpanan: restartRequired: - title: Restart required + title: Diperlukan untuk Memulai Kembali text: >- - You need to restart the game to apply the settings. + Anda harus memulai kembali permainan untuk menerapkan pengaturan. editKeybinding: - title: Change Keybinding - desc: Press the key or mouse button you want to assign, or escape to cancel. + title: Ganti Tombol Pintas + desc: Tekan tombol pada papan ketik atau tetikus yang ingin anda tetapkan, atau tekan escape untuk membatalkan. resetKeybindingsConfirmation: - title: Reset keybindings - desc: This will reset all keybindings to their default values. Please confirm. + title: Setel Ulang Tombol-tombol Pintas + desc: Ini akan menyetel ulang semua tombol pintas kepada pengaturan awalnya. Harap konfirmasi. keybindingsResetOk: - title: Keybindings reset - desc: The keybindings have been reset to their respective defaults! + title: Setel Ulang + desc: Tombol-tombol pintas sudah disetel ulang ke pengaturan awalnya! featureRestriction: - title: Demo Version - desc: You tried to access a feature () which is not available in the demo. Consider getting the standalone version for the full experience! + title: Versi Demo + desc: Anda mencoba untuk mengakses fitur () yang tidak tersedia pada versi demo. Pertimbangkan untuk mendapatkan versi penuh untuk pengalaman sepenuhnya! oneSavegameLimit: - title: Limited savegames - desc: You can only have one savegame at a time in the demo version. Please remove the existing one or get the standalone version! + title: Penyimpanan Permainan Terbatas + desc: Anda hanya dapat memiliki satu simpanan permainan dalam versi demo. Harap hapus yang telah ada atau dapatkan versi penuh! updateSummary: - title: New update! + title: Pembaruan Baru! desc: >- - Here are the changes since you last played: + Berikut perubahan-perubahan yang telah dibuat sejak Anda main terakhir kali: upgradesIntroduction: - title: Unlock Upgrades + title: Buka Tingkatan-tingkatan desc: >- - All shapes you produce can be used to unlock upgrades - Don't destroy your old factories! - The upgrades tab can be found on the top right corner of the screen. + Semua bentuk yang anda produksi dapat digunakan untuk membuka tingkatan baru - Jangan hancurkan pabrik-pabrik lama Anda! + Tab tingkatan dapat ditemukan di sudut atas kanan layar Anda. massDeleteConfirm: - title: Confirm delete + title: Konfirmasi Penghapusan desc: >- - You are deleting a lot of buildings ( to be exact)! Are you sure you want to do this? + Anda akan menghapus banyak bangunan (tepatnya )! Apakah Anda yakin untuk melakukannya? massCutConfirm: - title: Confirm cut + title: Pastikan Pemindahan desc: >- - You are cutting a lot of buildings ( to be exact)! Are you sure you want to do this? + Anda akan memindahkan banyak bangunan (tepatnya )! Apakah Anda yakin untuk melakukannya? massCutInsufficientConfirm: - title: Confirm cut + title: Tidak Mampu Memindahkan desc: >- - You can not afford to paste this area! Are you sure you want to cut it? + Anda tidak mampu menanggung biaya pemindahan area ini! Apakah Anda yakin untuk memindahkannya? blueprintsNotUnlocked: - title: Not unlocked yet + title: Belum Terbuka desc: >- - Complete level 12 to unlock Blueprints! + Selesaikan level 12 untuk membuka cetak biru! keybindingsIntroduction: - title: Useful keybindings + title: Tombol Pintas Berguna desc: >- - This game has a lot of keybindings which make it easier to build big factories. - Here are a few, but be sure to check out the keybindings!

- CTRL + Drag: Select an area.
- SHIFT: Hold to place multiple of one building.
- ALT: Invert orientation of placed belts.
+ Permainan ini memiliki banyak tombol pintas yang membuatnya lebih mudah untuk membangun pabrik-pabrik besar. + Berikut adalah beberapa, namun pastikan Anda perhatikan tombol-tombol pintasnya!

+ CTRL + Tarik: Pilih sebuah area.
+ SHIFT: Tahan untuk meletakkan beberapa kali bangunan yang.
+ ALT: Ganti orientasi sabuk konveyor yang telah diletakkan.
createMarker: - title: New Marker - titleEdit: Edit Marker - desc: Give it a meaningful name, you can also include a short key of a shape (Which you can generate here) + title: Penanda Baru + titleEdit: Sunting Penanda + desc: Berikan nama yang berarti, Anda juga dapat memasukkan tombol pintas suatu bentuk (yang dapat Anda buat disini) markerDemoLimit: - desc: You can only create two custom markers in the demo. Get the standalone for unlimited markers! + desc: Anda hanya dapat memuat dua penanda pada versi demo. Dapatkan versi penuh untuk penanda-penanda tak terhingga! exportScreenshotWarning: - title: Export screenshot - desc: You requested to export your base as a screenshot. Please note that this can be quite slow for a big base and even crash your game! + title: Ekspor Tangkapan Layar + desc: Anda meminta untuk mengekspor pangkalan pusat Anda sebagai tangkapan layar. Harap ketahui bahwa ini bisa menjadi lambat untuk pangkalan pusat yang besar dan bahkan dapat membuat permainan Anda mogok! ingame: # This is shown in the top left corner and displays useful keybindings in # every situation keybindingsOverlay: - moveMap: Move - selectBuildings: Select area - stopPlacement: Stop placement - rotateBuilding: Rotate building - placeMultiple: Place multiple - reverseOrientation: Reverse orientation - disableAutoOrientation: Disable auto-orientation - toggleHud: Toggle HUD - placeBuilding: Place building - createMarker: Create marker - delete: Delete - pasteLastBlueprint: Paste last blueprint - lockBeltDirection: Enable belt planner - plannerSwitchSide: Flip planner side - cutSelection: Cut - copySelection: Copy - clearSelection: Clear selection - pipette: Pipette - switchLayers: Switch layers + moveMap: Pindahkan + selectBuildings: Pilih area + stopPlacement: Hentikan peletakan + rotateBuilding: Putar bangunan + placeMultiple: Letakkan beberapa + reverseOrientation: Balik orientasi + disableAutoOrientation: Nonaktifkan orientasi otomatis. + toggleHud: Ganti HUD + placeBuilding: Letakan bangunan + createMarker: Ciptakan penanda + delete: Hapus + pasteLastBlueprint: Sisipkan cetak biru terakhir + lockBeltDirection: Aktifkan perencana sabuk konveyor + plannerSwitchSide: Balik sisi perencana + cutSelection: Pindahkan + copySelection: Gandakan + clearSelection: Hapus seleksi + pipette: Pipet + switchLayers: Ganti lapisan # Names of the colors, used for the color blind mode colors: - red: Red - green: Green - blue: Blue - yellow: Yellow - purple: Purple - cyan: Cyan - white: White - black: Black - uncolored: Gray + red: Merah + green: Hijau + blue: Biru + yellow: Kuning + purple: Ungu + cyan: Biru kehijauan + white: Putih + black: Hitam + uncolored: Abu-abu # Everything related to placing buildings (I.e. as soon as you selected a building # from the toolbar) buildingPlacement: # Buildings can have different variants which are unlocked at later levels, # and this is the hint shown when there are multiple variants available. - cycleBuildingVariants: Press to cycle variants. + cycleBuildingVariants: Tekan untuk ganti varian. # Shows the hotkey in the ui, e.g. "Hotkey: Q" hotkeyLabel: >- Hotkey: infoTexts: - speed: Speed - range: Range - storage: Storage - oneItemPerSecond: 1 item / second - itemsPerSecond: items / s + speed: Kecepatan + range: Rentang + storage: Penyimpanan + oneItemPerSecond: satu artikel / detik + itemsPerSecond: artikel / detik itemsPerSecondDouble: (x2) - tiles: tiles + tiles: ubin # The notification when completing a level levelCompleteNotification: # is replaced by the actual level, so this gets 'Level 03' for example. levelTitle: Level - completed: Completed - unlockText: Unlocked ! - buttonNextLevel: Next Level + completed: Selesai + unlockText: Membuka ! + buttonNextLevel: Level Selanjutnya # Notifications on the lower right notifications: - newUpgrade: A new upgrade is available! - gameSaved: Your game has been saved. + newUpgrade: Tingkatan baru tersedia! + gameSaved: Permainan Anda telah disimpan. # The "Upgrades" window shop: - title: Upgrades - buttonUnlock: Upgrade + title: Tingkatan-tingkatan + buttonUnlock: Tingkatkan # Gets replaced to e.g. "Tier IX" - tier: Tier + tier: Tingkat # The roman number for each tier tierLabels: [I, II, III, IV, V, VI, VII, VIII, IX, X] - maximumLevel: MAXIMUM LEVEL (Speed x) + maximumLevel: LEVEL MAKSIMUM (Kecepatan x) # The "Statistics" window statistics: - title: Statistics + title: Statistika dataSources: stored: - title: Stored - description: Displaying amount of stored shapes in your central building. + title: Tersimpan + description: Menunjukan jumlah bentuk-bentuk yang tersimpan pada bangunan pusat Anda. produced: - title: Produced - description: Displaying all shapes your whole factory produces, including intermediate products. + title: Terproduksi + description: Menunjukkan semua bentuk yang diproduksi seluruh pabrik Anda, termasuk produk-produk antara. delivered: - title: Delivered - description: Displaying shapes which are delivered to your central building. - noShapesProduced: No shapes have been produced so far. + title: Terkirim + description: Menunjukkan bentuk-bentuk yang telah terkirim ke bangunan pusat Anda. + noShapesProduced: Sejauh ini belum diproduksi. # Displays the shapes per minute, e.g. '523 / m' shapesPerMinute: / m # Settings menu, when you press "ESC" settingsMenu: - playtime: Playtime + playtime: Waktu bermain - buildingsPlaced: Buildings - beltsPlaced: Belts + buildingsPlaced: Bangunan + beltsPlaced: Sabuk konveyor buttons: - continue: Continue - settings: Settings - menu: Return to menu + continue: Lanjutkan + settings: Pengaturan + menu: Kembali ke menu # Bottom left tutorial hints tutorialHints: - title: Need help? - showHint: Show hint - hideHint: Close + title: Butuh bantuan? + showHint: Tampilkan petunjuk + hideHint: Tutup # When placing a blueprint blueprintPlacer: - cost: Cost + cost: Biaya # Map markers waypoints: - waypoints: Markers - hub: HUB - description: Left-click a marker to jump to it, right-click to delete it.

Press to create a marker from the current view, or right-click to create a marker at the selected location. - creationSuccessNotification: Marker has been created. + waypoints: Penanda + hub: PUSAT + description: Klik tombol kiri tetikus pada penanda untuk melompat kepadanya, klik tombol kanan untuk menghapusnya.

Tekan untuk membuat penanda dari sudut pandang saat ini, atau klik tombol kanan untuk membuat penanda pada lokasi yang dipilih. + creationSuccessNotification: Penanda telah dibuat. # Shape viewer shapeViewer: - title: Layers - empty: Empty - copyKey: Copy Key + title: Lapisan-lapisan + empty: Kosong + copyKey: Gandakan tombol # Interactive tutorial interactiveTutorial: - title: Tutorial + title: Penuntun hints: - 1_1_extractor: Place an extractor on top of a circle shape to extract it! + 1_1_extractor: Letakkan ekstraktor diatas bentuk lingkaran untuk mengekstrak bentuk tersebut! 1_2_conveyor: >- - Connect the extractor with a conveyor belt to your hub!

Tip: Click and drag the belt with your mouse! + Hubungkan ekstraktor dengan sabuk konveyor ke pusat pangkalan Anda!

Kiat: Klik dan seret sabuk konveyor dengan tetikus! 1_3_expand: >- - This is NOT an idle game! Build more extractors and belts to finish the goal quicker.

Tip: Hold SHIFT to place multiple extractors, and use R to rotate them. + Ini BUKAN permainan menganggur! Bangun lebih banyak ekstraktor dan sabuk konveyor untuk menyelesaikan obyektif dengan lebih cepat.

Kiat: Tahan tombolSHIFT untuk meletakkan beberapa ekstraktor, dan gunakan tombol R untuk memutar. # All shop upgrades shopUpgrades: belt: - name: Belts, Distributor & Tunnels - description: Speed x → x + name: Sabuk konveyor, Pembagi Arus & Terowongan + description: Kecepatan x → x miner: - name: Extraction - description: Speed x → x + name: Ekstraksi + description: Kecepatan x → x processors: - name: Cutting, Rotating & Stacking + name: Memotong, Memutar & Menyusun description: Speed x → x painting: - name: Mixing & Painting - description: Speed x → x + name: Mencampur & Mencat + description: Kecepatan x → x # Buildings and their name / description buildings: hub: - deliver: Deliver - toUnlock: to unlock + deliver: Kirim + toUnlock: untuk membuka levelShortcut: LVL belt: default: - name: &belt Conveyor Belt - description: Transports items, hold and drag to place multiple. + name: &belt Sabuk Konveyor + description: Mengangkut artikel-artikel, tahan dan seret untuk meletakkan beberapa. wire: default: - name: &wire Energy Wire - description: Allows you to transport energy. + name: &wire Kawat Energi + description: Memungkinkan anda untuk mengangkut energi. miner: # Internal name for the Extractor default: - name: &miner Extractor - description: Place over a shape or color to extract it. + name: &miner Ekstraktor + description: Letakkan diatas sumber bentuk atau warna untuk mengekstraksi mereka. chainable: - name: Extractor (Chain) - description: Place over a shape or color to extract it. Can be chained. + name: Ekstraktor (Berantai) + description: Letakkan di atas sumber bentuk atau warna untuk mengekstraksi mereka. Dapat dirantai. underground_belt: # Internal name for the Tunnel default: - name: &underground_belt Tunnel - description: Allows you to tunnel resources under buildings and belts. + name: &underground_belt Terowongan + description: Memungkinkan Anda untuk mengangkut sumber-sumber daya dibawah bangunan-bangunan atau sabuk konveyor. tier2: - name: Tunnel Tier II - description: Allows you to tunnel resources under buildings and belts. + name: Terowongan Tingkat II + description: Memungkinkan Anda untuk mengangkut sumber-sumber daya dibawah bangunan-bangunan atau sabuk konveyor. splitter: # Internal name for the Balancer default: - name: &splitter Balancer - description: Multifunctional - Evenly distributes all inputs onto all outputs. + name: &splitter Pengimbang + description: Multifungsi – Mendistribusi secara merata semua masukan ke semua keluaran. compact: - name: Merger (compact) - description: Merges two conveyor belts into one. + name: Penggabung (Padat) + description: Menggabungkan dua sabuk konveyor menjadi satu. compact-inverse: - name: Merger (compact) - description: Merges two conveyor belts into one. + name: Penggabung (Padat) + description: Menggabungkan dua sabuk konveyor menjadi satu. cutter: default: - name: &cutter Cutter - description: Cuts shapes from top to bottom and outputs both halves. If you use only one part, be sure to destroy the other part or it will stall! + name: &cutter Pemotong + description: Memotong bentuk-bentuk secara vertikal dan mengeluarkan kedua bagian. Apabila Anda hanya menggunakan satu bagian, pastikan Anda lenyapkan bagian lain atau mesin akan macet! quad: - name: Cutter (Quad) - description: Cuts shapes into four parts. If you use only one part, be sure to destroy the other parts or it will stall! + name: Pemotong (Empat Bagian) + description: Memotong bentuk-bentuk menjadi empat bagian. Apabila Anda hanya menggunakan satu bagian, pastikan Anda lenyapkan bagian-bagian lain atau mesin akan macet! advanced_processor: default: - name: &advanced_processor Color Inverter - description: Accepts a color or shape and inverts it. + name: &advanced_processor Pembalik Warna + description: Menerima warna atau bentuk dan kemudian membaliknya. rotater: default: - name: &rotater Rotate - description: Rotates shapes clockwise by 90 degrees. + name: &rotater Pemutar + description: Memutar bentuk searah jarum jam sebesar 90 derajat. ccw: - name: Rotate (CCW) - description: Rotates shapes counter-clockwise by 90 degrees. + name: Pemutar (Berlawanan Arah Jarum Jam) + description: Memutar bentuk berlawanan arah jarum jam sebesar 90 derajat. fl: - name: Rotate (180) - description: Rotates shapes by 180 degrees. + name: Pemutar (180) + description: Memutar bentuk sebesar 180 derajat. stacker: default: - name: &stacker Stacker - description: Stacks both items. If they can not be merged, the right item is placed above the left item. + name: &stacker Penyusun + description: Menggabungkan kedua artikel. Apabila mereka tidak dapat digabungkan, artikel kanan akan diletakkan diatas artikel kiri. mixer: default: - name: &mixer Color Mixer - description: Mixes two colors using additive blending. + name: &mixer Pencampur Warna + description: Mencampurkan dua warna menggunakan campuran aditif. painter: default: - name: &painter Painter - description: &painter_desc Colors the whole shape on the left input with the color from the top input. - + name: &painter Pencat + description: &painter_desc Mencat keseluruhan bentuk dari input kiri dengan warna dari input atas. mirrored: name: *painter description: *painter_desc double: - name: Painter (Double) - description: Colors the shapes on the left inputs with the color from the top input. + name: Pencat (Ganda) + description: Mencat bentuk-bentuk dari input kiri dengan warna dari input atas. quad: - name: Painter (Quad) - description: Allows you to color each quadrant of the shape with a different color. + name: Pencat (Empat Bagian) + description: Memungkinkan Anda untuk mencat setiap kuadran bentuk dengan warna-warna berbeda. trash: default: - name: &trash Trash - description: Accepts inputs from all sides and destroys them. Forever. + name: &trash Tong Sampah + description: Menerima input dari semua sisi dan menghancurkannya. Selamanya. storage: - name: Storage - description: Stores excess items, up to a given capacity. Can be used as an overflow gate. - + name: Penyimpanan + description: Menyimpan artikel-artikel berlebih, sampai kapasitas tertentu. Dapat dipergunakan sebagai gerbang luapan. energy_generator: - deliver: Deliver + deliver: Pengiriman # This will be shown before the amount, so for example 'For 123 Energy' - toGenerateEnergy: For + toGenerateEnergy: Untuk default: - name: &energy_generator Energy Generator - description: Generates energy by consuming shapes. + name: &energy_generator Pembangkit Energi + description: Menciptakan energy dengan mengonsumsi bentuk-bentuk. wire_crossings: default: - name: &wire_crossings Wire Splitter - description: Splits a energy wire into two. + name: &wire_crossings Pembelah Kawat + description: Membelah satu kawat energy menjadi dua. merger: - name: Wire Merger - description: Merges two energy wires into one. + name: Penggabung Kawat + description: Menggabungkan dua kawat energy menjadi satu. storyRewards: # Those are the rewards gained from completing the store reward_cutter_and_trash: - title: Cutting Shapes - desc: You just unlocked the cutter - it cuts shapes half from top to bottom regardless of its orientation!

Be sure to get rid of the waste, or otherwise it will stall - For this purpose I gave you a trash, which destroys everything you put into it! + title: Memotong Bentuk + desc: Anda baru saja membuka pemotong - ia memotong bentuk-bentuk separuhnya dari atas ke bawah tanpa memperhatikan orientasinya!

Pastikan Anda membuang yang tidak terpakai, atau mesin akan macet - Untuk tujuan ini saya memberikan Anda tong sampah, yang menghancurkan semua yang anda masukkan kedalamnya! reward_rotater: - title: Rotating - desc: The rotater has been unlocked! It rotates shapes clockwise by 90 degrees. + title: Memutar + desc: Pemutar telah dibuka! Ia memutar bentuk-bentuk searah jarum jam sebesar 90 derajat. reward_painter: - title: Painting + title: Pengecatan desc: >- - The painter has been unlocked - Extract some color veins (just as you do with shapes) and combine it with a shape in the painter to color them!

PS: If you are colorblind, there is a colorblind mode in the settings! + Pencat telah dibuka – Ekstraksi beberapa warna (seperti yang Anda lakukan dengan bentuk) dan kemudian kombinasikan dengan bentuk di dalam pencat untuk mewarnai mereka!

Catatan: Apabila Anda buta warna, terdapat mode buta warna di dalam pengaturan! reward_mixer: - title: Color Mixing - desc: The mixer has been unlocked - Combine two colors using additive blending with this building! + title: Pencampuran Warna + desc: Pencampur telah dibuka – Kombinasikan dua warna menggunakan pencampuran aditif dengan bangunan ini! reward_stacker: - title: Combiner - desc: You can now combine shapes with the combiner! Both inputs are combined, and if they can be put next to each other, they will be fused. If not, the right input is stacked on top of the left input! + title: Penyusun + desc: Anda sekarang dapat mengombinasikan bentuk-bentuk dengan penyusun! Kedua input akan dikombinasikan, dan apabila mereka dapat diletakan disebelah satu sama lain, mereka akan terpadukan. Apabila tidak dapat, input kanan akan diletakkan diatas input kiri! reward_splitter: - title: Splitter/Merger - desc: The multifunctional balancer has been unlocked - It can be used to build bigger factories by splitting and merging items onto multiple belts!

+ title: Pembagi/Penggabung + desc: Pengimbang multifungsi telah dibuka – Ia dapat digunakan untuk membangun pabrik yang lebih besar dengan membagi dan menggabungkan artikel-artikel ke berbagai sabuk konveyor!

reward_tunnel: - title: Tunnel - desc: The tunnel has been unlocked - You can now tunnel items through belts and buildings with it! + title: Terowongan + desc: Terowongan telah dibuka – Sekarang Anda dapat memindahkan artikel-artikel melalui terowongan di bawah sabuk-sabuk konveyor dan bangungan-bangunan dengannya! reward_rotater_ccw: - title: CCW Rotating - desc: You have unlocked a variant of the rotater - It allows you to rotate shapes counter-clockwise! To build it, select the rotater and press 'T' to cycle through its variants! + title: Memutar Berlawanan Arah Jarum Jam + desc: Anda telah membuka varian dari Pemutar - Ia memungkinkan Anda untuk memutar bentuk-bentuk berlawanan arah jarum jam! Untuk membangunnya, pilih pemutar dan tekan 'T' to memilih varian! reward_miner_chainable: - title: Chaining Extractor - desc: You have unlocked the chaining extractor! It can forward its resources to other extractors so you can more efficiently extract resources! + title: Merantai Ekstraktor + desc: Anda telah membuka ekstraktor rantai! Ia dapat meneruskan sumberdaya ekstraksinya ke ekstraktor selanjutnya sehingga Anda dapat mengekstraksi dengan lebih efisien! reward_underground_belt_tier_2: - title: Tunnel Tier II - desc: You have unlocked a new variant of the tunnel - It has a bigger range, and you can also mix-n-match those tunnels now! + title: Terowongan Tingkat II + desc: Anda telah membuka varian baru terowongan - Ia memiliki jangkauan yang lebih panjang, dan sekarang Anda juga dapat memadukan terowongan-terowongan tersebut! reward_splitter_compact: - title: Compact Balancer + title: Pengimbang Padat desc: >- - You have unlocked a compact variant of the balancer - It accepts two inputs and merges them into one belt! + Anda telah membuka varian padat dari pengimbang - Ia menerima dua input dan menggabungkannya ke dalam satu konveyor! reward_cutter_quad: - title: Quad Cutting - desc: You have unlocked a variant of the cutter - It allows you to cut shapes in four parts instead of just two! + title: Pemotongan Empat Bagian + desc: Anda telah membuka varian dari pemotong - Ia memungkinkan Anda memotong bentuk-bentuk ke dalam empat bagian daripada hanya dua bagian! reward_painter_double: - title: Double Painting - desc: You have unlocked a variant of the painter - It works as the regular painter but processes two shapes at once consuming just one color instead of two! + title: Pengecatan Ganda + desc: Anda telah membuka varian dari pencat - Ia bekerja seperti pencat biasa namun dapat memproses dua bentuk sekaligus mengonsumsi hanya satu warna daripada dua! reward_painter_quad: - title: Quad Painting - desc: You have unlocked a variant of the painter - It allows you to paint each part of the shape individually! + title: Pengecatan Empat Bagian + desc: Anda telah membuka varian dari pencat - Ia memungkinkan Anda untuk mencat setiap bagian dari masing-masing bentuk sendiri-sendiri! reward_storage: - title: Storage Buffer - desc: You have unlocked a variant of the trash - It allows you to store items up to a given capacity! + title: Penyangga Penyimpanan + desc: Anda telah membuka varian dari tong sampah - Ia memungkinkan Anda untuk menyimpan artikel-artikel sebanyak kapasitas tertentu! reward_freeplay: - title: Freeplay - desc: You did it! You unlocked the free-play mode! This means that shapes are now randomly generated! (No worries, more content is planned for the standalone!) + title: Permainan Bebas + desc: Anda berhasil! Anda telah membuka mode permainan bebas! Ini berarti sekarang bentuk-bentuk akan dihasilkan secara acak! (Jangan khawatir, lebih banyak konten akan direncanakan untuk versi penuh!) reward_blueprints: - title: Blueprints - desc: You can now copy and paste parts of your factory! Select an area (Hold CTRL, then drag with your mouse), and press 'C' to copy it.

Pasting it is not free, you need to produce blueprint shapes to afford it! (Those you just delivered). + title: Cetak Biru + desc: Anda sekarang dapat menyalin dan meletakkan bagian dari pabrik Anda! Pilih sebuah area (tahan CTRL, lalu seret dengan tetikus), dan tekan 'C' untuk menggandakannya.

Untuk meletakannya tidak gratis, Anda harus memproduksi bentuk cetak biru untuk dapat melakukannya! (Bentuk yang baru saja anda kirim). # Special reward, which is shown when there is no reward actually no_reward: - title: Next level + title: Level Selanjutnya desc: >- - This level gave you no reward, but the next one will!

PS: Better don't destroy your existing factory - You need all those shapes later again to unlock upgrades! + Level ini tidak memiliki hadiah, namun yang selanjutnya akan!

Catatan: Sebaiknya Anda jangan hancurkan pabrik yang telah ada – Anda membutuhkan semua bentuk-bentuk tersebut lagi nanti untuk membuka tingkatan-tingkatan selanjutnya! no_reward_freeplay: - title: Next level + title: Level Selanjutnya desc: >- - Congratulations! By the way, more content is planned for the standalone! + Selamat! Omong-omong, lebih banyak konten telah direncanakan untuk versi penuh! settings: - title: Settings + title: Pengaturan categories: - general: General - userInterface: User Interface - advanced: Advanced + general: Umum + userInterface: Antarmuka Pengguna + advanced: Tingkat Tinggi versionBadges: - dev: Development - staging: Staging - prod: Production - buildDate: Built + dev: Pengembangan + staging: Pementasan + prod: Produksi + buildDate: Dibangun labels: uiScale: - title: Interface scale + title: Skala Antarmuka description: >- - Changes the size of the user interface. The interface will still scale based on your device's resolution, but this setting controls the amount of scaling. + Ganti ukuran antarmuka pengguna. Antarmuka tetap akan berskalakan berdasar resolusi peralatan Anda, tetapi pengaturan ini mengontrol besar skala. scales: - super_small: Super small - small: Small - regular: Regular - large: Large - huge: Huge + super_small: Sangat kecil + small: Kecil + regular: Reguler + large: Besar + huge: Sangat besar autosaveInterval: - title: Autosave Interval + title: Jeda Penyimpanan Otomatis description: >- - Controls how often the game saves automatically. You can also disable it entirely here. + Mengatur seberapa sering permainan menyimpan secara otomatis. Anda juga dapat menonaktifkannya sama sekali disini. intervals: - one_minute: 1 Minute - two_minutes: 2 Minutes - five_minutes: 5 Minutes - ten_minutes: 10 Minutes - twenty_minutes: 20 Minutes - disabled: Disabled + one_minute: 1 Menit + two_minutes: 2 Menit + five_minutes: 5 Menit + ten_minutes: 10 Menit + twenty_minutes: 20 Menit + disabled: Dinonaktifkan scrollWheelSensitivity: - title: Zoom sensitivity + title: Kepekaan perbesaran description: >- - Changes how sensitive the zoom is (Either mouse wheel or trackpad). + Mengubah seberapa peka perbesaran yang dilakukan (baik dengan roda tetikus atau trackpad). sensitivity: - super_slow: Super slow - slow: Slow - regular: Regular - fast: Fast - super_fast: Super fast + super_slow: Sangat lambat + slow: Lambat + regular: Reguler + fast: Cepat + super_fast: Sangat cepat movementSpeed: - title: Movement speed + title: Kecepatan gerakan description: >- - Changes how fast the view moves when using the keyboard. + Mengubah seberapa cepat pandangan bergerak ketika menggunakan papan ketik. speeds: - super_slow: Super slow - slow: Slow - regular: Regular - fast: Fast - super_fast: Super Fast - extremely_fast: Extremely Fast + super_slow: Sangat lambat + slow: Lambat + regular: Reguler + fast: Cepat + super_fast: Sangat cepat + extremely_fast: Luar biasa cepat language: - title: Language + title: Bahasa description: >- - Change the language. All translations are user-contributed and might be incomplete! + Ganti bahasa. Semua terjemahan adalah contribusi pengguna dan mungkin saja tidak lengkap! enableColorBlindHelper: - title: Color Blind Mode + title: Mode buta warna description: >- - Enables various tools which allow you to play the game if you are color blind. + Mengaktifkan berbagai peralatan yang memungkinkan Anda bermain apabila Anda buta warna. fullscreen: - title: Fullscreen + title: Layar penuh description: >- - It is recommended to play the game in fullscreen to get the best experience. Only available in the standalone. + Direkomendasikan untuk bermain dengan layar penuh untuk mendapatkan pengalaman terbaik. Hanya tersedia dalam versi penuh. soundsMuted: - title: Mute Sounds + title: Bisukan suara description: >- - If enabled, mutes all sound effects. + Apabila diaktifkan, membisukan semua efek suara. musicMuted: - title: Mute Music + title: Bisukan musik description: >- - If enabled, mutes all music. + Apabila diaktifkan, membisukan semua musik. theme: - title: Game theme + title: Tema permainan description: >- - Choose the game theme (light / dark). + Pilih tema permainan (terang/gelap). themes: - dark: Dark - light: Light + dark: Gelap + light: Terang refreshRate: - title: Simulation Target + title: Target Simulasi description: >- - If you have a 144hz monitor, change the refresh rate here so the game will properly simulate at higher refresh rates. This might actually decrease the FPS if your computer is too slow. + Apabila Anda memiliki monitor 144hz, ganti laju penyegaran sehingga permainan dapat disimulasikan dengan benar pada laju yang lebih tinggi. Ini mungkin saja mengurangi laju bingkai per detik (frames per second) apabila computer anda terlalu lambat. alwaysMultiplace: - title: Multiplace + title: Peletakkan berganda description: >- - If enabled, all buildings will stay selected after placement until you cancel it. This is equivalent to holding SHIFT permanently. + Apabila diaktifkan, semua bangunan akan tetap terpilih setelah penempatan sampai Anda membatalkannya. Ini sama saja dengan menahan tombol SHIFT secara permanen. offerHints: - title: Hints & Tutorials + title: Petunjuk & penuntun description: >- - Whether to offer hints and tutorials while playing. Also hides certain UI elements up to a given level to make it easier to get into the game. + Apakah akan menawarkan petunjuk dan penuntun ketika bermain. Juga menyembunyikan elemen-elemen antarmuka pengguna (user interface) tertentu sampai level tertentu untuk membuat lebih mudah untuk bermain. enableTunnelSmartplace: - title: Smart Tunnels + title: Terowongan cerdas description: >- - When enabled, placing tunnels will automatically remove unnecessary belts. This also enables you to drag tunnels and excess tunnels will get removed. + Ketika diaktifkan, proses penempatan terowongan akan menghapus konveyor yang tidak berguna secara otomatis. Ini juga memungkinkan Anda untuk menyeret terowongan dan kelebihan terowongan akan dihilangkan. vignette: - title: Vignette + title: Vinyet description: >- - Enables the vignette, which darkens the screen corners and makes text easier to read. + Mengaktifkan vinyet, yang menggelapkan sudut-sudut layar dan membuat teks lebih mudah dibaca. rotationByBuilding: - title: Rotation by building type + title: Pemutaran masing-masing tipe bangunan description: >- - Each building type remembers the rotation you last set it to individually. This may be more comfortable if you frequently switch between placing different building types. + Setiap tipe bangunan mengingat putaran yang Anda tetapkan kepadanya. Ini mungkin lebih nyaman apabila Anda sering berganti untuk menempatkan berbagai tipe bangunan. compactBuildingInfo: - title: Compact Building Infos + title: Pemadatan informasi banguna description: >- - Shortens info boxes for buildings by only showing their ratios. Otherwise a description and image is shown. + Memendekkan kotak-kotak informasi bangunan-bangunan dengan hanya menampilkan rasionya. Jika tidak, deskripsi dan gambar ditampilkan. disableCutDeleteWarnings: - title: Disable Cut/Delete Warnings + title: Nonaktifkan peringatan pemindahan/penghapusan description: >- - Disables the warning dialogs brought up when cutting/deleting more than 100 entities. + Menonaktifkan peringatan yang muncul ketikan pemindahkan/menghapus lebih dari 100 entitas. keybindings: - title: Keybindings + title: Tombol pintas hint: >- - Tip: Be sure to make use of CTRL, SHIFT and ALT! They enable different placement options. + Petunjuk: Pastikan Anda menggunakan CTRL, SHIFT and ALT! Mereka memungkinkan berbagai opsi penempatan. - resetKeybindings: Reset Keybindings + resetKeybindings: Setel Ulang Tombol Pintas categoryLabels: - general: Application - ingame: Game - navigation: Navigating - placement: Placement - massSelect: Mass Select - buildings: Building Shortcuts - placementModifiers: Placement Modifiers + general: Aplikasi + ingame: Permainan + navigation: Navigasi + placement: Penempatan + massSelect: Pemilihan massal + buildings: Tombol pintas bangunan + placementModifiers: Pengubah penempatan mappings: - confirm: Confirm - back: Back - mapMoveUp: Move Up - mapMoveRight: Move Right - mapMoveDown: Move Down - mapMoveLeft: Move Left - mapMoveFaster: Move Faster - centerMap: Center Map + confirm: Konfirmasi + back: Kembali + mapMoveUp: Geser ke atas + mapMoveRight: Geser ke kanan + mapMoveDown: Geser ke bawah + mapMoveLeft: Geser ke kiri + mapMoveFaster: Geser lebih cepat + centerMap: Pusat peta - mapZoomIn: Zoom in - mapZoomOut: Zoom out - createMarker: Create Marker + mapZoomIn: Perbesar + mapZoomOut: Perkecil + createMarker: Buat penanda - menuOpenShop: Upgrades - menuOpenStats: Statistics - menuClose: Close Menu + menuOpenShop: Tingkatan-tingkatan + menuOpenStats: Statistik + menuClose: Tutup menu - toggleHud: Toggle HUD - toggleFPSInfo: Toggle FPS and Debug Info - switchLayers: Switch layers - exportScreenshot: Export whole Base as Image + toggleHud: Alihkan HUD + toggleFPSInfo: Alihkan laju bingkan per detik (frame per second) dan informasi debug + switchLayers: Ganti lapisan + exportScreenshot: Ekspor keseluruhan pangkalan pusat sebagai gambar belt: *belt splitter: *splitter underground_belt: *underground_belt @@ -830,49 +828,49 @@ keybindings: trash: *trash wire: *wire - pipette: Pipette - rotateWhilePlacing: Rotate + pipette: Pipet + rotateWhilePlacing: Putar rotateInverseModifier: >- - Modifier: Rotate CCW instead - cycleBuildingVariants: Cycle Variants - confirmMassDelete: Delete area - pasteLastBlueprint: Paste last blueprint - cycleBuildings: Cycle Buildings - lockBeltDirection: Enable belt planner + Modifier: Putar berlawanan arah jarum jam sebagai gantinya + cycleBuildingVariants: Ganti varian + confirmMassDelete: Hapus area + pasteLastBlueprint: Gandakan cetak biru terakhir + cycleBuildings: Ganti bangunan + lockBeltDirection: Aktifkan perencana konveyor switchDirectionLockSide: >- - Planner: Switch side + Planner: Alih sisi - massSelectStart: Hold and drag to start - massSelectSelectMultiple: Select multiple areas - massSelectCopy: Copy area - massSelectCut: Cut area + massSelectStart: Tahan dan seret untuk memulai + massSelectSelectMultiple: Pilih berbagai area + massSelectCopy: Gandakan area + massSelectCut: Pindahkan area - placementDisableAutoOrientation: Disable automatic orientation - placeMultiple: Stay in placement mode - placeInverse: Invert automatic belt orientation + placementDisableAutoOrientation: Nonaktifkan orientasi otomatis + placeMultiple: Tinggal di mode penempatan + placeInverse: Balikkan orientasi otomatis konveyor about: - title: About this Game + title: Tentang permainan ini body: >- - This game is open source and developed by Tobias Springer (this is me).

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

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

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

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

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

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

+ Lagunya dibuat oleh Peppsen - Dia mengagumkan.

- Finally, huge thanks to my best friend Niklas - Without our factorio sessions, this game would never have existed. + Akhirnya, banyak terima kasih kepada teman baik saya Niklas - Tanpa sesi-sesi factorio kami, permainan ini tidak mungkin tercipta. changelog: - title: Changelog + title: Catatan Perubahan demo: features: - restoringGames: Restoring savegames - importingGames: Importing savegames - oneGameLimit: Limited to one savegame - customizeKeybindings: Customizing Keybindings - exportingBase: Exporting whole Base as Image + restoringGames: Mengembalikan simpanan permainan + importingGames: Memasukkan simpanan permainan + oneGameLimit: Terbatas pada satu simpanan permainan + customizeKeybindings: Sesuaikan tombol-tombol pintas + exportingBase: Mengekspor keseluruhan pangkalan pusat sebagai gambar - settingNotAvailable: Not available in the demo. + settingNotAvailable: Tidak tersedia dalam versi demo. diff --git a/translations/base-it.yaml b/translations/base-it.yaml index c8431c68..df45601e 100644 --- a/translations/base-it.yaml +++ b/translations/base-it.yaml @@ -19,6 +19,7 @@ # the basic structure so the game also detects it. # +--- steamPage: # This is the short text appearing on the steam page shortText: In shapez.io potrai costruire delle fabbriche per automatizzare la creazione e la combinazione di forme sempre più complesse, in una mappa infinita. diff --git a/translations/base-ja.yaml b/translations/base-ja.yaml index edfc7219..cdb56104 100644 --- a/translations/base-ja.yaml +++ b/translations/base-ja.yaml @@ -19,6 +19,7 @@ # the basic structure so the game also detects it. # +--- steamPage: # This is the short text appearing on the steam page shortText: shapez.ioは無限のマップ内で様々な"形"を資源とし、段々と複雑になっていく形の作成や合成の自動化を目指して工場を構築するゲームです。 @@ -411,7 +412,7 @@ ingame: cyan: シアン white: 白 uncolored: 無色 - black: Black + black: 黒 shapeViewer: title: レイヤー empty: 空 @@ -491,8 +492,8 @@ buildings: name: 回転機 (逆) description: 形を反時計回り方向に90度回転します。 fl: - name: Rotate (180) - description: Rotates shapes by 180 degrees. + name: 回転機 (180) + description: 形を180度回転します。 stacker: default: @@ -533,20 +534,20 @@ buildings: advanced_processor: default: name: Color Inverter - description: Accepts a color or shape and inverts it. + description: 入力された色や形の色を反転します。 energy_generator: deliver: Deliver toGenerateEnergy: For default: - name: Energy Generator - description: Generates energy by consuming shapes. + name: エネルギー発電機 + description: 入力された形を使って、エネルギーを発電します。 wire_crossings: default: - name: Wire Splitter - description: Splits a energy wire into two. + name: ワイヤー分配機 + description: 1つのワイヤーを2つのワイヤーに分配します。 merger: - name: Wire Merger - description: Merges two energy wires into one. + name: ワイヤー合流機 + description: 2つのワイヤーを1つのワイヤーに合流します。 storyRewards: # Those are the rewards gained from completing the store diff --git a/translations/base-kor.yaml b/translations/base-kor.yaml index 899507e1..26f85da9 100644 --- a/translations/base-kor.yaml +++ b/translations/base-kor.yaml @@ -19,6 +19,7 @@ # the basic structure so the game also detects it. # +--- steamPage: # This is the short text appearing on the steam page shortText: shapez.io는 무한한 공간에서 점점 더 복잡한 도형의 생산과 조합을 자동화하는 공장을 짓는 게임입니다. diff --git a/translations/base-lt.yaml b/translations/base-lt.yaml index 122dd3cc..79a450bf 100644 --- a/translations/base-lt.yaml +++ b/translations/base-lt.yaml @@ -19,6 +19,7 @@ # the basic structure so the game also detects it. # +--- steamPage: # This is the short text appearing on the steam page shortText: shapez.io is a game about building factories to automate the creation and combination of increasingly complex shapes within an infinite map. diff --git a/translations/base-nl.yaml b/translations/base-nl.yaml index 8b29e557..2f061268 100644 --- a/translations/base-nl.yaml +++ b/translations/base-nl.yaml @@ -19,6 +19,7 @@ # the basic structure so the game also detects it. # +--- steamPage: # This is the short text appearing on the steam page shortText: shapez.io is een spel dat draait om het bouwen van fabrieken voor het produceren en automatiseren van steeds complexere vormen in een oneindig groot speelveld. diff --git a/translations/base-no.yaml b/translations/base-no.yaml index 0d91bcd4..90568fdd 100644 --- a/translations/base-no.yaml +++ b/translations/base-no.yaml @@ -19,6 +19,7 @@ # the basic structure so the game also detects it. # +--- steamPage: # This is the short text appearing on the steam page shortText: shapez.io er et spill som handler om å bygge fabrikker for å automatisere produksjon og kombinasjon av former med økende kompleksitet på et uendelig ekspanderende brett. diff --git a/translations/base-pl.yaml b/translations/base-pl.yaml index b09895f6..ae930721 100644 --- a/translations/base-pl.yaml +++ b/translations/base-pl.yaml @@ -19,6 +19,7 @@ # the basic structure so the game also detects it. # +--- steamPage: # This is the short text appearing on the steam page shortText: shapez.io to gra polegająca na budowaniu fabryki automatyzującej tworzenie i łączenie ze sobą coraz bardziej skomplikowanych kształtów na mapie, która nie ma końca. diff --git a/translations/base-pt-BR.yaml b/translations/base-pt-BR.yaml index 14af1915..bf269558 100644 --- a/translations/base-pt-BR.yaml +++ b/translations/base-pt-BR.yaml @@ -19,10 +19,14 @@ # the basic structure so the game also detects it. # +--- steamPage: # This is the short text appearing on the steam page shortText: shapez.io é um jogo sobre construir fábricas, automatizando a criação e combinação de formas cada vez mais complexas num mapa infinito. + # This is the text shown above the Discord link + discordLink: Discord Oficial - Converse comigo! + # This is the long description for the steam page - It is contained here so you can help to translate it, and I will regulary update the store page. # NOTICE: # - Do not translate the first line (This is the gif image at the start of the store) @@ -31,6 +35,7 @@ steamPage: [img]{STEAM_APP_IMAGE}/extras/store_page_gif.gif[/img] shapez.io é um jogo sobre construir fábricas, automatizando a criação e combinação de formas cada vez mais complexas num mapa infinito. + Após a entrega das formas requisitadas você progredirá no jogo e desbloqueará melhorias para acelerar sua fábrica. Conforme sua demanda por formas aumenta, você irá que aumentar sua fábrica para alcançar-la - Mas não se esqueça dos recursos, você precisará expandir pelo [b]mapa infinito[/b]! @@ -82,8 +87,6 @@ steamPage: [*] [url=https://github.com/tobspr/shapez.io/blob/master/translations/README.md]Ajude a traduzir[/url] [/list] - discordLink: Discord Oficial - Converse comigo! - global: loading: Carregando error: Erro @@ -134,14 +137,19 @@ demoBanners: # This is the "advertisement" shown in the main menu and other various places title: Versão Demo intro: >- - Pegue a versão completa para desbloquear todas os recursos + Pegue a versão completa para desbloquear todas os recursos! mainMenu: play: Jogar + continue: Continuar + newGame: Novo jogo changelog: Changelog + subreddit: Reddit importSavegame: Importar openSourceHint: Esse jogo tem código aberto! discordLink: Discord oficial + helpTranslate: Ajude a traduzir! + madeBy: Feito por # This is shown when using firefox and other browsers which are not supported. browserWarning: >- @@ -150,12 +158,6 @@ mainMenu: savegameLevel: Nível savegameLevelUnknown: Nível desconhecido - helpTranslate: Ajude a traduzir! - continue: Continuar - newGame: Novo jogo - madeBy: Feito por - subreddit: Reddit - dialogs: buttons: ok: OK @@ -163,11 +165,11 @@ dialogs: cancel: Cancelar later: Voltar restart: Reiniciar - reset: Reset + reset: Resetar getStandalone: Obter versão completa deleteGame: Sei o que estou fazendo viewUpdate: Atualizações - showUpgrades: Ver melhorias + showUpgrades: Melhorias showKeybindings: Controles importSavegameError: @@ -198,7 +200,7 @@ dialogs: restartRequired: title: Ação necessária text: >- - Voce precisa reiniciar o jogo para aplicar as mudanças. + Você precisa reiniciar o jogo para aplicar as mudanças. editKeybinding: title: Alterar tecla @@ -228,7 +230,7 @@ dialogs: upgradesIntroduction: title: Desbloquear melhorias desc: >- - Todas as formas que você produz podem ser usadas para desbloquear melhorias - Não destrua suas antigas fábricas!! + Todas as formas que você produz podem ser usadas para desbloquear melhorias - Não destrua suas antigas fábricas!! O guia de melhorias pode ser encontrado no canto superior direito da tela. massDeleteConfirm: @@ -236,6 +238,16 @@ dialogs: desc: >- Você está deletando vários objetos ( para ser exato)! Você quer continuar? + massCutConfirm: + title: Confirmar corte + desc: >- + Você está cortando vários objetos ( para ser exato)! Você quer continuar? + + massCutInsufficientConfirm: + title: Confirmar Corte + desc: >- + You can not afford to paste this area! Are you sure you want to cut it? + blueprintsNotUnlocked: title: Não desbloqueado ainda desc: >- @@ -245,42 +257,31 @@ dialogs: title: Teclas úteis desc: >- Este jogo possui muitas combinações de teclas que facilitam a construção de grandes fábricas - Aqui estão algumas, certifique-se de verificar as combinações de teclas !

+ Aqui estão algumas, certifique-se de verificar as combinações de teclas!

CTRL + Arrastar: Seleciona área para copiar/deletar.
SHIFT: Mantenha pressionado para colocar várias construções.
ALT: Inverte as posições.
createMarker: title: Nova Marcação - desc: Dê um nome com significado, também pode adicionar um pequeno código de uma forma. (Pode ser gerado aqui) titleEdit: Editar Marcador + desc: Dê um nome com significado, também pode adicionar um pequeno código de uma forma. (Pode ser gerado aqui) markerDemoLimit: - desc: >- - Você só pode criar dois marcadores na versão demo. Adquira a versão completa para marcadores ilimitados! - - massCutConfirm: - title: Confirmar corte - desc: >- - Você está cortando vários objetos ( para ser exato)! Você quer continuar? + desc: Você só pode criar dois marcadores na versão demo. Adquira a versão completa para marcadores ilimitados! exportScreenshotWarning: title: Exportar captura de tela - desc: >- - Você está prestes a exportar uma captura de tela da sua base. Note que isso pode ser bastante lento para uma base grande, e até mesmo pode travar o jogo! - - massCutInsufficientConfirm: - title: Confirmar Corte - desc: You can not afford to paste this area! Are you sure you want to cut it? + desc: Você está prestes a exportar uma captura de tela da sua base. Note que isso pode ser bastante lento para uma base grande, e até mesmo pode travar o jogo! ingame: # This is shown in the top left corner and displays useful keybindings in # every situation keybindingsOverlay: moveMap: Mover - + selectBuildings: Selecionar área stopPlacement: Parar - rotateBuilding: Rotação + rotateBuilding: Rotacionar placeMultiple: Colocar vários reverseOrientation: Inverter orientação disableAutoOrientation: Desligar orientação automática @@ -288,17 +289,27 @@ ingame: placeBuilding: Construir objeto createMarker: Criar marcador delete: Destruir - selectBuildings: Selecionar área pasteLastBlueprint: Colar último projeto - lockBeltDirection: Ativar Planejador de Esteiras - plannerSwitchSide: Flip planner side + plannerSwitchSide: Girar Planejador cutSelection: Cortar copySelection: Copiar clearSelection: Limpar Seleção pipette: Conta-Gotas switchLayers: Trocar Camadas + # Names of the colors, used for the color blind mode + colors: + red: Vermelho + green: Verde + blue: Azul + yellow: Amarelo + purple: Roxo + cyan: Ciano + white: Branco + black: Preto + uncolored: Sem cor + # Everything related to placing buildings (I.e. as soon as you selected a building # from the toolbar) buildingPlacement: @@ -324,7 +335,7 @@ ingame: levelCompleteNotification: # is replaced by the actual level, so this gets 'Level 03' for example. levelTitle: Nível - completed: Completado + completed: Concluído unlockText: Desbloqueado ! buttonNextLevel: Próximo Nível @@ -336,13 +347,14 @@ ingame: # The "Upgrades" window shop: title: Melhorias - buttonUnlock: Comprar + buttonUnlock: Melhorar # Gets replaced to e.g. "Tier IX" tier: Nível # The roman number for each tier tierLabels: [I, II, III, IV, V, VI, VII, VIII, IX, X] + maximumLevel: NÍVEL MÁXIMO (Velocidade x) # The "Statistics" window @@ -389,60 +401,58 @@ ingame: waypoints: waypoints: Marcadores hub: HUB - description: Clique com o botão esquerdo do mouse em um marcador para pular, clique com o botão direito do mouse para excluí-lo.

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

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

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

Dica, segure SHIFT para colocar vários extratores e use R para girá-los. - - colors: - red: Vermelho - green: Verde - blue: Azul - yellow: Amarelo - purple: Roxo - cyan: Ciano - white: Branco - black: Preto - uncolored: Sem cor + # Shape viewer shapeViewer: title: Camadas empty: Vazio copyKey: Copiar Chave + # Interactive tutorial + interactiveTutorial: + title: Tutorial + hints: + 1_1_extractor: Coloque um extrator em cima de uma fonte de círculo para extraí-lo! + 1_2_conveyor: >- + Conecte o extrator com uma esteira transportadora até a sua base!

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

Dica, segure SHIFT para colocar vários extratores e use R para girá-los. + # All shop upgrades shopUpgrades: belt: name: Esteiras, Distribuidores e Túneis description: Velocidade x → x - miner: name: Extração description: Velocidade x → x - processors: - name: Corte, Rotação & Montagem + name: Corte, Rotação e Montagem description: Velocidade x → x - painting: - name: Mistura & Pintura + name: Mistura e Pintura description: Velocidade x → x # Buildings and their name / description buildings: + hub: + deliver: Entregue + toUnlock: para desbloquear + levelShortcut: LVL + belt: default: name: &belt Esteira Transportadora description: Transporta itens; mantenha pressionado e arraste para colocar vários. + wire: + default: + name: &wire Fio de Energia + description: Permite transportar energia. + miner: # Internal name for the Extractor default: name: &miner Extrator @@ -477,10 +487,15 @@ buildings: cutter: default: name: &cutter Cortador - description: Corta as formas verticalmente e produz as duas metades. Se você usar apenas uma parte, não se esqueça de destruir a outra parte, ou ela irá parar a produção! + description: Corta as formas verticalmente e produz as duas metades. Se você usar apenas uma parte, não se esqueça de destruir a outra parte, ou ela irá parar a produção! quad: name: Cortador (Quádruplo) - description: Corta as formas em quatro partes. Se você usar apenas uma parte, não se esqueça de destruir as outras, ou ela irá parar a produção! + description: Corta as formas em quatro partes. Se você usar apenas uma parte, não se esqueça de destruir as outras, ou ela irá parar a produção! + + advanced_processor: + default: + name: &advanced_processor Inversor de Cor + description: Aceita uma cor ou forma e a inverte. rotater: default: @@ -490,8 +505,8 @@ buildings: name: Rotacionador (Anti-horário) description: Gira as formas no sentido anti-horário em 90 graus. fl: - name: Rotate (180) - description: Rotates shapes by 180 degrees. + name: Rotacionador (180) + description: Gira as formas em 180 graus. stacker: default: @@ -507,16 +522,18 @@ buildings: default: name: &painter Pintor description: &painter_desc Colore a forma inteira na entrada esquerda com a cor da entrada direita. - double: - name: Pintor (Duplo) - description: Colore as duas formas na entrada esquerda com a cor da entrada direita. - quad: - name: Pintor (Quádruplo) - description: Permite colorir cada quadrante da forma com uma cor diferente. + mirrored: name: *painter description: *painter_desc + double: + name: Pintor (Duplo) + description: Colore as formas na entrada esquerda com a cor da entrada superior. + quad: + name: Pintor (Quádruplo) + description: Permite colorir cada quadrante da forma com uma cor diferente. + trash: default: name: &trash Lixo @@ -525,29 +542,22 @@ buildings: storage: name: Estoque description: Armazena itens em excesso, até uma determinada capacidade. Pode ser usado como uma porta de transbordamento. - hub: - deliver: Entregue - toUnlock: para desbloquear - levelShortcut: LVL - wire: - default: - name: &wire Fio de Energia - description: Permite transportar energia. - advanced_processor: - default: - name: &advanced_processor Inversor de Cor - description: Aceita uma cor ou forma e a inverte. energy_generator: deliver: Entregar + + # This will be shown before the amount, so for example 'For 123 Energy' toGenerateEnergy: Para + default: name: &energy_generator Gerador de Energia description: Consome formas para gerar energia. + wire_crossings: default: name: &wire_crossings Divisor de Fios description: Divide um fio de energia em dois. + merger: name: Misturador de Fios description: Une dois fios de energia em um. @@ -556,11 +566,11 @@ storyRewards: # Those are the rewards gained from completing the store reward_cutter_and_trash: title: Cortando formas - desc: Voce desbloqueou cortador - corte de formas pela metade verticalmente independentemente de sua orientação!

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

Certifique-se de se livrar do lixo, ou então ele irá parar a produção - Para esse propósito, eu lhe dei uma lixeira, que destrói tudo o que você coloca nela! reward_rotater: title: Rotação - desc: O rotacionador foi desbloqueado! Gira as formas no sentido horário em 90 graus. + desc: O rotacionador foi desbloqueado! Gira as formas no sentido horário em 90 graus. reward_painter: title: Pintura @@ -569,11 +579,11 @@ storyRewards: reward_mixer: title: Misturando cores - desc: O misturador foi desbloqueado - combine duas cores usando mistura aditiva com esta construção! + desc: O misturador foi desbloqueado - combine duas cores usando mistura aditiva com esta construção! reward_stacker: title: Empilhador - desc: Agora você pode combinar formas com o empilhador! Ambas as entradas são combinadas e, se puderem ser colocadas próximas uma da outra, serão fundidas . Caso contrário, a entrada direita é empilhada em cima da entrada esquerda! + desc: Agora você pode combinar formas com o empilhador! Ambas as entradas são combinadas e, se puderem ser colocadas próximas uma da outra, serão fundidas. Caso contrário, a entrada direita é empilhada em cima da entrada esquerda! reward_splitter: title: Distribuidor @@ -597,7 +607,8 @@ storyRewards: reward_splitter_compact: title: Distribuidor compacto - desc: Você desbloqueou uma variante compacta do Distribuidor - ele aceita duas entradas e as une em uma! + desc: >- + Você desbloqueou uma variante compacta do Distribuidor - ele aceita duas entradas e as une em uma! reward_cutter_quad: title: Cortador quádruplo @@ -605,7 +616,7 @@ storyRewards: reward_painter_double: title: Pintura dupla - desc: Você desbloqueou uma variante do pintor - funciona como o pintor regular, mas processa duas formas ao mesmo tempo , consumindo apenas uma cor em vez de duas! + desc: Você desbloqueou uma variante do pintor - funciona como o pintor regular, mas processa duas formas ao mesmo tempo, consumindo apenas uma cor em vez de duas! reward_painter_quad: title: Pintura quádrupla @@ -637,9 +648,9 @@ storyRewards: settings: title: opções categories: - general: General - userInterface: User Interface - advanced: Advanced + general: Geral + userInterface: Interface de Usuário + advanced: Avançado versionBadges: dev: Desenvolvedor @@ -653,23 +664,58 @@ settings: description: >- Altera o tamanho da fonte do usuário. A interface ainda será dimensionada com base na resolução do dispositivo, mas essa configuração controla a escala do texto. scales: - super_small: Super pequeno + super_small: Super Pequeno small: Pequeno regular: Normal large: Grande huge: Gigante + autosaveInterval: + title: Intervalo de gravação automática + description: >- + Controla a frequência com que o jogo salva automaticamente. Você também pode desativá-lo totalmente aqui. + + intervals: + one_minute: 1 Minuto + two_minutes: 2 Minutos + five_minutes: 5 Minutos + ten_minutes: 10 Minutos + twenty_minutes: 20 Minutos + disabled: Desativado + scrollWheelSensitivity: title: Sensibilidade do zoom description: >- Altera a sensibilidade do zoom (roda do mouse ou touchpad). sensitivity: - super_slow: Super lento + super_slow: Super Lento slow: Lento regular: Normal fast: Rápido super_fast: Super Rápido + movementSpeed: + title: Velocidade da câmera + description: >- + Altera a velocidade com que a câmera se move com o teclado. + speeds: + super_slow: Super Lento + slow: Lento + regular: Normal + fast: Rápido + super_fast: Super Rápido + extremely_fast: Extremamente Rápido + + language: + title: Idioma + description: >- + Altera o idioma. Todas as traduções são contribuições de usuários e podem estar incompletas! + + enableColorBlindHelper: + title: Modo daltônico. + description: >- + Permite várias ferramentas que permitem jogar se você é daltônico. + fullscreen: title: Tela Cheia description: >- @@ -678,7 +724,7 @@ settings: soundsMuted: title: Som description: >- - Se ligado o jogo fica mudo + Se ligado, o jogo fica mudo. musicMuted: title: Música @@ -689,7 +735,6 @@ settings: title: Tema description: >- Escolha o tema entre (Claro / Escuro). - themes: dark: Escuro light: Claro @@ -709,63 +754,30 @@ settings: description: >- Se ativado, oferece dicas e tutoriais enquanto se joga. Além disso, esconde certos elementos da interface até certo ponto, para facilitar o começo do jogo. - language: - title: Idioma - description: >- - Altera o idioma. Todas as traduções são contribuições de usuários e podem estar incompletas! - - movementSpeed: - title: Velocidade da câmera - description: Altera a velocidade com que a câmera se move com o teclado. - speeds: - super_slow: Super Lento - slow: Lento - regular: Normal - fast: Rápido - super_fast: Super Rápido - extremely_fast: Extremamente Rápido enableTunnelSmartplace: title: Túneis inteligentes description: >- - Quando colocados, irão remover automaticamente esteiras desnecessárias. - Isso também permite arrastar túneis e túneis em excesso serão removidos. + Quando colocados, irão remover automaticamente esteiras desnecessárias. Isso também permite arrastar túneis e túneis em excesso serão removidos. + vignette: - title: Vignette + title: Vinheta description: >- - Permite o modo vinheta que escurece os cantos da tela e facilita a - leitura do texto. + Permite o modo vinheta que escurece os cantos da tela e facilita a leitura do texto. - autosaveInterval: - title: Intervalo de gravação automática - description: >- - Controla a frequência com que o jogo salva automaticamente. - Você também pode desativá-lo totalmente aqui. - intervals: - one_minute: 1 Minuto - two_minutes: 2 Minutos - five_minutes: 5 Minutos - ten_minutes: 10 Minutos - twenty_minutes: 20 Minutos - disabled: Desativado - compactBuildingInfo: - title: Informações compactas sobre construções - description: >- - Reduz as caixas de informações dos construções, mostrando apenas suas proporções. - Caso contrário, uma descrição e imagem são mostradas. - disableCutDeleteWarnings: - title: Desativar avisos de recorte / exclusão - description: >- - Desative as caixas de diálogo de aviso exibidas ao cortar / excluir - mais de 100 entidades. - - enableColorBlindHelper: - title: Modo daltônico. - description: Permite várias ferramentas que permitem jogar se você é daltônico. rotationByBuilding: title: Rotação por tipo de construção description: >- - Cada tipo de construção lembra a rotação que você definiu pela última vez individualmente. - Isso pode ser mais confortável se você alternar frequentemente entre a colocação de diferentes tipos de construção. + Cada tipo de construção lembra a rotação que você definiu pela última vez individualmente. Isso pode ser mais confortável se você alternar frequentemente entre a colocação de diferentes tipos de construção. + + compactBuildingInfo: + title: Informações compactas sobre construções + description: >- + Reduz as caixas de informações dos construções, mostrando apenas suas proporções. Caso contrário, uma descrição e imagem são mostradas. + + disableCutDeleteWarnings: + title: Desativar avisos de recorte / exclusão + description: >- + Desative as caixas de diálogo de aviso exibidas ao cortar / excluir mais de 100 entidades. keybindings: title: Controles @@ -790,6 +802,7 @@ keybindings: mapMoveRight: Mover para direita mapMoveDown: Mover para baixo mapMoveLeft: Mover para a esquerda + mapMoveFaster: Mover mais rápido centerMap: Centralizar mapa mapZoomIn: Aproximar @@ -798,12 +811,12 @@ keybindings: menuOpenShop: Melhorias menuOpenStats: Estatísticas + menuClose: Fechar Menu toggleHud: Ocultar Interface toggleFPSInfo: Mostrar FPS e Debug Info switchLayers: Alternar Camadas - exportScreenshot: Exportar Base inteira como Imagem - + exportScreenshot: Exportar Base Inteira como Imagem belt: *belt splitter: *splitter underground_belt: *underground_belt @@ -824,41 +837,33 @@ keybindings: Modifier: Rotação anti-horária cycleBuildingVariants: Variações confirmMassDelete: Confirmar exclusão em massa + pasteLastBlueprint: Colar último projeto cycleBuildings: Trocar de construção + lockBeltDirection: Ativar planejador de correia + switchDirectionLockSide: >- + Planejador: Mudar de lado massSelectStart: Segure e arraste para começar massSelectSelectMultiple: Selecionar mais áreas massSelectCopy: Copiar área + massSelectCut: Cortar área placementDisableAutoOrientation: Desligar orientação automática placeMultiple: Permanecer no modo de construção placeInverse: Inverter orientação de esteira - pasteLastBlueprint: Colar último projeto - massSelectCut: Cortar área - mapMoveFaster: Mover mais rápido - lockBeltDirection: Ativar planejador de correia - switchDirectionLockSide: "Planejador: Mudar de lado" - menuClose: Fechar Menu about: title: Sobre o jogo body: >- - Esse jogo tem código aberto e é desenvolvido por Tobias Springer (esse sou eu).

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

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

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

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

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

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

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

- Finalmente, agradeço muito ao meu melhor amigo - Niklas - Sem nossas sessões de Factorio, - esse jogo nunca teria existido. + Finalmente, agradeço muito ao meu melhor amigo Niklas - Sem nossas sessões de Factorio, esse jogo nunca teria existido. changelog: title: Alterações diff --git a/translations/base-pt-PT.yaml b/translations/base-pt-PT.yaml index 8b6db461..4f16e0a9 100644 --- a/translations/base-pt-PT.yaml +++ b/translations/base-pt-PT.yaml @@ -19,6 +19,7 @@ # the basic structure so the game also detects it. # +--- steamPage: # This is the short text appearing on the steam page shortText: shapez.io é um jogo cujo objetivo é construir fábricas para automatizar a criação e fusão de formas geométricas cada vez mais complexas num mapa infinito. diff --git a/translations/base-ro.yaml b/translations/base-ro.yaml index 0f9e2714..15d3ff4b 100644 --- a/translations/base-ro.yaml +++ b/translations/base-ro.yaml @@ -19,6 +19,7 @@ # the basic structure so the game also detects it. # +--- steamPage: # This is the short text appearing on the steam page shortText: shapez.io este un joc despre construirea fabricilor pentru a automatiza crearea și combinarea a din ce in ce mai complexe forme într-o hartă infinită. diff --git a/translations/base-ru.yaml b/translations/base-ru.yaml index 61f1ebf3..7dddc198 100644 --- a/translations/base-ru.yaml +++ b/translations/base-ru.yaml @@ -19,6 +19,7 @@ # the basic structure so the game also detects it. # +--- steamPage: # This is the short text appearing on the steam page shortText: shapez.io — это игра о строительстве фабрик для автоматизации создания и объединения все более сложных фигур на бесконечной карте. @@ -488,8 +489,8 @@ buildings: name: Вращатель (Обр.) description: Поворачивает фигуры против часовой стрелки на 90 градусов. fl: - name: Rotate (180) - description: Rotates shapes by 180 degrees. + name: Вращатель (180) + description: Вращает фигуры на 180 градусов. stacker: default: @@ -635,9 +636,9 @@ storyRewards: settings: title: Настройки categories: - general: General - userInterface: User Interface - advanced: Advanced + general: Основные + userInterface: Интерфейс + advanced: Продвинутые versionBadges: dev: Разработчик diff --git a/translations/base-sl.yaml b/translations/base-sl.yaml index 7b451dc8..ad084b9d 100644 --- a/translations/base-sl.yaml +++ b/translations/base-sl.yaml @@ -19,6 +19,7 @@ # the basic structure so the game also detects it. # +--- steamPage: # This is the short text appearing on the steam page shortText: shapez.io je igra grajenja tovarne katere cilj je avtomatiziranje kreiranja in procesiranja vse bolj zapletenih oblik na neskončni ravnini. diff --git a/translations/base-sr.yaml b/translations/base-sr.yaml index fb03f547..953c024a 100644 --- a/translations/base-sr.yaml +++ b/translations/base-sr.yaml @@ -36,6 +36,7 @@ # + Merger = Spajač # + Rotator = Obrtač +--- steamPage: # This is the short text appearing on the steam page shortText: shapez.io je igra o pravljenju fabrika za automatizaciju stvaranja i spajanja sve složenijih oblika na beskonačno velikoj mapi. diff --git a/translations/base-sv.yaml b/translations/base-sv.yaml index a2609184..ab302368 100644 --- a/translations/base-sv.yaml +++ b/translations/base-sv.yaml @@ -19,6 +19,7 @@ # the basic structure so the game also detects it. # +--- steamPage: # This is the short text appearing on the steam page shortText: shapez.io är ett spel som går ut på att automatisera skapandet av former med ökande komplexitet inom den oändligt stora världen. diff --git a/translations/base-tr.yaml b/translations/base-tr.yaml index ef79d218..b0b7d095 100644 --- a/translations/base-tr.yaml +++ b/translations/base-tr.yaml @@ -19,6 +19,7 @@ # the basic structure so the game also detects it. # +--- steamPage: # This is the short text appearing on the steam page shortText: shapez.io is a game about building factories to automate the creation and combination of increasingly complex shapes within an infinite map. diff --git a/translations/base-uk.yaml b/translations/base-uk.yaml index 92aba8d8..bd83b42d 100644 --- a/translations/base-uk.yaml +++ b/translations/base-uk.yaml @@ -1,6 +1,10 @@ # # GAME TRANSLATIONS # +# Translators: +# +# Prosta4ok_ua 07.07.2020 — 04.08.2020 +# # Contributing: # # If you want to contribute, please make a pull request on this respository @@ -23,8 +27,12 @@ # upgrade поліпшення # marker позначка # area ділянка -# hub +# hub центр +# range дальність +# storage сховище +# shape форма +--- steamPage: # This is the short text appearing on the steam page shortText: shapez.io — це гра про будування фабрик для автоматизації створення та обробки все більш складних форм на нескінченно розширюваній мапі. @@ -39,14 +47,14 @@ steamPage: longText: >- [img]{STEAM_APP_IMAGE}/extras/store_page_gif.gif[/img] - shapez.io is a game about building factories to automate the creation and processing of increasingly complex shapes across an infinitely expanding map. - Upon delivering the requested shapes you will progress within the game and unlock upgrades to speed up your factory. + shapez.io — це гра про будування фабрик для автоматизації створення та обробки все більш складних форм на нескінченно розширюваній мапі. + Після доставки потрібних форм ви просунетеся в грі та розблокуєте поліпшення, щоб пришвидшити свою фабрику. - As the demand for shapes increases, you will have to scale up your factory to meet the demand - Don't forget about resources though, you will have to expand across the [b]infinite map[/b]! + Коли попит на форми зростає, вам доведеться збільшити масштаб своєї фабрики, щоб задовольнити попит. Однак не забувайте про ресурси, вам доведеться розширюватися на [b]нескінченній мапі[/b]! - Soon you will have to mix colors and paint your shapes with them - Combine red, green and blue color resources to produce different colors and paint shapes with it to satisfy the demand. + Незабаром ви зможете змішути кольори і з їхньою допомогою фарбувати свої форми. Поєднуйте червоний, зелений та синій ресурси кольорів, щоб виготовити різноманітні кольори і пофарувати форми як вам заманеться. - This game features 18 progressive levels (Which should keep you busy for hours already!) but I'm constantly adding new content - There is a lot planned! + У цій грі є 18 передових рівнів, які повинні утримувати вас годинами. Але не турбуйтеся, я постійно додаю новий вміст — ще багато чого заплановано! Купуючи гру, ви отримуєте доступ до окремої версії, яка має додаткові функції, а також ви отримаєте доступ до нещодавно розроблених функцій. @@ -59,7 +67,7 @@ steamPage: [*] Додаткові налаштування [*] Незабаром: дроти й енергія! Гадаю, оновлення вийде у кінці липня 2020 року. [*] Незабаром: більше рівнів. - [*] Allows me to further develop shapez.io ❤️ + [*] Дозволяє мені розвиватися далі shapez.io ❤️ [/list] [img]{STEAM_APP_IMAGE}/extras/header_future_updates.png[/img] @@ -68,7 +76,7 @@ steamPage: [list] [*] Різноманітні мапи та випробування (наприклад, мапи з перешкодами) - [*] Пазли (Надайте потрібну форму з обмеженою площею/набором будівель) + [*] Пазли (надайте потрібну форму з обмеженою площею/набором будівель) [*] Режим історії, де будівлі матимуть вартість [*] Генератор мап, який можна налаштувати (ресурс/розмір/щільність форми, зерно та багато іншого) [*] Додаткові типи форм @@ -152,7 +160,7 @@ mainMenu: importSavegame: Імпортувати openSourceHint: Ця гра з відкритим вихідним кодом! discordLink: Офіційний Discord сервер - helpTranslate: Допоможіть перекласти! + helpTranslate: Допоможіть з перекладом! madeBy: Зробив # This is shown when using firefox and other browsers which are not supported. @@ -229,12 +237,12 @@ dialogs: updateSummary: title: Нове оновлення! desc: >- - Ось зміни з вашої останньої гри + Ось зміни з вашої останньої гри: upgradesIntroduction: title: Розблокування поліпшень desc: >- - Усі форми, що ви виробляєте, можуть використовуватися для розблокування поліпшення - Не зруйновуйте ваші старі заводи! + Усі форми, що ви виробляєте, можуть використовуватися для розблокування поліпшення - Не зруйнуйте свої старі фабрики! Вкладку з поліпшеннями можна знайти в правому верхньому куті екрана. massDeleteConfirm: @@ -255,21 +263,21 @@ dialogs: blueprintsNotUnlocked: title: Ще не розблоковано desc: >- - Досягніть 13-го рівня, щоб розблокувати Blueprints! + Досягніть 13-го рівня, щоб розблокувати креслення! keybindingsIntroduction: title: Корисні гарячі клавіши desc: >- - Гра має багато гарічих клавіш, що полегшує будівництво великих заводів. - Here are a few, but be sure to check out the keybindings!

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

+ CTRL + тягніть: виділити зону.
+ SHIFT: тримайте, щоб розмістити декілька одного будинку.
+ ALT: змінити орієнтацію розміщеної конвеєрної стрічки.
createMarker: title: Нова позначка - desc: Дайте йому змістовну назву, you can also include a short key of a shape (Which you can generate here) titleEdit: Редагувати позначку + desc: Дайте їй змістовну назву. Ви також можете додати короткий ключ форми, що можно згенерувати тут. markerDemoLimit: desc: Ви можете створити тільки 2 позначки в демоверсії. Отримайте окрему версії для створення необмеженної кількості позначок. @@ -284,21 +292,21 @@ ingame: keybindingsOverlay: moveMap: Рухатися selectBuildings: Виділити будівлі - stopPlacement: Stop placement + stopPlacement: Зупинити розміщення rotateBuilding: Повернути будівлю - placeMultiple: Place multiple - reverseOrientation: Reverse orientation - disableAutoOrientation: Disable auto-orientation - toggleHud: Toggle HUD - placeBuilding: Place building + placeMultiple: Розмістити декілька + reverseOrientation: Змінити орієнтацію + disableAutoOrientation: Вимкнути автоматичну орієнтацію + toggleHud: Перемкнути інтерфейс + placeBuilding: Розмістити будівлю createMarker: Створити позначку delete: Видалити - pasteLastBlueprint: Paste last blueprint - lockBeltDirection: Enable belt planner - plannerSwitchSide: Flip planner side + pasteLastBlueprint: Вставити останнє креслення + lockBeltDirection: Увімкнути стрічковий планувальник + plannerSwitchSide: Змінити сторону планувальника cutSelection: Вирізати copySelection: Скопіювати - clearSelection: Clear selection + clearSelection: Очистити виділене pipette: Піпетка switchLayers: Змінити шари @@ -319,7 +327,7 @@ ingame: buildingPlacement: # Buildings can have different variants which are unlocked at later levels, # and this is the hint shown when there are multiple variants available. - cycleBuildingVariants: Press to cycle variants. + cycleBuildingVariants: Натисніть для циклу варіантів. # Shows the hotkey in the ui, e.g. "Hotkey: Q" hotkeyLabel: >- @@ -327,7 +335,7 @@ ingame: infoTexts: speed: Швидкість - range: Range + range: Дальність storage: Сховище oneItemPerSecond: 1 предмет за сек. itemsPerSecond: предмет. за сек @@ -354,7 +362,7 @@ ingame: buttonUnlock: Поліпшення # Gets replaced to e.g. "Tier IX" - tier: Клас + tier: Ранг # The roman number for each tier tierLabels: [I, II, III, IV, V, VI, VII, VIII, IX, X] @@ -367,14 +375,14 @@ ingame: dataSources: stored: title: Зберігається - description: Displaying amount of stored shapes in your central building. + description: Відображає кількість збережених фігур у вашому центрі. produced: title: Виробляється - description: Displaying all shapes your whole factory produces, including intermediate products. + description: Відображає всі форми вашої цілої фабрики, що виробляються, включаючи проміжні продукти. delivered: title: Доставлено - description: Displaying shapes which are delivered to your central building. - noShapesProduced: No shapes have been produced so far. + description: Відображає форми, що доставляються до центру. + noShapesProduced: Жодної форми поки не випускається. # Displays the shapes per minute, e.g. '523 / m' shapesPerMinute: за хв. @@ -405,14 +413,14 @@ ingame: waypoints: waypoints: Позначки hub: Центр - description: Left-click a marker to jump to it, right-click to delete it.

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

Натисніть для створення позначки з поточного виду або ПКМ, щоб створити позначку в обраному місці. + creationSuccessNotification: Позначку створено. # Shape viewer shapeViewer: title: Шари empty: Пустий - copyKey: Copy Key + copyKey: Копіювати ключ # Interactive tutorial interactiveTutorial: @@ -449,78 +457,81 @@ buildings: belt: default: - name: &belt Conveyor Belt - description: Transports items, hold and drag to place multiple. + name: &belt Конвеєрна стрічка + description: Транспортує предмети, утримуйте і перетягуйте для розміщення декількох. wire: default: - name: &wire Wire - description: Allows you to transport energy + name: &wire Дріт + description: Дозволяє передавати енергію - miner: # Internal name for the Extractor + # Internal name for the Extractor + miner: default: - name: &miner Extractor - description: Place over a shape or color to extract it. + name: &miner Екстрактор + description: Розмістіть над формою чи кольором, який хочете видобути. chainable: - name: Extractor (Chain) - description: Place over a shape or color to extract it. Can be chained. + name: Екстрактор (Ланц.) + description: Розмістіть над формою чи кольором, який хочете видобути. Можна об’єднати в ланцюг. - underground_belt: # Internal name for the Tunnel + # Internal name for the Tunnel + underground_belt: default: - name: &underground_belt Tunnel - description: Allows you to tunnel resources under buildings and belts. + name: &underground_belt Тунель + description: Дозволяє транспортувати ресурси під будівлями та стрічками. tier2: - name: Tunnel Tier II - description: Allows you to tunnel resources under buildings and belts. + name: Тунель, ранг II + description: Дозволяє транспортувати ресурси під будівлями та стрічками. - splitter: # Internal name for the Balancer + # Internal name for the Balancer + splitter: default: - name: &splitter Balancer + name: &splitter Розподілювач description: Multifunctional - Evenly distributes all inputs onto all outputs. compact: - name: Merger (compact) - description: Merges two conveyor belts into one. + name: З’єднувач + description: Об’єднує дві конвеєрні стрічки в одну. Займає усього на всього одну клітину. compact-inverse: - name: Merger (compact) - description: Merges two conveyor belts into one. + name: З’єднувач + description: Об’єднує дві конвеєрні стрічки в одну. Займає усього на всього одну клітину. cutter: default: - name: &cutter Cutter - description: Cuts shapes from top to bottom and outputs both halves. If you use only one part, be sure to destroy the other part or it will stall! + name: &cutter Різчик + description: Розрізає форми зверху вниз і виводить обидві половинки. Якщо ви використовуєте лише одну частину, не забудьте знищити іншу частину, інакше вона застрягне в механізмі! quad: - name: Cutter (Quad) - description: Cuts shapes into four parts. If you use only one part, be sure to destroy the other parts or it will stall! + name: Різчик (4 вих.) + description: Розрізає форми на 4 частини. Якщо ви використовуєте лише одну частину, не забудьте знищити інші, інакше вони застрягнуть в механізмі! advanced_processor: default: - name: &advanced_processor Advanced Processor - description: Advanced shape processing + name: &advanced_processor Передовий процесор + description: Покращена обробка форм. rotater: default: - name: &rotater Rotate - description: Rotates shapes clockwise by 90 degrees. + name: &rotater Обертач + description: Обертає форми за годинниковою стрілкою на 90 градусів. ccw: - name: Rotate (CCW) - description: Rotates shapes counter-clockwise by 90 degrees. + name: Обертач (-90) + description: Обертає форми проти годинникової стрілки на 90 градусів. fl: - name: Rotate (180) - description: Rotates shapes by 180 degrees. + name: Обертач (180) + description: Обертає форми на 180 градусів. stacker: default: - name: &stacker Stacker + name: &stacker Укладальник description: Stacks both items. If they can not be merged, the right item is placed above the left item. mixer: default: - name: &mixer Color Mixer - description: Mixes two colors using additive blending. + name: &mixer Змішувач кольо8рів + description: Змішує два кольори за допомогою добавки. painter: default: @@ -591,7 +602,7 @@ storyRewards: reward_splitter: title: Splitter/Merger - desc: Багатофункціональний балансир було розблоковано. Його можна використовувати для створення великих заводів, розділяючи та об’єднуючи предмети на кілька стрічок!

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

reward_tunnel: title: Tunnel @@ -642,7 +653,7 @@ storyRewards: no_reward: title: Наступний рівень desc: >- - Цей рівень не дав нагороди, але в наступному... щось буде.

До речі, краще не руйнуйте свій поточний завод. Вам знадобляться всі ті форми пізніше, щоб розблокувати поліпшення! + Цей рівень не дав нагороди, але в наступному... щось буде.

До речі, краще не руйнуйте свою поточну фабрику. Вам знадобляться всі ті форми пізніше, щоб розблокувати поліпшення! no_reward_freeplay: title: Наступний рівень diff --git a/translations/base-zh-CN.yaml b/translations/base-zh-CN.yaml index 3aad1244..225619e0 100644 --- a/translations/base-zh-CN.yaml +++ b/translations/base-zh-CN.yaml @@ -176,7 +176,7 @@ mainMenu: # This is shown when using firefox and other browsers which are not supported. browserWarning: >- - 很抱歉, 本游戏在当前浏览器上可能运行缓慢! 使用chrome或者获取独立版以得到更好的体验。 + 很抱歉, 本游戏在当前浏览器上可能运行缓慢! 使用 Chrome 或者获取独立版以得到更好的体验。 savegameLevel: 第关 savegameLevelUnknown: @@ -232,7 +232,7 @@ dialogs: editKeybinding: title: 更改按键设置 - desc: 请按下你想要使用的按键,或者按下ESC键来取消设置。 + desc: 请按下你想要使用的按键,或者按下 ESC 键来取消设置。 resetKeybindingsConfirmation: title: 重置所有按键 @@ -244,11 +244,11 @@ dialogs: featureRestriction: title: 演示版 - desc: 你尝试使用了 功能。该功能在演示版中不可用。请考虑购买独立版以获得更好的体验。 + desc: 你尝试使用了功能。该功能在演示版中不可用。请考虑购买独立版以获得更好的体验。 oneSavegameLimit: title: 存档数量限制 - desc: 演示版中只能保存一份存档。 请删除旧存档或者获取独立版! + desc: 演示版中只能保存一份存档。请删除旧存档或者获取独立版! updateSummary: title: 更新啦! @@ -314,7 +314,7 @@ ingame: placeMultiple: 放置多个 reverseOrientation: 反向放置 disableAutoOrientation: 关闭自动定向 - toggleHud: 开关HUD + toggleHud: 开关 HUD placeBuilding: 放置建筑 createMarker: 创建地图标记 delete: 销毁 @@ -332,7 +332,7 @@ ingame: buildingPlacement: # Buildings can have different variants which are unlocked at later levels, # and this is the hint shown when there are multiple variants available. - cycleBuildingVariants: 按键以选择建筑变体. + cycleBuildingVariants: 按 键以选择建筑变体. # Shows the hotkey in the ui, e.g. "Hotkey: Q" hotkeyLabel: >- @@ -391,7 +391,7 @@ ingame: noShapesProduced: 你还没有生产任何图形。 # Displays the shapes per minute, e.g. '523 / m' - shapesPerMinute: 个/分钟 + shapesPerMinute: 个 / 分钟 # Settings menu, when you press "ESC" settingsMenu: @@ -419,7 +419,7 @@ ingame: waypoints: waypoints: 地图标记 hub: 基地 - description: 左键跳转到地图标记,右键删除地图标记。

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

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

- 提示:按住SHIFT键来放置多个开采机,用R键旋转它们。 + 提示:按住 SHIFT 键来放置多个开采机,用 R 键旋转它们。 colors: red: 红色 @@ -505,10 +505,10 @@ buildings: cutter: default: name: &cutter 切割机 - description: 将图形从上到下切开并输出。 如果你只需要其中一半,记得把另一半销毁掉,否则切割机会停止工作! + description: 将图形从上到下切开并输出。如果你只需要其中一半,记得把另一半销毁掉,否则切割机会停止工作! quad: name: 切割机(四向) - description: 将输入的图形切成四块。 如果你只需要其中一块,记得把其他的销毁掉,否则切割机会停止工作! + description: 将输入的图形切成四块。如果你只需要其中一块,记得把其他的销毁掉,否则切割机会停止工作! rotater: default: @@ -592,7 +592,7 @@ storyRewards: reward_painter: title: 上色 desc: >- - 恭喜!你解锁了上色机。 开采一些颜色 (就像你开采图形一样) 将其在上色机中与图形结合来将图形上色!

PS: 如果你患有色盲,可以在设置中启用色盲模式! + 恭喜!你解锁了上色机。开采一些颜色 (就像你开采图形一样) 将其在上色机中与图形结合来将图形上色!

PS:如果你患有色盲,可以在设置中启用色盲模式! reward_mixer: title: 混合颜色 @@ -612,7 +612,7 @@ storyRewards: reward_rotater_ccw: title: 逆时针旋转 - desc: 恭喜!你解锁了旋转机逆时针变体。这个变体可以逆时针旋转图形。选择旋转机然后按“T”键来选取这个变体。 + desc: 恭喜!你解锁了旋转机逆时针变体。这个变体可以逆时针旋转图形。选择旋转机然后按"T"键来选取这个变体。 reward_miner_chainable: title: 链式开采机 @@ -648,13 +648,13 @@ storyRewards: reward_blueprints: title: 蓝图 - desc: 你现在可以复制粘贴你的工厂的一部分了!按住CTRL键并拖动鼠标来选择一块区域,然后按C键复制。

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

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

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

PS:你生产过的所有图形都会被用来升级建筑。 no_reward_freeplay: title: 下一关 @@ -729,21 +729,21 @@ settings: refreshRate: title: 模拟频率、刷新频率 description: >- - 如果你的显示器是144hz的,请在这里更改刷新频率,这样游戏可以正确地根据你的屏幕进行模拟。但是如果你的电脑性能不佳,提高刷新频率可能降低帧数。 + 如果你的显示器是 144Hz 的,请在这里更改刷新频率,这样游戏可以正确地根据你的屏幕进行模拟。但是如果你的电脑性能不佳,提高刷新频率可能降低帧数。 # description: >- # If you have a 144hz monitor, change the refresh rate here so the game will properly simulate at higher refresh rates. This might actually decrease the FPS if your computer is too slow. alwaysMultiplace: title: 多重放置 description: >- - 开启这个选项之后放下建筑将不会取消建筑选择。等同于一直按下SHIFT键。 + 开启这个选项之后放下建筑将不会取消建筑选择。等同于一直按下 SHIFT 键。 # description: >- # If enabled, all buildings will stay selected after placement until you cancel it. This is equivalent to holding SHIFT permanently. offerHints: title: 提示与教程 description: >- - 是否显示提示、教程以及一些其他的帮助理解游戏的UI元素。 + 是否显示提示、教程以及一些其他的帮助理解游戏的 UI 元素。 # description: >- # Whether to offer hints and tutorials while playing. Also hides certain UI elements onto a given level to make it easier to get into the game. @@ -799,7 +799,7 @@ settings: keybindings: title: 按键设置 hint: >- - 提示:使用CTRL、SHIFT、ALT! 这些建在放置建筑时有不同的效果。 + 提示:使用 CTRL、SHIFT、ALT!这些建在放置建筑时有不同的效果。 # hint: >- # Tip: Be sure to make use of CTRL, SHIFT and ALT! They enable different placement options. @@ -881,20 +881,20 @@ about: title: 关于游戏 # title: About this Game body: >- - 本游戏由Tobias Springer(我)开发,并且已经开源。

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

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

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

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

- 最后,我想感谢我最好的朋友Niklas——如果没有与他的异星工厂(factorio)的游戏体验,shapez.io将不会存在。 + 最后,我想感谢我最好的朋友 Niklas ——如果没有与他的异星工厂(factorio)的游戏体验,shapez.io将不会存在。 changelog: title: 版本日志 diff --git a/translations/base-zh-TW.yaml b/translations/base-zh-TW.yaml index 6225a73b..65aef6fa 100644 --- a/translations/base-zh-TW.yaml +++ b/translations/base-zh-TW.yaml @@ -45,6 +45,7 @@ # Painter:上色機 # Trash:垃圾桶 +--- steamPage: # This is the short text appearing on the steam page shortText: shapez.io 是一款在一個無邊際的地圖上建造工廠、自動化生產與組合愈加複雜圖形的遊戲。 diff --git a/yarn.lock b/yarn.lock index dff261d2..a67c83c2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -703,14 +703,6 @@ "@babel/types" "^7.4.4" esutils "^2.0.2" -"@babel/runtime@7.0.0-beta.42": - version "7.0.0-beta.42" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.0.0-beta.42.tgz#352e40c92e0460d3e82f49bd7e79f6cda76f919f" - integrity sha512-iOGRzUoONLOtmCvjUsZv3mZzgCT6ljHQY5fr1qG1QIiJQwtM7zbPWGGpa3QWETq+UqwWyJnoi5XZDZRwZDFciQ== - dependencies: - core-js "^2.5.3" - regenerator-runtime "^0.11.1" - "@babel/runtime@^7.8.4": version "7.9.2" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.9.2.tgz#d90df0583a3a252f09aaa619665367bae518db06" @@ -1257,13 +1249,6 @@ accepts@~1.3.7: mime-types "~2.1.24" negotiator "0.6.2" -acorn-jsx@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-3.0.1.tgz#afdf9488fb1ecefc8348f6fb22f464e32a58b36b" - integrity sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s= - dependencies: - acorn "^3.0.4" - acorn-jsx@^5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.2.0.tgz#4c66069173d6fdd68ed85239fc256226182b2ebe" @@ -1274,16 +1259,6 @@ acorn-walk@^7.1.1: resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-7.1.1.tgz#345f0dffad5c735e7373d2fec9a1023e6a44b83e" integrity sha512-wdlPY2tm/9XBr7QkKlq0WQVgiuGTX6YWPyRyBviSoScBuLfTVQhvwg6wJ369GJ/1nPfTLMfnrFIfjqVg6d+jQQ== -acorn@^3.0.4: - version "3.3.0" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-3.3.0.tgz#45e37fb39e8da3f25baee3ff5369e2bb5f22017a" - integrity sha1-ReN/s56No/JbruP/U2niu18iAXo= - -acorn@^5.5.0: - version "5.7.4" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.7.4.tgz#3e8d8a9947d0599a1796d10225d7432f4a4acf5e" - integrity sha512-1D++VG7BhrtvQpNbBzovKNc1FLGGEE/oGe7b9xJm/RFHMBeUaUGpluV9RLjZa47YFdPcDAenEYuq9pQPcMdLJg== - acorn@^6.4.1: version "6.4.1" resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.1.tgz#531e58ba3f51b9dacb9a6646ca4debf5b14ca474" @@ -1344,11 +1319,6 @@ amdefine@>=0.0.4: resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5" integrity sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU= -ansi-escapes@^1.1.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-1.4.0.tgz#d3a8a83b319aa67793662b13e761c7911422306e" - integrity sha1-06ioOzGapneTZisT52HHkRQiMG4= - ansi-escapes@^4.2.1: version "4.3.1" resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.1.tgz#a5c47cc43181f1f38ffd7076837700d395522a61" @@ -1361,11 +1331,6 @@ ansi-regex@^2.0.0: resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" integrity sha1-w7M6te42DYbg5ijwRorn7yfWVN8= -ansi-regex@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" - integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg= - ansi-regex@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997" @@ -1456,11 +1421,6 @@ arr-union@^3.1.0: resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4" integrity sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ= -array-differ@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/array-differ/-/array-differ-1.0.0.tgz#eff52e3758249d33be402b8bb8e564bb2b5d4031" - integrity sha1-7/UuN1gknTO+QCuLuOVkuytdQDE= - array-find-index@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/array-find-index/-/array-find-index-1.0.2.tgz#df010aa1287e164bbda6f9723b0a96a1ec4187a1" @@ -1471,28 +1431,11 @@ array-flatten@1.1.1: resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" integrity sha1-ml9pkFGx5wczKPKgCJaLZOopVdI= -array-union@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/array-union/-/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39" - integrity sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk= - dependencies: - array-uniq "^1.0.1" - -array-uniq@^1.0.1: - version "1.0.3" - resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6" - integrity sha1-r2rId6Jcx/dOBYiUdThY39sk/bY= - array-unique@^0.3.2: version "0.3.2" resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" integrity sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg= -arrify@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" - integrity sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0= - asn1.js@^4.0.0: version "4.10.1" resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-4.10.1.tgz#b9c2bf5805f1e64aadeed6df3a2bfafb5a73f5a0" @@ -1615,23 +1558,6 @@ babel-plugin-dynamic-import-node@^2.3.0: dependencies: object.assign "^4.1.0" -babel-polyfill@6.23.0: - version "6.23.0" - resolved "https://registry.yarnpkg.com/babel-polyfill/-/babel-polyfill-6.23.0.tgz#8364ca62df8eafb830499f699177466c3b03499d" - integrity sha1-g2TKYt+Or7gwSZ9pkXdGbDsDSZ0= - dependencies: - babel-runtime "^6.22.0" - core-js "^2.4.0" - regenerator-runtime "^0.10.0" - -babel-runtime@^6.22.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe" - integrity sha1-llxwWGaOgrVde/4E/yM3vItWR/4= - dependencies: - core-js "^2.4.0" - regenerator-runtime "^0.11.0" - babel-runtime@^7.0.0-beta.3: version "7.0.0-beta.3" resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-7.0.0-beta.3.tgz#7c750de5514452c27612172506b49085a4a630f2" @@ -1951,6 +1877,14 @@ buffer@^4.3.0: ieee754 "^1.1.4" isarray "^1.0.0" +buffer@^5.1.0: + version "5.6.0" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.6.0.tgz#a31749dc7d81d84db08abf937b6b8c4033f62786" + integrity sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw== + dependencies: + base64-js "^1.0.2" + ieee754 "^1.1.4" + buffer@^5.2.0, buffer@^5.2.1: version "5.5.0" resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.5.0.tgz#9c3caa3d623c33dd1c7ef584b89b88bf9c9bc1ce" @@ -2135,7 +2069,16 @@ caw@^2.0.0, caw@^2.0.1: tunnel-agent "^0.6.0" url-to-options "^1.0.1" -chalk@1.1.3, chalk@^1.0.0, chalk@^1.1.3: +chalk@2.4.2, chalk@^2.0.0, chalk@^2.4.1, chalk@^2.4.2: + version "2.4.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" + integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== + dependencies: + ansi-styles "^3.2.1" + escape-string-regexp "^1.0.5" + supports-color "^5.3.0" + +chalk@^1.0.0, chalk@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" integrity sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg= @@ -2146,24 +2089,6 @@ chalk@1.1.3, chalk@^1.0.0, chalk@^1.1.3: strip-ansi "^3.0.0" supports-color "^2.0.0" -chalk@2.3.2: - version "2.3.2" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.3.2.tgz#250dc96b07491bfd601e648d66ddf5f60c7a5c65" - integrity sha512-ZM4j2/ld/YZDc3Ma8PgN7gyAk+kHMMMyzLNryCPGhWrsfAuDVeuid5bpRFTDgMH9JBK2lA4dyyAkkZYF/WcqDQ== - dependencies: - ansi-styles "^3.2.1" - escape-string-regexp "^1.0.5" - supports-color "^5.3.0" - -chalk@2.4.2, chalk@^2.0.0, chalk@^2.0.1, chalk@^2.4.1, chalk@^2.4.2: - version "2.4.2" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" - integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== - dependencies: - ansi-styles "^3.2.1" - escape-string-regexp "^1.0.5" - supports-color "^5.3.0" - chalk@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/chalk/-/chalk-3.0.0.tgz#3f73c2bf526591f574cc492c51e2456349f844e4" @@ -2180,26 +2105,11 @@ chalk@^4.0.0: ansi-styles "^4.1.0" supports-color "^7.1.0" -chance@1.0.13: - version "1.0.13" - resolved "https://registry.yarnpkg.com/chance/-/chance-1.0.13.tgz#666bec2db42b3084456a3e4f4c28a82db5ccb7e6" - integrity sha512-9cpcgmAIQiXC0eMgQuMZgXuHR2Y+gKUyGQnalqSAg5LlUJyJFsZeKyuHVSGhj+bx18ppH+Jo3VOayNeXR/7p9Q== - -chardet@^0.4.0: - version "0.4.2" - resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.4.2.tgz#b5473b33dc97c424e5d98dc87d55d4d8a29c8bf2" - integrity sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I= - chardet@^0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA== -charenc@~0.0.1: - version "0.0.2" - resolved "https://registry.yarnpkg.com/charenc/-/charenc-0.0.2.tgz#c0a1d2f3a7092e03774bfa83f14c0fc5790a8667" - integrity sha1-wKHS86cJLgN3S/qD8UwPxXkKhmc= - check-types@^8.0.3: version "8.0.3" resolved "https://registry.yarnpkg.com/check-types/-/check-types-8.0.3.tgz#3356cca19c889544f2d7a95ed49ce508a0ecf552" @@ -2279,13 +2189,6 @@ class-utils@^0.3.5: isobject "^3.0.0" static-extend "^0.1.1" -class-validator@0.8.5: - version "0.8.5" - resolved "https://registry.yarnpkg.com/class-validator/-/class-validator-0.8.5.tgz#484785acda98f68549c3a84dc1bb2f77b736dc58" - integrity sha512-84yezRo44aP4oGhvPmqj6obAFQF1NzUyfR0+f8jubzdAspO5pmjpHhBBlPf335epUskzXAFe5uo4Qf+c7SI+DA== - dependencies: - validator "9.2.0" - clean-css@4.2.x: version "4.2.3" resolved "https://registry.yarnpkg.com/clean-css/-/clean-css-4.2.3.tgz#507b5de7d97b48ee53d84adb0160ff6216380f78" @@ -2293,13 +2196,6 @@ clean-css@4.2.x: dependencies: source-map "~0.6.0" -cli-cursor@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5" - integrity sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU= - dependencies: - restore-cursor "^2.0.0" - cli-cursor@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-3.1.0.tgz#264305a7ae490d1d03bf0c9ba7c925d1753af307" @@ -2404,11 +2300,6 @@ colors@^1.3.3: resolved "https://registry.yarnpkg.com/colors/-/colors-1.4.0.tgz#c50491479d4c1bdaed2c9ced32cf7c7dc2360f78" integrity sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA== -commander@2.15.1: - version "2.15.1" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.15.1.tgz#df46e867d0fc2aec66a34662b406a9ccafff5b0f" - integrity sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag== - commander@2.17.x: version "2.17.1" resolved "https://registry.yarnpkg.com/commander/-/commander-2.17.1.tgz#bd77ab7de6de94205ceacc72f1716d29f20a77bf" @@ -2538,7 +2429,7 @@ core-js@3: resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.6.5.tgz#7395dc273af37fb2e50e9bd3d9fe841285231d1a" integrity sha512-vZVEEwZoIsI+vPEuoF9Iqf5H7/M3eeQqWlQnYa8FSKKePuYTf5MWnxb5SDAzCa60b3JBRS5g9b+Dq7b1y/RCrA== -core-js@^2.4.0, core-js@^2.5.3, core-js@^2.5.7: +core-js@^2.4.0, core-js@^2.5.7: version "2.6.11" resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.11.tgz#38831469f9922bded8ee21c9dc46985e0399308c" integrity sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg== @@ -2558,6 +2449,13 @@ cosmiconfig@^5.0.0: js-yaml "^3.13.1" parse-json "^4.0.0" +crc@^3.8.0: + version "3.8.0" + resolved "https://registry.yarnpkg.com/crc/-/crc-3.8.0.tgz#ad60269c2c856f8c299e2c4cc0de4556914056c6" + integrity sha512-iX3mfgcTMIq3ZKLIsVFAbv7+Mc10kxabAGQb8HvjA1o3T1PIYprbakQ65d3I+2HGHt6nSKkM9PYjgoJO2KcFBQ== + dependencies: + buffer "^5.1.0" + create-ecdh@^4.0.0: version "4.0.3" resolved "https://registry.yarnpkg.com/create-ecdh/-/create-ecdh-4.0.3.tgz#c9111b6f33045c4697f144787f9254cdc77c45ff" @@ -2618,11 +2516,6 @@ cross-spawn@^7.0.2: shebang-command "^2.0.0" which "^2.0.1" -crypt@~0.0.1: - version "0.0.2" - resolved "https://registry.yarnpkg.com/crypt/-/crypt-0.0.2.tgz#88d7ff7ec0dfb86f713dc87bbb42d044d3e6c41b" - integrity sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs= - crypto-browserify@^3.11.0: version "3.12.0" resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.12.0.tgz#396cf9f3137f03e4b8e532c58f698254e00f80ec" @@ -2931,7 +2824,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= @@ -3168,13 +3061,6 @@ encodeurl@~1.0.2: resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k= -encoding@^0.1.11: - version "0.1.12" - resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.12.tgz#538b66f3ee62cd1ab51ec323829d1f9480c74beb" - integrity sha1-U4tm8+5izRq1HsMjgp0flIDHS+s= - dependencies: - iconv-lite "~0.4.13" - end-of-stream@^1.0.0, end-of-stream@^1.1.0: version "1.4.4" resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" @@ -3263,18 +3149,6 @@ escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= -escodegen-wallaby@1.6.18: - version "1.6.18" - resolved "https://registry.yarnpkg.com/escodegen-wallaby/-/escodegen-wallaby-1.6.18.tgz#95a41e2fdc88687466e43550c7bf136386fd4363" - integrity sha512-3UvR14JRNh8VfKJixTDHWmhPNKAJiVZS807KUjECBk6f05WMe8ZeWL1gbrswNYhDiAUeDBQccyTWR91fayx3og== - dependencies: - esprima "^2.7.1" - estraverse "^1.9.1" - esutils "^2.0.2" - optionator "^0.8.1" - optionalDependencies: - source-map "~0.2.0" - eslint-config-prettier@6.11.0: version "6.11.0" resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-6.11.0.tgz#f6d2238c1290d01c859a8b5c1f7d352a0b0da8b1" @@ -3359,14 +3233,6 @@ eslint@7.1.0: text-table "^0.2.0" v8-compile-cache "^2.0.3" -espree@3.5.4: - version "3.5.4" - resolved "https://registry.yarnpkg.com/espree/-/espree-3.5.4.tgz#b0f447187c8a8bed944b815a660bddf5deb5d1a7" - integrity sha512-yAcIQxtmMiB/jL32dzEp2enBeidsB7xWPLNiw3IIkpVds1P+h7qF9YwJq1yUNzp2OKXgAprs4F61ih66UsoD1A== - dependencies: - acorn "^5.5.0" - acorn-jsx "^3.0.0" - espree@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/espree/-/espree-7.0.0.tgz#8a7a60f218e69f120a842dc24c5a88aa7748a74e" @@ -3376,11 +3242,6 @@ espree@^7.0.0: acorn-jsx "^5.2.0" eslint-visitor-keys "^1.1.0" -esprima@^2.7.1: - version "2.7.3" - resolved "https://registry.yarnpkg.com/esprima/-/esprima-2.7.3.tgz#96e3b70d5779f6ad49cd032673d1c312767ba581" - integrity sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE= - esprima@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" @@ -3405,16 +3266,6 @@ esrecurse@^4.1.0, esrecurse@^4.2.1: dependencies: estraverse "^4.1.0" -estraverse@4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.2.0.tgz#0dee3fed31fcd469618ce7342099fc1afa0bdb13" - integrity sha1-De4/7TH81GlhjOc0IJn8GvoL2xM= - -estraverse@^1.9.1: - version "1.9.3" - resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-1.9.3.tgz#af67f2dc922582415950926091a4005d29c9bb44" - integrity sha1-r2fy3JIlgkFZUJJgkaQAXSnJu0Q= - estraverse@^4.1.0, estraverse@^4.1.1, estraverse@^4.2.0: version "4.3.0" resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" @@ -3585,15 +3436,6 @@ extend-shallow@^3.0.0, extend-shallow@^3.0.2: assign-symbols "^1.0.0" is-extendable "^1.0.1" -external-editor@^2.0.1: - version "2.2.0" - resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-2.2.0.tgz#045511cfd8d133f3846673d1047c154e214ad3d5" - integrity sha512-bSn6gvGxKt+b7+6TKEv1ZycHleA7aHhRHyAqJyp5pbUFuYYNIzpZnQDk7AsYckyWdEnTeAnay0aCy2aV6iTk9A== - dependencies: - chardet "^0.4.0" - iconv-lite "^0.4.17" - tmp "^0.0.33" - external-editor@^3.0.3: version "3.1.0" resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-3.1.0.tgz#cb03f740befae03ea4d283caed2741a83f335495" @@ -3632,7 +3474,7 @@ fast-json-stable-stringify@^2.0.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= @@ -3674,13 +3516,6 @@ figures@^1.3.5: escape-string-regexp "^1.0.5" object-assign "^4.1.0" -figures@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/figures/-/figures-2.0.0.tgz#3ab1a2d2a62c8bfb431a0c94cb797a2fce27c962" - integrity sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI= - dependencies: - escape-string-regexp "^1.0.5" - figures@^3.0.0: version "3.2.0" resolved "https://registry.yarnpkg.com/figures/-/figures-3.2.0.tgz#625c18bd293c604dc4a8ddb2febf0c88341746af" @@ -4364,7 +4199,7 @@ https-browserify@^1.0.0: resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73" integrity sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM= -iconv-lite@0.4.24, iconv-lite@^0.4.17, iconv-lite@^0.4.24, iconv-lite@~0.4.13: +iconv-lite@0.4.24, iconv-lite@^0.4.24: version "0.4.24" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== @@ -4490,25 +4325,6 @@ ini@^1.3.4, ini@^1.3.5: resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927" integrity sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw== -inquirer@3.0.6: - version "3.0.6" - resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-3.0.6.tgz#e04aaa9d05b7a3cb9b0f407d04375f0447190347" - integrity sha1-4EqqnQW3o8ubD0B9BDdfBEcZA0c= - dependencies: - ansi-escapes "^1.1.0" - chalk "^1.0.0" - cli-cursor "^2.1.0" - cli-width "^2.0.0" - external-editor "^2.0.1" - figures "^2.0.0" - lodash "^4.3.0" - mute-stream "0.0.7" - run-async "^2.2.0" - rx "^4.1.0" - string-width "^2.0.0" - strip-ansi "^3.0.0" - through "^2.3.6" - inquirer@^7.0.0: version "7.1.0" resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-7.1.0.tgz#1298a01859883e17c7264b82870ae1034f92dd29" @@ -4548,11 +4364,6 @@ invariant@^2.2.2, invariant@^2.2.4: dependencies: loose-envify "^1.0.0" -inversify@4.11.1: - version "4.11.1" - resolved "https://registry.yarnpkg.com/inversify/-/inversify-4.11.1.tgz#9a10635d1fd347da11da96475b3608babd5945a6" - integrity sha512-9bs/36crPdTSOCcoomHMb96s+B8W0+2c9dHFP/Srv9ZQaPnUvsMgzmMHfgVECqfHVUIW+M5S7SYOjoig8khWuQ== - invert-kv@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-2.0.0.tgz#7393f5afa59ec9ff5f67a27620d11c226e3eec02" @@ -4606,7 +4417,7 @@ is-binary-path@~2.1.0: dependencies: binary-extensions "^2.0.0" -is-buffer@^1.1.5, is-buffer@~1.1.1: +is-buffer@^1.1.5: version "1.1.6" resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== @@ -4770,11 +4581,6 @@ is-png@^2.0.0: resolved "https://registry.yarnpkg.com/is-png/-/is-png-2.0.0.tgz#ee8cbc9e9b050425cedeeb4a6fb74a649b0a4a8d" integrity sha512-4KPGizaVGj2LK7xwJIz8o5B2ubu1D/vcQsgOGFEDlpcvgZHto4gBnyd0ig7Ws+67ixmwKoNmu0hYnpo6AaKb5g== -is-promise@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa" - integrity sha1-eaKp7OfwlugPNtKy87wWwf9L8/o= - is-regex@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.5.tgz#39d589a358bf18967f726967120b8fc1aed74eae" @@ -4792,7 +4598,7 @@ is-retry-allowed@^1.0.0, is-retry-allowed@^1.1.0: resolved "https://registry.yarnpkg.com/is-retry-allowed/-/is-retry-allowed-1.2.0.tgz#d778488bd0a4666a3be8a1482b9f2baafedea8b4" integrity sha512-RUbUeKwvm3XG2VYamhJL1xFktgjvPzL0Hq8C+6yrWIswDy3BIXGqCxhxkc30N9jqK311gVU137K8Ei55/zVJRg== -is-stream@^1.0.0, is-stream@^1.0.1, is-stream@^1.1.0: +is-stream@^1.0.0, is-stream@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ= @@ -4861,31 +4667,6 @@ isurl@^1.0.0-alpha5: has-to-string-tag-x "^1.2.0" is-object "^1.0.1" -javascript-obfuscator@^0.15.0: - version "0.15.0" - resolved "https://registry.yarnpkg.com/javascript-obfuscator/-/javascript-obfuscator-0.15.0.tgz#e2b348c3a6895ef9195e3088f05747cff7a914f1" - integrity sha512-d4mzMLkwZarZE9ZDFXQapNba4iHEj6ARveU4qCz7j/T/TlrHJVbyhVRcZigIuiQqgotTWGub5vMCa2/ep+hA+w== - dependencies: - "@babel/runtime" "7.0.0-beta.42" - chalk "2.3.2" - chance "1.0.13" - class-validator "0.8.5" - commander "2.15.1" - escodegen-wallaby "1.6.18" - espree "3.5.4" - estraverse "4.2.0" - inversify "4.11.1" - js-string-escape "1.0.1" - md5 "2.2.1" - mkdirp "0.5.1" - multimatch "2.1.0" - opencollective "1.0.3" - pjson "1.0.9" - reflect-metadata "0.1.12" - source-map-support "0.5.4" - string-template "1.0.0" - tslib "1.9.0" - jimp@^0.6.1: version "0.6.8" resolved "https://registry.yarnpkg.com/jimp/-/jimp-0.6.8.tgz#63074984337cc469cd4030946e503e7c02a18b5c" @@ -4907,11 +4688,6 @@ js-base64@^2.1.9: resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-2.5.2.tgz#313b6274dda718f714d00b3330bbae6e38e90209" integrity sha512-Vg8czh0Q7sFBSUMWWArX/miJeBWYBPpdU/3M/DKSaekLMqrqVPaedp+5mZhie/r0lgrcaYBfwXatEew6gwgiQQ== -js-string-escape@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/js-string-escape/-/js-string-escape-1.0.1.tgz#e2625badbc0d67c7533e9edc1068c587ae4137ef" - integrity sha1-4mJbrbwNZ8dTPp7cEGjFh65BN+8= - "js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" @@ -5045,14 +4821,6 @@ levn@^0.4.1: prelude-ls "^1.2.1" type-check "~0.4.0" -levn@~0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" - integrity sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4= - dependencies: - prelude-ls "~1.1.2" - type-check "~0.3.2" - load-bmfont@^1.3.1, load-bmfont@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/load-bmfont/-/load-bmfont-1.4.0.tgz#75f17070b14a8c785fe7f5bee2e6fd4f98093b6b" @@ -5164,7 +4932,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.15.0, lodash@^4.17.11, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.3.0: +lodash@^4.15.0, lodash@^4.17.11, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15: version "4.17.15" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A== @@ -5313,15 +5081,6 @@ md5.js@^1.3.4: inherits "^2.0.1" safe-buffer "^5.1.2" -md5@2.2.1, md5@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/md5/-/md5-2.2.1.tgz#53ab38d5fe3c8891ba465329ea23fac0540126f9" - integrity sha1-U6s41f48iJG6RlMp6iP6wFQBJvk= - dependencies: - charenc "~0.0.1" - crypt "~0.0.1" - is-buffer "~1.1.1" - mdn-data@2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.4.tgz#699b3c38ac6f1d728091a64650b65d388502fd5b" @@ -5437,11 +5196,6 @@ mime@^2.4.0: resolved "https://registry.yarnpkg.com/mime/-/mime-2.4.4.tgz#bd7b91135fc6b01cde3e9bae33d659b63d8857e5" integrity sha512-LRxmNwziLPT828z+4YkNzloCFC2YM4wrB99k+AV5ZbEyfGNWfG8SO1FUXLmLDBSo89NrJZ4DIWeLjy1CHGhMGA== -mimic-fn@^1.0.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022" - integrity sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ== - mimic-fn@^2.0.0, mimic-fn@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" @@ -5469,7 +5223,7 @@ minimalistic-crypto-utils@^1.0.0, minimalistic-crypto-utils@^1.0.1: resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" integrity sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo= -minimatch@^3.0.0, minimatch@^3.0.4: +minimatch@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== @@ -5481,11 +5235,6 @@ minimist@0.0.8: resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0= -minimist@1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" - integrity sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ= - minimist@^1.1.3, minimist@^1.2.0, minimist@^1.2.5: version "1.2.5" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" @@ -5565,21 +5314,6 @@ ms@^2.1.1: resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== -multimatch@2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/multimatch/-/multimatch-2.1.0.tgz#9c7906a22fb4c02919e2f5f75161b4cdbd4b2a2b" - integrity sha1-nHkGoi+0wCkZ4vX3UWG0zb1LKis= - dependencies: - array-differ "^1.0.0" - array-union "^1.0.1" - arrify "^1.0.0" - minimatch "^3.0.0" - -mute-stream@0.0.7: - version "0.0.7" - resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" - integrity sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s= - mute-stream@0.0.8: version "0.0.8" resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d" @@ -5634,22 +5368,6 @@ no-case@^2.2.0: dependencies: lower-case "^1.1.1" -node-fetch@1.6.3: - version "1.6.3" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-1.6.3.tgz#dc234edd6489982d58e8f0db4f695029abcd8c04" - integrity sha1-3CNO3WSJmC1Y6PDbT2lQKavNjAQ= - dependencies: - encoding "^0.1.11" - is-stream "^1.0.1" - -node-fetch@^1.6.3: - version "1.7.3" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-1.7.3.tgz#980f6f72d85211a5347c6b2bc18c5b84c3eb47ef" - integrity sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ== - dependencies: - encoding "^0.1.11" - is-stream "^1.0.1" - node-libs-browser@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/node-libs-browser/-/node-libs-browser-2.2.1.tgz#b64f513d18338625f90346d27b0d235e631f6425" @@ -5752,15 +5470,6 @@ num2fraction@^1.2.2: resolved "https://registry.yarnpkg.com/num2fraction/-/num2fraction-1.2.2.tgz#6f682b6a027a4e9ddfa4564cd2589d1d4e669ede" integrity sha1-b2gragJ6Tp3fpFZM0lidHU5mnt4= -obfuscator-loader@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/obfuscator-loader/-/obfuscator-loader-1.1.2.tgz#6e8460066296fc642a68c945e64906e3c964cb0f" - integrity sha512-5PKsa4Vzq8uLJG0GT9BvC9ZxCr44wyV0c9wi782RYWh44GdFMSqlnUldgqSV+HQkFH3MWNc34AlSVSEhg7I26w== - dependencies: - esprima "^4.0.0" - javascript-obfuscator "^0.15.0" - loader-utils "^1.1.0" - object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" @@ -5846,21 +5555,6 @@ once@^1.3.0, once@^1.3.1, once@^1.4.0: dependencies: wrappy "1" -onesky-fetch@^0.0.7: - version "0.0.7" - resolved "https://registry.yarnpkg.com/onesky-fetch/-/onesky-fetch-0.0.7.tgz#96fce1a258a80683d6a37840958bae2f6fdb2809" - integrity sha1-lvzholioBoPWo3hAlYuuL2/bKAk= - dependencies: - md5 "^2.2.1" - node-fetch "^1.6.3" - -onetime@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/onetime/-/onetime-2.0.1.tgz#067428230fd67443b2794b22bba528b6867962d4" - integrity sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ= - dependencies: - mimic-fn "^1.0.0" - onetime@^5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.0.tgz#fff0f3c91617fe62bb50189636e99ac8a6df7be5" @@ -5868,43 +5562,11 @@ onetime@^5.1.0: dependencies: mimic-fn "^2.1.0" -opencollective@1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/opencollective/-/opencollective-1.0.3.tgz#aee6372bc28144583690c3ca8daecfc120dd0ef1" - integrity sha1-ruY3K8KBRFg2kMPKja7PwSDdDvE= - dependencies: - babel-polyfill "6.23.0" - chalk "1.1.3" - inquirer "3.0.6" - minimist "1.2.0" - node-fetch "1.6.3" - opn "4.0.2" - opener@^1.5.1: version "1.5.1" resolved "https://registry.yarnpkg.com/opener/-/opener-1.5.1.tgz#6d2f0e77f1a0af0032aca716c2c1fbb8e7e8abed" integrity sha512-goYSy5c2UXE4Ra1xixabeVh1guIX/ZV/YokJksb6q2lubWu6UbvPQ20p542/sFIll1nl8JnCyK9oBaOcCWXwvA== -opn@4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/opn/-/opn-4.0.2.tgz#7abc22e644dff63b0a96d5ab7f2790c0f01abc95" - integrity sha1-erwi5kTf9jsKltWrfyeQwPAavJU= - dependencies: - object-assign "^4.0.1" - pinkie-promise "^2.0.0" - -optionator@^0.8.1: - version "0.8.3" - resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495" - integrity sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA== - dependencies: - deep-is "~0.1.3" - fast-levenshtein "~2.0.6" - levn "~0.3.0" - prelude-ls "~1.1.2" - type-check "~0.3.2" - word-wrap "~1.2.3" - optionator@^0.9.1: version "0.9.1" resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.1.tgz#4f236a6373dae0566a6d43e1326674f50c291499" @@ -6284,11 +5946,6 @@ pixelmatch@^4.0.2: dependencies: pngjs "^3.0.0" -pjson@1.0.9: - version "1.0.9" - resolved "https://registry.yarnpkg.com/pjson/-/pjson-1.0.9.tgz#8a9520ce76a4739f8fee91679dad6b065b1c7938" - integrity sha512-4hRJH3YzkUpOlShRzhyxAmThSNnAaIlWZCAb27hd0pVUAXNUAHAO7XZbsPPvsCYwBFEScTmCCL6DGE8NyZ8BdQ== - pkg-dir@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-3.0.0.tgz#2749020f239ed990881b1f71210d51eb6523bea3" @@ -6993,11 +6650,6 @@ prelude-ls@^1.2.1: resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== -prelude-ls@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" - integrity sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ= - prepend-http@^1.0.1: version "1.0.4" resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-1.0.4.tgz#d4f4562b0ce3696e41ac52d0e002e57a635dc6dc" @@ -7281,11 +6933,6 @@ redent@^1.0.0: indent-string "^2.1.0" strip-indent "^1.0.1" -reflect-metadata@0.1.12: - version "0.1.12" - resolved "https://registry.yarnpkg.com/reflect-metadata/-/reflect-metadata-0.1.12.tgz#311bf0c6b63cd782f228a81abe146a2bfa9c56f2" - integrity sha512-n+IyV+nGz3+0q3/Yf1ra12KpCyi001bi4XFxSjbiWWjfqb52iTTtpGXmCCAOWWIAn9KEuFZKGqBERHmrtScZ3A== - regenerate-unicode-properties@^8.2.0: version "8.2.0" resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-8.2.0.tgz#e5de7111d655e7ba60c057dbe9ff37c87e65cdec" @@ -7298,12 +6945,7 @@ regenerate@^1.4.0: resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.0.tgz#4a856ec4b56e4077c557589cae85e7a4c8869a11" integrity sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg== -regenerator-runtime@^0.10.0: - version "0.10.5" - resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz#336c3efc1220adcedda2c9fab67b5a7955a33658" - integrity sha1-M2w+/BIgrc7dosn6tntaeVWjNlg= - -regenerator-runtime@^0.11.0, regenerator-runtime@^0.11.1: +regenerator-runtime@^0.11.0: version "0.11.1" resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9" integrity sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg== @@ -7439,14 +7081,6 @@ responselike@1.0.2: dependencies: lowercase-keys "^1.0.0" -restore-cursor@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf" - integrity sha1-n37ih/gv0ybU/RYpI9YhKe7g368= - dependencies: - onetime "^2.0.0" - signal-exit "^3.0.2" - restore-cursor@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-3.1.0.tgz#39f67c54b3a7a58cea5236d95cf0034239631f7e" @@ -7492,13 +7126,6 @@ ripemd160@^2.0.0, ripemd160@^2.0.1: hash-base "^3.0.0" inherits "^2.0.1" -run-async@^2.2.0: - version "2.4.0" - resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.4.0.tgz#e59054a5b86876cfae07f431d18cbaddc594f1e8" - integrity sha512-xJTbh/d7Lm7SBhc1tNvTpeCHaEzoyxPrqNlvSdMfBTYwaY++UJFyXUOxAtsRUXjlqOfj8luNaR9vjCh4KeV+pg== - dependencies: - is-promise "^2.1.0" - run-async@^2.4.0: version "2.4.1" resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.4.1.tgz#8440eccf99ea3e70bd409d49aab88e10c189a455" @@ -7516,11 +7143,6 @@ rusha@^0.8.13: resolved "https://registry.yarnpkg.com/rusha/-/rusha-0.8.13.tgz#9a084e7b860b17bff3015b92c67a6a336191513a" integrity sha1-mghOe4YLF7/zAVuSxnpqM2GRUTo= -rx@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/rx/-/rx-4.1.0.tgz#a5f13ff79ef3b740fe30aa803fb09f98805d4782" - integrity sha1-pfE/957zt0D+MKqAP7CfmIBdR4I= - rxjs@^6.5.3: version "6.5.5" resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.5.5.tgz#c5c884e3094c8cfee31bf27eb87e54ccfc87f9ec" @@ -7813,13 +7435,6 @@ source-map-resolve@^0.5.0: source-map-url "^0.4.0" urix "^0.1.0" -source-map-support@0.5.4: - version "0.5.4" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.4.tgz#54456efa89caa9270af7cd624cc2f123e51fbae8" - integrity sha512-PETSPG6BjY1AHs2t64vS2aqAgu6dMIMXJULWFBGbh2Gr8nVLbCFDo6i/RMMvviIQ2h1Z8+5gQhVKSn2je9nmdg== - dependencies: - source-map "^0.6.0" - source-map-support@~0.5.12: version "0.5.19" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.19.tgz#a98b62f86dcaf4f67399648c085291ab9e8fed61" @@ -7850,13 +7465,6 @@ source-map@~0.1.38: dependencies: amdefine ">=0.0.4" -source-map@~0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.2.0.tgz#dab73fbcfc2ba819b4de03bd6f6eaa48164b3f9d" - integrity sha1-2rc/vPwrqBm03gO9b26qSBZLP50= - dependencies: - amdefine ">=0.0.4" - spdx-correct@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.0.tgz#fb83e504445268f154b074e218c87c003cd31df4" @@ -7883,13 +7491,6 @@ spdx-license-ids@^3.0.0: resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz#3694b5804567a458d3c8045842a6358632f62654" integrity sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q== -speed-measure-webpack-plugin@^1.3.1: - version "1.3.3" - resolved "https://registry.yarnpkg.com/speed-measure-webpack-plugin/-/speed-measure-webpack-plugin-1.3.3.tgz#6ff894fc83e8a6310dde3af863a0329cd79da4f5" - integrity sha512-2ljD4Ch/rz2zG3HsLsnPfp23osuPBS0qPuz9sGpkNXTN1Ic4M+W9xB8l8rS8ob2cO4b1L+WTJw/0AJwWYVgcxQ== - dependencies: - chalk "^2.0.1" - split-on-first@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/split-on-first/-/split-on-first-1.1.0.tgz#f610afeee3b12bce1d0c30425e76398b78249a5f" @@ -8000,19 +7601,6 @@ string-replace-webpack-plugin@^0.1.3: file-loader "^0.8.1" style-loader "^0.8.3" -string-template@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/string-template/-/string-template-1.0.0.tgz#9e9f2233dc00f218718ec379a28a5673ecca8b96" - integrity sha1-np8iM9wA8hhxjsN5oopWc+zKi5Y= - -string-width@^2.0.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" - integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== - dependencies: - is-fullwidth-code-point "^2.0.0" - strip-ansi "^4.0.0" - string-width@^3.0.0, string-width@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961" @@ -8086,13 +7674,6 @@ strip-ansi@^3.0.0: dependencies: ansi-regex "^2.0.0" -strip-ansi@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" - integrity sha1-qEeQIusaw2iocTibY1JixQXuNo8= - dependencies: - ansi-regex "^3.0.0" - strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae" @@ -8419,11 +8000,6 @@ tryer@^1.0.1: resolved "https://registry.yarnpkg.com/tryer/-/tryer-1.0.1.tgz#f2c85406800b9b0f74c9f7465b81eaad241252f8" integrity sha512-c3zayb8/kWWpycWYg87P71E1S1ZL6b6IJxfb5fvsUgsf0S2MVGaDhDXXjDMpdCpfWXqptc+4mXwmiy1ypXqRAA== -tslib@1.9.0: - version "1.9.0" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.0.tgz#e37a86fda8cbbaf23a057f473c9f4dc64e5fc2e8" - integrity sha512-f/qGG2tUkrISBlQZEjEqoZ3B2+npJjIf04H1wuAv9iA8i04Icp+61KRXxFdha22670NJopsZCIjhC3SnjPRKrQ== - tslib@^1.8.1, tslib@^1.9.0: version "1.13.0" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.13.0.tgz#c881e13cc7015894ed914862d276436fa9a47043" @@ -8455,13 +8031,6 @@ type-check@^0.4.0, type-check@~0.4.0: dependencies: prelude-ls "^1.2.1" -type-check@~0.3.2: - version "0.3.2" - resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" - integrity sha1-WITKtRLPHTVeP7eE8wgEsrUg23I= - dependencies: - prelude-ls "~1.1.2" - type-fest@^0.11.0: version "0.11.0" resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.11.0.tgz#97abf0872310fed88a5c466b25681576145e33f1" @@ -8720,11 +8289,6 @@ validate-npm-package-license@^3.0.1: spdx-correct "^3.0.0" spdx-expression-parse "^3.0.0" -validator@9.2.0: - version "9.2.0" - resolved "https://registry.yarnpkg.com/validator/-/validator-9.2.0.tgz#ad216eed5f37cac31a6fe00ceab1f6b88bded03e" - integrity sha512-6Ij4Eo0KM4LkR0d0IegOwluG5453uqT5QyF5SV5Ezvm8/zmkKI/L4eoraafZGlZPC9guLkwKzgypcw8VGWWnGA== - vary@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" @@ -8881,7 +8445,7 @@ which@^2.0.1: dependencies: isexe "^2.0.0" -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==