1
0
mirror of https://github.com/tobspr/shapez.io.git synced 2025-06-13 13:04:03 +00:00

Merge pull request #3 from tobspr/master

Updating from base project
This commit is contained in:
BaleineSanguine 2020-09-23 18:35:25 +02:00 committed by GitHub
commit 8a019c285d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
85 changed files with 17213 additions and 16702 deletions

View File

@ -81,7 +81,7 @@ This project is based on ES5. Some ES2015 features are used but most of them are
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! 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 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` 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` 11. In `src/css/resources.scss` add your building to `$buildings` as well as `$buildingAndVariants`
12. Done! Optional: Add a new reward for unlocking your building at some point. 12. Done! Optional: Add a new reward for unlocking your building at some point.
#### Adding a new game system #### Adding a new game system

View File

@ -1,99 +1,137 @@
const path = require("path"); const path = require("path");
const buildUtils = require("./buildutils"); const buildUtils = require("./buildutils");
function gulptasksCSS($, gulp, buildFolder, browserSync) { function gulptasksCSS($, gulp, buildFolder, browserSync) {
// The assets plugin copies the files // The assets plugin copies the files
const commitHash = buildUtils.getRevision(); const commitHash = buildUtils.getRevision();
const postcssAssetsPlugin = cachebust => const postcssAssetsPlugin = cachebust =>
$.postcssAssets({ $.postcssAssets({
loadPaths: [path.join(buildFolder, "res", "ui")], loadPaths: [path.join(buildFolder, "res", "ui")],
basePath: buildFolder, basePath: buildFolder,
baseUrl: ".", baseUrl: ".",
cachebuster: cachebust cachebuster: cachebust
? (filePath, urlPathname) => ({ ? (filePath, urlPathname) => ({
pathname: buildUtils.cachebust(urlPathname, commitHash), pathname: buildUtils.cachebust(urlPathname, commitHash),
}) })
: "", : "",
}); });
// Postcss configuration // Postcss configuration
const postcssPlugins = (prod, { cachebust = false }) => { const postcssPlugins = (prod, { cachebust = false }) => {
const plugins = [postcssAssetsPlugin(cachebust)]; const plugins = [postcssAssetsPlugin(cachebust)];
if (prod) { if (prod) {
plugins.unshift( plugins.unshift(
$.postcssUnprefix(), $.postcssUnprefix(),
$.postcssPresetEnv({ $.postcssPresetEnv({
browsers: ["> 0.1%"], browsers: ["> 0.1%"],
}) })
); );
plugins.push( plugins.push(
$.cssMqpacker({ $.cssMqpacker({
sort: true, sort: true,
}), }),
$.cssnano({ $.cssnano({
preset: [ preset: [
"advanced", "advanced",
{ {
cssDeclarationSorter: false, cssDeclarationSorter: false,
discardUnused: true, discardUnused: true,
mergeIdents: false, mergeIdents: false,
reduceIdents: true, reduceIdents: true,
zindex: true, zindex: true,
}, },
], ],
}), }),
$.postcssRoundSubpixels() $.postcssRoundSubpixels()
); );
} }
return plugins; return plugins;
}; };
// Performs linting on css // Performs linting on css
gulp.task("css.lint", () => { gulp.task("css.lint", () => {
return gulp return gulp
.src(["../src/css/**/*.scss"]) .src(["../src/css/**/*.scss"])
.pipe($.sassLint({ configFile: ".sasslint.yml" })) .pipe($.sassLint({ configFile: ".sasslint.yml" }))
.pipe($.sassLint.format()) .pipe($.sassLint.format())
.pipe($.sassLint.failOnError()); .pipe($.sassLint.failOnError());
}); });
// Builds the css in dev mode function resourcesTask({ cachebust, isProd }) {
gulp.task("css.dev", () => { return gulp
return gulp .src("../src/css/main.scss", { cwd: __dirname })
.src(["../src/css/main.scss"]) .pipe($.plumber())
.pipe($.plumber()) .pipe($.sass.sync().on("error", $.sass.logError))
.pipe($.sass.sync().on("error", $.sass.logError)) .pipe(
.pipe($.postcss(postcssPlugins(false, {}))) $.postcss([
.pipe(gulp.dest(buildFolder)) $.postcssCriticalSplit({
.pipe(browserSync.stream()); blockTag: "@load-async",
}); }),
])
// Builds the css in production mode (=minified) )
gulp.task("css.prod", () => { .pipe($.rename("async-resources.css"))
return ( .pipe($.postcss(postcssPlugins(isProd, { cachebust })))
gulp .pipe(gulp.dest(buildFolder))
.src("../src/css/main.scss", { cwd: __dirname }) .pipe(browserSync.stream());
.pipe($.plumber()) }
.pipe($.sass.sync({ outputStyle: "compressed" }).on("error", $.sass.logError))
.pipe($.postcss(postcssPlugins(true, { cachebust: true }))) // Builds the css resources
.pipe(gulp.dest(buildFolder)) gulp.task("css.resources.dev", () => {
); return resourcesTask({ cachebust: false, isProd: false });
}); });
// Builds the css in production mode (=minified), without cachebusting // Builds the css resources in prod (=minified)
gulp.task("css.prod-standalone", () => { gulp.task("css.resources.prod", () => {
return ( return resourcesTask({ cachebust: true, isProd: true });
gulp });
.src("../src/css/main.scss", { cwd: __dirname })
.pipe($.plumber()) // Builds the css resources in prod (=minified), without cachebusting
.pipe($.sass.sync({ outputStyle: "compressed" }).on("error", $.sass.logError)) gulp.task("css.resources.prod-standalone", () => {
.pipe($.postcss(postcssPlugins(true, { cachebust: false }))) return resourcesTask({ cachebust: false, isProd: true });
.pipe(gulp.dest(buildFolder)) });
);
}); function mainTask({ cachebust, isProd }) {
} return gulp
.src("../src/css/main.scss", { cwd: __dirname })
module.exports = { .pipe($.plumber())
gulptasksCSS, .pipe($.sass.sync().on("error", $.sass.logError))
}; .pipe(
$.postcss([
$.postcssCriticalSplit({
blockTag: "@load-async",
output: "rest",
}),
])
)
.pipe($.postcss(postcssPlugins(isProd, { cachebust })))
.pipe(gulp.dest(buildFolder))
.pipe(browserSync.stream());
}
// Builds the css main
gulp.task("css.main.dev", () => {
return mainTask({ cachebust: false, isProd: false });
});
// Builds the css main in prod (=minified)
gulp.task("css.main.prod", () => {
return mainTask({ cachebust: true, isProd: true });
});
// Builds the css main in prod (=minified), without cachebusting
gulp.task("css.main.prod-standalone", () => {
return mainTask({ cachebust: false, isProd: true });
});
gulp.task("css.dev", gulp.parallel("css.main.dev", "css.resources.dev"));
gulp.task("css.prod", gulp.parallel("css.main.prod", "css.resources.prod"));
gulp.task(
"css.prod-standalone",
gulp.parallel("css.main.prod-standalone", "css.resources.prod-standalone")
);
}
module.exports = {
gulptasksCSS,
};

View File

@ -1,325 +1,325 @@
/* eslint-disable */ /* eslint-disable */
require("colors"); require("colors");
const gulp = require("gulp"); const gulp = require("gulp");
const browserSync = require("browser-sync").create({}); const browserSync = require("browser-sync").create({});
const path = require("path"); const path = require("path");
const deleteEmpty = require("delete-empty"); const deleteEmpty = require("delete-empty");
const execSync = require("child_process").execSync; const execSync = require("child_process").execSync;
const lfsOutput = execSync("git lfs install", { encoding: "utf-8" }); const lfsOutput = execSync("git lfs install", { encoding: "utf-8" });
if (!lfsOutput.toLowerCase().includes("git lfs initialized")) { if (!lfsOutput.toLowerCase().includes("git lfs initialized")) {
console.error(` console.error(`
Git LFS is not installed, unable to build. Git LFS is not installed, unable to build.
To install Git LFS on Linux: To install Git LFS on Linux:
- Arch: - Arch:
sudo pacman -S git-lfs sudo pacman -S git-lfs
- Debian/Ubuntu: - Debian/Ubuntu:
sudo apt install git-lfs sudo apt install git-lfs
For other systems, see: For other systems, see:
https://github.com/git-lfs/git-lfs/wiki/Installation https://github.com/git-lfs/git-lfs/wiki/Installation
`); `);
process.exit(1); process.exit(1);
} }
// Load other plugins dynamically // Load other plugins dynamically
const $ = require("gulp-load-plugins")({ const $ = require("gulp-load-plugins")({
scope: ["devDependencies"], scope: ["devDependencies"],
pattern: "*", pattern: "*",
}); });
// Check environment variables // Check environment variables
const envVars = [ const envVars = [
"SHAPEZ_CLI_SERVER_HOST", "SHAPEZ_CLI_SERVER_HOST",
// "SHAPEZ_CLI_PHONEGAP_KEY", // "SHAPEZ_CLI_PHONEGAP_KEY",
"SHAPEZ_CLI_ALPHA_FTP_USER", "SHAPEZ_CLI_ALPHA_FTP_USER",
"SHAPEZ_CLI_ALPHA_FTP_PW", "SHAPEZ_CLI_ALPHA_FTP_PW",
"SHAPEZ_CLI_STAGING_FTP_USER", "SHAPEZ_CLI_STAGING_FTP_USER",
"SHAPEZ_CLI_STAGING_FTP_PW", "SHAPEZ_CLI_STAGING_FTP_PW",
"SHAPEZ_CLI_LIVE_FTP_USER", "SHAPEZ_CLI_LIVE_FTP_USER",
"SHAPEZ_CLI_LIVE_FTP_PW", "SHAPEZ_CLI_LIVE_FTP_PW",
]; ];
for (let i = 0; i < envVars.length; ++i) { for (let i = 0; i < envVars.length; ++i) {
if (!process.env[envVars[i]]) { if (!process.env[envVars[i]]) {
console.warn("Please set", envVars[i]); console.warn("Please set", envVars[i]);
// process.exit(1); // process.exit(1);
} }
} }
const baseDir = path.join(__dirname, ".."); const baseDir = path.join(__dirname, "..");
const buildFolder = path.join(baseDir, "build"); const buildFolder = path.join(baseDir, "build");
const imgres = require("./image-resources"); const imgres = require("./image-resources");
imgres.gulptasksImageResources($, gulp, buildFolder); imgres.gulptasksImageResources($, gulp, buildFolder);
const css = require("./css"); const css = require("./css");
css.gulptasksCSS($, gulp, buildFolder, browserSync); css.gulptasksCSS($, gulp, buildFolder, browserSync);
const sounds = require("./sounds"); const sounds = require("./sounds");
sounds.gulptasksSounds($, gulp, buildFolder); sounds.gulptasksSounds($, gulp, buildFolder);
const js = require("./js"); const js = require("./js");
js.gulptasksJS($, gulp, buildFolder, browserSync); js.gulptasksJS($, gulp, buildFolder, browserSync);
const html = require("./html"); const html = require("./html");
html.gulptasksHTML($, gulp, buildFolder, browserSync); html.gulptasksHTML($, gulp, buildFolder, browserSync);
const ftp = require("./ftp"); const ftp = require("./ftp");
ftp.gulptasksFTP($, gulp, buildFolder); ftp.gulptasksFTP($, gulp, buildFolder);
const docs = require("./docs"); const docs = require("./docs");
docs.gulptasksDocs($, gulp, buildFolder); docs.gulptasksDocs($, gulp, buildFolder);
const standalone = require("./standalone"); const standalone = require("./standalone");
standalone.gulptasksStandalone($, gulp, buildFolder); standalone.gulptasksStandalone($, gulp, buildFolder);
const translations = require("./translations"); const translations = require("./translations");
translations.gulptasksTranslations($, gulp, buildFolder); translations.gulptasksTranslations($, gulp, buildFolder);
// FIXME // FIXME
// const cordova = require("./cordova"); // const cordova = require("./cordova");
// cordova.gulptasksCordova($, gulp, buildFolder); // cordova.gulptasksCordova($, gulp, buildFolder);
///////////////////// BUILD TASKS ///////////////////// ///////////////////// BUILD TASKS /////////////////////
// Cleans up everything // Cleans up everything
gulp.task("utils.cleanBuildFolder", () => { gulp.task("utils.cleanBuildFolder", () => {
return gulp.src(buildFolder, { read: false, allowEmpty: true }).pipe($.clean({ force: true })); return gulp.src(buildFolder, { read: false, allowEmpty: true }).pipe($.clean({ force: true }));
}); });
gulp.task("utils.cleanBuildTempFolder", () => { gulp.task("utils.cleanBuildTempFolder", () => {
return gulp return gulp
.src(path.join(__dirname, "..", "src", "js", "built-temp"), { read: false, allowEmpty: true }) .src(path.join(__dirname, "..", "src", "js", "built-temp"), { read: false, allowEmpty: true })
.pipe($.clean({ force: true })); .pipe($.clean({ force: true }));
}); });
gulp.task("utils.cleanup", gulp.series("utils.cleanBuildFolder", "utils.cleanBuildTempFolder")); gulp.task("utils.cleanup", gulp.series("utils.cleanBuildFolder", "utils.cleanBuildTempFolder"));
// Requires no uncomitted files // Requires no uncomitted files
gulp.task("utils.requireCleanWorkingTree", cb => { gulp.task("utils.requireCleanWorkingTree", cb => {
let output = $.trim(execSync("git status -su").toString("ascii")).replace(/\r/gi, "").split("\n"); let output = $.trim(execSync("git status -su").toString("ascii")).replace(/\r/gi, "").split("\n");
// Filter files which are OK to be untracked // Filter files which are OK to be untracked
output = output output = output
.map(x => x.replace(/[\r\n]+/gi, "")) .map(x => x.replace(/[\r\n]+/gi, ""))
.filter(x => x.indexOf(".local.js") < 0) .filter(x => x.indexOf(".local.js") < 0)
.filter(x => x.length > 0); .filter(x => x.length > 0);
if (output.length > 0) { if (output.length > 0) {
console.error("\n\nYou have unstaged changes, please commit everything first!"); console.error("\n\nYou have unstaged changes, please commit everything first!");
console.error("Unstaged files:"); console.error("Unstaged files:");
console.error(output.map(x => "'" + x + "'").join("\n")); console.error(output.map(x => "'" + x + "'").join("\n"));
process.exit(1); process.exit(1);
} }
cb(); cb();
}); });
gulp.task("utils.copyAdditionalBuildFiles", cb => { gulp.task("utils.copyAdditionalBuildFiles", cb => {
const additionalFolder = path.join("additional_build_files"); const additionalFolder = path.join("additional_build_files");
const additionalSrcGlobs = [ const additionalSrcGlobs = [
path.join(additionalFolder, "**/*.*"), path.join(additionalFolder, "**/*.*"),
path.join(additionalFolder, "**/.*"), path.join(additionalFolder, "**/.*"),
path.join(additionalFolder, "**/*"), path.join(additionalFolder, "**/*"),
]; ];
return gulp.src(additionalSrcGlobs).pipe(gulp.dest(buildFolder)); return gulp.src(additionalSrcGlobs).pipe(gulp.dest(buildFolder));
}); });
// Starts a webserver on the built directory (useful for testing prod build) // Starts a webserver on the built directory (useful for testing prod build)
gulp.task("main.webserver", () => { gulp.task("main.webserver", () => {
return gulp.src(buildFolder).pipe( return gulp.src(buildFolder).pipe(
$.webserver({ $.webserver({
livereload: { livereload: {
enable: true, enable: true,
}, },
directoryListing: false, directoryListing: false,
open: true, open: true,
port: 3005, port: 3005,
}) })
); );
}); });
function serve({ standalone }) { function serve({ standalone }) {
browserSync.init({ browserSync.init({
server: buildFolder, server: buildFolder,
port: 3005, port: 3005,
ghostMode: { ghostMode: {
clicks: false, clicks: false,
scroll: false, scroll: false,
location: false, location: false,
forms: false, forms: false,
}, },
logLevel: "info", logLevel: "info",
logPrefix: "BS", logPrefix: "BS",
online: false, online: false,
xip: false, xip: false,
notify: false, notify: false,
reloadDebounce: 100, reloadDebounce: 100,
reloadOnRestart: true, reloadOnRestart: true,
watchEvents: ["add", "change"], watchEvents: ["add", "change"],
}); });
// Watch .scss files, those trigger a css rebuild // Watch .scss files, those trigger a css rebuild
gulp.watch(["../src/**/*.scss"], gulp.series("css.dev")); gulp.watch(["../src/**/*.scss"], gulp.series("css.dev"));
// Watch .html files, those trigger a html rebuild // Watch .html files, those trigger a html rebuild
gulp.watch("../src/**/*.html", gulp.series(standalone ? "html.standalone-dev" : "html.dev")); gulp.watch("../src/**/*.html", gulp.series(standalone ? "html.standalone-dev" : "html.dev"));
// Watch sound files // Watch sound files
// gulp.watch(["../res_raw/sounds/**/*.mp3", "../res_raw/sounds/**/*.wav"], gulp.series("sounds.dev")); // gulp.watch(["../res_raw/sounds/**/*.mp3", "../res_raw/sounds/**/*.wav"], gulp.series("sounds.dev"));
// Watch translations // Watch translations
gulp.watch("../translations/**/*.yaml", gulp.series("translations.convertToJson")); gulp.watch("../translations/**/*.yaml", gulp.series("translations.convertToJson"));
gulp.watch( gulp.watch(
["../res_raw/sounds/sfx/*.mp3", "../res_raw/sounds/sfx/*.wav"], ["../res_raw/sounds/sfx/*.mp3", "../res_raw/sounds/sfx/*.wav"],
gulp.series("sounds.sfx", "sounds.copy") gulp.series("sounds.sfx", "sounds.copy")
); );
gulp.watch( gulp.watch(
["../res_raw/sounds/music/*.mp3", "../res_raw/sounds/music/*.wav"], ["../res_raw/sounds/music/*.mp3", "../res_raw/sounds/music/*.wav"],
gulp.series("sounds.music", "sounds.copy") gulp.series("sounds.music", "sounds.copy")
); );
// Watch resource files and copy them on change // Watch resource files and copy them on change
gulp.watch(imgres.nonImageResourcesGlobs, gulp.series("imgres.copyNonImageResources")); gulp.watch(imgres.nonImageResourcesGlobs, gulp.series("imgres.copyNonImageResources"));
gulp.watch(imgres.imageResourcesGlobs, gulp.series("imgres.copyImageResources")); gulp.watch(imgres.imageResourcesGlobs, gulp.series("imgres.copyImageResources"));
// Watch .atlas files and recompile the atlas on change // Watch .atlas files and recompile the atlas on change
gulp.watch("../res_built/atlas/*.json", gulp.series("imgres.atlas")); gulp.watch("../res_built/atlas/*.json", gulp.series("imgres.atlas"));
// Watch the build folder and reload when anything changed // Watch the build folder and reload when anything changed
const extensions = ["html", "js", "png", "gif", "jpg", "svg", "mp3", "ico", "woff2", "json"]; const extensions = ["html", "js", "png", "gif", "jpg", "svg", "mp3", "ico", "woff2", "json"];
gulp.watch(extensions.map(ext => path.join(buildFolder, "**", "*." + ext))).on("change", function (path) { gulp.watch(extensions.map(ext => path.join(buildFolder, "**", "*." + ext))).on("change", function (path) {
return gulp.src(path).pipe(browserSync.reload({ stream: true })); return gulp.src(path).pipe(browserSync.reload({ stream: true }));
}); });
gulp.watch("../src/js/built-temp/*.json").on("change", function (path) { gulp.watch("../src/js/built-temp/*.json").on("change", function (path) {
return gulp.src(path).pipe(browserSync.reload({ stream: true })); return gulp.src(path).pipe(browserSync.reload({ stream: true }));
}); });
// Start the webpack watching server (Will never return) // Start the webpack watching server (Will never return)
if (standalone) { if (standalone) {
gulp.series("js.standalone-dev.watch")(() => true); gulp.series("js.standalone-dev.watch")(() => true);
} else { } else {
gulp.series("js.dev.watch")(() => true); gulp.series("js.dev.watch")(() => true);
} }
} }
///////////////////// RUNNABLE TASKS ///////////////////// ///////////////////// RUNNABLE TASKS /////////////////////
// Pre and postbuild // Pre and postbuild
gulp.task("step.baseResources", gulp.series("imgres.allOptimized")); gulp.task("step.baseResources", gulp.series("imgres.allOptimized"));
gulp.task("step.deleteEmpty", cb => { gulp.task("step.deleteEmpty", cb => {
deleteEmpty.sync(buildFolder); deleteEmpty.sync(buildFolder);
cb(); cb();
}); });
gulp.task("step.postbuild", gulp.series("imgres.cleanupUnusedCssInlineImages", "step.deleteEmpty")); gulp.task("step.postbuild", gulp.series("imgres.cleanupUnusedCssInlineImages", "step.deleteEmpty"));
// Builds everything (dev) // Builds everything (dev)
gulp.task( gulp.task(
"build.dev", "build.dev",
gulp.series( gulp.series(
"utils.cleanup", "utils.cleanup",
"utils.copyAdditionalBuildFiles", "utils.copyAdditionalBuildFiles",
"imgres.atlas", "imgres.atlas",
"sounds.dev", "sounds.dev",
"imgres.copyImageResources", "imgres.copyImageResources",
"imgres.copyNonImageResources", "imgres.copyNonImageResources",
"translations.fullBuild", "translations.fullBuild",
"css.dev", "css.dev",
"html.dev" "html.dev"
) )
); );
// Builds everything (standalone -dev) // Builds everything (standalone -dev)
gulp.task( gulp.task(
"build.standalone.dev", "build.standalone.dev",
gulp.series( gulp.series(
"utils.cleanup", "utils.cleanup",
"imgres.atlas", "imgres.atlas",
"sounds.dev", "sounds.dev",
"imgres.copyImageResources", "imgres.copyImageResources",
"imgres.copyNonImageResources", "imgres.copyNonImageResources",
"translations.fullBuild", "translations.fullBuild",
"js.standalone-dev", "js.standalone-dev",
"css.dev", "css.dev",
"html.standalone-dev" "html.standalone-dev"
) )
); );
// Builds everything (staging) // Builds everything (staging)
gulp.task("step.staging.code", gulp.series("sounds.fullbuild", "translations.fullBuild", "js.staging")); gulp.task("step.staging.code", gulp.series("sounds.fullbuild", "translations.fullBuild", "js.staging"));
gulp.task( gulp.task(
"step.staging.mainbuild", "step.staging.mainbuild",
gulp.parallel("utils.copyAdditionalBuildFiles", "step.baseResources", "step.staging.code") gulp.parallel("utils.copyAdditionalBuildFiles", "step.baseResources", "step.staging.code")
); );
gulp.task("step.staging.all", gulp.series("step.staging.mainbuild", "css.prod", "html.staging")); gulp.task("step.staging.all", gulp.series("step.staging.mainbuild", "css.prod", "html.staging"));
gulp.task("build.staging", gulp.series("utils.cleanup", "step.staging.all", "step.postbuild")); gulp.task("build.staging", gulp.series("utils.cleanup", "step.staging.all", "step.postbuild"));
// Builds everything (prod) // Builds everything (prod)
gulp.task("step.prod.code", gulp.series("sounds.fullbuild", "translations.fullBuild", "js.prod")); gulp.task("step.prod.code", gulp.series("sounds.fullbuild", "translations.fullBuild", "js.prod"));
gulp.task( gulp.task(
"step.prod.mainbuild", "step.prod.mainbuild",
gulp.parallel("utils.copyAdditionalBuildFiles", "step.baseResources", "step.prod.code") gulp.parallel("utils.copyAdditionalBuildFiles", "step.baseResources", "step.prod.code")
); );
gulp.task("step.prod.all", gulp.series("step.prod.mainbuild", "css.prod", "html.prod")); gulp.task("step.prod.all", gulp.series("step.prod.mainbuild", "css.prod", "html.prod"));
gulp.task("build.prod", gulp.series("utils.cleanup", "step.prod.all", "step.postbuild")); gulp.task("build.prod", gulp.series("utils.cleanup", "step.prod.all", "step.postbuild"));
// Builds everything (standalone-beta) // Builds everything (standalone-beta)
gulp.task( gulp.task(
"step.standalone-beta.code", "step.standalone-beta.code",
gulp.series("sounds.fullbuildHQ", "translations.fullBuild", "js.standalone-beta") gulp.series("sounds.fullbuildHQ", "translations.fullBuild", "js.standalone-beta")
); );
gulp.task("step.standalone-beta.mainbuild", gulp.parallel("step.baseResources", "step.standalone-beta.code")); gulp.task("step.standalone-beta.mainbuild", gulp.parallel("step.baseResources", "step.standalone-beta.code"));
gulp.task( gulp.task(
"step.standalone-beta.all", "step.standalone-beta.all",
gulp.series("step.standalone-beta.mainbuild", "css.prod-standalone", "html.standalone-beta") gulp.series("step.standalone-beta.mainbuild", "css.prod-standalone", "html.standalone-beta")
); );
gulp.task( gulp.task(
"build.standalone-beta", "build.standalone-beta",
gulp.series("utils.cleanup", "step.standalone-beta.all", "step.postbuild") gulp.series("utils.cleanup", "step.standalone-beta.all", "step.postbuild")
); );
// Builds everything (standalone-prod) // Builds everything (standalone-prod)
gulp.task( gulp.task(
"step.standalone-prod.code", "step.standalone-prod.code",
gulp.series("sounds.fullbuildHQ", "translations.fullBuild", "js.standalone-prod") gulp.series("sounds.fullbuildHQ", "translations.fullBuild", "js.standalone-prod")
); );
gulp.task("step.standalone-prod.mainbuild", gulp.parallel("step.baseResources", "step.standalone-prod.code")); gulp.task("step.standalone-prod.mainbuild", gulp.parallel("step.baseResources", "step.standalone-prod.code"));
gulp.task( gulp.task(
"step.standalone-prod.all", "step.standalone-prod.all",
gulp.series("step.standalone-prod.mainbuild", "css.prod-standalone", "html.standalone-prod") gulp.series("step.standalone-prod.mainbuild", "css.prod-standalone", "html.standalone-prod")
); );
gulp.task( gulp.task(
"build.standalone-prod", "build.standalone-prod",
gulp.series("utils.cleanup", "step.standalone-prod.all", "step.postbuild") gulp.series("utils.cleanup", "step.standalone-prod.all", "step.postbuild")
); );
// Deploying! // Deploying!
gulp.task( gulp.task(
"main.deploy.alpha", "main.deploy.alpha",
gulp.series("utils.requireCleanWorkingTree", "build.staging", "ftp.upload.alpha") gulp.series("utils.requireCleanWorkingTree", "build.staging", "ftp.upload.alpha")
); );
gulp.task( gulp.task(
"main.deploy.staging", "main.deploy.staging",
gulp.series("utils.requireCleanWorkingTree", "build.staging", "ftp.upload.staging") gulp.series("utils.requireCleanWorkingTree", "build.staging", "ftp.upload.staging")
); );
gulp.task("main.deploy.prod", gulp.series("utils.requireCleanWorkingTree", "build.prod", "ftp.upload.prod")); gulp.task("main.deploy.prod", gulp.series("utils.requireCleanWorkingTree", "build.prod", "ftp.upload.prod"));
gulp.task("main.deploy.all", gulp.series("main.deploy.staging", "main.deploy.prod")); gulp.task("main.deploy.all", gulp.series("main.deploy.staging", "main.deploy.prod"));
gulp.task("main.standalone", gulp.series("build.standalone-prod", "standalone.package.prod")); gulp.task("main.standalone", gulp.series("build.standalone-prod", "standalone.package.prod"));
// Live-development // Live-development
gulp.task( gulp.task(
"main.serveDev", "main.serveDev",
gulp.series("build.dev", () => serve({ standalone: false })) gulp.series("build.dev", () => serve({ standalone: false }))
); );
gulp.task( gulp.task(
"main.serveStandalone", "main.serveStandalone",
gulp.series("build.standalone.dev", () => serve({ standalone: true })) gulp.series("build.standalone.dev", () => serve({ standalone: true }))
); );
gulp.task("default", gulp.series("main.serveDev")); gulp.task("default", gulp.series("main.serveDev"));

View File

@ -1,283 +1,301 @@
const buildUtils = require("./buildutils"); const buildUtils = require("./buildutils");
const fs = require("fs"); const fs = require("fs");
const path = require("path"); const path = require("path");
const crypto = require("crypto"); const crypto = require("crypto");
function computeIntegrityHash(fullPath, algorithm = "sha256") { function computeIntegrityHash(fullPath, algorithm = "sha256") {
const file = fs.readFileSync(fullPath); const file = fs.readFileSync(fullPath);
const hash = crypto.createHash(algorithm).update(file).digest("base64"); const hash = crypto.createHash(algorithm).update(file).digest("base64");
return algorithm + "-" + hash; return algorithm + "-" + hash;
} }
function gulptasksHTML($, gulp, buildFolder) { function gulptasksHTML($, gulp, buildFolder) {
const commitHash = buildUtils.getRevision(); const commitHash = buildUtils.getRevision();
async function buildHtml( async function buildHtml(
apiUrl, apiUrl,
{ analytics = false, standalone = false, app = false, integrity = true, enableCachebust = true } { analytics = false, standalone = false, app = false, integrity = true, enableCachebust = true }
) { ) {
function cachebust(url) { function cachebust(url) {
if (enableCachebust) { if (enableCachebust) {
return buildUtils.cachebust(url, commitHash); return buildUtils.cachebust(url, commitHash);
} }
return url; return url;
} }
const hasLocalFiles = standalone || app; const hasLocalFiles = standalone || app;
return gulp return gulp
.src("../src/html/" + (standalone ? "index.standalone.html" : "index.html")) .src("../src/html/" + (standalone ? "index.standalone.html" : "index.html"))
.pipe( .pipe(
$.dom(/** @this {Document} **/ function () { $.dom(
const document = this; /** @this {Document} **/ function () {
const document = this;
// Preconnect to api
const prefetchLink = document.createElement("link"); // Preconnect to api
prefetchLink.rel = "preconnect"; const prefetchLink = document.createElement("link");
prefetchLink.href = apiUrl; prefetchLink.rel = "preconnect";
prefetchLink.setAttribute("crossorigin", "anonymous"); prefetchLink.href = apiUrl;
document.head.appendChild(prefetchLink); prefetchLink.setAttribute("crossorigin", "anonymous");
document.head.appendChild(prefetchLink);
// Append css
const css = document.createElement("link"); // Append css
css.rel = "stylesheet"; const css = document.createElement("link");
css.type = "text/css"; css.rel = "stylesheet";
css.media = "none"; css.type = "text/css";
css.setAttribute("onload", "this.media='all'"); css.media = "none";
css.href = cachebust("main.css"); css.setAttribute("onload", "this.media='all'");
if (integrity) { css.href = cachebust("main.css");
css.setAttribute( if (integrity) {
"integrity", css.setAttribute(
computeIntegrityHash(path.join(buildFolder, "main.css")) "integrity",
); computeIntegrityHash(path.join(buildFolder, "main.css"))
} );
document.head.appendChild(css); }
document.head.appendChild(css);
if (app) {
// Append cordova link // Append async css
const cdv = document.createElement("script"); const asyncCss = document.createElement("link");
cdv.src = "cordova.js"; asyncCss.rel = "stylesheet";
cdv.type = "text/javascript"; asyncCss.type = "text/css";
document.head.appendChild(cdv); asyncCss.media = "none";
} asyncCss.setAttribute("onload", "this.media='all'");
asyncCss.href = cachebust("async-resources.css");
// Google analytics if (integrity) {
if (analytics) { asyncCss.setAttribute(
const tagManagerScript = document.createElement("script"); "integrity",
tagManagerScript.src = "https://www.googletagmanager.com/gtag/js?id=UA-165342524-1"; computeIntegrityHash(path.join(buildFolder, "async-resources.css"))
tagManagerScript.setAttribute("async", ""); );
document.head.appendChild(tagManagerScript); }
document.head.appendChild(asyncCss);
const initScript = document.createElement("script");
initScript.textContent = ` if (app) {
window.dataLayer = window.dataLayer || []; // Append cordova link
function gtag(){dataLayer.push(arguments);} const cdv = document.createElement("script");
gtag('js', new Date()); cdv.src = "cordova.js";
gtag('config', 'UA-165342524-1', { anonymize_ip: true }); cdv.type = "text/javascript";
`; document.head.appendChild(cdv);
document.head.appendChild(initScript); }
const abTestingScript = document.createElement("script"); // Google analytics
abTestingScript.setAttribute( if (analytics) {
"src", const tagManagerScript = document.createElement("script");
"https://www.googleoptimize.com/optimize.js?id=OPT-M5NHCV7" tagManagerScript.src =
); "https://www.googletagmanager.com/gtag/js?id=UA-165342524-1";
abTestingScript.setAttribute("async", ""); tagManagerScript.setAttribute("async", "");
document.head.appendChild(abTestingScript); document.head.appendChild(tagManagerScript);
}
const initScript = document.createElement("script");
// Do not need to preload in app or standalone initScript.textContent = `
if (!hasLocalFiles) { window.dataLayer = window.dataLayer || [];
// Preload essentials function gtag(){dataLayer.push(arguments);}
const preloads = ["fonts/GameFont.woff2"]; gtag('js', new Date());
gtag('config', 'UA-165342524-1', { anonymize_ip: true });
preloads.forEach(src => { `;
const preloadLink = document.createElement("link"); document.head.appendChild(initScript);
preloadLink.rel = "preload";
preloadLink.href = cachebust("res/" + src); const abTestingScript = document.createElement("script");
if (src.endsWith(".woff2")) { abTestingScript.setAttribute(
preloadLink.setAttribute("crossorigin", "anonymous"); "src",
preloadLink.setAttribute("as", "font"); "https://www.googleoptimize.com/optimize.js?id=OPT-M5NHCV7"
} else { );
preloadLink.setAttribute("as", "image"); abTestingScript.setAttribute("async", "");
} document.head.appendChild(abTestingScript);
document.head.appendChild(preloadLink); }
});
} // Do not need to preload in app or standalone
if (!hasLocalFiles) {
const loadingSvg = `background-image: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHN0eWxlPSJtYXJnaW46YXV0bztiYWNrZ3JvdW5kOjAgMCIgd2lkdGg9IjIwMCIgaGVpZ2h0PSIyMDAiIHZpZXdCb3g9IjAgMCAxMDAgMTAwIiBwcmVzZXJ2ZUFzcGVjdFJhdGlvPSJ4TWlkWU1pZCIgZGlzcGxheT0iYmxvY2siPjxjaXJjbGUgY3g9IjUwIiBjeT0iNTAiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzM5Mzc0NyIgc3Ryb2tlLXdpZHRoPSIzIiByPSI0MiIgc3Ryb2tlLWRhc2hhcnJheT0iMTk3LjkyMDMzNzE3NjE1Njk4IDY3Ljk3MzQ0NTcyNTM4NTY2IiB0cmFuc2Zvcm09InJvdGF0ZSg0OC4yNjUgNTAgNTApIj48YW5pbWF0ZVRyYW5zZm9ybSBhdHRyaWJ1dGVOYW1lPSJ0cmFuc2Zvcm0iIHR5cGU9InJvdGF0ZSIgcmVwZWF0Q291bnQ9ImluZGVmaW5pdGUiIGR1cj0iNS41NTU1NTU1NTU1NTU1NTVzIiB2YWx1ZXM9IjAgNTAgNTA7MzYwIDUwIDUwIiBrZXlUaW1lcz0iMDsxIi8+PC9jaXJjbGU+PC9zdmc+")`; // Preload essentials
const preloads = ["fonts/GameFont.woff2"];
const loadingCss = `
@font-face { preloads.forEach(src => {
font-family: 'GameFont'; const preloadLink = document.createElement("link");
font-style: normal; preloadLink.rel = "preload";
font-weight: normal; preloadLink.href = cachebust("res/" + src);
font-display: swap; if (src.endsWith(".woff2")) {
src: url('${cachebust("res/fonts/GameFont.woff2")}') format('woff2'); preloadLink.setAttribute("crossorigin", "anonymous");
} preloadLink.setAttribute("as", "font");
} else {
#ll_fp { preloadLink.setAttribute("as", "image");
font-family: GameFont; }
font-size: 14px; document.head.appendChild(preloadLink);
position: fixed; });
z-index: -1; }
top: 0;
left: 0; const loadingSvg = `background-image: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHN0eWxlPSJtYXJnaW46YXV0bztiYWNrZ3JvdW5kOjAgMCIgd2lkdGg9IjIwMCIgaGVpZ2h0PSIyMDAiIHZpZXdCb3g9IjAgMCAxMDAgMTAwIiBwcmVzZXJ2ZUFzcGVjdFJhdGlvPSJ4TWlkWU1pZCIgZGlzcGxheT0iYmxvY2siPjxjaXJjbGUgY3g9IjUwIiBjeT0iNTAiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzM5Mzc0NyIgc3Ryb2tlLXdpZHRoPSIzIiByPSI0MiIgc3Ryb2tlLWRhc2hhcnJheT0iMTk3LjkyMDMzNzE3NjE1Njk4IDY3Ljk3MzQ0NTcyNTM4NTY2IiB0cmFuc2Zvcm09InJvdGF0ZSg0OC4yNjUgNTAgNTApIj48YW5pbWF0ZVRyYW5zZm9ybSBhdHRyaWJ1dGVOYW1lPSJ0cmFuc2Zvcm0iIHR5cGU9InJvdGF0ZSIgcmVwZWF0Q291bnQ9ImluZGVmaW5pdGUiIGR1cj0iNS41NTU1NTU1NTU1NTU1NTVzIiB2YWx1ZXM9IjAgNTAgNTA7MzYwIDUwIDUwIiBrZXlUaW1lcz0iMDsxIi8+PC9jaXJjbGU+PC9zdmc+")`;
opacity: 0.05;
} const loadingCss = `
@font-face {
#ll_p { font-family: 'GameFont';
display: flex; font-style: normal;
position: fixed; font-weight: normal;
z-index: 99999; font-display: swap;
top: 0; src: url('${cachebust("res/fonts/GameFont.woff2")}') format('woff2');
left: 0; }
right: 0;
bottom: 0; #ll_fp {
justify-content: font-family: GameFont;
center; font-size: 14px;
align-items: center; position: fixed;
} z-index: -1;
top: 0;
#ll_p > div { left: 0;
position: absolute; opacity: 0.05;
text-align: center; }
bottom: 40px;
left: 20px; #ll_p {
right: 20px; display: flex;
color: #393747; position: fixed;
font-family: 'GameFont', sans-serif; z-index: 99999;
font-size: 20px; top: 0;
} left: 0;
right: 0;
#ll_p > span { bottom: 0;
width: 60px; justify-content:
height: 60px; center;
display: inline-flex; align-items: center;
background: center center / contain no-repeat; }
${loadingSvg};
} #ll_p > div {
`; position: absolute;
text-align: center;
const style = document.createElement("style"); bottom: 40px;
style.setAttribute("type", "text/css"); left: 20px;
style.textContent = loadingCss; right: 20px;
document.head.appendChild(style); color: #393747;
font-family: 'GameFont', sans-serif;
// Append loader, but not in standalone (directly include bundle there) font-size: 20px;
if (standalone) { }
const bundleScript = document.createElement("script");
bundleScript.type = "text/javascript"; #ll_p > span {
bundleScript.src = "bundle.js"; width: 60px;
if (integrity) { height: 60px;
bundleScript.setAttribute( display: inline-flex;
"integrity", background: center center / contain no-repeat;
computeIntegrityHash(path.join(buildFolder, "bundle.js")) ${loadingSvg};
); }
} `;
document.head.appendChild(bundleScript);
} else { const style = document.createElement("style");
const loadJs = document.createElement("script"); style.setAttribute("type", "text/css");
loadJs.type = "text/javascript"; style.textContent = loadingCss;
let scriptContent = ""; document.head.appendChild(style);
scriptContent += `var bundleSrc = '${cachebust("bundle.js")}';\n`;
scriptContent += `var bundleSrcTranspiled = '${cachebust( // Append loader, but not in standalone (directly include bundle there)
"bundle-transpiled.js" if (standalone) {
)}';\n`; const bundleScript = document.createElement("script");
bundleScript.type = "text/javascript";
if (integrity) { bundleScript.src = "bundle.js";
scriptContent += if (integrity) {
"var bundleIntegrity = '" + bundleScript.setAttribute(
computeIntegrityHash(path.join(buildFolder, "bundle.js")) + "integrity",
"';\n"; computeIntegrityHash(path.join(buildFolder, "bundle.js"))
scriptContent += );
"var bundleIntegrityTranspiled = '" + }
computeIntegrityHash(path.join(buildFolder, "bundle-transpiled.js")) + document.head.appendChild(bundleScript);
"';\n"; } else {
} else { const loadJs = document.createElement("script");
scriptContent += "var bundleIntegrity = null;\n"; loadJs.type = "text/javascript";
scriptContent += "var bundleIntegrityTranspiled = null;\n"; let scriptContent = "";
} scriptContent += `var bundleSrc = '${cachebust("bundle.js")}';\n`;
scriptContent += `var bundleSrcTranspiled = '${cachebust(
scriptContent += fs.readFileSync("./bundle-loader.js").toString(); "bundle-transpiled.js"
loadJs.textContent = scriptContent; )}';\n`;
document.head.appendChild(loadJs);
} if (integrity) {
scriptContent +=
const bodyContent = ` "var bundleIntegrity = '" +
<div id="ll_fp">_</div> computeIntegrityHash(path.join(buildFolder, "bundle.js")) +
<div id="ll_p"> "';\n";
<span></span> scriptContent +=
<div>${hasLocalFiles ? "Loading" : "Downloading"} Game Files</div > "var bundleIntegrityTranspiled = '" +
</div > computeIntegrityHash(path.join(buildFolder, "bundle-transpiled.js")) +
`; "';\n";
} else {
document.body.innerHTML = bodyContent; scriptContent += "var bundleIntegrity = null;\n";
}) scriptContent += "var bundleIntegrityTranspiled = null;\n";
) }
.pipe(
$.htmlmin({ scriptContent += fs.readFileSync("./bundle-loader.js").toString();
caseSensitive: true, loadJs.textContent = scriptContent;
collapseBooleanAttributes: true, document.head.appendChild(loadJs);
collapseInlineTagWhitespace: true, }
collapseWhitespace: true,
preserveLineBreaks: true, const bodyContent = `
minifyJS: true, <div id="ll_fp">_</div>
minifyCSS: true, <div id="ll_p">
quoteCharacter: '"', <span></span>
useShortDoctype: true, <div>${hasLocalFiles ? "Loading" : "Downloading"} Game Files</div >
}) </div >
) `;
.pipe($.htmlBeautify())
.pipe($.rename("index.html")) document.body.innerHTML = bodyContent;
.pipe(gulp.dest(buildFolder)); }
} )
)
gulp.task("html.dev", () => { .pipe(
return buildHtml("http://localhost:5005", { $.htmlmin({
analytics: false, caseSensitive: true,
integrity: false, collapseBooleanAttributes: true,
enableCachebust: false, collapseInlineTagWhitespace: true,
}); collapseWhitespace: true,
}); preserveLineBreaks: true,
minifyJS: true,
gulp.task("html.staging", () => { minifyCSS: true,
return buildHtml("https://api-staging.shapez.io", { quoteCharacter: '"',
analytics: true, useShortDoctype: true,
}); })
}); )
.pipe($.htmlBeautify())
gulp.task("html.prod", () => { .pipe($.rename("index.html"))
return buildHtml("https://analytics.shapez.io", { .pipe(gulp.dest(buildFolder));
analytics: true, }
});
}); gulp.task("html.dev", () => {
return buildHtml("http://localhost:5005", {
gulp.task("html.standalone-dev", () => { analytics: false,
return buildHtml("https://localhost:5005", { integrity: false,
analytics: false, enableCachebust: false,
standalone: true, });
integrity: false, });
enableCachebust: false,
}); gulp.task("html.staging", () => {
}); return buildHtml("https://api-staging.shapez.io", {
analytics: true,
gulp.task("html.standalone-beta", () => { });
return buildHtml("https://api-staging.shapez.io", { });
analytics: false,
standalone: true, gulp.task("html.prod", () => {
enableCachebust: false, return buildHtml("https://analytics.shapez.io", {
}); analytics: true,
}); });
});
gulp.task("html.standalone-prod", () => {
return buildHtml("https://analytics.shapez.io", { gulp.task("html.standalone-dev", () => {
analytics: false, return buildHtml("https://localhost:5005", {
standalone: true, analytics: false,
enableCachebust: false, standalone: true,
}); integrity: false,
}); enableCachebust: false,
} });
});
module.exports = {
gulptasksHTML, gulp.task("html.standalone-beta", () => {
}; return buildHtml("https://api-staging.shapez.io", {
analytics: false,
standalone: true,
enableCachebust: false,
});
});
gulp.task("html.standalone-prod", () => {
return buildHtml("https://analytics.shapez.io", {
analytics: false,
standalone: true,
enableCachebust: false,
});
});
}
module.exports = {
gulptasksHTML,
};

View File

@ -1,110 +1,111 @@
{ {
"name": "builder", "name": "builder",
"version": "1.0.0", "version": "1.0.0",
"description": "builder", "description": "builder",
"private": true, "private": true,
"scripts": { "scripts": {
"gulp": "gulp" "gulp": "gulp"
}, },
"author": "tobspr", "author": "tobspr",
"license": "private", "license": "private",
"dependencies": { "dependencies": {
"@babel/core": "^7.9.0", "@babel/core": "^7.9.0",
"@babel/plugin-transform-block-scoping": "^7.4.4", "@babel/plugin-transform-block-scoping": "^7.4.4",
"@babel/plugin-transform-classes": "^7.5.5", "@babel/plugin-transform-classes": "^7.5.5",
"@babel/preset-env": "^7.5.4", "@babel/preset-env": "^7.5.4",
"@types/cordova": "^0.0.34", "@types/cordova": "^0.0.34",
"@types/filesystem": "^0.0.29", "@types/filesystem": "^0.0.29",
"@types/node": "^12.7.5", "@types/node": "^12.7.5",
"ajv": "^6.10.2", "ajv": "^6.10.2",
"audiosprite": "^0.7.2", "audiosprite": "^0.7.2",
"babel-loader": "^8.1.0", "babel-loader": "^8.1.0",
"browser-sync": "^2.26.10", "browser-sync": "^2.26.10",
"circular-dependency-plugin": "^5.0.2", "circular-dependency-plugin": "^5.0.2",
"circular-json": "^0.5.9", "circular-json": "^0.5.9",
"clipboard-copy": "^3.1.0", "clipboard-copy": "^3.1.0",
"colors": "^1.3.3", "colors": "^1.3.3",
"core-js": "3", "core-js": "3",
"crypto": "^1.0.1", "crypto": "^1.0.1",
"cssnano-preset-advanced": "^4.0.7", "cssnano-preset-advanced": "^4.0.7",
"delete-empty": "^3.0.0", "delete-empty": "^3.0.0",
"email-validator": "^2.0.4", "email-validator": "^2.0.4",
"eslint": "^5.9.0", "eslint": "^5.9.0",
"fastdom": "^1.0.9", "fastdom": "^1.0.9",
"flatted": "^2.0.1", "flatted": "^2.0.1",
"fs-extra": "^8.1.0", "fs-extra": "^8.1.0",
"gulp-audiosprite": "^1.1.0", "gulp-audiosprite": "^1.1.0",
"howler": "^2.1.2", "howler": "^2.1.2",
"html-loader": "^0.5.5", "html-loader": "^0.5.5",
"ignore-loader": "^0.1.2", "ignore-loader": "^0.1.2",
"lz-string": "^1.4.4", "lz-string": "^1.4.4",
"markdown-loader": "^5.1.0", "markdown-loader": "^5.1.0",
"node-sri": "^1.1.1", "node-sri": "^1.1.1",
"phonegap-plugin-mobile-accessibility": "^1.0.5", "phonegap-plugin-mobile-accessibility": "^1.0.5",
"promise-polyfill": "^8.1.0", "promise-polyfill": "^8.1.0",
"query-string": "^6.8.1", "query-string": "^6.8.1",
"rusha": "^0.8.13", "rusha": "^0.8.13",
"serialize-error": "^3.0.0", "serialize-error": "^3.0.0",
"strictdom": "^1.0.1", "strictdom": "^1.0.1",
"string-replace-webpack-plugin": "^0.1.3", "string-replace-webpack-plugin": "^0.1.3",
"terser-webpack-plugin": "^1.1.0", "terser-webpack-plugin": "^1.1.0",
"through2": "^3.0.1", "through2": "^3.0.1",
"uglify-template-string-loader": "^1.1.0", "uglify-template-string-loader": "^1.1.0",
"unused-files-webpack-plugin": "^3.4.0", "unused-files-webpack-plugin": "^3.4.0",
"webpack": "^4.43.0", "webpack": "^4.43.0",
"webpack-cli": "^3.1.0", "webpack-cli": "^3.1.0",
"webpack-deep-scope-plugin": "^1.6.0", "webpack-deep-scope-plugin": "^1.6.0",
"webpack-plugin-replace": "^1.1.1", "webpack-plugin-replace": "^1.1.1",
"webpack-strip-block": "^0.2.0", "webpack-strip-block": "^0.2.0",
"whatwg-fetch": "^3.0.0", "whatwg-fetch": "^3.0.0",
"worker-loader": "^2.0.0" "worker-loader": "^2.0.0"
}, },
"devDependencies": { "devDependencies": {
"autoprefixer": "^9.4.3", "autoprefixer": "^9.4.3",
"babel-plugin-closure-elimination": "^1.3.0", "babel-plugin-closure-elimination": "^1.3.0",
"babel-plugin-console-source": "^2.0.2", "babel-plugin-console-source": "^2.0.2",
"babel-plugin-danger-remove-unused-import": "^1.1.2", "babel-plugin-danger-remove-unused-import": "^1.1.2",
"css-mqpacker": "^7.0.0", "css-mqpacker": "^7.0.0",
"cssnano": "^4.1.10", "cssnano": "^4.1.10",
"electron-packager": "^14.0.6", "postcss-critical-split": "^2.5.3",
"faster.js": "^1.1.0", "electron-packager": "^14.0.6",
"glob": "^7.1.3", "faster.js": "^1.1.0",
"gulp": "^4.0.2", "glob": "^7.1.3",
"gulp-cache": "^1.1.3", "gulp": "^4.0.2",
"gulp-cached": "^1.1.1", "gulp-cache": "^1.1.3",
"gulp-clean": "^0.4.0", "gulp-cached": "^1.1.1",
"gulp-dom": "^1.0.0", "gulp-clean": "^0.4.0",
"gulp-flatten": "^0.4.0", "gulp-dom": "^1.0.0",
"gulp-fluent-ffmpeg": "^2.0.0", "gulp-flatten": "^0.4.0",
"gulp-html-beautify": "^1.0.1", "gulp-fluent-ffmpeg": "^2.0.0",
"gulp-htmlmin": "^5.0.1", "gulp-html-beautify": "^1.0.1",
"gulp-if": "^3.0.0", "gulp-htmlmin": "^5.0.1",
"gulp-imagemin": "^7.1.0", "gulp-if": "^3.0.0",
"gulp-load-plugins": "^2.0.3", "gulp-imagemin": "^7.1.0",
"gulp-phonegap-build": "^0.1.5", "gulp-load-plugins": "^2.0.3",
"gulp-plumber": "^1.2.1", "gulp-phonegap-build": "^0.1.5",
"gulp-pngquant": "^1.0.13", "gulp-plumber": "^1.2.1",
"gulp-postcss": "^8.0.0", "gulp-pngquant": "^1.0.13",
"gulp-rename": "^2.0.0", "gulp-postcss": "^8.0.0",
"gulp-sass": "^4.1.0", "gulp-rename": "^2.0.0",
"gulp-sass-lint": "^1.4.0", "gulp-sass": "^4.1.0",
"gulp-sftp": "git+https://git@github.com/webksde/gulp-sftp", "gulp-sass-lint": "^1.4.0",
"gulp-terser": "^1.2.0", "gulp-sftp": "git+https://git@github.com/webksde/gulp-sftp",
"gulp-webserver": "^0.9.1", "gulp-terser": "^1.2.0",
"gulp-yaml": "^2.0.4", "gulp-webserver": "^0.9.1",
"imagemin-gifsicle": "^7.0.0", "gulp-yaml": "^2.0.4",
"imagemin-jpegtran": "^7.0.0", "imagemin-gifsicle": "^7.0.0",
"imagemin-pngquant": "^9.0.0", "imagemin-jpegtran": "^7.0.0",
"jimp": "^0.6.1", "imagemin-pngquant": "^9.0.0",
"js-yaml": "^3.13.1", "jimp": "^0.6.1",
"postcss-assets": "^5.0.0", "js-yaml": "^3.13.1",
"postcss-preset-env": "^6.5.0", "postcss-assets": "^5.0.0",
"postcss-round-subpixels": "^1.2.0", "postcss-preset-env": "^6.5.0",
"postcss-unprefix": "^2.1.3", "postcss-round-subpixels": "^1.2.0",
"sass-unused": "^0.3.0", "postcss-unprefix": "^2.1.3",
"strip-json-comments": "^3.0.1", "sass-unused": "^0.3.0",
"trim": "^0.0.1", "strip-json-comments": "^3.0.1",
"webpack-stream": "^5.2.1", "trim": "^0.0.1",
"yaml-loader": "^0.6.0" "webpack-stream": "^5.2.1",
} "yaml-loader": "^0.6.0"
} }
}

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.0 KiB

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 242 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 35 KiB

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 40 KiB

View File

@ -2,7 +2,7 @@
"sprites/belt/built/forward_0.png": "sprites/belt/built/forward_0.png":
{ {
"frame": {"x":1867,"y":593,"w":116,"h":144}, "frame": {"x":1239,"y":1197,"w":116,"h":144},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":14,"y":0,"w":116,"h":144}, "spriteSourceSize": {"x":14,"y":0,"w":116,"h":144},
@ -10,7 +10,7 @@
}, },
"sprites/belt/built/forward_1.png": "sprites/belt/built/forward_1.png":
{ {
"frame": {"x":1241,"y":1197,"w":116,"h":144}, "frame": {"x":1361,"y":1195,"w":116,"h":144},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":14,"y":0,"w":116,"h":144}, "spriteSourceSize": {"x":14,"y":0,"w":116,"h":144},
@ -18,7 +18,7 @@
}, },
"sprites/belt/built/forward_2.png": "sprites/belt/built/forward_2.png":
{ {
"frame": {"x":1558,"y":753,"w":116,"h":144}, "frame": {"x":1436,"y":753,"w":116,"h":144},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":14,"y":0,"w":116,"h":144}, "spriteSourceSize": {"x":14,"y":0,"w":116,"h":144},
@ -26,7 +26,7 @@
}, },
"sprites/belt/built/forward_3.png": "sprites/belt/built/forward_3.png":
{ {
"frame": {"x":1555,"y":903,"w":116,"h":144}, "frame": {"x":1433,"y":903,"w":116,"h":144},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":14,"y":0,"w":116,"h":144}, "spriteSourceSize": {"x":14,"y":0,"w":116,"h":144},
@ -34,7 +34,7 @@
}, },
"sprites/belt/built/forward_4.png": "sprites/belt/built/forward_4.png":
{ {
"frame": {"x":1562,"y":1053,"w":116,"h":144}, "frame": {"x":1483,"y":1195,"w":116,"h":144},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":14,"y":0,"w":116,"h":144}, "spriteSourceSize": {"x":14,"y":0,"w":116,"h":144},
@ -42,7 +42,7 @@
}, },
"sprites/belt/built/forward_5.png": "sprites/belt/built/forward_5.png":
{ {
"frame": {"x":1680,"y":753,"w":116,"h":144}, "frame": {"x":1501,"y":1345,"w":116,"h":144},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":14,"y":0,"w":116,"h":144}, "spriteSourceSize": {"x":14,"y":0,"w":116,"h":144},
@ -50,7 +50,7 @@
}, },
"sprites/belt/built/forward_6.png": "sprites/belt/built/forward_6.png":
{ {
"frame": {"x":1677,"y":903,"w":116,"h":144}, "frame": {"x":1510,"y":1495,"w":116,"h":144},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":14,"y":0,"w":116,"h":144}, "spriteSourceSize": {"x":14,"y":0,"w":116,"h":144},
@ -58,7 +58,7 @@
}, },
"sprites/belt/built/forward_7.png": "sprites/belt/built/forward_7.png":
{ {
"frame": {"x":1684,"y":1053,"w":116,"h":144}, "frame": {"x":1555,"y":903,"w":116,"h":144},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":14,"y":0,"w":116,"h":144}, "spriteSourceSize": {"x":14,"y":0,"w":116,"h":144},
@ -66,7 +66,7 @@
}, },
"sprites/belt/built/forward_8.png": "sprites/belt/built/forward_8.png":
{ {
"frame": {"x":1802,"y":743,"w":116,"h":144}, "frame": {"x":1696,"y":1053,"w":116,"h":144},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":14,"y":0,"w":116,"h":144}, "spriteSourceSize": {"x":14,"y":0,"w":116,"h":144},
@ -74,7 +74,7 @@
}, },
"sprites/belt/built/forward_9.png": "sprites/belt/built/forward_9.png":
{ {
"frame": {"x":1924,"y":743,"w":116,"h":144}, "frame": {"x":1623,"y":1339,"w":116,"h":144},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":14,"y":0,"w":116,"h":144}, "spriteSourceSize": {"x":14,"y":0,"w":116,"h":144},
@ -82,7 +82,7 @@
}, },
"sprites/belt/built/forward_10.png": "sprites/belt/built/forward_10.png":
{ {
"frame": {"x":1363,"y":1195,"w":116,"h":144}, "frame": {"x":1379,"y":1345,"w":116,"h":144},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":14,"y":0,"w":116,"h":144}, "spriteSourceSize": {"x":14,"y":0,"w":116,"h":144},
@ -90,7 +90,7 @@
}, },
"sprites/belt/built/forward_11.png": "sprites/belt/built/forward_11.png":
{ {
"frame": {"x":845,"y":1548,"w":116,"h":144}, "frame": {"x":706,"y":1711,"w":116,"h":144},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":14,"y":0,"w":116,"h":144}, "spriteSourceSize": {"x":14,"y":0,"w":116,"h":144},
@ -98,7 +98,7 @@
}, },
"sprites/belt/built/forward_12.png": "sprites/belt/built/forward_12.png":
{ {
"frame": {"x":1436,"y":753,"w":116,"h":144}, "frame": {"x":1861,"y":593,"w":116,"h":144},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":14,"y":0,"w":116,"h":144}, "spriteSourceSize": {"x":14,"y":0,"w":116,"h":144},
@ -106,7 +106,7 @@
}, },
"sprites/belt/built/forward_13.png": "sprites/belt/built/forward_13.png":
{ {
"frame": {"x":1433,"y":903,"w":116,"h":144}, "frame": {"x":1875,"y":743,"w":116,"h":144},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":14,"y":0,"w":116,"h":144}, "spriteSourceSize": {"x":14,"y":0,"w":116,"h":144},
@ -114,7 +114,7 @@
}, },
"sprites/belt/built/left_0.png": "sprites/belt/built/left_0.png":
{ {
"frame": {"x":569,"y":1845,"w":130,"h":130}, "frame": {"x":1238,"y":1464,"w":130,"h":130},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":0,"y":14,"w":130,"h":130}, "spriteSourceSize": {"x":0,"y":14,"w":130,"h":130},
@ -122,7 +122,7 @@
}, },
"sprites/belt/built/left_1.png": "sprites/belt/built/left_1.png":
{ {
"frame": {"x":1426,"y":1053,"w":130,"h":130}, "frame": {"x":1374,"y":1495,"w":130,"h":130},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":0,"y":14,"w":130,"h":130}, "spriteSourceSize": {"x":0,"y":14,"w":130,"h":130},
@ -130,7 +130,7 @@
}, },
"sprites/belt/built/left_2.png": "sprites/belt/built/left_2.png":
{ {
"frame": {"x":1893,"y":1189,"w":130,"h":130}, "frame": {"x":1741,"y":1203,"w":130,"h":130},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":0,"y":14,"w":130,"h":130}, "spriteSourceSize": {"x":0,"y":14,"w":130,"h":130},
@ -138,7 +138,7 @@
}, },
"sprites/belt/built/left_3.png": "sprites/belt/built/left_3.png":
{ {
"frame": {"x":1241,"y":1347,"w":130,"h":130}, "frame": {"x":1745,"y":1339,"w":130,"h":130},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":0,"y":14,"w":130,"h":130}, "spriteSourceSize": {"x":0,"y":14,"w":130,"h":130},
@ -146,7 +146,7 @@
}, },
"sprites/belt/built/left_4.png": "sprites/belt/built/left_4.png":
{ {
"frame": {"x":1377,"y":1345,"w":130,"h":130}, "frame": {"x":1754,"y":1475,"w":130,"h":130},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":0,"y":14,"w":130,"h":130}, "spriteSourceSize": {"x":0,"y":14,"w":130,"h":130},
@ -154,7 +154,7 @@
}, },
"sprites/belt/built/left_5.png": "sprites/belt/built/left_5.png":
{ {
"frame": {"x":1513,"y":1339,"w":130,"h":130}, "frame": {"x":1813,"y":917,"w":130,"h":130},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":0,"y":14,"w":130,"h":130}, "spriteSourceSize": {"x":0,"y":14,"w":130,"h":130},
@ -162,7 +162,7 @@
}, },
"sprites/belt/built/left_6.png": "sprites/belt/built/left_6.png":
{ {
"frame": {"x":1649,"y":1339,"w":130,"h":130}, "frame": {"x":1818,"y":1053,"w":130,"h":130},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":0,"y":14,"w":130,"h":130}, "spriteSourceSize": {"x":0,"y":14,"w":130,"h":130},
@ -170,7 +170,7 @@
}, },
"sprites/belt/built/left_7.png": "sprites/belt/built/left_7.png":
{ {
"frame": {"x":1785,"y":1339,"w":130,"h":130}, "frame": {"x":1877,"y":1189,"w":130,"h":130},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":0,"y":14,"w":130,"h":130}, "spriteSourceSize": {"x":0,"y":14,"w":130,"h":130},
@ -178,7 +178,7 @@
}, },
"sprites/belt/built/left_8.png": "sprites/belt/built/left_8.png":
{ {
"frame": {"x":1377,"y":1481,"w":130,"h":130}, "frame": {"x":1881,"y":1325,"w":130,"h":130},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":0,"y":14,"w":130,"h":130}, "spriteSourceSize": {"x":0,"y":14,"w":130,"h":130},
@ -186,7 +186,7 @@
}, },
"sprites/belt/built/left_9.png": "sprites/belt/built/left_9.png":
{ {
"frame": {"x":1802,"y":1475,"w":130,"h":130}, "frame": {"x":1890,"y":1461,"w":130,"h":130},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":0,"y":14,"w":130,"h":130}, "spriteSourceSize": {"x":0,"y":14,"w":130,"h":130},
@ -194,7 +194,7 @@
}, },
"sprites/belt/built/left_10.png": "sprites/belt/built/left_10.png":
{ {
"frame": {"x":1485,"y":1203,"w":130,"h":130}, "frame": {"x":939,"y":1712,"w":130,"h":130},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":0,"y":14,"w":130,"h":130}, "spriteSourceSize": {"x":0,"y":14,"w":130,"h":130},
@ -202,7 +202,7 @@
}, },
"sprites/belt/built/left_11.png": "sprites/belt/built/left_11.png":
{ {
"frame": {"x":1621,"y":1203,"w":130,"h":130}, "frame": {"x":1677,"y":917,"w":130,"h":130},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":0,"y":14,"w":130,"h":130}, "spriteSourceSize": {"x":0,"y":14,"w":130,"h":130},
@ -210,7 +210,7 @@
}, },
"sprites/belt/built/left_12.png": "sprites/belt/built/left_12.png":
{ {
"frame": {"x":1757,"y":1203,"w":130,"h":130}, "frame": {"x":1560,"y":1053,"w":130,"h":130},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":0,"y":14,"w":130,"h":130}, "spriteSourceSize": {"x":0,"y":14,"w":130,"h":130},
@ -218,7 +218,7 @@
}, },
"sprites/belt/built/left_13.png": "sprites/belt/built/left_13.png":
{ {
"frame": {"x":1806,"y":1053,"w":130,"h":130}, "frame": {"x":1605,"y":1203,"w":130,"h":130},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":0,"y":14,"w":130,"h":130}, "spriteSourceSize": {"x":0,"y":14,"w":130,"h":130},
@ -226,7 +226,7 @@
}, },
"sprites/belt/built/right_0.png": "sprites/belt/built/right_0.png":
{ {
"frame": {"x":1799,"y":1611,"w":130,"h":130}, "frame": {"x":1754,"y":1611,"w":130,"h":130},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":14,"y":14,"w":130,"h":130}, "spriteSourceSize": {"x":14,"y":14,"w":130,"h":130},
@ -234,7 +234,7 @@
}, },
"sprites/belt/built/right_1.png": "sprites/belt/built/right_1.png":
{ {
"frame": {"x":294,"y":1885,"w":130,"h":130}, "frame": {"x":1890,"y":1597,"w":130,"h":130},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":14,"y":14,"w":130,"h":130}, "spriteSourceSize": {"x":14,"y":14,"w":130,"h":130},
@ -242,7 +242,7 @@
}, },
"sprites/belt/built/right_2.png": "sprites/belt/built/right_2.png":
{ {
"frame": {"x":1239,"y":1483,"w":130,"h":130}, "frame": {"x":842,"y":1848,"w":130,"h":130},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":14,"y":14,"w":130,"h":130}, "spriteSourceSize": {"x":14,"y":14,"w":130,"h":130},
@ -250,7 +250,7 @@
}, },
"sprites/belt/built/right_3.png": "sprites/belt/built/right_3.png":
{ {
"frame": {"x":997,"y":1785,"w":130,"h":130}, "frame": {"x":978,"y":1848,"w":130,"h":130},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":14,"y":14,"w":130,"h":130}, "spriteSourceSize": {"x":14,"y":14,"w":130,"h":130},
@ -258,7 +258,7 @@
}, },
"sprites/belt/built/right_4.png": "sprites/belt/built/right_4.png":
{ {
"frame": {"x":1375,"y":1617,"w":130,"h":130}, "frame": {"x":1114,"y":1848,"w":130,"h":130},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":14,"y":14,"w":130,"h":130}, "spriteSourceSize": {"x":14,"y":14,"w":130,"h":130},
@ -266,7 +266,7 @@
}, },
"sprites/belt/built/right_5.png": "sprites/belt/built/right_5.png":
{ {
"frame": {"x":1511,"y":1710,"w":130,"h":130}, "frame": {"x":271,"y":1885,"w":130,"h":130},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":14,"y":14,"w":130,"h":130}, "spriteSourceSize": {"x":14,"y":14,"w":130,"h":130},
@ -274,7 +274,7 @@
}, },
"sprites/belt/built/right_6.png": "sprites/belt/built/right_6.png":
{ {
"frame": {"x":1647,"y":1710,"w":130,"h":130}, "frame": {"x":407,"y":1885,"w":130,"h":130},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":14,"y":14,"w":130,"h":130}, "spriteSourceSize": {"x":14,"y":14,"w":130,"h":130},
@ -282,7 +282,7 @@
}, },
"sprites/belt/built/right_7.png": "sprites/belt/built/right_7.png":
{ {
"frame": {"x":1783,"y":1747,"w":130,"h":130}, "frame": {"x":1211,"y":1600,"w":130,"h":130},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":14,"y":14,"w":130,"h":130}, "spriteSourceSize": {"x":14,"y":14,"w":130,"h":130},
@ -290,7 +290,7 @@
}, },
"sprites/belt/built/right_8.png": "sprites/belt/built/right_8.png":
{ {
"frame": {"x":1111,"y":1635,"w":130,"h":130}, "frame": {"x":1347,"y":1631,"w":130,"h":130},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":14,"y":14,"w":130,"h":130}, "spriteSourceSize": {"x":14,"y":14,"w":130,"h":130},
@ -298,7 +298,7 @@
}, },
"sprites/belt/built/right_9.png": "sprites/belt/built/right_9.png":
{ {
"frame": {"x":1133,"y":1771,"w":130,"h":130}, "frame": {"x":1483,"y":1645,"w":130,"h":130},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":14,"y":14,"w":130,"h":130}, "spriteSourceSize": {"x":14,"y":14,"w":130,"h":130},
@ -306,7 +306,7 @@
}, },
"sprites/belt/built/right_10.png": "sprites/belt/built/right_10.png":
{ {
"frame": {"x":430,"y":1885,"w":130,"h":130}, "frame": {"x":1075,"y":1712,"w":130,"h":130},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":14,"y":14,"w":130,"h":130}, "spriteSourceSize": {"x":14,"y":14,"w":130,"h":130},
@ -314,7 +314,7 @@
}, },
"sprites/belt/built/right_11.png": "sprites/belt/built/right_11.png":
{ {
"frame": {"x":967,"y":1513,"w":130,"h":130}, "frame": {"x":1890,"y":1733,"w":130,"h":130},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":14,"y":14,"w":130,"h":130}, "spriteSourceSize": {"x":14,"y":14,"w":130,"h":130},
@ -322,7 +322,7 @@
}, },
"sprites/belt/built/right_12.png": "sprites/belt/built/right_12.png":
{ {
"frame": {"x":975,"y":1649,"w":130,"h":130}, "frame": {"x":570,"y":1878,"w":130,"h":130},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":14,"y":14,"w":130,"h":130}, "spriteSourceSize": {"x":14,"y":14,"w":130,"h":130},
@ -330,7 +330,7 @@
}, },
"sprites/belt/built/right_13.png": "sprites/belt/built/right_13.png":
{ {
"frame": {"x":1103,"y":1444,"w":130,"h":130}, "frame": {"x":706,"y":1861,"w":130,"h":130},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":14,"y":14,"w":130,"h":130}, "spriteSourceSize": {"x":14,"y":14,"w":130,"h":130},
@ -378,7 +378,7 @@
}, },
"sprites/blueprints/belt_left.png": "sprites/blueprints/belt_left.png":
{ {
"frame": {"x":1168,"y":1907,"w":130,"h":130}, "frame": {"x":1250,"y":1838,"w":130,"h":130},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":0,"y":14,"w":130,"h":130}, "spriteSourceSize": {"x":0,"y":14,"w":130,"h":130},
@ -386,7 +386,7 @@
}, },
"sprites/blueprints/belt_right.png": "sprites/blueprints/belt_right.png":
{ {
"frame": {"x":1269,"y":1753,"w":130,"h":130}, "frame": {"x":1726,"y":1747,"w":130,"h":130},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":14,"y":14,"w":130,"h":130}, "spriteSourceSize": {"x":14,"y":14,"w":130,"h":130},
@ -394,7 +394,7 @@
}, },
"sprites/blueprints/belt_top.png": "sprites/blueprints/belt_top.png":
{ {
"frame": {"x":1799,"y":903,"w":116,"h":144}, "frame": {"x":1632,"y":1489,"w":116,"h":144},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":14,"y":0,"w":116,"h":144}, "spriteSourceSize": {"x":14,"y":0,"w":116,"h":144},
@ -402,7 +402,7 @@
}, },
"sprites/blueprints/constant_signal.png": "sprites/blueprints/constant_signal.png":
{ {
"frame": {"x":1921,"y":1325,"w":105,"h":127}, "frame": {"x":828,"y":1709,"w":105,"h":127},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":20,"y":0,"w":105,"h":127}, "spriteSourceSize": {"x":20,"y":0,"w":105,"h":127},
@ -426,7 +426,7 @@
}, },
"sprites/blueprints/display.png": "sprites/blueprints/display.png":
{ {
"frame": {"x":841,"y":1698,"w":128,"h":136}, "frame": {"x":1426,"y":1053,"w":128,"h":136},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":8,"y":8,"w":128,"h":136}, "spriteSourceSize": {"x":8,"y":8,"w":128,"h":136},
@ -442,10 +442,10 @@
}, },
"sprites/blueprints/lever.png": "sprites/blueprints/lever.png":
{ {
"frame": {"x":1921,"y":893,"w":111,"h":129}, "frame": {"x":1719,"y":453,"w":100,"h":116},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":17,"y":4,"w":111,"h":129}, "spriteSourceSize": {"x":22,"y":9,"w":100,"h":116},
"sourceSize": {"w":144,"h":144} "sourceSize": {"w":144,"h":144}
}, },
"sprites/blueprints/logic_gate-not.png": "sprites/blueprints/logic_gate-not.png":
@ -482,7 +482,7 @@
}, },
"sprites/blueprints/logic_gate.png": "sprites/blueprints/logic_gate.png":
{ {
"frame": {"x":1821,"y":454,"w":144,"h":133}, "frame": {"x":1825,"y":454,"w":144,"h":133},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":0,"y":0,"w":144,"h":133}, "spriteSourceSize": {"x":0,"y":0,"w":144,"h":133},
@ -498,7 +498,7 @@
}, },
"sprites/blueprints/miner.png": "sprites/blueprints/miner.png":
{ {
"frame": {"x":1725,"y":593,"w":136,"h":143}, "frame": {"x":951,"y":1328,"w":136,"h":143},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":5,"y":0,"w":136,"h":143}, "spriteSourceSize": {"x":5,"y":0,"w":136,"h":143},
@ -562,10 +562,10 @@
}, },
"sprites/blueprints/rotater-rotate180.png": "sprites/blueprints/rotater-rotate180.png":
{ {
"frame": {"x":271,"y":1735,"w":142,"h":144}, "frame": {"x":271,"y":1735,"w":143,"h":144},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":0,"y":0,"w":142,"h":144}, "spriteSourceSize": {"x":1,"y":0,"w":143,"h":144},
"sourceSize": {"w":144,"h":144} "sourceSize": {"w":144,"h":144}
}, },
"sprites/blueprints/rotater.png": "sprites/blueprints/rotater.png":
@ -584,7 +584,7 @@
"spriteSourceSize": {"x":13,"y":0,"w":261,"h":144}, "spriteSourceSize": {"x":13,"y":0,"w":261,"h":144},
"sourceSize": {"w":288,"h":144} "sourceSize": {"w":288,"h":144}
}, },
"sprites/blueprints/trash-storage.png": "sprites/blueprints/storage.png":
{ {
"frame": {"x":4,"y":1001,"w":250,"h":288}, "frame": {"x":4,"y":1001,"w":250,"h":288},
"rotated": false, "rotated": false,
@ -602,7 +602,7 @@
}, },
"sprites/blueprints/underground_belt_entry-tier2.png": "sprites/blueprints/underground_belt_entry-tier2.png":
{ {
"frame": {"x":954,"y":1188,"w":138,"h":125}, "frame": {"x":806,"y":1461,"w":138,"h":125},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":4,"y":19,"w":138,"h":125}, "spriteSourceSize": {"x":4,"y":19,"w":138,"h":125},
@ -610,7 +610,7 @@
}, },
"sprites/blueprints/underground_belt_entry.png": "sprites/blueprints/underground_belt_entry.png":
{ {
"frame": {"x":954,"y":1319,"w":138,"h":112}, "frame": {"x":950,"y":1477,"w":138,"h":112},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":4,"y":32,"w":138,"h":112}, "spriteSourceSize": {"x":4,"y":32,"w":138,"h":112},
@ -618,7 +618,7 @@
}, },
"sprites/blueprints/underground_belt_exit-tier2.png": "sprites/blueprints/underground_belt_exit-tier2.png":
{ {
"frame": {"x":1513,"y":1475,"w":139,"h":112}, "frame": {"x":661,"y":1460,"w":139,"h":112},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":4,"y":0,"w":139,"h":112}, "spriteSourceSize": {"x":4,"y":0,"w":139,"h":112},
@ -626,7 +626,7 @@
}, },
"sprites/blueprints/underground_belt_exit.png": "sprites/blueprints/underground_belt_exit.png":
{ {
"frame": {"x":1658,"y":1475,"w":138,"h":112}, "frame": {"x":1094,"y":1475,"w":138,"h":112},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":4,"y":0,"w":138,"h":112}, "spriteSourceSize": {"x":4,"y":0,"w":138,"h":112},
@ -666,7 +666,7 @@
}, },
"sprites/blueprints/virtual_processor-stacker.png": "sprites/blueprints/virtual_processor-stacker.png":
{ {
"frame": {"x":569,"y":1695,"w":130,"h":144}, "frame": {"x":560,"y":1578,"w":130,"h":144},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":14,"y":0,"w":130,"h":144}, "spriteSourceSize": {"x":14,"y":0,"w":130,"h":144},
@ -706,7 +706,7 @@
}, },
"sprites/blueprints/wire-turn.png": "sprites/blueprints/wire-turn.png":
{ {
"frame": {"x":557,"y":1456,"w":82,"h":82}, "frame": {"x":1386,"y":1767,"w":82,"h":82},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":62,"y":62,"w":82,"h":82}, "spriteSourceSize": {"x":62,"y":62,"w":82,"h":82},
@ -714,7 +714,7 @@
}, },
"sprites/blueprints/wire.png": "sprites/blueprints/wire.png":
{ {
"frame": {"x":1980,"y":1028,"w":20,"h":144}, "frame": {"x":1954,"y":1033,"w":20,"h":144},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":62,"y":0,"w":20,"h":144}, "spriteSourceSize": {"x":62,"y":0,"w":20,"h":144},
@ -778,7 +778,7 @@
}, },
"sprites/buildings/belt_left.png": "sprites/buildings/belt_left.png":
{ {
"frame": {"x":569,"y":1845,"w":130,"h":130}, "frame": {"x":1238,"y":1464,"w":130,"h":130},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":0,"y":14,"w":130,"h":130}, "spriteSourceSize": {"x":0,"y":14,"w":130,"h":130},
@ -786,7 +786,7 @@
}, },
"sprites/buildings/belt_right.png": "sprites/buildings/belt_right.png":
{ {
"frame": {"x":1799,"y":1611,"w":130,"h":130}, "frame": {"x":1754,"y":1611,"w":130,"h":130},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":14,"y":14,"w":130,"h":130}, "spriteSourceSize": {"x":14,"y":14,"w":130,"h":130},
@ -794,7 +794,7 @@
}, },
"sprites/buildings/belt_top.png": "sprites/buildings/belt_top.png":
{ {
"frame": {"x":1867,"y":593,"w":116,"h":144}, "frame": {"x":1239,"y":1197,"w":116,"h":144},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":14,"y":0,"w":116,"h":144}, "spriteSourceSize": {"x":14,"y":0,"w":116,"h":144},
@ -802,7 +802,7 @@
}, },
"sprites/buildings/constant_signal.png": "sprites/buildings/constant_signal.png":
{ {
"frame": {"x":1938,"y":1458,"w":104,"h":127}, "frame": {"x":696,"y":1578,"w":104,"h":127},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":20,"y":0,"w":104,"h":127}, "spriteSourceSize": {"x":20,"y":0,"w":104,"h":127},
@ -826,7 +826,7 @@
}, },
"sprites/buildings/display.png": "sprites/buildings/display.png":
{ {
"frame": {"x":841,"y":1840,"w":126,"h":135}, "frame": {"x":1558,"y":753,"w":126,"h":135},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":9,"y":9,"w":126,"h":135}, "spriteSourceSize": {"x":9,"y":9,"w":126,"h":135},
@ -850,10 +850,10 @@
}, },
"sprites/buildings/lever.png": "sprites/buildings/lever.png":
{ {
"frame": {"x":1935,"y":1611,"w":109,"h":127}, "frame": {"x":557,"y":1456,"w":98,"h":114},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":18,"y":5,"w":109,"h":127}, "spriteSourceSize": {"x":23,"y":10,"w":98,"h":114},
"sourceSize": {"w":144,"h":144} "sourceSize": {"w":144,"h":144}
}, },
"sprites/buildings/logic_gate-not.png": "sprites/buildings/logic_gate-not.png":
@ -906,7 +906,7 @@
}, },
"sprites/buildings/miner.png": "sprites/buildings/miner.png":
{ {
"frame": {"x":560,"y":1547,"w":136,"h":142}, "frame": {"x":1097,"y":1197,"w":136,"h":142},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":5,"y":0,"w":136,"h":142}, "spriteSourceSize": {"x":5,"y":0,"w":136,"h":142},
@ -973,7 +973,7 @@
"frame": {"x":1286,"y":902,"w":141,"h":143}, "frame": {"x":1286,"y":902,"w":141,"h":143},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":1,"y":0,"w":141,"h":143}, "spriteSourceSize": {"x":2,"y":0,"w":141,"h":143},
"sourceSize": {"w":144,"h":144} "sourceSize": {"w":144,"h":144}
}, },
"sprites/buildings/rotater.png": "sprites/buildings/rotater.png":
@ -992,7 +992,7 @@
"spriteSourceSize": {"x":14,"y":0,"w":260,"h":143}, "spriteSourceSize": {"x":14,"y":0,"w":260,"h":143},
"sourceSize": {"w":288,"h":144} "sourceSize": {"w":288,"h":144}
}, },
"sprites/buildings/trash-storage.png": "sprites/buildings/storage.png":
{ {
"frame": {"x":4,"y":1295,"w":248,"h":288}, "frame": {"x":4,"y":1295,"w":248,"h":288},
"rotated": false, "rotated": false,
@ -1010,7 +1010,7 @@
}, },
"sprites/buildings/underground_belt_entry-tier2.png": "sprites/buildings/underground_belt_entry-tier2.png":
{ {
"frame": {"x":1098,"y":1197,"w":137,"h":124}, "frame": {"x":1093,"y":1345,"w":137,"h":124},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":5,"y":20,"w":137,"h":124}, "spriteSourceSize": {"x":5,"y":20,"w":137,"h":124},
@ -1018,7 +1018,7 @@
}, },
"sprites/buildings/underground_belt_entry.png": "sprites/buildings/underground_belt_entry.png":
{ {
"frame": {"x":1098,"y":1327,"w":137,"h":111}, "frame": {"x":1236,"y":1347,"w":137,"h":111},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":5,"y":33,"w":137,"h":111}, "spriteSourceSize": {"x":5,"y":33,"w":137,"h":111},
@ -1026,7 +1026,7 @@
}, },
"sprites/buildings/underground_belt_exit-tier2.png": "sprites/buildings/underground_belt_exit-tier2.png":
{ {
"frame": {"x":1513,"y":1593,"w":137,"h":111}, "frame": {"x":806,"y":1592,"w":137,"h":111},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":5,"y":0,"w":137,"h":111}, "spriteSourceSize": {"x":5,"y":0,"w":137,"h":111},
@ -1034,7 +1034,7 @@
}, },
"sprites/buildings/underground_belt_exit.png": "sprites/buildings/underground_belt_exit.png":
{ {
"frame": {"x":1656,"y":1593,"w":137,"h":111}, "frame": {"x":949,"y":1595,"w":137,"h":111},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":5,"y":0,"w":137,"h":111}, "spriteSourceSize": {"x":5,"y":0,"w":137,"h":111},
@ -1042,7 +1042,7 @@
}, },
"sprites/buildings/virtual_processor-analyzer.png": "sprites/buildings/virtual_processor-analyzer.png":
{ {
"frame": {"x":419,"y":1735,"w":144,"h":144}, "frame": {"x":420,"y":1735,"w":144,"h":144},
"rotated": false, "rotated": false,
"trimmed": false, "trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":144,"h":144}, "spriteSourceSize": {"x":0,"y":0,"w":144,"h":144},
@ -1050,7 +1050,7 @@
}, },
"sprites/buildings/virtual_processor-painter.png": "sprites/buildings/virtual_processor-painter.png":
{ {
"frame": {"x":705,"y":1688,"w":130,"h":144}, "frame": {"x":570,"y":1728,"w":130,"h":144},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":14,"y":0,"w":130,"h":144}, "spriteSourceSize": {"x":14,"y":0,"w":130,"h":144},
@ -1074,7 +1074,7 @@
}, },
"sprites/buildings/virtual_processor-stacker.png": "sprites/buildings/virtual_processor-stacker.png":
{ {
"frame": {"x":705,"y":1838,"w":130,"h":144}, "frame": {"x":1725,"y":593,"w":130,"h":144},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":14,"y":0,"w":130,"h":144}, "spriteSourceSize": {"x":14,"y":0,"w":130,"h":144},
@ -1114,7 +1114,7 @@
}, },
"sprites/buildings/wire-turn.png": "sprites/buildings/wire-turn.png":
{ {
"frame": {"x":997,"y":1921,"w":81,"h":81}, "frame": {"x":1386,"y":1855,"w":81,"h":81},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":63,"y":63,"w":81,"h":81}, "spriteSourceSize": {"x":63,"y":63,"w":81,"h":81},
@ -1122,7 +1122,7 @@
}, },
"sprites/buildings/wire.png": "sprites/buildings/wire.png":
{ {
"frame": {"x":2006,"y":1028,"w":18,"h":144}, "frame": {"x":2026,"y":116,"w":18,"h":144},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":63,"y":0,"w":18,"h":144}, "spriteSourceSize": {"x":63,"y":0,"w":18,"h":144},
@ -1130,7 +1130,7 @@
}, },
"sprites/buildings/wire_tunnel-coating.png": "sprites/buildings/wire_tunnel-coating.png":
{ {
"frame": {"x":1942,"y":1028,"w":32,"h":134}, "frame": {"x":1949,"y":893,"w":32,"h":134},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":56,"y":5,"w":32,"h":134}, "spriteSourceSize": {"x":56,"y":5,"w":32,"h":134},
@ -1138,7 +1138,7 @@
}, },
"sprites/buildings/wire_tunnel.png": "sprites/buildings/wire_tunnel.png":
{ {
"frame": {"x":702,"y":1548,"w":137,"h":134}, "frame": {"x":954,"y":1188,"w":137,"h":134},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":5,"y":5,"w":137,"h":134}, "spriteSourceSize": {"x":5,"y":5,"w":137,"h":134},
@ -1146,7 +1146,7 @@
}, },
"sprites/colors/blue.png": "sprites/colors/blue.png":
{ {
"frame": {"x":1103,"y":1580,"w":54,"h":49}, "frame": {"x":960,"y":1984,"w":54,"h":49},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":0,"y":4,"w":54,"h":49}, "spriteSourceSize": {"x":0,"y":4,"w":54,"h":49},
@ -1154,7 +1154,7 @@
}, },
"sprites/colors/cyan.png": "sprites/colors/cyan.png":
{ {
"frame": {"x":1163,"y":1580,"w":54,"h":49}, "frame": {"x":1020,"y":1984,"w":54,"h":49},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":0,"y":4,"w":54,"h":49}, "spriteSourceSize": {"x":0,"y":4,"w":54,"h":49},
@ -1162,7 +1162,7 @@
}, },
"sprites/colors/green.png": "sprites/colors/green.png":
{ {
"frame": {"x":705,"y":1988,"w":54,"h":49}, "frame": {"x":1080,"y":1984,"w":54,"h":49},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":0,"y":4,"w":54,"h":49}, "spriteSourceSize": {"x":0,"y":4,"w":54,"h":49},
@ -1170,7 +1170,7 @@
}, },
"sprites/colors/purple.png": "sprites/colors/purple.png":
{ {
"frame": {"x":765,"y":1988,"w":54,"h":49}, "frame": {"x":1140,"y":1984,"w":54,"h":49},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":0,"y":4,"w":54,"h":49}, "spriteSourceSize": {"x":0,"y":4,"w":54,"h":49},
@ -1178,7 +1178,7 @@
}, },
"sprites/colors/red.png": "sprites/colors/red.png":
{ {
"frame": {"x":1492,"y":1846,"w":54,"h":49}, "frame": {"x":1987,"y":928,"w":54,"h":49},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":0,"y":4,"w":54,"h":49}, "spriteSourceSize": {"x":0,"y":4,"w":54,"h":49},
@ -1186,7 +1186,7 @@
}, },
"sprites/colors/uncolored.png": "sprites/colors/uncolored.png":
{ {
"frame": {"x":1552,"y":1846,"w":54,"h":49}, "frame": {"x":1987,"y":983,"w":54,"h":49},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":0,"y":4,"w":54,"h":49}, "spriteSourceSize": {"x":0,"y":4,"w":54,"h":49},
@ -1194,7 +1194,7 @@
}, },
"sprites/colors/white.png": "sprites/colors/white.png":
{ {
"frame": {"x":1612,"y":1846,"w":54,"h":49}, "frame": {"x":1980,"y":1038,"w":54,"h":49},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":0,"y":4,"w":54,"h":49}, "spriteSourceSize": {"x":0,"y":4,"w":54,"h":49},
@ -1202,7 +1202,7 @@
}, },
"sprites/colors/yellow.png": "sprites/colors/yellow.png":
{ {
"frame": {"x":1672,"y":1846,"w":54,"h":49}, "frame": {"x":1980,"y":1093,"w":54,"h":49},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":0,"y":4,"w":54,"h":49}, "spriteSourceSize": {"x":0,"y":4,"w":54,"h":49},
@ -1210,7 +1210,7 @@
}, },
"sprites/debug/acceptor_slot.png": "sprites/debug/acceptor_slot.png":
{ {
"frame": {"x":1269,"y":1889,"w":12,"h":12}, "frame": {"x":1719,"y":575,"w":12,"h":12},
"rotated": false, "rotated": false,
"trimmed": false, "trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":12,"h":12}, "spriteSourceSize": {"x":0,"y":0,"w":12,"h":12},
@ -1218,7 +1218,7 @@
}, },
"sprites/debug/ejector_slot.png": "sprites/debug/ejector_slot.png":
{ {
"frame": {"x":1719,"y":555,"w":12,"h":12}, "frame": {"x":1737,"y":575,"w":12,"h":12},
"rotated": false, "rotated": false,
"trimmed": false, "trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":12,"h":12}, "spriteSourceSize": {"x":0,"y":0,"w":12,"h":12},
@ -1226,7 +1226,7 @@
}, },
"sprites/misc/hub_direction_indicator.png": "sprites/misc/hub_direction_indicator.png":
{ {
"frame": {"x":1247,"y":1619,"w":48,"h":48}, "frame": {"x":1386,"y":1942,"w":48,"h":48},
"rotated": false, "rotated": false,
"trimmed": false, "trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":48,"h":48}, "spriteSourceSize": {"x":0,"y":0,"w":48,"h":48},
@ -1234,7 +1234,7 @@
}, },
"sprites/misc/processor_disabled.png": "sprites/misc/processor_disabled.png":
{ {
"frame": {"x":1084,"y":1921,"w":78,"h":81}, "frame": {"x":1561,"y":1781,"w":78,"h":81},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":10,"y":10,"w":78,"h":81}, "spriteSourceSize": {"x":10,"y":10,"w":78,"h":81},
@ -1242,7 +1242,7 @@
}, },
"sprites/misc/processor_disconnected.png": "sprites/misc/processor_disconnected.png":
{ {
"frame": {"x":1304,"y":1619,"w":65,"h":84}, "frame": {"x":1645,"y":1765,"w":65,"h":84},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":17,"y":8,"w":65,"h":84}, "spriteSourceSize": {"x":17,"y":8,"w":65,"h":84},
@ -1250,7 +1250,7 @@
}, },
"sprites/misc/reader_overlay.png": "sprites/misc/reader_overlay.png":
{ {
"frame": {"x":951,"y":1437,"w":104,"h":70}, "frame": {"x":1250,"y":1974,"w":104,"h":70},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":20,"y":38,"w":104,"h":70}, "spriteSourceSize": {"x":20,"y":38,"w":104,"h":70},
@ -1258,7 +1258,7 @@
}, },
"sprites/misc/slot_bad_arrow.png": "sprites/misc/slot_bad_arrow.png":
{ {
"frame": {"x":1999,"y":161,"w":35,"h":35}, "frame": {"x":1980,"y":1148,"w":35,"h":35},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":2,"y":2,"w":35,"h":35}, "spriteSourceSize": {"x":2,"y":2,"w":35,"h":35},
@ -1266,7 +1266,7 @@
}, },
"sprites/misc/slot_good_arrow.png": "sprites/misc/slot_good_arrow.png":
{ {
"frame": {"x":1999,"y":116,"w":35,"h":39}, "frame": {"x":1766,"y":1883,"w":35,"h":39},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":2,"y":0,"w":35,"h":39}, "spriteSourceSize": {"x":2,"y":0,"w":35,"h":39},
@ -1274,7 +1274,7 @@
}, },
"sprites/misc/storage_overlay.png": "sprites/misc/storage_overlay.png":
{ {
"frame": {"x":566,"y":1981,"w":89,"h":44}, "frame": {"x":865,"y":1984,"w":89,"h":44},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":1,"y":1,"w":89,"h":44}, "spriteSourceSize": {"x":1,"y":1,"w":89,"h":44},
@ -1282,7 +1282,7 @@
}, },
"sprites/misc/waypoint.png": "sprites/misc/waypoint.png":
{ {
"frame": {"x":661,"y":1981,"w":38,"h":48}, "frame": {"x":1414,"y":1996,"w":38,"h":48},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":5,"y":0,"w":38,"h":48}, "spriteSourceSize": {"x":5,"y":0,"w":38,"h":48},
@ -1290,7 +1290,7 @@
}, },
"sprites/wires/boolean_false.png": "sprites/wires/boolean_false.png":
{ {
"frame": {"x":1061,"y":1437,"w":31,"h":41}, "frame": {"x":2013,"y":1189,"w":31,"h":41},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":9,"y":5,"w":31,"h":41}, "spriteSourceSize": {"x":9,"y":5,"w":31,"h":41},
@ -1298,7 +1298,7 @@
}, },
"sprites/wires/boolean_true.png": "sprites/wires/boolean_true.png":
{ {
"frame": {"x":1999,"y":202,"w":22,"h":41}, "frame": {"x":1862,"y":1747,"w":22,"h":41},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":11,"y":5,"w":22,"h":41}, "spriteSourceSize": {"x":11,"y":5,"w":22,"h":41},
@ -1306,7 +1306,7 @@
}, },
"sprites/wires/display/blue.png": "sprites/wires/display/blue.png":
{ {
"frame": {"x":1391,"y":1927,"w":47,"h":47}, "frame": {"x":706,"y":1997,"w":47,"h":47},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":1,"y":1,"w":47,"h":47}, "spriteSourceSize": {"x":1,"y":1,"w":47,"h":47},
@ -1314,7 +1314,7 @@
}, },
"sprites/wires/display/cyan.png": "sprites/wires/display/cyan.png":
{ {
"frame": {"x":1444,"y":1927,"w":47,"h":47}, "frame": {"x":759,"y":1997,"w":47,"h":47},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":1,"y":1,"w":47,"h":47}, "spriteSourceSize": {"x":1,"y":1,"w":47,"h":47},
@ -1322,7 +1322,7 @@
}, },
"sprites/wires/display/green.png": "sprites/wires/display/green.png":
{ {
"frame": {"x":1370,"y":1980,"w":47,"h":47}, "frame": {"x":812,"y":1997,"w":47,"h":47},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":1,"y":1,"w":47,"h":47}, "spriteSourceSize": {"x":1,"y":1,"w":47,"h":47},
@ -1330,7 +1330,7 @@
}, },
"sprites/wires/display/purple.png": "sprites/wires/display/purple.png":
{ {
"frame": {"x":1423,"y":1980,"w":47,"h":47}, "frame": {"x":1997,"y":716,"w":47,"h":47},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":1,"y":1,"w":47,"h":47}, "spriteSourceSize": {"x":1,"y":1,"w":47,"h":47},
@ -1338,7 +1338,7 @@
}, },
"sprites/wires/display/red.png": "sprites/wires/display/red.png":
{ {
"frame": {"x":1497,"y":1901,"w":47,"h":47}, "frame": {"x":1997,"y":769,"w":47,"h":47},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":1,"y":1,"w":47,"h":47}, "spriteSourceSize": {"x":1,"y":1,"w":47,"h":47},
@ -1346,7 +1346,7 @@
}, },
"sprites/wires/display/white.png": "sprites/wires/display/white.png":
{ {
"frame": {"x":1550,"y":1901,"w":47,"h":47}, "frame": {"x":1997,"y":822,"w":47,"h":47},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":1,"y":1,"w":47,"h":47}, "spriteSourceSize": {"x":1,"y":1,"w":47,"h":47},
@ -1354,7 +1354,7 @@
}, },
"sprites/wires/display/yellow.png": "sprites/wires/display/yellow.png":
{ {
"frame": {"x":1603,"y":1901,"w":47,"h":47}, "frame": {"x":1997,"y":875,"w":47,"h":47},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":1,"y":1,"w":47,"h":47}, "spriteSourceSize": {"x":1,"y":1,"w":47,"h":47},
@ -1362,10 +1362,10 @@
}, },
"sprites/wires/lever_on.png": "sprites/wires/lever_on.png":
{ {
"frame": {"x":1935,"y":1744,"w":109,"h":127}, "frame": {"x":1619,"y":1645,"w":101,"h":114},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":18,"y":5,"w":109,"h":127}, "spriteSourceSize": {"x":21,"y":10,"w":101,"h":114},
"sourceSize": {"w":144,"h":144} "sourceSize": {"w":144,"h":144}
}, },
"sprites/wires/logical_acceptor.png": "sprites/wires/logical_acceptor.png":
@ -1378,7 +1378,7 @@
}, },
"sprites/wires/logical_ejector.png": "sprites/wires/logical_ejector.png":
{ {
"frame": {"x":1304,"y":1976,"w":60,"h":67}, "frame": {"x":1647,"y":1855,"w":60,"h":67},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":44,"y":0,"w":60,"h":67}, "spriteSourceSize": {"x":44,"y":0,"w":60,"h":67},
@ -1386,7 +1386,7 @@
}, },
"sprites/wires/network_conflict.png": "sprites/wires/network_conflict.png":
{ {
"frame": {"x":1656,"y":1901,"w":47,"h":44}, "frame": {"x":1713,"y":1883,"w":47,"h":44},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":1,"y":2,"w":47,"h":44}, "spriteSourceSize": {"x":1,"y":2,"w":47,"h":44},
@ -1394,7 +1394,7 @@
}, },
"sprites/wires/network_empty.png": "sprites/wires/network_empty.png":
{ {
"frame": {"x":1732,"y":1846,"w":41,"h":48}, "frame": {"x":1200,"y":1984,"w":41,"h":48},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":5,"y":0,"w":41,"h":48}, "spriteSourceSize": {"x":5,"y":0,"w":41,"h":48},
@ -1402,7 +1402,7 @@
}, },
"sprites/wires/overlay_tile.png": "sprites/wires/overlay_tile.png":
{ {
"frame": {"x":1719,"y":453,"w":96,"h":96}, "frame": {"x":1211,"y":1736,"w":96,"h":96},
"rotated": false, "rotated": false,
"trimmed": false, "trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":96,"h":96}, "spriteSourceSize": {"x":0,"y":0,"w":96,"h":96},
@ -1418,7 +1418,7 @@
}, },
"sprites/wires/sets/color_forward.png": "sprites/wires/sets/color_forward.png":
{ {
"frame": {"x":270,"y":1889,"w":18,"h":144}, "frame": {"x":2026,"y":266,"w":18,"h":144},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":63,"y":0,"w":18,"h":144}, "spriteSourceSize": {"x":63,"y":0,"w":18,"h":144},
@ -1434,7 +1434,7 @@
}, },
"sprites/wires/sets/color_turn.png": "sprites/wires/sets/color_turn.png":
{ {
"frame": {"x":1405,"y":1753,"w":81,"h":81}, "frame": {"x":1474,"y":1781,"w":81,"h":81},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":63,"y":63,"w":81,"h":81}, "spriteSourceSize": {"x":63,"y":63,"w":81,"h":81},
@ -1450,7 +1450,7 @@
}, },
"sprites/wires/sets/conflict_forward.png": "sprites/wires/sets/conflict_forward.png":
{ {
"frame": {"x":973,"y":1840,"w":18,"h":144}, "frame": {"x":2026,"y":416,"w":18,"h":144},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":63,"y":0,"w":18,"h":144}, "spriteSourceSize": {"x":63,"y":0,"w":18,"h":144},
@ -1458,7 +1458,7 @@
}, },
"sprites/wires/sets/conflict_split.png": "sprites/wires/sets/conflict_split.png":
{ {
"frame": {"x":645,"y":1460,"w":144,"h":81}, "frame": {"x":1725,"y":743,"w":144,"h":81},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":0,"y":63,"w":144,"h":81}, "spriteSourceSize": {"x":0,"y":63,"w":144,"h":81},
@ -1466,7 +1466,7 @@
}, },
"sprites/wires/sets/conflict_turn.png": "sprites/wires/sets/conflict_turn.png":
{ {
"frame": {"x":1304,"y":1889,"w":81,"h":81}, "frame": {"x":1473,"y":1868,"w":81,"h":81},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":63,"y":63,"w":81,"h":81}, "spriteSourceSize": {"x":63,"y":63,"w":81,"h":81},
@ -1482,7 +1482,7 @@
}, },
"sprites/wires/sets/regular_forward.png": "sprites/wires/sets/regular_forward.png":
{ {
"frame": {"x":2006,"y":1028,"w":18,"h":144}, "frame": {"x":2026,"y":116,"w":18,"h":144},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":63,"y":0,"w":18,"h":144}, "spriteSourceSize": {"x":63,"y":0,"w":18,"h":144},
@ -1498,7 +1498,7 @@
}, },
"sprites/wires/sets/regular_turn.png": "sprites/wires/sets/regular_turn.png":
{ {
"frame": {"x":997,"y":1921,"w":81,"h":81}, "frame": {"x":1386,"y":1855,"w":81,"h":81},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":63,"y":63,"w":81,"h":81}, "spriteSourceSize": {"x":63,"y":63,"w":81,"h":81},
@ -1514,7 +1514,7 @@
}, },
"sprites/wires/sets/shape_forward.png": "sprites/wires/sets/shape_forward.png":
{ {
"frame": {"x":1975,"y":116,"w":18,"h":144}, "frame": {"x":2026,"y":566,"w":18,"h":144},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":63,"y":0,"w":18,"h":144}, "spriteSourceSize": {"x":63,"y":0,"w":18,"h":144},
@ -1522,7 +1522,7 @@
}, },
"sprites/wires/sets/shape_split.png": "sprites/wires/sets/shape_split.png":
{ {
"frame": {"x":795,"y":1461,"w":144,"h":81}, "frame": {"x":1690,"y":830,"w":144,"h":81},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":0,"y":63,"w":144,"h":81}, "spriteSourceSize": {"x":0,"y":63,"w":144,"h":81},
@ -1530,7 +1530,7 @@
}, },
"sprites/wires/sets/shape_turn.png": "sprites/wires/sets/shape_turn.png":
{ {
"frame": {"x":1405,"y":1840,"w":81,"h":81}, "frame": {"x":1560,"y":1868,"w":81,"h":81},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":63,"y":63,"w":81,"h":81}, "spriteSourceSize": {"x":63,"y":63,"w":81,"h":81},
@ -1538,7 +1538,7 @@
}, },
"sprites/wires/wires_preview.png": "sprites/wires/wires_preview.png":
{ {
"frame": {"x":1247,"y":1673,"w":48,"h":48}, "frame": {"x":1360,"y":1996,"w":48,"h":48},
"rotated": false, "rotated": false,
"trimmed": false, "trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":48,"h":48}, "spriteSourceSize": {"x":0,"y":0,"w":48,"h":48},
@ -1551,6 +1551,6 @@
"format": "RGBA8888", "format": "RGBA8888",
"size": {"w":2048,"h":2048}, "size": {"w":2048,"h":2048},
"scale": "0.75", "scale": "0.75",
"smartupdate": "$TexturePacker:SmartUpdate:c57f50d18c59efc0edbd4a3a732323a4:3fcf23da2ddc6370c437cf41f6d44ed0:908b89f5ca8ff73e331a35a3b14d0604$" "smartupdate": "$TexturePacker:SmartUpdate:5429cdf3b92834776437a91974e89d3c:fa61fb225cd312db144ce6a38d97871b:908b89f5ca8ff73e331a35a3b14d0604$"
} }
} }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 MiB

After

Width:  |  Height:  |  Size: 1.3 MiB

View File

@ -2,7 +2,7 @@
"sprites/belt/built/forward_0.png": "sprites/belt/built/forward_0.png":
{ {
"frame": {"x":157,"y":505,"w":40,"h":48}, "frame": {"x":902,"y":294,"w":40,"h":48},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":4,"y":0,"w":40,"h":48}, "spriteSourceSize": {"x":4,"y":0,"w":40,"h":48},
@ -10,7 +10,7 @@
}, },
"sprites/belt/built/forward_1.png": "sprites/belt/built/forward_1.png":
{ {
"frame": {"x":154,"y":559,"w":40,"h":48}, "frame": {"x":200,"y":476,"w":40,"h":48},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":4,"y":0,"w":40,"h":48}, "spriteSourceSize": {"x":4,"y":0,"w":40,"h":48},
@ -18,7 +18,7 @@
}, },
"sprites/belt/built/forward_2.png": "sprites/belt/built/forward_2.png":
{ {
"frame": {"x":200,"y":582,"w":40,"h":48}, "frame": {"x":146,"y":514,"w":40,"h":48},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":4,"y":0,"w":40,"h":48}, "spriteSourceSize": {"x":4,"y":0,"w":40,"h":48},
@ -26,7 +26,7 @@
}, },
"sprites/belt/built/forward_3.png": "sprites/belt/built/forward_3.png":
{ {
"frame": {"x":150,"y":613,"w":40,"h":48}, "frame": {"x":50,"y":552,"w":40,"h":48},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":4,"y":0,"w":40,"h":48}, "spriteSourceSize": {"x":4,"y":0,"w":40,"h":48},
@ -34,7 +34,7 @@
}, },
"sprites/belt/built/forward_4.png": "sprites/belt/built/forward_4.png":
{ {
"frame": {"x":100,"y":660,"w":40,"h":48}, "frame": {"x":4,"y":553,"w":40,"h":48},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":4,"y":0,"w":40,"h":48}, "spriteSourceSize": {"x":4,"y":0,"w":40,"h":48},
@ -42,7 +42,7 @@
}, },
"sprites/belt/built/forward_5.png": "sprites/belt/built/forward_5.png":
{ {
"frame": {"x":50,"y":678,"w":40,"h":48}, "frame": {"x":96,"y":552,"w":40,"h":48},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":4,"y":0,"w":40,"h":48}, "spriteSourceSize": {"x":4,"y":0,"w":40,"h":48},
@ -50,7 +50,7 @@
}, },
"sprites/belt/built/forward_6.png": "sprites/belt/built/forward_6.png":
{ {
"frame": {"x":4,"y":717,"w":40,"h":48}, "frame": {"x":559,"y":432,"w":40,"h":48},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":4,"y":0,"w":40,"h":48}, "spriteSourceSize": {"x":4,"y":0,"w":40,"h":48},
@ -58,7 +58,7 @@
}, },
"sprites/belt/built/forward_7.png": "sprites/belt/built/forward_7.png":
{ {
"frame": {"x":776,"y":352,"w":40,"h":48}, "frame": {"x":605,"y":432,"w":40,"h":48},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":4,"y":0,"w":40,"h":48}, "spriteSourceSize": {"x":4,"y":0,"w":40,"h":48},
@ -66,7 +66,7 @@
}, },
"sprites/belt/built/forward_8.png": "sprites/belt/built/forward_8.png":
{ {
"frame": {"x":715,"y":402,"w":40,"h":48}, "frame": {"x":651,"y":480,"w":40,"h":48},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":4,"y":0,"w":40,"h":48}, "spriteSourceSize": {"x":4,"y":0,"w":40,"h":48},
@ -74,7 +74,7 @@
}, },
"sprites/belt/built/forward_9.png": "sprites/belt/built/forward_9.png":
{ {
"frame": {"x":665,"y":428,"w":40,"h":48}, "frame": {"x":697,"y":499,"w":40,"h":48},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":4,"y":0,"w":40,"h":48}, "spriteSourceSize": {"x":4,"y":0,"w":40,"h":48},
@ -82,7 +82,7 @@
}, },
"sprites/belt/built/forward_10.png": "sprites/belt/built/forward_10.png":
{ {
"frame": {"x":104,"y":606,"w":40,"h":48}, "frame": {"x":246,"y":476,"w":40,"h":48},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":4,"y":0,"w":40,"h":48}, "spriteSourceSize": {"x":4,"y":0,"w":40,"h":48},
@ -90,7 +90,7 @@
}, },
"sprites/belt/built/forward_11.png": "sprites/belt/built/forward_11.png":
{ {
"frame": {"x":54,"y":624,"w":40,"h":48}, "frame": {"x":54,"y":498,"w":40,"h":48},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":4,"y":0,"w":40,"h":48}, "spriteSourceSize": {"x":4,"y":0,"w":40,"h":48},
@ -98,7 +98,7 @@
}, },
"sprites/belt/built/forward_12.png": "sprites/belt/built/forward_12.png":
{ {
"frame": {"x":4,"y":663,"w":40,"h":48}, "frame": {"x":4,"y":499,"w":40,"h":48},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":4,"y":0,"w":40,"h":48}, "spriteSourceSize": {"x":4,"y":0,"w":40,"h":48},
@ -106,7 +106,7 @@
}, },
"sprites/belt/built/forward_13.png": "sprites/belt/built/forward_13.png":
{ {
"frame": {"x":253,"y":532,"w":40,"h":48}, "frame": {"x":100,"y":498,"w":40,"h":48},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":4,"y":0,"w":40,"h":48}, "spriteSourceSize": {"x":4,"y":0,"w":40,"h":48},
@ -114,7 +114,7 @@
}, },
"sprites/belt/built/left_0.png": "sprites/belt/built/left_0.png":
{ {
"frame": {"x":487,"y":302,"w":44,"h":44}, "frame": {"x":668,"y":380,"w":44,"h":44},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":0,"y":4,"w":44,"h":44}, "spriteSourceSize": {"x":0,"y":4,"w":44,"h":44},
@ -122,7 +122,7 @@
}, },
"sprites/belt/built/left_1.png": "sprites/belt/built/left_1.png":
{ {
"frame": {"x":487,"y":352,"w":44,"h":44}, "frame": {"x":718,"y":399,"w":44,"h":44},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":0,"y":4,"w":44,"h":44}, "spriteSourceSize": {"x":0,"y":4,"w":44,"h":44},
@ -130,7 +130,7 @@
}, },
"sprites/belt/built/left_2.png": "sprites/belt/built/left_2.png":
{ {
"frame": {"x":565,"y":362,"w":44,"h":44}, "frame": {"x":932,"y":480,"w":44,"h":44},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":0,"y":4,"w":44,"h":44}, "spriteSourceSize": {"x":0,"y":4,"w":44,"h":44},
@ -138,7 +138,7 @@
}, },
"sprites/belt/built/left_3.png": "sprites/belt/built/left_3.png":
{ {
"frame": {"x":615,"y":362,"w":44,"h":44}, "frame": {"x":718,"y":449,"w":44,"h":44},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":0,"y":4,"w":44,"h":44}, "spriteSourceSize": {"x":0,"y":4,"w":44,"h":44},
@ -146,7 +146,7 @@
}, },
"sprites/belt/built/left_4.png": "sprites/belt/built/left_4.png":
{ {
"frame": {"x":487,"y":402,"w":44,"h":44}, "frame": {"x":768,"y":449,"w":44,"h":44},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":0,"y":4,"w":44,"h":44}, "spriteSourceSize": {"x":0,"y":4,"w":44,"h":44},
@ -154,7 +154,7 @@
}, },
"sprites/belt/built/left_5.png": "sprites/belt/built/left_5.png":
{ {
"frame": {"x":431,"y":404,"w":44,"h":44}, "frame": {"x":832,"y":478,"w":44,"h":44},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":0,"y":4,"w":44,"h":44}, "spriteSourceSize": {"x":0,"y":4,"w":44,"h":44},
@ -162,7 +162,7 @@
}, },
"sprites/belt/built/left_6.png": "sprites/belt/built/left_6.png":
{ {
"frame": {"x":381,"y":406,"w":44,"h":44}, "frame": {"x":882,"y":500,"w":44,"h":44},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":0,"y":4,"w":44,"h":44}, "spriteSourceSize": {"x":0,"y":4,"w":44,"h":44},
@ -170,7 +170,7 @@
}, },
"sprites/belt/built/left_7.png": "sprites/belt/built/left_7.png":
{ {
"frame": {"x":313,"y":436,"w":44,"h":44}, "frame": {"x":932,"y":530,"w":44,"h":44},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":0,"y":4,"w":44,"h":44}, "spriteSourceSize": {"x":0,"y":4,"w":44,"h":44},
@ -178,7 +178,7 @@
}, },
"sprites/belt/built/left_8.png": "sprites/belt/built/left_8.png":
{ {
"frame": {"x":205,"y":482,"w":44,"h":44}, "frame": {"x":384,"y":302,"w":44,"h":44},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":0,"y":4,"w":44,"h":44}, "spriteSourceSize": {"x":0,"y":4,"w":44,"h":44},
@ -186,7 +186,7 @@
}, },
"sprites/belt/built/left_9.png": "sprites/belt/built/left_9.png":
{ {
"frame": {"x":104,"y":556,"w":44,"h":44}, "frame": {"x":207,"y":376,"w":44,"h":44},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":0,"y":4,"w":44,"h":44}, "spriteSourceSize": {"x":0,"y":4,"w":44,"h":44},
@ -194,7 +194,7 @@
}, },
"sprites/belt/built/left_10.png": "sprites/belt/built/left_10.png":
{ {
"frame": {"x":437,"y":354,"w":44,"h":44}, "frame": {"x":668,"y":430,"w":44,"h":44},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":0,"y":4,"w":44,"h":44}, "spriteSourceSize": {"x":0,"y":4,"w":44,"h":44},
@ -202,7 +202,7 @@
}, },
"sprites/belt/built/left_11.png": "sprites/belt/built/left_11.png":
{ {
"frame": {"x":381,"y":356,"w":44,"h":44}, "frame": {"x":768,"y":399,"w":44,"h":44},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":0,"y":4,"w":44,"h":44}, "spriteSourceSize": {"x":0,"y":4,"w":44,"h":44},
@ -210,7 +210,7 @@
}, },
"sprites/belt/built/left_12.png": "sprites/belt/built/left_12.png":
{ {
"frame": {"x":733,"y":302,"w":44,"h":44}, "frame": {"x":832,"y":428,"w":44,"h":44},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":0,"y":4,"w":44,"h":44}, "spriteSourceSize": {"x":0,"y":4,"w":44,"h":44},
@ -218,7 +218,7 @@
}, },
"sprites/belt/built/left_13.png": "sprites/belt/built/left_13.png":
{ {
"frame": {"x":676,"y":328,"w":44,"h":44}, "frame": {"x":882,"y":450,"w":44,"h":44},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":0,"y":4,"w":44,"h":44}, "spriteSourceSize": {"x":0,"y":4,"w":44,"h":44},
@ -226,7 +226,7 @@
}, },
"sprites/belt/built/right_0.png": "sprites/belt/built/right_0.png":
{ {
"frame": {"x":54,"y":574,"w":44,"h":44}, "frame": {"x":257,"y":376,"w":44,"h":44},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":4,"y":4,"w":44,"h":44}, "spriteSourceSize": {"x":4,"y":4,"w":44,"h":44},
@ -234,7 +234,7 @@
}, },
"sprites/belt/built/right_1.png": "sprites/belt/built/right_1.png":
{ {
"frame": {"x":4,"y":613,"w":44,"h":44}, "frame": {"x":434,"y":302,"w":44,"h":44},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":4,"y":4,"w":44,"h":44}, "spriteSourceSize": {"x":4,"y":4,"w":44,"h":44},
@ -242,7 +242,7 @@
}, },
"sprites/belt/built/right_2.png": "sprites/belt/built/right_2.png":
{ {
"frame": {"x":947,"y":328,"w":44,"h":44}, "frame": {"x":252,"y":426,"w":44,"h":44},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":4,"y":4,"w":44,"h":44}, "spriteSourceSize": {"x":4,"y":4,"w":44,"h":44},
@ -250,7 +250,7 @@
}, },
"sprites/belt/built/right_3.png": "sprites/belt/built/right_3.png":
{ {
"frame": {"x":726,"y":352,"w":44,"h":44}, "frame": {"x":427,"y":352,"w":44,"h":44},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":4,"y":4,"w":44,"h":44}, "spriteSourceSize": {"x":4,"y":4,"w":44,"h":44},
@ -258,7 +258,7 @@
}, },
"sprites/belt/built/right_4.png": "sprites/belt/built/right_4.png":
{ {
"frame": {"x":665,"y":378,"w":44,"h":44}, "frame": {"x":477,"y":352,"w":44,"h":44},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":4,"y":4,"w":44,"h":44}, "spriteSourceSize": {"x":4,"y":4,"w":44,"h":44},
@ -266,7 +266,7 @@
}, },
"sprites/belt/built/right_5.png": "sprites/belt/built/right_5.png":
{ {
"frame": {"x":565,"y":412,"w":44,"h":44}, "frame": {"x":561,"y":382,"w":44,"h":44},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":4,"y":4,"w":44,"h":44}, "spriteSourceSize": {"x":4,"y":4,"w":44,"h":44},
@ -274,7 +274,7 @@
}, },
"sprites/belt/built/right_6.png": "sprites/belt/built/right_6.png":
{ {
"frame": {"x":615,"y":412,"w":44,"h":44}, "frame": {"x":58,"y":448,"w":44,"h":44},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":4,"y":4,"w":44,"h":44}, "spriteSourceSize": {"x":4,"y":4,"w":44,"h":44},
@ -282,7 +282,7 @@
}, },
"sprites/belt/built/right_7.png": "sprites/belt/built/right_7.png":
{ {
"frame": {"x":481,"y":452,"w":44,"h":44}, "frame": {"x":4,"y":449,"w":44,"h":44},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":4,"y":4,"w":44,"h":44}, "spriteSourceSize": {"x":4,"y":4,"w":44,"h":44},
@ -290,7 +290,7 @@
}, },
"sprites/belt/built/right_8.png": "sprites/belt/built/right_8.png":
{ {
"frame": {"x":431,"y":454,"w":44,"h":44}, "frame": {"x":108,"y":448,"w":44,"h":44},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":4,"y":4,"w":44,"h":44}, "spriteSourceSize": {"x":4,"y":4,"w":44,"h":44},
@ -298,7 +298,7 @@
}, },
"sprites/belt/built/right_9.png": "sprites/belt/built/right_9.png":
{ {
"frame": {"x":377,"y":456,"w":44,"h":44}, "frame": {"x":376,"y":402,"w":44,"h":44},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":4,"y":4,"w":44,"h":44}, "spriteSourceSize": {"x":4,"y":4,"w":44,"h":44},
@ -306,7 +306,7 @@
}, },
"sprites/belt/built/right_10.png": "sprites/belt/built/right_10.png":
{ {
"frame": {"x":255,"y":482,"w":44,"h":44}, "frame": {"x":484,"y":302,"w":44,"h":44},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":4,"y":4,"w":44,"h":44}, "spriteSourceSize": {"x":4,"y":4,"w":44,"h":44},
@ -314,7 +314,7 @@
}, },
"sprites/belt/built/right_11.png": "sprites/belt/built/right_11.png":
{ {
"frame": {"x":783,"y":302,"w":44,"h":44}, "frame": {"x":377,"y":352,"w":44,"h":44},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":4,"y":4,"w":44,"h":44}, "spriteSourceSize": {"x":4,"y":4,"w":44,"h":44},
@ -322,7 +322,7 @@
}, },
"sprites/belt/built/right_12.png": "sprites/belt/built/right_12.png":
{ {
"frame": {"x":833,"y":302,"w":44,"h":44}, "frame": {"x":307,"y":382,"w":44,"h":44},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":4,"y":4,"w":44,"h":44}, "spriteSourceSize": {"x":4,"y":4,"w":44,"h":44},
@ -330,7 +330,7 @@
}, },
"sprites/belt/built/right_13.png": "sprites/belt/built/right_13.png":
{ {
"frame": {"x":897,"y":314,"w":44,"h":44}, "frame": {"x":202,"y":426,"w":44,"h":44},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":4,"y":4,"w":44,"h":44}, "spriteSourceSize": {"x":4,"y":4,"w":44,"h":44},
@ -346,7 +346,7 @@
}, },
"sprites/blueprints/balancer-merger.png": "sprites/blueprints/balancer-merger.png":
{ {
"frame": {"x":208,"y":376,"w":47,"h":47}, "frame": {"x":678,"y":274,"w":47,"h":47},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":1,"y":0,"w":47,"h":47}, "spriteSourceSize": {"x":1,"y":0,"w":47,"h":47},
@ -362,7 +362,7 @@
}, },
"sprites/blueprints/balancer-splitter.png": "sprites/blueprints/balancer-splitter.png":
{ {
"frame": {"x":261,"y":376,"w":47,"h":47}, "frame": {"x":731,"y":302,"w":47,"h":47},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":1,"y":0,"w":47,"h":47}, "spriteSourceSize": {"x":1,"y":0,"w":47,"h":47},
@ -378,7 +378,7 @@
}, },
"sprites/blueprints/belt_left.png": "sprites/blueprints/belt_left.png":
{ {
"frame": {"x":305,"y":486,"w":44,"h":44}, "frame": {"x":302,"y":432,"w":44,"h":44},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":0,"y":4,"w":44,"h":44}, "spriteSourceSize": {"x":0,"y":4,"w":44,"h":44},
@ -386,7 +386,7 @@
}, },
"sprites/blueprints/belt_right.png": "sprites/blueprints/belt_right.png":
{ {
"frame": {"x":203,"y":532,"w":44,"h":44}, "frame": {"x":426,"y":402,"w":44,"h":44},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":4,"y":4,"w":44,"h":44}, "spriteSourceSize": {"x":4,"y":4,"w":44,"h":44},
@ -394,7 +394,7 @@
}, },
"sprites/blueprints/belt_top.png": "sprites/blueprints/belt_top.png":
{ {
"frame": {"x":822,"y":352,"w":40,"h":48}, "frame": {"x":743,"y":499,"w":40,"h":48},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":4,"y":0,"w":40,"h":48}, "spriteSourceSize": {"x":4,"y":0,"w":40,"h":48},
@ -426,7 +426,7 @@
}, },
"sprites/blueprints/display.png": "sprites/blueprints/display.png":
{ {
"frame": {"x":4,"y":561,"w":44,"h":46}, "frame": {"x":618,"y":328,"w":44,"h":46},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":2,"y":2,"w":44,"h":46}, "spriteSourceSize": {"x":2,"y":2,"w":44,"h":46},
@ -442,10 +442,10 @@
}, },
"sprites/blueprints/lever.png": "sprites/blueprints/lever.png":
{ {
"frame": {"x":906,"y":214,"w":38,"h":44}, "frame": {"x":982,"y":483,"w":35,"h":41},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":5,"y":1,"w":38,"h":44}, "spriteSourceSize": {"x":6,"y":2,"w":35,"h":41},
"sourceSize": {"w":48,"h":48} "sourceSize": {"w":48,"h":48}
}, },
"sprites/blueprints/logic_gate-not.png": "sprites/blueprints/logic_gate-not.png":
@ -466,7 +466,7 @@
}, },
"sprites/blueprints/logic_gate-transistor.png": "sprites/blueprints/logic_gate-transistor.png":
{ {
"frame": {"x":166,"y":397,"w":35,"h":48}, "frame": {"x":166,"y":317,"w":35,"h":48},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":0,"y":0,"w":35,"h":48}, "spriteSourceSize": {"x":0,"y":0,"w":35,"h":48},
@ -490,7 +490,7 @@
}, },
"sprites/blueprints/miner-chainable.png": "sprites/blueprints/miner-chainable.png":
{ {
"frame": {"x":680,"y":274,"w":47,"h":48}, "frame": {"x":849,"y":268,"w":47,"h":48},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":1,"y":0,"w":47,"h":48}, "spriteSourceSize": {"x":1,"y":0,"w":47,"h":48},
@ -498,7 +498,7 @@
}, },
"sprites/blueprints/miner.png": "sprites/blueprints/miner.png":
{ {
"frame": {"x":570,"y":308,"w":47,"h":48}, "frame": {"x":948,"y":328,"w":47,"h":48},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":1,"y":0,"w":47,"h":48}, "spriteSourceSize": {"x":1,"y":0,"w":47,"h":48},
@ -584,7 +584,7 @@
"spriteSourceSize": {"x":3,"y":0,"w":89,"h":48}, "spriteSourceSize": {"x":3,"y":0,"w":89,"h":48},
"sourceSize": {"w":96,"h":48} "sourceSize": {"w":96,"h":48}
}, },
"sprites/blueprints/trash-storage.png": "sprites/blueprints/storage.png":
{ {
"frame": {"x":768,"y":112,"w":85,"h":96}, "frame": {"x":768,"y":112,"w":85,"h":96},
"rotated": false, "rotated": false,
@ -642,7 +642,7 @@
}, },
"sprites/blueprints/virtual_processor-painter.png": "sprites/blueprints/virtual_processor-painter.png":
{ {
"frame": {"x":57,"y":466,"w":44,"h":48}, "frame": {"x":837,"y":374,"w":44,"h":48},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":4,"y":0,"w":44,"h":48}, "spriteSourceSize": {"x":4,"y":0,"w":44,"h":48},
@ -666,7 +666,7 @@
}, },
"sprites/blueprints/virtual_processor-stacker.png": "sprites/blueprints/virtual_processor-stacker.png":
{ {
"frame": {"x":4,"y":507,"w":44,"h":48}, "frame": {"x":887,"y":396,"w":44,"h":48},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":4,"y":0,"w":44,"h":48}, "spriteSourceSize": {"x":4,"y":0,"w":44,"h":48},
@ -698,7 +698,7 @@
}, },
"sprites/blueprints/wire-split.png": "sprites/blueprints/wire-split.png":
{ {
"frame": {"x":741,"y":268,"w":48,"h":28}, "frame": {"x":58,"y":414,"w":48,"h":28},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":0,"y":20,"w":48,"h":28}, "spriteSourceSize": {"x":0,"y":20,"w":48,"h":28},
@ -706,7 +706,7 @@
}, },
"sprites/blueprints/wire-turn.png": "sprites/blueprints/wire-turn.png":
{ {
"frame": {"x":912,"y":364,"w":28,"h":28}, "frame": {"x":166,"y":446,"w":28,"h":28},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":20,"y":20,"w":28,"h":28}, "spriteSourceSize": {"x":20,"y":20,"w":28,"h":28},
@ -722,7 +722,7 @@
}, },
"sprites/blueprints/wire_tunnel-coating.png": "sprites/blueprints/wire_tunnel-coating.png":
{ {
"frame": {"x":363,"y":345,"w":12,"h":46}, "frame": {"x":550,"y":294,"w":12,"h":46},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":18,"y":1,"w":12,"h":46}, "spriteSourceSize": {"x":18,"y":1,"w":12,"h":46},
@ -746,7 +746,7 @@
}, },
"sprites/buildings/balancer-merger.png": "sprites/buildings/balancer-merger.png":
{ {
"frame": {"x":207,"y":429,"w":47,"h":47}, "frame": {"x":678,"y":327,"w":47,"h":47},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":1,"y":0,"w":47,"h":47}, "spriteSourceSize": {"x":1,"y":0,"w":47,"h":47},
@ -762,7 +762,7 @@
}, },
"sprites/buildings/balancer-splitter.png": "sprites/buildings/balancer-splitter.png":
{ {
"frame": {"x":260,"y":429,"w":47,"h":47}, "frame": {"x":784,"y":302,"w":47,"h":47},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":1,"y":0,"w":47,"h":47}, "spriteSourceSize": {"x":1,"y":0,"w":47,"h":47},
@ -778,7 +778,7 @@
}, },
"sprites/buildings/belt_left.png": "sprites/buildings/belt_left.png":
{ {
"frame": {"x":487,"y":302,"w":44,"h":44}, "frame": {"x":668,"y":380,"w":44,"h":44},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":0,"y":4,"w":44,"h":44}, "spriteSourceSize": {"x":0,"y":4,"w":44,"h":44},
@ -786,7 +786,7 @@
}, },
"sprites/buildings/belt_right.png": "sprites/buildings/belt_right.png":
{ {
"frame": {"x":54,"y":574,"w":44,"h":44}, "frame": {"x":257,"y":376,"w":44,"h":44},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":4,"y":4,"w":44,"h":44}, "spriteSourceSize": {"x":4,"y":4,"w":44,"h":44},
@ -794,7 +794,7 @@
}, },
"sprites/buildings/belt_top.png": "sprites/buildings/belt_top.png":
{ {
"frame": {"x":157,"y":505,"w":40,"h":48}, "frame": {"x":902,"y":294,"w":40,"h":48},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":4,"y":0,"w":40,"h":48}, "spriteSourceSize": {"x":4,"y":0,"w":40,"h":48},
@ -802,7 +802,7 @@
}, },
"sprites/buildings/constant_signal.png": "sprites/buildings/constant_signal.png":
{ {
"frame": {"x":166,"y":317,"w":36,"h":43}, "frame": {"x":906,"y":214,"w":36,"h":43},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":6,"y":0,"w":36,"h":43}, "spriteSourceSize": {"x":6,"y":0,"w":36,"h":43},
@ -826,7 +826,7 @@
}, },
"sprites/buildings/display.png": "sprites/buildings/display.png":
{ {
"frame": {"x":437,"y":302,"w":44,"h":46}, "frame": {"x":618,"y":380,"w":44,"h":46},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":2,"y":2,"w":44,"h":46}, "spriteSourceSize": {"x":2,"y":2,"w":44,"h":46},
@ -850,15 +850,15 @@
}, },
"sprites/buildings/lever.png": "sprites/buildings/lever.png":
{ {
"frame": {"x":906,"y":264,"w":38,"h":44}, "frame": {"x":982,"y":576,"w":34,"h":40},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":5,"y":1,"w":38,"h":44}, "spriteSourceSize": {"x":7,"y":2,"w":34,"h":40},
"sourceSize": {"w":48,"h":48} "sourceSize": {"w":48,"h":48}
}, },
"sprites/buildings/logic_gate-not.png": "sprites/buildings/logic_gate-not.png":
{ {
"frame": {"x":314,"y":382,"w":43,"h":48}, "frame": {"x":476,"y":402,"w":43,"h":48},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":3,"y":0,"w":43,"h":48}, "spriteSourceSize": {"x":3,"y":0,"w":43,"h":48},
@ -874,7 +874,7 @@
}, },
"sprites/buildings/logic_gate-transistor.png": "sprites/buildings/logic_gate-transistor.png":
{ {
"frame": {"x":164,"y":451,"w":35,"h":48}, "frame": {"x":166,"y":371,"w":35,"h":48},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":0,"y":0,"w":35,"h":48}, "spriteSourceSize": {"x":0,"y":0,"w":35,"h":48},
@ -890,7 +890,7 @@
}, },
"sprites/buildings/logic_gate.png": "sprites/buildings/logic_gate.png":
{ {
"frame": {"x":208,"y":325,"w":48,"h":45}, "frame": {"x":207,"y":325,"w":48,"h":45},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":0,"y":0,"w":48,"h":45}, "spriteSourceSize": {"x":0,"y":0,"w":48,"h":45},
@ -898,7 +898,7 @@
}, },
"sprites/buildings/miner-chainable.png": "sprites/buildings/miner-chainable.png":
{ {
"frame": {"x":623,"y":308,"w":47,"h":48}, "frame": {"x":572,"y":274,"w":47,"h":48},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":1,"y":0,"w":47,"h":48}, "spriteSourceSize": {"x":1,"y":0,"w":47,"h":48},
@ -906,7 +906,7 @@
}, },
"sprites/buildings/miner.png": "sprites/buildings/miner.png":
{ {
"frame": {"x":384,"y":302,"w":47,"h":48}, "frame": {"x":625,"y":274,"w":47,"h":48},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":1,"y":0,"w":47,"h":48}, "spriteSourceSize": {"x":1,"y":0,"w":47,"h":48},
@ -992,7 +992,7 @@
"spriteSourceSize": {"x":4,"y":0,"w":88,"h":48}, "spriteSourceSize": {"x":4,"y":0,"w":88,"h":48},
"sourceSize": {"w":96,"h":48} "sourceSize": {"w":96,"h":48}
}, },
"sprites/buildings/trash-storage.png": "sprites/buildings/storage.png":
{ {
"frame": {"x":859,"y":112,"w":85,"h":96}, "frame": {"x":859,"y":112,"w":85,"h":96},
"rotated": false, "rotated": false,
@ -1010,7 +1010,7 @@
}, },
"sprites/buildings/underground_belt_entry-tier2.png": "sprites/buildings/underground_belt_entry-tier2.png":
{ {
"frame": {"x":4,"y":415,"w":47,"h":42}, "frame": {"x":890,"y":348,"w":47,"h":42},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":1,"y":6,"w":47,"h":42}, "spriteSourceSize": {"x":1,"y":6,"w":47,"h":42},
@ -1018,7 +1018,7 @@
}, },
"sprites/buildings/underground_belt_entry.png": "sprites/buildings/underground_belt_entry.png":
{ {
"frame": {"x":4,"y":463,"w":47,"h":38}, "frame": {"x":943,"y":382,"w":47,"h":38},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":1,"y":10,"w":47,"h":38}, "spriteSourceSize": {"x":1,"y":10,"w":47,"h":38},
@ -1026,7 +1026,7 @@
}, },
"sprites/buildings/underground_belt_exit-tier2.png": "sprites/buildings/underground_belt_exit-tier2.png":
{ {
"frame": {"x":111,"y":414,"w":47,"h":38}, "frame": {"x":731,"y":355,"w":47,"h":38},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":1,"y":0,"w":47,"h":38}, "spriteSourceSize": {"x":1,"y":0,"w":47,"h":38},
@ -1034,7 +1034,7 @@
}, },
"sprites/buildings/underground_belt_exit.png": "sprites/buildings/underground_belt_exit.png":
{ {
"frame": {"x":111,"y":458,"w":47,"h":38}, "frame": {"x":784,"y":355,"w":47,"h":38},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":1,"y":0,"w":47,"h":38}, "spriteSourceSize": {"x":1,"y":0,"w":47,"h":38},
@ -1050,7 +1050,7 @@
}, },
"sprites/buildings/virtual_processor-painter.png": "sprites/buildings/virtual_processor-painter.png":
{ {
"frame": {"x":107,"y":502,"w":44,"h":48}, "frame": {"x":937,"y":426,"w":44,"h":48},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":4,"y":0,"w":44,"h":48}, "spriteSourceSize": {"x":4,"y":0,"w":44,"h":48},
@ -1058,7 +1058,7 @@
}, },
"sprites/buildings/virtual_processor-rotater.png": "sprites/buildings/virtual_processor-rotater.png":
{ {
"frame": {"x":316,"y":328,"w":41,"h":48}, "frame": {"x":315,"y":328,"w":41,"h":48},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":4,"y":0,"w":41,"h":48}, "spriteSourceSize": {"x":4,"y":0,"w":41,"h":48},
@ -1066,7 +1066,7 @@
}, },
"sprites/buildings/virtual_processor-shapecompare.png": "sprites/buildings/virtual_processor-shapecompare.png":
{ {
"frame": {"x":262,"y":325,"w":48,"h":45}, "frame": {"x":261,"y":325,"w":48,"h":45},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":0,"y":0,"w":48,"h":45}, "spriteSourceSize": {"x":0,"y":0,"w":48,"h":45},
@ -1074,7 +1074,7 @@
}, },
"sprites/buildings/virtual_processor-stacker.png": "sprites/buildings/virtual_processor-stacker.png":
{ {
"frame": {"x":54,"y":520,"w":44,"h":48}, "frame": {"x":568,"y":328,"w":44,"h":48},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":4,"y":0,"w":44,"h":48}, "spriteSourceSize": {"x":4,"y":0,"w":44,"h":48},
@ -1090,7 +1090,7 @@
}, },
"sprites/buildings/virtual_processor.png": "sprites/buildings/virtual_processor.png":
{ {
"frame": {"x":950,"y":220,"w":48,"h":48}, "frame": {"x":948,"y":220,"w":48,"h":48},
"rotated": false, "rotated": false,
"trimmed": false, "trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":48,"h":48}, "spriteSourceSize": {"x":0,"y":0,"w":48,"h":48},
@ -1098,7 +1098,7 @@
}, },
"sprites/buildings/wire-cross.png": "sprites/buildings/wire-cross.png":
{ {
"frame": {"x":950,"y":274,"w":48,"h":48}, "frame": {"x":948,"y":274,"w":48,"h":48},
"rotated": false, "rotated": false,
"trimmed": false, "trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":48,"h":48}, "spriteSourceSize": {"x":0,"y":0,"w":48,"h":48},
@ -1106,7 +1106,7 @@
}, },
"sprites/buildings/wire-split.png": "sprites/buildings/wire-split.png":
{ {
"frame": {"x":795,"y":268,"w":48,"h":28}, "frame": {"x":4,"y":415,"w":48,"h":28},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":0,"y":20,"w":48,"h":28}, "spriteSourceSize": {"x":0,"y":20,"w":48,"h":28},
@ -1114,7 +1114,7 @@
}, },
"sprites/buildings/wire-turn.png": "sprites/buildings/wire-turn.png":
{ {
"frame": {"x":912,"y":398,"w":28,"h":28}, "frame": {"x":527,"y":381,"w":28,"h":28},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":20,"y":20,"w":28,"h":28}, "spriteSourceSize": {"x":20,"y":20,"w":28,"h":28},
@ -1122,7 +1122,7 @@
}, },
"sprites/buildings/wire.png": "sprites/buildings/wire.png":
{ {
"frame": {"x":537,"y":368,"w":8,"h":48}, "frame": {"x":818,"y":420,"w":8,"h":48},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":20,"y":0,"w":8,"h":48}, "spriteSourceSize": {"x":20,"y":0,"w":8,"h":48},
@ -1130,7 +1130,7 @@
}, },
"sprites/buildings/wire_tunnel-coating.png": "sprites/buildings/wire_tunnel-coating.png":
{ {
"frame": {"x":547,"y":316,"w":12,"h":46}, "frame": {"x":996,"y":393,"w":12,"h":46},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":18,"y":1,"w":12,"h":46}, "spriteSourceSize": {"x":18,"y":1,"w":12,"h":46},
@ -1138,7 +1138,7 @@
}, },
"sprites/buildings/wire_tunnel.png": "sprites/buildings/wire_tunnel.png":
{ {
"frame": {"x":58,"y":414,"w":47,"h":46}, "frame": {"x":837,"y":322,"w":47,"h":46},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":1,"y":1,"w":47,"h":46}, "spriteSourceSize": {"x":1,"y":1,"w":47,"h":46},
@ -1202,7 +1202,7 @@
}, },
"sprites/colors/yellow.png": "sprites/colors/yellow.png":
{ {
"frame": {"x":364,"y":261,"w":18,"h":18}, "frame": {"x":1002,"y":221,"w":18,"h":18},
"rotated": false, "rotated": false,
"trimmed": false, "trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":18,"h":18}, "spriteSourceSize": {"x":0,"y":0,"w":18,"h":18},
@ -1210,7 +1210,7 @@
}, },
"sprites/debug/acceptor_slot.png": "sprites/debug/acceptor_slot.png":
{ {
"frame": {"x":537,"y":302,"w":4,"h":4}, "frame": {"x":731,"y":274,"w":4,"h":4},
"rotated": false, "rotated": false,
"trimmed": false, "trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":4,"h":4}, "spriteSourceSize": {"x":0,"y":0,"w":4,"h":4},
@ -1218,7 +1218,7 @@
}, },
"sprites/debug/ejector_slot.png": "sprites/debug/ejector_slot.png":
{ {
"frame": {"x":537,"y":312,"w":4,"h":4}, "frame": {"x":731,"y":284,"w":4,"h":4},
"rotated": false, "rotated": false,
"trimmed": false, "trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":4,"h":4}, "spriteSourceSize": {"x":0,"y":0,"w":4,"h":4},
@ -1234,7 +1234,7 @@
}, },
"sprites/misc/processor_disabled.png": "sprites/misc/processor_disabled.png":
{ {
"frame": {"x":531,"y":452,"w":28,"h":29}, "frame": {"x":534,"y":346,"w":28,"h":29},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":2,"y":2,"w":28,"h":29}, "spriteSourceSize": {"x":2,"y":2,"w":28,"h":29},
@ -1250,7 +1250,7 @@
}, },
"sprites/misc/reader_overlay.png": "sprites/misc/reader_overlay.png":
{ {
"frame": {"x":166,"y":366,"w":36,"h":25}, "frame": {"x":906,"y":263,"w":36,"h":25},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":6,"y":12,"w":36,"h":25}, "spriteSourceSize": {"x":6,"y":12,"w":36,"h":25},
@ -1258,7 +1258,7 @@
}, },
"sprites/misc/slot_bad_arrow.png": "sprites/misc/slot_bad_arrow.png":
{ {
"frame": {"x":363,"y":307,"w":13,"h":13}, "frame": {"x":1001,"y":355,"w":13,"h":13},
"rotated": false, "rotated": false,
"trimmed": false, "trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13},
@ -1266,7 +1266,7 @@
}, },
"sprites/misc/slot_good_arrow.png": "sprites/misc/slot_good_arrow.png":
{ {
"frame": {"x":363,"y":326,"w":13,"h":13}, "frame": {"x":1001,"y":374,"w":13,"h":13},
"rotated": false, "rotated": false,
"trimmed": false, "trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":13,"h":13}, "spriteSourceSize": {"x":0,"y":0,"w":13,"h":13},
@ -1274,7 +1274,7 @@
}, },
"sprites/misc/storage_overlay.png": "sprites/misc/storage_overlay.png":
{ {
"frame": {"x":984,"y":378,"w":30,"h":15}, "frame": {"x":166,"y":425,"w":30,"h":15},
"rotated": false, "rotated": false,
"trimmed": false, "trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":30,"h":15}, "spriteSourceSize": {"x":0,"y":0,"w":30,"h":15},
@ -1282,7 +1282,7 @@
}, },
"sprites/misc/waypoint.png": "sprites/misc/waypoint.png":
{ {
"frame": {"x":550,"y":294,"w":14,"h":16}, "frame": {"x":1001,"y":333,"w":14,"h":16},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":1,"y":0,"w":14,"h":16}, "spriteSourceSize": {"x":1,"y":0,"w":14,"h":16},
@ -1290,7 +1290,7 @@
}, },
"sprites/wires/boolean_false.png": "sprites/wires/boolean_false.png":
{ {
"frame": {"x":363,"y":397,"w":12,"h":15}, "frame": {"x":818,"y":399,"w":12,"h":15},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":2,"y":1,"w":12,"h":15}, "spriteSourceSize": {"x":2,"y":1,"w":12,"h":15},
@ -1330,7 +1330,7 @@
}, },
"sprites/wires/display/purple.png": "sprites/wires/display/purple.png":
{ {
"frame": {"x":1004,"y":221,"w":16,"h":16}, "frame": {"x":1002,"y":245,"w":16,"h":16},
"rotated": false, "rotated": false,
"trimmed": false, "trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16},
@ -1338,7 +1338,7 @@
}, },
"sprites/wires/display/red.png": "sprites/wires/display/red.png":
{ {
"frame": {"x":1004,"y":243,"w":16,"h":16}, "frame": {"x":1002,"y":267,"w":16,"h":16},
"rotated": false, "rotated": false,
"trimmed": false, "trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16},
@ -1346,7 +1346,7 @@
}, },
"sprites/wires/display/white.png": "sprites/wires/display/white.png":
{ {
"frame": {"x":1004,"y":265,"w":16,"h":16}, "frame": {"x":1002,"y":289,"w":16,"h":16},
"rotated": false, "rotated": false,
"trimmed": false, "trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16},
@ -1354,7 +1354,7 @@
}, },
"sprites/wires/display/yellow.png": "sprites/wires/display/yellow.png":
{ {
"frame": {"x":1004,"y":287,"w":16,"h":16}, "frame": {"x":1002,"y":311,"w":16,"h":16},
"rotated": false, "rotated": false,
"trimmed": false, "trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16},
@ -1362,10 +1362,10 @@
}, },
"sprites/wires/lever_on.png": "sprites/wires/lever_on.png":
{ {
"frame": {"x":868,"y":364,"w":38,"h":44}, "frame": {"x":982,"y":530,"w":35,"h":40},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":5,"y":1,"w":38,"h":44}, "spriteSourceSize": {"x":6,"y":2,"w":35,"h":40},
"sourceSize": {"w":48,"h":48} "sourceSize": {"w":48,"h":48}
}, },
"sprites/wires/logical_acceptor.png": "sprites/wires/logical_acceptor.png":
@ -1386,7 +1386,7 @@
}, },
"sprites/wires/network_conflict.png": "sprites/wires/network_conflict.png":
{ {
"frame": {"x":1004,"y":309,"w":16,"h":16}, "frame": {"x":364,"y":261,"w":16,"h":16},
"rotated": false, "rotated": false,
"trimmed": false, "trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16},
@ -1394,7 +1394,7 @@
}, },
"sprites/wires/network_empty.png": "sprites/wires/network_empty.png":
{ {
"frame": {"x":363,"y":285,"w":15,"h":16}, "frame": {"x":363,"y":283,"w":15,"h":16},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":1,"y":0,"w":15,"h":16}, "spriteSourceSize": {"x":1,"y":0,"w":15,"h":16},
@ -1402,7 +1402,7 @@
}, },
"sprites/wires/overlay_tile.png": "sprites/wires/overlay_tile.png":
{ {
"frame": {"x":946,"y":378,"w":32,"h":32}, "frame": {"x":987,"y":445,"w":32,"h":32},
"rotated": false, "rotated": false,
"trimmed": false, "trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":32,"h":32}, "spriteSourceSize": {"x":0,"y":0,"w":32,"h":32},
@ -1418,7 +1418,7 @@
}, },
"sprites/wires/sets/color_forward.png": "sprites/wires/sets/color_forward.png":
{ {
"frame": {"x":551,"y":368,"w":8,"h":48}, "frame": {"x":818,"y":474,"w":8,"h":48},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":20,"y":0,"w":8,"h":48}, "spriteSourceSize": {"x":20,"y":0,"w":8,"h":48},
@ -1426,7 +1426,7 @@
}, },
"sprites/wires/sets/color_split.png": "sprites/wires/sets/color_split.png":
{ {
"frame": {"x":849,"y":268,"w":48,"h":28}, "frame": {"x":112,"y":414,"w":48,"h":28},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":0,"y":20,"w":48,"h":28}, "spriteSourceSize": {"x":0,"y":20,"w":48,"h":28},
@ -1434,7 +1434,7 @@
}, },
"sprites/wires/sets/color_turn.png": "sprites/wires/sets/color_turn.png":
{ {
"frame": {"x":984,"y":399,"w":28,"h":28}, "frame": {"x":525,"y":415,"w":28,"h":28},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":20,"y":20,"w":28,"h":28}, "spriteSourceSize": {"x":20,"y":20,"w":28,"h":28},
@ -1450,7 +1450,7 @@
}, },
"sprites/wires/sets/conflict_forward.png": "sprites/wires/sets/conflict_forward.png":
{ {
"frame": {"x":363,"y":418,"w":8,"h":48}, "frame": {"x":363,"y":305,"w":8,"h":48},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":20,"y":0,"w":8,"h":48}, "spriteSourceSize": {"x":20,"y":0,"w":8,"h":48},
@ -1458,7 +1458,7 @@
}, },
"sprites/wires/sets/conflict_split.png": "sprites/wires/sets/conflict_split.png":
{ {
"frame": {"x":572,"y":274,"w":48,"h":28}, "frame": {"x":741,"y":268,"w":48,"h":28},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":0,"y":20,"w":48,"h":28}, "spriteSourceSize": {"x":0,"y":20,"w":48,"h":28},
@ -1466,7 +1466,7 @@
}, },
"sprites/wires/sets/conflict_turn.png": "sprites/wires/sets/conflict_turn.png":
{ {
"frame": {"x":946,"y":416,"w":28,"h":28}, "frame": {"x":158,"y":480,"w":28,"h":28},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":20,"y":20,"w":28,"h":28}, "spriteSourceSize": {"x":20,"y":20,"w":28,"h":28},
@ -1474,7 +1474,7 @@
}, },
"sprites/wires/sets/regular_cross.png": "sprites/wires/sets/regular_cross.png":
{ {
"frame": {"x":950,"y":274,"w":48,"h":48}, "frame": {"x":948,"y":274,"w":48,"h":48},
"rotated": false, "rotated": false,
"trimmed": false, "trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":48,"h":48}, "spriteSourceSize": {"x":0,"y":0,"w":48,"h":48},
@ -1482,7 +1482,7 @@
}, },
"sprites/wires/sets/regular_forward.png": "sprites/wires/sets/regular_forward.png":
{ {
"frame": {"x":537,"y":368,"w":8,"h":48}, "frame": {"x":818,"y":420,"w":8,"h":48},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":20,"y":0,"w":8,"h":48}, "spriteSourceSize": {"x":20,"y":0,"w":8,"h":48},
@ -1490,7 +1490,7 @@
}, },
"sprites/wires/sets/regular_split.png": "sprites/wires/sets/regular_split.png":
{ {
"frame": {"x":795,"y":268,"w":48,"h":28}, "frame": {"x":4,"y":415,"w":48,"h":28},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":0,"y":20,"w":48,"h":28}, "spriteSourceSize": {"x":0,"y":20,"w":48,"h":28},
@ -1498,7 +1498,7 @@
}, },
"sprites/wires/sets/regular_turn.png": "sprites/wires/sets/regular_turn.png":
{ {
"frame": {"x":912,"y":398,"w":28,"h":28}, "frame": {"x":527,"y":381,"w":28,"h":28},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":20,"y":20,"w":28,"h":28}, "spriteSourceSize": {"x":20,"y":20,"w":28,"h":28},
@ -1514,7 +1514,7 @@
}, },
"sprites/wires/sets/shape_forward.png": "sprites/wires/sets/shape_forward.png":
{ {
"frame": {"x":883,"y":302,"w":8,"h":48}, "frame": {"x":362,"y":359,"w":8,"h":48},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":20,"y":0,"w":8,"h":48}, "spriteSourceSize": {"x":20,"y":0,"w":8,"h":48},
@ -1522,7 +1522,7 @@
}, },
"sprites/wires/sets/shape_split.png": "sprites/wires/sets/shape_split.png":
{ {
"frame": {"x":626,"y":274,"w":48,"h":28}, "frame": {"x":795,"y":268,"w":48,"h":28},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":0,"y":20,"w":48,"h":28}, "spriteSourceSize": {"x":0,"y":20,"w":48,"h":28},
@ -1530,7 +1530,7 @@
}, },
"sprites/wires/sets/shape_turn.png": "sprites/wires/sets/shape_turn.png":
{ {
"frame": {"x":980,"y":433,"w":28,"h":28}, "frame": {"x":525,"y":449,"w":28,"h":28},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":20,"y":20,"w":28,"h":28}, "spriteSourceSize": {"x":20,"y":20,"w":28,"h":28},
@ -1551,6 +1551,6 @@
"format": "RGBA8888", "format": "RGBA8888",
"size": {"w":1024,"h":1024}, "size": {"w":1024,"h":1024},
"scale": "0.25", "scale": "0.25",
"smartupdate": "$TexturePacker:SmartUpdate:c57f50d18c59efc0edbd4a3a732323a4:3fcf23da2ddc6370c437cf41f6d44ed0:908b89f5ca8ff73e331a35a3b14d0604$" "smartupdate": "$TexturePacker:SmartUpdate:5429cdf3b92834776437a91974e89d3c:fa61fb225cd312db144ce6a38d97871b:908b89f5ca8ff73e331a35a3b14d0604$"
} }
} }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 281 KiB

After

Width:  |  Height:  |  Size: 278 KiB

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 700 KiB

After

Width:  |  Height:  |  Size: 701 KiB

View File

@ -257,6 +257,10 @@
<key type="filename">sprites/belt/built/right_7.png</key> <key type="filename">sprites/belt/built/right_7.png</key>
<key type="filename">sprites/belt/built/right_8.png</key> <key type="filename">sprites/belt/built/right_8.png</key>
<key type="filename">sprites/belt/built/right_9.png</key> <key type="filename">sprites/belt/built/right_9.png</key>
<key type="filename">sprites/blueprints/balancer-merger-inverse.png</key>
<key type="filename">sprites/blueprints/balancer-merger.png</key>
<key type="filename">sprites/blueprints/balancer-splitter-inverse.png</key>
<key type="filename">sprites/blueprints/balancer-splitter.png</key>
<key type="filename">sprites/blueprints/constant_signal.png</key> <key type="filename">sprites/blueprints/constant_signal.png</key>
<key type="filename">sprites/blueprints/display.png</key> <key type="filename">sprites/blueprints/display.png</key>
<key type="filename">sprites/blueprints/lever.png</key> <key type="filename">sprites/blueprints/lever.png</key>
@ -271,10 +275,6 @@
<key type="filename">sprites/blueprints/rotater-ccw.png</key> <key type="filename">sprites/blueprints/rotater-ccw.png</key>
<key type="filename">sprites/blueprints/rotater-rotate180.png</key> <key type="filename">sprites/blueprints/rotater-rotate180.png</key>
<key type="filename">sprites/blueprints/rotater.png</key> <key type="filename">sprites/blueprints/rotater.png</key>
<key type="filename">sprites/blueprints/splitter-compact-inverse.png</key>
<key type="filename">sprites/blueprints/splitter-compact-merge-inverse.png</key>
<key type="filename">sprites/blueprints/splitter-compact-merge.png</key>
<key type="filename">sprites/blueprints/splitter-compact.png</key>
<key type="filename">sprites/blueprints/trash.png</key> <key type="filename">sprites/blueprints/trash.png</key>
<key type="filename">sprites/blueprints/underground_belt_entry-tier2.png</key> <key type="filename">sprites/blueprints/underground_belt_entry-tier2.png</key>
<key type="filename">sprites/blueprints/underground_belt_entry.png</key> <key type="filename">sprites/blueprints/underground_belt_entry.png</key>
@ -289,6 +289,10 @@
<key type="filename">sprites/blueprints/virtual_processor.png</key> <key type="filename">sprites/blueprints/virtual_processor.png</key>
<key type="filename">sprites/blueprints/wire_tunnel-coating.png</key> <key type="filename">sprites/blueprints/wire_tunnel-coating.png</key>
<key type="filename">sprites/blueprints/wire_tunnel.png</key> <key type="filename">sprites/blueprints/wire_tunnel.png</key>
<key type="filename">sprites/buildings/balancer-merger-inverse.png</key>
<key type="filename">sprites/buildings/balancer-merger.png</key>
<key type="filename">sprites/buildings/balancer-splitter-inverse.png</key>
<key type="filename">sprites/buildings/balancer-splitter.png</key>
<key type="filename">sprites/buildings/constant_signal.png</key> <key type="filename">sprites/buildings/constant_signal.png</key>
<key type="filename">sprites/buildings/display.png</key> <key type="filename">sprites/buildings/display.png</key>
<key type="filename">sprites/buildings/lever.png</key> <key type="filename">sprites/buildings/lever.png</key>
@ -301,10 +305,6 @@
<key type="filename">sprites/buildings/reader.png</key> <key type="filename">sprites/buildings/reader.png</key>
<key type="filename">sprites/buildings/rotater-ccw.png</key> <key type="filename">sprites/buildings/rotater-ccw.png</key>
<key type="filename">sprites/buildings/rotater-rotate180.png</key> <key type="filename">sprites/buildings/rotater-rotate180.png</key>
<key type="filename">sprites/buildings/splitter-compact-inverse.png</key>
<key type="filename">sprites/buildings/splitter-compact-merge-inverse.png</key>
<key type="filename">sprites/buildings/splitter-compact-merge.png</key>
<key type="filename">sprites/buildings/splitter-compact.png</key>
<key type="filename">sprites/buildings/underground_belt_entry-tier2.png</key> <key type="filename">sprites/buildings/underground_belt_entry-tier2.png</key>
<key type="filename">sprites/buildings/underground_belt_entry.png</key> <key type="filename">sprites/buildings/underground_belt_entry.png</key>
<key type="filename">sprites/buildings/underground_belt_exit-tier2.png</key> <key type="filename">sprites/buildings/underground_belt_exit-tier2.png</key>
@ -350,6 +350,30 @@
<key>scale9FromFile</key> <key>scale9FromFile</key>
<false/> <false/>
</struct> </struct>
<key type="filename">sprites/blueprints/balancer.png</key>
<key type="filename">sprites/blueprints/cutter.png</key>
<key type="filename">sprites/blueprints/filter.png</key>
<key type="filename">sprites/blueprints/mixer.png</key>
<key type="filename">sprites/blueprints/painter-mirrored.png</key>
<key type="filename">sprites/blueprints/painter.png</key>
<key type="filename">sprites/blueprints/stacker.png</key>
<key type="filename">sprites/buildings/balancer.png</key>
<key type="filename">sprites/buildings/filter.png</key>
<key type="filename">sprites/buildings/painter-mirrored.png</key>
<struct type="IndividualSpriteSettings">
<key>pivotPoint</key>
<point_f>0.5,0.5</point_f>
<key>spriteScale</key>
<double>1</double>
<key>scale9Enabled</key>
<false/>
<key>scale9Borders</key>
<rect>96,48,192,96</rect>
<key>scale9Paddings</key>
<rect>96,48,192,96</rect>
<key>scale9FromFile</key>
<false/>
</struct>
<key type="filename">sprites/blueprints/belt_left.png</key> <key type="filename">sprites/blueprints/belt_left.png</key>
<key type="filename">sprites/blueprints/belt_right.png</key> <key type="filename">sprites/blueprints/belt_right.png</key>
<key type="filename">sprites/blueprints/belt_top.png</key> <key type="filename">sprites/blueprints/belt_top.png</key>
@ -396,29 +420,6 @@
<key>scale9FromFile</key> <key>scale9FromFile</key>
<false/> <false/>
</struct> </struct>
<key type="filename">sprites/blueprints/cutter.png</key>
<key type="filename">sprites/blueprints/filter.png</key>
<key type="filename">sprites/blueprints/mixer.png</key>
<key type="filename">sprites/blueprints/painter-mirrored.png</key>
<key type="filename">sprites/blueprints/painter.png</key>
<key type="filename">sprites/blueprints/splitter.png</key>
<key type="filename">sprites/blueprints/stacker.png</key>
<key type="filename">sprites/buildings/filter.png</key>
<key type="filename">sprites/buildings/painter-mirrored.png</key>
<struct type="IndividualSpriteSettings">
<key>pivotPoint</key>
<point_f>0.5,0.5</point_f>
<key>spriteScale</key>
<double>1</double>
<key>scale9Enabled</key>
<false/>
<key>scale9Borders</key>
<rect>96,48,192,96</rect>
<key>scale9Paddings</key>
<rect>96,48,192,96</rect>
<key>scale9FromFile</key>
<false/>
</struct>
<key type="filename">sprites/blueprints/painter-double.png</key> <key type="filename">sprites/blueprints/painter-double.png</key>
<key type="filename">sprites/blueprints/trash-storage.png</key> <key type="filename">sprites/blueprints/trash-storage.png</key>
<key type="filename">sprites/buildings/painter-double.png</key> <key type="filename">sprites/buildings/painter-double.png</key>
@ -439,7 +440,6 @@
<key type="filename">sprites/buildings/cutter.png</key> <key type="filename">sprites/buildings/cutter.png</key>
<key type="filename">sprites/buildings/mixer.png</key> <key type="filename">sprites/buildings/mixer.png</key>
<key type="filename">sprites/buildings/painter.png</key> <key type="filename">sprites/buildings/painter.png</key>
<key type="filename">sprites/buildings/splitter.png</key>
<key type="filename">sprites/buildings/stacker.png</key> <key type="filename">sprites/buildings/stacker.png</key>
<struct type="IndividualSpriteSettings"> <struct type="IndividualSpriteSettings">
<key>pivotPoint</key> <key>pivotPoint</key>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 19 KiB

View File

Before

Width:  |  Height:  |  Size: 47 KiB

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.1 KiB

After

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 14 KiB

View File

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.5 KiB

After

Width:  |  Height:  |  Size: 14 KiB

View File

@ -50,7 +50,6 @@
left: 0; left: 0;
right: 0; right: 0;
bottom: 0; bottom: 0;
background: rgba($mainBgColor, 0.9) uiResource("loading.svg") center center / #{D(60px)} no-repeat;
@include InlineAnimation(0.2s ease-in-out) { @include InlineAnimation(0.2s ease-in-out) {
0% { 0% {
opacity: 0; opacity: 0;
@ -59,6 +58,11 @@
opacity: 1; opacity: 1;
} }
} }
& {
/* @load-async */
background: rgba($mainBgColor, 0.9) uiResource("loading.svg") center center / #{D(60px)} no-repeat;
}
} }
} }
} }

View File

@ -391,11 +391,15 @@ canvas {
color: #393747; color: #393747;
&::after { &::after {
content: " "; content: " ";
background: uiResource("loading.svg") center center / contain no-repeat;
@include S(width, 35px); @include S(width, 35px);
@include S(height, 35px); @include S(height, 35px);
display: inline-block; display: inline-block;
vertical-align: middle; vertical-align: middle;
& {
/* @load-async */
background: uiResource("loading.svg") center center / contain no-repeat;
}
} }
@include InlineAnimation(1.5s ease-in-out infinite) { @include InlineAnimation(1.5s ease-in-out infinite) {
@ -451,7 +455,6 @@ canvas {
.prefab_InfoIcon { .prefab_InfoIcon {
@include S(width, 25px); @include S(width, 25px);
@include S(height, 25px); @include S(height, 25px);
// background: uiResource("icons_small/info.png") center center / contain no-repeat;
z-index: 100; z-index: 100;
opacity: 0.8; opacity: 0.8;
cursor: pointer; cursor: pointer;
@ -468,7 +471,6 @@ canvas {
justify-content: center; justify-content: center;
flex-direction: column; flex-direction: column;
.loadingImage { .loadingImage {
background: uiResource("loading.svg") center center / #{D(40px)} no-repeat;
width: 100%; width: 100%;
display: flex; display: flex;
flex-grow: 1; flex-grow: 1;
@ -478,6 +480,11 @@ canvas {
transform: scale(1.2) rotate(160deg); transform: scale(1.2) rotate(160deg);
} }
} }
& {
/* @load-async */
background: uiResource("loading.svg") center center / #{D(40px)} no-repeat;
}
} }
.prefab_GameHint { .prefab_GameHint {

View File

@ -4,25 +4,14 @@
left: 50%; left: 50%;
transform: translateX(-50%); transform: translateX(-50%);
// NOTE: This flex rule may not be necessary. Need to find out intent. display: grid;
display: flex; grid-template-rows: auto auto;
flex-direction: column; justify-items: center;
background: transparent; background: transparent;
transition: transform 120ms ease-in-out; transition: transform 120ms ease-in-out;
will-change: transform; will-change: transform;
backdrop-filter: blur(D(3px));
background-color: rgba(0, 40, 80, 0.05);
@include S(border-radius, $globalBorderRadius);
@include DarkThemeOverride {
background-color: rgba(darken($darkModeGameBackground, 15), 0.4);
&#ingame_HUD_wires_toolbar {
background-color: rgba(darken($darkModeGameBackground, 5), 0.1);
}
}
&:not(.visible) { &:not(.visible) {
transform: translateX(-50%) translateY(#{D(100px)}); transform: translateX(-50%) translateY(#{D(100px)});
} }
@ -30,6 +19,34 @@
.buildings { .buildings {
display: grid; display: grid;
grid-auto-flow: column; grid-auto-flow: column;
justify-items: center;
align-self: center;
grid-row: 2 / 3;
background-color: rgba(240, 241, 243, 0.5);
@include S(border-radius, $globalBorderRadius);
@include DarkThemeOverride {
background-color: rgba(darken($darkModeGameBackground, 15), 0.4);
}
&.secondary {
grid-row: 1 / 2;
border-bottom-left-radius: 0;
border-bottom-right-radius: 0;
.building {
@include S(width, 30px);
@include S(height, 22px);
background-size: 45%;
&:not(.unlocked) {
&::before {
background-size: #{D(13px)};
}
}
}
}
.building { .building {
color: $accentColorDark; color: $accentColorDark;
@ -52,14 +69,18 @@
&::before { &::before {
content: " "; content: " ";
background: uiResource("locked_building.png") center center / #{D(20px)} #{D(20px)}
no-repeat;
position: absolute; position: absolute;
top: 0; top: 0;
right: 0; right: 0;
bottom: 0; bottom: 0;
left: 0; left: 0;
z-index: 4; z-index: 4;
& {
/* @load-async */
background: uiResource("locked_building.png") center center / #{D(20px)} #{D(20px)}
no-repeat;
}
} }
} }

View File

@ -122,13 +122,16 @@
opacity: 0.7; opacity: 0.7;
@include S(width, 20px); @include S(width, 20px);
@include S(height, 20px); @include S(height, 20px);
background: uiResource("icons/close.png") center center / 80% no-repeat;
cursor: pointer; cursor: pointer;
pointer-events: all; pointer-events: all;
transition: opacity 0.2s ease-in-out; transition: opacity 0.2s ease-in-out;
&:hover { &:hover {
opacity: 0.4; opacity: 0.4;
} }
& {
/* @load-async */
background: uiResource("icons/close.png") center center / 80% no-repeat;
}
} }
} }

View File

@ -38,17 +38,26 @@
@include DarkThemeInvert; @include DarkThemeInvert;
&.shop { &.shop {
background-image: uiResource("icons/shop.png");
grid-column: 1; grid-column: 1;
& {
/* @load-async */
background-image: uiResource("icons/shop.png");
}
} }
&.stats { &.stats {
background-image: uiResource("icons/statistics.png");
grid-column: 2; grid-column: 2;
& {
/* @load-async */
background-image: uiResource("icons/statistics.png");
}
} }
&.save { &.save {
background-image: uiResource("icons/save.png"); & {
/* @load-async */
background-image: uiResource("icons/save.png");
}
grid-column: 3; grid-column: 3;
@include MakeAnimationWrappedEvenOdd(0.5s ease-in-out) { @include MakeAnimationWrappedEvenOdd(0.5s ease-in-out) {
0% { 0% {
@ -83,8 +92,11 @@
} }
&.settings { &.settings {
background-image: uiResource("icons/settings_menu_settings.png");
grid-column: 4; grid-column: 4;
& {
/* @load-async */
background-image: uiResource("icons/settings_menu_settings.png");
}
} }
&:hover { &:hover {
@ -99,9 +111,14 @@
&.hasBadge { &.hasBadge {
&.shop { &.shop {
filter: none; filter: none;
background-image: uiResource("icons/shop_active.png");
opacity: 0.9; opacity: 0.9;
& {
/* @load-async */
background-image: uiResource("icons/shop_active.png");
}
} }
transform-origin: 50% 50%; transform-origin: 50% 50%;
@include InlineAnimation(0.8s ease-in-out infinite) { @include InlineAnimation(0.8s ease-in-out infinite) {
50% { 50% {

View File

@ -47,10 +47,12 @@
left: unset; left: unset;
margin: 0; margin: 0;
&.rightMouse { &.rightMouse {
/* @load-async */
background: #fff uiResource("icons/mouse_right.png") center center / 85% no-repeat; background: #fff uiResource("icons/mouse_right.png") center center / 85% no-repeat;
} }
&.leftMouse { &.leftMouse {
/* @load-async */
background: #fff uiResource("icons/mouse_left.png") center center / 85% no-repeat; background: #fff uiResource("icons/mouse_left.png") center center / 85% no-repeat;
} }
} }

View File

@ -77,7 +77,6 @@
> .infoButton { > .infoButton {
@include S(width, 8px); @include S(width, 8px);
@include S(height, 8px); @include S(height, 8px);
background: uiResource("icons/info_button.png") center center / 95% no-repeat;
position: absolute; position: absolute;
opacity: 0.7; opacity: 0.7;
@include S(top, 13px); @include S(top, 13px);
@ -90,6 +89,11 @@
&:hover { &:hover {
opacity: 0.8; opacity: 0.8;
} }
& {
/* @load-async */
background: uiResource("icons/info_button.png") center center / 95% no-repeat;
}
} }
&.goal, &.goal,
@ -107,11 +111,13 @@
&.goal .amountLabel { &.goal .amountLabel {
&::after { &::after {
/* @load-async */
background-image: uiResource("icons/current_goal_marker.png"); background-image: uiResource("icons/current_goal_marker.png");
background-size: 90%; background-size: 90%;
} }
@include DarkThemeOverride { @include DarkThemeOverride {
&::after { &::after {
/* @load-async */
background-image: uiResource("icons/current_goal_marker_inverted.png") !important; background-image: uiResource("icons/current_goal_marker_inverted.png") !important;
} }
} }
@ -119,11 +125,13 @@
&.blueprint .amountLabel { &.blueprint .amountLabel {
&::after { &::after {
/* @load-async */
background-image: uiResource("icons/blueprint_marker.png"); background-image: uiResource("icons/blueprint_marker.png");
background-size: 90%; background-size: 90%;
} }
@include DarkThemeOverride { @include DarkThemeOverride {
&::after { &::after {
/* @load-async */
background-image: uiResource("icons/blueprint_marker_inverted.png") !important; background-image: uiResource("icons/blueprint_marker_inverted.png") !important;
} }
} }

View File

@ -39,23 +39,29 @@
background: transparent; background: transparent;
filter: invert(1); filter: invert(1);
background: uiResource("icons/settings_menu_play.png") center top / contain no-repeat;
content: ""; content: "";
opacity: 0.8; opacity: 0.8;
@include S(width, 35px); @include S(width, 35px);
@include S(height, 35px); @include S(height, 35px);
&.settings { &.settings {
/* @load-async */
background-image: uiResource("icons/settings_menu_settings.png"); background-image: uiResource("icons/settings_menu_settings.png");
} }
&.menu { &.menu {
/* @load-async */
background-image: uiResource("icons/settings_menu_exit.png"); background-image: uiResource("icons/settings_menu_exit.png");
} }
&:hover { &:hover {
opacity: 0.6; opacity: 0.6;
} }
& {
/* @load-async */
background: uiResource("icons/settings_menu_play.png") center top / contain no-repeat;
}
} }
} }
} }

View File

@ -113,9 +113,13 @@
overflow: hidden; overflow: hidden;
button.pin { button.pin {
& {
/* @load-async */
background: uiResource("icons/pin.png") center center / 95% no-repeat;
}
@include S(width, 12px); @include S(width, 12px);
@include S(height, 12px); @include S(height, 12px);
background: uiResource("icons/pin.png") center center / 95% no-repeat;
position: absolute; position: absolute;
@include S(top, 2px); @include S(top, 2px);
@include S(right, 2px); @include S(right, 2px);
@ -143,6 +147,7 @@
} }
&.isGoal { &.isGoal {
/* @load-async */
background: uiResource("icons/current_goal_marker.png") center center / 95% background: uiResource("icons/current_goal_marker.png") center center / 95%
no-repeat; no-repeat;
opacity: $disabledOpacity !important; opacity: $disabledOpacity !important;
@ -198,7 +203,6 @@
button.showInfo { button.showInfo {
@include S(width, 11px); @include S(width, 11px);
@include S(height, 11px); @include S(height, 11px);
background: uiResource("icons/info_button.png") center center / 95% no-repeat;
position: absolute; position: absolute;
@include S(top, 17px); @include S(top, 17px);
@include S(right, 2.5px); @include S(right, 2.5px);
@ -213,6 +217,10 @@
opacity: 0.6; opacity: 0.6;
} }
} }
button.showInfo {
/* @load-async */
background: uiResource("icons/info_button.png") center center / 95% no-repeat;
}
canvas { canvas {
@include S(width, 40px); @include S(width, 40px);

View File

@ -39,10 +39,12 @@
} }
&.displayDetailed { &.displayDetailed {
/* @load-async */
background-image: uiResource("icons/display_list.png"); background-image: uiResource("icons/display_list.png");
} }
&.displayIcons { &.displayIcons {
/* @load-async */
background-image: uiResource("icons/display_icons.png"); background-image: uiResource("icons/display_icons.png");
background-size: #{D(11.5px)}; background-size: #{D(11.5px)};
} }
@ -53,7 +55,10 @@
} }
&.displaySorted { &.displaySorted {
background-image: uiResource("icons/display_sorted.png"); & {
/* @load-async */
background-image: uiResource("icons/display_sorted.png");
}
background-size: #{D(11.5px)}; background-size: #{D(11.5px)};
margin-right: 5px; margin-right: 5px;
@include S(border-top-right-radius, $globalBorderRadius); @include S(border-top-right-radius, $globalBorderRadius);
@ -63,7 +68,10 @@
} }
&.displayIterateUnit { &.displayIterateUnit {
background-image: uiResource("icons/toggle_unit.png"); & {
/* @load-async */
background-image: uiResource("icons/toggle_unit.png");
}
opacity: 0.8; opacity: 0.8;
@include S(padding, 1px, 0); @include S(padding, 1px, 0);
} }

View File

@ -1,117 +1,120 @@
#ingame_HUD_TutorialHints { #ingame_HUD_TutorialHints {
position: absolute; position: absolute;
@include S(left, 10px); @include S(left, 10px);
@include S(bottom, 10px); @include S(bottom, 10px);
@include StyleBelowWidth(1430px) { @include StyleBelowWidth(1430px) {
@include S(bottom, 50px); @include S(bottom, 50px);
} }
display: flex; display: flex;
flex-direction: column; flex-direction: column;
background: rgba(50, 60, 70, 0); background: rgba(50, 60, 70, 0);
transition: all 0.2s ease-in-out; transition: all 0.2s ease-in-out;
pointer-events: all; pointer-events: all;
transition-property: background-color, transform, bottom, left; transition-property: background-color, transform, bottom, left;
@include S(padding, 5px); @include S(padding, 5px);
video { video {
transition: all 0.2s ease-in-out; transition: all 0.2s ease-in-out;
transition-property: opacity, width; transition-property: opacity, width;
@include S(width, 0px); @include S(width, 0px);
opacity: 0; opacity: 0;
z-index: 10; z-index: 10;
position: relative; position: relative;
} }
.header { .header {
color: #333438; color: #333438;
display: grid; display: grid;
align-items: center; align-items: center;
@include S(grid-gap, 2px); @include S(grid-gap, 2px);
grid-template-columns: 1fr; grid-template-columns: 1fr;
@include S(margin-bottom, 3px); @include S(margin-bottom, 3px);
z-index: 11; z-index: 11;
position: relative; position: relative;
> span { > span {
@include DarkThemeInvert; @include DarkThemeInvert;
display: flex; display: flex;
@include SuperSmallText; @include SuperSmallText;
justify-content: flex-start; justify-content: flex-start;
align-items: center; align-items: center;
&::before { &::before {
@include S(margin-right, 4px); @include S(margin-right, 4px);
content: " "; content: " ";
@include S(width, 12px); @include S(width, 12px);
@include S(height, 12px); @include S(height, 12px);
display: inline-block; display: inline-block;
background: uiResource("icons/help.png") center center / 95% no-repeat; & {
} /* @load-async */
} background: uiResource("icons/help.png") center center / 95% no-repeat;
}
button.toggleHint { }
@include PlainText; }
@include IncreasedClickArea(0px);
} button.toggleHint {
} @include PlainText;
@include IncreasedClickArea(0px);
button.toggleHint { }
.hide { }
display: none;
} button.toggleHint {
} .hide {
display: none;
&.enlarged { }
background: $ingameHudBg; }
left: 50%;
bottom: 50%; &.enlarged {
transform: translate(-50%, 50%); background: $ingameHudBg;
left: 50%;
&::before { bottom: 50%;
pointer-events: all; transform: translate(-50%, 50%);
content: " ";
position: fixed; &::before {
top: -1000px; pointer-events: all;
left: -1000px; content: " ";
right: -1000px; position: fixed;
bottom: -1000px; top: -1000px;
z-index: 0; left: -1000px;
right: -1000px;
background: rgba($ingameHudBg, 0.3); bottom: -1000px;
} z-index: 0;
.header { background: rgba($ingameHudBg, 0.3);
grid-template-columns: 1fr auto; }
> span {
display: none; .header {
} grid-template-columns: 1fr auto;
button.toggleHint { > span {
grid-column: 2 / 3; display: none;
} }
} button.toggleHint {
grid-column: 2 / 3;
video { }
@include InlineAnimation(0.2s ease-in-out) { }
0% {
opacity: 0; video {
@include S(width, 0px); @include InlineAnimation(0.2s ease-in-out) {
} 0% {
} opacity: 0;
@include S(width, 0px);
opacity: 1; }
@include S(width, 500px); }
}
button.toggleHint { opacity: 1;
.hide { @include S(width, 500px);
display: block; }
} button.toggleHint {
.show { .hide {
display: none; display: block;
} }
} .show {
} display: none;
} }
}
}
}

View File

@ -1,177 +1,181 @@
#ingame_HUD_UnlockNotification { #ingame_HUD_UnlockNotification {
position: absolute; position: absolute;
top: 0; top: 0;
left: 0; left: 0;
right: 0; right: 0;
bottom: 0; bottom: 0;
background: rgba(#333538, 0.98) uiResource("dialog_bg_pattern.png") top left / #{D(10px)} repeat; display: flex;
display: flex; justify-content: center;
justify-content: center; align-items: center;
align-items: center; pointer-events: all;
pointer-events: all;
& {
@include InlineAnimation(0.1s ease-in-out) { /* @load-async */
0% { background: rgba(#333538, 0.98) uiResource("dialog_bg_pattern.png") top left / #{D(10px)} repeat;
opacity: 0; }
}
} @include InlineAnimation(0.1s ease-in-out) {
0% {
.dialog { opacity: 0;
// background: rgba(#222428, 0.5); }
@include S(border-radius, $globalBorderRadius); }
@include S(padding, 30px);
.dialog {
@include InlineAnimation(0.5s ease-in-out) { // background: rgba(#222428, 0.5);
0% { @include S(border-radius, $globalBorderRadius);
opacity: 0; @include S(padding, 30px);
}
} @include InlineAnimation(0.5s ease-in-out) {
display: flex; 0% {
align-items: center; opacity: 0;
flex-direction: column; }
max-height: 100vh; }
display: flex;
color: #fff; align-items: center;
text-align: center; flex-direction: column;
.title, max-height: 100vh;
.subTitle {
@include SuperHeading; color: #fff;
text-transform: uppercase; text-align: center;
@include S(font-size, 40px); .title,
.subTitle {
@include InlineAnimation(0.5s ease-in-out) { @include SuperHeading;
0% { text-transform: uppercase;
transform: translateY(-50vh); @include S(font-size, 40px);
}
50% { @include InlineAnimation(0.5s ease-in-out) {
transform: translateY(5vh); 0% {
} transform: translateY(-50vh);
75% { }
transform: translateY(-2vh); 50% {
} transform: translateY(5vh);
} }
} 75% {
transform: translateY(-2vh);
.subTitle { }
@include PlainText; }
display: inline-block; }
@include S(margin, 5px, 0, 20px);
color: $colorGreenBright; .subTitle {
@include PlainText;
@include S(border-radius, $globalBorderRadius); display: inline-block;
@include InlineAnimation(0.5s ease-in-out) { @include S(margin, 5px, 0, 20px);
0% { color: $colorGreenBright;
transform: translateY(-60vh);
} @include S(border-radius, $globalBorderRadius);
50% { @include InlineAnimation(0.5s ease-in-out) {
transform: translateY(6vh); 0% {
} transform: translateY(-60vh);
75% { }
transform: translateY(-3vh); 50% {
} transform: translateY(6vh);
} }
} 75% {
transform: translateY(-3vh);
.contents { }
@include S(width, 400px); }
@include InlineAnimation(0.5s ease-in-out) { }
0% {
transform: translateX(-100vw); .contents {
} @include S(width, 400px);
50% { @include InlineAnimation(0.5s ease-in-out) {
transform: translateX(5vw); 0% {
} transform: translateX(-100vw);
}
75% { 50% {
transform: translateX(-2vw); transform: translateX(5vw);
} }
}
display: flex; 75% {
flex-direction: column; transform: translateX(-2vw);
align-items: center; }
justify-content: center; }
@include S(grid-gap, 10px); display: flex;
flex-direction: column;
.rewardName { align-items: center;
grid-column: 1 / 3; justify-content: center;
display: none; @include S(grid-gap, 10px);
@include InlineAnimation(0.5s ease-in-out) {
0% { .rewardName {
transform: translateX(200vw); grid-column: 1 / 3;
} display: none;
50% { @include InlineAnimation(0.5s ease-in-out) {
transform: translateX(-10vw); 0% {
} transform: translateX(200vw);
}
75% { 50% {
transform: translateX(4vw); transform: translateX(-10vw);
} }
}
} 75% {
transform: translateX(4vw);
.rewardDesc { }
grid-column: 1 / 3; }
@include PlainText; }
@include S(margin-bottom, 15px);
color: #aaacaf; .rewardDesc {
@include S(width, 400px); grid-column: 1 / 3;
text-align: left; @include PlainText;
strong { @include S(margin-bottom, 15px);
color: #fff; color: #aaacaf;
} @include S(width, 400px);
} text-align: left;
strong {
.images { color: #fff;
display: flex; }
.buildingExplanation { }
@include S(width, 200px);
@include S(height, 200px); .images {
display: inline-block; display: flex;
background-position: center center; .buildingExplanation {
background-size: cover; @include S(width, 200px);
background-repeat: no-repeat; @include S(height, 200px);
@include S(border-radius, $globalBorderRadius); display: inline-block;
box-shadow: #{D(2px)} #{D(3px)} 0 0 rgba(0, 0, 0, 0.15); background-position: center center;
} background-size: cover;
} background-repeat: no-repeat;
} @include S(border-radius, $globalBorderRadius);
box-shadow: #{D(2px)} #{D(3px)} 0 0 rgba(0, 0, 0, 0.15);
button.close { }
border: 0; }
position: relative; }
@include S(margin-top, 30px);
button.close {
&:not(.unlocked) { border: 0;
pointer-events: none; position: relative;
opacity: 0.8; @include S(margin-top, 30px);
cursor: default;
} &:not(.unlocked) {
pointer-events: none;
&.unlocked { opacity: 0.8;
&::after { cursor: default;
animation: none !important; }
}
} &.unlocked {
&::after {
&::after { animation: none !important;
content: " "; }
display: inline-block; }
position: absolute;
top: 0; &::after {
left: 100%; content: " ";
right: 0; display: inline-block;
bottom: 0; position: absolute;
background: rgba(0, 10, 20, 0.8); top: 0;
left: 100%;
@include InlineAnimation(5s linear) { right: 0;
0% { bottom: 0;
left: 0; background: rgba(0, 10, 20, 0.8);
}
100% { @include InlineAnimation(5s linear) {
left: 100%; 0% {
} left: 0;
} }
} 100% {
} left: 100%;
} }
} }
}
}
}
}

View File

@ -4,7 +4,10 @@
left: 0; left: 0;
right: 0; right: 0;
bottom: 0; bottom: 0;
background: uiResource("vignette.lossless.png") center center / cover no-repeat; & {
/* @load-async */
background: uiResource("vignette.lossless.png") center center / cover no-repeat;
}
pointer-events: none; pointer-events: none;
@include DarkThemeOverride { @include DarkThemeOverride {

View File

@ -1,18 +1,22 @@
#ingame_HUD_Watermark { #ingame_HUD_Watermark {
position: absolute; position: absolute;
background: uiResource("get_on_steam.png") center center / contain no-repeat; & {
@include S(width, 110px); /* @load-async */
@include S(height, 40px); background: uiResource("get_on_steam.png") center center / contain no-repeat;
@include S(top, 10px); }
pointer-events: all;
cursor: pointer; @include S(width, 110px);
@include S(left, 160px); @include S(height, 40px);
@include S(top, 10px);
transition: all 0.12s ease-in; pointer-events: all;
transition-property: opacity, transform; cursor: pointer;
transform: skewX(-0.5deg); @include S(left, 160px);
&:hover {
transform: skewX(-1deg) scale(1.02); transition: all 0.12s ease-in;
opacity: 0.9; transition-property: opacity, transform;
} transform: skewX(-0.5deg);
} &:hover {
transform: skewX(-1deg) scale(1.02);
opacity: 0.9;
}
}

View File

@ -39,6 +39,8 @@
overflow-y: auto; overflow-y: auto;
pointer-events: all; pointer-events: all;
@include S(padding-right, 5px); @include S(padding-right, 5px);
@include S(padding-bottom, 5px);
@include S(padding-top, 5px);
// Scrollbar // Scrollbar
&::-webkit-scrollbar { &::-webkit-scrollbar {
@ -55,7 +57,10 @@
display: grid; display: grid;
grid-template-columns: 1fr auto; grid-template-columns: 1fr auto;
align-items: center; align-items: center;
background: uiResource("icons/waypoint.png") left 50% / #{D(8px)} no-repeat; & {
/* @load-async */
background: uiResource("icons/waypoint.png") left 50% / #{D(8px)} no-repeat;
}
opacity: 0.7; opacity: 0.7;
@include S(margin-bottom, 1px); @include S(margin-bottom, 1px);
font-weight: bold; font-weight: bold;
@ -68,7 +73,10 @@
@include S(width, 10px); @include S(width, 10px);
@include S(height, 10px); @include S(height, 10px);
@include S(margin-left, 4px); @include S(margin-left, 4px);
background: uiResource("icons/edit_key.png") center center / 70% no-repeat; & {
/* @load-async */
background: uiResource("icons/edit_key.png") center center / 70% no-repeat;
}
pointer-events: all; pointer-events: all;
cursor: pointer; cursor: pointer;
position: relative; position: relative;

View File

@ -6,7 +6,7 @@
@return inline($pth); @return inline($pth);
} }
@import "icons"; @import "resources";
@import "trigonometry"; @import "trigonometry";
@import "material_colors"; @import "material_colors";
@import "dynamic_ui"; @import "dynamic_ui";

View File

@ -1,363 +1,316 @@
// ---------------------------------------- // ----------------------------------------
/* Forces an element to get rendered on its own layer, increasing /* Forces an element to get rendered on its own layer, increasing
the performance when animated. Use only transform and opacity in animations! */ the performance when animated. Use only transform and opacity in animations! */
@mixin FastAnimation { @mixin FastAnimation {
will-change: transform, opacity, filter; will-change: transform, opacity, filter;
// transform: translateZ(0); // transform: translateZ(0);
backface-visibility: hidden; backface-visibility: hidden;
-webkit-backface-visibility: hidden; -webkit-backface-visibility: hidden;
} }
// Helper which includes the translateZ webkit fix, use together with Fast animation // Helper which includes the translateZ webkit fix, use together with Fast animation
// $hardwareAcc: translateZ(0); // $hardwareAcc: translateZ(0);
$hardwareAcc: null; $hardwareAcc: null;
// ---------------------------------------- // ----------------------------------------
/** Increased click area for this element, helpful on mobile */ /** Increased click area for this element, helpful on mobile */
@mixin IncreasedClickArea($size) { @mixin IncreasedClickArea($size) {
&::after { &::after {
content: ""; content: "";
position: absolute; position: absolute;
top: #{D(-$size)}; top: #{D(-$size)};
bottom: #{D(-$size)}; bottom: #{D(-$size)};
left: #{D(-$size)}; left: #{D(-$size)};
right: #{D(-$size)}; right: #{D(-$size)};
// background: rgba(255, 0, 0, 0.3); // background: rgba(255, 0, 0, 0.3);
} }
} }
button, button,
.increasedClickArea { .increasedClickArea {
position: relative; position: relative;
@include IncreasedClickArea(15px); @include IncreasedClickArea(15px);
} }
// ---------------------------------------- // ----------------------------------------
/* Duplicates an animation and adds two classes .<classPrefix>Even and .<classPrefix>Odd which uses the /* Duplicates an animation and adds two classes .<classPrefix>Even and .<classPrefix>Odd which uses the
animation. This can be used to replay the animation by toggling between the classes, because animation. This can be used to replay the animation by toggling between the classes, because
it is not possible to restart a css animation */ it is not possible to restart a css animation */
@mixin MakeAnimationWrappedEvenOdd($duration, $classPrefix: "anim", $childSelector: "") { @mixin MakeAnimationWrappedEvenOdd($duration, $classPrefix: "anim", $childSelector: "") {
$animName: autogen_anim_#{unique-id()}; $animName: autogen_anim_#{unique-id()};
@at-root { @at-root {
@keyframes #{$animName}_even { @keyframes #{$animName}_even {
@content; @content;
} }
@keyframes #{$animName}_odd { @keyframes #{$animName}_odd {
@content; @content;
} }
} }
&.#{$classPrefix}Even #{$childSelector} { &.#{$classPrefix}Even #{$childSelector} {
animation: #{$animName}_even $duration; animation: #{$animName}_even $duration;
} }
&.#{$classPrefix}Odd #{$childSelector} { &.#{$classPrefix}Odd #{$childSelector} {
animation: #{$animName}_odd $duration; animation: #{$animName}_odd $duration;
} }
} }
// ---------------------------------------- // ----------------------------------------
/* Allows to use and define an animation without specifying its name */ /* Allows to use and define an animation without specifying its name */
@mixin InlineAnimation($duration) { @mixin InlineAnimation($duration) {
$animName: autogen_anim_#{unique-id()}; $animName: autogen_anim_#{unique-id()};
@at-root { @at-root {
@keyframes #{$animName} { @keyframes #{$animName} {
@content; @content;
} }
} }
animation: $animName $duration !important; animation: $animName $duration !important;
} }
// ---------------------------------------- // ----------------------------------------
/* Animation prefab for a double bounce pop-in animation, useful for dialogs */ /* Animation prefab for a double bounce pop-in animation, useful for dialogs */
@mixin DoubleBounceAnim($duration: 0.5s ease-in-out, $amount: 0.2, $initialOpacity: 0) { @mixin DoubleBounceAnim($duration: 0.5s ease-in-out, $amount: 0.2, $initialOpacity: 0) {
@include InlineAnimation($duration) { @include InlineAnimation($duration) {
0% { 0% {
opacity: $initialOpacity; opacity: $initialOpacity;
transform: scale(0) $hardwareAcc; transform: scale(0) $hardwareAcc;
} }
25% { 25% {
opacity: 0.5; opacity: 0.5;
transform: scale(1 + $amount) $hardwareAcc; transform: scale(1 + $amount) $hardwareAcc;
} }
50% { 50% {
opacity: 1; opacity: 1;
transform: scale(1 - $amount * 0.5) $hardwareAcc; transform: scale(1 - $amount * 0.5) $hardwareAcc;
} }
75% { 75% {
transform: scale(1 + $amount * 0.25) $hardwareAcc; transform: scale(1 + $amount * 0.25) $hardwareAcc;
} }
100% { 100% {
transform: scale(1) $hardwareAcc; transform: scale(1) $hardwareAcc;
} }
} }
opacity: 1; opacity: 1;
} }
// ---------------------------------------- // ----------------------------------------
/* Define a style which is only applied in horizontal mode */ /* Define a style which is only applied in horizontal mode */
@mixin HorizontalStyle { @mixin HorizontalStyle {
@include AppendGlobal(".h") { @include AppendGlobal(".h") {
@content; @content;
} }
} }
// ---------------------------------------- // ----------------------------------------
/* Define a style which is only applied in vertical mode */ /* Define a style which is only applied in vertical mode */
@mixin VerticalStyle { @mixin VerticalStyle {
@include AppendGlobal(".v") { @include AppendGlobal(".v") {
@content; @content;
} }
} }
// ---------------------------------------- // ----------------------------------------
/* Define a style which is only while the hardware keyboard is open */ /* Define a style which is only while the hardware keyboard is open */
@mixin AndroidHwKeyboardOpen { @mixin AndroidHwKeyboardOpen {
@include AppendGlobal(".kb") { @include AppendGlobal(".kb") {
@content; @content;
} }
} }
// ---------------------------------------- // ----------------------------------------
/* Automatically transforms the game state if a hardware keyboard is open */ /* Automatically transforms the game state if a hardware keyboard is open */
@mixin TransformToMatchKeyboard { @mixin TransformToMatchKeyboard {
transition: transform 0.2s ease-in-out; transition: transform 0.2s ease-in-out;
@include AndroidHwKeyboardOpen { @include AndroidHwKeyboardOpen {
@include VerticalStyle { @include VerticalStyle {
transform: translateY(#{D(-125px)}) $hardwareAcc; transform: translateY(#{D(-125px)}) $hardwareAcc;
} }
@include HorizontalStyle { @include HorizontalStyle {
transform: translateY(#{D(-100px)}) $hardwareAcc; transform: translateY(#{D(-100px)}) $hardwareAcc;
} }
} }
} }
// ---------------------------------------- // ----------------------------------------
/* Define a style which is only applied when the viewport is at least X pixels wide */ /* Define a style which is only applied when the viewport is at least X pixels wide */
@mixin StyleAtWidth($minW) { @mixin StyleAtWidth($minW) {
@media (min-width: #{$minW}) { @media (min-width: #{$minW}) {
@content; @content;
} }
} }
// ---------------------------------------- // ----------------------------------------
/* Define a style which is only applied when the viewport is at least X pixels height */ /* Define a style which is only applied when the viewport is at least X pixels height */
@mixin StyleAtHeight($minH) { @mixin StyleAtHeight($minH) {
@media (min-height: #{$minH}) { @media (min-height: #{$minH}) {
@content; @content;
} }
} }
// ---------------------------------------- // ----------------------------------------
/* Define a style which is only applied when the viewport has at least the given dimensions */ /* Define a style which is only applied when the viewport has at least the given dimensions */
@mixin StyleAtDims($minW, $minH) { @mixin StyleAtDims($minW, $minH) {
@media (min-height: #{$minH}) and (min-width: #{$minW}) { @media (min-height: #{$minH}) and (min-width: #{$minW}) {
@content; @content;
} }
} }
// ---------------------------------------- // ----------------------------------------
/* Define a style which is only applied when the viewport has at maximum the given dimensions */ /* Define a style which is only applied when the viewport has at maximum the given dimensions */
@mixin StyleBelowDims($maxW, $maxH) { @mixin StyleBelowDims($maxW, $maxH) {
@media (max-height: #{$maxH}) and (max-width: #{$maxW}) { @media (max-height: #{$maxH}) and (max-width: #{$maxW}) {
@content; @content;
} }
} }
// ---------------------------------------- // ----------------------------------------
/* Define a style which is only applied when the viewport has at maximum the given height */ /* Define a style which is only applied when the viewport has at maximum the given height */
@mixin StyleBelowHeight($maxH) { @mixin StyleBelowHeight($maxH) {
@media (max-height: #{$maxH}) { @media (max-height: #{$maxH}) {
@content; @content;
} }
} }
// ---------------------------------------- // ----------------------------------------
/* Define a style which is only applied when the viewport has at maximum the given width */ /* Define a style which is only applied when the viewport has at maximum the given width */
@mixin StyleBelowWidth($maxW) { @mixin StyleBelowWidth($maxW) {
@media (max-width: #{$maxW}) { @media (max-width: #{$maxW}) {
@content; @content;
} }
} }
// ---------------------------------------- // ----------------------------------------
// Dynamic graphics quality styles // Dynamic graphics quality styles
@mixin BoxShadow3D($bgColor, $size: 3px, $pressEffect: true) { @mixin BoxShadow3D($bgColor, $size: 3px, $pressEffect: true) {
background-color: $bgColor; background-color: $bgColor;
$borderSize: 1.5px; $borderSize: 1.5px;
$borderColor: rgb(18, 20, 24); $borderColor: rgb(18, 20, 24);
// box-shadow: 0 0 0 D($borderSize) $borderColor, 0 D($size) 0 0px rgba(mix(darken($bgColor, 9), #b0e2ff, 95%), 1), // box-shadow: 0 0 0 D($borderSize) $borderColor, 0 D($size) 0 0px rgba(mix(darken($bgColor, 9), #b0e2ff, 95%), 1),
// 0 D($size) 0 D($borderSize) $borderColor; // 0 D($size) 0 D($borderSize) $borderColor;
// box-shadow: 0 0 0 D($borderSize) $borderColor, 0 D($size) 0 D($borderSize) $borderColor, // box-shadow: 0 0 0 D($borderSize) $borderColor, 0 D($size) 0 D($borderSize) $borderColor,
// D(-$size * 1.5) D($size * 2) 0 D($borderSize) rgba(0, 0, 0, 0.1); // D(-$size * 1.5) D($size * 2) 0 D($borderSize) rgba(0, 0, 0, 0.1);
// transition: box-shadow 0.1s ease-in-out; // transition: box-shadow 0.1s ease-in-out;
// @if $pressEffect { // @if $pressEffect {
// &.pressed { // &.pressed {
// transform: none !important; // transform: none !important;
// $pSize: max(0, $size - 1.5px); // $pSize: max(0, $size - 1.5px);
// transition: none !important; // transition: none !important;
// box-shadow: 0 0 0 D($borderSize) $borderColor, 0 D($pSize) 0 0px rgba(mix(darken($bgColor, 9), #b0e2ff, 95%), 1), // box-shadow: 0 0 0 D($borderSize) $borderColor, 0 D($pSize) 0 0px rgba(mix(darken($bgColor, 9), #b0e2ff, 95%), 1),
// 0 D($pSize) 0 D($borderSize) $borderColor; // 0 D($pSize) 0 D($borderSize) $borderColor;
// top: D($size - $pSize); // top: D($size - $pSize);
// } // }
// } // }
} }
@mixin BorderRadius($v1: 2px, $v2: "", $v3: "", $v4: "") { @mixin BorderRadius($v1: 2px, $v2: "", $v3: "", $v4: "") {
@include S(border-radius, $v1, $v2, $v3, $v4); @include S(border-radius, $v1, $v2, $v3, $v4);
} }
@mixin BoxShadow($x, $y, $blur, $offset, $color) { @mixin BoxShadow($x, $y, $blur, $offset, $color) {
box-shadow: D($x) D($y) D($blur) D($offset) $color; box-shadow: D($x) D($y) D($blur) D($offset) $color;
} }
@mixin DropShadow($yOffset: 2px, $blur: 2px, $amount: 0.2) { @mixin DropShadow($yOffset: 2px, $blur: 2px, $amount: 0.2) {
@include BoxShadow(0, $yOffset, $blur, 0, rgba(#000, $amount)); @include BoxShadow(0, $yOffset, $blur, 0, rgba(#000, $amount));
} }
@mixin TextShadow($yOffset: 2px, $blur: 1px, $amount: 0.6) { @mixin TextShadow($yOffset: 2px, $blur: 1px, $amount: 0.6) {
text-shadow: 0 D($yOffset) D($blur) rgba(#000, $amount); text-shadow: 0 D($yOffset) D($blur) rgba(#000, $amount);
} }
@mixin Button3D($bgColor, $pressEffect: true) { @mixin Button3D($bgColor, $pressEffect: true) {
@include BoxShadow3D($bgColor, 2px, $pressEffect); @include BoxShadow3D($bgColor, 2px, $pressEffect);
} }
@mixin ButtonDisabled3D($bgColor) { @mixin ButtonDisabled3D($bgColor) {
@include BoxShadow3D($bgColor, 0.5px, false); @include BoxShadow3D($bgColor, 0.5px, false);
} }
@mixin BoxShadowInset($bgColor, $size: 3px) { @mixin BoxShadowInset($bgColor, $size: 3px) {
background-color: $bgColor; background-color: $bgColor;
$borderSize: 1px; $borderSize: 1px;
$borderColor: rgb(15, 19, 24); $borderColor: rgb(15, 19, 24);
box-shadow: 0 0 0 D($borderSize) $borderColor, 0 D($size) 0 rgba(#fff, 0.07); box-shadow: 0 0 0 D($borderSize) $borderColor, 0 D($size) 0 rgba(#fff, 0.07);
border-top: D($size) solid rgba(#000, 0.1); border-top: D($size) solid rgba(#000, 0.1);
//, 0 D($size) 0 0px rgba(mix(darken($bgColor, 9), #b0e2ff, 95%), 1), //, 0 D($size) 0 0px rgba(mix(darken($bgColor, 9), #b0e2ff, 95%), 1),
// 0 D($size + $borderSize) 0 0 $borderColor; // 0 D($size + $borderSize) 0 0 $borderColor;
} }
@mixin TextShadow3D($color: rgb(222, 234, 238), $borderColor: #000) { @mixin TextShadow3D($color: rgb(222, 234, 238), $borderColor: #000) {
color: $color; color: $color;
} }
// ---------------------------------------- // ----------------------------------------
/* Shine animation prefab, useful for buttons etc. Adds a bright shine which moves over /* String replacement */
the button like a reflection. Performance heavy. */ @function str-replace($string, $search, $replace: "") {
@mixin ShineAnimation($duration, $bgColor, $w: 200px, $shineAlpha: 0.25, $lightenAmount: 7, $bgAnim: true) { $index: str-index($string, $search);
$bgBase: darken($bgColor, 5);
background-color: $bgBase; @if $index {
@return str-slice($string, 1, $index - 1) + $replace +
@include HighQualityOrMore { str-replace(str-slice($string, $index + str-length($search)), $search, $replace);
position: relative; }
// overflow: hidden;
// overflow: visible; @return $string;
}
&:before {
content: " "; @mixin BounceInFromSide($mul, $duration: 0.18s ease-in-out) {
position: absolute; @include InlineAnimation($duration) {
top: 0; 0% {
left: 0; transform: translateY(#{D(-100px * $mul)}) scale(0.9);
right: 0; opacity: 0;
bottom: 0; }
background: uiResource("misc/shine_bg.png") 0px center / 100% 100% no-repeat;
100% {
@include InlineAnimation($duration ease-in-out infinite) { opacity: 1;
0% { transform: none;
background-position-x: #{D(-$w)}; }
} }
100% { opacity: 1;
background-position-x: #{D($w)}; transform: none;
} }
}
} @mixin BreakText {
word-wrap: break-word;
@if ($bgAnim) { word-break: break-all;
@include InlineAnimation($duration ease-in-out infinite) { overflow-wrap: break-all;
0% { }
background-color: $bgBase;
} @mixin SupportsAndroidNotchQuery {
50% { @supports (color: constant(--notch-inset-left)) {
background-color: lighten($bgBase, $lightenAmount); @content;
} }
100% { }
background-color: $bgBase; @mixin SupportsiOsNotchQuery {
} @supports (color: env(safe-area-inset-left, 0px)) {
} @content;
} }
} }
}
@mixin DarkThemeOverride {
// ---------------------------------------- @at-root html[data-theme="dark"] &,
/* String replacement */ &[data-theme="dark"] {
@function str-replace($string, $search, $replace: "") { @content;
$index: str-index($string, $search); }
}
@if $index {
@return str-slice($string, 1, $index - 1) + $replace + @mixin DarkThemeInvert {
str-replace(str-slice($string, $index + str-length($search)), $search, $replace); @include DarkThemeOverride {
} filter: invert(1);
}
@return $string; }
}
@mixin BounceInFromSide($mul, $duration: 0.18s ease-in-out) {
@include InlineAnimation($duration) {
0% {
transform: translateY(#{D(-100px * $mul)}) scale(0.9);
opacity: 0;
}
100% {
opacity: 1;
transform: none;
}
}
opacity: 1;
transform: none;
}
@mixin BreakText {
word-wrap: break-word;
word-break: break-all;
overflow-wrap: break-all;
}
@mixin SupportsAndroidNotchQuery {
@supports (color: constant(--notch-inset-left)) {
@content;
}
}
@mixin SupportsiOsNotchQuery {
@supports (color: env(safe-area-inset-left, 0px)) {
@content;
}
}
@mixin DarkThemeOverride {
@at-root html[data-theme="dark"] &,
&[data-theme="dark"] {
@content;
}
}
@mixin DarkThemeInvert {
@include DarkThemeOverride {
filter: invert(1);
}
}

View File

@ -1,17 +1,20 @@
$buildings: belt, cutter, miner, mixer, painter, rotater, balancer, stacker, trash, underground_belt, wire, $buildings: belt, cutter, miner, mixer, painter, rotater, balancer, stacker, trash, underground_belt, wire,
constant_signal, logic_gate, lever, filter, wire_tunnel, display, virtual_processor, reader; constant_signal, logic_gate, lever, filter, wire_tunnel, display, virtual_processor, reader, storage;
@each $building in $buildings { @each $building in $buildings {
[data-icon="building_icons/#{$building}.png"] { [data-icon="building_icons/#{$building}.png"] {
/* @load-async */
background-image: uiResource("res/ui/building_icons/#{$building}.png") !important; background-image: uiResource("res/ui/building_icons/#{$building}.png") !important;
} }
} }
$buildingsAndVariants: belt, balancer, balancer-merger, balancer-splitter, underground_belt, $buildingsAndVariants: belt, balancer, balancer-merger, balancer-splitter, underground_belt,
underground_belt-tier2, miner, miner-chainable, cutter, cutter-quad, rotater, rotater-ccw, rotater-fl, underground_belt-tier2, miner, miner-chainable, cutter, cutter-quad, rotater, rotater-ccw, stacker, mixer,
stacker, mixer, painter, painter-double, painter-quad, trash, trash-storage; painter, painter-double, painter-quad, trash, storage, reader, rotater-rotate180, lever, display,
constant_signal;
@each $building in $buildingsAndVariants { @each $building in $buildingsAndVariants {
[data-icon="building_tutorials/#{$building}.png"] { [data-icon="building_tutorials/#{$building}.png"] {
/* @load-async */
background-image: uiResource("res/ui/building_tutorials/#{$building}.png") !important; background-image: uiResource("res/ui/building_tutorials/#{$building}.png") !important;
} }
} }
@ -20,18 +23,26 @@ $buildingsAndVariants: belt, balancer, balancer-merger, balancer-splitter, under
// Special cases for mirrored vairants // Special cases for mirrored vairants
[data-icon="building_tutorials/painter-mirrored.png"] { [data-icon="building_tutorials/painter-mirrored.png"] {
/* @load-async */
background-image: uiResource("res/ui/building_tutorials/painter.png") !important; background-image: uiResource("res/ui/building_tutorials/painter.png") !important;
} }
[data-icon="building_tutorials/balancer-merger-inverse.png"] { [data-icon="building_tutorials/balancer-merger-inverse.png"] {
/* @load-async */
background-image: uiResource("res/ui/building_tutorials/balancer-merger.png") !important; background-image: uiResource("res/ui/building_tutorials/balancer-merger.png") !important;
} }
[data-icon="building_tutorials/balancer-splitter-inverse.png"] { [data-icon="building_tutorials/balancer-splitter-inverse.png"] {
/* @load-async */
background-image: uiResource("res/ui/building_tutorials/balancer-splitter.png") !important; background-image: uiResource("res/ui/building_tutorials/balancer-splitter.png") !important;
} }
[data-icon="building_tutorials/filter.png"] {
/* @load-async */
background-image: uiResource("res/ui/building_tutorials/lever.png") !important;
}
$icons: notification_saved, notification_success, notification_upgrade; $icons: notification_saved, notification_success, notification_upgrade;
@each $icon in $icons { @each $icon in $icons {
[data-icon="icons/#{$icon}.png"] { [data-icon="icons/#{$icon}.png"] {
/* @load-async */
background-image: uiResource("res/ui/icons/#{$icon}.png") !important; background-image: uiResource("res/ui/icons/#{$icon}.png") !important;
} }
} }
@ -41,6 +52,7 @@ $languages: en, de, cs, da, et, es-419, fr, it, pt-BR, sv, tr, el, ru, uk, zh-TW
@each $language in $languages { @each $language in $languages {
[data-languageicon="#{$language}"] { [data-languageicon="#{$language}"] {
/* @load-async */
background-image: uiResource("languages/#{$language}.svg") !important; background-image: uiResource("languages/#{$language}.svg") !important;
} }
} }

View File

@ -35,10 +35,12 @@
background: transparent center center / 40% no-repeat; background: transparent center center / 40% no-repeat;
opacity: 0.9; opacity: 0.9;
&.editKeybinding { &.editKeybinding {
/* @load-async */
background-image: uiResource("icons/edit_key.png"); background-image: uiResource("icons/edit_key.png");
} }
&.resetKeybinding { &.resetKeybinding {
/* @load-async */
background-image: uiResource("icons/reset_key.png"); background-image: uiResource("icons/reset_key.png");
} }

View File

@ -22,7 +22,10 @@
@include S(height, 25px); @include S(height, 25px);
pointer-events: all; pointer-events: all;
cursor: pointer; cursor: pointer;
background: uiResource("icons/main_menu_settings.png") center center / contain no-repeat; & {
/* @load-async */
background: uiResource("icons/main_menu_settings.png") center center / contain no-repeat;
}
transition: opacity 0.12s ease-in-out; transition: opacity 0.12s ease-in-out;
@include IncreasedClickArea(2px); @include IncreasedClickArea(2px);
opacity: 0.7; opacity: 0.7;
@ -32,6 +35,7 @@
} }
.exitAppButton { .exitAppButton {
/* @load-async */
background-image: uiResource("icons/main_menu_exit.png"); background-image: uiResource("icons/main_menu_exit.png");
background-size: 90%; background-size: 90%;
} }
@ -129,8 +133,10 @@
width: 100%; width: 100%;
@include S(height, 40px); @include S(height, 40px);
@include S(width, 180px); @include S(width, 180px);
& {
background: #171a23 uiResource("get_on_steam.png") center center / contain no-repeat; /* @load-async */
background: #171a23 uiResource("get_on_steam.png") center center / contain no-repeat;
}
overflow: hidden; overflow: hidden;
display: block; display: block;
text-indent: -999em; text-indent: -999em;
@ -167,7 +173,10 @@
@include S(margin, 10px, 0); @include S(margin, 10px, 0);
@include S(width, 100px); @include S(width, 100px);
@include S(height, 30px); @include S(height, 30px);
background: uiResource("demo_badge.png") center center / contain no-repeat; & {
/* @load-async */
background: uiResource("demo_badge.png") center center / contain no-repeat;
}
display: inline-block; display: inline-block;
} }
@ -335,14 +344,26 @@
align-self: center; align-self: center;
justify-self: center; justify-self: center;
@include IncreasedClickArea(0px); @include IncreasedClickArea(0px);
background: #44484a uiResource("icons/play.png") center center / 40% no-repeat; background: #44484a center center / 40% no-repeat;
}
button.resumeGame {
background-color: #44484a;
& {
/* @load-async */
background-image: uiResource("icons/play.png");
}
} }
button.downloadGame { button.downloadGame {
grid-column: 3 / 4; grid-column: 3 / 4;
grid-row: 1 / 2; grid-row: 1 / 2;
background-color: transparent; background-color: transparent;
background-image: uiResource("icons/download.png");
& {
/* @load-async */
background-image: uiResource("icons/download.png");
}
@include S(width, 15px); @include S(width, 15px);
@include IncreasedClickArea(0px); @include IncreasedClickArea(0px);
@include S(height, 15px); @include S(height, 15px);
@ -362,7 +383,11 @@
grid-row: 2 / 3; grid-row: 2 / 3;
background-color: transparent; background-color: transparent;
@include IncreasedClickArea(0px); @include IncreasedClickArea(0px);
background-image: uiResource("icons/delete.png");
& {
/* @load-async */
background-image: uiResource("icons/delete.png");
}
@include S(width, 15px); @include S(width, 15px);
@include S(height, 15px); @include S(height, 15px);
align-self: end; align-self: end;
@ -379,7 +404,11 @@
button.renameGame { button.renameGame {
background-color: transparent; background-color: transparent;
@include IncreasedClickArea(2px); @include IncreasedClickArea(2px);
background-image: uiResource("icons/edit_key.png");
& {
/* @load-async */
background-image: uiResource("icons/edit_key.png");
}
@include S(width, 10px); @include S(width, 10px);
@include S(height, 10px); @include S(height, 10px);
align-self: center; align-self: center;
@ -445,7 +474,11 @@
grid-template-columns: 1fr auto; grid-template-columns: 1fr auto;
justify-content: center; justify-content: center;
background: $linkBg uiResource("icons/link.png") top D(3px) right D(3px) / D(9px) no-repeat;
& {
/* @load-async */
background: $linkBg uiResource("icons/link.png") top D(3px) right D(3px) / D(9px) no-repeat;
}
@include S(padding, 5px); @include S(padding, 5px);
@include S(padding-left, 10px); @include S(padding-left, 10px);
@include S(border-radius, $globalBorderRadius); @include S(border-radius, $globalBorderRadius);
@ -472,9 +505,11 @@
@include S(height, 50px); @include S(height, 50px);
background: center center / 80% no-repeat; background: center center / 80% no-repeat;
&.githubLogo { &.githubLogo {
/* @load-async */
background-image: uiResource("main_menu/github.png"); background-image: uiResource("main_menu/github.png");
} }
&.discordLogo { &.discordLogo {
/* @load-async */
background-image: uiResource("main_menu/discord.png"); background-image: uiResource("main_menu/discord.png");
background-size: 95%; background-size: 95%;
} }
@ -516,12 +551,15 @@
transition: background-color 0.12s ease-in-out; transition: background-color 0.12s ease-in-out;
&.redditLink { &.redditLink {
/* @load-async */
background-image: uiResource("main_menu/reddit.svg"); background-image: uiResource("main_menu/reddit.svg");
} }
&.changelog { &.changelog {
/* @load-async */
background-image: uiResource("main_menu/changelog.svg"); background-image: uiResource("main_menu/changelog.svg");
} }
&.helpTranslate { &.helpTranslate {
/* @load-async */
background-image: uiResource("main_menu/translate.svg"); background-image: uiResource("main_menu/translate.svg");
} }
} }

View File

@ -1,48 +1,51 @@
#state_MobileWarningState { #state_MobileWarningState {
display: flex; display: flex;
align-items: center; align-items: center;
background: #333438 !important; background: #333438 !important;
@include S(padding, 20px); @include S(padding, 20px);
box-sizing: border-box; box-sizing: border-box;
justify-content: center; justify-content: center;
flex-direction: column; flex-direction: column;
.logo { .logo {
width: 80%; width: 80%;
max-width: 200px; max-width: 200px;
margin-bottom: 10px; margin-bottom: 10px;
} }
p { p {
color: #aaacaf; color: #aaacaf;
display: block; display: block;
margin-bottom: 13px; margin-bottom: 13px;
font-size: 16px; font-size: 16px;
line-height: 20px; line-height: 20px;
max-width: 300px; max-width: 300px;
text-align: left; text-align: left;
a { a {
color: $colorBlueBright; color: $colorBlueBright;
} }
} }
.standaloneLink { .standaloneLink {
width: 200px; width: 200px;
height: 80px; height: 80px;
min-height: 40px; min-height: 40px;
background: uiResource("get_on_steam.png") center center / contain no-repeat; & {
overflow: hidden; /* @load-async */
display: block; background: uiResource("get_on_steam.png") center center / contain no-repeat;
text-indent: -999em; }
cursor: pointer; overflow: hidden;
margin-top: 10px; display: block;
pointer-events: all; text-indent: -999em;
transition: all 0.12s ease-in; cursor: pointer;
transition-property: opacity, transform; margin-top: 10px;
transform: skewX(-0.5deg); pointer-events: all;
&:hover { transition: all 0.12s ease-in;
transform: skewX(-1deg) scale(1.02); transition-property: opacity, transform;
opacity: 0.9; transform: skewX(-0.5deg);
} &:hover {
} transform: skewX(-1deg) scale(1.02);
} opacity: 0.9;
}
}
}

View File

@ -11,6 +11,7 @@
@include StyleBelowWidth($layoutBreak) { @include StyleBelowWidth($layoutBreak) {
grid-template-columns: 1fr; grid-template-columns: 1fr;
grid-template-rows: auto 1fr;
} }
.sidebar { .sidebar {
@ -159,8 +160,11 @@
@include S(padding, 4px); @include S(padding, 4px);
@include S(padding-right, 15px); @include S(padding-right, 15px);
background: #fff uiResource("icons/enum_selector.png") calc(100% - #{D(5px)}) & {
calc(50% + #{D(1px)}) / #{D(15px)} no-repeat; /* @load-async */
background: #fff uiResource("icons/enum_selector.png") calc(100% - #{D(5px)})
calc(50% + #{D(1px)}) / #{D(15px)} no-repeat;
}
transition: background-color 0.12s ease-in-out; transition: background-color 0.12s ease-in-out;
&:hover { &:hover {
@ -196,7 +200,11 @@
// dirty but works // dirty but works
// color: #222; // color: #222;
background-color: $darkModeControlsBackground; background-color: $darkModeControlsBackground;
background-image: uiResource("icons/enum_selector_white.png");
& {
/* @load-async */
background-image: uiResource("icons/enum_selector_white.png");
}
color: #ddd; color: #ddd;
&:hover { &:hover {
background-color: darken($darkModeControlsBackground, 2); background-color: darken($darkModeControlsBackground, 2);

View File

@ -26,9 +26,11 @@
@include S(height, 30px); @include S(height, 30px);
@include S(margin-right, 10px); @include S(margin-right, 10px);
@include S(margin-left, -5px); @include S(margin-left, -5px);
background: uiResource("icons/state_back_button.png") center center / 70% no-repeat; & {
/* @load-async */
background: uiResource("icons/state_back_button.png") center center / 70% no-repeat;
}
} }
@include S(margin-bottom, 20px); @include S(margin-bottom, 20px);
} }

View File

@ -31,6 +31,7 @@ export const CHANGELOG = [
"Show mouse and camera tile on debug overlay (F4) (by dengr)", "Show mouse and camera tile on debug overlay (F4) (by dengr)",
"Fix belt planner placing the belt when a dialog opens in the meantime", "Fix belt planner placing the belt when a dialog opens in the meantime",
"Added confirmation when deleting a savegame", "Added confirmation when deleting a savegame",
"Make chained mainer the default and only option after unlocking it",
"Fixed tunnels entrances connecting to exits sometimes when they shouldn't", "Fixed tunnels entrances connecting to exits sometimes when they shouldn't",
"You can now pan the map with your mouse by moving the cursor to the edges of the screen!", "You can now pan the map with your mouse by moving the cursor to the edges of the screen!",
"Added setting to auto select the extractor when pipetting a resource patch (by Exund)", "Added setting to auto select the extractor when pipetting a resource patch (by Exund)",

View File

@ -65,13 +65,13 @@ export const globalConfig = {
buildingSpeeds: { buildingSpeeds: {
cutter: 1 / 4, cutter: 1 / 4,
cutterQuad: 1 / 4, cutterQuad: 1 / 3,
rotater: 1 / 1, rotater: 1 / 1,
rotaterCCW: 1 / 1, rotaterCCW: 1 / 1,
rotater180: 1 / 1, rotater180: 1 / 1,
painter: 1 / 6, painter: 1 / 6,
painterDouble: 1 / 8, painterDouble: 1 / 8,
painterQuad: 1 / 8, painterQuad: 1 / 2,
mixer: 1 / 5, mixer: 1 / 5,
stacker: 1 / 6, stacker: 1 / 6,
}, },

View File

@ -7,7 +7,7 @@ import { MetaBuilding, defaultBuildingVariant } from "../meta_building";
import { GameRoot } from "../root"; import { GameRoot } from "../root";
import { enumHubGoalRewards } from "../tutorial_goals"; import { enumHubGoalRewards } from "../tutorial_goals";
import { T } from "../../translations"; import { T } from "../../translations";
import { formatItemsPerSecond } from "../../core/utils"; import { formatItemsPerSecond, generateMatrixRotations } from "../../core/utils";
import { BeltUnderlaysComponent } from "../components/belt_underlays"; import { BeltUnderlaysComponent } from "../components/belt_underlays";
/** @enum {string} */ /** @enum {string} */
@ -18,6 +18,14 @@ export const enumBalancerVariants = {
splitterInverse: "splitter-inverse", splitterInverse: "splitter-inverse",
}; };
const overlayMatrices = {
[defaultBuildingVariant]: null,
[enumBalancerVariants.merger]: generateMatrixRotations([0, 1, 0, 0, 1, 1, 0, 1, 0]),
[enumBalancerVariants.mergerInverse]: generateMatrixRotations([0, 1, 0, 1, 1, 0, 0, 1, 0]),
[enumBalancerVariants.splitter]: generateMatrixRotations([0, 1, 0, 0, 1, 1, 0, 1, 0]),
[enumBalancerVariants.splitterInverse]: generateMatrixRotations([0, 1, 0, 1, 1, 0, 0, 1, 0]),
};
export class MetaBalancerBuilding extends MetaBuilding { export class MetaBalancerBuilding extends MetaBuilding {
constructor() { constructor() {
super("balancer"); super("balancer");
@ -37,18 +45,43 @@ export class MetaBalancerBuilding extends MetaBuilding {
} }
} }
/**
* @param {number} rotation
* @param {number} rotationVariant
* @param {string} variant
* @param {Entity} entity
* @returns {Array<number>|null}
*/
getSpecialOverlayRenderMatrix(rotation, rotationVariant, variant, entity) {
const matrix = overlayMatrices[variant];
if (matrix) {
return matrix[rotation];
}
return null;
}
/** /**
* @param {GameRoot} root * @param {GameRoot} root
* @param {string} variant * @param {string} variant
* @returns {Array<[string, string]>} * @returns {Array<[string, string]>}
*/ */
getAdditionalStatistics(root, variant) { getAdditionalStatistics(root, variant) {
const speed = root.hubGoals.getProcessorBaseSpeed(enumItemProcessorTypes.balancer); let speedMultiplier = 2;
switch (variant) {
case enumBalancerVariants.merger:
case enumBalancerVariants.mergerInverse:
case enumBalancerVariants.splitter:
case enumBalancerVariants.splitterInverse:
speedMultiplier = 1;
}
const speed =
(root.hubGoals.getProcessorBaseSpeed(enumItemProcessorTypes.balancer) / 2) * speedMultiplier;
return [[T.ingame.buildingPlacement.infoTexts.speed, formatItemsPerSecond(speed)]]; return [[T.ingame.buildingPlacement.infoTexts.speed, formatItemsPerSecond(speed)]];
} }
getSilhouetteColor() { getSilhouetteColor() {
return "#444"; return "#555759";
} }
/** /**

View File

@ -1,51 +1,51 @@
import { enumDirection, Vector } from "../../core/vector"; import { enumDirection, Vector } from "../../core/vector";
import { enumPinSlotType, WiredPinsComponent } from "../components/wired_pins"; import { enumPinSlotType, WiredPinsComponent } from "../components/wired_pins";
import { Entity } from "../entity"; import { Entity } from "../entity";
import { MetaBuilding } from "../meta_building"; import { MetaBuilding } from "../meta_building";
import { GameRoot } from "../root"; import { GameRoot } from "../root";
import { DisplayComponent } from "../components/display"; import { DisplayComponent } from "../components/display";
import { enumHubGoalRewards } from "../tutorial_goals";
export class MetaDisplayBuilding extends MetaBuilding {
constructor() { export class MetaDisplayBuilding extends MetaBuilding {
super("display"); constructor() {
} super("display");
}
getSilhouetteColor() {
return "#aaaaaa"; getSilhouetteColor() {
} return "#aaaaaa";
}
/**
* @param {GameRoot} root /**
*/ * @param {GameRoot} root
getIsUnlocked(root) { */
// @todo getIsUnlocked(root) {
return true; return root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_display);
} }
getDimensions() { getDimensions() {
return new Vector(1, 1); return new Vector(1, 1);
} }
getShowWiresLayerPreview() { getShowWiresLayerPreview() {
return true; return true;
} }
/** /**
* Creates the entity at the given location * Creates the entity at the given location
* @param {Entity} entity * @param {Entity} entity
*/ */
setupEntityComponents(entity) { setupEntityComponents(entity) {
entity.addComponent( entity.addComponent(
new WiredPinsComponent({ new WiredPinsComponent({
slots: [ slots: [
{ {
pos: new Vector(0, 0), pos: new Vector(0, 0),
direction: enumDirection.bottom, direction: enumDirection.bottom,
type: enumPinSlotType.logicalAcceptor, type: enumPinSlotType.logicalAcceptor,
}, },
], ],
}) })
); );
entity.addComponent(new DisplayComponent()); entity.addComponent(new DisplayComponent());
} }
} }

View File

@ -6,6 +6,7 @@ import { enumPinSlotType, WiredPinsComponent } from "../components/wired_pins";
import { Entity } from "../entity"; import { Entity } from "../entity";
import { MetaBuilding } from "../meta_building"; import { MetaBuilding } from "../meta_building";
import { GameRoot } from "../root"; import { GameRoot } from "../root";
import { enumHubGoalRewards } from "../tutorial_goals";
export class MetaFilterBuilding extends MetaBuilding { export class MetaFilterBuilding extends MetaBuilding {
constructor() { constructor() {
@ -20,8 +21,7 @@ export class MetaFilterBuilding extends MetaBuilding {
* @param {GameRoot} root * @param {GameRoot} root
*/ */
getIsUnlocked(root) { getIsUnlocked(root) {
// @todo return root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_wires_filters_and_levers);
return true;
} }
getDimensions() { getDimensions() {

View File

@ -4,6 +4,7 @@ import { Entity } from "../entity";
import { MetaBuilding } from "../meta_building"; import { MetaBuilding } from "../meta_building";
import { GameRoot } from "../root"; import { GameRoot } from "../root";
import { LeverComponent } from "../components/lever"; import { LeverComponent } from "../components/lever";
import { enumHubGoalRewards } from "../tutorial_goals";
export class MetaLeverBuilding extends MetaBuilding { export class MetaLeverBuilding extends MetaBuilding {
constructor() { constructor() {
@ -19,8 +20,7 @@ export class MetaLeverBuilding extends MetaBuilding {
* @param {GameRoot} root * @param {GameRoot} root
*/ */
getIsUnlocked(root) { getIsUnlocked(root) {
// @todo return root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_wires_filters_and_levers);
return true;
} }
getDimensions() { getDimensions() {

View File

@ -1,78 +1,81 @@
import { enumDirection, Vector } from "../../core/vector"; import { enumDirection, Vector } from "../../core/vector";
import { ItemEjectorComponent } from "../components/item_ejector"; import { ItemEjectorComponent } from "../components/item_ejector";
import { MinerComponent } from "../components/miner"; import { MinerComponent } from "../components/miner";
import { Entity } from "../entity"; import { Entity } from "../entity";
import { MetaBuilding, defaultBuildingVariant } from "../meta_building"; import { MetaBuilding, defaultBuildingVariant } from "../meta_building";
import { GameRoot } from "../root"; import { GameRoot } from "../root";
import { enumHubGoalRewards } from "../tutorial_goals"; import { enumHubGoalRewards } from "../tutorial_goals";
import { T } from "../../translations"; import { T } from "../../translations";
import { formatItemsPerSecond } from "../../core/utils"; import { formatItemsPerSecond, generateMatrixRotations } from "../../core/utils";
/** @enum {string} */ /** @enum {string} */
export const enumMinerVariants = { chainable: "chainable" }; export const enumMinerVariants = { chainable: "chainable" };
const overlayMatrix = [1, 1, 1, 1, 0, 1, 1, 1, 1]; const overlayMatrix = {
[defaultBuildingVariant]: generateMatrixRotations([1, 1, 1, 1, 0, 1, 1, 1, 1]),
export class MetaMinerBuilding extends MetaBuilding { [enumMinerVariants.chainable]: generateMatrixRotations([0, 1, 0, 1, 1, 1, 1, 1, 1]),
constructor() { };
super("miner");
} export class MetaMinerBuilding extends MetaBuilding {
constructor() {
getSilhouetteColor() { super("miner");
return "#b37dcd"; }
}
getSilhouetteColor() {
/** return "#b37dcd";
* @param {GameRoot} root }
* @param {string} variant
* @returns {Array<[string, string]>} /**
*/ * @param {GameRoot} root
getAdditionalStatistics(root, variant) { * @param {string} variant
const speed = root.hubGoals.getMinerBaseSpeed(); * @returns {Array<[string, string]>}
return [[T.ingame.buildingPlacement.infoTexts.speed, formatItemsPerSecond(speed)]]; */
} getAdditionalStatistics(root, variant) {
const speed = root.hubGoals.getMinerBaseSpeed();
/** return [[T.ingame.buildingPlacement.infoTexts.speed, formatItemsPerSecond(speed)]];
* }
* @param {GameRoot} root
*/ /**
getAvailableVariants(root) { *
if (root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_miner_chainable)) { * @param {GameRoot} root
return [defaultBuildingVariant, enumMinerVariants.chainable]; */
} getAvailableVariants(root) {
return super.getAvailableVariants(root); if (root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_miner_chainable)) {
} return [enumMinerVariants.chainable];
}
/** return super.getAvailableVariants(root);
* @param {number} rotation }
* @param {number} rotationVariant
* @param {string} variant /**
* @param {Entity} entity * @param {number} rotation
*/ * @param {number} rotationVariant
getSpecialOverlayRenderMatrix(rotation, rotationVariant, variant, entity) { * @param {string} variant
return overlayMatrix; * @param {Entity} entity
} */
getSpecialOverlayRenderMatrix(rotation, rotationVariant, variant, entity) {
/** return overlayMatrix[variant][rotation];
* Creates the entity at the given location }
* @param {Entity} entity
*/ /**
setupEntityComponents(entity) { * Creates the entity at the given location
entity.addComponent(new MinerComponent({})); * @param {Entity} entity
entity.addComponent( */
new ItemEjectorComponent({ setupEntityComponents(entity) {
slots: [{ pos: new Vector(0, 0), direction: enumDirection.top }], entity.addComponent(new MinerComponent({}));
}) entity.addComponent(
); new ItemEjectorComponent({
} slots: [{ pos: new Vector(0, 0), direction: enumDirection.top }],
})
/** );
* }
* @param {Entity} entity
* @param {number} rotationVariant /**
* @param {string} variant *
*/ * @param {Entity} entity
updateVariants(entity, rotationVariant, variant) { * @param {number} rotationVariant
entity.components.Miner.chainable = variant === enumMinerVariants.chainable; * @param {string} variant
} */
} updateVariants(entity, rotationVariant, variant) {
entity.components.Miner.chainable = variant === enumMinerVariants.chainable;
}
}

View File

@ -8,6 +8,10 @@ import { MetaBuilding } from "../meta_building";
import { GameRoot } from "../root"; import { GameRoot } from "../root";
import { BeltUnderlaysComponent } from "../components/belt_underlays"; import { BeltUnderlaysComponent } from "../components/belt_underlays";
import { BeltReaderComponent } from "../components/belt_reader"; import { BeltReaderComponent } from "../components/belt_reader";
import { enumHubGoalRewards } from "../tutorial_goals";
import { generateMatrixRotations } from "../../core/utils";
const overlayMatrix = generateMatrixRotations([0, 1, 0, 0, 1, 0, 0, 1, 0]);
export class MetaReaderBuilding extends MetaBuilding { export class MetaReaderBuilding extends MetaBuilding {
constructor() { constructor() {
@ -22,8 +26,7 @@ export class MetaReaderBuilding extends MetaBuilding {
* @param {GameRoot} root * @param {GameRoot} root
*/ */
getIsUnlocked(root) { getIsUnlocked(root) {
// @todo return root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_belt_reader);
return true;
} }
getDimensions() { getDimensions() {
@ -34,6 +37,17 @@ export class MetaReaderBuilding extends MetaBuilding {
return true; return true;
} }
/**
* @param {number} rotation
* @param {number} rotationVariant
* @param {string} variant
* @param {Entity} entity
* @returns {Array<number>|null}
*/
getSpecialOverlayRenderMatrix(rotation, rotationVariant, variant, entity) {
return overlayMatrix[rotation];
}
/** /**
* Creates the entity at the given location * Creates the entity at the given location
* @param {Entity} entity * @param {Entity} entity

View File

@ -1,4 +1,4 @@
import { formatItemsPerSecond } from "../../core/utils"; import { formatItemsPerSecond, generateMatrixRotations } from "../../core/utils";
import { enumDirection, Vector } from "../../core/vector"; import { enumDirection, Vector } from "../../core/vector";
import { T } from "../../translations"; import { T } from "../../translations";
import { ItemAcceptorComponent } from "../components/item_acceptor"; import { ItemAcceptorComponent } from "../components/item_acceptor";
@ -12,6 +12,12 @@ import { enumHubGoalRewards } from "../tutorial_goals";
/** @enum {string} */ /** @enum {string} */
export const enumRotaterVariants = { ccw: "ccw", rotate180: "rotate180" }; export const enumRotaterVariants = { ccw: "ccw", rotate180: "rotate180" };
const overlayMatrices = {
[defaultBuildingVariant]: generateMatrixRotations([0, 1, 1, 1, 1, 0, 0, 1, 1]),
[enumRotaterVariants.ccw]: generateMatrixRotations([1, 1, 0, 0, 1, 1, 1, 1, 0]),
[enumRotaterVariants.rotate180]: generateMatrixRotations([1, 1, 0, 1, 1, 1, 0, 1, 1]),
};
export class MetaRotaterBuilding extends MetaBuilding { export class MetaRotaterBuilding extends MetaBuilding {
constructor() { constructor() {
super("rotater"); super("rotater");
@ -21,6 +27,21 @@ export class MetaRotaterBuilding extends MetaBuilding {
return "#7dc6cd"; return "#7dc6cd";
} }
/**
* @param {number} rotation
* @param {number} rotationVariant
* @param {string} variant
* @param {Entity} entity
* @returns {Array<number>|null}
*/
getSpecialOverlayRenderMatrix(rotation, rotationVariant, variant, entity) {
const matrix = overlayMatrices[variant];
if (matrix) {
return matrix[rotation];
}
return null;
}
/** /**
* @param {GameRoot} root * @param {GameRoot} root
* @param {string} variant * @param {string} variant

View File

@ -0,0 +1,101 @@
import { formatBigNumber } from "../../core/utils";
import { enumDirection, Vector } from "../../core/vector";
import { T } from "../../translations";
import { ItemAcceptorComponent } from "../components/item_acceptor";
import { ItemEjectorComponent } from "../components/item_ejector";
import { StorageComponent } from "../components/storage";
import { enumPinSlotType, WiredPinsComponent } from "../components/wired_pins";
import { Entity } from "../entity";
import { MetaBuilding } from "../meta_building";
import { GameRoot } from "../root";
import { enumHubGoalRewards } from "../tutorial_goals";
const storageSize = 5000;
export class MetaStorageBuilding extends MetaBuilding {
constructor() {
super("storage");
}
getSilhouetteColor() {
return "#bbdf6d";
}
/**
* @returns {Array<[string, string]>}
*/
getAdditionalStatistics(root, variant) {
return [[T.ingame.buildingPlacement.infoTexts.storage, formatBigNumber(storageSize)]];
}
getDimensions() {
return new Vector(2, 2);
}
/**
* @param {GameRoot} root
*/
getIsUnlocked(root) {
return root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_storage);
}
/**
* Creates the entity at the given location
* @param {Entity} entity
*/
setupEntityComponents(entity) {
// Required, since the item processor needs this.
entity.addComponent(
new ItemEjectorComponent({
slots: [
{
pos: new Vector(0, 0),
direction: enumDirection.top,
},
{
pos: new Vector(1, 0),
direction: enumDirection.top,
},
],
})
);
entity.addComponent(
new ItemAcceptorComponent({
slots: [
{
pos: new Vector(0, 1),
directions: [enumDirection.bottom],
},
{
pos: new Vector(1, 1),
directions: [enumDirection.bottom],
},
],
})
);
entity.addComponent(
new StorageComponent({
maximumStorage: storageSize,
})
);
entity.addComponent(
new WiredPinsComponent({
slots: [
{
pos: new Vector(1, 1),
direction: enumDirection.right,
type: enumPinSlotType.logicalEjector,
},
{
pos: new Vector(0, 1),
direction: enumDirection.left,
type: enumPinSlotType.logicalEjector,
},
],
})
);
}
}

View File

@ -1,65 +1,26 @@
import { formatBigNumber } from "../../core/utils";
import { enumDirection, Vector } from "../../core/vector"; import { enumDirection, Vector } from "../../core/vector";
import { T } from "../../translations";
import { ItemAcceptorComponent } from "../components/item_acceptor"; import { ItemAcceptorComponent } from "../components/item_acceptor";
import { ItemEjectorComponent } from "../components/item_ejector";
import { enumItemProcessorTypes, ItemProcessorComponent } from "../components/item_processor"; import { enumItemProcessorTypes, ItemProcessorComponent } from "../components/item_processor";
import { StorageComponent } from "../components/storage";
import { enumPinSlotType, WiredPinsComponent } from "../components/wired_pins";
import { Entity } from "../entity"; import { Entity } from "../entity";
import { defaultBuildingVariant, MetaBuilding } from "../meta_building"; import { MetaBuilding } from "../meta_building";
import { GameRoot } from "../root"; import { GameRoot } from "../root";
import { enumHubGoalRewards } from "../tutorial_goals"; import { enumHubGoalRewards } from "../tutorial_goals";
/** @enum {string} */
export const enumTrashVariants = { storage: "storage" };
const trashSize = 5000;
export class MetaTrashBuilding extends MetaBuilding { export class MetaTrashBuilding extends MetaBuilding {
constructor() { constructor() {
super("trash"); super("trash");
} }
getIsRotateable(variant) { getIsRotateable() {
return variant !== defaultBuildingVariant; return false;
} }
getSilhouetteColor() { getSilhouetteColor() {
return "#cd7d86"; return "#cd7d86";
} }
/** getDimensions() {
* @param {GameRoot} root return new Vector(1, 1);
* @param {string} variant
* @returns {Array<[string, string]>}
*/
getAdditionalStatistics(root, variant) {
if (variant === enumTrashVariants.storage) {
return [[T.ingame.buildingPlacement.infoTexts.storage, formatBigNumber(trashSize)]];
}
return [];
}
getDimensions(variant) {
switch (variant) {
case defaultBuildingVariant:
return new Vector(1, 1);
case enumTrashVariants.storage:
return new Vector(2, 2);
default:
assertAlways(false, "Unknown trash variant: " + variant);
}
}
/**
* @param {GameRoot} root
*/
getAvailableVariants(root) {
if (root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_storage)) {
return [defaultBuildingVariant, enumTrashVariants.storage];
}
return super.getAvailableVariants(root);
} }
/** /**
@ -74,13 +35,6 @@ export class MetaTrashBuilding extends MetaBuilding {
* @param {Entity} entity * @param {Entity} entity
*/ */
setupEntityComponents(entity) { setupEntityComponents(entity) {
// Required, since the item processor needs this.
entity.addComponent(
new ItemEjectorComponent({
slots: [],
})
);
entity.addComponent( entity.addComponent(
new ItemAcceptorComponent({ new ItemAcceptorComponent({
slots: [ slots: [
@ -96,99 +50,11 @@ export class MetaTrashBuilding extends MetaBuilding {
], ],
}) })
); );
} entity.addComponent(
new ItemProcessorComponent({
/** inputsPerCharge: 1,
* processorType: enumItemProcessorTypes.trash,
* @param {Entity} entity })
* @param {number} rotationVariant );
* @param {string} variant
*/
updateVariants(entity, rotationVariant, variant) {
switch (variant) {
case defaultBuildingVariant: {
if (!entity.components.ItemProcessor) {
entity.addComponent(
new ItemProcessorComponent({
inputsPerCharge: 1,
processorType: enumItemProcessorTypes.trash,
})
);
}
if (entity.components.Storage) {
entity.removeComponent(StorageComponent);
}
if (entity.components.WiredPins) {
entity.removeComponent(WiredPinsComponent);
}
entity.components.ItemAcceptor.setSlots([
{
pos: new Vector(0, 0),
directions: [
enumDirection.top,
enumDirection.right,
enumDirection.bottom,
enumDirection.left,
],
},
]);
entity.components.ItemEjector.setSlots([]);
entity.components.ItemProcessor.type = enumItemProcessorTypes.trash;
break;
}
case enumTrashVariants.storage: {
if (entity.components.ItemProcessor) {
entity.removeComponent(ItemProcessorComponent);
}
if (!entity.components.Storage) {
entity.addComponent(new StorageComponent({}));
}
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([
{
pos: new Vector(0, 1),
directions: [enumDirection.bottom],
},
{
pos: new Vector(1, 1),
directions: [enumDirection.bottom],
},
]);
entity.components.ItemEjector.setSlots([
{
pos: new Vector(0, 0),
direction: enumDirection.top,
},
{
pos: new Vector(1, 0),
direction: enumDirection.top,
},
]);
break;
}
default:
assertAlways(false, "Unknown trash variant: " + variant);
}
} }
} }

View File

@ -1,266 +1,268 @@
import { Loader } from "../../core/loader"; import { Loader } from "../../core/loader";
import { enumDirection, Vector, enumAngleToDirection, enumDirectionToVector } from "../../core/vector"; import { enumDirection, Vector, enumAngleToDirection, enumDirectionToVector } from "../../core/vector";
import { ItemAcceptorComponent } from "../components/item_acceptor"; import { ItemAcceptorComponent } from "../components/item_acceptor";
import { ItemEjectorComponent } from "../components/item_ejector"; import { ItemEjectorComponent } from "../components/item_ejector";
import { enumUndergroundBeltMode, UndergroundBeltComponent } from "../components/underground_belt"; import { enumUndergroundBeltMode, UndergroundBeltComponent } from "../components/underground_belt";
import { Entity } from "../entity"; import { Entity } from "../entity";
import { MetaBuilding, defaultBuildingVariant } from "../meta_building"; import { MetaBuilding, defaultBuildingVariant } from "../meta_building";
import { GameRoot } from "../root"; import { GameRoot } from "../root";
import { globalConfig } from "../../core/config"; import { globalConfig } from "../../core/config";
import { enumHubGoalRewards } from "../tutorial_goals"; import { enumHubGoalRewards } from "../tutorial_goals";
import { formatItemsPerSecond, generateMatrixRotations } from "../../core/utils"; import { formatItemsPerSecond, generateMatrixRotations } from "../../core/utils";
import { T } from "../../translations"; import { T } from "../../translations";
/** @enum {string} */ /** @enum {string} */
export const arrayUndergroundRotationVariantToMode = [ export const arrayUndergroundRotationVariantToMode = [
enumUndergroundBeltMode.sender, enumUndergroundBeltMode.sender,
enumUndergroundBeltMode.receiver, enumUndergroundBeltMode.receiver,
]; ];
/** @enum {string} */ /** @enum {string} */
export const enumUndergroundBeltVariants = { tier2: "tier2" }; export const enumUndergroundBeltVariants = { tier2: "tier2" };
export const enumUndergroundBeltVariantToTier = { export const enumUndergroundBeltVariantToTier = {
[defaultBuildingVariant]: 0, [defaultBuildingVariant]: 0,
[enumUndergroundBeltVariants.tier2]: 1, [enumUndergroundBeltVariants.tier2]: 1,
}; };
const overlayMatrices = [ const colorsByRotationVariant = ["#6d9dff", "#9cad40"];
// Sender
generateMatrixRotations([1, 1, 1, 0, 1, 0, 0, 1, 0]), const overlayMatrices = [
// Sender
// Receiver generateMatrixRotations([1, 1, 1, 0, 1, 0, 0, 1, 0]),
generateMatrixRotations([0, 1, 0, 0, 1, 0, 1, 1, 1]),
]; // Receiver
generateMatrixRotations([0, 1, 0, 0, 1, 0, 1, 1, 1]),
export class MetaUndergroundBeltBuilding extends MetaBuilding { ];
constructor() {
super("underground_belt"); export class MetaUndergroundBeltBuilding extends MetaBuilding {
} constructor() {
super("underground_belt");
getSilhouetteColor() { }
return "#222";
} getSilhouetteColor(variant, rotationVariant) {
return colorsByRotationVariant[rotationVariant];
getFlipOrientationAfterPlacement() { }
return true;
} getFlipOrientationAfterPlacement() {
return true;
getStayInPlacementMode() { }
return true;
} getStayInPlacementMode() {
return true;
/** }
* @param {number} rotation
* @param {number} rotationVariant /**
* @param {string} variant * @param {number} rotation
* @param {Entity} entity * @param {number} rotationVariant
*/ * @param {string} variant
getSpecialOverlayRenderMatrix(rotation, rotationVariant, variant, entity) { * @param {Entity} entity
return overlayMatrices[rotationVariant][rotation]; */
} getSpecialOverlayRenderMatrix(rotation, rotationVariant, variant, entity) {
return overlayMatrices[rotationVariant][rotation];
/** }
* @param {GameRoot} root
* @param {string} variant /**
* @returns {Array<[string, string]>} * @param {GameRoot} root
*/ * @param {string} variant
getAdditionalStatistics(root, variant) { * @returns {Array<[string, string]>}
const rangeTiles = */
globalConfig.undergroundBeltMaxTilesByTier[enumUndergroundBeltVariantToTier[variant]]; getAdditionalStatistics(root, variant) {
const rangeTiles =
const beltSpeed = root.hubGoals.getUndergroundBeltBaseSpeed(); globalConfig.undergroundBeltMaxTilesByTier[enumUndergroundBeltVariantToTier[variant]];
return [
[ const beltSpeed = root.hubGoals.getUndergroundBeltBaseSpeed();
T.ingame.buildingPlacement.infoTexts.range, return [
T.ingame.buildingPlacement.infoTexts.tiles.replace("<x>", "" + rangeTiles), [
], T.ingame.buildingPlacement.infoTexts.range,
[T.ingame.buildingPlacement.infoTexts.speed, formatItemsPerSecond(beltSpeed)], T.ingame.buildingPlacement.infoTexts.tiles.replace("<x>", "" + rangeTiles),
]; ],
} [T.ingame.buildingPlacement.infoTexts.speed, formatItemsPerSecond(beltSpeed)],
];
/** }
* @param {GameRoot} root
*/ /**
getAvailableVariants(root) { * @param {GameRoot} root
if (root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_underground_belt_tier_2)) { */
return [defaultBuildingVariant, enumUndergroundBeltVariants.tier2]; getAvailableVariants(root) {
} if (root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_underground_belt_tier_2)) {
return super.getAvailableVariants(root); return [defaultBuildingVariant, enumUndergroundBeltVariants.tier2];
} }
return super.getAvailableVariants(root);
/** }
* @param {number} rotationVariant
* @param {string} variant /**
*/ * @param {number} rotationVariant
getPreviewSprite(rotationVariant, variant) { * @param {string} variant
let suffix = ""; */
if (variant !== defaultBuildingVariant) { getPreviewSprite(rotationVariant, variant) {
suffix = "-" + variant; let suffix = "";
} if (variant !== defaultBuildingVariant) {
suffix = "-" + variant;
switch (arrayUndergroundRotationVariantToMode[rotationVariant]) { }
case enumUndergroundBeltMode.sender:
return Loader.getSprite("sprites/buildings/underground_belt_entry" + suffix + ".png"); switch (arrayUndergroundRotationVariantToMode[rotationVariant]) {
case enumUndergroundBeltMode.receiver: case enumUndergroundBeltMode.sender:
return Loader.getSprite("sprites/buildings/underground_belt_exit" + suffix + ".png"); return Loader.getSprite("sprites/buildings/underground_belt_entry" + suffix + ".png");
default: case enumUndergroundBeltMode.receiver:
assertAlways(false, "Invalid rotation variant"); return Loader.getSprite("sprites/buildings/underground_belt_exit" + suffix + ".png");
} default:
} assertAlways(false, "Invalid rotation variant");
}
/** }
* @param {number} rotationVariant
* @param {string} variant /**
*/ * @param {number} rotationVariant
getBlueprintSprite(rotationVariant, variant) { * @param {string} variant
let suffix = ""; */
if (variant !== defaultBuildingVariant) { getBlueprintSprite(rotationVariant, variant) {
suffix = "-" + variant; let suffix = "";
} if (variant !== defaultBuildingVariant) {
suffix = "-" + variant;
switch (arrayUndergroundRotationVariantToMode[rotationVariant]) { }
case enumUndergroundBeltMode.sender:
return Loader.getSprite("sprites/blueprints/underground_belt_entry" + suffix + ".png"); switch (arrayUndergroundRotationVariantToMode[rotationVariant]) {
case enumUndergroundBeltMode.receiver: case enumUndergroundBeltMode.sender:
return Loader.getSprite("sprites/blueprints/underground_belt_exit" + suffix + ".png"); return Loader.getSprite("sprites/blueprints/underground_belt_entry" + suffix + ".png");
default: case enumUndergroundBeltMode.receiver:
assertAlways(false, "Invalid rotation variant"); return Loader.getSprite("sprites/blueprints/underground_belt_exit" + suffix + ".png");
} default:
} assertAlways(false, "Invalid rotation variant");
}
/** }
* @param {number} rotationVariant
* @param {string} variant /**
*/ * @param {number} rotationVariant
getSprite(rotationVariant, variant) { * @param {string} variant
return this.getPreviewSprite(rotationVariant, variant); */
} getSprite(rotationVariant, variant) {
return this.getPreviewSprite(rotationVariant, variant);
/** }
* @param {GameRoot} root
*/ /**
getIsUnlocked(root) { * @param {GameRoot} root
return root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_tunnel); */
} getIsUnlocked(root) {
return root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_tunnel);
/** }
* Creates the entity at the given location
* @param {Entity} entity /**
*/ * Creates the entity at the given location
setupEntityComponents(entity) { * @param {Entity} entity
// Required, since the item processor needs this. */
entity.addComponent( setupEntityComponents(entity) {
new ItemEjectorComponent({ // Required, since the item processor needs this.
slots: [], entity.addComponent(
}) new ItemEjectorComponent({
); slots: [],
})
entity.addComponent(new UndergroundBeltComponent({})); );
entity.addComponent(
new ItemAcceptorComponent({ entity.addComponent(new UndergroundBeltComponent({}));
slots: [], entity.addComponent(
}) new ItemAcceptorComponent({
); slots: [],
} })
);
/** }
* Should compute the optimal rotation variant on the given tile
* @param {object} param0 /**
* @param {GameRoot} param0.root * Should compute the optimal rotation variant on the given tile
* @param {Vector} param0.tile * @param {object} param0
* @param {number} param0.rotation * @param {GameRoot} param0.root
* @param {string} param0.variant * @param {Vector} param0.tile
* @param {Layer} param0.layer * @param {number} param0.rotation
* @return {{ rotation: number, rotationVariant: number, connectedEntities?: Array<Entity> }} * @param {string} param0.variant
*/ * @param {Layer} param0.layer
computeOptimalDirectionAndRotationVariantAtTile({ root, tile, rotation, variant, layer }) { * @return {{ rotation: number, rotationVariant: number, connectedEntities?: Array<Entity> }}
const searchDirection = enumAngleToDirection[rotation]; */
const searchVector = enumDirectionToVector[searchDirection]; computeOptimalDirectionAndRotationVariantAtTile({ root, tile, rotation, variant, layer }) {
const tier = enumUndergroundBeltVariantToTier[variant]; const searchDirection = enumAngleToDirection[rotation];
const searchVector = enumDirectionToVector[searchDirection];
const targetRotation = (rotation + 180) % 360; const tier = enumUndergroundBeltVariantToTier[variant];
const targetSenderRotation = rotation;
const targetRotation = (rotation + 180) % 360;
for ( const targetSenderRotation = rotation;
let searchOffset = 1;
searchOffset <= globalConfig.undergroundBeltMaxTilesByTier[tier]; for (
++searchOffset let searchOffset = 1;
) { searchOffset <= globalConfig.undergroundBeltMaxTilesByTier[tier];
tile = tile.addScalars(searchVector.x, searchVector.y); ++searchOffset
) {
/* WIRES: FIXME */ tile = tile.addScalars(searchVector.x, searchVector.y);
const contents = root.map.getTileContent(tile, "regular");
if (contents) { /* WIRES: FIXME */
const undergroundComp = contents.components.UndergroundBelt; const contents = root.map.getTileContent(tile, "regular");
if (undergroundComp && undergroundComp.tier === tier) { if (contents) {
const staticComp = contents.components.StaticMapEntity; const undergroundComp = contents.components.UndergroundBelt;
if (staticComp.rotation === targetRotation) { if (undergroundComp && undergroundComp.tier === tier) {
if (undergroundComp.mode !== enumUndergroundBeltMode.sender) { const staticComp = contents.components.StaticMapEntity;
// If we encounter an underground receiver on our way which is also faced in our direction, we don't accept that if (staticComp.rotation === targetRotation) {
break; if (undergroundComp.mode !== enumUndergroundBeltMode.sender) {
} // If we encounter an underground receiver on our way which is also faced in our direction, we don't accept that
return { break;
rotation: targetRotation, }
rotationVariant: 1, return {
connectedEntities: [contents], rotation: targetRotation,
}; rotationVariant: 1,
} else if (staticComp.rotation === targetSenderRotation) { connectedEntities: [contents],
// Draw connections to receivers };
if (undergroundComp.mode === enumUndergroundBeltMode.receiver) { } else if (staticComp.rotation === targetSenderRotation) {
return { // Draw connections to receivers
rotation: rotation, if (undergroundComp.mode === enumUndergroundBeltMode.receiver) {
rotationVariant: 0, return {
connectedEntities: [contents], rotation: rotation,
}; rotationVariant: 0,
} else { connectedEntities: [contents],
break; };
} } else {
} break;
} }
} }
} }
}
return { }
rotation,
rotationVariant: 0, return {
}; rotation,
} rotationVariant: 0,
};
/** }
*
* @param {Entity} entity /**
* @param {number} rotationVariant *
* @param {string} variant * @param {Entity} entity
*/ * @param {number} rotationVariant
updateVariants(entity, rotationVariant, variant) { * @param {string} variant
entity.components.UndergroundBelt.tier = enumUndergroundBeltVariantToTier[variant]; */
updateVariants(entity, rotationVariant, variant) {
switch (arrayUndergroundRotationVariantToMode[rotationVariant]) { entity.components.UndergroundBelt.tier = enumUndergroundBeltVariantToTier[variant];
case enumUndergroundBeltMode.sender: {
entity.components.UndergroundBelt.mode = enumUndergroundBeltMode.sender; switch (arrayUndergroundRotationVariantToMode[rotationVariant]) {
entity.components.ItemEjector.setSlots([]); case enumUndergroundBeltMode.sender: {
entity.components.ItemAcceptor.setSlots([ entity.components.UndergroundBelt.mode = enumUndergroundBeltMode.sender;
{ entity.components.ItemEjector.setSlots([]);
pos: new Vector(0, 0), entity.components.ItemAcceptor.setSlots([
directions: [enumDirection.bottom], {
}, pos: new Vector(0, 0),
]); directions: [enumDirection.bottom],
return; },
} ]);
case enumUndergroundBeltMode.receiver: { return;
entity.components.UndergroundBelt.mode = enumUndergroundBeltMode.receiver; }
entity.components.ItemAcceptor.setSlots([]); case enumUndergroundBeltMode.receiver: {
entity.components.ItemEjector.setSlots([ entity.components.UndergroundBelt.mode = enumUndergroundBeltMode.receiver;
{ entity.components.ItemAcceptor.setSlots([]);
pos: new Vector(0, 0), entity.components.ItemEjector.setSlots([
direction: enumDirection.top, {
}, pos: new Vector(0, 0),
]); direction: enumDirection.top,
return; },
} ]);
default: return;
assertAlways(false, "Invalid rotation variant"); }
} default:
} assertAlways(false, "Invalid rotation variant");
} }
}
}

View File

@ -212,7 +212,7 @@ export class HubGoals extends BasicSerializableObject {
this.currentGoal = { this.currentGoal = {
/** @type {ShapeDefinition} */ /** @type {ShapeDefinition} */
definition: this.createRandomShape(), definition: this.createRandomShape(),
required: findNiceIntegerValue(5000 + Math.pow(this.level * 2000, 0.75)), required: findNiceIntegerValue(1000 + Math.pow(this.level * 2000, 0.8)),
reward: enumHubGoalRewards.no_reward_freeplay, reward: enumHubGoalRewards.no_reward_freeplay,
}; };
} }

View File

@ -1,177 +1,217 @@
import { gMetaBuildingRegistry } from "../../../core/global_registries"; import { gMetaBuildingRegistry } from "../../../core/global_registries";
import { Signal, STOP_PROPAGATION } from "../../../core/signal"; import { Signal, STOP_PROPAGATION } from "../../../core/signal";
import { makeDiv } from "../../../core/utils"; import { makeDiv } from "../../../core/utils";
import { KEYMAPPINGS } from "../../key_action_mapper"; import { KEYMAPPINGS } from "../../key_action_mapper";
import { MetaBuilding } from "../../meta_building"; import { MetaBuilding } from "../../meta_building";
import { GameRoot } from "../../root"; import { GameRoot } from "../../root";
import { BaseHUDPart } from "../base_hud_part"; import { BaseHUDPart } from "../base_hud_part";
import { DynamicDomAttach } from "../dynamic_dom_attach"; import { DynamicDomAttach } from "../dynamic_dom_attach";
export class HUDBaseToolbar extends BaseHUDPart { export class HUDBaseToolbar extends BaseHUDPart {
/** /**
* @param {GameRoot} root * @param {GameRoot} root
* @param {object} param0 * @param {object} param0
* @param {Array<typeof MetaBuilding>} param0.supportedBuildings * @param {Array<typeof MetaBuilding>} param0.primaryBuildings
* @param {function} param0.visibilityCondition * @param {Array<typeof MetaBuilding>=} param0.secondaryBuildings
* @param {string} param0.htmlElementId * @param {function} param0.visibilityCondition
*/ * @param {string} param0.htmlElementId
constructor(root, { supportedBuildings, visibilityCondition, htmlElementId }) { */
super(root); constructor(root, { primaryBuildings, secondaryBuildings = [], visibilityCondition, htmlElementId }) {
super(root);
this.supportedBuildings = supportedBuildings;
this.visibilityCondition = visibilityCondition; this.primaryBuildings = primaryBuildings;
this.htmlElementId = htmlElementId; this.secondaryBuildings = secondaryBuildings;
this.visibilityCondition = visibilityCondition;
/** @type {Object.<string, { this.htmlElementId = htmlElementId;
* metaBuilding: MetaBuilding,
* unlocked: boolean, /** @type {Object.<string, {
* selected: boolean, * metaBuilding: MetaBuilding,
* element: HTMLElement, * unlocked: boolean,
* index: number * selected: boolean,
* }>} */ * element: HTMLElement,
this.buildingHandles = {}; * index: number
} * }>} */
this.buildingHandles = {};
/** }
* Should create all require elements
* @param {HTMLElement} parent /**
*/ * Should create all require elements
createElements(parent) { * @param {HTMLElement} parent
this.element = makeDiv(parent, this.htmlElementId, ["ingame_buildingsToolbar"], ""); */
} createElements(parent) {
this.element = makeDiv(parent, this.htmlElementId, ["ingame_buildingsToolbar"], "");
initialize() { }
const actionMapper = this.root.keyMapper;
/**
const items = makeDiv(this.element, null, ["buildings"]); * Returns all buildings
* @returns {Array<typeof MetaBuilding>}
for (let i = 0; i < this.supportedBuildings.length; ++i) { */
const metaBuilding = gMetaBuildingRegistry.findByClass(this.supportedBuildings[i]); get allBuildings() {
const binding = actionMapper.getBinding(KEYMAPPINGS.buildings[metaBuilding.getId()]); return [...this.primaryBuildings, ...this.secondaryBuildings];
}
const itemContainer = makeDiv(items, null, ["building"]);
itemContainer.setAttribute("data-icon", "building_icons/" + metaBuilding.getId() + ".png"); initialize() {
const actionMapper = this.root.keyMapper;
binding.add(() => this.selectBuildingForPlacement(metaBuilding)); let rowSecondary;
if (this.secondaryBuildings.length > 0) {
this.trackClicks(itemContainer, () => this.selectBuildingForPlacement(metaBuilding), { rowSecondary = makeDiv(this.element, null, ["buildings", "secondary"]);
clickSound: null,
}); this.secondaryDomAttach = new DynamicDomAttach(this.root, rowSecondary, {
attachClass: "visible",
this.buildingHandles[metaBuilding.id] = { });
metaBuilding, }
element: itemContainer,
unlocked: false, const rowPrimary = makeDiv(this.element, null, ["buildings", "primary"]);
selected: false,
index: i, const allBuildings = this.allBuildings;
};
} for (let i = 0; i < allBuildings.length; ++i) {
const metaBuilding = gMetaBuildingRegistry.findByClass(allBuildings[i]);
this.root.hud.signals.selectedPlacementBuildingChanged.add( const binding = actionMapper.getBinding(KEYMAPPINGS.buildings[metaBuilding.getId()]);
this.onSelectedPlacementBuildingChanged,
this const itemContainer = makeDiv(
); this.primaryBuildings.includes(allBuildings[i]) ? rowPrimary : rowSecondary,
null,
this.domAttach = new DynamicDomAttach(this.root, this.element, { ["building"]
timeToKeepSeconds: 0.12, );
attachClass: "visible", itemContainer.setAttribute("data-icon", "building_icons/" + metaBuilding.getId() + ".png");
}); itemContainer.setAttribute("data-id", metaBuilding.getId());
this.lastSelectedIndex = 0;
actionMapper.getBinding(KEYMAPPINGS.placement.cycleBuildings).add(this.cycleBuildings, this); binding.add(() => this.selectBuildingForPlacement(metaBuilding));
}
this.trackClicks(itemContainer, () => this.selectBuildingForPlacement(metaBuilding), {
/** clickSound: null,
* Updates the toolbar });
*/
update() { this.buildingHandles[metaBuilding.id] = {
const visible = this.visibilityCondition(); metaBuilding,
this.domAttach.update(visible); element: itemContainer,
unlocked: false,
if (visible) { selected: false,
for (const buildingId in this.buildingHandles) { index: i,
const handle = this.buildingHandles[buildingId]; };
const newStatus = handle.metaBuilding.getIsUnlocked(this.root); }
if (handle.unlocked !== newStatus) {
handle.unlocked = newStatus; this.root.hud.signals.selectedPlacementBuildingChanged.add(
handle.element.classList.toggle("unlocked", newStatus); this.onSelectedPlacementBuildingChanged,
} this
} );
}
} this.domAttach = new DynamicDomAttach(this.root, this.element, {
timeToKeepSeconds: 0.12,
/** attachClass: "visible",
* Cycles through all buildings });
*/ this.lastSelectedIndex = 0;
cycleBuildings() { actionMapper.getBinding(KEYMAPPINGS.placement.cycleBuildings).add(this.cycleBuildings, this);
const visible = this.visibilityCondition(); }
if (!visible) {
return; /**
} * Updates the toolbar
*/
let newBuildingFound = false; update() {
let newIndex = this.lastSelectedIndex; const visible = this.visibilityCondition();
for (let i = 0; i < this.supportedBuildings.length; ++i, ++newIndex) { this.domAttach.update(visible);
newIndex %= this.supportedBuildings.length;
const metaBuilding = gMetaBuildingRegistry.findByClass(this.supportedBuildings[newIndex]); if (visible) {
const handle = this.buildingHandles[metaBuilding.id]; let recomputeSecondaryToolbarVisibility = false;
if (!handle.selected && handle.unlocked) { for (const buildingId in this.buildingHandles) {
newBuildingFound = true; const handle = this.buildingHandles[buildingId];
break; const newStatus = handle.metaBuilding.getIsUnlocked(this.root);
} if (handle.unlocked !== newStatus) {
} handle.unlocked = newStatus;
if (!newBuildingFound) { handle.element.classList.toggle("unlocked", newStatus);
return; recomputeSecondaryToolbarVisibility = true;
} }
const metaBuildingClass = this.supportedBuildings[newIndex]; }
const metaBuilding = gMetaBuildingRegistry.findByClass(metaBuildingClass);
this.selectBuildingForPlacement(metaBuilding); if (recomputeSecondaryToolbarVisibility && this.secondaryDomAttach) {
} let anyUnlocked = false;
for (let i = 0; i < this.secondaryBuildings.length; ++i) {
/** const metaClass = gMetaBuildingRegistry.findByClass(this.secondaryBuildings[i]);
* Called when the selected building got changed if (metaClass.getIsUnlocked(this.root)) {
* @param {MetaBuilding} metaBuilding anyUnlocked = true;
*/ break;
onSelectedPlacementBuildingChanged(metaBuilding) { }
for (const buildingId in this.buildingHandles) { }
const handle = this.buildingHandles[buildingId];
const newStatus = handle.metaBuilding === metaBuilding; this.secondaryDomAttach.update(anyUnlocked);
if (handle.selected !== newStatus) { }
handle.selected = newStatus; }
handle.element.classList.toggle("selected", newStatus); }
}
if (handle.selected) { /**
this.lastSelectedIndex = handle.index; * Cycles through all buildings
} */
} cycleBuildings() {
const visible = this.visibilityCondition();
this.element.classList.toggle("buildingSelected", !!metaBuilding); if (!visible) {
} return;
}
/**
* @param {MetaBuilding} metaBuilding let newBuildingFound = false;
*/ let newIndex = this.lastSelectedIndex;
selectBuildingForPlacement(metaBuilding) { for (let i = 0; i < this.primaryBuildings.length; ++i, ++newIndex) {
if (!this.visibilityCondition()) { newIndex %= this.primaryBuildings.length;
// Not active const metaBuilding = gMetaBuildingRegistry.findByClass(this.primaryBuildings[newIndex]);
return; const handle = this.buildingHandles[metaBuilding.id];
} if (!handle.selected && handle.unlocked) {
newBuildingFound = true;
if (!metaBuilding.getIsUnlocked(this.root)) { break;
this.root.soundProxy.playUiError(); }
return STOP_PROPAGATION; }
} if (!newBuildingFound) {
return;
// Allow clicking an item again to deselect it }
for (const buildingId in this.buildingHandles) { const metaBuildingClass = this.primaryBuildings[newIndex];
const handle = this.buildingHandles[buildingId]; const metaBuilding = gMetaBuildingRegistry.findByClass(metaBuildingClass);
if (handle.selected && handle.metaBuilding === metaBuilding) { this.selectBuildingForPlacement(metaBuilding);
metaBuilding = null; }
break;
} /**
} * Called when the selected building got changed
* @param {MetaBuilding} metaBuilding
this.root.soundProxy.playUiClick(); */
this.root.hud.signals.buildingSelectedForPlacement.dispatch(metaBuilding); onSelectedPlacementBuildingChanged(metaBuilding) {
this.onSelectedPlacementBuildingChanged(metaBuilding); for (const buildingId in this.buildingHandles) {
} const handle = this.buildingHandles[buildingId];
} const newStatus = handle.metaBuilding === metaBuilding;
if (handle.selected !== newStatus) {
handle.selected = newStatus;
handle.element.classList.toggle("selected", newStatus);
}
if (handle.selected) {
this.lastSelectedIndex = handle.index;
}
}
this.element.classList.toggle("buildingSelected", !!metaBuilding);
}
/**
* @param {MetaBuilding} metaBuilding
*/
selectBuildingForPlacement(metaBuilding) {
if (!this.visibilityCondition()) {
// Not active
return;
}
if (!metaBuilding.getIsUnlocked(this.root)) {
this.root.soundProxy.playUiError();
return STOP_PROPAGATION;
}
// Allow clicking an item again to deselect it
for (const buildingId in this.buildingHandles) {
const handle = this.buildingHandles[buildingId];
if (handle.selected && handle.metaBuilding === metaBuilding) {
metaBuilding = null;
break;
}
}
this.root.soundProxy.playUiClick();
this.root.hud.signals.buildingSelectedForPlacement.dispatch(metaBuilding);
this.onSelectedPlacementBuildingChanged(metaBuilding);
}
}

View File

@ -121,6 +121,7 @@ export class HUDBuildingPlacerLogic extends BaseHUDPart {
this.root.hud.signals.buildingsSelectedForCopy.add(this.abortPlacement, this); this.root.hud.signals.buildingsSelectedForCopy.add(this.abortPlacement, this);
this.root.hud.signals.pasteBlueprintRequested.add(this.abortPlacement, this); this.root.hud.signals.pasteBlueprintRequested.add(this.abortPlacement, this);
this.root.signals.storyGoalCompleted.add(() => this.signals.variantChanged.dispatch()); this.root.signals.storyGoalCompleted.add(() => this.signals.variantChanged.dispatch());
this.root.signals.storyGoalCompleted.add(() => this.currentMetaBuilding.set(null));
this.root.signals.upgradePurchased.add(() => this.signals.variantChanged.dispatch()); this.root.signals.upgradePurchased.add(() => this.signals.variantChanged.dispatch());
this.root.signals.editModeChanged.add(this.onEditModeChanged, this); this.root.signals.editModeChanged.add(this.onEditModeChanged, this);
@ -457,11 +458,11 @@ export class HUDBuildingPlacerLogic extends BaseHUDPart {
this.currentVariant.set(defaultBuildingVariant); this.currentVariant.set(defaultBuildingVariant);
} else { } else {
const availableVariants = metaBuilding.getAvailableVariants(this.root); const availableVariants = metaBuilding.getAvailableVariants(this.root);
const index = availableVariants.indexOf(this.currentVariant.get()); let index = availableVariants.indexOf(this.currentVariant.get());
assert( if (index < 0) {
index >= 0, index = 0;
"Current variant was invalid: " + this.currentVariant.get() + " out of " + availableVariants console.warn("Invalid variant selected:", this.currentVariant.get());
); }
const newIndex = (index + 1) % availableVariants.length; const newIndex = (index + 1) % availableVariants.length;
const newVariant = availableVariants[newIndex]; const newVariant = availableVariants[newIndex];
this.setVariant(newVariant); this.setVariant(newVariant);
@ -595,7 +596,17 @@ export class HUDBuildingPlacerLogic extends BaseHUDPart {
this.abortDragging(); this.abortDragging();
this.root.hud.signals.selectedPlacementBuildingChanged.dispatch(metaBuilding); this.root.hud.signals.selectedPlacementBuildingChanged.dispatch(metaBuilding);
if (metaBuilding) { if (metaBuilding) {
const variant = this.preferredVariants[metaBuilding.getId()] || defaultBuildingVariant; const availableVariants = metaBuilding.getAvailableVariants(this.root);
const preferredVariant = this.preferredVariants[metaBuilding.getId()];
// Choose last stored variant if possible, otherwise the default one
let variant;
if (!preferredVariant || !availableVariants.includes(preferredVariant)) {
variant = availableVariants[0];
} else {
variant = preferredVariant;
}
this.currentVariant.set(variant); this.currentVariant.set(variant);
this.fakeEntity = new Entity(null); this.fakeEntity = new Entity(null);

View File

@ -13,28 +13,30 @@ import { MetaStackerBuilding } from "../../buildings/stacker";
import { MetaTrashBuilding } from "../../buildings/trash"; import { MetaTrashBuilding } from "../../buildings/trash";
import { MetaUndergroundBeltBuilding } from "../../buildings/underground_belt"; import { MetaUndergroundBeltBuilding } from "../../buildings/underground_belt";
import { HUDBaseToolbar } from "./base_toolbar"; import { HUDBaseToolbar } from "./base_toolbar";
import { MetaStorageBuilding } from "../../buildings/storage";
const supportedBuildings = [
MetaBeltBuilding,
MetaBalancerBuilding,
MetaUndergroundBeltBuilding,
MetaMinerBuilding,
MetaCutterBuilding,
MetaRotaterBuilding,
MetaStackerBuilding,
MetaMixerBuilding,
MetaPainterBuilding,
MetaTrashBuilding,
MetaLeverBuilding,
MetaFilterBuilding,
MetaDisplayBuilding,
MetaReaderBuilding,
];
export class HUDBuildingsToolbar extends HUDBaseToolbar { export class HUDBuildingsToolbar extends HUDBaseToolbar {
constructor(root) { constructor(root) {
super(root, { super(root, {
supportedBuildings, primaryBuildings: [
MetaBeltBuilding,
MetaBalancerBuilding,
MetaUndergroundBeltBuilding,
MetaMinerBuilding,
MetaCutterBuilding,
MetaRotaterBuilding,
MetaStackerBuilding,
MetaMixerBuilding,
MetaPainterBuilding,
MetaTrashBuilding,
],
secondaryBuildings: [
MetaStorageBuilding,
MetaLeverBuilding,
MetaFilterBuilding,
MetaDisplayBuilding,
MetaReaderBuilding,
],
visibilityCondition: () => visibilityCondition: () =>
!this.root.camera.getIsMapOverlayActive() && this.root.currentLayer === "regular", !this.root.camera.getIsMapOverlayActive() && this.root.currentLayer === "regular",
htmlElementId: "ingame_HUD_buildings_toolbar", htmlElementId: "ingame_HUD_buildings_toolbar",

View File

@ -7,6 +7,7 @@ import {
KEYCODE_RMB, KEYCODE_RMB,
KEYMAPPINGS, KEYMAPPINGS,
} from "../../key_action_mapper"; } from "../../key_action_mapper";
import { enumHubGoalRewards } from "../../tutorial_goals";
import { BaseHUDPart } from "../base_hud_part"; import { BaseHUDPart } from "../base_hud_part";
import { DynamicDomAttach } from "../dynamic_dom_attach"; import { DynamicDomAttach } from "../dynamic_dom_attach";
@ -257,7 +258,8 @@ export class HUDKeybindingOverlay extends BaseHUDPart {
// Switch layers // Switch layers
label: T.ingame.keybindingsOverlay.switchLayers, label: T.ingame.keybindingsOverlay.switchLayers,
keys: [k.ingame.switchLayers], keys: [k.ingame.switchLayers],
condition: () => true, condition: () =>
this.root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_wires_filters_and_levers),
}, },
]; ];

View File

@ -319,9 +319,7 @@ export class HUDWaypoints extends BaseHUDPart {
this.waypoints.push({ this.waypoints.push({
label, label,
center: { x: position.x, y: position.y }, center: { x: position.x, y: position.y },
// Make sure the zoom is *just* a bit above the zoom level where the map overview zoomLevel: this.root.camera.zoomLevel,
// starts, so you always see all buildings
zoomLevel: Math.max(this.root.camera.zoomLevel, globalConfig.mapChunkOverviewMinZoom + 0.05),
}); });
this.sortWaypoints(); this.sortWaypoints();

View File

@ -6,19 +6,17 @@ import { MetaLeverBuilding } from "../../buildings/lever";
import { MetaWireTunnelBuilding } from "../../buildings/wire_tunnel"; import { MetaWireTunnelBuilding } from "../../buildings/wire_tunnel";
import { MetaVirtualProcessorBuilding } from "../../buildings/virtual_processor"; import { MetaVirtualProcessorBuilding } from "../../buildings/virtual_processor";
const supportedBuildings = [
MetaWireBuilding,
MetaWireTunnelBuilding,
MetaConstantSignalBuilding,
MetaLogicGateBuilding,
MetaLeverBuilding,
MetaVirtualProcessorBuilding,
];
export class HUDWiresToolbar extends HUDBaseToolbar { export class HUDWiresToolbar extends HUDBaseToolbar {
constructor(root) { constructor(root) {
super(root, { super(root, {
supportedBuildings, primaryBuildings: [
MetaWireBuilding,
MetaWireTunnelBuilding,
MetaConstantSignalBuilding,
MetaLogicGateBuilding,
MetaLeverBuilding,
MetaVirtualProcessorBuilding,
],
visibilityCondition: () => visibilityCondition: () =>
!this.root.camera.getIsMapOverlayActive() && this.root.currentLayer === "wires", !this.root.camera.getIsMapOverlayActive() && this.root.currentLayer === "wires",
htmlElementId: "ingame_HUD_wires_toolbar", htmlElementId: "ingame_HUD_wires_toolbar",

View File

@ -54,6 +54,7 @@ export const KEYMAPPINGS = {
mixer: { keyCode: key("8") }, mixer: { keyCode: key("8") },
painter: { keyCode: key("9") }, painter: { keyCode: key("9") },
trash: { keyCode: key("0") }, trash: { keyCode: key("0") },
storage: { keyCode: key("I") },
lever: { keyCode: key("L") }, lever: { keyCode: key("L") },
filter: { keyCode: key("B") }, filter: { keyCode: key("B") },
@ -352,6 +353,13 @@ export class KeyActionMapper {
} }
this.keybindings[key] = new Keybinding(this, this.root.app, payload); this.keybindings[key] = new Keybinding(this, this.root.app, payload);
if (G_IS_DEV) {
// Sanity
if (!T.keybindings.mappings[key]) {
assertAlways(false, "Keybinding " + key + " has no translation!");
}
}
} }
} }

View File

@ -170,7 +170,10 @@ export class MapChunkView extends MapChunk {
); );
} }
context.fillStyle = metaBuilding.getSilhouetteColor(); context.fillStyle = metaBuilding.getSilhouetteColor(
data.variant,
data.rotationVariant
);
for (let dx = 0; dx < 3; ++dx) { for (let dx = 0; dx < 3; ++dx) {
for (let dy = 0; dy < 3; ++dy) { for (let dy = 0; dy < 3; ++dy) {
const isFilled = overlayMatrix[dx + dy * 3]; const isFilled = overlayMatrix[dx + dy * 3];
@ -187,7 +190,10 @@ export class MapChunkView extends MapChunk {
continue; continue;
} else { } else {
context.fillStyle = metaBuilding.getSilhouetteColor(); context.fillStyle = metaBuilding.getSilhouetteColor(
data.variant,
data.rotationVariant
);
context.fillRect( context.fillRect(
x * CHUNK_OVERLAY_RES, x * CHUNK_OVERLAY_RES,
y * CHUNK_OVERLAY_RES, y * CHUNK_OVERLAY_RES,
@ -256,7 +262,8 @@ export class MapChunkView extends MapChunk {
data.variant, data.variant,
entity entity
); );
context.fillStyle = overrideColor || metaBuilding.getSilhouetteColor(); context.fillStyle =
overrideColor || metaBuilding.getSilhouetteColor(data.variant, data.rotationVariant);
if (overlayMatrix) { if (overlayMatrix) {
for (let dx = 0; dx < 3; ++dx) { for (let dx = 0; dx < 3; ++dx) {
for (let dy = 0; dy < 3; ++dy) { for (let dy = 0; dy < 3; ++dy) {

View File

@ -1,273 +1,275 @@
import { Loader } from "../core/loader"; import { Loader } from "../core/loader";
import { AtlasSprite } from "../core/sprites"; import { AtlasSprite } from "../core/sprites";
import { Vector } from "../core/vector"; import { Vector } from "../core/vector";
import { SOUNDS } from "../platform/sound"; import { SOUNDS } from "../platform/sound";
import { StaticMapEntityComponent } from "./components/static_map_entity"; import { StaticMapEntityComponent } from "./components/static_map_entity";
import { Entity } from "./entity"; import { Entity } from "./entity";
import { GameRoot } from "./root"; import { GameRoot } from "./root";
import { getCodeFromBuildingData } from "./building_codes"; import { getCodeFromBuildingData } from "./building_codes";
export const defaultBuildingVariant = "default"; export const defaultBuildingVariant = "default";
export class MetaBuilding { export class MetaBuilding {
/** /**
* *
* @param {string} id Building id * @param {string} id Building id
*/ */
constructor(id) { constructor(id) {
this.id = id; this.id = id;
} }
/** /**
* Returns the id of this building * Returns the id of this building
*/ */
getId() { getId() {
return this.id; return this.id;
} }
/** /**
* Returns the edit layer of the building * Returns the edit layer of the building
* @returns {Layer} * @returns {Layer}
*/ */
getLayer() { getLayer() {
return "regular"; return "regular";
} }
/** /**
* Should return the dimensions of the building * Should return the dimensions of the building
*/ */
getDimensions(variant = defaultBuildingVariant) { getDimensions(variant = defaultBuildingVariant) {
return new Vector(1, 1); return new Vector(1, 1);
} }
/** /**
* Returns whether the building has the direction lock switch available * Returns whether the building has the direction lock switch available
*/ */
getHasDirectionLockAvailable() { getHasDirectionLockAvailable() {
return false; return false;
} }
/** /**
* Whether to stay in placement mode after having placed a building * Whether to stay in placement mode after having placed a building
*/ */
getStayInPlacementMode() { getStayInPlacementMode() {
return false; return false;
} }
/** /**
* Can return a special interlaved 9 elements overlay matrix for rendering * Can return a special interlaved 9 elements overlay matrix for rendering
* @param {number} rotation * @param {number} rotation
* @param {number} rotationVariant * @param {number} rotationVariant
* @param {string} variant * @param {string} variant
* @param {Entity} entity * @param {Entity} entity
* @returns {Array<number>|null} * @returns {Array<number>|null}
*/ */
getSpecialOverlayRenderMatrix(rotation, rotationVariant, variant, entity) { getSpecialOverlayRenderMatrix(rotation, rotationVariant, variant, entity) {
return null; return null;
} }
/** /**
* Should return additional statistics about this building * Should return additional statistics about this building
* @param {GameRoot} root * @param {GameRoot} root
* @param {string} variant * @param {string} variant
* @returns {Array<[string, string]>} * @returns {Array<[string, string]>}
*/ */
getAdditionalStatistics(root, variant) { getAdditionalStatistics(root, variant) {
return []; return [];
} }
/** /**
* Returns whether this building can get replaced * Returns whether this building can get replaced
*/ */
getIsReplaceable() { getIsReplaceable() {
return false; return false;
} }
/** /**
* Whether to flip the orientation after a building has been placed - useful * Whether to flip the orientation after a building has been placed - useful
* for tunnels. * for tunnels.
*/ */
getFlipOrientationAfterPlacement() { getFlipOrientationAfterPlacement() {
return false; return false;
} }
/** /**
* Whether to show a preview of the wires layer when placing the building * Whether to show a preview of the wires layer when placing the building
*/ */
getShowWiresLayerPreview() { getShowWiresLayerPreview() {
return false; return false;
} }
/** /**
* Whether to rotate automatically in the dragging direction while placing * Whether to rotate automatically in the dragging direction while placing
* @param {string} variant * @param {string} variant
*/ */
getRotateAutomaticallyWhilePlacing(variant) { getRotateAutomaticallyWhilePlacing(variant) {
return false; return false;
} }
/** /**
* Returns whether this building is removable * Returns whether this building is removable
* @returns {boolean} * @returns {boolean}
*/ */
getIsRemovable() { getIsRemovable() {
return true; return true;
} }
/** /**
* Returns the placement sound * Returns the placement sound
* @returns {string} * @returns {string}
*/ */
getPlacementSound() { getPlacementSound() {
return SOUNDS.placeBuilding; return SOUNDS.placeBuilding;
} }
/** /**
* @param {GameRoot} root * @param {GameRoot} root
*/ */
getAvailableVariants(root) { getAvailableVariants(root) {
return [defaultBuildingVariant]; return [defaultBuildingVariant];
} }
/** /**
* Returns a preview sprite * Returns a preview sprite
* @returns {AtlasSprite} * @returns {AtlasSprite}
*/ */
getPreviewSprite(rotationVariant = 0, variant = defaultBuildingVariant) { getPreviewSprite(rotationVariant = 0, variant = defaultBuildingVariant) {
return Loader.getSprite( return Loader.getSprite(
"sprites/buildings/" + "sprites/buildings/" +
this.id + this.id +
(variant === defaultBuildingVariant ? "" : "-" + variant) + (variant === defaultBuildingVariant ? "" : "-" + variant) +
".png" ".png"
); );
} }
/** /**
* Returns a sprite for blueprints * Returns a sprite for blueprints
* @returns {AtlasSprite} * @returns {AtlasSprite}
*/ */
getBlueprintSprite(rotationVariant = 0, variant = defaultBuildingVariant) { getBlueprintSprite(rotationVariant = 0, variant = defaultBuildingVariant) {
return Loader.getSprite( return Loader.getSprite(
"sprites/blueprints/" + "sprites/blueprints/" +
this.id + this.id +
(variant === defaultBuildingVariant ? "" : "-" + variant) + (variant === defaultBuildingVariant ? "" : "-" + variant) +
".png" ".png"
); );
} }
/** /**
* Returns whether this building is rotateable * Returns whether this building is rotateable
* @param {string} variant * @param {string} variant
* @returns {boolean} * @returns {boolean}
*/ */
getIsRotateable(variant) { getIsRotateable(variant) {
return true; return true;
} }
/** /**
* Returns whether this building is unlocked for the given game * Returns whether this building is unlocked for the given game
* @param {GameRoot} root * @param {GameRoot} root
*/ */
getIsUnlocked(root) { getIsUnlocked(root) {
return true; return true;
} }
/** /**
* Should return a silhouette color for the map overview or null if not set * Should return a silhouette color for the map overview or null if not set
*/ * @param {string} variant
getSilhouetteColor() { * @param {number} rotationVariant
return null; */
} getSilhouetteColor(variant, rotationVariant) {
return null;
/** }
* Should return false if the pins are already included in the sprite of the building
* @returns {boolean} /**
*/ * Should return false if the pins are already included in the sprite of the building
getRenderPins() { * @returns {boolean}
return true; */
} getRenderPins() {
return true;
/** }
* Creates the entity without placing it
* @param {object} param0 /**
* @param {GameRoot} param0.root * Creates the entity without placing it
* @param {Vector} param0.origin Origin tile * @param {object} param0
* @param {number=} param0.rotation Rotation * @param {GameRoot} param0.root
* @param {number} param0.originalRotation Original Rotation * @param {Vector} param0.origin Origin tile
* @param {number} param0.rotationVariant Rotation variant * @param {number=} param0.rotation Rotation
* @param {string} param0.variant * @param {number} param0.originalRotation Original Rotation
*/ * @param {number} param0.rotationVariant Rotation variant
createEntity({ root, origin, rotation, originalRotation, rotationVariant, variant }) { * @param {string} param0.variant
const entity = new Entity(root); */
entity.layer = this.getLayer(); createEntity({ root, origin, rotation, originalRotation, rotationVariant, variant }) {
entity.addComponent( const entity = new Entity(root);
new StaticMapEntityComponent({ entity.layer = this.getLayer();
origin: new Vector(origin.x, origin.y), entity.addComponent(
rotation, new StaticMapEntityComponent({
originalRotation, origin: new Vector(origin.x, origin.y),
tileSize: this.getDimensions(variant).copy(), rotation,
code: getCodeFromBuildingData(this, variant, rotationVariant), originalRotation,
}) tileSize: this.getDimensions(variant).copy(),
); code: getCodeFromBuildingData(this, variant, rotationVariant),
this.setupEntityComponents(entity, root); })
this.updateVariants(entity, rotationVariant, variant); );
return entity; this.setupEntityComponents(entity, root);
} this.updateVariants(entity, rotationVariant, variant);
return entity;
/** }
* Returns the sprite for a given variant
* @param {number} rotationVariant /**
* @param {string} variant * Returns the sprite for a given variant
* @returns {AtlasSprite} * @param {number} rotationVariant
*/ * @param {string} variant
getSprite(rotationVariant, variant) { * @returns {AtlasSprite}
return Loader.getSprite( */
"sprites/buildings/" + getSprite(rotationVariant, variant) {
this.id + return Loader.getSprite(
(variant === defaultBuildingVariant ? "" : "-" + variant) + "sprites/buildings/" +
".png" this.id +
); (variant === defaultBuildingVariant ? "" : "-" + variant) +
} ".png"
);
/** }
* Should compute the optimal rotation variant on the given tile
* @param {object} param0 /**
* @param {GameRoot} param0.root * Should compute the optimal rotation variant on the given tile
* @param {Vector} param0.tile * @param {object} param0
* @param {number} param0.rotation * @param {GameRoot} param0.root
* @param {string} param0.variant * @param {Vector} param0.tile
* @param {Layer} param0.layer * @param {number} param0.rotation
* @return {{ rotation: number, rotationVariant: number, connectedEntities?: Array<Entity> }} * @param {string} param0.variant
*/ * @param {Layer} param0.layer
computeOptimalDirectionAndRotationVariantAtTile({ root, tile, rotation, variant, layer }) { * @return {{ rotation: number, rotationVariant: number, connectedEntities?: Array<Entity> }}
if (!this.getIsRotateable(variant)) { */
return { computeOptimalDirectionAndRotationVariantAtTile({ root, tile, rotation, variant, layer }) {
rotation: 0, if (!this.getIsRotateable(variant)) {
rotationVariant: 0, return {
}; rotation: 0,
} rotationVariant: 0,
return { };
rotation, }
rotationVariant: 0, return {
}; rotation,
} rotationVariant: 0,
};
/** }
* Should update the entity to match the given variants
* @param {Entity} entity /**
* @param {number} rotationVariant * Should update the entity to match the given variants
* @param {string} variant * @param {Entity} entity
*/ * @param {number} rotationVariant
updateVariants(entity, rotationVariant, variant) {} * @param {string} variant
*/
// PRIVATE INTERFACE updateVariants(entity, rotationVariant, variant) {}
/** // PRIVATE INTERFACE
* Should setup the entity components
* @param {Entity} entity /**
* @param {GameRoot} root * Should setup the entity components
*/ * @param {Entity} entity
setupEntityComponents(entity, root) { * @param {GameRoot} root
abstract; */
} setupEntityComponents(entity, root) {
} abstract;
}
}

View File

@ -9,7 +9,7 @@ import { enumPainterVariants, MetaPainterBuilding } from "./buildings/painter";
import { enumRotaterVariants, MetaRotaterBuilding } from "./buildings/rotater"; import { enumRotaterVariants, MetaRotaterBuilding } from "./buildings/rotater";
import { enumBalancerVariants, MetaBalancerBuilding } from "./buildings/balancer"; import { enumBalancerVariants, MetaBalancerBuilding } from "./buildings/balancer";
import { MetaStackerBuilding } from "./buildings/stacker"; import { MetaStackerBuilding } from "./buildings/stacker";
import { enumTrashVariants, MetaTrashBuilding } from "./buildings/trash"; import { MetaTrashBuilding } from "./buildings/trash";
import { enumUndergroundBeltVariants, MetaUndergroundBeltBuilding } from "./buildings/underground_belt"; import { enumUndergroundBeltVariants, MetaUndergroundBeltBuilding } from "./buildings/underground_belt";
import { MetaWireBuilding } from "./buildings/wire"; import { MetaWireBuilding } from "./buildings/wire";
import { buildBuildingCodeCache, gBuildingVariants, registerBuildingVariant } from "./building_codes"; import { buildBuildingCodeCache, gBuildingVariants, registerBuildingVariant } from "./building_codes";
@ -22,6 +22,9 @@ import { MetaWireTunnelBuilding, enumWireTunnelVariants } from "./buildings/wire
import { MetaDisplayBuilding } from "./buildings/display"; import { MetaDisplayBuilding } from "./buildings/display";
import { MetaVirtualProcessorBuilding, enumVirtualProcessorVariants } from "./buildings/virtual_processor"; import { MetaVirtualProcessorBuilding, enumVirtualProcessorVariants } from "./buildings/virtual_processor";
import { MetaReaderBuilding } from "./buildings/reader"; import { MetaReaderBuilding } from "./buildings/reader";
import { MetaStorageBuilding } from "./buildings/storage";
import { KEYMAPPINGS } from "./key_action_mapper";
import { T } from "../translations";
const logger = createLogger("building_registry"); const logger = createLogger("building_registry");
@ -34,6 +37,7 @@ export function initMetaBuildingRegistry() {
gMetaBuildingRegistry.register(MetaMixerBuilding); gMetaBuildingRegistry.register(MetaMixerBuilding);
gMetaBuildingRegistry.register(MetaPainterBuilding); gMetaBuildingRegistry.register(MetaPainterBuilding);
gMetaBuildingRegistry.register(MetaTrashBuilding); gMetaBuildingRegistry.register(MetaTrashBuilding);
gMetaBuildingRegistry.register(MetaStorageBuilding);
gMetaBuildingRegistry.register(MetaBeltBuilding); gMetaBuildingRegistry.register(MetaBeltBuilding);
gMetaBuildingRegistry.register(MetaUndergroundBeltBuilding); gMetaBuildingRegistry.register(MetaUndergroundBeltBuilding);
gMetaBuildingRegistry.register(MetaHubBuilding); gMetaBuildingRegistry.register(MetaHubBuilding);
@ -86,7 +90,9 @@ export function initMetaBuildingRegistry() {
// Trash // Trash
registerBuildingVariant(20, MetaTrashBuilding); registerBuildingVariant(20, MetaTrashBuilding);
registerBuildingVariant(21, MetaTrashBuilding, enumTrashVariants.storage);
// Storage
registerBuildingVariant(21, MetaStorageBuilding);
// Underground belt // Underground belt
registerBuildingVariant(22, MetaUndergroundBeltBuilding, defaultBuildingVariant, 0); registerBuildingVariant(22, MetaUndergroundBeltBuilding, defaultBuildingVariant, 0);
@ -157,6 +163,29 @@ export function initMetaBuildingRegistry() {
} }
} }
// Check for valid keycodes
if (G_IS_DEV) {
gMetaBuildingRegistry.entries.forEach(metaBuilding => {
const id = metaBuilding.getId();
if (!["hub"].includes(id)) {
if (!KEYMAPPINGS.buildings[id]) {
assertAlways(
false,
"Building " + id + " has no keybinding assigned! Add it to key_action_mapper.js"
);
}
if (!T.buildings[id]) {
assertAlways(false, "Translation for building " + id + " missing!");
}
if (!T.buildings[id].default) {
assertAlways(false, "Translation for building " + id + " missing (default variant)!");
}
}
});
}
logger.log("Registered", gMetaBuildingRegistry.getNumEntries(), "buildings"); logger.log("Registered", gMetaBuildingRegistry.getNumEntries(), "buildings");
logger.log("Registered", Object.keys(gBuildingVariants).length, "building codes"); logger.log("Registered", Object.keys(gBuildingVariants).length, "building codes");
} }
@ -174,7 +203,10 @@ export function initBuildingCodesAfterResourcesLoaded() {
variant.rotationVariant, variant.rotationVariant,
variant.variant variant.variant
); );
variant.silhouetteColor = variant.metaInstance.getSilhouetteColor(); variant.silhouetteColor = variant.metaInstance.getSilhouetteColor(
variant.variant,
variant.rotationVariant
);
} }
// Update caches // Update caches

View File

@ -94,6 +94,8 @@ export class ItemProcessorSystem extends GameSystemWithFilter {
for (let j = 0; j < itemsToEject.length; ++j) { for (let j = 0; j < itemsToEject.length; ++j) {
const { item, requiredSlot, preferredSlot } = itemsToEject[j]; const { item, requiredSlot, preferredSlot } = itemsToEject[j];
assert(ejectorComp, "To eject items, the building needs to have an ejector");
let slot = null; let slot = null;
if (requiredSlot !== null && requiredSlot !== undefined) { if (requiredSlot !== null && requiredSlot !== undefined) {
// We have a slot override, check if that is free // We have a slot override, check if that is free
@ -306,6 +308,10 @@ export class ItemProcessorSystem extends GameSystemWithFilter {
* @param {ProcessorImplementationPayload} payload * @param {ProcessorImplementationPayload} payload
*/ */
process_BALANCER(payload) { process_BALANCER(payload) {
assert(
payload.entity.components.ItemEjector,
"To be a balancer, the building needs to have an ejector"
);
const availableSlots = payload.entity.components.ItemEjector.slots.length; const availableSlots = payload.entity.components.ItemEjector.slots.length;
const processorComp = payload.entity.components.ItemProcessor; const processorComp = payload.entity.components.ItemProcessor;

View File

@ -5,7 +5,6 @@ import { BaseItem } from "../base_item";
import { MinerComponent } from "../components/miner"; import { MinerComponent } from "../components/miner";
import { Entity } from "../entity"; import { Entity } from "../entity";
import { GameSystemWithFilter } from "../game_system_with_filter"; import { GameSystemWithFilter } from "../game_system_with_filter";
import { statisticsUnitsSeconds } from "../hud/parts/statistics_handle";
import { MapChunkView } from "../map_chunk_view"; import { MapChunkView } from "../map_chunk_view";
export class MinerSystem extends GameSystemWithFilter { export class MinerSystem extends GameSystemWithFilter {

View File

@ -18,12 +18,19 @@ export const enumHubGoalRewards = {
reward_rotater_180: "reward_rotater_180", reward_rotater_180: "reward_rotater_180",
reward_miner_chainable: "reward_miner_chainable", reward_miner_chainable: "reward_miner_chainable",
reward_underground_belt_tier_2: "reward_underground_belt_tier_2", reward_underground_belt_tier_2: "reward_underground_belt_tier_2",
reward_belt_reader: "reward_belt_reader",
reward_splitter: "reward_splitter", reward_splitter: "reward_splitter",
reward_cutter_quad: "reward_cutter_quad", reward_cutter_quad: "reward_cutter_quad",
reward_painter_double: "reward_painter_double", reward_painter_double: "reward_painter_double",
reward_painter_quad: "reward_painter_quad", reward_painter_quad: "reward_painter_quad",
reward_storage: "reward_storage", reward_storage: "reward_storage",
reward_merger: "reward_merger", reward_merger: "reward_merger",
reward_wires_filters_and_levers: "reward_wires_filters_and_levers",
reward_display: "reward_display",
reward_constant_signal: "reward_constant_signal",
reward_logic_gates: "reward_logic_gates",
reward_virtual_processing: "reward_virtual_processing",
reward_second_wire: "reward_second_wire",
reward_blueprints: "reward_blueprints", reward_blueprints: "reward_blueprints",
reward_freeplay: "reward_freeplay", reward_freeplay: "reward_freeplay",
@ -99,11 +106,11 @@ export const tutorialGoals = [
{ {
shape: "CpCpCpCp", // belts t3 shape: "CpCpCpCp", // belts t3
required: 800, required: 800,
reward: enumHubGoalRewards.reward_splitter, reward: enumHubGoalRewards.reward_merger,
}, },
// 10 // 10
// Star shape + cyan // STACKER: Star shape + cyan
{ {
shape: "ScScScSc", // miners t3 shape: "ScScScSc", // miners t3
required: 900, required: 900,
@ -111,7 +118,7 @@ export const tutorialGoals = [
}, },
// 11 // 11
// Stacker // Chainable miner
{ {
shape: "CgScScCg", // processors t3 shape: "CgScScCg", // processors t3
required: 1000, required: 1000,
@ -127,6 +134,7 @@ export const tutorialGoals = [
}, },
// 13 // 13
// Tunnel Tier 2
{ {
shape: "RpRpRpRp:CwCwCwCw", // painting t3 shape: "RpRpRpRp:CwCwCwCw", // painting t3
required: 5000, required: 5000,
@ -134,44 +142,121 @@ export const tutorialGoals = [
}, },
// 14 // 14
// Belt reader
{
// @todo
shape: "CuCuCuCu",
required: 7000,
reward: enumHubGoalRewards.reward_belt_reader,
},
// 15
// Storage
{ {
shape: "SrSrSrSr:CyCyCyCy", // unused shape: "SrSrSrSr:CyCyCyCy", // unused
required: 7500, required: 7500,
reward: enumHubGoalRewards.reward_storage, reward: enumHubGoalRewards.reward_storage,
}, },
// 15 // 16
// Quad Cutter
{ {
shape: "SrSrSrSr:CyCyCyCy:SwSwSwSw", // belts t4 (two variants) shape: "SrSrSrSr:CyCyCyCy:SwSwSwSw", // belts t4 (two variants)
required: 15000, required: 12500,
reward: enumHubGoalRewards.reward_cutter_quad, reward: enumHubGoalRewards.reward_cutter_quad,
}, },
// 16 // 17
// Double painter
{ {
shape: "CbRbRbCb:CwCwCwCw:WbWbWbWb", // miner t4 (two variants) shape: "CbRbRbCb:CwCwCwCw:WbWbWbWb", // miner t4 (two variants)
required: 20000, required: 15000,
reward: enumHubGoalRewards.reward_painter_double, reward: enumHubGoalRewards.reward_painter_double,
}, },
// 17 // 18
// Rotater (180deg)
{ {
shape: "CbRbRbCb:CwCwCwCw:WbWbWbWb", // rotater 180 // @TODO
required: 25000, shape: "CuCuCuCu",
required: 20000,
reward: enumHubGoalRewards.reward_rotater_180, reward: enumHubGoalRewards.reward_rotater_180,
}, },
// 18 // 19
// Compact splitter
{ {
shape: "WrRgWrRg:CwCrCwCr:SgSgSgSg", // processors t4 (two variants) // @TODO
required: 30000, shape: "CuCuCuCu",
reward: enumHubGoalRewards.reward_painter_quad, required: 25000,
reward: enumHubGoalRewards.reward_splitter,
}, },
// 19 // 20
// WIRES
{ {
shape: finalGameShape, shape: finalGameShape,
required: 50000, required: 50000,
reward: enumHubGoalRewards.reward_wires_filters_and_levers,
},
// 21
// Display
{
// @TODO
shape: "CuCuCuCu",
required: 25000,
reward: enumHubGoalRewards.reward_display,
},
// 22
// Constant signal
{
// @TODO
shape: "CuCuCuCu",
required: 30000,
reward: enumHubGoalRewards.reward_constant_signal,
},
// 23
// Quad Painter
{
// @TODO
shape: "CuCuCuCu",
// shape: "WrRgWrRg:CwCrCwCr:SgSgSgSg", // processors t4 (two variants)
required: 35000,
reward: enumHubGoalRewards.reward_painter_quad,
},
// 24 Logic gates
{
// @TODO
shape: "CuCuCuCu",
required: 40000,
reward: enumHubGoalRewards.reward_logic_gates,
},
// 25 Virtual Processing
{
// @TODO
shape: "CuCuCuCu",
required: 45000,
reward: enumHubGoalRewards.reward_virtual_processing,
},
// 26 Secondary type of wire
{
// @TODO
shape: "CuCuCuCu",
required: 50000,
reward: enumHubGoalRewards.reward_second_wire,
},
// 27 Freeplay
{
// @TODO
shape: "CuCuCuCu",
required: 100000,
reward: enumHubGoalRewards.reward_freeplay, reward: enumHubGoalRewards.reward_freeplay,
}, },
]; ];

View File

@ -1,16 +1,19 @@
import { MetaBuilding, defaultBuildingVariant } from "./meta_building"; import { T } from "../translations";
import { MetaCutterBuilding, enumCutterVariants } from "./buildings/cutter"; import { enumBalancerVariants, MetaBalancerBuilding } from "./buildings/balancer";
import { MetaRotaterBuilding, enumRotaterVariants } from "./buildings/rotater"; import { MetaConstantSignalBuilding } from "./buildings/constant_signal";
import { MetaPainterBuilding, enumPainterVariants } from "./buildings/painter"; import { enumCutterVariants, MetaCutterBuilding } from "./buildings/cutter";
import { MetaDisplayBuilding } from "./buildings/display";
import { MetaLeverBuilding } from "./buildings/lever";
import { enumMinerVariants, MetaMinerBuilding } from "./buildings/miner";
import { MetaMixerBuilding } from "./buildings/mixer"; import { MetaMixerBuilding } from "./buildings/mixer";
import { enumPainterVariants, MetaPainterBuilding } from "./buildings/painter";
import { MetaReaderBuilding } from "./buildings/reader";
import { enumRotaterVariants, MetaRotaterBuilding } from "./buildings/rotater";
import { MetaStackerBuilding } from "./buildings/stacker"; import { MetaStackerBuilding } from "./buildings/stacker";
import { MetaBalancerBuilding, enumBalancerVariants } from "./buildings/balancer"; import { MetaStorageBuilding } from "./buildings/storage";
import { MetaUndergroundBeltBuilding, enumUndergroundBeltVariants } from "./buildings/underground_belt"; import { enumUndergroundBeltVariants, MetaUndergroundBeltBuilding } from "./buildings/underground_belt";
import { MetaMinerBuilding, enumMinerVariants } from "./buildings/miner"; import { defaultBuildingVariant, MetaBuilding } from "./meta_building";
import { MetaTrashBuilding, enumTrashVariants } from "./buildings/trash";
/** @typedef {Array<[typeof MetaBuilding, string]>} TutorialGoalReward */ /** @typedef {Array<[typeof MetaBuilding, string]>} TutorialGoalReward */
import { enumHubGoalRewards } from "./tutorial_goals"; import { enumHubGoalRewards } from "./tutorial_goals";
/** /**
@ -43,9 +46,41 @@ export const enumHubGoalRewardsToContentUnlocked = {
[enumHubGoalRewards.reward_cutter_quad]: typed([[MetaCutterBuilding, enumCutterVariants.quad]]), [enumHubGoalRewards.reward_cutter_quad]: typed([[MetaCutterBuilding, enumCutterVariants.quad]]),
[enumHubGoalRewards.reward_painter_double]: typed([[MetaPainterBuilding, enumPainterVariants.double]]), [enumHubGoalRewards.reward_painter_double]: typed([[MetaPainterBuilding, enumPainterVariants.double]]),
[enumHubGoalRewards.reward_painter_quad]: typed([[MetaPainterBuilding, enumPainterVariants.quad]]), [enumHubGoalRewards.reward_painter_quad]: typed([[MetaPainterBuilding, enumPainterVariants.quad]]),
[enumHubGoalRewards.reward_storage]: typed([[MetaTrashBuilding, enumTrashVariants.storage]]), [enumHubGoalRewards.reward_storage]: typed([[MetaStorageBuilding, defaultBuildingVariant]]),
[enumHubGoalRewards.reward_belt_reader]: typed([[MetaReaderBuilding, defaultBuildingVariant]]),
[enumHubGoalRewards.reward_display]: typed([[MetaDisplayBuilding, defaultBuildingVariant]]),
[enumHubGoalRewards.reward_constant_signal]: typed([
[MetaConstantSignalBuilding, defaultBuildingVariant],
]),
[enumHubGoalRewards.reward_second_wire]: null, // @TODO!
[enumHubGoalRewards.reward_logic_gates]: null, // @TODO!
[enumHubGoalRewards.reward_virtual_processing]: null, // @TODO!
[enumHubGoalRewards.reward_wires_filters_and_levers]: typed([
[MetaLeverBuilding, defaultBuildingVariant],
]),
[enumHubGoalRewards.reward_freeplay]: null, [enumHubGoalRewards.reward_freeplay]: null,
[enumHubGoalRewards.reward_blueprints]: null,
[enumHubGoalRewards.no_reward]: null, [enumHubGoalRewards.no_reward]: null,
[enumHubGoalRewards.no_reward_freeplay]: null, [enumHubGoalRewards.no_reward_freeplay]: null,
}; };
if (G_IS_DEV) {
// Sanity check
for (const rewardId in enumHubGoalRewards) {
const mapping = enumHubGoalRewardsToContentUnlocked[rewardId];
if (typeof mapping === "undefined") {
assertAlways(
false,
"Please define a mapping for the reward " + rewardId + " in tutorial_goals_mappings.js"
);
}
const translation = T.storyRewards[rewardId];
if (!translation || !translation.title || !translation.desc) {
assertAlways(false, "Translation for reward " + rewardId + "missing");
}
}
}

View File

@ -38,7 +38,7 @@ export const UPGRADES = {
required: [{ shape: "SrSrSrSr:CyCyCyCy:SwSwSwSw", amount: 20000 }], required: [{ shape: "SrSrSrSr:CyCyCyCy:SwSwSwSw", amount: 20000 }],
}, },
{ {
required: [{ shape: finalGameShape, amount: 75000 }], required: [{ shape: finalGameShape, amount: 50000 }],
excludePrevious: true, excludePrevious: true,
}, },
], ],
@ -60,7 +60,7 @@ export const UPGRADES = {
required: [{ shape: "CbRbRbCb:CwCwCwCw:WbWbWbWb", amount: 30000 }], required: [{ shape: "CbRbRbCb:CwCwCwCw:WbWbWbWb", amount: 30000 }],
}, },
{ {
required: [{ shape: finalGameShape, amount: 85000 }], required: [{ shape: finalGameShape, amount: 65000 }],
excludePrevious: true, excludePrevious: true,
}, },
], ],
@ -82,7 +82,7 @@ export const UPGRADES = {
required: [{ shape: "WrRgWrRg:CwCrCwCr:SgSgSgSg", amount: 30000 }], required: [{ shape: "WrRgWrRg:CwCrCwCr:SgSgSgSg", amount: 30000 }],
}, },
{ {
required: [{ shape: finalGameShape, amount: 100000 }], required: [{ shape: finalGameShape, amount: 75000 }],
excludePrevious: true, excludePrevious: true,
}, },
], ],
@ -104,7 +104,7 @@ export const UPGRADES = {
required: [{ shape: "WpWpWpWp:CwCwCwCw:WpWpWpWp:CwCwCwCw", amount: 30000 }], required: [{ shape: "WpWpWpWp:CwCwCwCw:WpWpWpWp:CwCwCwCw", amount: 30000 }],
}, },
{ {
required: [{ shape: finalGameShape, amount: 125000 }], required: [{ shape: finalGameShape, amount: 100000 }],
excludePrevious: true, excludePrevious: true,
}, },
], ],

View File

@ -1,5 +1,6 @@
import { gMetaBuildingRegistry } from "../../core/global_registries.js"; import { gMetaBuildingRegistry } from "../../core/global_registries.js";
import { createLogger } from "../../core/logging.js"; import { createLogger } from "../../core/logging.js";
import { enumBalancerVariants, MetaBalancerBuilding } from "../../game/buildings/balancer.js";
import { MetaBeltBuilding } from "../../game/buildings/belt.js"; import { MetaBeltBuilding } from "../../game/buildings/belt.js";
import { enumCutterVariants, MetaCutterBuilding } from "../../game/buildings/cutter.js"; import { enumCutterVariants, MetaCutterBuilding } from "../../game/buildings/cutter.js";
import { MetaHubBuilding } from "../../game/buildings/hub.js"; import { MetaHubBuilding } from "../../game/buildings/hub.js";
@ -7,9 +8,9 @@ import { enumMinerVariants, MetaMinerBuilding } from "../../game/buildings/miner
import { MetaMixerBuilding } from "../../game/buildings/mixer.js"; import { MetaMixerBuilding } from "../../game/buildings/mixer.js";
import { enumPainterVariants, MetaPainterBuilding } from "../../game/buildings/painter.js"; import { enumPainterVariants, MetaPainterBuilding } from "../../game/buildings/painter.js";
import { enumRotaterVariants, MetaRotaterBuilding } from "../../game/buildings/rotater.js"; import { enumRotaterVariants, MetaRotaterBuilding } from "../../game/buildings/rotater.js";
import { enumBalancerVariants, MetaBalancerBuilding } from "../../game/buildings/balancer.js";
import { MetaStackerBuilding } from "../../game/buildings/stacker.js"; import { MetaStackerBuilding } from "../../game/buildings/stacker.js";
import { enumTrashVariants, MetaTrashBuilding } from "../../game/buildings/trash.js"; import { MetaStorageBuilding } from "../../game/buildings/storage.js";
import { MetaTrashBuilding } from "../../game/buildings/trash.js";
import { import {
enumUndergroundBeltVariants, enumUndergroundBeltVariants,
MetaUndergroundBeltBuilding, MetaUndergroundBeltBuilding,
@ -126,9 +127,11 @@ export class SavegameInterface_V1006 extends SavegameInterface_V1005 {
), ),
"sprites/blueprints/painter-quad.png": findCode(MetaPainterBuilding, enumPainterVariants.quad), "sprites/blueprints/painter-quad.png": findCode(MetaPainterBuilding, enumPainterVariants.quad),
// Trash / Storage // Trash
"sprites/blueprints/trash.png": findCode(MetaTrashBuilding), "sprites/blueprints/trash.png": findCode(MetaTrashBuilding),
"sprites/blueprints/trash-storage.png": findCode(MetaTrashBuilding, enumTrashVariants.storage),
// Storage
"sprites/blueprints/trash-storage.png": findCode(MetaStorageBuilding),
}; };
} }

View File

@ -557,9 +557,10 @@ buildings:
name: &trash Trash name: &trash Trash
description: Accepts inputs from all sides and destroys them. Forever. description: Accepts inputs from all sides and destroys them. Forever.
storage: storage:
name: Storage default:
description: Stores excess items, up to a given capacity. Can be used as an overflow gate. name: &storage Storage
description: Stores excess items, up to a given capacity. Prioritizes the left output and can be used as an overflow gate.
wire: wire:
default: default:
@ -578,12 +579,12 @@ buildings:
constant_signal: constant_signal:
default: default:
name: &constant_signal Constant Signal name: &constant_signal Constant Signal
description: Emits a constant signal (shape, color or boolean). description: Emits a constant signal, which can be either a shape, color or boolean.
lever: lever:
default: default:
name: &lever Switch name: &lever Switch
description: Can be toggled to emit 1 / 0 description: Can be toggled to emit a boolean signal, which can then be used to control for example an item filter.
logic_gate: logic_gate:
default: default:
@ -606,20 +607,17 @@ buildings:
filter: filter:
default: default:
name: &filter Filter name: &filter Filter
# TEMP description: Connect with a signal to route all matching items to the top and the remaining to the right. Can be controlled with boolean signals too.
description: Only allows through items which match exactly the provided shape / color. If you put in a boolean 1, it allows everything through, if you put in a 0 it will allow nothing through.
display: display:
default: default:
name: &display Display name: &display Display
# TEMP description: Connect a signal to show it on the display - It can be a shape, color or boolean.
description: Can be connected on the wires layer to show a color or shape. When inputting a boolean item, the display will be white if the value is 1.
reader: reader:
default: default:
name: &reader Belt Reader name: &reader Belt Reader
# TEMP description: Allows to measure belt throughput. Outputs the last read item on the wires layer (once unlocked).
description: Allows to read the current item from a belt, as well as measuring the throughput.
virtual_processor: virtual_processor:
default: default:
@ -670,8 +668,8 @@ storyRewards:
desc: The <strong>mixer</strong> has been unlocked - Combine two colors using <strong>additive blending</strong> with this building! desc: The <strong>mixer</strong> has been unlocked - Combine two colors using <strong>additive blending</strong> with this building!
reward_stacker: reward_stacker:
title: Combiner title: Stacker
desc: You can now combine shapes with the <strong>combiner</strong>! Both inputs are combined, and if they can be put next to each other, they will be <strong>fused</strong>. If not, the right input is <strong>stacked on top</strong> of the left input! desc: You can now combine shapes with the <strong>stacker</strong>! Both inputs are combined, and if they can be put next to each other, they will be <strong>fused</strong>. If not, the right input is <strong>stacked on top</strong> of the left input!
reward_balancer: reward_balancer:
title: Balancer title: Balancer
@ -687,7 +685,9 @@ storyRewards:
reward_miner_chainable: reward_miner_chainable:
title: Chaining Extractor title: Chaining Extractor
desc: You have unlocked the <strong>chaining extractor</strong>! It can <strong>forward its resources</strong> to other extractors so you can more efficiently extract resources! desc: >-
You have unlocked the <strong>chained extractor</strong>! It can <strong>forward its resources</strong> to other extractors so you can more efficiently extract resources!<br><br>
PS: The old extractor has been replaced in your toolbar now!
reward_underground_belt_tier_2: reward_underground_belt_tier_2:
title: Tunnel Tier II title: Tunnel Tier II
@ -701,10 +701,15 @@ storyRewards:
reward_splitter: reward_splitter:
title: Compact Splitter title: Compact Splitter
desc: >- desc: >-
You have unlocked a merger variant of the <strong>balancer</strong> - It accepts one input and splits them into two! You have unlocked a splitter variant of the <strong>balancer</strong> - It accepts one input and splits them into two!
reward_belt_reader:
title: Belt reader
desc: >-
You have now unlocked the <strong>belt reader</strong>! It allows you to measure the throughput of a belt.<br><br>And wait until you unlock wires - then it gets really useful!
reward_cutter_quad: reward_cutter_quad:
title: Quad Cutting title: Quad Cutter
desc: You have unlocked a variant of the <strong>cutter</strong> - It allows you to cut shapes in <strong>four parts</strong> instead of just two! desc: You have unlocked a variant of the <strong>cutter</strong> - It allows you to cut shapes in <strong>four parts</strong> instead of just two!
reward_painter_double: reward_painter_double:
@ -713,15 +718,15 @@ storyRewards:
reward_painter_quad: reward_painter_quad:
title: Quad Painting title: Quad Painting
desc: You have unlocked a variant of the <strong>painter</strong> - It allows you to paint each part of the shape individually! desc: >-
You have unlocked a variant of the <strong>painter</strong> - It allows you to paint each part of the shape individually!<br><br>
To use it, connect each slot which should be painted on the wires layer!
reward_storage: reward_storage:
title: Storage Buffer title: Storage Buffer
desc: You have unlocked a variant of the <strong>trash</strong> - It allows you to store items up to a given capacity! desc: >-
You have unlocked the <strong>storage</strong> building - It allows you to store items up to a given capacity!<br><br>
reward_freeplay: It priorities the left output, so you can also use it as an <strong>overflow gate</strong>!
title: Freeplay
desc: You did it! You unlocked the <strong>free-play mode</strong>! This means that shapes are now randomly generated! (No worries, more content is planned for the standalone!)
reward_blueprints: reward_blueprints:
title: Blueprints title: Blueprints
@ -731,6 +736,45 @@ storyRewards:
title: Rotater (180 degrees) title: Rotater (180 degrees)
desc: You just unlocked the 180 degress <strong>rotater</strong>! - It allows you to rotate a shape by 180 degress (Surprise! :D) desc: You just unlocked the 180 degress <strong>rotater</strong>! - It allows you to rotate a shape by 180 degress (Surprise! :D)
reward_wires_filters_and_levers:
title: >-
Wires: Filters & Levers
desc: >-
You just unlocked the <strong>wires layer</strong>! It is a separate layer on top of the regular layer and introduces a lot of new mechanics!<br><br>
Since it can be overwhelming a bit, I added a small tutorial - Be sure to have <strong>tutorials enabled</strong> in the settings!
reward_display:
title: Display
desc: >-
You have unlocked the <strong>Display</strong>! Connect a wires signal to it to present a color, shape or boolean!
reward_constant_signal:
title: Constant Signal
desc: >-
You can now emit a <strong>constant signal</strong> on the wires layer! This is useful to connect it to <strong>item filters</strong> for example!
reward_logic_gates:
title: Logic Gates
desc: >-
You unlocked <strong>logic gates</strong>! You don't have to be excited about this, but it's actually super cool!<br><br>
With those gates you can now perform AND, OR, XOR and NOT boolean operations!
reward_virtual_processing:
title: Virtual Processing
desc: >-
I just gave a whole bunch of new buildings which allow you to <strong>simulate the processing of shapes</strong>!<br><br>
You can now simulate a cutter, rotater, stacker and more on the wires layer!<br><br>
With this you now have three options to continue the game:<br><br>
- Build an <strong>automated machine</strong> to create any possible shape requested by the hub (This is cool, I swear!).<br><br>
- Build something cool with wires.<br><br>
- Continue to play regulary.
reward_second_wire:
title: Second Wire Type
desc: >-
Annoyed by wires automatically connecting? I just gave you another <strong>type of wire</strong>!<br><br>
Different types of wires do not connect to each other, so you can now build much compacter circuits.
# Special reward, which is shown when there is no reward actually # Special reward, which is shown when there is no reward actually
no_reward: no_reward:
title: Next level title: Next level
@ -742,6 +786,12 @@ storyRewards:
desc: >- desc: >-
Congratulations! By the way, more content is planned for the standalone! Congratulations! By the way, more content is planned for the standalone!
reward_freeplay:
title: Freeplay
desc: >-
You did it! You unlocked the <strong>free-play mode</strong>! This means that shapes are now <strong>randomly</strong> generated!<br><br>
Since the hub will only require low quantities, I highly recommend to build a machine which automatically delivers the requested shape!
settings: settings:
title: Settings title: Settings
categories: categories:
@ -980,6 +1030,7 @@ keybindings:
mixer: *mixer mixer: *mixer
painter: *painter painter: *painter
trash: *trash trash: *trash
storage: *storage
wire: *wire wire: *wire
constant_signal: *constant_signal constant_signal: *constant_signal
logic_gate: *logic_gate logic_gate: *logic_gate
@ -988,6 +1039,7 @@ keybindings:
wire_tunnel: *wire_tunnel wire_tunnel: *wire_tunnel
display: *display display: *display
reader: *reader reader: *reader
virtual_processor: *virtual_processor
# --- # ---
pipette: Pipette pipette: Pipette
@ -1082,10 +1134,11 @@ tips:
- Use <b>CTRL</b> + Click to select an area. - Use <b>CTRL</b> + Click to select an area.
- Building too close to the hub can get in the way of later projects. - Building too close to the hub can get in the way of later projects.
- The pin icon next to each shape in the upgrade list pins it to the screen. - The pin icon next to each shape in the upgrade list pins it to the screen.
- Mix all primary colours together to make white! - Mix all primary colors together to make white!
- You have an infinite map, don't cramp your factory, expand! - You have an infinite map, don't cramp your factory, expand!
- Also try Factorio! It's my favourite game. - Also try Factorio! It's my favorite game.
- The quad cutter cuts clockwise starting from the top right! - The quad cutter cuts clockwise starting from the top right!
- You can download your savegames in the main menu! - You can download your savegames in the main menu!
- This game has a lot of useful keybindings! Be sure to check out the settings page. - This game has a lot of useful keybindings! Be sure to check out the settings page.
- This game has a lot of settings, be sure to check them out! - This game has a lot of settings, be sure to check them out!
- The marker to your hub has a small compass to indicate its direction!