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

Merge pull request #9 from tobspr/master

Update
This commit is contained in:
Killgaru 2020-06-22 14:18:08 +03:00 committed by GitHub
commit 375b581c28
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
138 changed files with 8961 additions and 4609 deletions

1
.gitignore vendored
View File

@ -115,3 +115,4 @@ tmp_standalone_files
# Local config # Local config
config.local.js config.local.js
.DS_Store

9
.vscode/extensions.json vendored Normal file
View File

@ -0,0 +1,9 @@
{
// See https://go.microsoft.com/fwlink/?LinkId=827846 to learn about workspace recommendations.
// Extension identifier format: ${publisher}.${name}. Example: vscode.csharp
// List of extensions which should be recommended for users of this workspace.
"recommendations": ["esbenp.prettier-vscode"],
// List of extensions recommended by VS Code that should not be recommended for users of this workspace.
"unwantedRecommendations": []
}

View File

@ -16,7 +16,7 @@ Your goal is to produce shapes by cutting, rotating, merging and painting parts
- Make sure git `git lfs` extension is on your path - Make sure git `git lfs` extension is on your path
- Run `git lfs pull` to download sound assets - Run `git lfs pull` to download sound assets
- Make sure `ffmpeg` is on your path - Make sure `ffmpeg` is on your path
- Install Yarn and Node.js 10 - Install Node.js and Yarn
- Run `yarn` in the root folder, then run `yarn` in the `gulp/` folder - Run `yarn` in the root folder, then run `yarn` in the `gulp/` folder
- Cd into `gulp` and run `yarn gulp` - it should now open in your browser - Cd into `gulp` and run `yarn gulp` - it should now open in your browser

View File

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:6463b33b2cae50d1ecb11f0a845f06633aff331a5c2c0998d9eb93e40ad576b1 oid sha256:7d05e340acb18f7b6b6f05fa7536f14179cda54a9ead0923fbb8e39c68da148c
size 636254 size 703229

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 MiB

BIN
artwork/reddit/banner.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 597 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 63 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 17 KiB

View File

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:47b6aca7fe07f4628b041f32ce813a840793cfdce8ffa27c7ff4562858ac05f9 oid sha256:ebde52e75e54d2f4add0cf498c85f059082a0745212a23c4de7328a7d78b00a5
size 194245 size 238170

BIN
artwork/steam/devlog.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

3
artwork/steam/devlog.psd Normal file
View File

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:746c6cf3f0284798a78c08f77d7e9d0c28b02323081fda42b5fa876a7ade29a0
size 205925

Binary file not shown.

After

Width:  |  Height:  |  Size: 380 KiB

View File

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:e0cd2d82917e470202d38d32277f7519ccfd1821cb21791266539ddf07486d1b
size 7314327

BIN
artwork/wires/prefab.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 132 KiB

3
artwork/wires/prefab.psd Normal file
View File

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:498dea7314b8720c40dcd8bdd64b1b4a7a35259b2ffe7e896fc3db22878d6414
size 1954036

BIN
electron/favicon.icns Normal file

Binary file not shown.

27
gulp/cordova.js vendored
View File

@ -2,13 +2,15 @@ const path = require("path");
const fs = require("fs"); const fs = require("fs");
const buildUtils = require("./buildutils"); const buildUtils = require("./buildutils");
export function gulptasksCordova($, gulp, buildFolder) { function gulptasksCordova($, gulp, buildFolder) {
const cdvRes = path.join("..", "..", "res"); const cdvRes = path.join("..", "..", "res");
// Cleans up the app assets // Cleans up the app assets
// Removes all temporary folders used while optimizing the assets // Removes all temporary folders used while optimizing the assets
gulp.task("cleanupAppAssetsBuiltFolder", () => { gulp.task("cleanupAppAssetsBuiltFolder", () => {
return gulp.src(path.join(cdvRes, "built"), { read: false }).pipe($.clean({ force: true })); return gulp
.src(path.join(cdvRes, "built"), { read: false, allowEmpty: true })
.pipe($.clean({ force: true }));
}); });
// Optimizes all built assets // Optimizes all built assets
@ -64,7 +66,7 @@ export function gulptasksCordova($, gulp, buildFolder) {
.pipe(gulp.dest(path.join(cdvRes, "built", "ios"))); .pipe(gulp.dest(path.join(cdvRes, "built", "ios")));
}); });
gulp.task("prepareIosRes", ["scaleIconIos", "copyOtherIosResources"]); gulp.task("prepareIosRes", gulp.series("scaleIconIos", "copyOtherIosResources"));
gulp.task("copyAndroidResources", () => { gulp.task("copyAndroidResources", () => {
return gulp return gulp
@ -72,19 +74,20 @@ export function gulptasksCordova($, gulp, buildFolder) {
.pipe(gulp.dest(path.join(cdvRes, "built", "android"))); .pipe(gulp.dest(path.join(cdvRes, "built", "android")));
}); });
gulp.task("prepareAndroidRes", ["copyAndroidResources"]); gulp.task("prepareAndroidRes", gulp.series("copyAndroidResources"));
gulp.task("prepareCordovaAssets", cb => { gulp.task(
return $.sequence( "prepareCordovaAssets",
gulp.series(
"cleanupAppAssetsBuiltFolder", "cleanupAppAssetsBuiltFolder",
["prepareIosRes", "prepareAndroidRes"], gulp.parallel("prepareIosRes", "prepareAndroidRes"),
"optimizeBuiltAppAssets" "optimizeBuiltAppAssets"
)(cb); )
}); );
// Patches the config.xml by replacing the app id to app_beta // Patches the config.xml by replacing the app id to app_beta
gulp.task("patchConfigXML", () => { gulp.task("patchConfigXML", cb => {
const configUrl = path.join("..", "..", "config.xml"); const configUrl = path.join("..", "..", "config.xml");
let configContent = fs.readFileSync(configUrl).toString(); let configContent = fs.readFileSync(configUrl).toString();
const version = buildUtils.getVersion(); const version = buildUtils.getVersion();
@ -92,14 +95,16 @@ export function gulptasksCordova($, gulp, buildFolder) {
configContent = configContent.replace(' id="io.shapez.app" ', ' id="io.shapez.app_beta" '); configContent = configContent.replace(' id="io.shapez.app" ', ' id="io.shapez.app_beta" ');
configContent = configContent.replace("<name>Shapez.io</name>", "<name>Shapez.io BETA</name>"); configContent = configContent.replace("<name>Shapez.io</name>", "<name>Shapez.io BETA</name>");
fs.writeFileSync(configUrl, configContent); fs.writeFileSync(configUrl, configContent);
cb();
}); });
gulp.task("patchConfigXMLChangeStagingToProd", () => { gulp.task("patchConfigXMLChangeStagingToProd", cb => {
const configUrl = path.join("..", "..", "config.xml"); const configUrl = path.join("..", "..", "config.xml");
let configContent = fs.readFileSync(configUrl).toString(); let configContent = fs.readFileSync(configUrl).toString();
configContent = configContent.replace(' id="io.shapez.app_beta" ', ' id="io.shapez.app" '); configContent = configContent.replace(' id="io.shapez.app_beta" ', ' id="io.shapez.app" ');
configContent = configContent.replace("<name>Shapez.io BETA</name>", "<name>Shapez.io</name>"); configContent = configContent.replace("<name>Shapez.io BETA</name>", "<name>Shapez.io</name>");
fs.writeFileSync(configUrl, configContent); fs.writeFileSync(configUrl, configContent);
cb();
}); });
// Triggers a new build on phonegap // Triggers a new build on phonegap

View File

@ -13,7 +13,7 @@ function gulptasksDocs($, gulp, buildFolder) {
.pipe(gulp.dest(path.join("..", "tsc_temp"))); .pipe(gulp.dest(path.join("..", "tsc_temp")));
}); });
gulp.task("docs.copyTsconfigForHints", () => { gulp.task("docs.copyTsconfigForHints", cb => {
const src = fs.readFileSync(path.join("..", "src", "js", "tsconfig.json")).toString(); const src = fs.readFileSync(path.join("..", "src", "js", "tsconfig.json")).toString();
const baseConfig = JSON.parse($.stripJsonComments(src)); const baseConfig = JSON.parse($.stripJsonComments(src));
@ -28,9 +28,10 @@ function gulptasksDocs($, gulp, buildFolder) {
baseConfig.composite = true; baseConfig.composite = true;
baseConfig.outFile = "bundled-ts.js"; baseConfig.outFile = "bundled-ts.js";
fs.writeFileSync(path.join("..", "tsc_temp", "tsconfig.json"), JSON.stringify(baseConfig)); fs.writeFileSync(path.join("..", "tsc_temp", "tsconfig.json"), JSON.stringify(baseConfig));
cb();
}); });
gulp.task("main.prepareDocs", $.sequence("docs.convertJsToTs", "docs.copyTsconfigForHints")); gulp.task("main.prepareDocs", gulp.series("docs.convertJsToTs", "docs.copyTsconfigForHints"));
} }
module.exports = { module.exports = {

View File

@ -28,7 +28,7 @@ function gulptasksFTP($, gulp, buildFolder) {
}; };
// Write the "commit.txt" file // Write the "commit.txt" file
gulp.task("ftp.writeVersion", () => { gulp.task("ftp.writeVersion", cb => {
fs.writeFileSync( fs.writeFileSync(
path.join(buildFolder, "version.json"), path.join(buildFolder, "version.json"),
JSON.stringify( JSON.stringify(
@ -41,6 +41,7 @@ function gulptasksFTP($, gulp, buildFolder) {
4 4
) )
); );
cb();
}); });
const gameSrcGlobs = [ const gameSrcGlobs = [
@ -78,14 +79,15 @@ function gulptasksFTP($, gulp, buildFolder) {
.pipe($.sftp(deployCredentials)); .pipe($.sftp(deployCredentials));
}); });
gulp.task(`ftp.upload.${deployEnv}`, cb => { gulp.task(
$.sequence( `ftp.upload.${deployEnv}`,
gulp.series(
"ftp.writeVersion", "ftp.writeVersion",
`ftp.upload.${deployEnv}.game`, `ftp.upload.${deployEnv}.game`,
`ftp.upload.${deployEnv}.indexHtml`, `ftp.upload.${deployEnv}.indexHtml`,
`ftp.upload.${deployEnv}.additionalFiles` `ftp.upload.${deployEnv}.additionalFiles`
)(cb); )
}); );
} }
} }

View File

@ -1,11 +1,5 @@
/* eslint-disable */ /* eslint-disable */
const nodeVersion = process.versions.node.split(".")[0];
if (nodeVersion !== "10") {
console.error("This cli requires exactly Node.js 10. You are using Node.js " + nodeVersion);
process.exit(1);
}
require("colors"); require("colors");
const gulp = require("gulp"); const gulp = require("gulp");
@ -95,15 +89,15 @@ translations.gulptasksTranslations($, gulp, buildFolder);
// Cleans up everything // Cleans up everything
gulp.task("utils.cleanBuildFolder", () => { gulp.task("utils.cleanBuildFolder", () => {
return gulp.src(buildFolder, { read: false }).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 }) .src(path.join(__dirname, "..", "src", "js", "built-temp"), { read: false, allowEmpty: true })
.pipe($.clean({ force: true })); .pipe($.clean({ force: true }));
}); });
gulp.task("utils.cleanup", $.sequence("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 => {
@ -166,71 +160,66 @@ function serve({ standalone }) {
}); });
// Watch .scss files, those trigger a css rebuild // Watch .scss files, those trigger a css rebuild
gulp.watch(["../src/**/*.scss"], ["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", [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"], ["sounds.dev"]); // gulp.watch(["../res_raw/sounds/**/*.mp3", "../res_raw/sounds/**/*.wav"], gulp.series("sounds.dev"));
// Watch translations // Watch translations
gulp.watch("../translations/**/*.yaml", ["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"],
$.sequence("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"],
$.sequence("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, ["imgres.copyNonImageResources"]); gulp.watch(imgres.nonImageResourcesGlobs, gulp.series("imgres.copyNonImageResources"));
gulp.watch(imgres.imageResourcesGlobs, ["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", ["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 (e) { gulp.watch(extensions.map(ext => path.join(buildFolder, "**", "*." + ext))).on("change", function (path) {
return gulp.src(e.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 (e) { gulp.watch("../src/js/built-temp/*.json").on("change", function (path) {
return gulp.src(e.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) {
$.sequence("js.standalone-dev.watch")(() => true); gulp.series("js.standalone-dev.watch")(() => true);
} else { } else {
$.sequence("js.dev.watch")(() => true); gulp.series("js.dev.watch")(() => true);
} }
} }
// Live-development
gulp.task("main.serveDev", ["build.dev"], () => serve({ standalone: false }));
gulp.task("main.serveStandalone", ["build.standalone.dev"], () => serve({ standalone: true }));
gulp.task("default", ["main.serveDev"]);
///////////////////// RUNNABLE TASKS ///////////////////// ///////////////////// RUNNABLE TASKS /////////////////////
// Pre and postbuild // Pre and postbuild
gulp.task("step.baseResources", cb => $.sequence("imgres.allOptimized")(cb)); 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", $.sequence("imgres.cleanupUnusedCssInlineImages", "step.deleteEmpty")); gulp.task("step.postbuild", gulp.series("imgres.cleanupUnusedCssInlineImages", "step.deleteEmpty"));
// Builds everything (dev) // Builds everything (dev)
gulp.task("build.dev", cb => { gulp.task(
$.sequence( "build.dev",
gulp.series(
"utils.cleanup", "utils.cleanup",
"utils.copyAdditionalBuildFiles", "utils.copyAdditionalBuildFiles",
"imgres.atlas", "imgres.atlas",
@ -240,12 +229,13 @@ gulp.task("build.dev", cb => {
"translations.fullBuild", "translations.fullBuild",
"css.dev", "css.dev",
"html.dev" "html.dev"
)(cb); )
}); );
// Builds everything (standalone -dev) // Builds everything (standalone -dev)
gulp.task("build.standalone.dev", cb => { gulp.task(
$.sequence( "build.standalone.dev",
gulp.series(
"utils.cleanup", "utils.cleanup",
"imgres.atlas", "imgres.atlas",
"sounds.dev", "sounds.dev",
@ -255,58 +245,74 @@ gulp.task("build.standalone.dev", cb => {
"js.standalone-dev", "js.standalone-dev",
"css.dev", "css.dev",
"html.standalone-dev" "html.standalone-dev"
)(cb); )
}); );
// Builds everything (staging) // Builds everything (staging)
gulp.task("step.staging.code", $.sequence("sounds.fullbuild", "translations.fullBuild", "js.staging")); gulp.task("step.staging.code", gulp.series("sounds.fullbuild", "translations.fullBuild", "js.staging"));
gulp.task("step.staging.mainbuild", cb => gulp.task(
$.multiProcess(["utils.copyAdditionalBuildFiles", "step.baseResources", "step.staging.code"], cb, false) "step.staging.mainbuild",
gulp.parallel("utils.copyAdditionalBuildFiles", "step.baseResources", "step.staging.code")
); );
gulp.task("step.staging.all", $.sequence("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", $.sequence("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", $.sequence("sounds.fullbuild", "translations.fullBuild", "js.prod")); gulp.task("step.prod.code", gulp.series("sounds.fullbuild", "translations.fullBuild", "js.prod"));
gulp.task("step.prod.mainbuild", cb => gulp.task(
$.multiProcess(["utils.copyAdditionalBuildFiles", "step.baseResources", "step.prod.code"], cb, false) "step.prod.mainbuild",
gulp.parallel("utils.copyAdditionalBuildFiles", "step.baseResources", "step.prod.code")
); );
gulp.task("step.prod.all", $.sequence("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", $.sequence("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",
$.sequence("sounds.fullbuild", "translations.fullBuild", "js.standalone-beta") gulp.series("sounds.fullbuildHQ", "translations.fullBuild", "js.standalone-beta")
);
gulp.task("step.standalone-beta.mainbuild", cb =>
$.multiProcess(["step.baseResources", "step.standalone-beta.code"], cb, false)
); );
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",
$.sequence("step.standalone-beta.mainbuild", "css.prod-standalone", "html.standalone-beta") gulp.series("step.standalone-beta.mainbuild", "css.prod-standalone", "html.standalone-beta")
);
gulp.task(
"build.standalone-beta",
gulp.series("utils.cleanup", "step.standalone-beta.all", "step.postbuild")
); );
gulp.task("build.standalone-beta", $.sequence("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",
$.sequence("sounds.fullbuild", "translations.fullBuild", "js.standalone-prod") gulp.series("sounds.fullbuildHQ", "translations.fullBuild", "js.standalone-prod")
);
gulp.task("step.standalone-prod.mainbuild", cb =>
$.multiProcess(["step.baseResources", "step.standalone-prod.code"], cb, false)
); );
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",
$.sequence("step.standalone-prod.mainbuild", "css.prod-standalone", "html.standalone-prod") gulp.series("step.standalone-prod.mainbuild", "css.prod-standalone", "html.standalone-prod")
);
gulp.task(
"build.standalone-prod",
gulp.series("utils.cleanup", "step.standalone-prod.all", "step.postbuild")
); );
gulp.task("build.standalone-prod", $.sequence("utils.cleanup", "step.standalone-prod.all", "step.postbuild"));
// Deploying! // Deploying!
gulp.task( gulp.task(
"main.deploy.staging", "main.deploy.staging",
$.sequence("utils.requireCleanWorkingTree", "build.staging", "ftp.upload.staging") gulp.series("utils.requireCleanWorkingTree", "build.staging", "ftp.upload.staging")
); );
gulp.task("main.deploy.prod", $.sequence("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", $.sequence("main.deploy.staging", "main.deploy.prod")); gulp.task("main.deploy.all", gulp.series("main.deploy.staging", "main.deploy.prod"));
gulp.task("main.standalone", $.sequence("build.standalone-prod", "standalone.package.prod")); gulp.task("main.standalone", gulp.series("build.standalone-prod", "standalone.package.prod"));
// Live-development
gulp.task(
"main.serveDev",
gulp.series("build.dev", () => serve({ standalone: false }))
);
gulp.task(
"main.serveStandalone",
gulp.series("build.standalone.dev", () => serve({ standalone: true }))
);
gulp.task("default", gulp.series("main.serveDev"));

View File

@ -10,7 +10,7 @@ const imageResourcesGlobs = ["../res/**/*.png", "../res/**/*.svg", "../res/**/*.
function gulptasksImageResources($, gulp, buildFolder) { function gulptasksImageResources($, gulp, buildFolder) {
// Lossless options // Lossless options
const minifyImagesOptsLossless = () => [ const minifyImagesOptsLossless = () => [
$.imagemin.jpegtran({ $.imageminJpegtran({
progressive: true, progressive: true,
}), }),
$.imagemin.svgo({}), $.imagemin.svgo({}),
@ -25,7 +25,7 @@ function gulptasksImageResources($, gulp, buildFolder) {
// Lossy options // Lossy options
const minifyImagesOpts = () => [ const minifyImagesOpts = () => [
$.imageminMozjpeg({ $.imagemin.mozjpeg({
quality: 80, quality: 80,
maxMemory: 1024 * 1024 * 8, maxMemory: 1024 * 1024 * 8,
}), }),
@ -116,11 +116,12 @@ function gulptasksImageResources($, gulp, buildFolder) {
}); });
// Copies all resources and optimizes them // Copies all resources and optimizes them
gulp.task("imgres.allOptimized", cb => gulp.task(
$.multiProcess( "imgres.allOptimized",
["imgres.atlasOptimized", "imgres.copyNonImageResources", "imgres.copyImageResourcesOptimized"], gulp.parallel(
cb, "imgres.atlasOptimized",
false "imgres.copyNonImageResources",
"imgres.copyImageResourcesOptimized"
) )
); );

View File

@ -68,7 +68,7 @@ function gulptasksJS($, gulp, buildFolder, browserSync) {
) )
.pipe(gulp.dest(buildFolder)); .pipe(gulp.dest(buildFolder));
}); });
gulp.task("js.staging", cb => $.multiProcess(["js.staging.transpiled", "js.staging.latest"], cb, false)); gulp.task("js.staging", gulp.parallel("js.staging.transpiled", "js.staging.latest"));
//// PROD //// PROD
gulp.task("js.prod.transpiled", () => { gulp.task("js.prod.transpiled", () => {
@ -104,7 +104,7 @@ function gulptasksJS($, gulp, buildFolder, browserSync) {
.pipe(browserSync.stream()); .pipe(browserSync.stream());
}); });
gulp.task("js.prod", cb => $.multiProcess(["js.prod.transpiled", "js.prod.latest"], cb, false)); gulp.task("js.prod", gulp.parallel("js.prod.transpiled", "js.prod.latest"));
//// STANDALONE //// STANDALONE

View File

@ -70,40 +70,38 @@
"css-mqpacker": "^7.0.0", "css-mqpacker": "^7.0.0",
"cssnano": "^4.1.10", "cssnano": "^4.1.10",
"electron-packager": "^14.0.6", "electron-packager": "^14.0.6",
"imagemin-gifsicle": "^7.0.0",
"faster.js": "^1.1.0", "faster.js": "^1.1.0",
"glob": "^7.1.3", "glob": "^7.1.3",
"gulp": "^3.9.1", "gulp": "^4.0.2",
"gulp-cache": "^1.1.3", "gulp-cache": "^1.1.3",
"gulp-cached": "^1.1.1", "gulp-cached": "^1.1.1",
"gulp-clean": "^0.4.0", "gulp-clean": "^0.4.0",
"gulp-cssbeautify": "^1.0.1", "gulp-cssbeautify": "^2.0.1",
"gulp-csslint": "^1.0.1", "gulp-csslint": "^1.0.1",
"gulp-dom": "^1.0.0", "gulp-dom": "^1.0.0",
"gulp-flatten": "^0.4.0", "gulp-flatten": "^0.4.0",
"gulp-fluent-ffmpeg": "^1.0.2", "gulp-fluent-ffmpeg": "^2.0.0",
"gulp-html-beautify": "^1.0.1", "gulp-html-beautify": "^1.0.1",
"gulp-htmlmin": "^5.0.1", "gulp-htmlmin": "^5.0.1",
"gulp-if": "^2.0.2", "gulp-if": "^3.0.0",
"gulp-imagemin": "^5.0.3", "gulp-imagemin": "^7.1.0",
"gulp-javascript-obfuscator": "^1.1.5", "gulp-javascript-obfuscator": "^1.1.5",
"gulp-jsbeautifier": "^3.0.0", "gulp-jsbeautifier": "^3.0.0",
"gulp-load-plugins": "^1.5.0", "gulp-load-plugins": "^2.0.3",
"gulp-multi-process": "^1.3.1",
"gulp-phonegap-build": "^0.1.5", "gulp-phonegap-build": "^0.1.5",
"gulp-plumber": "^1.2.1", "gulp-plumber": "^1.2.1",
"gulp-pngquant": "^1.0.12", "gulp-pngquant": "^1.0.13",
"gulp-postcss": "^8.0.0", "gulp-postcss": "^8.0.0",
"gulp-rename": "^1.4.0", "gulp-rename": "^2.0.0",
"gulp-sass": "^4.0.1", "gulp-sass": "^4.1.0",
"gulp-sass-lint": "^1.4.0", "gulp-sass-lint": "^1.4.0",
"gulp-sequence": "^1.0.0", "gulp-sftp": "git+https://git@github.com/webksde/gulp-sftp",
"gulp-sftp": "^0.1.5",
"gulp-terser": "^1.2.0", "gulp-terser": "^1.2.0",
"gulp-webserver": "^0.9.1", "gulp-webserver": "^0.9.1",
"gulp-yaml": "^2.0.4", "gulp-yaml": "^2.0.4",
"imagemin-mozjpeg": "^8.0.0", "imagemin-gifsicle": "^7.0.0",
"imagemin-pngquant": "^8.0.0", "imagemin-jpegtran": "^7.0.0",
"imagemin-pngquant": "^9.0.0",
"jimp": "^0.6.1", "jimp": "^0.6.1",
"js-yaml": "^3.13.1", "js-yaml": "^3.13.1",
"onesky-fetch": "^0.0.7", "onesky-fetch": "^0.0.7",

View File

@ -3,11 +3,11 @@ const audiosprite = require("gulp-audiosprite");
function gulptasksSounds($, gulp, buildFolder) { function gulptasksSounds($, gulp, buildFolder) {
// Gather some basic infos // Gather some basic infos
const soundsDir = path.join("..", "res_raw", "sounds"); const soundsDir = path.join(__dirname, "..", "res_raw", "sounds");
const builtSoundsDir = path.join("..", "res_built", "sounds"); const builtSoundsDir = path.join(__dirname, "..", "res_built", "sounds");
gulp.task("sounds.clear", () => { gulp.task("sounds.clear", () => {
return gulp.src(builtSoundsDir).pipe($.clean({ force: true })); return gulp.src(builtSoundsDir, { read: false, allowEmpty: true }).pipe($.clean({ force: true }));
}); });
const filters = ["volume=0.2"]; const filters = ["volume=0.2"];
@ -29,7 +29,7 @@ function gulptasksSounds($, gulp, buildFolder) {
.audioChannels(1) .audioChannels(1)
.audioFrequency(22050) .audioFrequency(22050)
.audioCodec("libmp3lame") .audioCodec("libmp3lame")
.audioFilters(["volume=0.3"]); .audioFilters(["volume=0.15"]);
}), }),
{ {
name: "music", name: "music",
@ -40,6 +40,30 @@ function gulptasksSounds($, gulp, buildFolder) {
.pipe(gulp.dest(path.join(builtSoundsDir, "music"))); .pipe(gulp.dest(path.join(builtSoundsDir, "music")));
}); });
// Encodes the game music in high quality for the standalone
gulp.task("sounds.musicHQ", () => {
return gulp
.src([path.join(soundsDir, "music", "**", "*.wav"), path.join(soundsDir, "music", "**", "*.mp3")])
.pipe($.plumber())
.pipe(
$.cache(
$.fluentFfmpeg("mp3", function (cmd) {
return cmd
.audioBitrate(256)
.audioChannels(2)
.audioFrequency(44100)
.audioCodec("libmp3lame")
.audioFilters(["volume=0.15"]);
}),
{
name: "music-high-quality",
fileCache,
}
)
)
.pipe(gulp.dest(path.join(builtSoundsDir, "music")));
});
// Encodes the ui sounds // Encodes the ui sounds
gulp.task("sounds.sfxGenerateSprites", () => { gulp.task("sounds.sfxGenerateSprites", () => {
return gulp return gulp
@ -79,7 +103,7 @@ function gulptasksSounds($, gulp, buildFolder) {
gulp.task( gulp.task(
"sounds.sfx", "sounds.sfx",
$.sequence("sounds.sfxGenerateSprites", "sounds.sfxOptimize", "sounds.sfxCopyAtlas") gulp.series("sounds.sfxGenerateSprites", "sounds.sfxOptimize", "sounds.sfxCopyAtlas")
); );
gulp.task("sounds.copy", () => { gulp.task("sounds.copy", () => {
@ -90,10 +114,12 @@ function gulptasksSounds($, gulp, buildFolder) {
.pipe(gulp.dest(path.join(buildFolder, "res", "sounds"))); .pipe(gulp.dest(path.join(buildFolder, "res", "sounds")));
}); });
gulp.task("sounds.buildall", cb => $.multiProcess(["sounds.music", "sounds.sfx"], cb, true)); gulp.task("sounds.buildall", gulp.parallel("sounds.music", "sounds.sfx"));
gulp.task("sounds.buildallHQ", gulp.parallel("sounds.musicHQ", "sounds.sfx"));
gulp.task("sounds.fullbuild", cb => $.sequence("sounds.clear", "sounds.buildall", "sounds.copy")(cb)); gulp.task("sounds.fullbuild", gulp.series("sounds.clear", "sounds.buildall", "sounds.copy"));
gulp.task("sounds.dev", cb => $.sequence("sounds.buildall", "sounds.copy")(cb)); gulp.task("sounds.fullbuildHQ", gulp.series("sounds.clear", "sounds.buildallHQ", "sounds.copy"));
gulp.task("sounds.dev", gulp.series("sounds.buildall", "sounds.copy"));
} }
module.exports = { module.exports = {

View File

@ -6,13 +6,13 @@ const fse = require("fs-extra");
const execSync = require("child_process").execSync; const execSync = require("child_process").execSync;
function gulptasksStandalone($, gulp, buildFolder) { function gulptasksStandalone($, gulp, buildFolder) {
const electronBaseDir = path.join("../electron"); const electronBaseDir = path.join(__dirname, "..", "electron");
const tempDestDir = path.join("..", "tmp_standalone_files"); const tempDestDir = path.join(__dirname, "..", "tmp_standalone_files");
const tempDestBuildDir = path.join(tempDestDir, "built"); const tempDestBuildDir = path.join(tempDestDir, "built");
gulp.task("standalone.prepare.cleanup", () => { gulp.task("standalone.prepare.cleanup", () => {
return gulp.src(tempDestDir, { read: false }).pipe($.clean({ force: true })); return gulp.src(tempDestDir, { read: false, allowEmpty: true }).pipe($.clean({ force: true }));
}); });
gulp.task("standalone.prepare.copyPrefab", () => { gulp.task("standalone.prepare.copyPrefab", () => {
@ -30,7 +30,7 @@ function gulptasksStandalone($, gulp, buildFolder) {
return gulp.src(requiredFiles, { base: electronBaseDir }).pipe(gulp.dest(tempDestBuildDir)); return gulp.src(requiredFiles, { base: electronBaseDir }).pipe(gulp.dest(tempDestBuildDir));
}); });
gulp.task("standalone.prepare.writePackageJson", () => { gulp.task("standalone.prepare.writePackageJson", cb => {
fs.writeFileSync( fs.writeFileSync(
path.join(tempDestBuildDir, "package.json"), path.join(tempDestBuildDir, "package.json"),
JSON.stringify( JSON.stringify(
@ -43,67 +43,71 @@ function gulptasksStandalone($, gulp, buildFolder) {
4 4
) )
); );
cb();
}); });
gulp.task("standalone.prepare.minifyCode", () => { gulp.task("standalone.prepare.minifyCode", () => {
return gulp return (
gulp
.src(path.join(electronBaseDir, "*.js")) .src(path.join(electronBaseDir, "*.js"))
.pipe( // .pipe(
$.terser({ // $.terser({
ecma: 6, // ecma: 6,
parse: {}, // parse: {},
module: false, // module: false,
toplevel: true, // toplevel: true,
keep_classnames: false, // keep_classnames: false,
keep_fnames: false, // keep_fnames: false,
safari10: false, // safari10: false,
compress: { // compress: {
arguments: false, // breaks // arguments: false, // breaks
drop_console: false, // drop_console: false,
// keep_fargs: false, // // keep_fargs: false,
keep_infinity: true, // keep_infinity: true,
passes: 2, // passes: 2,
module: false, // module: false,
toplevel: true, // toplevel: true,
unsafe_math: true, // unsafe_math: true,
unsafe_arrows: false, // unsafe_arrows: false,
warnings: true, // warnings: true,
}, // },
mangle: { // mangle: {
eval: true, // eval: true,
keep_classnames: false, // keep_classnames: false,
keep_fnames: false, // keep_fnames: false,
module: false, // module: false,
toplevel: true, // toplevel: true,
safari10: false, // safari10: false,
}, // },
output: { // output: {
comments: false, // comments: false,
ascii_only: true, // ascii_only: true,
beautify: false, // beautify: false,
braces: false, // braces: false,
ecma: 6, // ecma: 6,
}, // },
}) // })
) // )
.pipe(gulp.dest(tempDestBuildDir)); .pipe(gulp.dest(tempDestBuildDir))
);
}); });
gulp.task("standalone.prepare.copyGamefiles", () => { gulp.task("standalone.prepare.copyGamefiles", () => {
return gulp.src("../build/**/*.*", { base: "../build" }).pipe(gulp.dest(tempDestBuildDir)); return gulp.src("../build/**/*.*", { base: "../build" }).pipe(gulp.dest(tempDestBuildDir));
}); });
gulp.task("standalone.killRunningInstances", () => { gulp.task("standalone.killRunningInstances", cb => {
try { try {
execSync("taskkill /F /IM shapezio.exe"); execSync("taskkill /F /IM shapezio.exe");
} catch (ex) { } catch (ex) {
console.warn("Failed to kill running instances, maybe none are up."); console.warn("Failed to kill running instances, maybe none are up.");
} }
cb();
}); });
gulp.task( gulp.task(
"standalone.prepare", "standalone.prepare",
$.sequence( gulp.series(
"standalone.killRunningInstances", "standalone.killRunningInstances",
"standalone.prepare.cleanup", "standalone.prepare.cleanup",
"standalone.prepare.copyPrefab", "standalone.prepare.copyPrefab",
@ -190,13 +194,16 @@ function gulptasksStandalone($, gulp, buildFolder) {
gulp.task( gulp.task(
"standalone.package.prod", "standalone.package.prod",
$.sequence("standalone.prepare", [ gulp.series(
"standalone.prepare",
gulp.parallel(
"standalone.package.prod.win64", "standalone.package.prod.win64",
"standalone.package.prod.linux64", "standalone.package.prod.linux64",
"standalone.package.prod.darwin64", "standalone.package.prod.darwin64"
// "standalone.package.prod.win32", // "standalone.package.prod.win32",
// "standalone.package.prod.linux32", // "standalone.package.prod.linux32",
]) )
)
); );
} }

View File

@ -14,7 +14,7 @@ function gulptasksTranslations($, gulp, buildFolder) {
.pipe(gulp.dest(translationsJsonDir)); .pipe(gulp.dest(translationsJsonDir));
}); });
gulp.task("translations.fullBuild", $.sequence("translations.convertToJson")); gulp.task("translations.fullBuild", gulp.series("translations.convertToJson"));
} }
module.exports = { module.exports = {

File diff suppressed because it is too large Load Diff

View File

@ -7,7 +7,7 @@
"license": "MIT", "license": "MIT",
"private": true, "private": true,
"scripts": { "scripts": {
"dev": "./gulp/gulp main.serveDev", "dev": "cd gulp && yarn gulp main.serveDev",
"tslint": "cd src/js && tsc", "tslint": "cd src/js && tsc",
"lint": "npx eslint src/js", "lint": "npx eslint src/js",
"prettier-all": "prettier --write src/**/*.* && prettier --write gulp/**/*.*", "prettier-all": "prettier --write src/**/*.* && prettier --write gulp/**/*.*",

Binary file not shown.

Before

Width:  |  Height:  |  Size: 35 KiB

After

Width:  |  Height:  |  Size: 111 KiB

View File

@ -1,60 +1,25 @@
<?xml version="1.0" encoding="iso-8859-1"?> <?xml version="1.0" encoding="iso-8859-1"?>
<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> <!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" id="Layer_1" x="0px" y="0px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve"> <svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
<path style="fill:#C8414B;" d="M400,0H112C50.144,0,0,50.144,0,112v288c0,61.856,50.144,112,112,112h288 c61.856,0,112-50.144,112-112V112C512,50.144,461.856,0,400,0z"/> viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
<rect y="106.63" style="fill:#FFD250;" width="512" height="298.74"/> <g transform="translate(-1)">
<path style="fill:#C8414B;" d="M223.091,256.412l8.255-33.665c0.76-3.1-1.843-6.041-5.347-6.041h-5.815 c-3.504,0-6.108,2.941-5.347,6.041L223.091,256.412z"/> <path style="fill:#46B29D;" d="M328.61,98.163h0.088c1.971-0.012,3.923,0.379,5.738,1.148l71.683,29.484
<rect x="213.35" y="238.76" style="fill:#F5F5F5;" width="19.473" height="75"/> c4.07,1.723,7.249,5.049,8.787,9.193c1.537,4.144,1.297,8.739-0.665,12.699l-11.652,24.099
<rect x="208.49" y="229.94" style="fill:#FAB446;" width="29.21" height="8.823"/> c-5.942,12.252-10.388,25.174-13.242,38.488l-12.624,58.086c-1.107,5.424-5.003,9.857-10.24,11.652l-11.653,3.972
<g> c-5.094,1.809-8.94,6.053-10.241,11.299l-6.885,28.513c-0.25,1.103-0.635,2.17-1.148,3.178l-5.473,11.211
<rect x="189.01" y="256.41" style="fill:#C8414B;" width="48.681" height="8.823"/> c-2.003,4.139-5.709,7.201-10.152,8.386l-18.715,4.855c-7.018,1.83-11.893,8.196-11.829,15.448v11.211
<polygon style="fill:#C8414B;" points="237.696,291.706 208.487,282.882 208.487,274.059 237.696,282.882 "/> c-0.023,3.42-1.102,6.75-3.09,9.534l-19.51,26.748c-3.683,5.056-5.967,10.993-6.621,17.214l-6.091,56.585
<path style="fill:#C8414B;" d="M77.047,256.412l8.255-33.665c0.76-3.1-1.843-6.041-5.347-6.041H74.14 c-3.504,0-6.108,2.941-5.347,6.041L77.047,256.412z"/> c-0.638,5.71-3.3,11.002-7.503,14.919c-4.172,3.812-9.621,5.922-15.272,5.914c-10.207-0.042-19.147-6.854-21.896-16.684
</g> L187.45,416.75c-0.269-0.922-0.447-1.868-0.53-2.825l-17.656-163.84c-0.585-5.323-3.801-9.997-8.563-12.447l-21.629-11.211
<path style="fill:#F5F5F5;" d="M111.124,229.941c-5.377,0-9.736,3.95-9.736,8.824v57.353c0,10.721,11.041,30.882,48.682,30.882 s48.682-20.162,48.682-30.882v-57.353c0-4.873-4.359-8.824-9.736-8.824L111.124,229.941L111.124,229.941z"/> c-5.391-2.781-9.662-7.331-12.094-12.888l-26.661-61.793c-4.326-9.941-2.235-21.509,5.297-29.308l10.064-10.417
<g> c3.583-3.658,5.192-8.813,4.326-13.859l-4.414-27.63c-2.316-13.91,2.107-28.094,11.918-38.223l18.715-19.244
<path style="fill:#C8414B;" d="M150.069,274.059h-48.682V239.21c0-5.119,4.15-9.269,9.269-9.269h39.413V274.059z"/> C154.266,4.72,165.356,0.003,176.945,0h29.662c11.59,0.003,22.679,4.72,30.721,13.065l16.244,16.684L328.61,98.163z"/>
<path style="fill:#C8414B;" d="M150.069,274.059h48.682v20.946c0,12.797-10.374,23.172-23.172,23.172h-2.338 c-12.797,0-23.172-10.374-23.172-23.172L150.069,274.059L150.069,274.059z"/> <path style="fill:#BDC3C7;" d="M283.478,97.103h35.31V220.69c0,9.751-7.904,17.655-17.655,17.655l0,0
</g> c-9.751,0-17.655-7.904-17.655-17.655V97.103z"/>
<path style="fill:#FAB446;" d="M101.387,274.059h48.682v20.946c0,12.797-10.374,23.172-23.172,23.172h-2.338 c-12.797,0-23.172-10.374-23.172-23.172C101.387,295.005,101.387,274.059,101.387,274.059z"/> <circle style="fill:#CC4B4C;" cx="301.133" cy="52.966" r="52.966"/>
<g> <path style="fill:#FB7B76;" d="M283.478,61.793c-4.875,0-8.828-3.952-8.828-8.828c0.016-14.619,11.863-26.467,26.483-26.483
<path style="fill:#C8414B;" d="M140.333,313.665v-39.606h-9.736v43.673C134.217,317.065,137.49,315.612,140.333,313.665z"/> c4.875,0,8.828,3.952,8.828,8.828s-3.952,8.828-8.828,8.828c-4.873,0.006-8.821,3.955-8.828,8.828
<path style="fill:#C8414B;" d="M120.86,317.732v-43.673h-9.736v39.606C113.967,315.612,117.239,317.065,120.86,317.732z"/> C292.305,57.841,288.353,61.793,283.478,61.793z"/>
</g>
<rect x="111.12" y="256.41" style="fill:#FFB441;" width="29.21" height="8.823"/>
<g>
<rect x="111.12" y="238.76" style="fill:#FAB446;" width="29.21" height="8.824"/>
<rect x="115.99" y="244.01" style="fill:#FAB446;" width="19.473" height="15.985"/>
</g>
<rect x="67.31" y="238.76" style="fill:#F5F5F5;" width="19.473" height="75"/>
<g>
<rect x="62.44" y="309.35" style="fill:#FAB446;" width="29.21" height="8.823"/>
<rect x="62.44" y="229.94" style="fill:#FAB446;" width="29.21" height="8.823"/>
</g>
<rect x="57.57" y="318.18" style="fill:#5064AA;" width="38.945" height="8.823"/>
<rect x="213.35" y="309.35" style="fill:#FAB446;" width="29.21" height="8.823"/>
<rect x="203.62" y="318.18" style="fill:#5064AA;" width="38.945" height="8.823"/>
<rect x="120.86" y="221.12" style="fill:#FAB446;" width="58.42" height="8.823"/>
<rect x="145.2" y="194.65" style="fill:#FFB441;" width="9.736" height="26.471"/>
<g>
<path style="fill:#F5F5F5;" d="M140.333,207.882c-8.053,0-14.604-5.937-14.604-13.235s6.551-13.235,14.604-13.235 c8.053,0,14.604,5.937,14.604,13.235S148.386,207.882,140.333,207.882z M140.333,190.235c-2.686,0-4.868,1.978-4.868,4.412 s2.182,4.412,4.868,4.412c2.686,0,4.868-1.978,4.868-4.412C145.201,192.213,143.019,190.235,140.333,190.235z"/>
<path style="fill:#F5F5F5;" d="M159.805,207.882c-8.053,0-14.604-5.937-14.604-13.235s6.551-13.235,14.604-13.235 c8.053,0,14.604,5.937,14.604,13.235S167.859,207.882,159.805,207.882z M159.805,190.235c-2.686,0-4.868,1.978-4.868,4.412 s2.182,4.412,4.868,4.412c2.686,0,4.868-1.978,4.868-4.412C164.673,192.213,162.491,190.235,159.805,190.235z"/>
<path style="fill:#F5F5F5;" d="M179.278,216.706c-8.053,0-14.604-5.937-14.604-13.235s6.551-13.235,14.604-13.235 c8.053,0,14.605,5.937,14.605,13.235S187.331,216.706,179.278,216.706z M179.278,199.059c-2.686,0-4.868,1.978-4.868,4.412 s2.182,4.412,4.868,4.412c2.686,0,4.868-1.978,4.868-4.412C184.146,201.036,181.964,199.059,179.278,199.059z"/>
<path style="fill:#F5F5F5;" d="M120.86,216.706c-8.053,0-14.604-5.937-14.604-13.235s6.551-13.235,14.604-13.235 s14.604,5.937,14.604,13.235S128.913,216.706,120.86,216.706z M120.86,199.059c-2.686,0-4.868,1.978-4.868,4.412 s2.182,4.412,4.868,4.412s4.868-1.978,4.868-4.412C125.728,201.036,123.546,199.059,120.86,199.059z"/>
</g>
<path style="fill:#FAB446;" d="M179.278,291.706v4.412c0,2.433-2.184,4.412-4.868,4.412c-2.684,0-4.868-1.979-4.868-4.412v-4.412 H179.278 M189.014,282.882h-29.209v13.235c0,7.298,6.552,13.235,14.604,13.235c8.053,0,14.605-5.938,14.605-13.235V282.882 L189.014,282.882z"/>
<path style="fill:#FFA0D2;" d="M174.877,265.235h-0.935c-5.119,0-9.269-4.15-9.269-9.269v-7.933c0-5.119,4.15-9.269,9.269-9.269 h0.935c5.119,0,9.269,4.15,9.269,9.269v7.933C184.146,261.086,179.996,265.235,174.877,265.235z"/>
<ellipse style="fill:#5064AA;" cx="150.07" cy="274.06" rx="14.604" ry="13.235"/>
<rect x="145.2" y="177" style="fill:#FAB446;" width="9.736" height="26.471"/>
<path style="fill:#C8414B;" d="M120.86,221.118l-9.736-8.824l5.703-5.169c8.816-7.99,20.774-12.478,33.242-12.478l0,0 c12.468,0,24.426,4.489,33.242,12.478l5.703,5.169l-9.736,8.824H120.86z"/>
<g>
<ellipse style="fill:#FFD250;" cx="150.07" cy="212.29" rx="4.868" ry="4.412"/>
<ellipse style="fill:#FFD250;" cx="130.6" cy="212.29" rx="4.868" ry="4.412"/>
<ellipse style="fill:#FFD250;" cx="169.54" cy="212.29" rx="4.868" ry="4.412"/>
</g>
<g>
<rect x="62.44" y="256.41" style="fill:#C8414B;" width="48.681" height="8.823"/>
<polygon style="fill:#C8414B;" points="62.442,291.706 91.651,282.882 91.651,274.059 62.442,282.882 "/>
</g> </g>
<g> <g>
</g> </g>

Before

Width:  |  Height:  |  Size: 5.8 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

41
res/ui/languages/no.svg Normal file
View File

@ -0,0 +1,41 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
<path style="fill:#FF4B55;" d="M400,0H112C50.144,0,0,50.144,0,112v288c0,61.856,50.144,112,112,112h288
c61.856,0,112-50.144,112-112V112C512,50.144,461.856,0,400,0z"/>
<polygon style="fill:#F5F5F5;" points="512,211.862 229.517,211.862 229.517,0 141.241,0 141.241,211.862 0,211.862 0,300.138
141.241,300.138 141.241,512 229.517,512 229.517,300.138 512,300.138 "/>
<polygon style="fill:#41479B;" points="512,229.517 211.862,229.517 211.862,0 158.897,0 158.897,229.517 0,229.517 0,282.483
158.897,282.483 158.897,512 211.862,512 211.862,282.483 512,282.483 "/>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@ -0,0 +1,64 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
<path style="fill:#FF4B55;" d="M400,0H185.379v512H400c61.856,0,112-50.144,112-112V112C512,50.144,461.856,0,400,0z"/>
<path style="fill:#73AF00;" d="M112,0C50.144,0,0,50.144,0,112v288c0,61.856,50.144,112,112,112h73.379V0H112z"/>
<circle style="fill:#FFE15A;" cx="185.45" cy="256" r="112.38"/>
<path style="fill:#FF4B55;" d="M222.941,218.508v49.99c0,20.673-16.819,37.492-37.492,37.492s-37.492-16.819-37.492-37.492v-49.99
L222.941,218.508 M235.438,193.513h-99.98c-6.902,0-12.497,5.595-12.497,12.497v62.487c0,34.511,27.977,62.487,62.487,62.487
s62.487-27.977,62.487-62.487V206.01C247.936,199.108,242.34,193.513,235.438,193.513L235.438,193.513z"/>
<path style="fill:#F5F5F5;" d="M211.931,229.517v35.31c0,14.603-11.88,26.483-26.483,26.483s-26.483-11.88-26.483-26.483v-35.31
H211.931"/>
<g>
<circle style="fill:#FFE15A;" cx="135.36" cy="206.01" r="6.249"/>
<circle style="fill:#FFE15A;" cx="235.34" cy="206.01" r="6.249"/>
<circle style="fill:#FFE15A;" cx="135.36" cy="256" r="6.249"/>
<circle style="fill:#FFE15A;" cx="235.34" cy="256" r="6.249"/>
<circle style="fill:#FFE15A;" cx="185.35" cy="206.01" r="6.249"/>
<circle style="fill:#FFE15A;" cx="222.87" cy="302.08" r="6.249"/>
<circle style="fill:#FFE15A;" cx="148.57" cy="302.08" r="6.249"/>
</g>
<g>
<path style="fill:#41479B;" d="M193.52,252.832v10.762c0,4.451-3.621,8.071-8.071,8.071s-8.071-3.621-8.071-8.071v-10.762H193.52"
/>
<path style="fill:#41479B;" d="M193.52,227.317v10.762c0,4.451-3.621,8.071-8.071,8.071s-8.071-3.621-8.071-8.071v-10.762H193.52"
/>
<path style="fill:#41479B;" d="M193.52,278.608v10.762c0,4.451-3.621,8.071-8.071,8.071s-8.071-3.621-8.071-8.071v-10.762H193.52"
/>
<path style="fill:#41479B;" d="M215.26,252.832v10.762c0,4.451-3.621,8.071-8.071,8.071s-8.071-3.621-8.071-8.071v-10.762H215.26"
/>
<path style="fill:#41479B;" d="M171.779,252.832v10.762c0,4.451-3.621,8.071-8.071,8.071s-8.071-3.621-8.071-8.071v-10.762H171.779
"/>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

@ -0,0 +1,42 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" id="Layer_1" x="0px" y="0px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
<path style="fill:#FF4B55;" d="M400,0H112C50.144,0,0,50.144,0,112v288c0,61.856,50.144,112,112,112h288 c61.856,0,112-50.144,112-112V112C512,50.144,461.856,0,400,0z"/>
<g>
<path style="fill:#FFE15A;" d="M114.021,87.182l12.722,38.146l40.21,0.312c5.206,0.04,7.365,6.684,3.177,9.777l-32.348,23.887 l12.129,38.339c1.57,4.964-4.081,9.07-8.317,6.042l-32.714-23.383l-32.714,23.383c-4.235,3.027-9.887-1.079-8.317-6.042 l12.129-38.339L47.63,135.417c-4.188-3.093-2.029-9.736,3.177-9.777l40.21-0.312l12.722-38.146 C105.388,82.243,112.374,82.243,114.021,87.182z"/>
<path style="fill:#FFE15A;" d="M260.037,96.582l9.122,12.44l14.723-4.604c1.906-0.596,3.474,1.577,2.307,3.198l-9.012,12.52 l8.928,12.58c1.156,1.629-0.427,3.791-2.329,3.183l-14.692-4.702l-9.205,12.378c-1.192,1.603-3.738,0.766-3.746-1.231 l-0.068-15.426l-14.617-4.929c-1.893-0.638-1.883-3.318,0.013-3.944l14.65-4.831l0.171-15.425 C256.305,95.791,258.856,94.971,260.037,96.582z"/>
<path style="fill:#FFE15A;" d="M204.496,59.501l15.336,1.667l6.542-13.97c0.847-1.809,3.509-1.499,3.917,0.457l3.154,15.1 l15.308,1.905c1.982,0.247,2.509,2.874,0.776,3.866l-13.387,7.665l2.919,15.147c0.378,1.961-1.958,3.275-3.437,1.933 l-11.427-10.363l-13.504,7.457c-1.748,0.965-3.719-0.85-2.901-2.672l6.324-14.07l-11.265-10.539 C201.393,61.721,202.511,59.285,204.496,59.501z"/>
<path style="fill:#FFE15A;" d="M228.739,208.997l-9.122,12.44l-14.723-4.604c-1.906-0.596-3.474,1.577-2.307,3.198l9.012,12.52 l-8.928,12.58c-1.156,1.629,0.426,3.791,2.329,3.183l14.692-4.702l9.205,12.378c1.192,1.603,3.738,0.766,3.746-1.231l0.068-15.426 l14.617-4.929c1.892-0.638,1.883-3.318-0.013-3.943l-14.65-4.831l-0.171-15.425C232.472,208.206,229.92,207.386,228.739,208.997z"/>
<path style="fill:#FFE15A;" d="M284.281,174.151l-15.336,1.667l-6.542-13.97c-0.847-1.809-3.509-1.499-3.917,0.456l-3.154,15.1 l-15.308,1.905c-1.982,0.247-2.509,2.874-0.776,3.866l13.387,7.665l-2.919,15.147c-0.378,1.961,1.958,3.275,3.437,1.933 l11.427-10.363l13.504,7.457c1.748,0.965,3.719-0.85,2.901-2.672l-6.324-14.07l11.265-10.539 C287.384,176.371,286.266,173.935,284.281,174.151z"/>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.5 KiB

View File

@ -74,7 +74,7 @@
}, },
"sprites/belt/left_3.png": "sprites/belt/left_3.png":
{ {
"frame": {"x":313,"y":112,"w":13,"h":13}, "frame": {"x":289,"y":49,"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},
@ -82,7 +82,7 @@
}, },
"sprites/belt/left_4.png": "sprites/belt/left_4.png":
{ {
"frame": {"x":289,"y":26,"w":13,"h":13}, "frame": {"x":306,"y":49,"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},
@ -90,7 +90,7 @@
}, },
"sprites/belt/left_5.png": "sprites/belt/left_5.png":
{ {
"frame": {"x":306,"y":26,"w":13,"h":13}, "frame": {"x":323,"y":49,"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},
@ -98,7 +98,7 @@
}, },
"sprites/belt/right_0.png": "sprites/belt/right_0.png":
{ {
"frame": {"x":330,"y":112,"w":13,"h":13}, "frame": {"x":313,"y":112,"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},
@ -106,7 +106,7 @@
}, },
"sprites/belt/right_1.png": "sprites/belt/right_1.png":
{ {
"frame": {"x":347,"y":112,"w":13,"h":13}, "frame": {"x":330,"y":112,"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},
@ -114,7 +114,7 @@
}, },
"sprites/belt/right_2.png": "sprites/belt/right_2.png":
{ {
"frame": {"x":323,"y":26,"w":13,"h":13}, "frame": {"x":340,"y":49,"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},
@ -122,7 +122,7 @@
}, },
"sprites/belt/right_3.png": "sprites/belt/right_3.png":
{ {
"frame": {"x":364,"y":111,"w":13,"h":13}, "frame": {"x":347,"y":112,"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},
@ -130,7 +130,7 @@
}, },
"sprites/belt/right_4.png": "sprites/belt/right_4.png":
{ {
"frame": {"x":381,"y":111,"w":13,"h":13}, "frame": {"x":357,"y":49,"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},
@ -138,7 +138,7 @@
}, },
"sprites/belt/right_5.png": "sprites/belt/right_5.png":
{ {
"frame": {"x":340,"y":25,"w":13,"h":13}, "frame": {"x":374,"y":49,"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},
@ -146,7 +146,7 @@
}, },
"sprites/blueprints/belt_left.png": "sprites/blueprints/belt_left.png":
{ {
"frame": {"x":357,"y":23,"w":13,"h":13}, "frame": {"x":391,"y":48,"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},
@ -154,7 +154,7 @@
}, },
"sprites/blueprints/belt_right.png": "sprites/blueprints/belt_right.png":
{ {
"frame": {"x":374,"y":23,"w":13,"h":13}, "frame": {"x":404,"y":25,"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},
@ -162,7 +162,7 @@
}, },
"sprites/blueprints/belt_top.png": "sprites/blueprints/belt_top.png":
{ {
"frame": {"x":391,"y":23,"w":13,"h":13}, "frame": {"x":400,"y":85,"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},
@ -178,7 +178,7 @@
}, },
"sprites/blueprints/cutter.png": "sprites/blueprints/cutter.png":
{ {
"frame": {"x":207,"y":43,"w":36,"h":19}, "frame": {"x":245,"y":66,"w":36,"h":19},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":1,"y":0,"w":36,"h":19}, "spriteSourceSize": {"x":1,"y":0,"w":36,"h":19},
@ -186,7 +186,7 @@
}, },
"sprites/blueprints/miner-chainable.png": "sprites/blueprints/miner-chainable.png":
{ {
"frame": {"x":285,"y":3,"w":19,"h":19}, "frame": {"x":285,"y":66,"w":19,"h":19},
"rotated": false, "rotated": false,
"trimmed": false, "trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":19,"h":19}, "spriteSourceSize": {"x":0,"y":0,"w":19,"h":19},
@ -194,7 +194,7 @@
}, },
"sprites/blueprints/miner.png": "sprites/blueprints/miner.png":
{ {
"frame": {"x":245,"y":89,"w":19,"h":19}, "frame": {"x":285,"y":89,"w":19,"h":19},
"rotated": false, "rotated": false,
"trimmed": false, "trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":19,"h":19}, "spriteSourceSize": {"x":0,"y":0,"w":19,"h":19},
@ -202,7 +202,7 @@
}, },
"sprites/blueprints/mixer.png": "sprites/blueprints/mixer.png":
{ {
"frame": {"x":166,"y":45,"w":37,"h":19}, "frame": {"x":204,"y":68,"w":37,"h":19},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":0,"y":0,"w":37,"h":19}, "spriteSourceSize": {"x":0,"y":0,"w":37,"h":19},
@ -216,6 +216,14 @@
"spriteSourceSize": {"x":0,"y":0,"w":38,"h":38}, "spriteSourceSize": {"x":0,"y":0,"w":38,"h":38},
"sourceSize": {"w":38,"h":38} "sourceSize": {"w":38,"h":38}
}, },
"sprites/blueprints/painter-mirrored.png":
{
"frame": {"x":82,"y":49,"w":38,"h":19},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":38,"h":19},
"sourceSize": {"w":38,"h":19}
},
"sprites/blueprints/painter-quad.png": "sprites/blueprints/painter-quad.png":
{ {
"frame": {"x":3,"y":83,"w":77,"h":19}, "frame": {"x":3,"y":83,"w":77,"h":19},
@ -226,7 +234,7 @@
}, },
"sprites/blueprints/painter.png": "sprites/blueprints/painter.png":
{ {
"frame": {"x":82,"y":49,"w":38,"h":19}, "frame": {"x":124,"y":49,"w":38,"h":19},
"rotated": false, "rotated": false,
"trimmed": false, "trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":38,"h":19}, "spriteSourceSize": {"x":0,"y":0,"w":38,"h":19},
@ -234,7 +242,7 @@
}, },
"sprites/blueprints/rotater-ccw.png": "sprites/blueprints/rotater-ccw.png":
{ {
"frame": {"x":268,"y":89,"w":19,"h":19}, "frame": {"x":289,"y":26,"w":19,"h":19},
"rotated": false, "rotated": false,
"trimmed": false, "trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":19,"h":19}, "spriteSourceSize": {"x":0,"y":0,"w":19,"h":19},
@ -242,7 +250,7 @@
}, },
"sprites/blueprints/rotater.png": "sprites/blueprints/rotater.png":
{ {
"frame": {"x":285,"y":66,"w":19,"h":19}, "frame": {"x":312,"y":26,"w":19,"h":19},
"rotated": false, "rotated": false,
"trimmed": false, "trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":19,"h":19}, "spriteSourceSize": {"x":0,"y":0,"w":19,"h":19},
@ -250,7 +258,7 @@
}, },
"sprites/blueprints/splitter-compact-inverse.png": "sprites/blueprints/splitter-compact-inverse.png":
{ {
"frame": {"x":291,"y":89,"w":19,"h":19}, "frame": {"x":327,"y":3,"w":19,"h":19},
"rotated": false, "rotated": false,
"trimmed": false, "trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":19,"h":19}, "spriteSourceSize": {"x":0,"y":0,"w":19,"h":19},
@ -258,7 +266,7 @@
}, },
"sprites/blueprints/splitter-compact.png": "sprites/blueprints/splitter-compact.png":
{ {
"frame": {"x":287,"y":43,"w":19,"h":19}, "frame": {"x":308,"y":66,"w":19,"h":19},
"rotated": false, "rotated": false,
"trimmed": false, "trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":19,"h":19}, "spriteSourceSize": {"x":0,"y":0,"w":19,"h":19},
@ -266,7 +274,7 @@
}, },
"sprites/blueprints/splitter.png": "sprites/blueprints/splitter.png":
{ {
"frame": {"x":245,"y":3,"w":36,"h":19}, "frame": {"x":249,"y":43,"w":36,"h":19},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":1,"y":0,"w":36,"h":19}, "spriteSourceSize": {"x":1,"y":0,"w":36,"h":19},
@ -274,7 +282,7 @@
}, },
"sprites/blueprints/stacker.png": "sprites/blueprints/stacker.png":
{ {
"frame": {"x":204,"y":3,"w":37,"h":19}, "frame": {"x":204,"y":91,"w":37,"h":19},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":0,"y":0,"w":37,"h":19}, "spriteSourceSize": {"x":0,"y":0,"w":37,"h":19},
@ -290,7 +298,7 @@
}, },
"sprites/blueprints/trash.png": "sprites/blueprints/trash.png":
{ {
"frame": {"x":308,"y":66,"w":19,"h":19}, "frame": {"x":335,"y":26,"w":19,"h":19},
"rotated": false, "rotated": false,
"trimmed": false, "trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":19,"h":19}, "spriteSourceSize": {"x":0,"y":0,"w":19,"h":19},
@ -298,7 +306,7 @@
}, },
"sprites/blueprints/underground_belt_entry-tier2.png": "sprites/blueprints/underground_belt_entry-tier2.png":
{ {
"frame": {"x":360,"y":89,"w":19,"h":18}, "frame": {"x":381,"y":26,"w":19,"h":18},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":0,"y":1,"w":19,"h":18}, "spriteSourceSize": {"x":0,"y":1,"w":19,"h":18},
@ -306,7 +314,7 @@
}, },
"sprites/blueprints/underground_belt_entry.png": "sprites/blueprints/underground_belt_entry.png":
{ {
"frame": {"x":354,"y":3,"w":19,"h":16}, "frame": {"x":354,"y":89,"w":19,"h":16},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":0,"y":3,"w":19,"h":16}, "spriteSourceSize": {"x":0,"y":3,"w":19,"h":16},
@ -314,7 +322,7 @@
}, },
"sprites/blueprints/underground_belt_exit-tier2.png": "sprites/blueprints/underground_belt_exit-tier2.png":
{ {
"frame": {"x":356,"y":42,"w":19,"h":16}, "frame": {"x":364,"y":109,"w":19,"h":16},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":0,"y":0,"w":19,"h":16}, "spriteSourceSize": {"x":0,"y":0,"w":19,"h":16},
@ -322,7 +330,7 @@
}, },
"sprites/blueprints/underground_belt_exit.png": "sprites/blueprints/underground_belt_exit.png":
{ {
"frame": {"x":377,"y":62,"w":19,"h":16}, "frame": {"x":377,"y":66,"w":19,"h":16},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":0,"y":0,"w":19,"h":16}, "spriteSourceSize": {"x":0,"y":0,"w":19,"h":16},
@ -338,7 +346,7 @@
}, },
"sprites/buildings/belt_right.png": "sprites/buildings/belt_right.png":
{ {
"frame": {"x":330,"y":112,"w":13,"h":13}, "frame": {"x":313,"y":112,"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},
@ -362,7 +370,7 @@
}, },
"sprites/buildings/cutter.png": "sprites/buildings/cutter.png":
{ {
"frame": {"x":245,"y":66,"w":36,"h":19}, "frame": {"x":287,"y":3,"w":36,"h":19},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":1,"y":0,"w":36,"h":19}, "spriteSourceSize": {"x":1,"y":0,"w":36,"h":19},
@ -378,7 +386,7 @@
}, },
"sprites/buildings/miner-chainable.png": "sprites/buildings/miner-chainable.png":
{ {
"frame": {"x":314,"y":89,"w":19,"h":19}, "frame": {"x":350,"y":3,"w":19,"h":19},
"rotated": false, "rotated": false,
"trimmed": false, "trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":19,"h":19}, "spriteSourceSize": {"x":0,"y":0,"w":19,"h":19},
@ -386,7 +394,7 @@
}, },
"sprites/buildings/miner.png": "sprites/buildings/miner.png":
{ {
"frame": {"x":310,"y":43,"w":19,"h":19}, "frame": {"x":308,"y":89,"w":19,"h":19},
"rotated": false, "rotated": false,
"trimmed": false, "trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":19,"h":19}, "spriteSourceSize": {"x":0,"y":0,"w":19,"h":19},
@ -394,7 +402,7 @@
}, },
"sprites/buildings/mixer.png": "sprites/buildings/mixer.png":
{ {
"frame": {"x":204,"y":68,"w":37,"h":19}, "frame": {"x":208,"y":43,"w":37,"h":19},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":0,"y":0,"w":37,"h":19}, "spriteSourceSize": {"x":0,"y":0,"w":37,"h":19},
@ -408,6 +416,14 @@
"spriteSourceSize": {"x":0,"y":0,"w":38,"h":38}, "spriteSourceSize": {"x":0,"y":0,"w":38,"h":38},
"sourceSize": {"w":38,"h":38} "sourceSize": {"w":38,"h":38}
}, },
"sprites/buildings/painter-mirrored.png":
{
"frame": {"x":166,"y":45,"w":38,"h":19},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":38,"h":19},
"sourceSize": {"w":38,"h":19}
},
"sprites/buildings/painter-quad.png": "sprites/buildings/painter-quad.png":
{ {
"frame": {"x":3,"y":106,"w":77,"h":19}, "frame": {"x":3,"y":106,"w":77,"h":19},
@ -418,7 +434,7 @@
}, },
"sprites/buildings/painter.png": "sprites/buildings/painter.png":
{ {
"frame": {"x":124,"y":49,"w":38,"h":19}, "frame": {"x":204,"y":3,"w":38,"h":19},
"rotated": false, "rotated": false,
"trimmed": false, "trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":38,"h":19}, "spriteSourceSize": {"x":0,"y":0,"w":38,"h":19},
@ -434,7 +450,7 @@
}, },
"sprites/buildings/rotater.png": "sprites/buildings/rotater.png":
{ {
"frame": {"x":337,"y":89,"w":19,"h":19}, "frame": {"x":331,"y":89,"w":19,"h":19},
"rotated": false, "rotated": false,
"trimmed": false, "trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":19,"h":19}, "spriteSourceSize": {"x":0,"y":0,"w":19,"h":19},
@ -442,7 +458,7 @@
}, },
"sprites/buildings/splitter-compact-inverse.png": "sprites/buildings/splitter-compact-inverse.png":
{ {
"frame": {"x":308,"y":3,"w":19,"h":19}, "frame": {"x":354,"y":66,"w":19,"h":19},
"rotated": false, "rotated": false,
"trimmed": false, "trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":19,"h":19}, "spriteSourceSize": {"x":0,"y":0,"w":19,"h":19},
@ -450,7 +466,7 @@
}, },
"sprites/buildings/splitter-compact.png": "sprites/buildings/splitter-compact.png":
{ {
"frame": {"x":333,"y":43,"w":19,"h":19}, "frame": {"x":358,"y":26,"w":19,"h":19},
"rotated": false, "rotated": false,
"trimmed": false, "trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":19,"h":19}, "spriteSourceSize": {"x":0,"y":0,"w":19,"h":19},
@ -458,7 +474,7 @@
}, },
"sprites/buildings/splitter.png": "sprites/buildings/splitter.png":
{ {
"frame": {"x":247,"y":43,"w":36,"h":19}, "frame": {"x":245,"y":89,"w":36,"h":19},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":1,"y":0,"w":36,"h":19}, "spriteSourceSize": {"x":1,"y":0,"w":36,"h":19},
@ -466,7 +482,7 @@
}, },
"sprites/buildings/stacker.png": "sprites/buildings/stacker.png":
{ {
"frame": {"x":204,"y":91,"w":37,"h":19}, "frame": {"x":246,"y":3,"w":37,"h":19},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":0,"y":0,"w":37,"h":19}, "spriteSourceSize": {"x":0,"y":0,"w":37,"h":19},
@ -482,7 +498,7 @@
}, },
"sprites/buildings/trash.png": "sprites/buildings/trash.png":
{ {
"frame": {"x":354,"y":66,"w":19,"h":19}, "frame": {"x":373,"y":3,"w":19,"h":19},
"rotated": false, "rotated": false,
"trimmed": false, "trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":19,"h":19}, "spriteSourceSize": {"x":0,"y":0,"w":19,"h":19},
@ -490,7 +506,7 @@
}, },
"sprites/buildings/underground_belt_entry-tier2.png": "sprites/buildings/underground_belt_entry-tier2.png":
{ {
"frame": {"x":331,"y":3,"w":19,"h":18}, "frame": {"x":396,"y":3,"w":19,"h":18},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":0,"y":1,"w":19,"h":18}, "spriteSourceSize": {"x":0,"y":1,"w":19,"h":18},
@ -498,7 +514,7 @@
}, },
"sprites/buildings/underground_belt_entry.png": "sprites/buildings/underground_belt_entry.png":
{ {
"frame": {"x":383,"y":82,"w":19,"h":16}, "frame": {"x":377,"y":86,"w":19,"h":16},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":0,"y":3,"w":19,"h":16}, "spriteSourceSize": {"x":0,"y":3,"w":19,"h":16},
@ -506,7 +522,7 @@
}, },
"sprites/buildings/underground_belt_exit-tier2.png": "sprites/buildings/underground_belt_exit-tier2.png":
{ {
"frame": {"x":377,"y":3,"w":19,"h":16}, "frame": {"x":387,"y":106,"w":19,"h":16},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":0,"y":0,"w":19,"h":16}, "spriteSourceSize": {"x":0,"y":0,"w":19,"h":16},
@ -514,7 +530,7 @@
}, },
"sprites/buildings/underground_belt_exit.png": "sprites/buildings/underground_belt_exit.png":
{ {
"frame": {"x":379,"y":40,"w":19,"h":16}, "frame": {"x":400,"y":65,"w":19,"h":16},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":0,"y":0,"w":19,"h":16}, "spriteSourceSize": {"x":0,"y":0,"w":19,"h":16},
@ -538,7 +554,7 @@
}, },
"sprites/map_overview/belt_forward.png": "sprites/map_overview/belt_forward.png":
{ {
"frame": {"x":102,"y":72,"w":3,"h":3}, "frame": {"x":111,"y":72,"w":3,"h":3},
"rotated": false, "rotated": false,
"trimmed": false, "trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":3,"h":3}, "spriteSourceSize": {"x":0,"y":0,"w":3,"h":3},
@ -546,7 +562,7 @@
}, },
"sprites/map_overview/belt_left.png": "sprites/map_overview/belt_left.png":
{ {
"frame": {"x":109,"y":72,"w":3,"h":3}, "frame": {"x":118,"y":72,"w":3,"h":3},
"rotated": false, "rotated": false,
"trimmed": false, "trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":3,"h":3}, "spriteSourceSize": {"x":0,"y":0,"w":3,"h":3},
@ -554,7 +570,7 @@
}, },
"sprites/map_overview/belt_right.png": "sprites/map_overview/belt_right.png":
{ {
"frame": {"x":116,"y":72,"w":3,"h":3}, "frame": {"x":125,"y":72,"w":3,"h":3},
"rotated": false, "rotated": false,
"trimmed": false, "trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":3,"h":3}, "spriteSourceSize": {"x":0,"y":0,"w":3,"h":3},
@ -568,6 +584,22 @@
"spriteSourceSize": {"x":0,"y":0,"w":10,"h":10}, "spriteSourceSize": {"x":0,"y":0,"w":10,"h":10},
"sourceSize": {"w":10,"h":10} "sourceSize": {"w":10,"h":10}
}, },
"sprites/misc/hub_direction_indicator.png":
{
"frame": {"x":132,"y":72,"w":3,"h":3},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":3,"h":3},
"sourceSize": {"w":3,"h":3}
},
"sprites/misc/lock_direction_indicator.png":
{
"frame": {"x":102,"y":72,"w":5,"h":5},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":5,"h":5},
"sourceSize": {"w":5,"h":5}
},
"sprites/misc/slot_bad_arrow.png": "sprites/misc/slot_bad_arrow.png":
{ {
"frame": {"x":187,"y":114,"w":10,"h":10}, "frame": {"x":187,"y":114,"w":10,"h":10},
@ -594,7 +626,7 @@
}, },
"sprites/misc/waypoint.png": "sprites/misc/waypoint.png":
{ {
"frame": {"x":123,"y":72,"w":3,"h":3}, "frame": {"x":139,"y":72,"w":3,"h":3},
"rotated": false, "rotated": false,
"trimmed": false, "trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":3,"h":3}, "spriteSourceSize": {"x":0,"y":0,"w":3,"h":3},
@ -605,8 +637,8 @@
"version": "1.0", "version": "1.0",
"image": "atlas0_10.png", "image": "atlas0_10.png",
"format": "RGBA8888", "format": "RGBA8888",
"size": {"w":407,"h":128}, "size": {"w":422,"h":128},
"scale": "0.1", "scale": "0.1",
"smartupdate": "$TexturePacker:SmartUpdate:3dd7a89f30024dd4787ad4af6b14588a:9ba11f8b02134c4376ab4e0a44f8b850:f159918d23e5952766c6d23ab52278c6$" "smartupdate": "$TexturePacker:SmartUpdate:8985524bba1a3f16cecab3c03b6aaa06:d614d20bfce033d8a8ab0990af085d16:f159918d23e5952766c6d23ab52278c6$"
} }
} }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 50 KiB

After

Width:  |  Height:  |  Size: 52 KiB

View File

@ -2,7 +2,7 @@
"sprites/belt/forward_0.png": "sprites/belt/forward_0.png":
{ {
"frame": {"x":1871,"y":1504,"w":100,"h":126}, "frame": {"x":1876,"y":1166,"w":100,"h":126},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":13,"y":0,"w":100,"h":126}, "spriteSourceSize": {"x":13,"y":0,"w":100,"h":126},
@ -10,7 +10,7 @@
}, },
"sprites/belt/forward_1.png": "sprites/belt/forward_1.png":
{ {
"frame": {"x":1871,"y":240,"w":100,"h":126}, "frame": {"x":1876,"y":1296,"w":100,"h":126},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":13,"y":0,"w":100,"h":126}, "spriteSourceSize": {"x":13,"y":0,"w":100,"h":126},
@ -18,7 +18,7 @@
}, },
"sprites/belt/forward_2.png": "sprites/belt/forward_2.png":
{ {
"frame": {"x":1844,"y":394,"w":100,"h":126}, "frame": {"x":1869,"y":1543,"w":100,"h":126},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":13,"y":0,"w":100,"h":126}, "spriteSourceSize": {"x":13,"y":0,"w":100,"h":126},
@ -26,7 +26,7 @@
}, },
"sprites/belt/forward_3.png": "sprites/belt/forward_3.png":
{ {
"frame": {"x":1871,"y":1634,"w":100,"h":126}, "frame": {"x":1857,"y":395,"w":100,"h":126},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":13,"y":0,"w":100,"h":126}, "spriteSourceSize": {"x":13,"y":0,"w":100,"h":126},
@ -34,7 +34,7 @@
}, },
"sprites/belt/forward_4.png": "sprites/belt/forward_4.png":
{ {
"frame": {"x":1433,"y":785,"w":100,"h":126}, "frame": {"x":1865,"y":1690,"w":100,"h":126},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":13,"y":0,"w":100,"h":126}, "spriteSourceSize": {"x":13,"y":0,"w":100,"h":126},
@ -42,7 +42,7 @@
}, },
"sprites/belt/forward_5.png": "sprites/belt/forward_5.png":
{ {
"frame": {"x":917,"y":1564,"w":100,"h":126}, "frame": {"x":920,"y":1370,"w":100,"h":126},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":13,"y":0,"w":100,"h":126}, "spriteSourceSize": {"x":13,"y":0,"w":100,"h":126},
@ -50,7 +50,7 @@
}, },
"sprites/belt/left_0.png": "sprites/belt/left_0.png":
{ {
"frame": {"x":1021,"y":1563,"w":113,"h":113}, "frame": {"x":1870,"y":1426,"w":113,"h":113},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":0,"y":13,"w":113,"h":113}, "spriteSourceSize": {"x":0,"y":13,"w":113,"h":113},
@ -58,7 +58,7 @@
}, },
"sprites/belt/left_1.png": "sprites/belt/left_1.png":
{ {
"frame": {"x":1138,"y":1563,"w":113,"h":113}, "frame": {"x":920,"y":1500,"w":113,"h":113},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":0,"y":13,"w":113,"h":113}, "spriteSourceSize": {"x":0,"y":13,"w":113,"h":113},
@ -66,7 +66,7 @@
}, },
"sprites/belt/left_2.png": "sprites/belt/left_2.png":
{ {
"frame": {"x":1255,"y":1563,"w":113,"h":113}, "frame": {"x":935,"y":1617,"w":113,"h":113},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":0,"y":13,"w":113,"h":113}, "spriteSourceSize": {"x":0,"y":13,"w":113,"h":113},
@ -74,7 +74,7 @@
}, },
"sprites/belt/left_3.png": "sprites/belt/left_3.png":
{ {
"frame": {"x":1372,"y":1562,"w":113,"h":113}, "frame": {"x":935,"y":1734,"w":113,"h":113},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":0,"y":13,"w":113,"h":113}, "spriteSourceSize": {"x":0,"y":13,"w":113,"h":113},
@ -82,7 +82,7 @@
}, },
"sprites/belt/left_4.png": "sprites/belt/left_4.png":
{ {
"frame": {"x":1489,"y":1562,"w":113,"h":113}, "frame": {"x":1052,"y":1721,"w":113,"h":113},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":0,"y":13,"w":113,"h":113}, "spriteSourceSize": {"x":0,"y":13,"w":113,"h":113},
@ -90,7 +90,7 @@
}, },
"sprites/belt/left_5.png": "sprites/belt/left_5.png":
{ {
"frame": {"x":1021,"y":1680,"w":113,"h":113}, "frame": {"x":1169,"y":1721,"w":113,"h":113},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":0,"y":13,"w":113,"h":113}, "spriteSourceSize": {"x":0,"y":13,"w":113,"h":113},
@ -98,7 +98,7 @@
}, },
"sprites/belt/right_0.png": "sprites/belt/right_0.png":
{ {
"frame": {"x":1138,"y":1680,"w":113,"h":113}, "frame": {"x":1286,"y":1721,"w":113,"h":113},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":13,"y":13,"w":113,"h":113}, "spriteSourceSize": {"x":13,"y":13,"w":113,"h":113},
@ -106,7 +106,7 @@
}, },
"sprites/belt/right_1.png": "sprites/belt/right_1.png":
{ {
"frame": {"x":1255,"y":1680,"w":113,"h":113}, "frame": {"x":1403,"y":1721,"w":113,"h":113},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":13,"y":13,"w":113,"h":113}, "spriteSourceSize": {"x":13,"y":13,"w":113,"h":113},
@ -114,7 +114,7 @@
}, },
"sprites/belt/right_2.png": "sprites/belt/right_2.png":
{ {
"frame": {"x":1372,"y":1679,"w":113,"h":113}, "frame": {"x":1520,"y":1721,"w":113,"h":113},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":13,"y":13,"w":113,"h":113}, "spriteSourceSize": {"x":13,"y":13,"w":113,"h":113},
@ -122,7 +122,7 @@
}, },
"sprites/belt/right_3.png": "sprites/belt/right_3.png":
{ {
"frame": {"x":1489,"y":1679,"w":113,"h":113}, "frame": {"x":1052,"y":1552,"w":113,"h":113},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":13,"y":13,"w":113,"h":113}, "spriteSourceSize": {"x":13,"y":13,"w":113,"h":113},
@ -130,7 +130,7 @@
}, },
"sprites/belt/right_4.png": "sprites/belt/right_4.png":
{ {
"frame": {"x":1606,"y":1676,"w":113,"h":113}, "frame": {"x":1169,"y":1552,"w":113,"h":113},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":13,"y":13,"w":113,"h":113}, "spriteSourceSize": {"x":13,"y":13,"w":113,"h":113},
@ -138,7 +138,7 @@
}, },
"sprites/belt/right_5.png": "sprites/belt/right_5.png":
{ {
"frame": {"x":1723,"y":1676,"w":113,"h":113}, "frame": {"x":1286,"y":1554,"w":113,"h":113},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":13,"y":13,"w":113,"h":113}, "spriteSourceSize": {"x":13,"y":13,"w":113,"h":113},
@ -162,7 +162,7 @@
}, },
"sprites/blueprints/belt_top.png": "sprites/blueprints/belt_top.png":
{ {
"frame": {"x":1871,"y":1374,"w":102,"h":126}, "frame": {"x":1871,"y":240,"w":102,"h":126},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":12,"y":0,"w":102,"h":126}, "spriteSourceSize": {"x":12,"y":0,"w":102,"h":126},
@ -178,7 +178,7 @@
}, },
"sprites/blueprints/cutter.png": "sprites/blueprints/cutter.png":
{ {
"frame": {"x":726,"y":979,"w":341,"h":191}, "frame": {"x":1433,"y":785,"w":341,"h":191},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":23,"y":0,"w":341,"h":191}, "spriteSourceSize": {"x":23,"y":0,"w":341,"h":191},
@ -186,7 +186,7 @@
}, },
"sprites/blueprints/miner-chainable.png": "sprites/blueprints/miner-chainable.png":
{ {
"frame": {"x":1500,"y":1368,"w":182,"h":190}, "frame": {"x":749,"y":1655,"w":182,"h":190},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":6,"y":0,"w":182,"h":190}, "spriteSourceSize": {"x":6,"y":0,"w":182,"h":190},
@ -194,7 +194,7 @@
}, },
"sprites/blueprints/miner.png": "sprites/blueprints/miner.png":
{ {
"frame": {"x":1437,"y":590,"w":182,"h":190}, "frame": {"x":1690,"y":1174,"w":182,"h":190},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":6,"y":0,"w":182,"h":190}, "spriteSourceSize": {"x":6,"y":0,"w":182,"h":190},
@ -202,7 +202,7 @@
}, },
"sprites/blueprints/mixer.png": "sprites/blueprints/mixer.png":
{ {
"frame": {"x":735,"y":590,"w":347,"h":191}, "frame": {"x":1123,"y":590,"w":347,"h":191},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":18,"y":0,"w":347,"h":191}, "spriteSourceSize": {"x":18,"y":0,"w":347,"h":191},
@ -216,6 +216,14 @@
"spriteSourceSize": {"x":0,"y":0,"w":384,"h":382}, "spriteSourceSize": {"x":0,"y":0,"w":384,"h":382},
"sourceSize": {"w":384,"h":384} "sourceSize": {"w":384,"h":384}
}, },
"sprites/blueprints/painter-mirrored.png":
{
"frame": {"x":1485,"y":3,"w":384,"h":192},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":384,"h":192},
"sourceSize": {"w":384,"h":192}
},
"sprites/blueprints/painter-quad.png": "sprites/blueprints/painter-quad.png":
{ {
"frame": {"x":735,"y":3,"w":746,"h":192}, "frame": {"x":735,"y":3,"w":746,"h":192},
@ -226,7 +234,7 @@
}, },
"sprites/blueprints/painter.png": "sprites/blueprints/painter.png":
{ {
"frame": {"x":1485,"y":3,"w":384,"h":192}, "frame": {"x":1483,"y":199,"w":384,"h":192},
"rotated": false, "rotated": false,
"trimmed": false, "trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":384,"h":192}, "spriteSourceSize": {"x":0,"y":0,"w":384,"h":192},
@ -234,7 +242,7 @@
}, },
"sprites/blueprints/rotater-ccw.png": "sprites/blueprints/rotater-ccw.png":
{ {
"frame": {"x":1116,"y":1368,"w":189,"h":191}, "frame": {"x":922,"y":1174,"w":189,"h":191},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":2,"y":0,"w":189,"h":191}, "spriteSourceSize": {"x":2,"y":0,"w":189,"h":191},
@ -242,7 +250,7 @@
}, },
"sprites/blueprints/rotater.png": "sprites/blueprints/rotater.png":
{ {
"frame": {"x":724,"y":1564,"w":189,"h":191}, "frame": {"x":1115,"y":1173,"w":189,"h":191},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":2,"y":0,"w":189,"h":191}, "spriteSourceSize": {"x":2,"y":0,"w":189,"h":191},
@ -250,7 +258,7 @@
}, },
"sprites/blueprints/splitter-compact-inverse.png": "sprites/blueprints/splitter-compact-inverse.png":
{ {
"frame": {"x":1652,"y":394,"w":188,"h":182}, "frame": {"x":1756,"y":980,"w":188,"h":182},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":0,"y":4,"w":188,"h":182}, "spriteSourceSize": {"x":0,"y":4,"w":188,"h":182},
@ -258,7 +266,7 @@
}, },
"sprites/blueprints/splitter-compact.png": "sprites/blueprints/splitter-compact.png":
{ {
"frame": {"x":1623,"y":587,"w":185,"h":182}, "frame": {"x":1306,"y":1368,"w":185,"h":182},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":7,"y":4,"w":185,"h":182}, "spriteSourceSize": {"x":7,"y":4,"w":185,"h":182},
@ -266,7 +274,7 @@
}, },
"sprites/blueprints/splitter.png": "sprites/blueprints/splitter.png":
{ {
"frame": {"x":1071,"y":979,"w":340,"h":191}, "frame": {"x":726,"y":979,"w":340,"h":191},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":23,"y":0,"w":340,"h":191}, "spriteSourceSize": {"x":23,"y":0,"w":340,"h":191},
@ -274,7 +282,7 @@
}, },
"sprites/blueprints/stacker.png": "sprites/blueprints/stacker.png":
{ {
"frame": {"x":1086,"y":590,"w":347,"h":191}, "frame": {"x":1474,"y":590,"w":347,"h":191},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":18,"y":0,"w":347,"h":191}, "spriteSourceSize": {"x":18,"y":0,"w":347,"h":191},
@ -290,7 +298,7 @@
}, },
"sprites/blueprints/trash.png": "sprites/blueprints/trash.png":
{ {
"frame": {"x":724,"y":1368,"w":192,"h":192}, "frame": {"x":726,"y":1174,"w":192,"h":192},
"rotated": false, "rotated": false,
"trimmed": false, "trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":192,"h":192}, "spriteSourceSize": {"x":0,"y":0,"w":192,"h":192},
@ -298,7 +306,7 @@
}, },
"sprites/blueprints/underground_belt_entry-tier2.png": "sprites/blueprints/underground_belt_entry-tier2.png":
{ {
"frame": {"x":1791,"y":1035,"w":183,"h":166}, "frame": {"x":1683,"y":1368,"w":183,"h":166},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":5,"y":26,"w":183,"h":166}, "spriteSourceSize": {"x":5,"y":26,"w":183,"h":166},
@ -306,7 +314,7 @@
}, },
"sprites/blueprints/underground_belt_entry.png": "sprites/blueprints/underground_belt_entry.png":
{ {
"frame": {"x":1812,"y":580,"w":182,"h":148}, "frame": {"x":192,"y":1702,"w":182,"h":148},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":6,"y":44,"w":182,"h":148}, "spriteSourceSize": {"x":6,"y":44,"w":182,"h":148},
@ -314,7 +322,7 @@
}, },
"sprites/blueprints/underground_belt_exit-tier2.png": "sprites/blueprints/underground_belt_exit-tier2.png":
{ {
"frame": {"x":1623,"y":773,"w":185,"h":148}, "frame": {"x":3,"y":1702,"w":185,"h":148},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":5,"y":0,"w":185,"h":148}, "spriteSourceSize": {"x":5,"y":0,"w":185,"h":148},
@ -322,7 +330,7 @@
}, },
"sprites/blueprints/underground_belt_exit.png": "sprites/blueprints/underground_belt_exit.png":
{ {
"frame": {"x":1812,"y":732,"w":182,"h":148}, "frame": {"x":1683,"y":1538,"w":182,"h":148},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":6,"y":0,"w":182,"h":148}, "spriteSourceSize": {"x":6,"y":0,"w":182,"h":148},
@ -330,7 +338,7 @@
}, },
"sprites/buildings/belt_left.png": "sprites/buildings/belt_left.png":
{ {
"frame": {"x":1021,"y":1563,"w":113,"h":113}, "frame": {"x":1870,"y":1426,"w":113,"h":113},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":0,"y":13,"w":113,"h":113}, "spriteSourceSize": {"x":0,"y":13,"w":113,"h":113},
@ -338,7 +346,7 @@
}, },
"sprites/buildings/belt_right.png": "sprites/buildings/belt_right.png":
{ {
"frame": {"x":1138,"y":1680,"w":113,"h":113}, "frame": {"x":1286,"y":1721,"w":113,"h":113},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":13,"y":13,"w":113,"h":113}, "spriteSourceSize": {"x":13,"y":13,"w":113,"h":113},
@ -346,7 +354,7 @@
}, },
"sprites/buildings/belt_top.png": "sprites/buildings/belt_top.png":
{ {
"frame": {"x":1871,"y":1504,"w":100,"h":126}, "frame": {"x":1876,"y":1166,"w":100,"h":126},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":13,"y":0,"w":100,"h":126}, "spriteSourceSize": {"x":13,"y":0,"w":100,"h":126},
@ -362,7 +370,7 @@
}, },
"sprites/buildings/cutter.png": "sprites/buildings/cutter.png":
{ {
"frame": {"x":726,"y":1174,"w":339,"h":190}, "frame": {"x":1070,"y":979,"w":339,"h":190},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":24,"y":0,"w":339,"h":190}, "spriteSourceSize": {"x":24,"y":0,"w":339,"h":190},
@ -378,7 +386,7 @@
}, },
"sprites/buildings/miner-chainable.png": "sprites/buildings/miner-chainable.png":
{ {
"frame": {"x":1469,"y":395,"w":179,"h":188}, "frame": {"x":1825,"y":590,"w":179,"h":188},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":8,"y":1,"w":179,"h":188}, "spriteSourceSize": {"x":8,"y":1,"w":179,"h":188},
@ -386,7 +394,7 @@
}, },
"sprites/buildings/miner.png": "sprites/buildings/miner.png":
{ {
"frame": {"x":1415,"y":979,"w":179,"h":189}, "frame": {"x":1778,"y":785,"w":179,"h":189},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":8,"y":0,"w":179,"h":189}, "spriteSourceSize": {"x":8,"y":0,"w":179,"h":189},
@ -408,6 +416,14 @@
"spriteSourceSize": {"x":0,"y":0,"w":384,"h":381}, "spriteSourceSize": {"x":0,"y":0,"w":384,"h":381},
"sourceSize": {"w":384,"h":384} "sourceSize": {"w":384,"h":384}
}, },
"sprites/buildings/painter-mirrored.png":
{
"frame": {"x":735,"y":590,"w":384,"h":191},
"rotated": false,
"trimmed": true,
"spriteSourceSize": {"x":0,"y":0,"w":384,"h":191},
"sourceSize": {"w":384,"h":192}
},
"sprites/buildings/painter-quad.png": "sprites/buildings/painter-quad.png":
{ {
"frame": {"x":735,"y":199,"w":744,"h":192}, "frame": {"x":735,"y":199,"w":744,"h":192},
@ -418,7 +434,7 @@
}, },
"sprites/buildings/painter.png": "sprites/buildings/painter.png":
{ {
"frame": {"x":1483,"y":199,"w":384,"h":191}, "frame": {"x":1469,"y":395,"w":384,"h":191},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":0,"y":0,"w":384,"h":191}, "spriteSourceSize": {"x":0,"y":0,"w":384,"h":191},
@ -426,7 +442,7 @@
}, },
"sprites/buildings/rotater-ccw.png": "sprites/buildings/rotater-ccw.png":
{ {
"frame": {"x":1309,"y":1368,"w":187,"h":190}, "frame": {"x":1308,"y":1174,"w":187,"h":190},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":3,"y":0,"w":187,"h":190}, "spriteSourceSize": {"x":3,"y":0,"w":187,"h":190},
@ -434,7 +450,7 @@
}, },
"sprites/buildings/rotater.png": "sprites/buildings/rotater.png":
{ {
"frame": {"x":1412,"y":1174,"w":187,"h":190}, "frame": {"x":1499,"y":1174,"w":187,"h":190},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":3,"y":0,"w":187,"h":190}, "spriteSourceSize": {"x":3,"y":0,"w":187,"h":190},
@ -442,7 +458,7 @@
}, },
"sprites/buildings/splitter-compact-inverse.png": "sprites/buildings/splitter-compact-inverse.png":
{ {
"frame": {"x":1598,"y":925,"w":187,"h":180}, "frame": {"x":1115,"y":1368,"w":187,"h":180},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":0,"y":5,"w":187,"h":180}, "spriteSourceSize": {"x":0,"y":5,"w":187,"h":180},
@ -450,7 +466,7 @@
}, },
"sprites/buildings/splitter-compact.png": "sprites/buildings/splitter-compact.png":
{ {
"frame": {"x":1603,"y":1109,"w":184,"h":180}, "frame": {"x":1495,"y":1368,"w":184,"h":180},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":8,"y":5,"w":184,"h":180}, "spriteSourceSize": {"x":8,"y":5,"w":184,"h":180},
@ -458,7 +474,7 @@
}, },
"sprites/buildings/splitter.png": "sprites/buildings/splitter.png":
{ {
"frame": {"x":1069,"y":1174,"w":339,"h":190}, "frame": {"x":1413,"y":980,"w":339,"h":190},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":24,"y":0,"w":339,"h":190}, "spriteSourceSize": {"x":24,"y":0,"w":339,"h":190},
@ -482,7 +498,7 @@
}, },
"sprites/buildings/trash.png": "sprites/buildings/trash.png":
{ {
"frame": {"x":920,"y":1368,"w":192,"h":191}, "frame": {"x":724,"y":1370,"w":192,"h":191},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":0,"y":1,"w":192,"h":191}, "spriteSourceSize": {"x":0,"y":1,"w":192,"h":191},
@ -490,7 +506,7 @@
}, },
"sprites/buildings/underground_belt_entry-tier2.png": "sprites/buildings/underground_belt_entry-tier2.png":
{ {
"frame": {"x":1791,"y":1205,"w":181,"h":165}, "frame": {"x":1495,"y":1552,"w":181,"h":165},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":7,"y":27,"w":181,"h":165}, "spriteSourceSize": {"x":7,"y":27,"w":181,"h":165},
@ -498,7 +514,7 @@
}, },
"sprites/buildings/underground_belt_entry.png": "sprites/buildings/underground_belt_entry.png":
{ {
"frame": {"x":1686,"y":1374,"w":181,"h":147}, "frame": {"x":564,"y":1707,"w":181,"h":147},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":7,"y":45,"w":181,"h":147}, "spriteSourceSize": {"x":7,"y":45,"w":181,"h":147},
@ -506,7 +522,7 @@
}, },
"sprites/buildings/underground_belt_exit-tier2.png": "sprites/buildings/underground_belt_exit-tier2.png":
{ {
"frame": {"x":1812,"y":884,"w":182,"h":147}, "frame": {"x":378,"y":1707,"w":182,"h":147},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":7,"y":0,"w":182,"h":147}, "spriteSourceSize": {"x":7,"y":0,"w":182,"h":147},
@ -514,7 +530,7 @@
}, },
"sprites/buildings/underground_belt_exit.png": "sprites/buildings/underground_belt_exit.png":
{ {
"frame": {"x":1686,"y":1525,"w":181,"h":147}, "frame": {"x":1680,"y":1690,"w":181,"h":147},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":7,"y":0,"w":181,"h":147}, "spriteSourceSize": {"x":7,"y":0,"w":181,"h":147},
@ -522,7 +538,7 @@
}, },
"sprites/debug/acceptor_slot.png": "sprites/debug/acceptor_slot.png":
{ {
"frame": {"x":1603,"y":1293,"w":50,"h":64}, "frame": {"x":1961,"y":782,"w":50,"h":64},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":7,"y":0,"w":50,"h":64}, "spriteSourceSize": {"x":7,"y":0,"w":50,"h":64},
@ -530,7 +546,7 @@
}, },
"sprites/debug/ejector_slot.png": "sprites/debug/ejector_slot.png":
{ {
"frame": {"x":1606,"y":1562,"w":50,"h":64}, "frame": {"x":1961,"y":850,"w":50,"h":64},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":7,"y":0,"w":50,"h":64}, "spriteSourceSize": {"x":7,"y":0,"w":50,"h":64},
@ -538,7 +554,7 @@
}, },
"sprites/map_overview/belt_forward.png": "sprites/map_overview/belt_forward.png":
{ {
"frame": {"x":353,"y":1702,"w":24,"h":32}, "frame": {"x":1637,"y":1721,"w":24,"h":32},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":4,"y":0,"w":24,"h":32}, "spriteSourceSize": {"x":4,"y":0,"w":24,"h":32},
@ -546,7 +562,7 @@
}, },
"sprites/map_overview/belt_left.png": "sprites/map_overview/belt_left.png":
{ {
"frame": {"x":1433,"y":915,"w":28,"h":28}, "frame": {"x":1893,"y":525,"w":28,"h":28},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":0,"y":4,"w":28,"h":28}, "spriteSourceSize": {"x":0,"y":4,"w":28,"h":28},
@ -554,7 +570,7 @@
}, },
"sprites/map_overview/belt_right.png": "sprites/map_overview/belt_right.png":
{ {
"frame": {"x":1433,"y":947,"w":28,"h":28}, "frame": {"x":1080,"y":1669,"w":28,"h":28},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":4,"y":4,"w":28,"h":28}, "spriteSourceSize": {"x":4,"y":4,"w":28,"h":28},
@ -562,15 +578,31 @@
}, },
"sprites/misc/deletion_marker.png": "sprites/misc/deletion_marker.png":
{ {
"frame": {"x":267,"y":1702,"w":82,"h":82}, "frame": {"x":1403,"y":1554,"w":82,"h":82},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":7,"y":7,"w":82,"h":82}, "spriteSourceSize": {"x":7,"y":7,"w":82,"h":82},
"sourceSize": {"w":96,"h":96} "sourceSize": {"w":96,"h":96}
}, },
"sprites/misc/hub_direction_indicator.png":
{
"frame": {"x":1857,"y":525,"w":32,"h":32},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":32,"h":32},
"sourceSize": {"w":32,"h":32}
},
"sprites/misc/lock_direction_indicator.png":
{
"frame": {"x":1961,"y":918,"w":48,"h":30},
"rotated": false,
"trimmed": true,
"spriteSourceSize": {"x":0,"y":9,"w":48,"h":30},
"sourceSize": {"w":48,"h":48}
},
"sprites/misc/slot_bad_arrow.png": "sprites/misc/slot_bad_arrow.png":
{ {
"frame": {"x":267,"y":1702,"w":82,"h":82}, "frame": {"x":1403,"y":1554,"w":82,"h":82},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":7,"y":7,"w":82,"h":82}, "spriteSourceSize": {"x":7,"y":7,"w":82,"h":82},
@ -578,7 +610,7 @@
}, },
"sprites/misc/slot_good_arrow.png": "sprites/misc/slot_good_arrow.png":
{ {
"frame": {"x":183,"y":1702,"w":80,"h":96}, "frame": {"x":1024,"y":1369,"w":80,"h":96},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":8,"y":0,"w":80,"h":96}, "spriteSourceSize": {"x":8,"y":0,"w":80,"h":96},
@ -586,7 +618,7 @@
}, },
"sprites/misc/storage_overlay.png": "sprites/misc/storage_overlay.png":
{ {
"frame": {"x":3,"y":1702,"w":176,"h":86}, "frame": {"x":724,"y":1565,"w":176,"h":86},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":3,"y":4,"w":176,"h":86}, "spriteSourceSize": {"x":3,"y":4,"w":176,"h":86},
@ -594,7 +626,7 @@
}, },
"sprites/misc/waypoint.png": "sprites/misc/waypoint.png":
{ {
"frame": {"x":1844,"y":524,"w":24,"h":32}, "frame": {"x":1052,"y":1669,"w":24,"h":32},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":4,"y":0,"w":24,"h":32}, "spriteSourceSize": {"x":4,"y":0,"w":24,"h":32},
@ -605,8 +637,8 @@
"version": "1.0", "version": "1.0",
"image": "atlas0_100.png", "image": "atlas0_100.png",
"format": "RGBA8888", "format": "RGBA8888",
"size": {"w":1997,"h":1801}, "size": {"w":2014,"h":1857},
"scale": "1", "scale": "1",
"smartupdate": "$TexturePacker:SmartUpdate:3dd7a89f30024dd4787ad4af6b14588a:9ba11f8b02134c4376ab4e0a44f8b850:f159918d23e5952766c6d23ab52278c6$" "smartupdate": "$TexturePacker:SmartUpdate:8985524bba1a3f16cecab3c03b6aaa06:d614d20bfce033d8a8ab0990af085d16:f159918d23e5952766c6d23ab52278c6$"
} }
} }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 743 KiB

After

Width:  |  Height:  |  Size: 776 KiB

View File

@ -2,7 +2,7 @@
"sprites/belt/forward_0.png": "sprites/belt/forward_0.png":
{ {
"frame": {"x":479,"y":103,"w":28,"h":32}, "frame": {"x":3,"y":1010,"w":28,"h":32},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":2,"y":0,"w":28,"h":32}, "spriteSourceSize": {"x":2,"y":0,"w":28,"h":32},
@ -10,7 +10,7 @@
}, },
"sprites/belt/forward_1.png": "sprites/belt/forward_1.png":
{ {
"frame": {"x":479,"y":139,"w":28,"h":32}, "frame": {"x":3,"y":967,"w":28,"h":32},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":2,"y":0,"w":28,"h":32}, "spriteSourceSize": {"x":2,"y":0,"w":28,"h":32},
@ -18,7 +18,7 @@
}, },
"sprites/belt/forward_2.png": "sprites/belt/forward_2.png":
{ {
"frame": {"x":479,"y":175,"w":28,"h":32}, "frame": {"x":3,"y":1046,"w":28,"h":32},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":2,"y":0,"w":28,"h":32}, "spriteSourceSize": {"x":2,"y":0,"w":28,"h":32},
@ -26,7 +26,7 @@
}, },
"sprites/belt/forward_3.png": "sprites/belt/forward_3.png":
{ {
"frame": {"x":262,"y":331,"w":28,"h":32}, "frame": {"x":35,"y":1044,"w":28,"h":32},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":2,"y":0,"w":28,"h":32}, "spriteSourceSize": {"x":2,"y":0,"w":28,"h":32},
@ -34,7 +34,7 @@
}, },
"sprites/belt/forward_4.png": "sprites/belt/forward_4.png":
{ {
"frame": {"x":285,"y":383,"w":28,"h":32}, "frame": {"x":67,"y":1044,"w":28,"h":32},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":2,"y":0,"w":28,"h":32}, "spriteSourceSize": {"x":2,"y":0,"w":28,"h":32},
@ -42,7 +42,7 @@
}, },
"sprites/belt/forward_5.png": "sprites/belt/forward_5.png":
{ {
"frame": {"x":317,"y":383,"w":28,"h":32}, "frame": {"x":133,"y":1053,"w":28,"h":32},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":2,"y":0,"w":28,"h":32}, "spriteSourceSize": {"x":2,"y":0,"w":28,"h":32},
@ -50,7 +50,7 @@
}, },
"sprites/belt/left_0.png": "sprites/belt/left_0.png":
{ {
"frame": {"x":343,"y":159,"w":30,"h":30}, "frame": {"x":143,"y":883,"w":30,"h":30},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":0,"y":2,"w":30,"h":30}, "spriteSourceSize": {"x":0,"y":2,"w":30,"h":30},
@ -58,7 +58,7 @@
}, },
"sprites/belt/left_1.png": "sprites/belt/left_1.png":
{ {
"frame": {"x":343,"y":193,"w":30,"h":30}, "frame": {"x":143,"y":917,"w":30,"h":30},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":0,"y":2,"w":30,"h":30}, "spriteSourceSize": {"x":0,"y":2,"w":30,"h":30},
@ -66,7 +66,7 @@
}, },
"sprites/belt/left_2.png": "sprites/belt/left_2.png":
{ {
"frame": {"x":477,"y":211,"w":30,"h":30}, "frame": {"x":143,"y":951,"w":30,"h":30},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":0,"y":2,"w":30,"h":30}, "spriteSourceSize": {"x":0,"y":2,"w":30,"h":30},
@ -74,7 +74,7 @@
}, },
"sprites/belt/left_3.png": "sprites/belt/left_3.png":
{ {
"frame": {"x":477,"y":245,"w":30,"h":30}, "frame": {"x":35,"y":960,"w":30,"h":30},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":0,"y":2,"w":30,"h":30}, "spriteSourceSize": {"x":0,"y":2,"w":30,"h":30},
@ -82,7 +82,7 @@
}, },
"sprites/belt/left_4.png": "sprites/belt/left_4.png":
{ {
"frame": {"x":469,"y":279,"w":30,"h":30}, "frame": {"x":69,"y":967,"w":30,"h":30},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":0,"y":2,"w":30,"h":30}, "spriteSourceSize": {"x":0,"y":2,"w":30,"h":30},
@ -90,7 +90,7 @@
}, },
"sprites/belt/left_5.png": "sprites/belt/left_5.png":
{ {
"frame": {"x":3,"y":331,"w":30,"h":30}, "frame": {"x":35,"y":994,"w":30,"h":30},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":0,"y":2,"w":30,"h":30}, "spriteSourceSize": {"x":0,"y":2,"w":30,"h":30},
@ -98,7 +98,7 @@
}, },
"sprites/belt/right_0.png": "sprites/belt/right_0.png":
{ {
"frame": {"x":37,"y":331,"w":30,"h":30}, "frame": {"x":103,"y":967,"w":30,"h":30},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":2,"y":2,"w":30,"h":30}, "spriteSourceSize": {"x":2,"y":2,"w":30,"h":30},
@ -106,7 +106,7 @@
}, },
"sprites/belt/right_1.png": "sprites/belt/right_1.png":
{ {
"frame": {"x":71,"y":331,"w":30,"h":30}, "frame": {"x":137,"y":985,"w":30,"h":30},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":2,"y":2,"w":30,"h":30}, "spriteSourceSize": {"x":2,"y":2,"w":30,"h":30},
@ -114,7 +114,7 @@
}, },
"sprites/belt/right_2.png": "sprites/belt/right_2.png":
{ {
"frame": {"x":3,"y":296,"w":30,"h":30}, "frame": {"x":171,"y":997,"w":30,"h":30},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":2,"y":2,"w":30,"h":30}, "spriteSourceSize": {"x":2,"y":2,"w":30,"h":30},
@ -122,7 +122,7 @@
}, },
"sprites/belt/right_3.png": "sprites/belt/right_3.png":
{ {
"frame": {"x":37,"y":296,"w":30,"h":30}, "frame": {"x":205,"y":1010,"w":30,"h":30},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":2,"y":2,"w":30,"h":30}, "spriteSourceSize": {"x":2,"y":2,"w":30,"h":30},
@ -130,7 +130,7 @@
}, },
"sprites/belt/right_4.png": "sprites/belt/right_4.png":
{ {
"frame": {"x":71,"y":296,"w":30,"h":30}, "frame": {"x":99,"y":1001,"w":30,"h":30},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":2,"y":2,"w":30,"h":30}, "spriteSourceSize": {"x":2,"y":2,"w":30,"h":30},
@ -138,7 +138,7 @@
}, },
"sprites/belt/right_5.png": "sprites/belt/right_5.png":
{ {
"frame": {"x":105,"y":331,"w":30,"h":30}, "frame": {"x":133,"y":1019,"w":30,"h":30},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":2,"y":2,"w":30,"h":30}, "spriteSourceSize": {"x":2,"y":2,"w":30,"h":30},
@ -146,7 +146,7 @@
}, },
"sprites/blueprints/belt_left.png": "sprites/blueprints/belt_left.png":
{ {
"frame": {"x":139,"y":331,"w":30,"h":30}, "frame": {"x":99,"y":1035,"w":30,"h":30},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":0,"y":2,"w":30,"h":30}, "spriteSourceSize": {"x":0,"y":2,"w":30,"h":30},
@ -154,7 +154,7 @@
}, },
"sprites/blueprints/belt_right.png": "sprites/blueprints/belt_right.png":
{ {
"frame": {"x":173,"y":331,"w":30,"h":30}, "frame": {"x":167,"y":1031,"w":30,"h":30},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":2,"y":2,"w":30,"h":30}, "spriteSourceSize": {"x":2,"y":2,"w":30,"h":30},
@ -162,7 +162,7 @@
}, },
"sprites/blueprints/belt_top.png": "sprites/blueprints/belt_top.png":
{ {
"frame": {"x":467,"y":416,"w":28,"h":32}, "frame": {"x":201,"y":1044,"w":28,"h":32},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":2,"y":0,"w":28,"h":32}, "spriteSourceSize": {"x":2,"y":0,"w":28,"h":32},
@ -170,7 +170,7 @@
}, },
"sprites/blueprints/cutter-quad.png": "sprites/blueprints/cutter-quad.png":
{ {
"frame": {"x":191,"y":55,"w":184,"h":48}, "frame": {"x":3,"y":296,"w":184,"h":48},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":5,"y":0,"w":184,"h":48}, "spriteSourceSize": {"x":5,"y":0,"w":184,"h":48},
@ -178,7 +178,7 @@
}, },
"sprites/blueprints/cutter.png": "sprites/blueprints/cutter.png":
{ {
"frame": {"x":95,"y":244,"w":87,"h":48}, "frame": {"x":155,"y":419,"w":87,"h":48},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":5,"y":0,"w":87,"h":48}, "spriteSourceSize": {"x":5,"y":0,"w":87,"h":48},
@ -186,7 +186,7 @@
}, },
"sprites/blueprints/miner-chainable.png": "sprites/blueprints/miner-chainable.png":
{ {
"frame": {"x":262,"y":419,"w":47,"h":48}, "frame": {"x":195,"y":3,"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},
@ -194,7 +194,7 @@
}, },
"sprites/blueprints/miner.png": "sprites/blueprints/miner.png":
{ {
"frame": {"x":313,"y":419,"w":47,"h":48}, "frame": {"x":195,"y":55,"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},
@ -202,7 +202,7 @@
}, },
"sprites/blueprints/mixer.png": "sprites/blueprints/mixer.png":
{ {
"frame": {"x":191,"y":211,"w":89,"h":48}, "frame": {"x":3,"y":808,"w":89,"h":48},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":3,"y":0,"w":89,"h":48}, "spriteSourceSize": {"x":3,"y":0,"w":89,"h":48},
@ -210,12 +210,20 @@
}, },
"sprites/blueprints/painter-double.png": "sprites/blueprints/painter-double.png":
{ {
"frame": {"x":387,"y":3,"w":96,"h":96}, "frame": {"x":3,"y":400,"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},
"sourceSize": {"w":96,"h":96} "sourceSize": {"w":96,"h":96}
}, },
"sprites/blueprints/painter-mirrored.png":
{
"frame": {"x":3,"y":600,"w":96,"h":48},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":96,"h":48},
"sourceSize": {"w":96,"h":48}
},
"sprites/blueprints/painter-quad.png": "sprites/blueprints/painter-quad.png":
{ {
"frame": {"x":3,"y":3,"w":188,"h":48}, "frame": {"x":3,"y":3,"w":188,"h":48},
@ -226,7 +234,7 @@
}, },
"sprites/blueprints/painter.png": "sprites/blueprints/painter.png":
{ {
"frame": {"x":191,"y":159,"w":96,"h":48}, "frame": {"x":3,"y":652,"w":96,"h":48},
"rotated": false, "rotated": false,
"trimmed": false, "trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":96,"h":48}, "spriteSourceSize": {"x":0,"y":0,"w":96,"h":48},
@ -234,7 +242,7 @@
}, },
"sprites/blueprints/rotater-ccw.png": "sprites/blueprints/rotater-ccw.png":
{ {
"frame": {"x":291,"y":159,"w":48,"h":48}, "frame": {"x":191,"y":107,"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},
@ -242,7 +250,7 @@
}, },
"sprites/blueprints/rotater.png": "sprites/blueprints/rotater.png":
{ {
"frame": {"x":459,"y":313,"w":48,"h":48}, "frame": {"x":191,"y":159,"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},
@ -250,7 +258,7 @@
}, },
"sprites/blueprints/splitter-compact-inverse.png": "sprites/blueprints/splitter-compact-inverse.png":
{ {
"frame": {"x":210,"y":315,"w":48,"h":48}, "frame": {"x":191,"y":211,"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},
@ -258,7 +266,7 @@
}, },
"sprites/blueprints/splitter-compact.png": "sprites/blueprints/splitter-compact.png":
{ {
"frame": {"x":415,"y":416,"w":47,"h":47}, "frame": {"x":103,"y":780,"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},
@ -266,7 +274,7 @@
}, },
"sprites/blueprints/splitter.png": "sprites/blueprints/splitter.png":
{ {
"frame": {"x":186,"y":263,"w":87,"h":48}, "frame": {"x":155,"y":471,"w":87,"h":48},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":5,"y":0,"w":87,"h":48}, "spriteSourceSize": {"x":5,"y":0,"w":87,"h":48},
@ -274,7 +282,7 @@
}, },
"sprites/blueprints/stacker.png": "sprites/blueprints/stacker.png":
{ {
"frame": {"x":284,"y":227,"w":89,"h":48}, "frame": {"x":96,"y":831,"w":89,"h":48},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":3,"y":0,"w":89,"h":48}, "spriteSourceSize": {"x":3,"y":0,"w":89,"h":48},
@ -282,7 +290,7 @@
}, },
"sprites/blueprints/trash-storage.png": "sprites/blueprints/trash-storage.png":
{ {
"frame": {"x":3,"y":365,"w":85,"h":96}, "frame": {"x":155,"y":627,"w":85,"h":96},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":6,"y":0,"w":85,"h":96}, "spriteSourceSize": {"x":6,"y":0,"w":85,"h":96},
@ -290,7 +298,7 @@
}, },
"sprites/blueprints/trash.png": "sprites/blueprints/trash.png":
{ {
"frame": {"x":181,"y":391,"w":48,"h":48}, "frame": {"x":191,"y":263,"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},
@ -298,7 +306,7 @@
}, },
"sprites/blueprints/underground_belt_entry-tier2.png": "sprites/blueprints/underground_belt_entry-tier2.png":
{ {
"frame": {"x":3,"y":465,"w":48,"h":43}, "frame": {"x":103,"y":503,"w":48,"h":43},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":0,"y":5,"w":48,"h":43}, "spriteSourceSize": {"x":0,"y":5,"w":48,"h":43},
@ -306,7 +314,7 @@
}, },
"sprites/blueprints/underground_belt_entry.png": "sprites/blueprints/underground_belt_entry.png":
{ {
"frame": {"x":106,"y":465,"w":48,"h":38}, "frame": {"x":103,"y":550,"w":48,"h":38},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":0,"y":10,"w":48,"h":38}, "spriteSourceSize": {"x":0,"y":10,"w":48,"h":38},
@ -314,7 +322,7 @@
}, },
"sprites/blueprints/underground_belt_exit-tier2.png": "sprites/blueprints/underground_belt_exit-tier2.png":
{ {
"frame": {"x":158,"y":465,"w":48,"h":38}, "frame": {"x":103,"y":592,"w":48,"h":38},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":0,"y":0,"w":48,"h":38}, "spriteSourceSize": {"x":0,"y":0,"w":48,"h":38},
@ -322,7 +330,7 @@
}, },
"sprites/blueprints/underground_belt_exit.png": "sprites/blueprints/underground_belt_exit.png":
{ {
"frame": {"x":262,"y":471,"w":48,"h":38}, "frame": {"x":103,"y":634,"w":48,"h":38},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":0,"y":0,"w":48,"h":38}, "spriteSourceSize": {"x":0,"y":0,"w":48,"h":38},
@ -330,7 +338,7 @@
}, },
"sprites/buildings/belt_left.png": "sprites/buildings/belt_left.png":
{ {
"frame": {"x":343,"y":159,"w":30,"h":30}, "frame": {"x":143,"y":883,"w":30,"h":30},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":0,"y":2,"w":30,"h":30}, "spriteSourceSize": {"x":0,"y":2,"w":30,"h":30},
@ -338,7 +346,7 @@
}, },
"sprites/buildings/belt_right.png": "sprites/buildings/belt_right.png":
{ {
"frame": {"x":37,"y":331,"w":30,"h":30}, "frame": {"x":103,"y":967,"w":30,"h":30},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":2,"y":2,"w":30,"h":30}, "spriteSourceSize": {"x":2,"y":2,"w":30,"h":30},
@ -346,7 +354,7 @@
}, },
"sprites/buildings/belt_top.png": "sprites/buildings/belt_top.png":
{ {
"frame": {"x":479,"y":103,"w":28,"h":32}, "frame": {"x":3,"y":1010,"w":28,"h":32},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":2,"y":0,"w":28,"h":32}, "spriteSourceSize": {"x":2,"y":0,"w":28,"h":32},
@ -354,7 +362,7 @@
}, },
"sprites/buildings/cutter-quad.png": "sprites/buildings/cutter-quad.png":
{ {
"frame": {"x":191,"y":107,"w":184,"h":48}, "frame": {"x":3,"y":348,"w":184,"h":48},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":5,"y":0,"w":184,"h":48}, "spriteSourceSize": {"x":5,"y":0,"w":184,"h":48},
@ -362,7 +370,7 @@
}, },
"sprites/buildings/cutter.png": "sprites/buildings/cutter.png":
{ {
"frame": {"x":277,"y":279,"w":87,"h":48}, "frame": {"x":155,"y":523,"w":87,"h":48},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":5,"y":0,"w":87,"h":48}, "spriteSourceSize": {"x":5,"y":0,"w":87,"h":48},
@ -370,7 +378,7 @@
}, },
"sprites/buildings/hub.png": "sprites/buildings/hub.png":
{ {
"frame": {"x":3,"y":55,"w":184,"h":185}, "frame": {"x":3,"y":107,"w":184,"h":185},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":4,"y":4,"w":184,"h":185}, "spriteSourceSize": {"x":4,"y":4,"w":184,"h":185},
@ -378,7 +386,7 @@
}, },
"sprites/buildings/miner-chainable.png": "sprites/buildings/miner-chainable.png":
{ {
"frame": {"x":349,"y":365,"w":47,"h":48}, "frame": {"x":103,"y":676,"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},
@ -386,7 +394,7 @@
}, },
"sprites/buildings/miner.png": "sprites/buildings/miner.png":
{ {
"frame": {"x":364,"y":417,"w":47,"h":48}, "frame": {"x":103,"y":728,"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},
@ -394,7 +402,7 @@
}, },
"sprites/buildings/mixer.png": "sprites/buildings/mixer.png":
{ {
"frame": {"x":377,"y":255,"w":88,"h":48}, "frame": {"x":154,"y":727,"w":88,"h":48},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":4,"y":0,"w":88,"h":48}, "spriteSourceSize": {"x":4,"y":0,"w":88,"h":48},
@ -402,15 +410,23 @@
}, },
"sprites/buildings/painter-double.png": "sprites/buildings/painter-double.png":
{ {
"frame": {"x":379,"y":103,"w":96,"h":96}, "frame": {"x":3,"y":500,"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},
"sourceSize": {"w":96,"h":96} "sourceSize": {"w":96,"h":96}
}, },
"sprites/buildings/painter-mirrored.png":
{
"frame": {"x":3,"y":704,"w":96,"h":48},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":96,"h":48},
"sourceSize": {"w":96,"h":48}
},
"sprites/buildings/painter-quad.png": "sprites/buildings/painter-quad.png":
{ {
"frame": {"x":195,"y":3,"w":188,"h":48}, "frame": {"x":3,"y":55,"w":188,"h":48},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":1,"y":0,"w":188,"h":48}, "spriteSourceSize": {"x":1,"y":0,"w":188,"h":48},
@ -418,7 +434,7 @@
}, },
"sprites/buildings/painter.png": "sprites/buildings/painter.png":
{ {
"frame": {"x":377,"y":203,"w":96,"h":48}, "frame": {"x":3,"y":756,"w":96,"h":48},
"rotated": false, "rotated": false,
"trimmed": false, "trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":96,"h":48}, "spriteSourceSize": {"x":0,"y":0,"w":96,"h":48},
@ -426,7 +442,7 @@
}, },
"sprites/buildings/rotater-ccw.png": "sprites/buildings/rotater-ccw.png":
{ {
"frame": {"x":210,"y":443,"w":48,"h":48}, "frame": {"x":191,"y":315,"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},
@ -434,7 +450,7 @@
}, },
"sprites/buildings/rotater.png": "sprites/buildings/rotater.png":
{ {
"frame": {"x":233,"y":367,"w":48,"h":48}, "frame": {"x":191,"y":367,"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},
@ -442,7 +458,7 @@
}, },
"sprites/buildings/splitter-compact-inverse.png": "sprites/buildings/splitter-compact-inverse.png":
{ {
"frame": {"x":400,"y":365,"w":48,"h":47}, "frame": {"x":103,"y":452,"w":48,"h":47},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":0,"y":0,"w":48,"h":47}, "spriteSourceSize": {"x":0,"y":0,"w":48,"h":47},
@ -450,7 +466,7 @@
}, },
"sprites/buildings/splitter-compact.png": "sprites/buildings/splitter-compact.png":
{ {
"frame": {"x":452,"y":365,"w":47,"h":47}, "frame": {"x":189,"y":831,"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},
@ -458,7 +474,7 @@
}, },
"sprites/buildings/splitter.png": "sprites/buildings/splitter.png":
{ {
"frame": {"x":368,"y":307,"w":87,"h":48}, "frame": {"x":155,"y":575,"w":87,"h":48},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":5,"y":0,"w":87,"h":48}, "spriteSourceSize": {"x":5,"y":0,"w":87,"h":48},
@ -466,7 +482,7 @@
}, },
"sprites/buildings/stacker.png": "sprites/buildings/stacker.png":
{ {
"frame": {"x":3,"y":244,"w":88,"h":48}, "frame": {"x":154,"y":779,"w":88,"h":48},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":4,"y":0,"w":88,"h":48}, "spriteSourceSize": {"x":4,"y":0,"w":88,"h":48},
@ -474,7 +490,7 @@
}, },
"sprites/buildings/trash-storage.png": "sprites/buildings/trash-storage.png":
{ {
"frame": {"x":92,"y":365,"w":85,"h":96}, "frame": {"x":3,"y":860,"w":85,"h":96},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":6,"y":0,"w":85,"h":96}, "spriteSourceSize": {"x":6,"y":0,"w":85,"h":96},
@ -482,7 +498,7 @@
}, },
"sprites/buildings/trash.png": "sprites/buildings/trash.png":
{ {
"frame": {"x":294,"y":331,"w":48,"h":48}, "frame": {"x":103,"y":400,"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},
@ -490,7 +506,7 @@
}, },
"sprites/buildings/underground_belt_entry-tier2.png": "sprites/buildings/underground_belt_entry-tier2.png":
{ {
"frame": {"x":55,"y":465,"w":47,"h":42}, "frame": {"x":189,"y":882,"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},
@ -498,7 +514,7 @@
}, },
"sprites/buildings/underground_belt_entry.png": "sprites/buildings/underground_belt_entry.png":
{ {
"frame": {"x":314,"y":471,"w":47,"h":38}, "frame": {"x":92,"y":883,"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},
@ -506,7 +522,7 @@
}, },
"sprites/buildings/underground_belt_exit-tier2.png": "sprites/buildings/underground_belt_exit-tier2.png":
{ {
"frame": {"x":365,"y":469,"w":47,"h":38}, "frame": {"x":92,"y":925,"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},
@ -514,7 +530,7 @@
}, },
"sprites/buildings/underground_belt_exit.png": "sprites/buildings/underground_belt_exit.png":
{ {
"frame": {"x":416,"y":467,"w":47,"h":38}, "frame": {"x":189,"y":928,"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},
@ -522,7 +538,7 @@
}, },
"sprites/debug/acceptor_slot.png": "sprites/debug/acceptor_slot.png":
{ {
"frame": {"x":487,"y":3,"w":14,"h":16}, "frame": {"x":226,"y":970,"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},
@ -530,7 +546,7 @@
}, },
"sprites/debug/ejector_slot.png": "sprites/debug/ejector_slot.png":
{ {
"frame": {"x":487,"y":23,"w":14,"h":16}, "frame": {"x":226,"y":990,"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},
@ -538,7 +554,7 @@
}, },
"sprites/map_overview/belt_forward.png": "sprites/map_overview/belt_forward.png":
{ {
"frame": {"x":487,"y":43,"w":8,"h":8}, "frame": {"x":171,"y":400,"w":8,"h":8},
"rotated": false, "rotated": false,
"trimmed": false, "trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":8,"h":8}, "spriteSourceSize": {"x":0,"y":0,"w":8,"h":8},
@ -546,7 +562,7 @@
}, },
"sprites/map_overview/belt_left.png": "sprites/map_overview/belt_left.png":
{ {
"frame": {"x":499,"y":43,"w":8,"h":8}, "frame": {"x":177,"y":883,"w":8,"h":8},
"rotated": false, "rotated": false,
"trimmed": false, "trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":8,"h":8}, "spriteSourceSize": {"x":0,"y":0,"w":8,"h":8},
@ -554,7 +570,7 @@
}, },
"sprites/map_overview/belt_right.png": "sprites/map_overview/belt_right.png":
{ {
"frame": {"x":487,"y":55,"w":8,"h":8}, "frame": {"x":177,"y":895,"w":8,"h":8},
"rotated": false, "rotated": false,
"trimmed": false, "trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":8,"h":8}, "spriteSourceSize": {"x":0,"y":0,"w":8,"h":8},
@ -562,15 +578,31 @@
}, },
"sprites/misc/deletion_marker.png": "sprites/misc/deletion_marker.png":
{ {
"frame": {"x":181,"y":365,"w":22,"h":22}, "frame": {"x":165,"y":1065,"w":22,"h":22},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":1,"y":1,"w":22,"h":22}, "spriteSourceSize": {"x":1,"y":1,"w":22,"h":22},
"sourceSize": {"w":24,"h":24} "sourceSize": {"w":24,"h":24}
}, },
"sprites/misc/hub_direction_indicator.png":
{
"frame": {"x":177,"y":907,"w":8,"h":8},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":8,"h":8},
"sourceSize": {"w":8,"h":8}
},
"sprites/misc/lock_direction_indicator.png":
{
"frame": {"x":155,"y":400,"w":12,"h":10},
"rotated": false,
"trimmed": true,
"spriteSourceSize": {"x":0,"y":1,"w":12,"h":10},
"sourceSize": {"w":12,"h":12}
},
"sprites/misc/slot_bad_arrow.png": "sprites/misc/slot_bad_arrow.png":
{ {
"frame": {"x":181,"y":365,"w":22,"h":22}, "frame": {"x":165,"y":1065,"w":22,"h":22},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":1,"y":1,"w":22,"h":22}, "spriteSourceSize": {"x":1,"y":1,"w":22,"h":22},
@ -578,7 +610,7 @@
}, },
"sprites/misc/slot_good_arrow.png": "sprites/misc/slot_good_arrow.png":
{ {
"frame": {"x":105,"y":296,"w":22,"h":24}, "frame": {"x":69,"y":1001,"w":22,"h":24},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":1,"y":0,"w":22,"h":24}, "spriteSourceSize": {"x":1,"y":0,"w":22,"h":24},
@ -586,7 +618,7 @@
}, },
"sprites/misc/storage_overlay.png": "sprites/misc/storage_overlay.png":
{ {
"frame": {"x":131,"y":296,"w":45,"h":23}, "frame": {"x":177,"y":970,"w":45,"h":23},
"rotated": false, "rotated": false,
"trimmed": false, "trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":45,"h":23}, "spriteSourceSize": {"x":0,"y":0,"w":45,"h":23},
@ -594,7 +626,7 @@
}, },
"sprites/misc/waypoint.png": "sprites/misc/waypoint.png":
{ {
"frame": {"x":499,"y":55,"w":8,"h":8}, "frame": {"x":177,"y":919,"w":8,"h":8},
"rotated": false, "rotated": false,
"trimmed": false, "trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":8,"h":8}, "spriteSourceSize": {"x":0,"y":0,"w":8,"h":8},
@ -605,8 +637,8 @@
"version": "1.0", "version": "1.0",
"image": "atlas0_25.png", "image": "atlas0_25.png",
"format": "RGBA8888", "format": "RGBA8888",
"size": {"w":510,"h":512}, "size": {"w":245,"h":1090},
"scale": "0.25", "scale": "0.25",
"smartupdate": "$TexturePacker:SmartUpdate:3dd7a89f30024dd4787ad4af6b14588a:9ba11f8b02134c4376ab4e0a44f8b850:f159918d23e5952766c6d23ab52278c6$" "smartupdate": "$TexturePacker:SmartUpdate:8985524bba1a3f16cecab3c03b6aaa06:d614d20bfce033d8a8ab0990af085d16:f159918d23e5952766c6d23ab52278c6$"
} }
} }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 160 KiB

After

Width:  |  Height:  |  Size: 166 KiB

View File

@ -2,7 +2,7 @@
"sprites/belt/forward_0.png": "sprites/belt/forward_0.png":
{ {
"frame": {"x":49,"y":1765,"w":51,"h":63}, "frame": {"x":1966,"y":3,"w":51,"h":63},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":6,"y":0,"w":51,"h":63}, "spriteSourceSize": {"x":6,"y":0,"w":51,"h":63},
@ -10,7 +10,7 @@
}, },
"sprites/belt/forward_1.png": "sprites/belt/forward_1.png":
{ {
"frame": {"x":3,"y":1902,"w":51,"h":63}, "frame": {"x":1835,"y":203,"w":51,"h":63},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":6,"y":0,"w":51,"h":63}, "spriteSourceSize": {"x":6,"y":0,"w":51,"h":63},
@ -18,7 +18,7 @@
}, },
"sprites/belt/forward_2.png": "sprites/belt/forward_2.png":
{ {
"frame": {"x":58,"y":1902,"w":51,"h":63}, "frame": {"x":1879,"y":304,"w":51,"h":63},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":6,"y":0,"w":51,"h":63}, "spriteSourceSize": {"x":6,"y":0,"w":51,"h":63},
@ -26,7 +26,7 @@
}, },
"sprites/belt/forward_3.png": "sprites/belt/forward_3.png":
{ {
"frame": {"x":113,"y":1887,"w":51,"h":63}, "frame": {"x":1934,"y":304,"w":51,"h":63},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":6,"y":0,"w":51,"h":63}, "spriteSourceSize": {"x":6,"y":0,"w":51,"h":63},
@ -34,7 +34,7 @@
}, },
"sprites/belt/forward_4.png": "sprites/belt/forward_4.png":
{ {
"frame": {"x":168,"y":1830,"w":51,"h":63}, "frame": {"x":1844,"y":381,"w":51,"h":63},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":6,"y":0,"w":51,"h":63}, "spriteSourceSize": {"x":6,"y":0,"w":51,"h":63},
@ -42,7 +42,7 @@
}, },
"sprites/belt/forward_5.png": "sprites/belt/forward_5.png":
{ {
"frame": {"x":168,"y":1897,"w":51,"h":63}, "frame": {"x":1899,"y":371,"w":51,"h":63},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":6,"y":0,"w":51,"h":63}, "spriteSourceSize": {"x":6,"y":0,"w":51,"h":63},
@ -50,7 +50,7 @@
}, },
"sprites/belt/left_0.png": "sprites/belt/left_0.png":
{ {
"frame": {"x":104,"y":1765,"w":57,"h":57}, "frame": {"x":1890,"y":243,"w":57,"h":57},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":0,"y":6,"w":57,"h":57}, "spriteSourceSize": {"x":0,"y":6,"w":57,"h":57},
@ -58,7 +58,7 @@
}, },
"sprites/belt/left_1.png": "sprites/belt/left_1.png":
{ {
"frame": {"x":165,"y":1769,"w":57,"h":57}, "frame": {"x":1951,"y":243,"w":57,"h":57},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":0,"y":6,"w":57,"h":57}, "spriteSourceSize": {"x":0,"y":6,"w":57,"h":57},
@ -66,7 +66,7 @@
}, },
"sprites/belt/left_2.png": "sprites/belt/left_2.png":
{ {
"frame": {"x":104,"y":1826,"w":57,"h":57}, "frame": {"x":1783,"y":381,"w":57,"h":57},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":0,"y":6,"w":57,"h":57}, "spriteSourceSize": {"x":0,"y":6,"w":57,"h":57},
@ -74,7 +74,7 @@
}, },
"sprites/belt/left_3.png": "sprites/belt/left_3.png":
{ {
"frame": {"x":226,"y":1782,"w":57,"h":57}, "frame": {"x":1954,"y":371,"w":57,"h":57},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":0,"y":6,"w":57,"h":57}, "spriteSourceSize": {"x":0,"y":6,"w":57,"h":57},
@ -82,7 +82,7 @@
}, },
"sprites/belt/left_4.png": "sprites/belt/left_4.png":
{ {
"frame": {"x":287,"y":1782,"w":57,"h":57}, "frame": {"x":1954,"y":432,"w":57,"h":57},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":0,"y":6,"w":57,"h":57}, "spriteSourceSize": {"x":0,"y":6,"w":57,"h":57},
@ -90,7 +90,7 @@
}, },
"sprites/belt/left_5.png": "sprites/belt/left_5.png":
{ {
"frame": {"x":348,"y":1835,"w":57,"h":57}, "frame": {"x":1363,"y":403,"w":57,"h":57},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":0,"y":6,"w":57,"h":57}, "spriteSourceSize": {"x":0,"y":6,"w":57,"h":57},
@ -98,7 +98,7 @@
}, },
"sprites/belt/right_0.png": "sprites/belt/right_0.png":
{ {
"frame": {"x":409,"y":1835,"w":57,"h":57}, "frame": {"x":1424,"y":403,"w":57,"h":57},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":6,"y":6,"w":57,"h":57}, "spriteSourceSize": {"x":6,"y":6,"w":57,"h":57},
@ -106,7 +106,7 @@
}, },
"sprites/belt/right_1.png": "sprites/belt/right_1.png":
{ {
"frame": {"x":223,"y":1896,"w":57,"h":57}, "frame": {"x":1485,"y":403,"w":57,"h":57},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":6,"y":6,"w":57,"h":57}, "spriteSourceSize": {"x":6,"y":6,"w":57,"h":57},
@ -114,7 +114,7 @@
}, },
"sprites/belt/right_2.png": "sprites/belt/right_2.png":
{ {
"frame": {"x":284,"y":1843,"w":57,"h":57}, "frame": {"x":1546,"y":403,"w":57,"h":57},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":6,"y":6,"w":57,"h":57}, "spriteSourceSize": {"x":6,"y":6,"w":57,"h":57},
@ -122,7 +122,7 @@
}, },
"sprites/belt/right_3.png": "sprites/belt/right_3.png":
{ {
"frame": {"x":284,"y":1904,"w":57,"h":57}, "frame": {"x":1607,"y":402,"w":57,"h":57},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":6,"y":6,"w":57,"h":57}, "spriteSourceSize": {"x":6,"y":6,"w":57,"h":57},
@ -130,7 +130,7 @@
}, },
"sprites/belt/right_4.png": "sprites/belt/right_4.png":
{ {
"frame": {"x":345,"y":1896,"w":57,"h":57}, "frame": {"x":1668,"y":402,"w":57,"h":57},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":6,"y":6,"w":57,"h":57}, "spriteSourceSize": {"x":6,"y":6,"w":57,"h":57},
@ -138,7 +138,7 @@
}, },
"sprites/belt/right_5.png": "sprites/belt/right_5.png":
{ {
"frame": {"x":406,"y":1896,"w":57,"h":57}, "frame": {"x":1952,"y":181,"w":57,"h":57},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":6,"y":6,"w":57,"h":57}, "spriteSourceSize": {"x":6,"y":6,"w":57,"h":57},
@ -146,7 +146,7 @@
}, },
"sprites/blueprints/belt_left.png": "sprites/blueprints/belt_left.png":
{ {
"frame": {"x":178,"y":1707,"w":58,"h":58}, "frame": {"x":1301,"y":400,"w":58,"h":58},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":0,"y":5,"w":58,"h":58}, "spriteSourceSize": {"x":0,"y":5,"w":58,"h":58},
@ -154,7 +154,7 @@
}, },
"sprites/blueprints/belt_right.png": "sprites/blueprints/belt_right.png":
{ {
"frame": {"x":370,"y":1773,"w":58,"h":58}, "frame": {"x":1890,"y":181,"w":58,"h":58},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":5,"y":5,"w":58,"h":58}, "spriteSourceSize": {"x":5,"y":5,"w":58,"h":58},
@ -162,7 +162,7 @@
}, },
"sprites/blueprints/belt_top.png": "sprites/blueprints/belt_top.png":
{ {
"frame": {"x":3,"y":1835,"w":53,"h":63}, "frame": {"x":1151,"y":403,"w":53,"h":63},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":5,"y":0,"w":53,"h":63}, "spriteSourceSize": {"x":5,"y":0,"w":53,"h":63},
@ -170,7 +170,7 @@
}, },
"sprites/blueprints/cutter-quad.png": "sprites/blueprints/cutter-quad.png":
{ {
"frame": {"x":3,"y":574,"w":366,"h":96}, "frame": {"x":3,"y":374,"w":366,"h":96},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":11,"y":0,"w":366,"h":96}, "spriteSourceSize": {"x":11,"y":0,"w":366,"h":96},
@ -178,7 +178,7 @@
}, },
"sprites/blueprints/cutter.png": "sprites/blueprints/cutter.png":
{ {
"frame": {"x":3,"y":1465,"w":172,"h":96}, "frame": {"x":1285,"y":203,"w":172,"h":96},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":11,"y":0,"w":172,"h":96}, "spriteSourceSize": {"x":11,"y":0,"w":172,"h":96},
@ -186,7 +186,7 @@
}, },
"sprites/blueprints/miner-chainable.png": "sprites/blueprints/miner-chainable.png":
{ {
"frame": {"x":179,"y":1507,"w":92,"h":96}, "frame": {"x":1401,"y":303,"w":92,"h":96},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":3,"y":0,"w":92,"h":96}, "spriteSourceSize": {"x":3,"y":0,"w":92,"h":96},
@ -194,7 +194,7 @@
}, },
"sprites/blueprints/miner.png": "sprites/blueprints/miner.png":
{ {
"frame": {"x":178,"y":1607,"w":92,"h":96}, "frame": {"x":1497,"y":303,"w":92,"h":96},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":3,"y":0,"w":92,"h":96}, "spriteSourceSize": {"x":3,"y":0,"w":92,"h":96},
@ -202,7 +202,7 @@
}, },
"sprites/blueprints/mixer.png": "sprites/blueprints/mixer.png":
{ {
"frame": {"x":296,"y":1217,"w":175,"h":96}, "frame": {"x":1143,"y":103,"w":175,"h":96},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":8,"y":0,"w":175,"h":96}, "spriteSourceSize": {"x":8,"y":0,"w":175,"h":96},
@ -210,15 +210,23 @@
}, },
"sprites/blueprints/painter-double.png": "sprites/blueprints/painter-double.png":
{ {
"frame": {"x":3,"y":774,"w":192,"h":192}, "frame": {"x":373,"y":203,"w":192,"h":192},
"rotated": false, "rotated": false,
"trimmed": false, "trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":192,"h":192}, "spriteSourceSize": {"x":0,"y":0,"w":192,"h":192},
"sourceSize": {"w":192,"h":192} "sourceSize": {"w":192,"h":192}
}, },
"sprites/blueprints/painter-mirrored.png":
{
"frame": {"x":751,"y":103,"w":192,"h":96},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":192,"h":96},
"sourceSize": {"w":192,"h":96}
},
"sprites/blueprints/painter-quad.png": "sprites/blueprints/painter-quad.png":
{ {
"frame": {"x":3,"y":3,"w":374,"h":96}, "frame": {"x":373,"y":3,"w":374,"h":96},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":3,"y":0,"w":374,"h":96}, "spriteSourceSize": {"x":3,"y":0,"w":374,"h":96},
@ -226,7 +234,7 @@
}, },
"sprites/blueprints/painter.png": "sprites/blueprints/painter.png":
{ {
"frame": {"x":3,"y":1165,"w":192,"h":96}, "frame": {"x":1121,"y":3,"w":192,"h":96},
"rotated": false, "rotated": false,
"trimmed": false, "trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":192,"h":96}, "spriteSourceSize": {"x":0,"y":0,"w":192,"h":96},
@ -234,7 +242,7 @@
}, },
"sprites/blueprints/rotater-ccw.png": "sprites/blueprints/rotater-ccw.png":
{ {
"frame": {"x":373,"y":249,"w":96,"h":96}, "frame": {"x":1866,"y":3,"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},
@ -242,7 +250,7 @@
}, },
"sprites/blueprints/rotater.png": "sprites/blueprints/rotater.png":
{ {
"frame": {"x":373,"y":349,"w":96,"h":96}, "frame": {"x":1675,"y":103,"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},
@ -250,7 +258,7 @@
}, },
"sprites/blueprints/splitter-compact-inverse.png": "sprites/blueprints/splitter-compact-inverse.png":
{ {
"frame": {"x":370,"y":849,"w":95,"h":93}, "frame": {"x":1205,"y":303,"w":95,"h":93},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":0,"y":1,"w":95,"h":93}, "spriteSourceSize": {"x":0,"y":1,"w":95,"h":93},
@ -258,7 +266,7 @@
}, },
"sprites/blueprints/splitter-compact.png": "sprites/blueprints/splitter-compact.png":
{ {
"frame": {"x":369,"y":1120,"w":93,"h":93}, "frame": {"x":1304,"y":303,"w":93,"h":93},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":3,"y":1,"w":93,"h":93}, "spriteSourceSize": {"x":3,"y":1,"w":93,"h":93},
@ -266,7 +274,7 @@
}, },
"sprites/blueprints/splitter.png": "sprites/blueprints/splitter.png":
{ {
"frame": {"x":3,"y":1565,"w":171,"h":96}, "frame": {"x":1691,"y":3,"w":171,"h":96},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":11,"y":0,"w":171,"h":96}, "spriteSourceSize": {"x":11,"y":0,"w":171,"h":96},
@ -274,7 +282,7 @@
}, },
"sprites/blueprints/stacker.png": "sprites/blueprints/stacker.png":
{ {
"frame": {"x":296,"y":1317,"w":175,"h":96}, "frame": {"x":1106,"y":203,"w":175,"h":96},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":8,"y":0,"w":175,"h":96}, "spriteSourceSize": {"x":8,"y":0,"w":175,"h":96},
@ -282,7 +290,7 @@
}, },
"sprites/blueprints/trash-storage.png": "sprites/blueprints/trash-storage.png":
{ {
"frame": {"x":199,"y":774,"w":167,"h":192}, "frame": {"x":765,"y":203,"w":167,"h":192},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":14,"y":0,"w":167,"h":192}, "spriteSourceSize": {"x":14,"y":0,"w":167,"h":192},
@ -290,7 +298,7 @@
}, },
"sprites/blueprints/trash.png": "sprites/blueprints/trash.png":
{ {
"frame": {"x":373,"y":449,"w":96,"h":96}, "frame": {"x":1636,"y":203,"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},
@ -298,7 +306,7 @@
}, },
"sprites/blueprints/underground_belt_entry-tier2.png": "sprites/blueprints/underground_belt_entry-tier2.png":
{ {
"frame": {"x":199,"y":1261,"w":93,"h":84}, "frame": {"x":764,"y":399,"w":93,"h":84},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":2,"y":12,"w":93,"h":84}, "spriteSourceSize": {"x":2,"y":12,"w":93,"h":84},
@ -306,7 +314,7 @@
}, },
"sprites/blueprints/underground_belt_entry.png": "sprites/blueprints/underground_belt_entry.png":
{ {
"frame": {"x":199,"y":1349,"w":93,"h":75}, "frame": {"x":373,"y":399,"w":93,"h":75},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":2,"y":21,"w":93,"h":75}, "spriteSourceSize": {"x":2,"y":21,"w":93,"h":75},
@ -314,7 +322,7 @@
}, },
"sprites/blueprints/underground_belt_exit-tier2.png": "sprites/blueprints/underground_belt_exit-tier2.png":
{ {
"frame": {"x":369,"y":1041,"w":94,"h":75}, "frame": {"x":957,"y":399,"w":94,"h":75},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":2,"y":0,"w":94,"h":75}, "spriteSourceSize": {"x":2,"y":0,"w":94,"h":75},
@ -322,7 +330,7 @@
}, },
"sprites/blueprints/underground_belt_exit.png": "sprites/blueprints/underground_belt_exit.png":
{ {
"frame": {"x":181,"y":1428,"w":93,"h":75}, "frame": {"x":470,"y":399,"w":93,"h":75},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":2,"y":0,"w":93,"h":75}, "spriteSourceSize": {"x":2,"y":0,"w":93,"h":75},
@ -330,7 +338,7 @@
}, },
"sprites/buildings/belt_left.png": "sprites/buildings/belt_left.png":
{ {
"frame": {"x":104,"y":1765,"w":57,"h":57}, "frame": {"x":1890,"y":243,"w":57,"h":57},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":0,"y":6,"w":57,"h":57}, "spriteSourceSize": {"x":0,"y":6,"w":57,"h":57},
@ -338,7 +346,7 @@
}, },
"sprites/buildings/belt_right.png": "sprites/buildings/belt_right.png":
{ {
"frame": {"x":409,"y":1835,"w":57,"h":57}, "frame": {"x":1424,"y":403,"w":57,"h":57},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":6,"y":6,"w":57,"h":57}, "spriteSourceSize": {"x":6,"y":6,"w":57,"h":57},
@ -346,7 +354,7 @@
}, },
"sprites/buildings/belt_top.png": "sprites/buildings/belt_top.png":
{ {
"frame": {"x":49,"y":1765,"w":51,"h":63}, "frame": {"x":1966,"y":3,"w":51,"h":63},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":6,"y":0,"w":51,"h":63}, "spriteSourceSize": {"x":6,"y":0,"w":51,"h":63},
@ -354,7 +362,7 @@
}, },
"sprites/buildings/cutter-quad.png": "sprites/buildings/cutter-quad.png":
{ {
"frame": {"x":3,"y":674,"w":366,"h":96}, "frame": {"x":751,"y":3,"w":366,"h":96},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":11,"y":0,"w":366,"h":96}, "spriteSourceSize": {"x":11,"y":0,"w":366,"h":96},
@ -362,7 +370,7 @@
}, },
"sprites/buildings/cutter.png": "sprites/buildings/cutter.png":
{ {
"frame": {"x":275,"y":1517,"w":171,"h":96}, "frame": {"x":1500,"y":103,"w":171,"h":96},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":11,"y":0,"w":171,"h":96}, "spriteSourceSize": {"x":11,"y":0,"w":171,"h":96},
@ -370,7 +378,7 @@
}, },
"sprites/buildings/hub.png": "sprites/buildings/hub.png":
{ {
"frame": {"x":3,"y":203,"w":366,"h":367}, "frame": {"x":3,"y":3,"w":366,"h":367},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":9,"y":10,"w":366,"h":367}, "spriteSourceSize": {"x":9,"y":10,"w":366,"h":367},
@ -378,7 +386,7 @@
}, },
"sprites/buildings/miner-chainable.png": "sprites/buildings/miner-chainable.png":
{ {
"frame": {"x":381,"y":3,"w":91,"h":95}, "frame": {"x":1593,"y":303,"w":91,"h":95},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":3,"y":0,"w":91,"h":95}, "spriteSourceSize": {"x":3,"y":0,"w":91,"h":95},
@ -386,7 +394,7 @@
}, },
"sprites/buildings/miner.png": "sprites/buildings/miner.png":
{ {
"frame": {"x":381,"y":102,"w":91,"h":95}, "frame": {"x":1688,"y":303,"w":91,"h":95},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":3,"y":0,"w":91,"h":95}, "spriteSourceSize": {"x":3,"y":0,"w":91,"h":95},
@ -394,7 +402,7 @@
}, },
"sprites/buildings/mixer.png": "sprites/buildings/mixer.png":
{ {
"frame": {"x":296,"y":1417,"w":174,"h":96}, "frame": {"x":1513,"y":3,"w":174,"h":96},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":9,"y":0,"w":174,"h":96}, "spriteSourceSize": {"x":9,"y":0,"w":174,"h":96},
@ -402,15 +410,23 @@
}, },
"sprites/buildings/painter-double.png": "sprites/buildings/painter-double.png":
{ {
"frame": {"x":3,"y":970,"w":192,"h":191}, "frame": {"x":569,"y":203,"w":192,"h":191},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":0,"y":0,"w":192,"h":191}, "spriteSourceSize": {"x":0,"y":0,"w":192,"h":191},
"sourceSize": {"w":192,"h":192} "sourceSize": {"w":192,"h":192}
}, },
"sprites/buildings/painter-mirrored.png":
{
"frame": {"x":947,"y":103,"w":192,"h":96},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":192,"h":96},
"sourceSize": {"w":192,"h":96}
},
"sprites/buildings/painter-quad.png": "sprites/buildings/painter-quad.png":
{ {
"frame": {"x":3,"y":103,"w":374,"h":96}, "frame": {"x":373,"y":103,"w":374,"h":96},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":3,"y":0,"w":374,"h":96}, "spriteSourceSize": {"x":3,"y":0,"w":374,"h":96},
@ -418,7 +434,7 @@
}, },
"sprites/buildings/painter.png": "sprites/buildings/painter.png":
{ {
"frame": {"x":3,"y":1265,"w":192,"h":96}, "frame": {"x":1317,"y":3,"w":192,"h":96},
"rotated": false, "rotated": false,
"trimmed": false, "trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":192,"h":96}, "spriteSourceSize": {"x":0,"y":0,"w":192,"h":96},
@ -426,7 +442,7 @@
}, },
"sprites/buildings/rotater-ccw.png": "sprites/buildings/rotater-ccw.png":
{ {
"frame": {"x":373,"y":649,"w":95,"h":96}, "frame": {"x":1736,"y":203,"w":95,"h":96},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":1,"y":0,"w":95,"h":96}, "spriteSourceSize": {"x":1,"y":0,"w":95,"h":96},
@ -434,7 +450,7 @@
}, },
"sprites/buildings/rotater.png": "sprites/buildings/rotater.png":
{ {
"frame": {"x":373,"y":749,"w":95,"h":96}, "frame": {"x":1106,"y":303,"w":95,"h":96},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":1,"y":0,"w":95,"h":96}, "spriteSourceSize": {"x":1,"y":0,"w":95,"h":96},
@ -442,7 +458,7 @@
}, },
"sprites/buildings/splitter-compact-inverse.png": "sprites/buildings/splitter-compact-inverse.png":
{ {
"frame": {"x":370,"y":946,"w":94,"h":91}, "frame": {"x":569,"y":398,"w":94,"h":91},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":0,"y":2,"w":94,"h":91}, "spriteSourceSize": {"x":0,"y":2,"w":94,"h":91},
@ -450,7 +466,7 @@
}, },
"sprites/buildings/splitter-compact.png": "sprites/buildings/splitter-compact.png":
{ {
"frame": {"x":199,"y":1166,"w":93,"h":91}, "frame": {"x":667,"y":398,"w":93,"h":91},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":3,"y":2,"w":93,"h":91}, "spriteSourceSize": {"x":3,"y":2,"w":93,"h":91},
@ -458,7 +474,7 @@
}, },
"sprites/buildings/splitter.png": "sprites/buildings/splitter.png":
{ {
"frame": {"x":3,"y":1665,"w":171,"h":96}, "frame": {"x":1461,"y":203,"w":171,"h":96},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":11,"y":0,"w":171,"h":96}, "spriteSourceSize": {"x":11,"y":0,"w":171,"h":96},
@ -466,7 +482,7 @@
}, },
"sprites/buildings/stacker.png": "sprites/buildings/stacker.png":
{ {
"frame": {"x":3,"y":1365,"w":174,"h":96}, "frame": {"x":1322,"y":103,"w":174,"h":96},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":9,"y":0,"w":174,"h":96}, "spriteSourceSize": {"x":9,"y":0,"w":174,"h":96},
@ -474,7 +490,7 @@
}, },
"sprites/buildings/trash-storage.png": "sprites/buildings/trash-storage.png":
{ {
"frame": {"x":199,"y":970,"w":166,"h":192}, "frame": {"x":936,"y":203,"w":166,"h":192},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":14,"y":0,"w":166,"h":192}, "spriteSourceSize": {"x":14,"y":0,"w":166,"h":192},
@ -482,7 +498,7 @@
}, },
"sprites/buildings/trash.png": "sprites/buildings/trash.png":
{ {
"frame": {"x":373,"y":549,"w":96,"h":96}, "frame": {"x":1775,"y":103,"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},
@ -490,7 +506,7 @@
}, },
"sprites/buildings/underground_belt_entry-tier2.png": "sprites/buildings/underground_belt_entry-tier2.png":
{ {
"frame": {"x":274,"y":1617,"w":92,"h":83}, "frame": {"x":861,"y":399,"w":92,"h":83},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":3,"y":13,"w":92,"h":83}, "spriteSourceSize": {"x":3,"y":13,"w":92,"h":83},
@ -498,7 +514,7 @@
}, },
"sprites/buildings/underground_belt_entry.png": "sprites/buildings/underground_belt_entry.png":
{ {
"frame": {"x":370,"y":1617,"w":92,"h":74}, "frame": {"x":1875,"y":103,"w":92,"h":74},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":3,"y":22,"w":92,"h":74}, "spriteSourceSize": {"x":3,"y":22,"w":92,"h":74},
@ -506,7 +522,7 @@
}, },
"sprites/buildings/underground_belt_exit-tier2.png": "sprites/buildings/underground_belt_exit-tier2.png":
{ {
"frame": {"x":370,"y":1695,"w":92,"h":74}, "frame": {"x":1783,"y":303,"w":92,"h":74},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":3,"y":0,"w":92,"h":74}, "spriteSourceSize": {"x":3,"y":0,"w":92,"h":74},
@ -514,7 +530,7 @@
}, },
"sprites/buildings/underground_belt_exit.png": "sprites/buildings/underground_belt_exit.png":
{ {
"frame": {"x":274,"y":1704,"w":92,"h":74}, "frame": {"x":1055,"y":403,"w":92,"h":74},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":3,"y":0,"w":92,"h":74}, "spriteSourceSize": {"x":3,"y":0,"w":92,"h":74},
@ -522,7 +538,7 @@
}, },
"sprites/debug/acceptor_slot.png": "sprites/debug/acceptor_slot.png":
{ {
"frame": {"x":240,"y":1707,"w":26,"h":32}, "frame": {"x":1989,"y":304,"w":26,"h":32},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":3,"y":0,"w":26,"h":32}, "spriteSourceSize": {"x":3,"y":0,"w":26,"h":32},
@ -530,7 +546,7 @@
}, },
"sprites/debug/ejector_slot.png": "sprites/debug/ejector_slot.png":
{ {
"frame": {"x":240,"y":1743,"w":26,"h":32}, "frame": {"x":1971,"y":116,"w":26,"h":32},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":3,"y":0,"w":26,"h":32}, "spriteSourceSize": {"x":3,"y":0,"w":26,"h":32},
@ -538,7 +554,7 @@
}, },
"sprites/map_overview/belt_forward.png": "sprites/map_overview/belt_forward.png":
{ {
"frame": {"x":181,"y":1365,"w":14,"h":16}, "frame": {"x":1835,"y":270,"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},
@ -546,7 +562,7 @@
}, },
"sprites/map_overview/belt_left.png": "sprites/map_overview/belt_left.png":
{ {
"frame": {"x":342,"y":1166,"w":15,"h":15}, "frame": {"x":3,"y":474,"w":15,"h":15},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":0,"y":1,"w":15,"h":15}, "spriteSourceSize": {"x":0,"y":1,"w":15,"h":15},
@ -554,7 +570,7 @@
}, },
"sprites/map_overview/belt_right.png": "sprites/map_overview/belt_right.png":
{ {
"frame": {"x":342,"y":1185,"w":15,"h":15}, "frame": {"x":22,"y":474,"w":15,"h":15},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":1,"y":1,"w":15,"h":15}, "spriteSourceSize": {"x":1,"y":1,"w":15,"h":15},
@ -562,15 +578,31 @@
}, },
"sprites/misc/deletion_marker.png": "sprites/misc/deletion_marker.png":
{ {
"frame": {"x":296,"y":1166,"w":42,"h":42}, "frame": {"x":1971,"y":70,"w":42,"h":42},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":3,"y":3,"w":42,"h":42}, "spriteSourceSize": {"x":3,"y":3,"w":42,"h":42},
"sourceSize": {"w":48,"h":48} "sourceSize": {"w":48,"h":48}
}, },
"sprites/misc/hub_direction_indicator.png":
{
"frame": {"x":2001,"y":116,"w":16,"h":16},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":16,"h":16},
"sourceSize": {"w":16,"h":16}
},
"sprites/misc/lock_direction_indicator.png":
{
"frame": {"x":1208,"y":448,"w":24,"h":16},
"rotated": false,
"trimmed": true,
"spriteSourceSize": {"x":0,"y":4,"w":24,"h":16},
"sourceSize": {"w":24,"h":24}
},
"sprites/misc/slot_bad_arrow.png": "sprites/misc/slot_bad_arrow.png":
{ {
"frame": {"x":296,"y":1166,"w":42,"h":42}, "frame": {"x":1971,"y":70,"w":42,"h":42},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":3,"y":3,"w":42,"h":42}, "spriteSourceSize": {"x":3,"y":3,"w":42,"h":42},
@ -578,7 +610,7 @@
}, },
"sprites/misc/slot_good_arrow.png": "sprites/misc/slot_good_arrow.png":
{ {
"frame": {"x":3,"y":1782,"w":42,"h":48}, "frame": {"x":1729,"y":402,"w":42,"h":48},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":3,"y":0,"w":42,"h":48}, "spriteSourceSize": {"x":3,"y":0,"w":42,"h":48},
@ -586,7 +618,7 @@
}, },
"sprites/misc/storage_overlay.png": "sprites/misc/storage_overlay.png":
{ {
"frame": {"x":381,"y":201,"w":89,"h":44}, "frame": {"x":1208,"y":400,"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},
@ -594,7 +626,7 @@
}, },
"sprites/misc/waypoint.png": "sprites/misc/waypoint.png":
{ {
"frame": {"x":181,"y":1385,"w":14,"h":16}, "frame": {"x":1989,"y":340,"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},
@ -605,8 +637,8 @@
"version": "1.0", "version": "1.0",
"image": "atlas0_50.png", "image": "atlas0_50.png",
"format": "RGBA8888", "format": "RGBA8888",
"size": {"w":475,"h":1968}, "size": {"w":2020,"h":492},
"scale": "0.5", "scale": "0.5",
"smartupdate": "$TexturePacker:SmartUpdate:3dd7a89f30024dd4787ad4af6b14588a:9ba11f8b02134c4376ab4e0a44f8b850:f159918d23e5952766c6d23ab52278c6$" "smartupdate": "$TexturePacker:SmartUpdate:8985524bba1a3f16cecab3c03b6aaa06:d614d20bfce033d8a8ab0990af085d16:f159918d23e5952766c6d23ab52278c6$"
} }
} }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 374 KiB

After

Width:  |  Height:  |  Size: 397 KiB

View File

@ -2,7 +2,7 @@
"sprites/belt/forward_0.png": "sprites/belt/forward_0.png":
{ {
"frame": {"x":1936,"y":151,"w":77,"h":95}, "frame": {"x":1963,"y":102,"w":77,"h":95},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":9,"y":0,"w":77,"h":95}, "spriteSourceSize": {"x":9,"y":0,"w":77,"h":95},
@ -10,7 +10,7 @@
}, },
"sprites/belt/forward_1.png": "sprites/belt/forward_1.png":
{ {
"frame": {"x":1936,"y":250,"w":77,"h":95}, "frame": {"x":1963,"y":201,"w":77,"h":95},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":9,"y":0,"w":77,"h":95}, "spriteSourceSize": {"x":9,"y":0,"w":77,"h":95},
@ -18,7 +18,7 @@
}, },
"sprites/belt/forward_2.png": "sprites/belt/forward_2.png":
{ {
"frame": {"x":1600,"y":708,"w":77,"h":95}, "frame": {"x":1967,"y":300,"w":77,"h":95},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":9,"y":0,"w":77,"h":95}, "spriteSourceSize": {"x":9,"y":0,"w":77,"h":95},
@ -26,7 +26,7 @@
}, },
"sprites/belt/forward_3.png": "sprites/belt/forward_3.png":
{ {
"frame": {"x":1544,"y":808,"w":77,"h":95}, "frame": {"x":1967,"y":399,"w":77,"h":95},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":9,"y":0,"w":77,"h":95}, "spriteSourceSize": {"x":9,"y":0,"w":77,"h":95},
@ -34,7 +34,7 @@
}, },
"sprites/belt/forward_4.png": "sprites/belt/forward_4.png":
{ {
"frame": {"x":1625,"y":807,"w":77,"h":95}, "frame": {"x":1967,"y":498,"w":77,"h":95},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":9,"y":0,"w":77,"h":95}, "spriteSourceSize": {"x":9,"y":0,"w":77,"h":95},
@ -42,7 +42,7 @@
}, },
"sprites/belt/forward_5.png": "sprites/belt/forward_5.png":
{ {
"frame": {"x":1544,"y":907,"w":77,"h":95}, "frame": {"x":1679,"y":952,"w":77,"h":95},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":9,"y":0,"w":77,"h":95}, "spriteSourceSize": {"x":9,"y":0,"w":77,"h":95},
@ -50,7 +50,7 @@
}, },
"sprites/belt/left_0.png": "sprites/belt/left_0.png":
{ {
"frame": {"x":1680,"y":593,"w":86,"h":86}, "frame": {"x":1217,"y":969,"w":86,"h":86},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":0,"y":9,"w":86,"h":86}, "spriteSourceSize": {"x":0,"y":9,"w":86,"h":86},
@ -58,7 +58,7 @@
}, },
"sprites/belt/left_1.png": "sprites/belt/left_1.png":
{ {
"frame": {"x":1770,"y":592,"w":86,"h":86}, "frame": {"x":1307,"y":969,"w":86,"h":86},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":0,"y":9,"w":86,"h":86}, "spriteSourceSize": {"x":0,"y":9,"w":86,"h":86},
@ -66,7 +66,7 @@
}, },
"sprites/belt/left_2.png": "sprites/belt/left_2.png":
{ {
"frame": {"x":1860,"y":592,"w":86,"h":86}, "frame": {"x":1916,"y":597,"w":86,"h":86},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":0,"y":9,"w":86,"h":86}, "spriteSourceSize": {"x":0,"y":9,"w":86,"h":86},
@ -74,7 +74,7 @@
}, },
"sprites/belt/left_3.png": "sprites/belt/left_3.png":
{ {
"frame": {"x":1681,"y":683,"w":86,"h":86}, "frame": {"x":1916,"y":687,"w":86,"h":86},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":0,"y":9,"w":86,"h":86}, "spriteSourceSize": {"x":0,"y":9,"w":86,"h":86},
@ -82,7 +82,7 @@
}, },
"sprites/belt/left_4.png": "sprites/belt/left_4.png":
{ {
"frame": {"x":1771,"y":682,"w":86,"h":86}, "frame": {"x":1916,"y":777,"w":86,"h":86},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":0,"y":9,"w":86,"h":86}, "spriteSourceSize": {"x":0,"y":9,"w":86,"h":86},
@ -90,7 +90,7 @@
}, },
"sprites/belt/left_5.png": "sprites/belt/left_5.png":
{ {
"frame": {"x":1861,"y":682,"w":86,"h":86}, "frame": {"x":1914,"y":867,"w":86,"h":86},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":0,"y":9,"w":86,"h":86}, "spriteSourceSize": {"x":0,"y":9,"w":86,"h":86},
@ -98,7 +98,7 @@
}, },
"sprites/belt/right_0.png": "sprites/belt/right_0.png":
{ {
"frame": {"x":1706,"y":773,"w":86,"h":86}, "frame": {"x":1499,"y":852,"w":86,"h":86},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":9,"y":9,"w":86,"h":86}, "spriteSourceSize": {"x":9,"y":9,"w":86,"h":86},
@ -106,7 +106,7 @@
}, },
"sprites/belt/right_1.png": "sprites/belt/right_1.png":
{ {
"frame": {"x":1796,"y":772,"w":86,"h":86}, "frame": {"x":1397,"y":967,"w":86,"h":86},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":9,"y":9,"w":86,"h":86}, "spriteSourceSize": {"x":9,"y":9,"w":86,"h":86},
@ -114,7 +114,7 @@
}, },
"sprites/belt/right_2.png": "sprites/belt/right_2.png":
{ {
"frame": {"x":1886,"y":772,"w":86,"h":86}, "frame": {"x":1589,"y":862,"w":86,"h":86},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":9,"y":9,"w":86,"h":86}, "spriteSourceSize": {"x":9,"y":9,"w":86,"h":86},
@ -122,7 +122,7 @@
}, },
"sprites/belt/right_3.png": "sprites/belt/right_3.png":
{ {
"frame": {"x":1716,"y":863,"w":86,"h":86}, "frame": {"x":1679,"y":862,"w":86,"h":86},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":9,"y":9,"w":86,"h":86}, "spriteSourceSize": {"x":9,"y":9,"w":86,"h":86},
@ -130,7 +130,7 @@
}, },
"sprites/belt/right_4.png": "sprites/belt/right_4.png":
{ {
"frame": {"x":1806,"y":862,"w":86,"h":86}, "frame": {"x":1499,"y":942,"w":86,"h":86},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":9,"y":9,"w":86,"h":86}, "spriteSourceSize": {"x":9,"y":9,"w":86,"h":86},
@ -138,7 +138,7 @@
}, },
"sprites/belt/right_5.png": "sprites/belt/right_5.png":
{ {
"frame": {"x":1896,"y":862,"w":86,"h":86}, "frame": {"x":1589,"y":952,"w":86,"h":86},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":9,"y":9,"w":86,"h":86}, "spriteSourceSize": {"x":9,"y":9,"w":86,"h":86},
@ -146,7 +146,7 @@
}, },
"sprites/blueprints/belt_left.png": "sprites/blueprints/belt_left.png":
{ {
"frame": {"x":1924,"y":349,"w":87,"h":87}, "frame": {"x":1397,"y":593,"w":87,"h":87},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":0,"y":8,"w":87,"h":87}, "spriteSourceSize": {"x":0,"y":8,"w":87,"h":87},
@ -154,7 +154,7 @@
}, },
"sprites/blueprints/belt_right.png": "sprites/blueprints/belt_right.png":
{ {
"frame": {"x":1625,"y":906,"w":87,"h":87}, "frame": {"x":1397,"y":684,"w":87,"h":87},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":8,"y":8,"w":87,"h":87}, "spriteSourceSize": {"x":8,"y":8,"w":87,"h":87},
@ -162,7 +162,7 @@
}, },
"sprites/blueprints/belt_top.png": "sprites/blueprints/belt_top.png":
{ {
"frame": {"x":1517,"y":709,"w":79,"h":95}, "frame": {"x":1963,"y":3,"w":79,"h":95},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":8,"y":0,"w":79,"h":95}, "spriteSourceSize": {"x":8,"y":0,"w":79,"h":95},
@ -186,7 +186,7 @@
}, },
"sprites/blueprints/miner-chainable.png": "sprites/blueprints/miner-chainable.png":
{ {
"frame": {"x":1784,"y":299,"w":136,"h":143}, "frame": {"x":1827,"y":447,"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},
@ -194,7 +194,7 @@
}, },
"sprites/blueprints/miner.png": "sprites/blueprints/miner.png":
{ {
"frame": {"x":1544,"y":446,"w":136,"h":143}, "frame": {"x":1076,"y":739,"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},
@ -202,7 +202,7 @@
}, },
"sprites/blueprints/mixer.png": "sprites/blueprints/mixer.png":
{ {
"frame": {"x":1671,"y":151,"w":261,"h":144}, "frame": {"x":547,"y":738,"w":261,"h":144},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":13,"y":0,"w":261,"h":144}, "spriteSourceSize": {"x":13,"y":0,"w":261,"h":144},
@ -216,6 +216,14 @@
"spriteSourceSize": {"x":0,"y":0,"w":288,"h":287}, "spriteSourceSize": {"x":0,"y":0,"w":288,"h":287},
"sourceSize": {"w":288,"h":288} "sourceSize": {"w":288,"h":288}
}, },
"sprites/blueprints/painter-mirrored.png":
{
"frame": {"x":1119,"y":150,"w":288,"h":144},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":288,"h":144},
"sourceSize": {"w":288,"h":144}
},
"sprites/blueprints/painter-quad.png": "sprites/blueprints/painter-quad.png":
{ {
"frame": {"x":555,"y":3,"w":560,"h":144}, "frame": {"x":555,"y":3,"w":560,"h":144},
@ -226,7 +234,7 @@
}, },
"sprites/blueprints/painter.png": "sprites/blueprints/painter.png":
{ {
"frame": {"x":1119,"y":150,"w":288,"h":144}, "frame": {"x":1671,"y":3,"w":288,"h":144},
"rotated": false, "rotated": false,
"trimmed": false, "trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":288,"h":144}, "spriteSourceSize": {"x":0,"y":0,"w":288,"h":144},
@ -234,7 +242,7 @@
}, },
"sprites/blueprints/rotater-ccw.png": "sprites/blueprints/rotater-ccw.png":
{ {
"frame": {"x":1397,"y":445,"w":143,"h":144}, "frame": {"x":1639,"y":299,"w":143,"h":144},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":1,"y":0,"w":143,"h":144}, "spriteSourceSize": {"x":1,"y":0,"w":143,"h":144},
@ -242,7 +250,7 @@
}, },
"sprites/blueprints/rotater.png": "sprites/blueprints/rotater.png":
{ {
"frame": {"x":1084,"y":594,"w":143,"h":144}, "frame": {"x":1786,"y":299,"w":143,"h":144},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":1,"y":0,"w":143,"h":144}, "spriteSourceSize": {"x":1,"y":0,"w":143,"h":144},
@ -250,7 +258,7 @@
}, },
"sprites/blueprints/splitter-compact-inverse.png": "sprites/blueprints/splitter-compact-inverse.png":
{ {
"frame": {"x":1071,"y":742,"w":142,"h":138}, "frame": {"x":1071,"y":886,"w":142,"h":138},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":0,"y":2,"w":142,"h":138}, "spriteSourceSize": {"x":0,"y":2,"w":142,"h":138},
@ -258,7 +266,7 @@
}, },
"sprites/blueprints/splitter-compact.png": "sprites/blueprints/splitter-compact.png":
{ {
"frame": {"x":1217,"y":742,"w":139,"h":138}, "frame": {"x":1488,"y":594,"w":139,"h":138},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":5,"y":2,"w":139,"h":138}, "spriteSourceSize": {"x":5,"y":2,"w":139,"h":138},
@ -266,7 +274,7 @@
}, },
"sprites/blueprints/splitter.png": "sprites/blueprints/splitter.png":
{ {
"frame": {"x":1119,"y":298,"w":256,"h":144}, "frame": {"x":811,"y":886,"w":256,"h":144},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":17,"y":0,"w":256,"h":144}, "spriteSourceSize": {"x":17,"y":0,"w":256,"h":144},
@ -274,7 +282,7 @@
}, },
"sprites/blueprints/stacker.png": "sprites/blueprints/stacker.png":
{ {
"frame": {"x":555,"y":590,"w":261,"h":144}, "frame": {"x":847,"y":591,"w":261,"h":144},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":13,"y":0,"w":261,"h":144}, "spriteSourceSize": {"x":13,"y":0,"w":261,"h":144},
@ -290,7 +298,7 @@
}, },
"sprites/blueprints/trash.png": "sprites/blueprints/trash.png":
{ {
"frame": {"x":1101,"y":446,"w":144,"h":144}, "frame": {"x":1241,"y":445,"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},
@ -298,7 +306,7 @@
}, },
"sprites/blueprints/underground_belt_entry-tier2.png": "sprites/blueprints/underground_belt_entry-tier2.png":
{ {
"frame": {"x":835,"y":885,"w":138,"h":125}, "frame": {"x":1774,"y":594,"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},
@ -306,7 +314,7 @@
}, },
"sprites/blueprints/underground_belt_entry.png": "sprites/blueprints/underground_belt_entry.png":
{ {
"frame": {"x":1261,"y":884,"w":138,"h":112}, "frame": {"x":1774,"y":723,"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},
@ -314,7 +322,7 @@
}, },
"sprites/blueprints/underground_belt_exit-tier2.png": "sprites/blueprints/underground_belt_exit-tier2.png":
{ {
"frame": {"x":1118,"y":884,"w":139,"h":112}, "frame": {"x":1488,"y":736,"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},
@ -322,7 +330,7 @@
}, },
"sprites/blueprints/underground_belt_exit.png": "sprites/blueprints/underground_belt_exit.png":
{ {
"frame": {"x":1397,"y":593,"w":138,"h":112}, "frame": {"x":1772,"y":839,"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},
@ -330,7 +338,7 @@
}, },
"sprites/buildings/belt_left.png": "sprites/buildings/belt_left.png":
{ {
"frame": {"x":1680,"y":593,"w":86,"h":86}, "frame": {"x":1217,"y":969,"w":86,"h":86},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":0,"y":9,"w":86,"h":86}, "spriteSourceSize": {"x":0,"y":9,"w":86,"h":86},
@ -338,7 +346,7 @@
}, },
"sprites/buildings/belt_right.png": "sprites/buildings/belt_right.png":
{ {
"frame": {"x":1706,"y":773,"w":86,"h":86}, "frame": {"x":1499,"y":852,"w":86,"h":86},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":9,"y":9,"w":86,"h":86}, "spriteSourceSize": {"x":9,"y":9,"w":86,"h":86},
@ -346,7 +354,7 @@
}, },
"sprites/buildings/belt_top.png": "sprites/buildings/belt_top.png":
{ {
"frame": {"x":1936,"y":151,"w":77,"h":95}, "frame": {"x":1963,"y":102,"w":77,"h":95},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":9,"y":0,"w":77,"h":95}, "spriteSourceSize": {"x":9,"y":0,"w":77,"h":95},
@ -362,7 +370,7 @@
}, },
"sprites/buildings/cutter.png": "sprites/buildings/cutter.png":
{ {
"frame": {"x":811,"y":738,"w":256,"h":143}, "frame": {"x":1119,"y":298,"w":256,"h":143},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":17,"y":0,"w":256,"h":143}, "spriteSourceSize": {"x":17,"y":0,"w":256,"h":143},
@ -378,7 +386,7 @@
}, },
"sprites/buildings/miner-chainable.png": "sprites/buildings/miner-chainable.png":
{ {
"frame": {"x":1684,"y":446,"w":136,"h":142}, "frame": {"x":1101,"y":445,"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},
@ -386,7 +394,7 @@
}, },
"sprites/buildings/miner.png": "sprites/buildings/miner.png":
{ {
"frame": {"x":1824,"y":446,"w":136,"h":142}, "frame": {"x":1112,"y":593,"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},
@ -394,7 +402,7 @@
}, },
"sprites/buildings/mixer.png": "sprites/buildings/mixer.png":
{ {
"frame": {"x":547,"y":738,"w":260,"h":143}, "frame": {"x":812,"y":739,"w":260,"h":143},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":14,"y":0,"w":260,"h":143}, "spriteSourceSize": {"x":14,"y":0,"w":260,"h":143},
@ -408,6 +416,14 @@
"spriteSourceSize": {"x":0,"y":0,"w":288,"h":286}, "spriteSourceSize": {"x":0,"y":0,"w":288,"h":286},
"sourceSize": {"w":288,"h":288} "sourceSize": {"w":288,"h":288}
}, },
"sprites/buildings/painter-mirrored.png":
{
"frame": {"x":1671,"y":151,"w":288,"h":144},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":288,"h":144},
"sourceSize": {"w":288,"h":144}
},
"sprites/buildings/painter-quad.png": "sprites/buildings/painter-quad.png":
{ {
"frame": {"x":555,"y":151,"w":560,"h":144}, "frame": {"x":555,"y":151,"w":560,"h":144},
@ -418,7 +434,7 @@
}, },
"sprites/buildings/painter.png": "sprites/buildings/painter.png":
{ {
"frame": {"x":1671,"y":3,"w":288,"h":144}, "frame": {"x":555,"y":590,"w":288,"h":144},
"rotated": false, "rotated": false,
"trimmed": false, "trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":288,"h":144}, "spriteSourceSize": {"x":0,"y":0,"w":288,"h":144},
@ -426,7 +442,7 @@
}, },
"sprites/buildings/rotater-ccw.png": "sprites/buildings/rotater-ccw.png":
{ {
"frame": {"x":1231,"y":594,"w":141,"h":143}, "frame": {"x":1537,"y":447,"w":141,"h":143},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":2,"y":0,"w":141,"h":143}, "spriteSourceSize": {"x":2,"y":0,"w":141,"h":143},
@ -434,7 +450,7 @@
}, },
"sprites/buildings/rotater.png": "sprites/buildings/rotater.png":
{ {
"frame": {"x":1639,"y":299,"w":141,"h":143}, "frame": {"x":1682,"y":447,"w":141,"h":143},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":2,"y":0,"w":141,"h":143}, "spriteSourceSize": {"x":2,"y":0,"w":141,"h":143},
@ -442,7 +458,7 @@
}, },
"sprites/buildings/splitter-compact-inverse.png": "sprites/buildings/splitter-compact-inverse.png":
{ {
"frame": {"x":547,"y":885,"w":141,"h":136}, "frame": {"x":1252,"y":593,"w":141,"h":136},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":0,"y":3,"w":141,"h":136}, "spriteSourceSize": {"x":0,"y":3,"w":141,"h":136},
@ -450,7 +466,7 @@
}, },
"sprites/buildings/splitter-compact.png": "sprites/buildings/splitter-compact.png":
{ {
"frame": {"x":692,"y":885,"w":139,"h":136}, "frame": {"x":1631,"y":594,"w":139,"h":136},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":5,"y":3,"w":139,"h":136}, "spriteSourceSize": {"x":5,"y":3,"w":139,"h":136},
@ -466,7 +482,7 @@
}, },
"sprites/buildings/stacker.png": "sprites/buildings/stacker.png":
{ {
"frame": {"x":820,"y":591,"w":260,"h":143}, "frame": {"x":547,"y":886,"w":260,"h":143},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":14,"y":0,"w":260,"h":143}, "spriteSourceSize": {"x":14,"y":0,"w":260,"h":143},
@ -482,7 +498,7 @@
}, },
"sprites/buildings/trash.png": "sprites/buildings/trash.png":
{ {
"frame": {"x":1249,"y":446,"w":144,"h":144}, "frame": {"x":1389,"y":445,"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},
@ -490,7 +506,7 @@
}, },
"sprites/buildings/underground_belt_entry-tier2.png": "sprites/buildings/underground_belt_entry-tier2.png":
{ {
"frame": {"x":977,"y":885,"w":137,"h":124}, "frame": {"x":1631,"y":734,"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},
@ -498,7 +514,7 @@
}, },
"sprites/buildings/underground_belt_entry.png": "sprites/buildings/underground_belt_entry.png":
{ {
"frame": {"x":1539,"y":593,"w":137,"h":111}, "frame": {"x":1216,"y":739,"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},
@ -506,7 +522,7 @@
}, },
"sprites/buildings/underground_belt_exit-tier2.png": "sprites/buildings/underground_belt_exit-tier2.png":
{ {
"frame": {"x":1376,"y":709,"w":137,"h":111}, "frame": {"x":1217,"y":854,"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},
@ -514,7 +530,7 @@
}, },
"sprites/buildings/underground_belt_exit.png": "sprites/buildings/underground_belt_exit.png":
{ {
"frame": {"x":1403,"y":824,"w":137,"h":111}, "frame": {"x":1358,"y":852,"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},
@ -522,7 +538,7 @@
}, },
"sprites/debug/acceptor_slot.png": "sprites/debug/acceptor_slot.png":
{ {
"frame": {"x":1963,"y":3,"w":38,"h":48}, "frame": {"x":2006,"y":597,"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},
@ -530,7 +546,7 @@
}, },
"sprites/debug/ejector_slot.png": "sprites/debug/ejector_slot.png":
{ {
"frame": {"x":1963,"y":55,"w":38,"h":48}, "frame": {"x":2006,"y":649,"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},
@ -538,7 +554,7 @@
}, },
"sprites/map_overview/belt_forward.png": "sprites/map_overview/belt_forward.png":
{ {
"frame": {"x":1625,"y":997,"w":20,"h":24}, "frame": {"x":1826,"y":955,"w":20,"h":24},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":2,"y":0,"w":20,"h":24}, "spriteSourceSize": {"x":2,"y":0,"w":20,"h":24},
@ -546,7 +562,7 @@
}, },
"sprites/map_overview/belt_left.png": "sprites/map_overview/belt_left.png":
{ {
"frame": {"x":3,"y":994,"w":22,"h":22}, "frame": {"x":206,"y":994,"w":22,"h":22},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":0,"y":2,"w":22,"h":22}, "spriteSourceSize": {"x":0,"y":2,"w":22,"h":22},
@ -554,7 +570,7 @@
}, },
"sprites/map_overview/belt_right.png": "sprites/map_overview/belt_right.png":
{ {
"frame": {"x":1963,"y":107,"w":22,"h":22}, "frame": {"x":2006,"y":701,"w":22,"h":22},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":2,"y":2,"w":22,"h":22}, "spriteSourceSize": {"x":2,"y":2,"w":22,"h":22},
@ -562,15 +578,31 @@
}, },
"sprites/misc/deletion_marker.png": "sprites/misc/deletion_marker.png":
{ {
"frame": {"x":1716,"y":953,"w":62,"h":62}, "frame": {"x":140,"y":994,"w":62,"h":62},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":5,"y":5,"w":62,"h":62}, "spriteSourceSize": {"x":5,"y":5,"w":62,"h":62},
"sourceSize": {"w":72,"h":72} "sourceSize": {"w":72,"h":72}
}, },
"sprites/misc/hub_direction_indicator.png":
{
"frame": {"x":1933,"y":299,"w":24,"h":24},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":24,"h":24},
"sourceSize": {"w":24,"h":24}
},
"sprites/misc/lock_direction_indicator.png":
{
"frame": {"x":1357,"y":733,"w":36,"h":24},
"rotated": false,
"trimmed": true,
"spriteSourceSize": {"x":0,"y":6,"w":36,"h":24},
"sourceSize": {"w":36,"h":36}
},
"sprites/misc/slot_bad_arrow.png": "sprites/misc/slot_bad_arrow.png":
{ {
"frame": {"x":1716,"y":953,"w":62,"h":62}, "frame": {"x":140,"y":994,"w":62,"h":62},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":5,"y":5,"w":62,"h":62}, "spriteSourceSize": {"x":5,"y":5,"w":62,"h":62},
@ -578,7 +610,7 @@
}, },
"sprites/misc/slot_good_arrow.png": "sprites/misc/slot_good_arrow.png":
{ {
"frame": {"x":1950,"y":592,"w":62,"h":72}, "frame": {"x":1760,"y":955,"w":62,"h":72},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":5,"y":0,"w":62,"h":72}, "spriteSourceSize": {"x":5,"y":0,"w":62,"h":72},
@ -586,7 +618,7 @@
}, },
"sprites/misc/storage_overlay.png": "sprites/misc/storage_overlay.png":
{ {
"frame": {"x":1403,"y":939,"w":133,"h":66}, "frame": {"x":3,"y":994,"w":133,"h":66},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":2,"y":2,"w":133,"h":66}, "spriteSourceSize": {"x":2,"y":2,"w":133,"h":66},
@ -594,7 +626,7 @@
}, },
"sprites/misc/waypoint.png": "sprites/misc/waypoint.png":
{ {
"frame": {"x":1649,"y":997,"w":20,"h":24}, "frame": {"x":1357,"y":761,"w":20,"h":24},
"rotated": false, "rotated": false,
"trimmed": true, "trimmed": true,
"spriteSourceSize": {"x":2,"y":0,"w":20,"h":24}, "spriteSourceSize": {"x":2,"y":0,"w":20,"h":24},
@ -605,8 +637,8 @@
"version": "1.0", "version": "1.0",
"image": "atlas0_75.png", "image": "atlas0_75.png",
"format": "RGBA8888", "format": "RGBA8888",
"size": {"w":2016,"h":1024}, "size": {"w":2047,"h":1063},
"scale": "0.75", "scale": "0.75",
"smartupdate": "$TexturePacker:SmartUpdate:3dd7a89f30024dd4787ad4af6b14588a:9ba11f8b02134c4376ab4e0a44f8b850:f159918d23e5952766c6d23ab52278c6$" "smartupdate": "$TexturePacker:SmartUpdate:8985524bba1a3f16cecab3c03b6aaa06:d614d20bfce033d8a8ab0990af085d16:f159918d23e5952766c6d23ab52278c6$"
} }
} }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 735 KiB

After

Width:  |  Height:  |  Size: 780 KiB

View File

@ -324,9 +324,11 @@
</struct> </struct>
<key type="filename">sprites/blueprints/cutter.png</key> <key type="filename">sprites/blueprints/cutter.png</key>
<key type="filename">sprites/blueprints/mixer.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/painter.png</key>
<key type="filename">sprites/blueprints/splitter.png</key> <key type="filename">sprites/blueprints/splitter.png</key>
<key type="filename">sprites/blueprints/stacker.png</key> <key type="filename">sprites/blueprints/stacker.png</key>
<key type="filename">sprites/buildings/painter-mirrored.png</key>
<struct type="IndividualSpriteSettings"> <struct type="IndividualSpriteSettings">
<key>pivotPoint</key> <key>pivotPoint</key>
<point_f>0.5,0.5</point_f> <point_f>0.5,0.5</point_f>
@ -445,6 +447,7 @@
<key type="filename">sprites/map_overview/belt_forward.png</key> <key type="filename">sprites/map_overview/belt_forward.png</key>
<key type="filename">sprites/map_overview/belt_left.png</key> <key type="filename">sprites/map_overview/belt_left.png</key>
<key type="filename">sprites/map_overview/belt_right.png</key> <key type="filename">sprites/map_overview/belt_right.png</key>
<key type="filename">sprites/misc/hub_direction_indicator.png</key>
<key type="filename">sprites/misc/waypoint.png</key> <key type="filename">sprites/misc/waypoint.png</key>
<struct type="IndividualSpriteSettings"> <struct type="IndividualSpriteSettings">
<key>pivotPoint</key> <key>pivotPoint</key>
@ -477,6 +480,21 @@
<key>scale9FromFile</key> <key>scale9FromFile</key>
<false/> <false/>
</struct> </struct>
<key type="filename">sprites/misc/lock_direction_indicator.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>12,12,24,24</rect>
<key>scale9Paddings</key>
<rect>12,12,24,24</rect>
<key>scale9FromFile</key>
<false/>
</struct>
<key type="filename">sprites/misc/storage_overlay.png</key> <key type="filename">sprites/misc/storage_overlay.png</key>
<struct type="IndividualSpriteSettings"> <struct type="IndividualSpriteSettings">
<key>pivotPoint</key> <key>pivotPoint</key>

View File

@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:f61e851402fbc92d6909912fb203c63258fedbdea83e81f7ececb5091f4bee03
size 3732550

View File

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:8c334a9f100fce4647b4803d2a8270b30e26d53622b3717bdb81b3ea07f84aed
size 150286082

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 495 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

@ -38,6 +38,10 @@ html {
right: 0; right: 0;
background: #dee1ea; background: #dee1ea;
@include DarkThemeOverride {
background: $darkModeGameBackground;
}
} }
body { body {
@ -413,6 +417,10 @@ canvas {
display: inline-block; display: inline-block;
vertical-align: middle; vertical-align: middle;
} }
@include DarkThemeOverride {
color: #fff;
}
} }
.prefab_LoadingTextWithAnimDelayed { .prefab_LoadingTextWithAnimDelayed {

View File

@ -15,6 +15,11 @@ $buildingsAndVariants: belt, splitter, splitter-compact, splitter-compact-invers
} }
} }
// Special case
[data-icon="building_tutorials/painter-mirrored.png"] {
background-image: uiResource("res/ui/building_tutorials/painter.png") !important;
}
$icons: notification_saved, notification_success, notification_upgrade; $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"] {
@ -22,8 +27,8 @@ $icons: notification_saved, notification_success, notification_upgrade;
} }
} }
$languages: en, de, cs, da, et, es-419, fr, it, pt-BR, sv, tr, el, ru, uk, zh-TW, nb, mt-MT, ar, nl, vi, th, $languages: en, de, cs, da, et, es-419, fr, it, pt-BR, sv, tr, el, ru, uk, zh-TW, zh-CN, nb, mt-MT, ar, nl, vi, th,
hu, pl, ja, kor; hu, pl, ja, kor, no, pt-PT;
@each $language in $languages { @each $language in $languages {
[data-languageicon="#{$language}"] { [data-languageicon="#{$language}"] {

View File

@ -75,6 +75,15 @@
@include StyleBelowWidth(700px) { @include StyleBelowWidth(700px) {
display: none !important; display: none !important;
} }
&.compact {
width: unset !important;
grid-template-columns: 1fr;
.buildingImage,
.description > .text {
display: none;
}
}
} }
#ingame_HUD_PlacerVariants { #ingame_HUD_PlacerVariants {
@ -86,6 +95,10 @@
flex-direction: column; flex-direction: column;
align-items: flex-end; align-items: flex-end;
&.compact {
@include S(top, 150px);
}
.explanation { .explanation {
text-transform: uppercase; text-transform: uppercase;
grid-row: 1 / 2; grid-row: 1 / 2;

View File

@ -21,15 +21,32 @@
} }
} }
$darkModeDialogBg: darken($darkModeGameBackground, 10);
@include DarkThemeOverride { @include DarkThemeOverride {
background: rgba(#33363d, 0.9); background: rgba($darkModeDialogBg, 0.9);
@include InlineAnimation(0.12s ease-in-out) { @include InlineAnimation(0.12s ease-in-out) {
0% { 0% {
background-color: transparent; background-color: transparent;
opacity: 0.5; opacity: 0.5;
} }
100% { 100% {
background-color: rgba(#33363d, 0.9); background-color: rgba($darkModeDialogBg, 0.9);
}
}
> .dialogInner.optionChooserDialog .optionParent {
.option {
background: #3d3f42;
&:hover {
background-color: #424348;
}
&.active {
background: $colorBlueBright;
color: #fff;
}
} }
} }
} }
@ -122,6 +139,10 @@
color: #aaa; color: #aaa;
} }
a {
color: $colorBlueBright;
}
strong { strong {
font-weight: bold; font-weight: bold;
} }

View File

@ -14,6 +14,10 @@
} }
> .binding { > .binding {
&:not(.visible) {
display: none !important;
}
display: inline-grid; display: inline-grid;
@include PlainText; @include PlainText;
align-items: center; align-items: center;
@ -57,42 +61,6 @@
@include S(margin-left, 5px); @include S(margin-left, 5px);
} }
} }
&:not(.placementActive) .binding.placementOnly,
&.mapOverviewActive .binding.placementOnly {
display: none;
}
&.placementActive:not(.mapOverviewActive) .noPlacementOnly {
display: none;
}
&:not(.mapOverviewActive) .binding.overviewOnly {
display: none;
}
&.mapOverviewActive .noOverviewOnly {
display: none;
}
.binding.placementOnly,
&:not(.placementActive) .binding.noPlacementOnly {
transform-origin: 0% 50%;
@include InlineAnimation(0.3s ease-in-out) {
0% {
color: $colorRedBright;
transform: scale(1.2);
}
}
}
.keybinding.builtinKey {
transition: all 0.1s ease-in-out;
transition-property: background-color, color, border-color;
background: $colorRedBright;
border-color: $colorRedBright;
color: #fff;
}
} }
body.uiHidden #ingame_HUD_KeybindingOverlay .binding:not(.hudToggle) { body.uiHidden #ingame_HUD_KeybindingOverlay .binding:not(.hudToggle) {

View File

@ -1,22 +0,0 @@
#ingame_HUD_MassSelector {
position: absolute;
@include S(top, 50px);
left: 50%;
transform: translateX(-50%);
background: $ingameHudBg;
@include S(padding, 6px, 10px);
@include SuperSmallText;
color: #fff;
// color: #f77;
.keybinding {
vertical-align: middle;
@include S(margin, 0, 1px);
position: relative;
top: unset;
left: unset;
right: unset;
bottom: unset;
@include S(margin-top, -2px);
}
}

View File

@ -241,6 +241,10 @@
&.complete { &.complete {
background-color: $colorGreenBright; background-color: $colorGreenBright;
@include DarkThemeOverride {
background-color: $colorGreenBright;
}
} }
} }
} }

View File

@ -29,7 +29,7 @@
#ingame_HUD_Waypoints { #ingame_HUD_Waypoints {
position: absolute; position: absolute;
@include S(right, 10px); @include S(right, 10px);
@include S(top, 60px); @include S(top, 45px);
display: flex; display: flex;
flex-direction: column; flex-direction: column;
@include DarkThemeInvert(); @include DarkThemeInvert();
@ -47,6 +47,7 @@
opacity: 0.7; opacity: 0.7;
@include S(margin-bottom, 1px); @include S(margin-bottom, 1px);
font-weight: bold; font-weight: bold;
&:hover { &:hover {
opacity: 1; opacity: 1;
} }
@ -63,5 +64,29 @@
transform: scale(1.5); transform: scale(1.5);
} }
} }
&.hub {
// Transform because there is a canvas before
@include S(margin-left, -2px);
grid-template-columns: auto 1fr;
background: none !important;
@include S(padding-left, 0);
canvas {
@include S(width, 12px);
@include S(height, 12px);
@include S(margin-right, 1px);
}
}
&.shapeIcon {
canvas {
@include S(width, 15px);
@include S(height, 15px);
pointer-events: none;
// Double invert, to make sure it has the right color
@include DarkThemeInvert();
}
}
} }
} }

View File

@ -37,7 +37,6 @@
@import "ingame_hud/shop"; @import "ingame_hud/shop";
@import "ingame_hud/game_menu"; @import "ingame_hud/game_menu";
@import "ingame_hud/dialogs"; @import "ingame_hud/dialogs";
@import "ingame_hud/mass_selector";
@import "ingame_hud/vignette_overlay"; @import "ingame_hud/vignette_overlay";
@import "ingame_hud/statistics"; @import "ingame_hud/statistics";
@import "ingame_hud/pinned_shapes"; @import "ingame_hud/pinned_shapes";
@ -67,7 +66,6 @@ ingame_HUD_PinnedShapes,
ingame_HUD_GameMenu, ingame_HUD_GameMenu,
ingame_HUD_KeybindingOverlay, ingame_HUD_KeybindingOverlay,
ingame_HUD_Notifications, ingame_HUD_Notifications,
ingame_HUD_MassSelector,
ingame_HUD_DebugInfo, ingame_HUD_DebugInfo,
ingame_HUD_EntityDebugger, ingame_HUD_EntityDebugger,
ingame_HUD_InteractiveTutorial, ingame_HUD_InteractiveTutorial,
@ -101,7 +99,6 @@ body.uiHidden {
#ingame_HUD_buildings_toolbar, #ingame_HUD_buildings_toolbar,
#ingame_HUD_PlacementHints, #ingame_HUD_PlacementHints,
#ingame_HUD_GameMenu, #ingame_HUD_GameMenu,
#ingame_HUD_MassSelector,
#ingame_HUD_PinnedShapes, #ingame_HUD_PinnedShapes,
#ingame_HUD_Notifications, #ingame_HUD_Notifications,
#ingame_HUD_TutorialHints, #ingame_HUD_TutorialHints,
@ -115,6 +112,6 @@ body.modalDialogActive,
body.externalAdOpen, body.externalAdOpen,
body.ingameDialogOpen { body.ingameDialogOpen {
> *:not(.ingameDialog):not(.modalDialogParent):not(.loadingDialog):not(.gameLoadingOverlay):not(#ingame_HUD_ModalDialogs):not(.noBlur) { > *:not(.ingameDialog):not(.modalDialogParent):not(.loadingDialog):not(.gameLoadingOverlay):not(#ingame_HUD_ModalDialogs):not(.noBlur) {
filter: blur(5px) !important; // filter: blur(5px) !important;
} }
} }

View File

@ -350,7 +350,7 @@ button,
} }
@mixin DarkThemeOverride { @mixin DarkThemeOverride {
@at-root body[data-theme="dark"] &, @at-root html[data-theme="dark"] &,
&[data-theme="dark"] { &[data-theme="dark"] {
@content; @content;
} }

View File

@ -28,4 +28,10 @@
right: 0; right: 0;
bottom: 0; bottom: 0;
} }
@include DarkThemeOverride {
.gameLoadingOverlay {
background: $darkModeGameBackground;
}
}
} }

View File

@ -51,4 +51,21 @@
} }
} }
} }
@include DarkThemeOverride {
.content {
.hint {
background: #3b3d40;
}
.category .entry {
color: #c0c4c8;
border-bottom-color: #888;
button {
filter: invert(1);
}
}
}
}
} }

View File

@ -37,6 +37,7 @@
.languageChoose { .languageChoose {
@include S(border-radius, 8px); @include S(border-radius, 8px);
border: solid #222428; border: solid #222428;
background-color: #fff;
@include S(border-width, 2px); @include S(border-width, 2px);
background-size: cover; background-size: cover;
} }
@ -233,7 +234,8 @@
@include S(width, 300px); @include S(width, 300px);
} }
.playButton { .playButton,
.continueButton {
@include SuperHeading; @include SuperHeading;
@include S(min-width, 130px); @include S(min-width, 130px);
@include S(padding, 15px, 20px); @include S(padding, 15px, 20px);
@ -246,12 +248,21 @@
&:hover { &:hover {
transform: scale(1.02); transform: scale(1.02);
} }
&.continueButton {
@include Heading;
}
} }
.importButton { .importButton {
@include S(margin-top, 15px); @include S(margin-top, 15px);
} }
.newGameButton {
@include S(margin-top, 15px);
@include S(margin-left, 15px);
}
.savegames { .savegames {
@include S(max-height, 105px); @include S(max-height, 105px);
overflow-y: auto; overflow-y: auto;
@ -390,4 +401,44 @@
} }
} }
} }
@include DarkThemeOverride {
background: $darkModeGameBackground center center / cover !important;
.topButtons {
filter: invert(1);
.languageChoose {
filter: invert(1);
}
}
.mainContainer {
background: darken($darkModeGameBackground, 10);
.savegames .savegame {
background: darken($darkModeGameBackground, 15);
color: white;
}
}
.footer {
> a {
background: darken($darkModeGameBackground, 10);
color: #eee;
}
.author {
color: #bdbdbd;
> a {
color: white;
}
}
.thirdpartyLogo.githubLogo {
filter: invert(1);
}
}
}
} }

View File

@ -15,6 +15,10 @@
box-sizing: border-box; box-sizing: border-box;
background: #eef1f4; background: #eef1f4;
@include DarkThemeOverride {
background: #424242;
}
.version { .version {
@include Heading; @include Heading;
} }

View File

@ -88,4 +88,26 @@
} }
} }
} }
@include DarkThemeOverride {
.content {
.setting {
background: darken($darkModeGameBackground, 10);
.value.enum {
// dirty but works
filter: invert(0.85);
color: #222;
}
.value.checkbox {
background-color: #74767b;
&.checked {
background-color: $colorBlueBright;
}
}
}
}
}
} }

View File

@ -61,4 +61,21 @@
} }
} }
} }
@include DarkThemeOverride {
.headerBar {
h1 {
color: #e2e0db;
}
.backButton {
filter: invert(1);
}
}
> .container > .content {
background: darken($darkModeGameBackground, 3);
color: #eee;
}
}
} }

View File

@ -38,6 +38,8 @@ $ingameHudBg: rgba(#333438, 0.9);
$text3dColor: #f4ffff; $text3dColor: #f4ffff;
$darkModeGameBackground: #5c606c;
// Dialog properties // Dialog properties
$modalDialogBg: rgba(160, 165, 180, 0.8); $modalDialogBg: rgba(160, 165, 180, 0.8);
$dialogBgColor: lighten($mainBgColor, 10); $dialogBgColor: lighten($mainBgColor, 10);

View File

@ -1,4 +1,83 @@
export const CHANGELOG = [ export const CHANGELOG = [
{
version: "1.1.17",
date: "unreleased",
entries: [
"Allow configuring autosave interval and disabling it in the settings",
"The smart-tunnel placement has been reworked to properly replace belts. Thus the setting has been turned on again by default",
"The soundtrack now has a higher quality on the standalone version than the web version",
"Add setting to disable cut/delete warnings (by hexy)",
"Fix bug where belts in blueprints don't orient correctly (by hexy)",
"Fix camera moving weird after dragging and holding (by hexy)",
"Fix keybinding for pipette showing while pasting blueprints",
"Update tutorial image for tier 2 tunnels to explain mix/match (by jimmyshadow1)",
"Prevent default actions on all keybindings in the web version so you don't accidentally use builtin browser shortcuts",
],
},
{
version: "1.1.16",
date: "21.06.2020",
entries: [
"You can now pickup buildings below your cursor with 'Q'!",
"The game soundtrack has been extended! There are now 4 songs with over 13 minutes of playtime from <a href='https://soundcloud.com/pettersumelius' target='blank'>Peppsen</a>!",
"Refactor keybindings overlay to show more appropriate keybindings",
"Show keybindings for area-select in the upper left instead",
"Automatically deselect area when selecting a new building",
"Raise markers limit from 14 characters to 71 (by Joker-vD)",
"Optimize performance by caching extractor items (by Phlosioneer)",
"Added setting to enable compact building infos, which only show ratios and hide the image / description",
"Apply dark theme to menu as well (by dengr1065)",
"Fix belt planner not placing the last belt",
"Fix buildings getting deleted when right clicking while placing a blueprint",
"Fix for exporting screenshots for huge bases (It was showing an empty file) (by xSparfuchs)",
"Fix buttons not responding when using right click directly after left click (by davidburhans)",
"Fix hub marker being hidden by building info panel",
"Disable dialog background blur since it can cause performance issues",
"Added simplified chinese translations",
"Update translations (Thanks to all translators!)",
],
},
{
version: "1.1.15",
date: "17.06.2020",
entries: [
"You can now place straight belts (and tunnels) by holding SHIFT! (For you, @giantwaffle ❤️)",
"Added continue button to main menu and add seperate 'New game' button (by jaysc)",
"Added setting to disable smart tunnel placement introduced with the last update",
"Added setting to disable vignette",
"Update translations",
],
},
{
version: "1.1.14",
date: "16.06.2020",
entries: [
"There is now an indicator (compass) to the HUB for the HUB Marker!",
"You can now include shape short keys in markers to render shape icons instead of text!",
"Added mirrored variant of the painter",
"When placing tunnels, unnecessary belts inbetween are now removed!",
"You can now drag tunnels and they will automatically expand! (Just try it out, its intuitive)",
],
},
{
version: "1.1.13",
date: "15.06.2020",
entries: [
"Added shift modifier for faster pan (by jaysc)",
"Added Japanese translations",
"Added Portuguese (Portugal) translations",
"Updated icon for Spanish (Latin America) - It was showing a Spanish flag before",
"Updated existing translations",
],
},
{
version: "1.1.12",
date: "14.06.2020",
entries: [
"Huge performance improvements! The game should now run up to 60% faster!",
"Added norwegian translation",
],
},
{ {
version: "1.1.11", version: "1.1.11",
date: "13.06.2020", date: "13.06.2020",

View File

@ -3,7 +3,7 @@ import { createLogger } from "../core/logging";
import { Signal } from "../core/signal"; import { Signal } from "../core/signal";
import { fastArrayDelete, fastArrayDeleteValueIfContained } from "./utils"; import { fastArrayDelete, fastArrayDeleteValueIfContained } from "./utils";
import { Vector } from "./vector"; import { Vector } from "./vector";
import { IS_MOBILE } from "./config"; import { IS_MOBILE, SUPPORT_TOUCH } from "./config";
import { SOUNDS } from "../platform/sound"; import { SOUNDS } from "../platform/sound";
import { GLOBAL_APP } from "./globals"; import { GLOBAL_APP } from "./globals";
@ -119,16 +119,21 @@ export class ClickDetector {
} }
} }
const options = this.internalGetEventListenerOptions(); const options = this.internalGetEventListenerOptions();
if (SUPPORT_TOUCH) {
this.element.removeEventListener("touchstart", this.handlerTouchStart, options); this.element.removeEventListener("touchstart", this.handlerTouchStart, options);
this.element.removeEventListener("touchend", this.handlerTouchEnd, options); this.element.removeEventListener("touchend", this.handlerTouchEnd, options);
this.element.removeEventListener("touchcancel", this.handlerTouchCancel, options); this.element.removeEventListener("touchcancel", this.handlerTouchCancel, options);
}
this.element.removeEventListener("mouseup", this.handlerTouchStart, options); this.element.removeEventListener("mouseup", this.handlerTouchStart, options);
this.element.removeEventListener("mousedown", this.handlerTouchEnd, options); this.element.removeEventListener("mousedown", this.handlerTouchEnd, options);
this.element.removeEventListener("mouseout", this.handlerTouchCancel, options); this.element.removeEventListener("mouseout", this.handlerTouchCancel, options);
if (this.captureTouchmove) { if (this.captureTouchmove) {
if (SUPPORT_TOUCH) {
this.element.removeEventListener("touchmove", this.handlerTouchMove, options); this.element.removeEventListener("touchmove", this.handlerTouchMove, options);
}
this.element.removeEventListener("mousemove", this.handlerTouchMove, options); this.element.removeEventListener("mousemove", this.handlerTouchMove, options);
} }
@ -186,16 +191,20 @@ export class ClickDetector {
element.addEventListener("click", this.handlerPreventClick, options); element.addEventListener("click", this.handlerPreventClick, options);
} }
if (SUPPORT_TOUCH) {
element.addEventListener("touchstart", this.handlerTouchStart, options); element.addEventListener("touchstart", this.handlerTouchStart, options);
element.addEventListener("touchend", this.handlerTouchEnd, options); element.addEventListener("touchend", this.handlerTouchEnd, options);
element.addEventListener("touchcancel", this.handlerTouchCancel, options); element.addEventListener("touchcancel", this.handlerTouchCancel, options);
}
element.addEventListener("mousedown", this.handlerTouchStart, options); element.addEventListener("mousedown", this.handlerTouchStart, options);
element.addEventListener("mouseup", this.handlerTouchEnd, options); element.addEventListener("mouseup", this.handlerTouchEnd, options);
element.addEventListener("mouseout", this.handlerTouchCancel, options); element.addEventListener("mouseout", this.handlerTouchCancel, options);
if (this.captureTouchmove) { if (this.captureTouchmove) {
if (SUPPORT_TOUCH) {
element.addEventListener("touchmove", this.handlerTouchMove, options); element.addEventListener("touchmove", this.handlerTouchMove, options);
}
element.addEventListener("mousemove", this.handlerTouchMove, options); element.addEventListener("mousemove", this.handlerTouchMove, options);
} }
@ -316,6 +325,7 @@ export class ClickDetector {
// Ignore right clicks // Ignore right clicks
this.rightClick.dispatch(position, event); this.rightClick.dispatch(position, event);
this.cancelled = true; this.cancelled = true;
this.clickDownPosition = null;
return; return;
} }
} }

View File

@ -12,6 +12,8 @@ export const IS_DEMO = queryParamOptions.fullVersion
: (G_IS_PROD && !G_IS_STANDALONE) || : (G_IS_PROD && !G_IS_STANDALONE) ||
(typeof window !== "undefined" && window.location.search.indexOf("demo") >= 0); (typeof window !== "undefined" && window.location.search.indexOf("demo") >= 0);
export const SUPPORT_TOUCH = false;
const smoothCanvas = true; const smoothCanvas = true;
export const THIRDPARTY_URLS = { export const THIRDPARTY_URLS = {

View File

@ -191,17 +191,7 @@ export class InputDistributor {
*/ */
handleKeyMouseDown(event) { handleKeyMouseDown(event) {
const keyCode = event instanceof MouseEvent ? event.button + 1 : event.keyCode; const keyCode = event instanceof MouseEvent ? event.button + 1 : event.keyCode;
if (
keyCode === 4 || // MB4
keyCode === 5 || // MB5
keyCode === 9 || // TAB
keyCode === 16 || // SHIFT
keyCode === 17 || // CTRL
keyCode === 18 || // ALT
(keyCode >= 112 && keyCode < 122) // F1 - F10
) {
event.preventDefault(); event.preventDefault();
}
const isInitial = !this.keysDown.has(keyCode); const isInitial = !this.keysDown.has(keyCode);
this.keysDown.add(keyCode); this.keysDown.add(keyCode);

View File

@ -646,13 +646,12 @@ export function measure(name, target) {
} }
/** /**
* Helper method to create a new div * Helper method to create a new div element
* @param {Element} parent
* @param {string=} id * @param {string=} id
* @param {Array<string>=} classes * @param {Array<string>=} classes
* @param {string=} innerHTML * @param {string=} innerHTML
*/ */
export function makeDiv(parent, id = null, classes = [], innerHTML = "") { export function makeDivElement(id = null, classes = [], innerHTML = "") {
const div = document.createElement("div"); const div = document.createElement("div");
if (id) { if (id) {
div.id = id; div.id = id;
@ -661,10 +660,51 @@ export function makeDiv(parent, id = null, classes = [], innerHTML = "") {
div.classList.add(classes[i]); div.classList.add(classes[i]);
} }
div.innerHTML = innerHTML; div.innerHTML = innerHTML;
return div;
}
/**
* Helper method to create a new div
* @param {Element} parent
* @param {string=} id
* @param {Array<string>=} classes
* @param {string=} innerHTML
*/
export function makeDiv(parent, id = null, classes = [], innerHTML = "") {
const div = makeDivElement(id, classes, innerHTML);
parent.appendChild(div); parent.appendChild(div);
return div; return div;
} }
/**
* Helper method to create a new div and place before reference Node
* @param {Element} parent
* @param {Element} referenceNode
* @param {string=} id
* @param {Array<string>=} classes
* @param {string=} innerHTML
*/
export function makeDivBefore(parent, referenceNode, id = null, classes = [], innerHTML = "") {
const div = makeDivElement(id, classes, innerHTML);
parent.insertBefore(div, referenceNode);
return div;
}
/**
* Helper method to create a new button element
* @param {Array<string>=} classes
* @param {string=} innerHTML
*/
export function makeButtonElement(classes = [], innerHTML = "") {
const element = document.createElement("button");
for (let i = 0; i < classes.length; ++i) {
element.classList.add(classes[i]);
}
element.classList.add("styledButton");
element.innerHTML = innerHTML;
return element;
}
/** /**
* Helper method to create a new button * Helper method to create a new button
* @param {Element} parent * @param {Element} parent
@ -672,16 +712,24 @@ export function makeDiv(parent, id = null, classes = [], innerHTML = "") {
* @param {string=} innerHTML * @param {string=} innerHTML
*/ */
export function makeButton(parent, classes = [], innerHTML = "") { export function makeButton(parent, classes = [], innerHTML = "") {
const element = document.createElement("button"); const element = makeButtonElement(classes, innerHTML);
for (let i = 0; i < classes.length; ++i) {
element.classList.add(classes[i]);
}
element.classList.add("styledButton");
element.innerHTML = innerHTML;
parent.appendChild(element); parent.appendChild(element);
return element; return element;
} }
/**
* Helper method to create a new button and place before reference Node
* @param {Element} parent
* @param {Element} referenceNode
* @param {Array<string>=} classes
* @param {string=} innerHTML
*/
export function makeButtonBefore(parent, referenceNode, classes = [], innerHTML = "") {
const element = makeButtonElement(classes, innerHTML);
parent.insertBefore(element, referenceNode);
return element;
}
/** /**
* Removes all children of the given element * Removes all children of the given element
* @param {Element} elem * @param {Element} elem

View File

@ -47,10 +47,16 @@ export class AutomaticSave {
return; return;
} }
const saveInterval = this.root.app.settings.getAutosaveIntervalSeconds();
if (!saveInterval) {
// Disabled
return;
}
// Check when the last save was, but make sure that if it fails, we don't spam // Check when the last save was, but make sure that if it fails, we don't spam
const lastSaveTime = Math_max(this.lastSaveAttempt, this.root.savegame.getRealLastUpdate()); const lastSaveTime = Math_max(this.lastSaveAttempt, this.root.savegame.getRealLastUpdate());
let secondsSinceLastSave = (Date.now() - lastSaveTime) / 1000.0; const secondsSinceLastSave = (Date.now() - lastSaveTime) / 1000.0;
let shouldSave = false; let shouldSave = false;
switch (this.saveImportance) { switch (this.saveImportance) {
@ -61,7 +67,7 @@ export class AutomaticSave {
case enumSavePriority.regular: case enumSavePriority.regular:
// Could determine if there is a good / bad point here // Could determine if there is a good / bad point here
shouldSave = secondsSinceLastSave > MIN_INTERVAL_SECS; shouldSave = secondsSinceLastSave > saveInterval;
break; break;
default: default:

View File

@ -22,6 +22,10 @@ export class MetaBeltBaseBuilding extends MetaBuilding {
return "#777"; return "#777";
} }
getHasDirectionLockAvailable() {
return true;
}
/** /**
* @param {GameRoot} root * @param {GameRoot} root
* @param {string} variant * @param {string} variant

View File

@ -11,7 +11,7 @@ import { T } from "../../translations";
import { formatItemsPerSecond } from "../../core/utils"; import { formatItemsPerSecond } from "../../core/utils";
/** @enum {string} */ /** @enum {string} */
export const enumPainterVariants = { double: "double", quad: "quad" }; export const enumPainterVariants = { mirrored: "mirrored", double: "double", quad: "quad" };
export class MetaPainterBuilding extends MetaBuilding { export class MetaPainterBuilding extends MetaBuilding {
constructor() { constructor() {
@ -21,6 +21,7 @@ export class MetaPainterBuilding extends MetaBuilding {
getDimensions(variant) { getDimensions(variant) {
switch (variant) { switch (variant) {
case defaultBuildingVariant: case defaultBuildingVariant:
case enumPainterVariants.mirrored:
return new Vector(2, 1); return new Vector(2, 1);
case enumPainterVariants.double: case enumPainterVariants.double:
return new Vector(2, 2); return new Vector(2, 2);
@ -42,7 +43,8 @@ export class MetaPainterBuilding extends MetaBuilding {
*/ */
getAdditionalStatistics(root, variant) { getAdditionalStatistics(root, variant) {
switch (variant) { switch (variant) {
case defaultBuildingVariant: { case defaultBuildingVariant:
case enumPainterVariants.mirrored: {
const speed = root.hubGoals.getProcessorBaseSpeed(enumItemProcessorTypes.painter); const speed = root.hubGoals.getProcessorBaseSpeed(enumItemProcessorTypes.painter);
return [[T.ingame.buildingPlacement.infoTexts.speed, formatItemsPerSecond(speed)]]; return [[T.ingame.buildingPlacement.infoTexts.speed, formatItemsPerSecond(speed)]];
} }
@ -61,7 +63,7 @@ export class MetaPainterBuilding extends MetaBuilding {
* @param {GameRoot} root * @param {GameRoot} root
*/ */
getAvailableVariants(root) { getAvailableVariants(root) {
let variants = [defaultBuildingVariant]; let variants = [defaultBuildingVariant, enumPainterVariants.mirrored];
if (root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_painter_double)) { if (root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_painter_double)) {
variants.push(enumPainterVariants.double); variants.push(enumPainterVariants.double);
} }
@ -116,7 +118,8 @@ export class MetaPainterBuilding extends MetaBuilding {
*/ */
updateVariants(entity, rotationVariant, variant) { updateVariants(entity, rotationVariant, variant) {
switch (variant) { switch (variant) {
case defaultBuildingVariant: { case defaultBuildingVariant:
case enumPainterVariants.mirrored: {
entity.components.ItemAcceptor.setSlots([ entity.components.ItemAcceptor.setSlots([
{ {
pos: new Vector(0, 0), pos: new Vector(0, 0),
@ -125,7 +128,9 @@ export class MetaPainterBuilding extends MetaBuilding {
}, },
{ {
pos: new Vector(1, 0), pos: new Vector(1, 0),
directions: [enumDirection.top], directions: [
variant === defaultBuildingVariant ? enumDirection.top : enumDirection.bottom,
],
filter: enumItemAcceptorItemFilter.color, filter: enumItemAcceptorItemFilter.color,
}, },
]); ]);

View File

@ -8,7 +8,7 @@ import {
performanceNow, performanceNow,
} from "../core/builtins"; } from "../core/builtins";
import { clickDetectorGlobals } from "../core/click_detector"; import { clickDetectorGlobals } from "../core/click_detector";
import { globalConfig } from "../core/config"; import { globalConfig, SUPPORT_TOUCH } from "../core/config";
import { createLogger } from "../core/logging"; import { createLogger } from "../core/logging";
import { Rectangle } from "../core/rectangle"; import { Rectangle } from "../core/rectangle";
import { Signal, STOP_PROPAGATION } from "../core/signal"; import { Signal, STOP_PROPAGATION } from "../core/signal";
@ -28,6 +28,7 @@ const velocitySmoothing = 0.5;
const velocityFade = 0.98; const velocityFade = 0.98;
const velocityStrength = 0.4; const velocityStrength = 0.4;
const velocityMax = 20; const velocityMax = 20;
const ticksBeforeErasingVelocity = 10;
/** /**
* @enum {string} * @enum {string}
@ -58,6 +59,8 @@ export class Camera extends BasicSerializableObject {
// Input handling // Input handling
this.currentlyMoving = false; this.currentlyMoving = false;
this.lastMovingPosition = null; this.lastMovingPosition = null;
this.lastMovingPositionLastTick = null;
this.numTicksStandingStill = null;
this.cameraUpdateTimeBucket = 0.0; this.cameraUpdateTimeBucket = 0.0;
this.didMoveSinceTouchStart = false; this.didMoveSinceTouchStart = false;
this.currentlyPinching = false; this.currentlyPinching = false;
@ -312,32 +315,36 @@ export class Camera extends BasicSerializableObject {
this.eventListenerMouseMove = this.onMouseMove.bind(this); this.eventListenerMouseMove = this.onMouseMove.bind(this);
this.eventListenerMouseUp = this.onMouseUp.bind(this); this.eventListenerMouseUp = this.onMouseUp.bind(this);
if (SUPPORT_TOUCH) {
this.root.canvas.addEventListener("touchstart", this.eventListenerTouchStart); this.root.canvas.addEventListener("touchstart", this.eventListenerTouchStart);
this.root.canvas.addEventListener("touchend", this.eventListenerTouchEnd); this.root.canvas.addEventListener("touchend", this.eventListenerTouchEnd);
this.root.canvas.addEventListener("touchcancel", this.eventListenerTouchEnd); this.root.canvas.addEventListener("touchcancel", this.eventListenerTouchEnd);
this.root.canvas.addEventListener("touchmove", this.eventListenerTouchMove); this.root.canvas.addEventListener("touchmove", this.eventListenerTouchMove);
}
this.root.canvas.addEventListener("wheel", this.eventListenerMousewheel); this.root.canvas.addEventListener("wheel", this.eventListenerMousewheel);
this.root.canvas.addEventListener("mousedown", this.eventListenerMouseDown); this.root.canvas.addEventListener("mousedown", this.eventListenerMouseDown);
this.root.canvas.addEventListener("mousemove", this.eventListenerMouseMove); this.root.canvas.addEventListener("mousemove", this.eventListenerMouseMove);
this.root.canvas.addEventListener("mouseup", this.eventListenerMouseUp); window.addEventListener("mouseup", this.eventListenerMouseUp);
this.root.canvas.addEventListener("mouseout", this.eventListenerMouseUp); // this.root.canvas.addEventListener("mouseout", this.eventListenerMouseUp);
} }
/** /**
* Cleans up all event listeners * Cleans up all event listeners
*/ */
cleanup() { cleanup() {
if (SUPPORT_TOUCH) {
this.root.canvas.removeEventListener("touchstart", this.eventListenerTouchStart); this.root.canvas.removeEventListener("touchstart", this.eventListenerTouchStart);
this.root.canvas.removeEventListener("touchend", this.eventListenerTouchEnd); this.root.canvas.removeEventListener("touchend", this.eventListenerTouchEnd);
this.root.canvas.removeEventListener("touchcancel", this.eventListenerTouchEnd); this.root.canvas.removeEventListener("touchcancel", this.eventListenerTouchEnd);
this.root.canvas.removeEventListener("touchmove", this.eventListenerTouchMove); this.root.canvas.removeEventListener("touchmove", this.eventListenerTouchMove);
}
this.root.canvas.removeEventListener("wheel", this.eventListenerMousewheel); this.root.canvas.removeEventListener("wheel", this.eventListenerMousewheel);
this.root.canvas.removeEventListener("mousedown", this.eventListenerMouseDown); this.root.canvas.removeEventListener("mousedown", this.eventListenerMouseDown);
this.root.canvas.removeEventListener("mousemove", this.eventListenerMouseMove); this.root.canvas.removeEventListener("mousemove", this.eventListenerMouseMove);
this.root.canvas.removeEventListener("mouseup", this.eventListenerMouseUp); window.removeEventListener("mouseup", this.eventListenerMouseUp);
this.root.canvas.removeEventListener("mouseout", this.eventListenerMouseUp); // this.root.canvas.removeEventListener("mouseout", this.eventListenerMouseUp);
} }
/** /**
@ -663,6 +670,8 @@ export class Camera extends BasicSerializableObject {
this.touchPostMoveVelocity = new Vector(0, 0); this.touchPostMoveVelocity = new Vector(0, 0);
this.currentlyMoving = true; this.currentlyMoving = true;
this.lastMovingPosition = pos; this.lastMovingPosition = pos;
this.lastMovingPositionLastTick = null;
this.numTicksStandingStill = 0;
this.didMoveSinceTouchStart = false; this.didMoveSinceTouchStart = false;
} }
@ -712,6 +721,8 @@ export class Camera extends BasicSerializableObject {
this.currentlyMoving = false; this.currentlyMoving = false;
this.currentlyPinching = false; this.currentlyPinching = false;
this.lastMovingPosition = null; this.lastMovingPosition = null;
this.lastMovingPositionLastTick = null;
this.numTicksStandingStill = 0;
this.lastPinchPositions = null; this.lastPinchPositions = null;
this.userInteraction.dispatch(USER_INTERACT_TOUCHEND); this.userInteraction.dispatch(USER_INTERACT_TOUCHEND);
this.didMoveSinceTouchStart = false; this.didMoveSinceTouchStart = false;
@ -809,6 +820,23 @@ export class Camera extends BasicSerializableObject {
this.touchPostMoveVelocity = this.touchPostMoveVelocity.multiplyScalar(velocityFade); this.touchPostMoveVelocity = this.touchPostMoveVelocity.multiplyScalar(velocityFade);
// Check if the camera is being dragged but standing still: if not, zero out `touchPostMoveVelocity`.
if (this.currentlyMoving && this.desiredCenter === null) {
if (
this.lastMovingPositionLastTick !== null &&
this.lastMovingPositionLastTick.equalsEpsilon(this.lastMovingPosition)
) {
this.numTicksStandingStill++;
} else {
this.numTicksStandingStill = 0;
}
this.lastMovingPositionLastTick = this.lastMovingPosition.copy();
if (this.numTicksStandingStill >= ticksBeforeErasingVelocity) {
this.touchPostMoveVelocity.x = 0;
this.touchPostMoveVelocity.y = 0;
}
}
// Check influence of past points // Check influence of past points
if (!this.currentlyMoving && !this.currentlyPinching) { if (!this.currentlyMoving && !this.currentlyPinching) {
const len = this.touchPostMoveVelocity.length(); const len = this.touchPostMoveVelocity.length();
@ -885,24 +913,28 @@ export class Camera extends BasicSerializableObject {
let forceY = 0; let forceY = 0;
const actionMapper = this.root.keyMapper; const actionMapper = this.root.keyMapper;
if (actionMapper.getBinding(KEYMAPPINGS.navigation.mapMoveUp).isCurrentlyPressed()) { if (actionMapper.getBinding(KEYMAPPINGS.navigation.mapMoveUp).pressed) {
forceY -= 1; forceY -= 1;
} }
if (actionMapper.getBinding(KEYMAPPINGS.navigation.mapMoveDown).isCurrentlyPressed()) { if (actionMapper.getBinding(KEYMAPPINGS.navigation.mapMoveDown).pressed) {
forceY += 1; forceY += 1;
} }
if (actionMapper.getBinding(KEYMAPPINGS.navigation.mapMoveLeft).isCurrentlyPressed()) { if (actionMapper.getBinding(KEYMAPPINGS.navigation.mapMoveLeft).pressed) {
forceX -= 1; forceX -= 1;
} }
if (actionMapper.getBinding(KEYMAPPINGS.navigation.mapMoveRight).isCurrentlyPressed()) { if (actionMapper.getBinding(KEYMAPPINGS.navigation.mapMoveRight).pressed) {
forceX += 1; forceX += 1;
} }
this.center.x += moveAmount * forceX * this.root.app.settings.getMovementSpeed(); let movementSpeed =
this.center.y += moveAmount * forceY * this.root.app.settings.getMovementSpeed(); this.root.app.settings.getMovementSpeed() *
(actionMapper.getBinding(KEYMAPPINGS.navigation.mapMoveFaster).pressed ? 4 : 1);
this.center.x += moveAmount * forceX * movementSpeed;
this.center.y += moveAmount * forceY * movementSpeed;
} }
} }
} }

View File

@ -1,70 +0,0 @@
import { STOP_PROPAGATION } from "../core/signal";
import { GameRoot } from "./root";
import { ClickDetector } from "../core/click_detector";
import { createLogger } from "../core/logging";
const logger = createLogger("canvas_click_interceptor");
export class CanvasClickInterceptor {
/**
* @param {GameRoot} root
*/
constructor(root) {
this.root = root;
this.root.signals.postLoadHook.add(this.initialize, this);
this.root.signals.aboutToDestruct.add(this.cleanup, this);
/** @type {Array<object>} */
this.interceptors = [];
}
initialize() {
this.clickDetector = new ClickDetector(this.root.canvas, {
applyCssClass: null,
captureTouchmove: false,
targetOnly: true,
preventDefault: true,
maxDistance: 13,
clickSound: null,
});
this.clickDetector.click.add(this.onCanvasClick, this);
this.clickDetector.rightClick.add(this.onCanvasRightClick, this);
if (this.root.hud.parts.buildingPlacer) {
this.interceptors.push(this.root.hud.parts.buildingPlacer);
}
logger.log("Registered", this.interceptors.length, "interceptors");
}
cleanup() {
if (this.clickDetector) {
this.clickDetector.cleanup();
}
this.interceptors = [];
}
onCanvasClick(position, event, cancelAction = false) {
if (!this.root.gameInitialized) {
logger.warn("Skipping click outside of game initiaization!");
return;
}
if (this.root.hud.hasBlockingOverlayOpen()) {
return;
}
for (let i = 0; i < this.interceptors.length; ++i) {
const interceptor = this.interceptors[i];
if (interceptor.onCanvasClick(position, cancelAction) === STOP_PROPAGATION) {
// log(this, "Interceptor", interceptor.constructor.name, "catched click");
break;
}
}
}
onCanvasRightClick(position, event) {
this.onCanvasClick(position, event, true);
}
}

View File

@ -64,7 +64,7 @@ export class BeltComponent extends Component {
/** /**
* Returns if the belt can currently accept an item from the given direction * Returns if the belt can currently accept an item from the given direction
*/ */
canAcceptItem(leftoverProgress = 0.0) { canAcceptItem() {
const firstItem = this.sortedItems[0]; const firstItem = this.sortedItems[0];
if (!firstItem) { if (!firstItem) {
return true; return true;

View File

@ -20,6 +20,14 @@ export const enumItemAcceptorItemFilter = {
* filter?: enumItemAcceptorItemFilter * filter?: enumItemAcceptorItemFilter
* }} ItemAcceptorSlot */ * }} ItemAcceptorSlot */
/**
* Contains information about a slot plus its location
* @typedef {{
* slot: ItemAcceptorSlot,
* index: number,
* acceptedDirection: enumDirection
* }} ItemAcceptorLocatedSlot */
export class ItemAcceptorComponent extends Component { export class ItemAcceptorComponent extends Component {
static getId() { static getId() {
return "ItemAcceptor"; return "ItemAcceptor";
@ -164,11 +172,7 @@ export class ItemAcceptorComponent extends Component {
* Tries to find a slot which accepts the current item * Tries to find a slot which accepts the current item
* @param {Vector} targetLocalTile * @param {Vector} targetLocalTile
* @param {enumDirection} fromLocalDirection * @param {enumDirection} fromLocalDirection
* @returns {{ * @returns {ItemAcceptorLocatedSlot|null}
* slot: ItemAcceptorSlot,
* index: number,
* acceptedDirection: enumDirection
* }|null}
*/ */
findMatchingSlot(targetLocalTile, fromLocalDirection) { findMatchingSlot(targetLocalTile, fromLocalDirection) {
// We need to invert our direction since the acceptor specifies *from* which direction // We need to invert our direction since the acceptor specifies *from* which direction

View File

@ -12,6 +12,7 @@ export class MinerComponent extends Component {
} }
static getSchema() { static getSchema() {
// cachedMinedItem is not serialized.
return { return {
lastMiningTime: types.ufloat, lastMiningTime: types.ufloat,
chainable: types.bool, chainable: types.bool,
@ -25,8 +26,6 @@ export class MinerComponent extends Component {
}); });
} }
/**
*/
constructor({ chainable = false }) { constructor({ chainable = false }) {
super(); super();
this.lastMiningTime = 0; this.lastMiningTime = 0;
@ -38,6 +37,11 @@ export class MinerComponent extends Component {
* @type {Array<BaseItem>} * @type {Array<BaseItem>}
*/ */
this.itemChainBuffer = []; this.itemChainBuffer = [];
/**
* @type {BaseItem}
*/
this.cachedMinedItem = null;
} }
/** /**

View File

@ -17,7 +17,6 @@ import { SavegameSerializer } from "../savegame/savegame_serializer";
import { AutomaticSave } from "./automatic_save"; import { AutomaticSave } from "./automatic_save";
import { MetaHubBuilding } from "./buildings/hub"; import { MetaHubBuilding } from "./buildings/hub";
import { Camera } from "./camera"; import { Camera } from "./camera";
import { CanvasClickInterceptor } from "./canvas_click_interceptor";
import { EntityManager } from "./entity_manager"; import { EntityManager } from "./entity_manager";
import { GameSystemManager } from "./game_system_manager"; import { GameSystemManager } from "./game_system_manager";
import { HubGoals } from "./hub_goals"; import { HubGoals } from "./hub_goals";
@ -98,7 +97,6 @@ export class GameCore {
root.logic = new GameLogic(root); root.logic = new GameLogic(root);
root.hud = new GameHUD(root); root.hud = new GameHUD(root);
root.time = new GameTime(root); root.time = new GameTime(root);
root.canvasClickInterceptor = new CanvasClickInterceptor(root);
root.automaticSave = new AutomaticSave(root); root.automaticSave = new AutomaticSave(root);
root.soundProxy = new SoundProxy(root); root.soundProxy = new SoundProxy(root);

View File

@ -92,6 +92,9 @@ export class GameSystemManager {
add("staticMapEntities", StaticMapEntitySystem); add("staticMapEntities", StaticMapEntitySystem);
// IMPORTANT: Must be after belt system since belt system can change the
// orientation of an entity after it is placed -> the item acceptor cache
// then would be invalid
add("itemAcceptor", ItemAcceptorSystem); add("itemAcceptor", ItemAcceptorSystem);
logger.log("📦 There are", this.systemUpdateOrder.length, "game systems"); logger.log("📦 There are", this.systemUpdateOrder.length, "game systems");

View File

@ -34,6 +34,7 @@ import { HUDPartTutorialHints } from "./parts/tutorial_hints";
import { HUDWaypoints } from "./parts/waypoints"; import { HUDWaypoints } from "./parts/waypoints";
import { HUDInteractiveTutorial } from "./parts/interactive_tutorial"; import { HUDInteractiveTutorial } from "./parts/interactive_tutorial";
import { HUDScreenshotExporter } from "./parts/screenshot_exporter"; import { HUDScreenshotExporter } from "./parts/screenshot_exporter";
import { Entity } from "../entity";
export class GameHUD { export class GameHUD {
/** /**
@ -58,7 +59,6 @@ export class GameHUD {
shop: new HUDShop(this.root), shop: new HUDShop(this.root),
statistics: new HUDStatistics(this.root), statistics: new HUDStatistics(this.root),
waypoints: new HUDWaypoints(this.root), waypoints: new HUDWaypoints(this.root),
vignetteOverlay: new HUDVignetteOverlay(this.root),
// Must always exist // Must always exist
pinnedShapes: new HUDPinnedShapes(this.root), pinnedShapes: new HUDPinnedShapes(this.root),
@ -90,11 +90,16 @@ export class GameHUD {
if (IS_DEMO) { if (IS_DEMO) {
this.parts.watermark = new HUDWatermark(this.root); this.parts.watermark = new HUDWatermark(this.root);
} }
if (this.root.app.settings.getAllSettings().offerHints) { if (this.root.app.settings.getAllSettings().offerHints) {
this.parts.tutorialHints = new HUDPartTutorialHints(this.root); this.parts.tutorialHints = new HUDPartTutorialHints(this.root);
this.parts.interactiveTutorial = new HUDInteractiveTutorial(this.root); this.parts.interactiveTutorial = new HUDInteractiveTutorial(this.root);
} }
if (this.root.app.settings.getAllSettings().vignette) {
this.parts.vignetteOverlay = new HUDVignetteOverlay(this.root);
}
const frag = document.createDocumentFragment(); const frag = document.createDocumentFragment();
for (const key in this.parts) { for (const key in this.parts) {
this.parts[key].createElements(frag); this.parts[key].createElements(frag);

View File

@ -176,6 +176,7 @@ export class Blueprint {
tryPlace(root, tile) { tryPlace(root, tile) {
return root.logic.performBulkOperation(() => { return root.logic.performBulkOperation(() => {
let anyPlaced = false; let anyPlaced = false;
const beltsToRegisterLater = [];
for (let i = 0; i < this.entities.length; ++i) { for (let i = 0; i < this.entities.length; ++i) {
let placeable = true; let placeable = true;
const entity = this.entities[i]; const entity = this.entities[i];
@ -202,10 +203,10 @@ export class Blueprint {
"Can not delete entity for blueprint" "Can not delete entity for blueprint"
); );
if (!root.logic.tryDeleteBuilding(contents)) { if (!root.logic.tryDeleteBuilding(contents)) {
logger.error( assertAlways(
false,
"Building has replaceable component but is also unremovable in blueprint" "Building has replaceable component but is also unremovable in blueprint"
); );
return false;
} }
} }
} }
@ -215,10 +216,22 @@ export class Blueprint {
clone.components.StaticMapEntity.origin.addInplace(tile); clone.components.StaticMapEntity.origin.addInplace(tile);
root.map.placeStaticEntity(clone); root.map.placeStaticEntity(clone);
// Registering a belt immediately triggers a recalculation of surrounding belt
// directions, which is no good when not all belts have been placed. To resolve
// this, only register belts after all entities have been placed.
if (!clone.components.Belt) {
root.entityMgr.registerEntity(clone); root.entityMgr.registerEntity(clone);
} else {
beltsToRegisterLater.push(clone);
}
anyPlaced = true; anyPlaced = true;
} }
} }
for (let i = 0; i < beltsToRegisterLater.length; i++) {
root.entityMgr.registerEntity(beltsToRegisterLater[i]);
}
return anyPlaced; return anyPlaced;
}); });
} }

View File

@ -1,15 +1,15 @@
import { DrawParameters } from "../../../core/draw_parameters"; import { DrawParameters } from "../../../core/draw_parameters";
import { STOP_PROPAGATION } from "../../../core/signal"; import { STOP_PROPAGATION } from "../../../core/signal";
import { TrackedState } from "../../../core/tracked_state"; import { TrackedState } from "../../../core/tracked_state";
import { makeDiv } from "../../../core/utils";
import { Vector } from "../../../core/vector"; import { Vector } from "../../../core/vector";
import { T } from "../../../translations";
import { enumMouseButton } from "../../camera"; import { enumMouseButton } from "../../camera";
import { KEYMAPPINGS } from "../../key_action_mapper"; import { KEYMAPPINGS } from "../../key_action_mapper";
import { BaseHUDPart } from "../base_hud_part";
import { Blueprint } from "./blueprint";
import { makeDiv } from "../../../core/utils";
import { DynamicDomAttach } from "../dynamic_dom_attach";
import { blueprintShape } from "../../upgrades"; import { blueprintShape } from "../../upgrades";
import { T } from "../../../translations"; import { BaseHUDPart } from "../base_hud_part";
import { DynamicDomAttach } from "../dynamic_dom_attach";
import { Blueprint } from "./blueprint";
export class HUDBlueprintPlacer extends BaseHUDPart { export class HUDBlueprintPlacer extends BaseHUDPart {
createElements(parent) { createElements(parent) {
@ -34,9 +34,7 @@ export class HUDBlueprintPlacer extends BaseHUDPart {
const keyActionMapper = this.root.keyMapper; const keyActionMapper = this.root.keyMapper;
keyActionMapper.getBinding(KEYMAPPINGS.general.back).add(this.abortPlacement, this); keyActionMapper.getBinding(KEYMAPPINGS.general.back).add(this.abortPlacement, this);
keyActionMapper keyActionMapper.getBinding(KEYMAPPINGS.placement.pipette).add(this.abortPlacement, this);
.getBinding(KEYMAPPINGS.placement.abortBuildingPlacement)
.add(this.abortPlacement, this);
keyActionMapper.getBinding(KEYMAPPINGS.placement.rotateWhilePlacing).add(this.rotateBlueprint, this); keyActionMapper.getBinding(KEYMAPPINGS.placement.rotateWhilePlacing).add(this.rotateBlueprint, this);
keyActionMapper.getBinding(KEYMAPPINGS.massSelect.pasteLastBlueprint).add(this.pasteBlueprint, this); keyActionMapper.getBinding(KEYMAPPINGS.massSelect.pasteLastBlueprint).add(this.pasteBlueprint, this);
@ -62,10 +60,9 @@ export class HUDBlueprintPlacer extends BaseHUDPart {
} }
update() { update() {
this.domAttach.update(this.currentBlueprint.get()); const currentBlueprint = this.currentBlueprint.get();
this.trackedCanAfford.set( this.domAttach.update(currentBlueprint && currentBlueprint.getCost() > 0);
this.currentBlueprint.get() && this.currentBlueprint.get().canAfford(this.root) this.trackedCanAfford.set(currentBlueprint && currentBlueprint.canAfford(this.root));
);
} }
/** /**
@ -108,7 +105,7 @@ export class HUDBlueprintPlacer extends BaseHUDPart {
this.root.hubGoals.takeShapeByKey(blueprintShape, cost); this.root.hubGoals.takeShapeByKey(blueprintShape, cost);
// This actually feels weird // This actually feels weird
// if (!this.root.keyMapper.getBinding(KEYMAPPINGS.placementModifiers.placeMultiple).isCurrentlyPressed()) { // if (!this.root.keyMapper.getBinding(KEYMAPPINGS.placementModifiers.placeMultiple).pressed) {
// this.currentBlueprint.set(null); // this.currentBlueprint.set(null);
// } // }
} }
@ -133,11 +130,7 @@ export class HUDBlueprintPlacer extends BaseHUDPart {
rotateBlueprint() { rotateBlueprint() {
if (this.currentBlueprint.get()) { if (this.currentBlueprint.get()) {
if ( if (this.root.keyMapper.getBinding(KEYMAPPINGS.placement.rotateInverseModifier).pressed) {
this.root.keyMapper
.getBinding(KEYMAPPINGS.placement.rotateInverseModifier)
.isCurrentlyPressed()
) {
this.currentBlueprint.get().rotateCcw(); this.currentBlueprint.get().rotateCcw();
} else { } else {
this.currentBlueprint.get().rotateCw(); this.currentBlueprint.get().rotateCw();

View File

@ -1,85 +1,26 @@
import { Math_abs, Math_degrees, Math_radians } from "../../../core/builtins"; import { Math_radians } from "../../../core/builtins";
import { globalConfig } from "../../../core/config"; import { globalConfig } from "../../../core/config";
import { DrawParameters } from "../../../core/draw_parameters"; import { DrawParameters } from "../../../core/draw_parameters";
import { drawRotatedSprite } from "../../../core/draw_utils"; import { drawRotatedSprite } from "../../../core/draw_utils";
import { Loader } from "../../../core/loader"; import { Loader } from "../../../core/loader";
import { STOP_PROPAGATION } from "../../../core/signal"; import { makeDiv, removeAllChildren, pulseAnimation, clamp } from "../../../core/utils";
import { TrackedState } from "../../../core/tracked_state";
import { makeDiv, removeAllChildren } from "../../../core/utils";
import { import {
enumDirectionToAngle, enumDirectionToAngle,
enumDirectionToVector, enumDirectionToVector,
enumInvertedDirections, enumInvertedDirections,
Vector, Vector,
} from "../../../core/vector"; } from "../../../core/vector";
import { enumMouseButton } from "../../camera";
import { StaticMapEntityComponent } from "../../components/static_map_entity";
import { Entity } from "../../entity";
import { defaultBuildingVariant, MetaBuilding } from "../../meta_building";
import { BaseHUDPart } from "../base_hud_part";
import { DynamicDomAttach } from "../dynamic_dom_attach";
import { T } from "../../../translations"; import { T } from "../../../translations";
import { KEYMAPPINGS } from "../../key_action_mapper"; import { KEYMAPPINGS } from "../../key_action_mapper";
import { defaultBuildingVariant } from "../../meta_building";
import { THEME } from "../../theme";
import { DynamicDomAttach } from "../dynamic_dom_attach";
import { HUDBuildingPlacerLogic } from "./building_placer_logic";
export class HUDBuildingPlacer extends BaseHUDPart { export class HUDBuildingPlacer extends HUDBuildingPlacerLogic {
initialize() {
/** @type {TypedTrackedState<MetaBuilding?>} */
this.currentMetaBuilding = new TrackedState(this.onSelectedMetaBuildingChanged, this);
this.currentBaseRotation = 0;
/** @type {Entity} */
this.fakeEntity = null;
const keyActionMapper = this.root.keyMapper;
keyActionMapper
.getBinding(KEYMAPPINGS.placement.abortBuildingPlacement)
.add(this.abortPlacement, this);
keyActionMapper.getBinding(KEYMAPPINGS.general.back).add(this.abortPlacement, this);
keyActionMapper.getBinding(KEYMAPPINGS.placement.rotateWhilePlacing).add(this.tryRotate, this);
keyActionMapper.getBinding(KEYMAPPINGS.placement.cycleBuildingVariants).add(this.cycleVariants, this);
this.root.hud.signals.buildingsSelectedForCopy.add(this.abortPlacement, this);
this.root.hud.signals.pasteBlueprintRequested.add(this.abortPlacement, this);
this.domAttach = new DynamicDomAttach(this.root, this.element, {});
this.root.camera.downPreHandler.add(this.onMouseDown, this);
this.root.camera.movePreHandler.add(this.onMouseMove, this);
this.root.camera.upPostHandler.add(this.abortDragging, this);
this.currentlyDragging = false;
this.currentVariant = new TrackedState(this.rerenderVariants, this);
this.variantsAttach = new DynamicDomAttach(this.root, this.variantsElement, {});
/** /**
* Whether we are currently drag-deleting * @param {HTMLElement} parent
*/ */
this.currentlyDeleting = false;
/**
* Stores which variants for each building we prefer, this is based on what
* the user last selected
*/
this.preferredVariants = {};
/**
* The tile we last dragged onto
* @type {Vector}
* */
this.lastDragTile = null;
/**
* The tile we initially dragged from
* @type {Vector}
*/
this.initialDragTile = null;
this.root.signals.storyGoalCompleted.add(this.rerenderVariants, this);
this.root.signals.upgradePurchased.add(this.rerenderVariants, this);
}
createElements(parent) { createElements(parent) {
this.element = makeDiv(parent, "ingame_HUD_PlacementHints", [], ``); this.element = makeDiv(parent, "ingame_HUD_PlacementHints", [], ``);
@ -97,183 +38,24 @@ export class HUDBuildingPlacer extends BaseHUDPart {
this.buildingInfoElements.tutorialImage = makeDiv(this.element, null, ["buildingImage"]); this.buildingInfoElements.tutorialImage = makeDiv(this.element, null, ["buildingImage"]);
this.variantsElement = makeDiv(parent, "ingame_HUD_PlacerVariants"); this.variantsElement = makeDiv(parent, "ingame_HUD_PlacerVariants");
const compact = this.root.app.settings.getAllSettings().compactBuildingInfo;
this.element.classList.toggle("compact", compact);
this.variantsElement.classList.toggle("compact", compact);
} }
abortPlacement() { initialize() {
if (this.currentMetaBuilding.get()) { super.initialize();
this.currentMetaBuilding.set(null);
return STOP_PROPAGATION;
}
}
/** // Bind to signals
* mouse down pre handler this.signals.variantChanged.add(this.rerenderVariants, this);
* @param {Vector} pos
* @param {enumMouseButton} button
*/
onMouseDown(pos, button) {
if (this.root.camera.getIsMapOverlayActive()) {
return;
}
// Placement this.domAttach = new DynamicDomAttach(this.root, this.element, {});
if (button === enumMouseButton.left && this.currentMetaBuilding.get()) { this.variantsAttach = new DynamicDomAttach(this.root, this.variantsElement, {});
this.currentlyDragging = true;
this.currentlyDeleting = false;
this.lastDragTile = this.root.camera.screenToWorld(pos).toTileSpace();
// Place initial building this.currentInterpolatedCornerTile = new Vector();
this.tryPlaceCurrentBuildingAt(this.lastDragTile);
return STOP_PROPAGATION; this.lockIndicatorSprite = Loader.getSprite("sprites/misc/lock_direction_indicator.png");
}
// Deletion
if (button === enumMouseButton.right && !this.currentMetaBuilding.get()) {
this.currentlyDragging = true;
this.currentlyDeleting = true;
this.lastDragTile = this.root.camera.screenToWorld(pos).toTileSpace();
this.currentMetaBuilding.set(null);
return STOP_PROPAGATION;
}
}
/**
* mouse move pre handler
* @param {Vector} pos
*/
onMouseMove(pos) {
if (this.root.camera.getIsMapOverlayActive()) {
return;
}
const metaBuilding = this.currentMetaBuilding.get();
if ((metaBuilding || this.currentlyDeleting) && this.lastDragTile) {
const oldPos = this.lastDragTile;
const newPos = this.root.camera.screenToWorld(pos).toTileSpace();
if (this.root.camera.desiredCenter) {
// Camera is moving
this.lastDragTile = newPos;
return;
}
if (!oldPos.equals(newPos)) {
if (
metaBuilding &&
metaBuilding.getRotateAutomaticallyWhilePlacing(this.currentVariant.get()) &&
!this.root.keyMapper
.getBinding(KEYMAPPINGS.placementModifiers.placementDisableAutoOrientation)
.isCurrentlyPressed()
) {
const delta = newPos.sub(oldPos);
const angleDeg = Math_degrees(delta.angle());
this.currentBaseRotation = (Math.round(angleDeg / 90) * 90 + 360) % 360;
// Holding alt inverts the placement
if (
this.root.keyMapper
.getBinding(KEYMAPPINGS.placementModifiers.placeInverse)
.isCurrentlyPressed()
) {
this.currentBaseRotation = (180 + this.currentBaseRotation) % 360;
}
}
// - Using bresenhams algorithmus
let x0 = oldPos.x;
let y0 = oldPos.y;
let x1 = newPos.x;
let y1 = newPos.y;
var dx = Math_abs(x1 - x0);
var dy = Math_abs(y1 - y0);
var sx = x0 < x1 ? 1 : -1;
var sy = y0 < y1 ? 1 : -1;
var err = dx - dy;
while (this.currentlyDeleting || this.currentMetaBuilding.get()) {
if (this.currentlyDeleting) {
const contents = this.root.map.getTileContentXY(x0, y0);
if (contents && !contents.queuedForDestroy && !contents.destroyed) {
this.root.logic.tryDeleteBuilding(contents);
}
} else {
this.tryPlaceCurrentBuildingAt(new Vector(x0, y0));
}
if (x0 === x1 && y0 === y1) break;
var e2 = 2 * err;
if (e2 > -dy) {
err -= dy;
x0 += sx;
}
if (e2 < dx) {
err += dx;
y0 += sy;
}
}
}
this.lastDragTile = newPos;
return STOP_PROPAGATION;
}
}
update() {
// ALways update since the camera might have moved
const mousePos = this.root.app.mousePosition;
if (mousePos) {
this.onMouseMove(mousePos);
}
}
/**
* aborts any dragging op
*/
abortDragging() {
this.currentlyDragging = true;
this.currentlyDeleting = false;
this.lastDragTile = null;
}
/**
*
* @param {MetaBuilding} metaBuilding
*/
startSelection(metaBuilding) {
this.currentMetaBuilding.set(metaBuilding);
}
/**
* @param {MetaBuilding} metaBuilding
*/
onSelectedMetaBuildingChanged(metaBuilding) {
this.abortDragging();
this.root.hud.signals.selectedPlacementBuildingChanged.dispatch(metaBuilding);
if (metaBuilding) {
const variant = this.preferredVariants[metaBuilding.getId()] || defaultBuildingVariant;
this.currentVariant.set(variant);
this.fakeEntity = new Entity(null);
metaBuilding.setupEntityComponents(this.fakeEntity, null);
this.fakeEntity.addComponent(
new StaticMapEntityComponent({
origin: new Vector(0, 0),
rotation: 0,
tileSize: metaBuilding.getDimensions(this.currentVariant.get()).copy(),
blueprintSpriteKey: "",
})
);
metaBuilding.updateVariants(this.fakeEntity, 0, this.currentVariant.get());
} else {
this.fakeEntity = null;
}
// Since it depends on both, rerender twice
this.rerenderVariants();
} }
/** /**
@ -368,147 +150,6 @@ export class HUDBuildingPlacer extends BaseHUDPart {
} }
} }
/**
* Cycles through the variants
*/
cycleVariants() {
const metaBuilding = this.currentMetaBuilding.get();
if (!metaBuilding) {
this.currentVariant.set(defaultBuildingVariant);
} else {
const availableVariants = metaBuilding.getAvailableVariants(this.root);
const index = availableVariants.indexOf(this.currentVariant.get());
assert(
index >= 0,
"Current variant was invalid: " + this.currentVariant.get() + " out of " + availableVariants
);
const newIndex = (index + 1) % availableVariants.length;
const newVariant = availableVariants[newIndex];
this.currentVariant.set(newVariant);
this.preferredVariants[metaBuilding.getId()] = newVariant;
}
}
/**
* Tries to rotate
*/
tryRotate() {
const selectedBuilding = this.currentMetaBuilding.get();
if (selectedBuilding) {
if (
this.root.keyMapper
.getBinding(KEYMAPPINGS.placement.rotateInverseModifier)
.isCurrentlyPressed()
) {
this.currentBaseRotation = (this.currentBaseRotation + 270) % 360;
} else {
this.currentBaseRotation = (this.currentBaseRotation + 90) % 360;
}
const staticComp = this.fakeEntity.components.StaticMapEntity;
staticComp.rotation = this.currentBaseRotation;
}
}
/**
* Tries to delete the building under the mouse
*/
deleteBelowCursor() {
const mousePosition = this.root.app.mousePosition;
if (!mousePosition) {
// Not on screen
return;
}
const worldPos = this.root.camera.screenToWorld(mousePosition);
const tile = worldPos.toTileSpace();
const contents = this.root.map.getTileContent(tile);
if (contents) {
this.root.logic.tryDeleteBuilding(contents);
}
}
/**
* Canvas click handler
* @param {Vector} mousePos
* @param {boolean} cancelAction
*/
onCanvasClick(mousePos, cancelAction = false) {
if (cancelAction) {
if (this.currentMetaBuilding.get()) {
this.currentMetaBuilding.set(null);
} else {
this.deleteBelowCursor();
}
return STOP_PROPAGATION;
}
if (!this.currentMetaBuilding.get()) {
return;
}
return STOP_PROPAGATION;
}
/**
* Tries to place the current building at the given tile
* @param {Vector} tile
*/
tryPlaceCurrentBuildingAt(tile) {
if (this.root.camera.zoomLevel < globalConfig.mapChunkOverviewMinZoom) {
// Dont allow placing in overview mode
return;
}
// Transform to world space
const metaBuilding = this.currentMetaBuilding.get();
const { rotation, rotationVariant } = metaBuilding.computeOptimalDirectionAndRotationVariantAtTile(
this.root,
tile,
this.currentBaseRotation,
this.currentVariant.get()
);
if (
this.root.logic.tryPlaceBuilding({
origin: tile,
rotation,
rotationVariant,
originalRotation: this.currentBaseRotation,
building: this.currentMetaBuilding.get(),
variant: this.currentVariant.get(),
})
) {
// Succesfully placed
if (
metaBuilding.getFlipOrientationAfterPlacement() &&
!this.root.keyMapper
.getBinding(KEYMAPPINGS.placementModifiers.placementDisableAutoOrientation)
.isCurrentlyPressed()
) {
this.currentBaseRotation = (180 + this.currentBaseRotation) % 360;
}
if (
!metaBuilding.getStayInPlacementMode() &&
!this.root.keyMapper
.getBinding(KEYMAPPINGS.placementModifiers.placeMultiple)
.isCurrentlyPressed() &&
!this.root.app.settings.getAllSettings().alwaysMultiplace
) {
// Stop placement
this.currentMetaBuilding.set(null);
}
return true;
} else {
return false;
}
}
/** /**
* *
* @param {DrawParameters} parameters * @param {DrawParameters} parameters
@ -529,14 +170,28 @@ export class HUDBuildingPlacer extends BaseHUDPart {
return; return;
} }
// Draw direction lock
if (this.isDirectionLockActive) {
this.drawDirectionLock(parameters);
} else {
this.drawRegularPlacement(parameters);
}
}
/**
* @param {DrawParameters} parameters
*/
drawRegularPlacement(parameters) {
const mousePosition = this.root.app.mousePosition; const mousePosition = this.root.app.mousePosition;
if (!mousePosition) { if (!mousePosition) {
// Not on screen // Not on screen
return; return;
} }
const metaBuilding = this.currentMetaBuilding.get();
const worldPos = this.root.camera.screenToWorld(mousePosition); const worldPos = this.root.camera.screenToWorld(mousePosition);
const tile = worldPos.toTileSpace(); const mouseTile = worldPos.toTileSpace();
// Compute best rotation variant // Compute best rotation variant
const { const {
@ -545,7 +200,7 @@ export class HUDBuildingPlacer extends BaseHUDPart {
connectedEntities, connectedEntities,
} = metaBuilding.computeOptimalDirectionAndRotationVariantAtTile( } = metaBuilding.computeOptimalDirectionAndRotationVariantAtTile(
this.root, this.root,
tile, mouseTile,
this.currentBaseRotation, this.currentBaseRotation,
this.currentVariant.get() this.currentVariant.get()
); );
@ -558,7 +213,7 @@ export class HUDBuildingPlacer extends BaseHUDPart {
.getCenter() .getCenter()
.toWorldSpace(); .toWorldSpace();
const startWsPoint = tile.toWorldSpaceCenterOfTile(); const startWsPoint = mouseTile.toWorldSpaceCenterOfTile();
const startOffset = connectedWsPoint const startOffset = connectedWsPoint
.sub(startWsPoint) .sub(startWsPoint)
@ -583,14 +238,14 @@ export class HUDBuildingPlacer extends BaseHUDPart {
// Synchronize rotation and origin // Synchronize rotation and origin
const staticComp = this.fakeEntity.components.StaticMapEntity; const staticComp = this.fakeEntity.components.StaticMapEntity;
staticComp.origin = tile; staticComp.origin = mouseTile;
staticComp.rotation = rotation; staticComp.rotation = rotation;
staticComp.tileSize = metaBuilding.getDimensions(this.currentVariant.get()); staticComp.tileSize = metaBuilding.getDimensions(this.currentVariant.get());
metaBuilding.updateVariants(this.fakeEntity, rotationVariant, this.currentVariant.get()); metaBuilding.updateVariants(this.fakeEntity, rotationVariant, this.currentVariant.get());
// Check if we could place the buildnig // Check if we could place the buildnig
const canBuild = this.root.logic.checkCanPlaceBuilding({ const canBuild = this.root.logic.checkCanPlaceBuilding({
origin: tile, origin: mouseTile,
rotation, rotation,
rotationVariant, rotationVariant,
building: metaBuilding, building: metaBuilding,
@ -627,7 +282,7 @@ export class HUDBuildingPlacer extends BaseHUDPart {
const previewSprite = metaBuilding.getBlueprintSprite(rotationVariant, this.currentVariant.get()); const previewSprite = metaBuilding.getBlueprintSprite(rotationVariant, this.currentVariant.get());
staticComp.origin = worldPos.divideScalar(globalConfig.tileSize).subScalars(0.5, 0.5); staticComp.origin = worldPos.divideScalar(globalConfig.tileSize).subScalars(0.5, 0.5);
staticComp.drawSpriteOnFullEntityBounds(parameters, previewSprite); staticComp.drawSpriteOnFullEntityBounds(parameters, previewSprite);
staticComp.origin = tile; staticComp.origin = mouseTile;
// Draw ejectors // Draw ejectors
if (canBuild) { if (canBuild) {
@ -636,7 +291,63 @@ export class HUDBuildingPlacer extends BaseHUDPart {
} }
/** /**
* * @param {DrawParameters} parameters
*/
drawDirectionLock(parameters) {
const mousePosition = this.root.app.mousePosition;
if (!mousePosition) {
// Not on screen
return;
}
const mouseWorld = this.root.camera.screenToWorld(mousePosition);
const mouseTile = mouseWorld.toTileSpace();
parameters.context.fillStyle = THEME.map.directionLock;
parameters.context.strokeStyle = THEME.map.directionLockTrack;
parameters.context.lineWidth = 10;
parameters.context.beginCircle(mouseWorld.x, mouseWorld.y, 4);
parameters.context.fill();
if (this.lastDragTile) {
const startLine = this.lastDragTile.toWorldSpaceCenterOfTile();
const endLine = mouseTile.toWorldSpaceCenterOfTile();
const midLine = this.currentDirectionLockCorner.toWorldSpaceCenterOfTile();
parameters.context.beginCircle(startLine.x, startLine.y, 8);
parameters.context.fill();
parameters.context.beginPath();
parameters.context.moveTo(startLine.x, startLine.y);
parameters.context.lineTo(midLine.x, midLine.y);
parameters.context.lineTo(endLine.x, endLine.y);
parameters.context.stroke();
parameters.context.beginCircle(endLine.x, endLine.y, 5);
parameters.context.fill();
// Draw arrows
const path = this.computeDirectionLockPath();
for (let i = 0; i < path.length - 1; i += 1) {
const { rotation, tile } = path[i];
const worldPos = tile.toWorldSpaceCenterOfTile();
drawRotatedSprite({
parameters,
sprite: this.lockIndicatorSprite,
x: worldPos.x,
y: worldPos.y,
angle: Math_radians(rotation),
size: 12,
offsetY:
-globalConfig.halfTileSize -
clamp((this.root.time.now() * 1.5) % 1.0, 0, 1) * 1 * globalConfig.tileSize +
globalConfig.halfTileSize,
});
}
}
}
/**
* @param {DrawParameters} parameters * @param {DrawParameters} parameters
*/ */
drawMatchingAcceptorsAndEjectors(parameters) { drawMatchingAcceptorsAndEjectors(parameters) {

View File

@ -0,0 +1,690 @@
import { Math_abs, Math_degrees, Math_round } from "../../../core/builtins";
import { globalConfig } from "../../../core/config";
import { gMetaBuildingRegistry } from "../../../core/global_registries";
import { Signal, STOP_PROPAGATION } from "../../../core/signal";
import { TrackedState } from "../../../core/tracked_state";
import { Vector } from "../../../core/vector";
import { enumMouseButton } from "../../camera";
import { StaticMapEntityComponent } from "../../components/static_map_entity";
import { Entity } from "../../entity";
import { KEYMAPPINGS } from "../../key_action_mapper";
import { defaultBuildingVariant, MetaBuilding } from "../../meta_building";
import { BaseHUDPart } from "../base_hud_part";
/**
* Contains all logic for the building placer - this doesn't include the rendering
* of info boxes or drawing.
*/
export class HUDBuildingPlacerLogic extends BaseHUDPart {
/**
* Initializes the logic
* @see BaseHUDPart.initialize
*/
initialize() {
/**
* We use a fake entity to get information about how a building will look
* once placed
* @type {Entity}
*/
this.fakeEntity = null;
// Signals
this.signals = {
variantChanged: new Signal(),
draggingStarted: new Signal(),
};
/**
* The current building
* @type {TypedTrackedState<MetaBuilding?>}
*/
this.currentMetaBuilding = new TrackedState(this.onSelectedMetaBuildingChanged, this);
/**
* The current rotation
* @type {number}
*/
this.currentBaseRotation = 0;
/**
* Whether we are currently dragging
* @type {boolean}
*/
this.currentlyDragging = false;
/**
* Current building variant
* @type {TypedTrackedState<string>}
*/
this.currentVariant = new TrackedState(() => this.signals.variantChanged.dispatch());
/**
* Whether we are currently drag-deleting
* @type {boolean}
*/
this.currentlyDeleting = false;
/**
* Stores which variants for each building we prefer, this is based on what
* the user last selected
* @type {Object.<string, string>}
*/
this.preferredVariants = {};
/**
* The tile we last dragged from
* @type {Vector}
*/
this.lastDragTile = null;
/**
* The side for direction lock
* @type {number} (0|1)
*/
this.currentDirectionLockSide = 0;
this.initializeBindings();
}
/**
* Initializes all bindings
*/
initializeBindings() {
// KEYBINDINGS
const keyActionMapper = this.root.keyMapper;
keyActionMapper.getBinding(KEYMAPPINGS.placement.rotateWhilePlacing).add(this.tryRotate, this);
keyActionMapper.getBinding(KEYMAPPINGS.placement.cycleBuildingVariants).add(this.cycleVariants, this);
keyActionMapper
.getBinding(KEYMAPPINGS.placement.switchDirectionLockSide)
.add(this.switchDirectionLockSide, this);
keyActionMapper.getBinding(KEYMAPPINGS.general.back).add(this.abortPlacement, this);
keyActionMapper.getBinding(KEYMAPPINGS.placement.pipette).add(this.startPipette, this);
this.root.gameState.inputReciever.keyup.add(this.checkForDirectionLockSwitch, this);
// BINDINGS TO GAME EVENTS
this.root.hud.signals.buildingsSelectedForCopy.add(this.abortPlacement, this);
this.root.hud.signals.pasteBlueprintRequested.add(this.abortPlacement, this);
this.root.signals.storyGoalCompleted.add(() => this.signals.variantChanged.dispatch());
this.root.signals.upgradePurchased.add(() => this.signals.variantChanged.dispatch());
// MOUSE BINDINGS
this.root.camera.downPreHandler.add(this.onMouseDown, this);
this.root.camera.movePreHandler.add(this.onMouseMove, this);
this.root.camera.upPostHandler.add(this.onMouseUp, this);
}
/**
* Returns if the direction lock is currently active
* @returns {boolean}
*/
get isDirectionLockActive() {
const metaBuilding = this.currentMetaBuilding.get();
return (
metaBuilding &&
metaBuilding.getHasDirectionLockAvailable() &&
this.root.keyMapper.getBinding(KEYMAPPINGS.placementModifiers.lockBeltDirection).pressed
);
}
/**
* Returns the current direction lock corner, that is, the corner between
* mouse and original start point
* @returns {Vector|null}
*/
get currentDirectionLockCorner() {
const mousePosition = this.root.app.mousePosition;
if (!mousePosition) {
// Not on screen
return null;
}
if (!this.lastDragTile) {
// Haven't dragged yet
return null;
}
// Figure which points the line visits
const worldPos = this.root.camera.screenToWorld(mousePosition);
const mouseTile = worldPos.toTileSpace();
if (this.currentDirectionLockSide === 0) {
return new Vector(this.lastDragTile.x, mouseTile.y);
} else {
return new Vector(mouseTile.x, this.lastDragTile.y);
}
}
/**
* Aborts the placement
*/
abortPlacement() {
if (this.currentMetaBuilding.get()) {
this.currentMetaBuilding.set(null);
return STOP_PROPAGATION;
}
}
/**
* Aborts any dragging
*/
abortDragging() {
this.currentlyDragging = true;
this.currentlyDeleting = false;
this.initialPlacementVector = null;
this.lastDragTile = null;
}
/**
* @see BaseHUDPart.update
*/
update() {
// Always update since the camera might have moved
const mousePos = this.root.app.mousePosition;
if (mousePos) {
this.onMouseMove(mousePos);
}
}
/**
* Tries to rotate the current building
*/
tryRotate() {
const selectedBuilding = this.currentMetaBuilding.get();
if (selectedBuilding) {
if (this.root.keyMapper.getBinding(KEYMAPPINGS.placement.rotateInverseModifier).pressed) {
this.currentBaseRotation = (this.currentBaseRotation + 270) % 360;
} else {
this.currentBaseRotation = (this.currentBaseRotation + 90) % 360;
}
const staticComp = this.fakeEntity.components.StaticMapEntity;
staticComp.rotation = this.currentBaseRotation;
}
}
/**
* Tries to delete the building under the mouse
*/
deleteBelowCursor() {
const mousePosition = this.root.app.mousePosition;
if (!mousePosition) {
// Not on screen
return;
}
const worldPos = this.root.camera.screenToWorld(mousePosition);
const tile = worldPos.toTileSpace();
const contents = this.root.map.getTileContent(tile);
if (contents) {
this.root.logic.tryDeleteBuilding(contents);
}
}
/**
* Starts the pipette function
*/
startPipette() {
// Disable in overview
if (this.root.camera.getIsMapOverlayActive()) {
return;
}
const mousePosition = this.root.app.mousePosition;
if (!mousePosition) {
// Not on screen
return;
}
const worldPos = this.root.camera.screenToWorld(mousePosition);
const tile = worldPos.toTileSpace();
const contents = this.root.map.getTileContent(tile);
if (!contents) {
this.currentMetaBuilding.set(null);
return;
}
// Try to extract the building
const extracted = this.hack_reconstructMetaBuildingAndVariantFromBuilding(contents);
if (!extracted) {
this.currentMetaBuilding.set(null);
return;
}
this.currentMetaBuilding.set(extracted.metaBuilding);
this.currentVariant.set(extracted.variant);
this.currentBaseRotation = contents.components.StaticMapEntity.rotation;
// Make sure we selected something, and also make sure it's not a special entity
// if (contents && !contents.components.Unremovable) {
// }
}
/**
* HACK!
*
* This attempts to reconstruct the meta building and its variant from a given entity
* @param {Entity} entity
* @returns {{ metaBuilding: MetaBuilding, variant: string }}
*/
hack_reconstructMetaBuildingAndVariantFromBuilding(entity) {
if (entity.components.Hub) {
// Hub is not copyable
return null;
}
const matches = [];
const metaBuildings = gMetaBuildingRegistry.entries;
for (let i = 0; i < metaBuildings.length; ++i) {
const metaBuilding = metaBuildings[i];
const availableVariants = metaBuilding.getAvailableVariants(this.root);
checkVariant: for (let k = 0; k < availableVariants.length; ++k) {
const variant = availableVariants[k];
let unplaced = metaBuilding.createEntity({
root: this.root,
variant,
origin: new Vector(0, 0),
rotation: 0,
originalRotation: 0,
rotationVariant: 0,
});
// Compare if both entities share the same components
for (let component in entity.components) {
if ((entity.components[component] == null) !== (unplaced.components[component] == null)) {
continue checkVariant;
}
}
// Check for same item processor
if (
entity.components.ItemProcessor &&
entity.components.ItemProcessor.type != unplaced.components.ItemProcessor.type
) {
continue checkVariant;
}
// Check for underground belt
if (
entity.components.UndergroundBelt &&
entity.components.UndergroundBelt.tier != unplaced.components.UndergroundBelt.tier
) {
continue checkVariant;
}
// Check for same sprite key - except for underground belts
// since the sprite may vary here
if (
!entity.components.UndergroundBelt &&
entity.components.StaticMapEntity.spriteKey !=
unplaced.components.StaticMapEntity.spriteKey
) {
continue checkVariant;
}
matches.push({ metaBuilding, variant });
}
}
if (matches.length == 1) {
const staticEntity = entity.components.StaticMapEntity;
const key = staticEntity.spriteKey || staticEntity.blueprintSpriteKey;
assert(
key &&
key.includes(matches[0].metaBuilding.id) &&
(matches[0].variant === defaultBuildingVariant || key.includes(matches[0].variant))
);
return matches[0];
}
return null;
}
switchDirectionLockSide() {
this.currentDirectionLockSide = 1 - this.currentDirectionLockSide;
}
/**
* Checks if the direction lock key got released and if such, resets the placement
* @param {any} args
*/
checkForDirectionLockSwitch({ keyCode }) {
if (
keyCode ===
this.root.keyMapper.getBinding(KEYMAPPINGS.placementModifiers.lockBeltDirection).keyCode
) {
this.abortDragging();
}
}
/**
* Tries to place the current building at the given tile
* @param {Vector} tile
*/
tryPlaceCurrentBuildingAt(tile) {
if (this.root.camera.zoomLevel < globalConfig.mapChunkOverviewMinZoom) {
// Dont allow placing in overview mode
return;
}
const metaBuilding = this.currentMetaBuilding.get();
const { rotation, rotationVariant } = metaBuilding.computeOptimalDirectionAndRotationVariantAtTile(
this.root,
tile,
this.currentBaseRotation,
this.currentVariant.get()
);
const entity = this.root.logic.tryPlaceBuilding({
origin: tile,
rotation,
rotationVariant,
originalRotation: this.currentBaseRotation,
building: this.currentMetaBuilding.get(),
variant: this.currentVariant.get(),
});
if (entity) {
// Succesfully placed, find which entity we actually placed
this.root.signals.entityManuallyPlaced.dispatch(entity);
// Check if we should flip the orientation (used for tunnels)
if (
metaBuilding.getFlipOrientationAfterPlacement() &&
!this.root.keyMapper.getBinding(
KEYMAPPINGS.placementModifiers.placementDisableAutoOrientation
).pressed
) {
this.currentBaseRotation = (180 + this.currentBaseRotation) % 360;
}
// Check if we should stop placement
if (
!metaBuilding.getStayInPlacementMode() &&
!this.root.keyMapper.getBinding(KEYMAPPINGS.placementModifiers.placeMultiple).pressed &&
!this.root.app.settings.getAllSettings().alwaysMultiplace
) {
// Stop placement
this.currentMetaBuilding.set(null);
}
return true;
} else {
return false;
}
}
/**
* Cycles through the variants
*/
cycleVariants() {
const metaBuilding = this.currentMetaBuilding.get();
if (!metaBuilding) {
this.currentVariant.set(defaultBuildingVariant);
} else {
const availableVariants = metaBuilding.getAvailableVariants(this.root);
const index = availableVariants.indexOf(this.currentVariant.get());
assert(
index >= 0,
"Current variant was invalid: " + this.currentVariant.get() + " out of " + availableVariants
);
const newIndex = (index + 1) % availableVariants.length;
const newVariant = availableVariants[newIndex];
this.currentVariant.set(newVariant);
this.preferredVariants[metaBuilding.getId()] = newVariant;
}
}
/**
* Performs the direction locked placement between two points after
* releasing the mouse
*/
executeDirectionLockedPlacement() {
const path = this.computeDirectionLockPath();
this.root.logic.performBulkOperation(() => {
for (let i = 0; i < path.length; ++i) {
const { rotation, tile } = path[i];
this.currentBaseRotation = rotation;
this.tryPlaceCurrentBuildingAt(tile);
}
});
}
/**
* Finds the path which the current direction lock will use
* @returns {Array<{ tile: Vector, rotation: number }>}
*/
computeDirectionLockPath() {
const mousePosition = this.root.app.mousePosition;
if (!mousePosition) {
// Not on screen
return [];
}
let result = [];
// Figure which points the line visits
const worldPos = this.root.camera.screenToWorld(mousePosition);
const mouseTile = worldPos.toTileSpace();
const startTile = this.lastDragTile;
// Place from start to corner
const pathToCorner = this.currentDirectionLockCorner.sub(startTile);
const deltaToCorner = pathToCorner.normalize().round();
const lengthToCorner = Math_round(pathToCorner.length());
let currentPos = startTile.copy();
let rotation = (Math.round(Math_degrees(deltaToCorner.angle()) / 90) * 90 + 360) % 360;
if (lengthToCorner > 0) {
for (let i = 0; i < lengthToCorner; ++i) {
result.push({
tile: currentPos.copy(),
rotation,
});
currentPos.addInplace(deltaToCorner);
}
}
// Place from corner to end
const pathFromCorner = mouseTile.sub(this.currentDirectionLockCorner);
const deltaFromCorner = pathFromCorner.normalize().round();
const lengthFromCorner = Math_round(pathFromCorner.length());
if (lengthFromCorner > 0) {
rotation = (Math.round(Math_degrees(deltaFromCorner.angle()) / 90) * 90 + 360) % 360;
for (let i = 0; i < lengthFromCorner + 1; ++i) {
result.push({
tile: currentPos.copy(),
rotation,
});
currentPos.addInplace(deltaFromCorner);
}
} else {
// Finish last one
result.push({
tile: currentPos.copy(),
rotation,
});
}
return result;
}
/**
* Selects a given building
* @param {MetaBuilding} metaBuilding
*/
startSelection(metaBuilding) {
this.currentMetaBuilding.set(metaBuilding);
}
/**
* Called when the selected buildings changed
* @param {MetaBuilding} metaBuilding
*/
onSelectedMetaBuildingChanged(metaBuilding) {
this.abortDragging();
this.root.hud.signals.selectedPlacementBuildingChanged.dispatch(metaBuilding);
if (metaBuilding) {
const variant = this.preferredVariants[metaBuilding.getId()] || defaultBuildingVariant;
this.currentVariant.set(variant);
this.fakeEntity = new Entity(null);
metaBuilding.setupEntityComponents(this.fakeEntity, null);
this.fakeEntity.addComponent(
new StaticMapEntityComponent({
origin: new Vector(0, 0),
rotation: 0,
tileSize: metaBuilding.getDimensions(this.currentVariant.get()).copy(),
blueprintSpriteKey: "",
})
);
metaBuilding.updateVariants(this.fakeEntity, 0, this.currentVariant.get());
} else {
this.fakeEntity = null;
}
// Since it depends on both, rerender twice
this.signals.variantChanged.dispatch();
}
/**
* mouse down pre handler
* @param {Vector} pos
* @param {enumMouseButton} button
*/
onMouseDown(pos, button) {
if (this.root.camera.getIsMapOverlayActive()) {
// We do not allow dragging if the overlay is active
return;
}
const metaBuilding = this.currentMetaBuilding.get();
// Placement
if (button === enumMouseButton.left && metaBuilding) {
this.currentlyDragging = true;
this.currentlyDeleting = false;
this.lastDragTile = this.root.camera.screenToWorld(pos).toTileSpace();
// Place initial building, but only if direction lock is not active
if (!this.isDirectionLockActive) {
this.tryPlaceCurrentBuildingAt(this.lastDragTile);
}
return STOP_PROPAGATION;
}
// Deletion
if (button === enumMouseButton.right && !metaBuilding) {
this.currentlyDragging = true;
this.currentlyDeleting = true;
this.lastDragTile = this.root.camera.screenToWorld(pos).toTileSpace();
this.deleteBelowCursor();
return STOP_PROPAGATION;
}
// Cancel placement
if (button === enumMouseButton.right && metaBuilding) {
this.currentMetaBuilding.set(null);
}
}
/**
* mouse move pre handler
* @param {Vector} pos
*/
onMouseMove(pos) {
if (this.root.camera.getIsMapOverlayActive()) {
return;
}
// Check for direction lock
if (this.isDirectionLockActive) {
return;
}
const metaBuilding = this.currentMetaBuilding.get();
if ((metaBuilding || this.currentlyDeleting) && this.lastDragTile) {
const oldPos = this.lastDragTile;
let newPos = this.root.camera.screenToWorld(pos).toTileSpace();
// Check if camera is moving, since then we do nothing
if (this.root.camera.desiredCenter) {
this.lastDragTile = newPos;
return;
}
// Check if anything changed
if (!oldPos.equals(newPos)) {
// Automatic Direction
if (
metaBuilding &&
metaBuilding.getRotateAutomaticallyWhilePlacing(this.currentVariant.get()) &&
!this.root.keyMapper.getBinding(
KEYMAPPINGS.placementModifiers.placementDisableAutoOrientation
).pressed
) {
const delta = newPos.sub(oldPos);
const angleDeg = Math_degrees(delta.angle());
this.currentBaseRotation = (Math.round(angleDeg / 90) * 90 + 360) % 360;
// Holding alt inverts the placement
if (this.root.keyMapper.getBinding(KEYMAPPINGS.placementModifiers.placeInverse).pressed) {
this.currentBaseRotation = (180 + this.currentBaseRotation) % 360;
}
}
// bresenham
let x0 = oldPos.x;
let y0 = oldPos.y;
let x1 = newPos.x;
let y1 = newPos.y;
var dx = Math_abs(x1 - x0);
var dy = Math_abs(y1 - y0);
var sx = x0 < x1 ? 1 : -1;
var sy = y0 < y1 ? 1 : -1;
var err = dx - dy;
while (this.currentlyDeleting || this.currentMetaBuilding.get()) {
if (this.currentlyDeleting) {
const contents = this.root.map.getTileContentXY(x0, y0);
if (contents && !contents.queuedForDestroy && !contents.destroyed) {
this.root.logic.tryDeleteBuilding(contents);
}
} else {
this.tryPlaceCurrentBuildingAt(new Vector(x0, y0));
}
if (x0 === x1 && y0 === y1) break;
var e2 = 2 * err;
if (e2 > -dy) {
err -= dy;
x0 += sx;
}
if (e2 < dx) {
err += dx;
y0 += sy;
}
}
}
this.lastDragTile = newPos;
return STOP_PROPAGATION;
}
}
/**
* Mouse up handler
*/
onMouseUp() {
if (this.root.camera.getIsMapOverlayActive()) {
return;
}
// Check for direction lock
if (this.lastDragTile && this.currentlyDragging && this.isDirectionLockActive) {
this.executeDirectionLockedPlacement();
}
this.abortDragging();
}
}

View File

@ -1,102 +1,316 @@
import { makeDiv } from "../../../core/utils"; import { makeDiv } from "../../../core/utils";
import { T } from "../../../translations"; import { T } from "../../../translations";
import { getStringForKeyCode, KEYMAPPINGS } from "../../key_action_mapper"; import {
getStringForKeyCode,
KEYCODE_LMB,
KEYCODE_MMB,
KEYCODE_RMB,
KEYMAPPINGS,
} from "../../key_action_mapper";
import { BaseHUDPart } from "../base_hud_part"; import { BaseHUDPart } from "../base_hud_part";
import { TrackedState } from "../../../core/tracked_state"; import { DynamicDomAttach } from "../dynamic_dom_attach";
const DIVIDER_TOKEN = "/";
const ADDER_TOKEN = "+";
/**
* @typedef {{ keyCode: number }} KeyCode
*/
/**
* @typedef {{
* condition: () => boolean,
* keys: Array<KeyCode|number|string>,
* label: string,
* cachedElement?: HTMLElement,
* cachedVisibility?: boolean
* }} KeyBinding
*/
export class HUDKeybindingOverlay extends BaseHUDPart { export class HUDKeybindingOverlay extends BaseHUDPart {
initialize() { initialize() {}
this.root.hud.signals.selectedPlacementBuildingChanged.add(
this.onSelectedBuildingForPlacementChanged,
this
);
this.trackedMapOverviewActive = new TrackedState(this.applyCssClasses, this); /**
* HELPER / Returns if there is a building selected for placement
* @returns {boolean}
*/
get buildingPlacementActive() {
const placer = this.root.hud.parts.buildingPlacer;
return !this.mapOverviewActive && placer && !!placer.currentMetaBuilding.get();
} }
/**
* HELPER / Returns if there is a building selected for placement and
* it supports the belt planner
* @returns {boolean}
*/
get buildingPlacementSupportsBeltPlanner() {
const placer = this.root.hud.parts.buildingPlacer;
return (
!this.mapOverviewActive &&
placer &&
placer.currentMetaBuilding.get() &&
placer.currentMetaBuilding.get().getHasDirectionLockAvailable()
);
}
/**
* HELPER / Returns if there is a building selected for placement and
* it has multiplace enabled by default
* @returns {boolean}
*/
get buildingPlacementStaysInPlacement() {
const placer = this.root.hud.parts.buildingPlacer;
return (
!this.mapOverviewActive &&
placer &&
placer.currentMetaBuilding.get() &&
placer.currentMetaBuilding.get().getStayInPlacementMode()
);
}
/**
* HELPER / Returns if there is a blueprint selected for placement
* @returns {boolean}
*/
get blueprintPlacementActive() {
const placer = this.root.hud.parts.blueprintPlacer;
return placer && !!placer.currentBlueprint.get();
}
/**
* HELPER / Returns if the belt planner is currently active
* @returns {boolean}
*/
get beltPlannerActive() {
const placer = this.root.hud.parts.buildingPlacer;
return !this.mapOverviewActive && placer && placer.isDirectionLockActive;
}
/**
* HELPER / Returns if there is a last blueprint available
* @returns {boolean}
*/
get lastBlueprintAvailable() {
const placer = this.root.hud.parts.blueprintPlacer;
return placer && !!placer.lastBlueprintUsed;
}
/**
* HELPER / Returns if there is anything selected on the map
* @returns {boolean}
*/
get anythingSelectedOnMap() {
const selector = this.root.hud.parts.massSelector;
return selector && selector.selectedUids.size > 0;
}
/**
* HELPER / Returns if there is a building or blueprint selected for placement
* @returns {boolean}
*/
get anyPlacementActive() {
return this.buildingPlacementActive || this.blueprintPlacementActive;
}
/**
* HELPER / Returns if the map overview is active
* @returns {boolean}
*/
get mapOverviewActive() {
return this.root.camera.getIsMapOverlayActive();
}
/**
* Initializes the element
* @param {HTMLElement} parent
*/
createElements(parent) { createElements(parent) {
const mapper = this.root.keyMapper; const mapper = this.root.keyMapper;
const k = KEYMAPPINGS;
const getKeycode = id => { /** @type {Array<KeyBinding>} */
return getStringForKeyCode(mapper.getBinding(id).keyCode); this.keybindings = [
}; {
// Move map - Including mouse
label: T.ingame.keybindingsOverlay.moveMap,
keys: [
KEYCODE_LMB,
DIVIDER_TOKEN,
k.navigation.mapMoveUp,
k.navigation.mapMoveLeft,
k.navigation.mapMoveDown,
k.navigation.mapMoveRight,
],
condition: () => !this.anyPlacementActive,
},
this.element = makeDiv( {
parent, // Move map - No mouse
"ingame_HUD_KeybindingOverlay", label: T.ingame.keybindingsOverlay.moveMap,
[], keys: [
` k.navigation.mapMoveUp,
k.navigation.mapMoveLeft,
k.navigation.mapMoveDown,
k.navigation.mapMoveRight,
],
condition: () => this.anyPlacementActive,
},
<div class="binding"> {
<code class="keybinding leftMouse noPlacementOnly"></code><i class="noPlacementOnly"></i> // [OVERVIEW] Create marker with right click
<code class="keybinding">${getKeycode(KEYMAPPINGS.navigation.mapMoveUp)}</code> label: T.ingame.keybindingsOverlay.createMarker,
<code class="keybinding">${getKeycode(KEYMAPPINGS.navigation.mapMoveLeft)}</code> keys: [KEYCODE_RMB],
<code class="keybinding">${getKeycode(KEYMAPPINGS.navigation.mapMoveDown)}</code> condition: () => this.mapOverviewActive && !this.blueprintPlacementActive,
<code class="keybinding">${getKeycode(KEYMAPPINGS.navigation.mapMoveRight)}</code> },
<label>${T.ingame.keybindingsOverlay.moveMap}</label>
</div>
{
// Pipette
label: T.ingame.keybindingsOverlay.pipette,
keys: [k.placement.pipette],
condition: () => !this.mapOverviewActive && !this.blueprintPlacementActive,
},
{
// Cancel placement
label: T.ingame.keybindingsOverlay.stopPlacement,
keys: [KEYCODE_RMB],
condition: () => this.anyPlacementActive,
},
<div class="binding noPlacementOnly noOverviewOnly"> {
<code class="keybinding rightMouse"></code> // Delete with right click
<label>${T.ingame.keybindingsOverlay.delete}</label> label: T.ingame.keybindingsOverlay.delete,
</div> keys: [KEYCODE_RMB],
condition: () =>
!this.anyPlacementActive && !this.mapOverviewActive && !this.anythingSelectedOnMap,
},
<div class="binding noPlacementOnly overviewOnly"> {
<code class="keybinding rightMouse"></code> // Area select
<label>${T.ingame.keybindingsOverlay.createMarker}</label> label: T.ingame.keybindingsOverlay.selectBuildings,
</div> keys: [k.massSelect.massSelectStart, ADDER_TOKEN, KEYCODE_LMB],
condition: () => !this.anyPlacementActive && !this.anythingSelectedOnMap,
},
{
// Place building
label: T.ingame.keybindingsOverlay.placeBuilding,
keys: [KEYCODE_LMB],
condition: () => this.anyPlacementActive,
},
<div class="binding noPlacementOnly"> {
<code class="keybinding builtinKey">${getKeycode( // Rotate
KEYMAPPINGS.massSelect.massSelectStart label: T.ingame.keybindingsOverlay.rotateBuilding,
)}</code>+ keys: [k.placement.rotateWhilePlacing],
<code class="keybinding leftMouse"></code> condition: () => this.anyPlacementActive && !this.beltPlannerActive,
<label>${T.ingame.keybindingsOverlay.selectBuildings}</label> },
</div>
<div class="binding placementOnly"> {
<code class="keybinding leftMouse"></code> // [BELT PLANNER] Flip Side
<label>${T.ingame.keybindingsOverlay.placeBuilding}</label> label: T.ingame.keybindingsOverlay.plannerSwitchSide,
</div> keys: [k.placement.switchDirectionLockSide],
condition: () => this.beltPlannerActive,
},
<div class="binding placementOnly"> {
<code class="keybinding rightMouse"></code><i></i> // Place last blueprint
<code class="keybinding">${getKeycode(KEYMAPPINGS.placement.abortBuildingPlacement)}</code> label: T.ingame.keybindingsOverlay.pasteLastBlueprint,
<label>${T.ingame.keybindingsOverlay.stopPlacement}</label> keys: [k.massSelect.pasteLastBlueprint],
</div> condition: () => !this.blueprintPlacementActive && this.lastBlueprintAvailable,
},
<div class="binding placementOnly"> {
<code class="keybinding">${getKeycode(KEYMAPPINGS.placement.rotateWhilePlacing)}</code> // Belt planner
<label>${T.ingame.keybindingsOverlay.rotateBuilding}</label> label: T.ingame.keybindingsOverlay.lockBeltDirection,
</div> keys: [k.placementModifiers.lockBeltDirection],
condition: () => this.buildingPlacementSupportsBeltPlanner && !this.beltPlannerActive,
},
` + {
(this.root.app.settings.getAllSettings().alwaysMultiplace // [SELECTION] Destroy
? "" label: T.ingame.keybindingsOverlay.delete,
: ` keys: [k.massSelect.confirmMassDelete],
<div class="binding placementOnly"> condition: () => this.anythingSelectedOnMap,
<code class="keybinding builtinKey shift">${getKeycode( },
KEYMAPPINGS.placementModifiers.placeMultiple
)}</code> {
<label>${T.ingame.keybindingsOverlay.placeMultiple}</label> // [SELECTION] Cancel
</div>`) + label: T.ingame.keybindingsOverlay.clearSelection,
` keys: [k.general.back],
` condition: () => this.anythingSelectedOnMap,
); },
{
// [SELECTION] Cut
label: T.ingame.keybindingsOverlay.cutSelection,
keys: [k.massSelect.massSelectCut],
condition: () => this.anythingSelectedOnMap,
},
{
// [SELECTION] Copy
label: T.ingame.keybindingsOverlay.copySelection,
keys: [k.massSelect.massSelectCopy],
condition: () => this.anythingSelectedOnMap,
},
];
if (!this.root.app.settings.getAllSettings().alwaysMultiplace) {
this.keybindings.push({
// Multiplace
label: T.ingame.keybindingsOverlay.placeMultiple,
keys: [k.placementModifiers.placeMultiple],
condition: () => this.anyPlacementActive && !this.buildingPlacementStaysInPlacement,
});
} }
onSelectedBuildingForPlacementChanged(selectedMetaBuilding) { this.element = makeDiv(parent, "ingame_HUD_KeybindingOverlay", []);
this.element.classList.toggle("placementActive", !!selectedMetaBuilding);
}
applyCssClasses() { for (let i = 0; i < this.keybindings.length; ++i) {
this.element.classList.toggle("mapOverviewActive", this.root.camera.getIsMapOverlayActive()); let html = "";
const handle = this.keybindings[i];
for (let k = 0; k < handle.keys.length; ++k) {
const key = handle.keys[k];
switch (key) {
case KEYCODE_LMB:
html += `<code class="keybinding leftMouse"></code>`;
break;
case KEYCODE_RMB:
html += `<code class="keybinding rightMouse"></code>`;
break;
case KEYCODE_MMB:
html += `<code class="keybinding middleMouse"></code>`;
break;
case DIVIDER_TOKEN:
html += `<i></i>`;
break;
case ADDER_TOKEN:
html += `+`;
break;
default:
html += `<code class="keybinding">${getStringForKeyCode(
mapper.getBinding(/** @type {KeyCode} */ (key)).keyCode
)}</code>`;
}
}
html += `<label>${handle.label}</label>`;
handle.cachedElement = makeDiv(this.element, null, ["binding"], html);
handle.cachedVisibility = false;
}
} }
update() { update() {
this.trackedMapOverviewActive.set(this.root.camera.getIsMapOverlayActive()); for (let i = 0; i < this.keybindings.length; ++i) {
const handle = this.keybindings[i];
const visibility = handle.condition();
if (visibility !== handle.cachedVisibility) {
handle.cachedVisibility = visibility;
handle.cachedElement.classList.toggle("visible", visibility);
}
}
} }
} }

View File

@ -17,29 +17,7 @@ import { enumHubGoalRewards } from "../../tutorial_goals";
const logger = createLogger("hud/mass_selector"); const logger = createLogger("hud/mass_selector");
export class HUDMassSelector extends BaseHUDPart { export class HUDMassSelector extends BaseHUDPart {
createElements(parent) { createElements(parent) {}
const removalKeybinding = this.root.keyMapper
.getBinding(KEYMAPPINGS.massSelect.confirmMassDelete)
.getKeyCodeString();
const abortKeybinding = this.root.keyMapper.getBinding(KEYMAPPINGS.general.back).getKeyCodeString();
const cutKeybinding = this.root.keyMapper
.getBinding(KEYMAPPINGS.massSelect.massSelectCut)
.getKeyCodeString();
const copyKeybinding = this.root.keyMapper
.getBinding(KEYMAPPINGS.massSelect.massSelectCopy)
.getKeyCodeString();
this.element = makeDiv(
parent,
"ingame_HUD_MassSelector",
[],
T.ingame.massSelect.infoText
.replace("<keyDelete>", `<code class='keybinding'>${removalKeybinding}</code>`)
.replace("<keyCut>", `<code class='keybinding'>${cutKeybinding}</code>`)
.replace("<keyCopy>", `<code class='keybinding'>${copyKeybinding}</code>`)
.replace("<keyCancel>", `<code class='keybinding'>${abortKeybinding}</code>`)
);
}
initialize() { initialize() {
this.deletionMarker = Loader.getSprite("sprites/misc/deletion_marker.png"); this.deletionMarker = Loader.getSprite("sprites/misc/deletion_marker.png");
@ -49,6 +27,7 @@ export class HUDMassSelector extends BaseHUDPart {
this.selectedUids = new Set(); this.selectedUids = new Set();
this.root.signals.entityQueuedForDestroy.add(this.onEntityDestroyed, this); this.root.signals.entityQueuedForDestroy.add(this.onEntityDestroyed, this);
this.root.hud.signals.pasteBlueprintRequested.add(this.clearSelection, this);
this.root.camera.downPreHandler.add(this.onMouseDown, this); this.root.camera.downPreHandler.add(this.onMouseDown, this);
this.root.camera.movePreHandler.add(this.onMouseMove, this); this.root.camera.movePreHandler.add(this.onMouseMove, this);
@ -61,7 +40,7 @@ export class HUDMassSelector extends BaseHUDPart {
this.root.keyMapper.getBinding(KEYMAPPINGS.massSelect.massSelectCut).add(this.confirmCut, this); this.root.keyMapper.getBinding(KEYMAPPINGS.massSelect.massSelectCut).add(this.confirmCut, this);
this.root.keyMapper.getBinding(KEYMAPPINGS.massSelect.massSelectCopy).add(this.startCopy, this); this.root.keyMapper.getBinding(KEYMAPPINGS.massSelect.massSelectCopy).add(this.startCopy, this);
this.domAttach = new DynamicDomAttach(this.root, this.element); this.root.hud.signals.selectedPlacementBuildingChanged.add(this.clearSelection, this);
} }
/** /**
@ -83,15 +62,25 @@ export class HUDMassSelector extends BaseHUDPart {
} }
} }
/**
* Clears the entire selection
*/
clearSelection() {
this.selectedUids = new Set();
}
confirmDelete() { confirmDelete() {
if (this.selectedUids.size > 100) { if (
!this.root.app.settings.getAllSettings().disableCutDeleteWarnings &&
this.selectedUids.size > 100
) {
const { ok } = this.root.hud.parts.dialogs.showWarning( const { ok } = this.root.hud.parts.dialogs.showWarning(
T.dialogs.massDeleteConfirm.title, T.dialogs.massDeleteConfirm.title,
T.dialogs.massDeleteConfirm.desc.replace( T.dialogs.massDeleteConfirm.desc.replace(
"<count>", "<count>",
"" + formatBigNumberFull(this.selectedUids.size) "" + formatBigNumberFull(this.selectedUids.size)
), ),
["cancel:good", "ok:bad"] ["cancel:good:escape", "ok:bad:enter"]
); );
ok.add(() => this.doDelete()); ok.add(() => this.doDelete());
} else { } else {
@ -134,14 +123,17 @@ export class HUDMassSelector extends BaseHUDPart {
T.dialogs.blueprintsNotUnlocked.title, T.dialogs.blueprintsNotUnlocked.title,
T.dialogs.blueprintsNotUnlocked.desc T.dialogs.blueprintsNotUnlocked.desc
); );
} else if (this.selectedUids.size > 100) { } else if (
!this.root.app.settings.getAllSettings().disableCutDeleteWarnings &&
this.selectedUids.size > 100
) {
const { ok } = this.root.hud.parts.dialogs.showWarning( const { ok } = this.root.hud.parts.dialogs.showWarning(
T.dialogs.massCutConfirm.title, T.dialogs.massCutConfirm.title,
T.dialogs.massCutConfirm.desc.replace( T.dialogs.massCutConfirm.desc.replace(
"<count>", "<count>",
"" + formatBigNumberFull(this.selectedUids.size) "" + formatBigNumberFull(this.selectedUids.size)
), ),
["cancel:good", "ok:bad"] ["cancel:good:escape", "ok:bad:enter"]
); );
ok.add(() => this.doCut()); ok.add(() => this.doCut());
} else { } else {
@ -177,7 +169,7 @@ export class HUDMassSelector extends BaseHUDPart {
* @param {enumMouseButton} mouseButton * @param {enumMouseButton} mouseButton
*/ */
onMouseDown(pos, mouseButton) { onMouseDown(pos, mouseButton) {
if (!this.root.keyMapper.getBinding(KEYMAPPINGS.massSelect.massSelectStart).isCurrentlyPressed()) { if (!this.root.keyMapper.getBinding(KEYMAPPINGS.massSelect.massSelectStart).pressed) {
return; return;
} }
@ -185,11 +177,7 @@ export class HUDMassSelector extends BaseHUDPart {
return; return;
} }
if ( if (!this.root.keyMapper.getBinding(KEYMAPPINGS.massSelect.massSelectSelectMultiple).pressed) {
!this.root.keyMapper
.getBinding(KEYMAPPINGS.massSelect.massSelectSelectMultiple)
.isCurrentlyPressed()
) {
// Start new selection // Start new selection
this.selectedUids = new Set(); this.selectedUids = new Set();
} }
@ -234,10 +222,6 @@ export class HUDMassSelector extends BaseHUDPart {
} }
} }
update() {
this.domAttach.update(this.selectedUids.size > 0);
}
/** /**
* *
* @param {DrawParameters} parameters * @param {DrawParameters} parameters

View File

@ -5,7 +5,7 @@ import { T } from "../../../translations";
import { createLogger } from "../../../core/logging"; import { createLogger } from "../../../core/logging";
import { StaticMapEntityComponent } from "../../components/static_map_entity"; import { StaticMapEntityComponent } from "../../components/static_map_entity";
import { Vector } from "../../../core/vector"; import { Vector } from "../../../core/vector";
import { Math_max, Math_min } from "../../../core/builtins"; import { Math_max, Math_min, Math_floor } from "../../../core/builtins";
import { makeOffscreenBuffer } from "../../../core/buffer_utils"; import { makeOffscreenBuffer } from "../../../core/buffer_utils";
import { DrawParameters } from "../../../core/draw_parameters"; import { DrawParameters } from "../../../core/draw_parameters";
import { Rectangle } from "../../../core/rectangle"; import { Rectangle } from "../../../core/rectangle";
@ -56,7 +56,14 @@ export class HUDScreenshotExporter extends BaseHUDPart {
const dimensions = maxChunk.sub(minChunk); const dimensions = maxChunk.sub(minChunk);
logger.log("Dimensions:", dimensions); logger.log("Dimensions:", dimensions);
const chunkSizePixels = 128; let chunkSizePixels = 128;
const maxDimensions = Math_max(dimensions.x, dimensions.y);
if (maxDimensions > 128) {
chunkSizePixels = Math_max(1, Math_floor(128 * (128 / maxDimensions)));
}
logger.log("ChunkSizePixels:", chunkSizePixels);
const chunkScale = chunkSizePixels / (globalConfig.mapChunkSize * globalConfig.tileSize); const chunkScale = chunkSizePixels / (globalConfig.mapChunkSize * globalConfig.tileSize);
logger.log("Scale:", chunkScale); logger.log("Scale:", chunkScale);

View File

@ -1,5 +1,5 @@
import { makeOffscreenBuffer } from "../../../core/buffer_utils"; import { makeOffscreenBuffer } from "../../../core/buffer_utils";
import { Math_max } from "../../../core/builtins"; import { Math_max, Math_PI, Math_radians } from "../../../core/builtins";
import { globalConfig, IS_DEMO } from "../../../core/config"; import { globalConfig, IS_DEMO } from "../../../core/config";
import { DrawParameters } from "../../../core/draw_parameters"; import { DrawParameters } from "../../../core/draw_parameters";
import { Loader } from "../../../core/loader"; import { Loader } from "../../../core/loader";
@ -7,7 +7,7 @@ import { DialogWithForm } from "../../../core/modal_dialog_elements";
import { FormElementInput } from "../../../core/modal_dialog_forms"; import { FormElementInput } from "../../../core/modal_dialog_forms";
import { Rectangle } from "../../../core/rectangle"; import { Rectangle } from "../../../core/rectangle";
import { STOP_PROPAGATION } from "../../../core/signal"; import { STOP_PROPAGATION } from "../../../core/signal";
import { arrayDeleteValue, lerp, makeDiv, removeAllChildren } from "../../../core/utils"; import { arrayDeleteValue, lerp, makeDiv, removeAllChildren, clamp } from "../../../core/utils";
import { Vector } from "../../../core/vector"; import { Vector } from "../../../core/vector";
import { T } from "../../../translations"; import { T } from "../../../translations";
import { enumMouseButton } from "../../camera"; import { enumMouseButton } from "../../camera";
@ -15,16 +15,28 @@ import { KEYMAPPINGS } from "../../key_action_mapper";
import { BaseHUDPart } from "../base_hud_part"; import { BaseHUDPart } from "../base_hud_part";
import { DynamicDomAttach } from "../dynamic_dom_attach"; import { DynamicDomAttach } from "../dynamic_dom_attach";
import { enumNotificationType } from "./notifications"; import { enumNotificationType } from "./notifications";
import { ShapeDefinition } from "../../shape_definition";
/** @typedef {{ /** @typedef {{
* label: string, * label: string | null,
* center: { x: number, y: number }, * center: { x: number, y: number },
* zoomLevel: number, * zoomLevel: number
* deletable: boolean
* }} Waypoint */ * }} Waypoint */
/**
* Used when a shape icon is rendered instead
*/
const SHAPE_LABEL_PLACEHOLDER = " ";
const MAX_LABEL_LENGTH = 71;
export class HUDWaypoints extends BaseHUDPart { export class HUDWaypoints extends BaseHUDPart {
/**
* Creates the overview of waypoints
* @param {HTMLElement} parent
*/
createElements(parent) { createElements(parent) {
// Create the helper box on the lower right when zooming out
if (this.root.app.settings.getAllSettings().offerHints) { if (this.root.app.settings.getAllSettings().offerHints) {
this.hintElement = makeDiv( this.hintElement = makeDiv(
parent, parent,
@ -42,17 +54,23 @@ export class HUDWaypoints extends BaseHUDPart {
); );
} }
this.waypointSprite = Loader.getSprite("sprites/misc/waypoint.png"); // Create the waypoint list on the upper right
this.waypointsListElement = makeDiv(parent, "ingame_HUD_Waypoints", [], "Waypoints"); this.waypointsListElement = makeDiv(parent, "ingame_HUD_Waypoints", [], "Waypoints");
} }
/**
* Serializes the waypoints
*/
serialize() { serialize() {
return { return {
waypoints: this.waypoints, waypoints: this.waypoints,
}; };
} }
/**
* Deserializes the waypoints
* @param {{waypoints: Array<Waypoint>}} data
*/
deserialize(data) { deserialize(data) {
if (!data || !data.waypoints || !Array.isArray(data.waypoints)) { if (!data || !data.waypoints || !Array.isArray(data.waypoints)) {
return "Invalid waypoints data"; return "Invalid waypoints data";
@ -61,21 +79,97 @@ export class HUDWaypoints extends BaseHUDPart {
this.rerenderWaypointList(); this.rerenderWaypointList();
} }
/**
* Initializes everything
*/
initialize() {
// Cache the sprite for the waypoints
this.waypointSprite = Loader.getSprite("sprites/misc/waypoint.png");
this.directionIndicatorSprite = Loader.getSprite("sprites/misc/hub_direction_indicator.png");
/** @type {Array<Waypoint>}
*/
this.waypoints = [
{
label: null,
center: { x: 0, y: 0 },
zoomLevel: 3,
},
];
// Create a buffer we can use to measure text
this.dummyBuffer = makeOffscreenBuffer(1, 1, {
reusable: false,
label: "waypoints-measure-canvas",
})[1];
// Dynamically attach/detach the lower right hint in the map overview
if (this.hintElement) {
this.domAttach = new DynamicDomAttach(this.root, this.hintElement);
}
// Catch mouse and key events
this.root.camera.downPreHandler.add(this.onMouseDown, this);
this.root.keyMapper
.getBinding(KEYMAPPINGS.navigation.createMarker)
.add(this.requestCreateMarker, this);
/**
* Stores at how much opacity the markers should be rendered on the map.
* This is interpolated over multiple frames so we have some sort of fade effect
*/
this.currentMarkerOpacity = 1;
this.currentCompassOpacity = 0;
// Create buffer which is used to indicate the hub direction
const [canvas, context] = makeOffscreenBuffer(48, 48, {
smooth: true,
reusable: false,
label: "waypoints-compass",
});
this.compassBuffer = { canvas, context };
/**
* Stores a cache from a shape short key to its canvas representation
*/
this.cachedKeyToCanvas = {};
// Initial render
this.rerenderWaypointList();
}
/**
* Re-renders the waypoint list to account for changes
*/
rerenderWaypointList() { rerenderWaypointList() {
removeAllChildren(this.waypointsListElement); removeAllChildren(this.waypointsListElement);
this.cleanupClickDetectors(); this.cleanupClickDetectors();
for (let i = 0; i < this.waypoints.length; ++i) { for (let i = 0; i < this.waypoints.length; ++i) {
const waypoint = this.waypoints[i]; const waypoint = this.waypoints[i];
const label = this.getWaypointLabel(waypoint);
const element = makeDiv(this.waypointsListElement, null, ["waypoint"]); const element = makeDiv(this.waypointsListElement, null, ["waypoint"]);
element.innerText = waypoint.label;
if (waypoint.deletable) { if (ShapeDefinition.isValidShortKey(label)) {
const canvas = this.getWaypointCanvas(waypoint);
element.appendChild(canvas);
element.classList.add("shapeIcon");
} else {
element.innerText = label;
}
if (this.isWaypointDeletable(waypoint)) {
const deleteButton = makeDiv(element, null, ["deleteButton"]); const deleteButton = makeDiv(element, null, ["deleteButton"]);
this.trackClicks(deleteButton, () => this.deleteWaypoint(waypoint)); this.trackClicks(deleteButton, () => this.deleteWaypoint(waypoint));
} }
if (!waypoint.label) {
// This must be the hub label
element.classList.add("hub");
element.insertBefore(this.compassBuffer.canvas, element.childNodes[0]);
}
this.trackClicks(element, () => this.moveToWaypoint(waypoint), { this.trackClicks(element, () => this.moveToWaypoint(waypoint), {
targetOnly: true, targetOnly: true,
}); });
@ -83,6 +177,7 @@ export class HUDWaypoints extends BaseHUDPart {
} }
/** /**
* Moves the camera to a given waypoint
* @param {Waypoint} waypoint * @param {Waypoint} waypoint
*/ */
moveToWaypoint(waypoint) { moveToWaypoint(waypoint) {
@ -91,6 +186,7 @@ export class HUDWaypoints extends BaseHUDPart {
} }
/** /**
* Deletes a waypoint from the list
* @param {Waypoint} waypoint * @param {Waypoint} waypoint
*/ */
deleteWaypoint(waypoint) { deleteWaypoint(waypoint) {
@ -98,86 +194,132 @@ export class HUDWaypoints extends BaseHUDPart {
this.rerenderWaypointList(); this.rerenderWaypointList();
} }
initialize() { /**
/** @type {Array<Waypoint>} * Gets the canvas for a given waypoint
* @param {Waypoint} waypoint
* @returns {HTMLCanvasElement}
*/ */
this.waypoints = [ getWaypointCanvas(waypoint) {
{ const key = waypoint.label;
label: T.ingame.waypoints.hub, if (this.cachedKeyToCanvas[key]) {
center: { x: 0, y: 0 }, return this.cachedKeyToCanvas[key];
zoomLevel: 3,
deletable: false,
},
];
this.dummyBuffer = makeOffscreenBuffer(1, 1, {
reusable: false,
label: "waypoints-measure-canvas",
})[1];
this.root.camera.downPreHandler.add(this.onMouseDown, this);
if (this.hintElement) {
this.domAttach = new DynamicDomAttach(this.root, this.hintElement);
} }
this.root.keyMapper assert(ShapeDefinition.isValidShortKey(key), "Invalid short key: " + key);
.getBinding(KEYMAPPINGS.navigation.createMarker) const definition = ShapeDefinition.fromShortKey(key);
.add(this.requestCreateMarker, this); const preRendered = definition.generateAsCanvas(48);
return (this.cachedKeyToCanvas[key] = preRendered);
this.currentMarkerOpacity = 1;
this.rerenderWaypointList();
} }
/** /**
* Requests to create a marker at the current camera position. If worldPos is set,
* uses that position instead.
* @param {Vector=} worldPos Override the world pos, otherwise it is the camera position * @param {Vector=} worldPos Override the world pos, otherwise it is the camera position
*/ */
requestCreateMarker(worldPos = null) { requestCreateMarker(worldPos = null) {
// Construct dialog with input field
const markerNameInput = new FormElementInput({ const markerNameInput = new FormElementInput({
id: "markerName", id: "markerName",
label: null, label: null,
placeholder: "", placeholder: "",
validator: val => val.length > 0 && val.length < 15, validator: val =>
val.length > 0 && (val.length < MAX_LABEL_LENGTH || ShapeDefinition.isValidShortKey(val)),
}); });
const dialog = new DialogWithForm({ const dialog = new DialogWithForm({
app: this.root.app, app: this.root.app,
title: T.dialogs.createMarker.title, title: T.dialogs.createMarker.title,
desc: T.dialogs.createMarker.desc, desc: T.dialogs.createMarker.desc,
formElements: [markerNameInput], formElements: [markerNameInput],
}); });
this.root.hud.parts.dialogs.internalShowDialog(dialog); this.root.hud.parts.dialogs.internalShowDialog(dialog);
// Compute where to create the marker
const center = worldPos || this.root.camera.center; const center = worldPos || this.root.camera.center;
dialog.buttonSignals.ok.add(() => { dialog.buttonSignals.ok.add(() => {
// Show info that you can have only N markers in the demo,
// actually show this *after* entering the name so you want the
// standalone even more (I'm evil :P)
if (IS_DEMO && this.waypoints.length > 2) { if (IS_DEMO && this.waypoints.length > 2) {
this.root.hud.parts.dialogs.showFeatureRestrictionInfo("", T.dialogs.markerDemoLimit.desc); this.root.hud.parts.dialogs.showFeatureRestrictionInfo("", T.dialogs.markerDemoLimit.desc);
return; return;
} }
this.waypoints.push({ // Actually create the waypoint
label: markerNameInput.getValue(), this.addWaypoint(markerNameInput.getValue(), center);
center: { x: center.x, y: center.y },
zoomLevel: Math_max(this.root.camera.zoomLevel, globalConfig.mapChunkOverviewMinZoom + 0.05),
deletable: true,
}); });
this.waypoints.sort((a, b) => a.label.padStart(20, "0").localeCompare(b.label.padStart(20, "0"))); }
/**
* Adds a new waypoint at the given location with the given label
* @param {string} label
* @param {Vector} position
*/
addWaypoint(label, position) {
this.waypoints.push({
label,
center: { x: position.x, y: position.y },
// Make sure the zoom is *just* a bit above the zoom level where the map overview
// starts, so you always see all buildings
zoomLevel: Math_max(this.root.camera.zoomLevel, globalConfig.mapChunkOverviewMinZoom + 0.05),
});
// Sort waypoints by name
this.waypoints.sort((a, b) => {
if (!a.label) {
return -1;
}
if (!b.label) {
return 1;
}
return this.getWaypointLabel(a)
.padEnd(MAX_LABEL_LENGTH, "0")
.localeCompare(this.getWaypointLabel(b).padEnd(MAX_LABEL_LENGTH, "0"));
});
// Show notification about creation
this.root.hud.signals.notification.dispatch( this.root.hud.signals.notification.dispatch(
T.ingame.waypoints.creationSuccessNotification, T.ingame.waypoints.creationSuccessNotification,
enumNotificationType.success enumNotificationType.success
); );
// Re-render the list and thus add it
this.rerenderWaypointList(); this.rerenderWaypointList();
});
} }
/**
* Called every frame to update stuff
*/
update() { update() {
if (this.domAttach) { if (this.domAttach) {
this.domAttach.update(this.root.camera.getIsMapOverlayActive()); this.domAttach.update(this.root.camera.getIsMapOverlayActive());
} }
} }
/**
* Returns the label for a given waypoint
* @param {Waypoint} waypoint
* @returns {string}
*/
getWaypointLabel(waypoint) {
return waypoint.label || T.ingame.waypoints.hub;
}
/**
* Returns if a waypoint is deletable
* @param {Waypoint} waypoint
* @returns {boolean}
*/
isWaypointDeletable(waypoint) {
return waypoint.label !== null;
}
/**
* Finds the currently intersected waypoint on the map overview under
* the cursor.
*
* @returns {Waypoint | null}
*/
findCurrentIntersectedWaypoint() { findCurrentIntersectedWaypoint() {
const mousePos = this.root.app.mousePosition; const mousePos = this.root.app.mousePosition;
if (!mousePos) { if (!mousePos) {
@ -197,10 +339,18 @@ export class HUDWaypoints extends BaseHUDPart {
const screenPos = this.root.camera.worldToScreen( const screenPos = this.root.camera.worldToScreen(
new Vector(waypoint.center.x, waypoint.center.y) new Vector(waypoint.center.x, waypoint.center.y)
); );
let label = this.getWaypointLabel(waypoint);
// Special case for icons
if (ShapeDefinition.isValidShortKey(label)) {
label = SHAPE_LABEL_PLACEHOLDER;
}
const intersectionRect = new Rectangle( const intersectionRect = new Rectangle(
screenPos.x - 7 * scale, screenPos.x - 7 * scale,
screenPos.y - 12 * scale, screenPos.y - 12 * scale,
15 * scale + this.dummyBuffer.measureText(waypoint.label).width, 15 * scale + this.dummyBuffer.measureText(label).width,
15 * scale 15 * scale
); );
if (intersectionRect.containsPoint(mousePos.x, mousePos.y)) { if (intersectionRect.containsPoint(mousePos.x, mousePos.y)) {
@ -210,7 +360,7 @@ export class HUDWaypoints extends BaseHUDPart {
} }
/** /**
* * Mouse-Down handler
* @param {Vector} pos * @param {Vector} pos
* @param {enumMouseButton} button * @param {enumMouseButton} button
*/ */
@ -221,7 +371,7 @@ export class HUDWaypoints extends BaseHUDPart {
this.root.soundProxy.playUiClick(); this.root.soundProxy.playUiClick();
this.moveToWaypoint(waypoint); this.moveToWaypoint(waypoint);
} else if (button === enumMouseButton.right) { } else if (button === enumMouseButton.right) {
if (waypoint.deletable) { if (this.isWaypointDeletable(waypoint)) {
this.root.soundProxy.playUiClick(); this.root.soundProxy.playUiClick();
this.deleteWaypoint(waypoint); this.deleteWaypoint(waypoint);
} else { } else {
@ -243,50 +393,111 @@ export class HUDWaypoints extends BaseHUDPart {
} }
/** /**
* * Rerenders the compass
*/
rerenderWaypointsCompass() {
const context = this.compassBuffer.context;
const dims = 48;
context.clearRect(0, 0, dims, dims);
const indicatorSize = 30;
const cameraPos = this.root.camera.center;
const distanceToHub = cameraPos.length();
const compassVisible = distanceToHub > (10 * globalConfig.tileSize) / this.root.camera.zoomLevel;
const targetCompassAlpha = compassVisible ? 1 : 0;
this.currentCompassOpacity = lerp(this.currentCompassOpacity, targetCompassAlpha, 0.08);
if (this.currentCompassOpacity > 0.01) {
context.globalAlpha = this.currentCompassOpacity;
const angle = cameraPos.angle() + Math_radians(45) + Math_PI / 2;
context.translate(dims / 2, dims / 2);
context.rotate(angle);
this.directionIndicatorSprite.drawCentered(context, 0, 0, indicatorSize);
context.rotate(-angle);
context.translate(-dims / 2, -dims / 2);
context.globalAlpha = 1;
}
const iconOpacity = 1 - this.currentCompassOpacity;
if (iconOpacity > 0.01) {
// Draw icon
context.globalAlpha = iconOpacity;
this.waypointSprite.drawCentered(context, dims / 2, dims / 2, dims * 0.7);
context.globalAlpha = 1;
}
}
/**
* Draws the waypoints on the map
* @param {DrawParameters} parameters * @param {DrawParameters} parameters
*/ */
draw(parameters) { draw(parameters) {
const desiredOpacity = this.root.camera.getIsMapOverlayActive() ? 1 : 0; const desiredOpacity = this.root.camera.getIsMapOverlayActive() ? 1 : 0;
this.currentMarkerOpacity = lerp(this.currentMarkerOpacity, desiredOpacity, 0.08); this.currentMarkerOpacity = lerp(this.currentMarkerOpacity, desiredOpacity, 0.08);
this.rerenderWaypointsCompass();
// Don't render with low opacity
if (this.currentMarkerOpacity < 0.01) { if (this.currentMarkerOpacity < 0.01) {
return; return;
} }
// Find waypoint below cursor
const selected = this.findCurrentIntersectedWaypoint(); const selected = this.findCurrentIntersectedWaypoint();
// Determine rendering scale
const scale = (1 / this.root.camera.zoomLevel) * this.root.app.getEffectiveUiScale(); const scale = (1 / this.root.camera.zoomLevel) * this.root.app.getEffectiveUiScale();
// Render all of 'em
for (let i = 0; i < this.waypoints.length; ++i) { for (let i = 0; i < this.waypoints.length; ++i) {
const waypoint = this.waypoints[i]; const waypoint = this.waypoints[i];
const pos = waypoint.center; const pos = waypoint.center;
parameters.context.globalAlpha = this.currentMarkerOpacity * (selected === waypoint ? 1 : 0.7); parameters.context.globalAlpha = this.currentMarkerOpacity * (selected === waypoint ? 1 : 0.7);
const yOffset = -5 * scale; const yOffset = -5 * scale;
const originalLabel = this.getWaypointLabel(waypoint);
let renderLabel = originalLabel;
let isShapeIcon = false;
if (ShapeDefinition.isValidShortKey(originalLabel)) {
renderLabel = SHAPE_LABEL_PLACEHOLDER;
isShapeIcon = true;
}
// Render the background rectangle
parameters.context.font = "bold " + 12 * scale + "px GameFont"; parameters.context.font = "bold " + 12 * scale + "px GameFont";
parameters.context.fillStyle = "rgba(255, 255, 255, 0.7)"; parameters.context.fillStyle = "rgba(255, 255, 255, 0.7)";
parameters.context.fillRect( parameters.context.fillRect(
pos.x - 7 * scale, pos.x - 7 * scale,
pos.y - 12 * scale, pos.y - 12 * scale,
15 * scale + this.dummyBuffer.measureText(waypoint.label).width / this.root.camera.zoomLevel, 15 * scale + this.dummyBuffer.measureText(renderLabel).width / this.root.camera.zoomLevel,
15 * scale 15 * scale
); );
// Render the text
if (isShapeIcon) {
const canvas = this.getWaypointCanvas(waypoint);
parameters.context.drawImage(
canvas,
pos.x + 6 * scale,
pos.y - 11.5 * scale,
14 * scale,
14 * scale
);
} else {
// Render the text
parameters.context.fillStyle = "#000"; parameters.context.fillStyle = "#000";
parameters.context.textAlign = "left";
parameters.context.textBaseline = "middle"; parameters.context.textBaseline = "middle";
parameters.context.fillText(waypoint.label, pos.x + 6 * scale, pos.y + 0.5 * scale + yOffset); parameters.context.fillText(renderLabel, pos.x + 6 * scale, pos.y + 0.5 * scale + yOffset);
parameters.context.textBaseline = "alphabetic"; parameters.context.textBaseline = "alphabetic";
parameters.context.textAlign = "left"; }
// Render the small icon on the left
this.waypointSprite.drawCentered(parameters.context, pos.x, pos.y + yOffset, 10 * scale); this.waypointSprite.drawCentered(parameters.context, pos.x, pos.y + yOffset, 10 * scale);
} }
parameters.context.globalAlpha = 1; parameters.context.globalAlpha = 1;
} }
} }

View File

@ -24,7 +24,7 @@ export const KEYMAPPINGS = {
menuOpenStats: { keyCode: key("G") }, menuOpenStats: { keyCode: key("G") },
toggleHud: { keyCode: 113 }, // F2 toggleHud: { keyCode: 113 }, // F2
exportScreenshot: { keyCode: 114 }, // F3 exportScreenshot: { keyCode: 114 }, // F3PS
toggleFPSInfo: { keyCode: 115 }, // F4 toggleFPSInfo: { keyCode: 115 }, // F4
}, },
@ -33,6 +33,7 @@ export const KEYMAPPINGS = {
mapMoveRight: { keyCode: key("D") }, mapMoveRight: { keyCode: key("D") },
mapMoveDown: { keyCode: key("S") }, mapMoveDown: { keyCode: key("S") },
mapMoveLeft: { keyCode: key("A") }, mapMoveLeft: { keyCode: key("A") },
mapMoveFaster: { keyCode: 16 }, //shift
centerMap: { keyCode: 32 }, // SPACE centerMap: { keyCode: 32 }, // SPACE
mapZoomIn: { keyCode: 187, repeated: true }, // "+" mapZoomIn: { keyCode: 187, repeated: true }, // "+"
@ -55,11 +56,12 @@ export const KEYMAPPINGS = {
}, },
placement: { placement: {
abortBuildingPlacement: { keyCode: key("Q") }, pipette: { keyCode: key("Q") },
rotateWhilePlacing: { keyCode: key("R") }, rotateWhilePlacing: { keyCode: key("R") },
rotateInverseModifier: { keyCode: 16 }, // SHIFT rotateInverseModifier: { keyCode: 16 }, // SHIFT
cycleBuildingVariants: { keyCode: key("T") }, cycleBuildingVariants: { keyCode: key("T") },
cycleBuildings: { keyCode: 9 }, // TAB cycleBuildings: { keyCode: 9 }, // TAB
switchDirectionLockSide: { keyCode: key("R") },
}, },
massSelect: { massSelect: {
@ -72,6 +74,7 @@ export const KEYMAPPINGS = {
}, },
placementModifiers: { placementModifiers: {
lockBeltDirection: { keyCode: 16 }, // SHIFT
placementDisableAutoOrientation: { keyCode: 17 }, // CTRL placementDisableAutoOrientation: { keyCode: 17 }, // CTRL
placeMultiple: { keyCode: 16 }, // SHIFT placeMultiple: { keyCode: 16 }, // SHIFT
placeInverse: { keyCode: 18 }, // ALT placeInverse: { keyCode: 18 }, // ALT
@ -85,6 +88,10 @@ for (const categoryId in KEYMAPPINGS) {
} }
} }
export const KEYCODE_LMB = 1;
export const KEYCODE_MMB = 2;
export const KEYCODE_RMB = 3;
/** /**
* Returns a keycode -> string * Returns a keycode -> string
* @param {number} code * @param {number} code
@ -92,11 +99,11 @@ for (const categoryId in KEYMAPPINGS) {
*/ */
export function getStringForKeyCode(code) { export function getStringForKeyCode(code) {
switch (code) { switch (code) {
case 1: case KEYCODE_LMB:
return "LMB"; return "LMB";
case 2: case KEYCODE_MMB:
return "MMB"; return "MMB";
case 3: case KEYCODE_RMB:
return "RMB"; return "RMB";
case 4: case 4:
return "MB4"; return "MB4";
@ -259,14 +266,16 @@ export class Keybinding {
/** /**
* Returns whether this binding is currently pressed * Returns whether this binding is currently pressed
* @returns {boolean}
*/ */
isCurrentlyPressed() { get pressed() {
// Check if the key is down // Check if the key is down
if (this.app.inputMgr.keysDown.has(this.keyCode)) { if (this.app.inputMgr.keysDown.has(this.keyCode)) {
// Check if it is the top reciever // Check if it is the top reciever
const reciever = this.keyMapper.inputReceiver; const reciever = this.keyMapper.inputReceiver;
return this.app.inputMgr.getTopReciever() === reciever; return this.app.inputMgr.getTopReciever() === reciever;
} }
return false;
} }
/** /**

View File

@ -151,6 +151,7 @@ export class GameLogic {
* @param {number} param0.rotationVariant * @param {number} param0.rotationVariant
* @param {string} param0.variant * @param {string} param0.variant
* @param {MetaBuilding} param0.building * @param {MetaBuilding} param0.building
* @returns {Entity}
*/ */
tryPlaceBuilding({ origin, rotation, rotationVariant, originalRotation, variant, building }) { tryPlaceBuilding({ origin, rotation, rotationVariant, originalRotation, variant, building }) {
if (this.checkCanPlaceBuilding({ origin, rotation, rotationVariant, variant, building })) { if (this.checkCanPlaceBuilding({ origin, rotation, rotationVariant, variant, building })) {
@ -170,13 +171,13 @@ export class GameLogic {
if (contents) { if (contents) {
if (!this.tryDeleteBuilding(contents)) { if (!this.tryDeleteBuilding(contents)) {
logger.error("Building has replaceable component but is also unremovable"); logger.error("Building has replaceable component but is also unremovable");
return false; return null;
} }
} }
} }
} }
building.createAndPlaceEntity({ const entity = building.createAndPlaceEntity({
root: this.root, root: this.root,
origin, origin,
rotation, rotation,
@ -186,10 +187,9 @@ export class GameLogic {
}); });
this.root.soundProxy.playUi(building.getPlacementSound()); this.root.soundProxy.playUi(building.getPlacementSound());
return entity;
return true;
} }
return false; return null;
} }
/** /**

View File

@ -31,6 +31,13 @@ export class MetaBuilding {
return new Vector(1, 1); return new Vector(1, 1);
} }
/**
* Returns whether the building has the direction lock switch available
*/
getHasDirectionLockAvailable() {
return false;
}
/** /**
* Whether to stay in placement mode after having placed a building * Whether to stay in placement mode after having placed a building
*/ */
@ -140,10 +147,32 @@ export class MetaBuilding {
* @param {string} param0.variant * @param {string} param0.variant
*/ */
createAndPlaceEntity({ root, origin, rotation, originalRotation, rotationVariant, variant }) { createAndPlaceEntity({ root, origin, rotation, originalRotation, rotationVariant, variant }) {
const entity = this.createEntity({
root,
origin,
rotation,
originalRotation,
rotationVariant,
variant,
});
root.map.placeStaticEntity(entity);
root.entityMgr.registerEntity(entity);
return entity;
}
/**
* Creates the entity without placing it
* @param {object} param0
* @param {GameRoot} param0.root
* @param {Vector} param0.origin Origin tile
* @param {number=} param0.rotation Rotation
* @param {number} param0.originalRotation Original Rotation
* @param {number} param0.rotationVariant Rotation variant
* @param {string} param0.variant
*/
createEntity({ root, origin, rotation, originalRotation, rotationVariant, variant }) {
const entity = new Entity(root); const entity = new Entity(root);
const blueprintSprite = this.getBlueprintSprite(rotationVariant, variant); const blueprintSprite = this.getBlueprintSprite(rotationVariant, variant);
entity.addComponent( entity.addComponent(
new StaticMapEntityComponent({ new StaticMapEntityComponent({
spriteKey: spriteKey:
@ -159,12 +188,8 @@ export class MetaBuilding {
blueprintSpriteKey: blueprintSprite ? blueprintSprite.spriteName : "", blueprintSpriteKey: blueprintSprite ? blueprintSprite.spriteName : "",
}) })
); );
this.setupEntityComponents(entity, root); this.setupEntityComponents(entity, root);
this.updateVariants(entity, rotationVariant, variant); this.updateVariants(entity, rotationVariant, variant);
root.map.placeStaticEntity(entity);
root.entityMgr.registerEntity(entity);
return entity; return entity;
} }

View File

@ -19,7 +19,6 @@ import { SoundProxy } from "./sound_proxy";
import { Savegame } from "../savegame/savegame"; import { Savegame } from "../savegame/savegame";
import { GameLogic } from "./logic"; import { GameLogic } from "./logic";
import { ShapeDefinitionManager } from "./shape_definition_manager"; import { ShapeDefinitionManager } from "./shape_definition_manager";
import { CanvasClickInterceptor } from "./canvas_click_interceptor";
import { HubGoals } from "./hub_goals"; import { HubGoals } from "./hub_goals";
import { BufferMaintainer } from "../core/buffer_maintainer"; import { BufferMaintainer } from "../core/buffer_maintainer";
import { ProductionAnalytics } from "./production_analytics"; import { ProductionAnalytics } from "./production_analytics";
@ -110,9 +109,6 @@ export class GameRoot {
/** @type {BufferMaintainer} */ /** @type {BufferMaintainer} */
this.buffers = null; this.buffers = null;
/** @type {CanvasClickInterceptor} */
this.canvasClickInterceptor = null;
/** @type {AutomaticSave} */ /** @type {AutomaticSave} */
this.automaticSave = null; this.automaticSave = null;
@ -130,6 +126,7 @@ export class GameRoot {
this.signals = { this.signals = {
// Entities // Entities
entityManuallyPlaced: /** @type {TypedSignal<[Entity]>} */ (new Signal()),
entityAdded: /** @type {TypedSignal<[Entity]>} */ (new Signal()), entityAdded: /** @type {TypedSignal<[Entity]>} */ (new Signal()),
entityGotNewComponent: /** @type {TypedSignal<[Entity]>} */ (new Signal()), entityGotNewComponent: /** @type {TypedSignal<[Entity]>} */ (new Signal()),
entityComponentRemoved: /** @type {TypedSignal<[Entity]>} */ (new Signal()), entityComponentRemoved: /** @type {TypedSignal<[Entity]>} */ (new Signal()),

View File

@ -70,6 +70,12 @@ export function createSimpleShape(layers) {
return layers; return layers;
} }
/**
* Cache which shapes are valid short keys and which not
* @type {Map<string, boolean>}
*/
const SHORT_KEY_CACHE = new Map();
export class ShapeDefinition extends BasicSerializableObject { export class ShapeDefinition extends BasicSerializableObject {
static getId() { static getId() {
return "ShapeDefinition"; return "ShapeDefinition";
@ -114,6 +120,8 @@ export class ShapeDefinition extends BasicSerializableObject {
/** /**
* Generates the definition from the given short key * Generates the definition from the given short key
* @param {string} key
* @returns {ShapeDefinition}
*/ */
static fromShortKey(key) { static fromShortKey(key) {
const sourceLayers = key.split(":"); const sourceLayers = key.split(":");
@ -147,6 +155,81 @@ export class ShapeDefinition extends BasicSerializableObject {
return definition; return definition;
} }
/**
* Checks if a given string is a valid short key
* @param {string} key
* @returns {boolean}
*/
static isValidShortKey(key) {
if (SHORT_KEY_CACHE.has(key)) {
return SHORT_KEY_CACHE.get(key);
}
const result = ShapeDefinition.isValidShortKeyInternal(key);
SHORT_KEY_CACHE.set(key, result);
return result;
}
/**
* INTERNAL
* Checks if a given string is a valid short key
* @param {string} key
* @returns {boolean}
*/
static isValidShortKeyInternal(key) {
const sourceLayers = key.split(":");
let layers = [];
for (let i = 0; i < sourceLayers.length; ++i) {
const text = sourceLayers[i];
if (text.length !== 8) {
return false;
}
/** @type {ShapeLayer} */
const quads = [null, null, null, null];
let anyFilled = false;
for (let quad = 0; quad < 4; ++quad) {
const shapeText = text[quad * 2 + 0];
const colorText = text[quad * 2 + 1];
const subShape = enumShortcodeToSubShape[shapeText];
const color = enumShortcodeToColor[colorText];
// Valid shape
if (subShape) {
if (!color) {
// Invalid color
return false;
}
quads[quad] = {
subShape,
color,
};
anyFilled = true;
} else if (shapeText === "-") {
// Make sure color is empty then, too
if (colorText !== "-") {
return false;
}
} else {
// Invalid shape key
return false;
}
}
if (!anyFilled) {
// Empty layer
return false;
}
layers.push(quads);
}
if (layers.length === 0 || layers.length > 4) {
return false;
}
return true;
}
/** /**
* Internal method to clone the shape definition * Internal method to clone the shape definition
* @returns {Array<ShapeLayer>} * @returns {Array<ShapeLayer>}

View File

@ -6,7 +6,9 @@ import { Vector } from "../core/vector";
import { SOUNDS } from "../platform/sound"; import { SOUNDS } from "../platform/sound";
const avgSoundDurationSeconds = 0.25; const avgSoundDurationSeconds = 0.25;
const maxOngoingSounds = 10; const maxOngoingSounds = 2;
const maxOngoingUiSounds = 25;
// Proxy to the application sound instance // Proxy to the application sound instance
export class SoundProxy { export class SoundProxy {
@ -17,7 +19,8 @@ export class SoundProxy {
this.root = root; this.root = root;
// Store a list of sounds and when we started them // Store a list of sounds and when we started them
this.playingSounds = []; this.playing3DSounds = [];
this.playingUiSounds = [];
} }
/** /**
@ -26,7 +29,14 @@ export class SoundProxy {
*/ */
playUi(id) { playUi(id) {
assert(typeof id === "string", "Not a valid sound id: " + id); assert(typeof id === "string", "Not a valid sound id: " + id);
this.internalUpdateOngoingSounds();
if (this.playingUiSounds.length > maxOngoingUiSounds) {
// Too many ongoing sounds
return false;
}
this.root.app.sound.playUiSound(id); this.root.app.sound.playUiSound(id);
this.playingUiSounds.push(this.root.time.realtimeNow());
} }
/** /**
@ -53,13 +63,13 @@ export class SoundProxy {
assert(pos instanceof Vector, "Invalid sound position"); assert(pos instanceof Vector, "Invalid sound position");
this.internalUpdateOngoingSounds(); this.internalUpdateOngoingSounds();
if (this.playingSounds.length > maxOngoingSounds) { if (this.playing3DSounds.length > maxOngoingSounds) {
// Too many ongoing sounds // Too many ongoing sounds
return false; return false;
} }
this.root.app.sound.play3DSound(id, pos, this.root); this.root.app.sound.play3DSound(id, pos, this.root);
this.playingSounds.push(this.root.time.realtimeNow()); this.playing3DSounds.push(this.root.time.realtimeNow());
return true; return true;
} }
@ -68,9 +78,16 @@ export class SoundProxy {
*/ */
internalUpdateOngoingSounds() { internalUpdateOngoingSounds() {
const now = this.root.time.realtimeNow(); const now = this.root.time.realtimeNow();
for (let i = 0; i < this.playingSounds.length; ++i) { for (let i = 0; i < this.playing3DSounds.length; ++i) {
if (now - this.playingSounds[i] > avgSoundDurationSeconds) { if (now - this.playing3DSounds[i] > avgSoundDurationSeconds) {
this.playingSounds.splice(i, 1); this.playing3DSounds.splice(i, 1);
i -= 1;
}
}
for (let i = 0; i < this.playingUiSounds.length; ++i) {
if (now - this.playingUiSounds[i] > avgSoundDurationSeconds) {
this.playingUiSounds.splice(i, 1);
i -= 1; i -= 1;
} }
} }

View File

@ -1,4 +1,4 @@
import { Math_radians, Math_min, Math_max } from "../../core/builtins"; import { Math_radians, Math_min, Math_max, Math_sqrt } from "../../core/builtins";
import { globalConfig } from "../../core/config"; import { globalConfig } from "../../core/config";
import { DrawParameters } from "../../core/draw_parameters"; import { DrawParameters } from "../../core/draw_parameters";
import { Loader } from "../../core/loader"; import { Loader } from "../../core/loader";
@ -15,6 +15,7 @@ import { GameRoot } from "../root";
import { createLogger } from "../../core/logging"; import { createLogger } from "../../core/logging";
const BELT_ANIM_COUNT = 6; const BELT_ANIM_COUNT = 6;
const SQRT_2 = Math_sqrt(2);
const logger = createLogger("belt"); const logger = createLogger("belt");
@ -211,6 +212,7 @@ export class BeltSystem extends GameSystemWithFilter {
this.root.hubGoals.getBeltBaseSpeed() * this.root.hubGoals.getBeltBaseSpeed() *
this.root.dynamicTickrate.deltaSeconds * this.root.dynamicTickrate.deltaSeconds *
globalConfig.itemSpacingOnBelts; globalConfig.itemSpacingOnBelts;
if (G_IS_DEV && globalConfig.debug.instantBelts) { if (G_IS_DEV && globalConfig.debug.instantBelts) {
beltSpeed *= 100; beltSpeed *= 100;
} }
@ -229,35 +231,43 @@ export class BeltSystem extends GameSystemWithFilter {
const ejectorComp = entity.components.ItemEjector; const ejectorComp = entity.components.ItemEjector;
let maxProgress = 1; let maxProgress = 1;
/* PERFORMANCE OPTIMIZATION */
// Original:
// const isCurrentlyEjecting = ejectorComp.isAnySlotEjecting();
// Replaced (Since belts always have just one slot):
const ejectorSlot = ejectorComp.slots[0];
const isCurrentlyEjecting = ejectorSlot.item;
// When ejecting, we can not go further than the item spacing since it // When ejecting, we can not go further than the item spacing since it
// will be on the corner // will be on the corner
if (ejectorComp.isAnySlotEjecting()) { if (isCurrentlyEjecting) {
maxProgress = 1 - globalConfig.itemSpacingOnBelts; maxProgress = 1 - globalConfig.itemSpacingOnBelts;
} else { } else {
// Otherwise our progress depends on the follow up // Otherwise our progress depends on the follow up
if (followUp) { if (followUp) {
const spacingOnBelt = followUp.components.Belt.getDistanceToFirstItemCenter(); const spacingOnBelt = followUp.components.Belt.getDistanceToFirstItemCenter();
maxProgress = Math_min(2, 1 - globalConfig.itemSpacingOnBelts + spacingOnBelt); maxProgress = Math.min(2, 1 - globalConfig.itemSpacingOnBelts + spacingOnBelt);
assert(maxProgress >= 0.0, "max progress < 0 (I)");
// Useful check, but hurts performance
// assert(maxProgress >= 0.0, "max progress < 0 (I)");
} }
} }
let speedMultiplier = 1; let speedMultiplier = 1;
if (beltComp.direction !== enumDirection.top) { if (beltComp.direction !== enumDirection.top) {
// Shaped belts are longer, thus being quicker // Curved belts are shorter, thus being quicker (Looks weird otherwise)
speedMultiplier = 1.41; speedMultiplier = SQRT_2;
} }
// Not really nice. haven't found the reason for this yet. // Not really nice. haven't found the reason for this yet.
if (items.length > 2 / globalConfig.itemSpacingOnBelts) { if (items.length > 2 / globalConfig.itemSpacingOnBelts) {
logger.error("Fixing broken belt:", entity, items);
beltComp.sortedItems = []; beltComp.sortedItems = [];
} }
for (let itemIndex = items.length - 1; itemIndex >= 0; --itemIndex) { for (let itemIndex = items.length - 1; itemIndex >= 0; --itemIndex) {
const progressAndItem = items[itemIndex]; const progressAndItem = items[itemIndex];
progressAndItem[0] = Math_min(maxProgress, progressAndItem[0] + speedMultiplier * beltSpeed); progressAndItem[0] = Math.min(maxProgress, progressAndItem[0] + speedMultiplier * beltSpeed);
if (progressAndItem[0] >= 1.0) { if (progressAndItem[0] >= 1.0) {
if (followUp) { if (followUp) {
@ -273,14 +283,18 @@ export class BeltSystem extends GameSystemWithFilter {
} }
} else { } else {
// Try to give this item to a new belt // Try to give this item to a new belt
const freeSlot = ejectorComp.getFirstFreeSlot();
if (freeSlot === null) { /* PERFORMANCE OPTIMIZATION */
// Original:
// const freeSlot = ejectorComp.getFirstFreeSlot();
// Replaced
if (ejectorSlot.item) {
// So, we don't have a free slot - damned! // So, we don't have a free slot - damned!
progressAndItem[0] = 1.0; progressAndItem[0] = 1.0;
maxProgress = 1 - globalConfig.itemSpacingOnBelts; maxProgress = 1 - globalConfig.itemSpacingOnBelts;
} else { } else {
// We got a free slot, remove this item and keep it on the ejector slot // We got a free slot, remove this item and keep it on the ejector slot
if (!ejectorComp.tryEject(freeSlot, progressAndItem[1])) { if (!ejectorComp.tryEject(0, progressAndItem[1])) {
assert(false, "Ejection failed"); assert(false, "Ejection failed");
} }
items.splice(itemIndex, 1); items.splice(itemIndex, 1);
@ -290,7 +304,7 @@ export class BeltSystem extends GameSystemWithFilter {
} }
} else { } else {
// We just moved this item forward, so determine the maximum progress of other items // We just moved this item forward, so determine the maximum progress of other items
maxProgress = Math_max(0, progressAndItem[0] - globalConfig.itemSpacingOnBelts); maxProgress = Math.max(0, progressAndItem[0] - globalConfig.itemSpacingOnBelts);
} }
} }
} }

View File

@ -6,20 +6,41 @@ import { ItemEjectorComponent } from "../components/item_ejector";
import { Entity } from "../entity"; import { Entity } from "../entity";
import { GameSystemWithFilter } from "../game_system_with_filter"; import { GameSystemWithFilter } from "../game_system_with_filter";
import { Math_min } from "../../core/builtins"; import { Math_min } from "../../core/builtins";
import { createLogger } from "../../core/logging";
const logger = createLogger("systems/ejector");
export class ItemEjectorSystem extends GameSystemWithFilter { export class ItemEjectorSystem extends GameSystemWithFilter {
constructor(root) { constructor(root) {
super(root, [ItemEjectorComponent]); super(root, [ItemEjectorComponent]);
/**
* @type {Array<{
* targetEntity: Entity,
* sourceSlot: import("../components/item_ejector").ItemEjectorSlot,
* destSlot: import("../components/item_acceptor").ItemAcceptorLocatedSlot
* }>}
*/
this.cache = [];
this.cacheNeedsUpdate = true;
this.root.signals.entityAdded.add(this.invalidateCache, this);
this.root.signals.entityDestroyed.add(this.invalidateCache, this);
} }
update() { invalidateCache() {
const effectiveBeltSpeed = this.root.hubGoals.getBeltBaseSpeed() * globalConfig.itemSpacingOnBelts; this.cacheNeedsUpdate = true;
let progressGrowth = (effectiveBeltSpeed / 0.5) * this.root.dynamicTickrate.deltaSeconds;
if (G_IS_DEV && globalConfig.debug.instantBelts) {
progressGrowth = 1;
} }
/**
* Precomputes the cache, which makes up for a huge performance improvement
*/
recomputeCache() {
logger.log("Recomputing cache");
const cache = [];
// Try to find acceptors for every ejector // Try to find acceptors for every ejector
for (let i = 0; i < this.allEntities.length; ++i) { for (let i = 0; i < this.allEntities.length; ++i) {
const entity = this.allEntities[i]; const entity = this.allEntities[i];
@ -29,17 +50,6 @@ export class ItemEjectorSystem extends GameSystemWithFilter {
// For every ejector slot, try to find an acceptor // For every ejector slot, try to find an acceptor
for (let ejectorSlotIndex = 0; ejectorSlotIndex < ejectorComp.slots.length; ++ejectorSlotIndex) { for (let ejectorSlotIndex = 0; ejectorSlotIndex < ejectorComp.slots.length; ++ejectorSlotIndex) {
const ejectorSlot = ejectorComp.slots[ejectorSlotIndex]; const ejectorSlot = ejectorComp.slots[ejectorSlotIndex];
const ejectingItem = ejectorSlot.item;
if (!ejectingItem) {
// No item ejected
continue;
}
ejectorSlot.progress = Math_min(1, ejectorSlot.progress + progressGrowth);
if (ejectorSlot.progress < 1.0) {
// Still ejecting
continue;
}
// Figure out where and into which direction we eject items // Figure out where and into which direction we eject items
const ejectSlotWsTile = staticComp.localTileToWorld(ejectorSlot.pos); const ejectSlotWsTile = staticComp.localTileToWorld(ejectorSlot.pos);
@ -71,20 +81,63 @@ export class ItemEjectorSystem extends GameSystemWithFilter {
continue; continue;
} }
if (!targetAcceptorComp.canAcceptItem(matchingSlot.index, ejectingItem)) { // Ok we found a connection
// Can not accept item cache.push({
targetEntity,
sourceSlot: ejectorSlot,
destSlot: matchingSlot,
});
}
}
this.cache = cache;
logger.log("Found", cache.length, "entries to update");
}
update() {
if (this.cacheNeedsUpdate) {
this.cacheNeedsUpdate = false;
this.recomputeCache();
}
// Precompute effective belt speed
const effectiveBeltSpeed = this.root.hubGoals.getBeltBaseSpeed() * globalConfig.itemSpacingOnBelts;
let progressGrowth = (effectiveBeltSpeed / 0.5) * this.root.dynamicTickrate.deltaSeconds;
if (G_IS_DEV && globalConfig.debug.instantBelts) {
progressGrowth = 1;
}
// Go over all cache entries
for (let i = 0; i < this.cache.length; ++i) {
const { sourceSlot, destSlot, targetEntity } = this.cache[i];
const item = sourceSlot.item;
if (!item) {
// No item available to be ejected
continue; continue;
} }
if (this.tryPassOverItem(ejectingItem, targetEntity, matchingSlot.index)) { // Advance items on the slot
targetAcceptorComp.onItemAccepted( sourceSlot.progress = Math_min(1, sourceSlot.progress + progressGrowth);
matchingSlot.index,
matchingSlot.acceptedDirection, // Check if we are still in the process of ejecting, can't proceed then
ejectingItem if (sourceSlot.progress < 1.0) {
);
ejectorSlot.item = null;
continue; continue;
} }
// Check if the target acceptor can actually accept this item
const targetAcceptorComp = targetEntity.components.ItemAcceptor;
if (!targetAcceptorComp.canAcceptItem(destSlot.index, item)) {
continue;
}
// Try to hand over the item
if (this.tryPassOverItem(item, targetEntity, destSlot.index)) {
// Handover successful, clear slot
targetAcceptorComp.onItemAccepted(destSlot.index, destSlot.acceptedDirection, item);
sourceSlot.item = null;
continue;
} }
} }
} }

View File

@ -24,12 +24,18 @@ export class MinerSystem extends GameSystemWithFilter {
// Check if miner is above an actual tile // Check if miner is above an actual tile
const minerComp = entity.components.Miner; const minerComp = entity.components.Miner;
const staticComp = entity.components.StaticMapEntity;
const tileBelow = this.root.map.getLowerLayerContentXY(staticComp.origin.x, staticComp.origin.y); if (!minerComp.cachedMinedItem) {
const staticComp = entity.components.StaticMapEntity;
const tileBelow = this.root.map.getLowerLayerContentXY(
staticComp.origin.x,
staticComp.origin.y
);
if (!tileBelow) { if (!tileBelow) {
continue; continue;
} }
minerComp.cachedMinedItem = tileBelow;
}
// First, try to get rid of chained items // First, try to get rid of chained items
if (minerComp.itemChainBuffer.length > 0) { if (minerComp.itemChainBuffer.length > 0) {
@ -40,20 +46,9 @@ export class MinerSystem extends GameSystemWithFilter {
} }
if (this.root.time.isIngameTimerExpired(minerComp.lastMiningTime, 1 / miningSpeed)) { if (this.root.time.isIngameTimerExpired(minerComp.lastMiningTime, 1 / miningSpeed)) {
const lowerLayerItem = this.root.map.getLowerLayerContentXY( if (this.tryPerformMinerEject(entity, minerComp.cachedMinedItem)) {
staticComp.origin.x,
staticComp.origin.y
);
// TODO: Should not be required actually
if (!lowerLayerItem) {
// Nothing below;
continue;
}
if (this.tryPerformMinerEject(entity, lowerLayerItem)) {
// Analytics hook // Analytics hook
this.root.signals.itemProduced.dispatch(lowerLayerItem); this.root.signals.itemProduced.dispatch(minerComp.cachedMinedItem);
// Actually mine // Actually mine
minerComp.lastMiningTime = this.root.time.now(); minerComp.lastMiningTime = this.root.time.now();
@ -114,18 +109,17 @@ export class MinerSystem extends GameSystemWithFilter {
if (entity && entity.components.Miner) { if (entity && entity.components.Miner) {
const staticComp = entity.components.StaticMapEntity; const staticComp = entity.components.StaticMapEntity;
const minerComp = entity.components.Miner;
if (!staticComp.shouldBeDrawn(parameters)) { if (!staticComp.shouldBeDrawn(parameters)) {
continue; continue;
} }
if (!minerComp.cachedMinedItem) {
continue;
}
const lowerLayerItem = this.root.map.getLowerLayerContentXY( if (minerComp.cachedMinedItem) {
staticComp.origin.x,
staticComp.origin.y
);
if (lowerLayerItem) {
const padding = 3; const padding = 3;
parameters.context.fillStyle = lowerLayerItem.getBackgroundColorAsResource(); parameters.context.fillStyle = minerComp.cachedMinedItem.getBackgroundColorAsResource();
parameters.context.fillRect( parameters.context.fillRect(
staticComp.origin.x * globalConfig.tileSize + padding, staticComp.origin.x * globalConfig.tileSize + padding,
staticComp.origin.y * globalConfig.tileSize + padding, staticComp.origin.y * globalConfig.tileSize + padding,
@ -134,8 +128,8 @@ export class MinerSystem extends GameSystemWithFilter {
); );
} }
if (lowerLayerItem) { if (minerComp.cachedMinedItem) {
lowerLayerItem.draw( minerComp.cachedMinedItem.draw(
(0.5 + staticComp.origin.x) * globalConfig.tileSize, (0.5 + staticComp.origin.x) * globalConfig.tileSize,
(0.5 + staticComp.origin.y) * globalConfig.tileSize, (0.5 + staticComp.origin.y) * globalConfig.tileSize,
parameters parameters

Some files were not shown because too many files have changed in this diff Show More