Restructure buildings

This commit is contained in:
tobspr 2020-09-24 12:53:40 +02:00
parent 0202387739
commit c54ec9fd2a
99 changed files with 2374 additions and 2449 deletions

View File

@ -1,148 +1,141 @@
// @ts-ignore // @ts-ignore
const path = require("path"); const path = require("path");
// Globs for non-ui resources // Globs for non-ui resources
const nonImageResourcesGlobs = ["../res/**/*.woff2", "../res/*.ico", "../res/**/*.webm"]; const nonImageResourcesGlobs = ["../res/**/*.woff2", "../res/*.ico", "../res/**/*.webm"];
// Globs for ui resources // Globs for ui resources
const imageResourcesGlobs = ["../res/**/*.png", "../res/**/*.svg", "../res/**/*.jpg", "../res/**/*.gif"]; const imageResourcesGlobs = ["../res/**/*.png", "../res/**/*.svg", "../res/**/*.jpg", "../res/**/*.gif"];
function gulptasksImageResources($, gulp, buildFolder) { function gulptasksImageResources($, gulp, buildFolder) {
// Lossless options // Lossless options
const minifyImagesOptsLossless = () => [ const minifyImagesOptsLossless = () => [
$.imageminJpegtran({ $.imageminJpegtran({
progressive: true, progressive: true,
}), }),
$.imagemin.svgo({}), $.imagemin.svgo({}),
$.imagemin.optipng({ $.imagemin.optipng({
optimizationLevel: 3, optimizationLevel: 3,
}), }),
$.imageminGifsicle({ $.imageminGifsicle({
optimizationLevel: 3, optimizationLevel: 3,
colors: 128, colors: 128,
}), }),
]; ];
// Lossy options // Lossy options
const minifyImagesOpts = () => [ const minifyImagesOpts = () => [
$.imagemin.mozjpeg({ $.imagemin.mozjpeg({
quality: 80, quality: 80,
maxMemory: 1024 * 1024 * 8, maxMemory: 1024 * 1024 * 8,
}), }),
$.imagemin.svgo({}), $.imagemin.svgo({}),
$.imageminPngquant({ $.imageminPngquant({
speed: 1, speed: 1,
strip: true, strip: true,
quality: [0.65, 0.9], quality: [0.65, 0.9],
dithering: false, dithering: false,
verbose: false, verbose: false,
}), }),
$.imagemin.optipng({ $.imagemin.optipng({
optimizationLevel: 3, optimizationLevel: 3,
}), }),
$.imageminGifsicle({ $.imageminGifsicle({
optimizationLevel: 3, optimizationLevel: 3,
colors: 128, colors: 128,
}), }),
]; ];
// Where the resources folder are // Where the resources folder are
const resourcesDestFolder = path.join(buildFolder, "res"); const resourcesDestFolder = path.join(buildFolder, "res");
/** /**
* Determines if an atlas must use lossless compression * Determines if an atlas must use lossless compression
* @param {string} fname * @param {string} fname
*/ */
function fileMustBeLossless(fname) { function fileMustBeLossless(fname) {
return fname.indexOf("lossless") >= 0; return fname.indexOf("lossless") >= 0;
} }
/////////////// ATLAS ///////////////////// /////////////// ATLAS /////////////////////
// Copies the atlas to the final destination // Copies the atlas to the final destination
gulp.task("imgres.atlas", () => { gulp.task("imgres.atlas", () => {
return gulp return gulp.src(["../res_built/atlas/*.png"]).pipe(gulp.dest(resourcesDestFolder));
.src(["../res_built/atlas/*.png"]) });
.pipe($.cached("imgres.atlas"))
.pipe(gulp.dest(resourcesDestFolder)); // Copies the atlas to the final destination after optimizing it (lossy compression)
}); gulp.task("imgres.atlasOptimized", () => {
return gulp
// Copies the atlas to the final destination after optimizing it (lossy compression) .src(["../res_built/atlas/*.png"])
gulp.task("imgres.atlasOptimized", () => { .pipe(
return gulp $.if(
.src(["../res_built/atlas/*.png"]) fname => fileMustBeLossless(fname.history[0]),
.pipe($.cached("imgres.atlasOptimized")) $.imagemin(minifyImagesOptsLossless()),
.pipe( $.imagemin(minifyImagesOpts())
$.if( )
fname => fileMustBeLossless(fname.history[0]), )
$.imagemin(minifyImagesOptsLossless()), .pipe(gulp.dest(resourcesDestFolder));
$.imagemin(minifyImagesOpts()) });
)
) //////////////////// RESOURCES //////////////////////
.pipe(gulp.dest(resourcesDestFolder));
}); // Copies all resources which are no ui resources
gulp.task("imgres.copyNonImageResources", () => {
//////////////////// RESOURCES ////////////////////// return gulp.src(nonImageResourcesGlobs).pipe(gulp.dest(resourcesDestFolder));
});
// Copies all resources which are no ui resources
gulp.task("imgres.copyNonImageResources", () => { // Copies all ui resources
return gulp gulp.task("imgres.copyImageResources", () => {
.src(nonImageResourcesGlobs) return gulp
.pipe($.cached("imgres.copyNonImageResources")) .src(imageResourcesGlobs)
.pipe(gulp.dest(resourcesDestFolder));
}); .pipe($.cached("imgres.copyImageResources"))
.pipe(gulp.dest(path.join(resourcesDestFolder)));
// Copies all ui resources });
gulp.task("imgres.copyImageResources", () => {
return gulp // Copies all ui resources and optimizes them
.src(imageResourcesGlobs) gulp.task("imgres.copyImageResourcesOptimized", () => {
.pipe($.cached("copyImageResources")) return gulp
.pipe(gulp.dest(path.join(resourcesDestFolder))); .src(imageResourcesGlobs)
}); .pipe(
$.if(
// Copies all ui resources and optimizes them fname => fileMustBeLossless(fname.history[0]),
gulp.task("imgres.copyImageResourcesOptimized", () => { $.imagemin(minifyImagesOptsLossless()),
return gulp $.imagemin(minifyImagesOpts())
.src(imageResourcesGlobs) )
.pipe($.cached("imgres.copyImageResourcesOptimized")) )
.pipe( .pipe(gulp.dest(path.join(resourcesDestFolder)));
$.if( });
fname => fileMustBeLossless(fname.history[0]),
$.imagemin(minifyImagesOptsLossless()), // Copies all resources and optimizes them
$.imagemin(minifyImagesOpts()) gulp.task(
) "imgres.allOptimized",
) gulp.parallel(
.pipe(gulp.dest(path.join(resourcesDestFolder))); "imgres.atlasOptimized",
}); "imgres.copyNonImageResources",
"imgres.copyImageResourcesOptimized"
// Copies all resources and optimizes them )
gulp.task( );
"imgres.allOptimized",
gulp.parallel( // Cleans up unused images which are instead inline into the css
"imgres.atlasOptimized", gulp.task("imgres.cleanupUnusedCssInlineImages", () => {
"imgres.copyNonImageResources", return gulp
"imgres.copyImageResourcesOptimized" .src(
) [
); path.join(buildFolder, "res", "ui", "**", "*.png"),
path.join(buildFolder, "res", "ui", "**", "*.jpg"),
// Cleans up unused images which are instead inline into the css path.join(buildFolder, "res", "ui", "**", "*.svg"),
gulp.task("imgres.cleanupUnusedCssInlineImages", () => { path.join(buildFolder, "res", "ui", "**", "*.gif"),
return gulp ],
.src( { read: false }
[ )
path.join(buildFolder, "res", "ui", "**", "*.png"), .pipe($.if(fname => fname.history[0].indexOf("noinline") < 0, $.clean({ force: true })));
path.join(buildFolder, "res", "ui", "**", "*.jpg"), });
path.join(buildFolder, "res", "ui", "**", "*.svg"), }
path.join(buildFolder, "res", "ui", "**", "*.gif"),
], module.exports = {
{ read: false } nonImageResourcesGlobs,
) imageResourcesGlobs,
.pipe($.if(fname => fname.history[0].indexOf("noinline") < 0, $.clean({ force: true }))); gulptasksImageResources,
}); };
}
module.exports = {
nonImageResourcesGlobs,
imageResourcesGlobs,
gulptasksImageResources,
};

View File

@ -18,7 +18,7 @@ function gulptasksSounds($, gulp, buildFolder) {
function getFileCacheValue(file) { function getFileCacheValue(file) {
const { _isVinyl, base, cwd, contents, history, stat, path } = file; const { _isVinyl, base, cwd, contents, history, stat, path } = file;
const encodedContents = Buffer.from(contents).toString('base64'); const encodedContents = Buffer.from(contents).toString("base64");
return { _isVinyl, base, cwd, contents: encodedContents, history, stat, path }; return { _isVinyl, base, cwd, contents: encodedContents, history, stat, path };
} }
@ -118,7 +118,6 @@ function gulptasksSounds($, gulp, buildFolder) {
return gulp return gulp
.src(path.join(builtSoundsDir, "**", "*.mp3")) .src(path.join(builtSoundsDir, "**", "*.mp3"))
.pipe($.plumber()) .pipe($.plumber())
.pipe($.cached("sounds.copy"))
.pipe(gulp.dest(path.join(buildFolder, "res", "sounds"))); .pipe(gulp.dest(path.join(buildFolder, "res", "sounds")));
}); });

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.0 KiB

After

Width:  |  Height:  |  Size: 7.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.9 KiB

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.2 KiB

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.1 KiB

After

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.2 KiB

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 233 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 281 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 287 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 283 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 286 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 260 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 116 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 116 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 106 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 121 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 121 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 107 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 138 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 91 KiB

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 MiB

After

Width:  |  Height:  |  Size: 1.3 MiB

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 278 KiB

After

Width:  |  Height:  |  Size: 279 KiB

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 701 KiB

After

Width:  |  Height:  |  Size: 703 KiB

View File

@ -104,7 +104,7 @@
</struct> </struct>
</struct> </struct>
<key>shapePadding</key> <key>shapePadding</key>
<uint>0</uint> <uint>2</uint>
<key>jpgQuality</key> <key>jpgQuality</key>
<uint>80</uint> <uint>80</uint>
<key>pngOptimizationLevel</key> <key>pngOptimizationLevel</key>
@ -118,7 +118,7 @@
<key>textureFormat</key> <key>textureFormat</key>
<enum type="SettingsBase::TextureFormat">png</enum> <enum type="SettingsBase::TextureFormat">png</enum>
<key>borderPadding</key> <key>borderPadding</key>
<uint>1</uint> <uint>3</uint>
<key>maxTextureSize</key> <key>maxTextureSize</key>
<QSize> <QSize>
<key>width</key> <key>width</key>
@ -197,7 +197,7 @@
<key>scaleMode</key> <key>scaleMode</key>
<enum type="ScaleMode">Smooth</enum> <enum type="ScaleMode">Smooth</enum>
<key>extrude</key> <key>extrude</key>
<uint>3</uint> <uint>2</uint>
<key>trimThreshold</key> <key>trimThreshold</key>
<uint>2</uint> <uint>2</uint>
<key>trimMargin</key> <key>trimMargin</key>
@ -260,35 +260,6 @@
<key type="filename">sprites/blueprints/balancer-merger-inverse.png</key> <key type="filename">sprites/blueprints/balancer-merger-inverse.png</key>
<key type="filename">sprites/blueprints/balancer-merger.png</key> <key type="filename">sprites/blueprints/balancer-merger.png</key>
<key type="filename">sprites/blueprints/balancer-splitter-inverse.png</key> <key type="filename">sprites/blueprints/balancer-splitter-inverse.png</key>
<key type="filename">sprites/blueprints/balancer-splitter.png</key>
<key type="filename">sprites/blueprints/constant_signal.png</key>
<key type="filename">sprites/blueprints/display.png</key>
<key type="filename">sprites/blueprints/lever.png</key>
<key type="filename">sprites/blueprints/logic_gate-not.png</key>
<key type="filename">sprites/blueprints/logic_gate-or.png</key>
<key type="filename">sprites/blueprints/logic_gate-transistor.png</key>
<key type="filename">sprites/blueprints/logic_gate-xor.png</key>
<key type="filename">sprites/blueprints/logic_gate.png</key>
<key type="filename">sprites/blueprints/miner-chainable.png</key>
<key type="filename">sprites/blueprints/miner.png</key>
<key type="filename">sprites/blueprints/reader.png</key>
<key type="filename">sprites/blueprints/rotater-ccw.png</key>
<key type="filename">sprites/blueprints/rotater-rotate180.png</key>
<key type="filename">sprites/blueprints/rotater.png</key>
<key type="filename">sprites/blueprints/trash.png</key>
<key type="filename">sprites/blueprints/underground_belt_entry-tier2.png</key>
<key type="filename">sprites/blueprints/underground_belt_entry.png</key>
<key type="filename">sprites/blueprints/underground_belt_exit-tier2.png</key>
<key type="filename">sprites/blueprints/underground_belt_exit.png</key>
<key type="filename">sprites/blueprints/virtual_processor-analyzer.png</key>
<key type="filename">sprites/blueprints/virtual_processor-painter.png</key>
<key type="filename">sprites/blueprints/virtual_processor-rotater.png</key>
<key type="filename">sprites/blueprints/virtual_processor-shapecompare.png</key>
<key type="filename">sprites/blueprints/virtual_processor-stacker.png</key>
<key type="filename">sprites/blueprints/virtual_processor-unstacker.png</key>
<key type="filename">sprites/blueprints/virtual_processor.png</key>
<key type="filename">sprites/blueprints/wire_tunnel-coating.png</key>
<key type="filename">sprites/blueprints/wire_tunnel.png</key>
<key type="filename">sprites/buildings/balancer-merger-inverse.png</key> <key type="filename">sprites/buildings/balancer-merger-inverse.png</key>
<key type="filename">sprites/buildings/balancer-merger.png</key> <key type="filename">sprites/buildings/balancer-merger.png</key>
<key type="filename">sprites/buildings/balancer-splitter-inverse.png</key> <key type="filename">sprites/buildings/balancer-splitter-inverse.png</key>
@ -298,13 +269,14 @@
<key type="filename">sprites/buildings/lever.png</key> <key type="filename">sprites/buildings/lever.png</key>
<key type="filename">sprites/buildings/logic_gate-not.png</key> <key type="filename">sprites/buildings/logic_gate-not.png</key>
<key type="filename">sprites/buildings/logic_gate-or.png</key> <key type="filename">sprites/buildings/logic_gate-or.png</key>
<key type="filename">sprites/buildings/logic_gate-transistor.png</key>
<key type="filename">sprites/buildings/logic_gate-xor.png</key> <key type="filename">sprites/buildings/logic_gate-xor.png</key>
<key type="filename">sprites/buildings/logic_gate.png</key> <key type="filename">sprites/buildings/logic_gate.png</key>
<key type="filename">sprites/buildings/miner-chainable.png</key> <key type="filename">sprites/buildings/miner-chainable.png</key>
<key type="filename">sprites/buildings/reader.png</key> <key type="filename">sprites/buildings/reader.png</key>
<key type="filename">sprites/buildings/rotater-ccw.png</key> <key type="filename">sprites/buildings/rotater-ccw.png</key>
<key type="filename">sprites/buildings/rotater-rotate180.png</key> <key type="filename">sprites/buildings/rotater-rotate180.png</key>
<key type="filename">sprites/buildings/transistor-mirrored.png</key>
<key type="filename">sprites/buildings/transistor.png</key>
<key type="filename">sprites/buildings/underground_belt_entry-tier2.png</key> <key type="filename">sprites/buildings/underground_belt_entry-tier2.png</key>
<key type="filename">sprites/buildings/underground_belt_entry.png</key> <key type="filename">sprites/buildings/underground_belt_entry.png</key>
<key type="filename">sprites/buildings/underground_belt_exit-tier2.png</key> <key type="filename">sprites/buildings/underground_belt_exit-tier2.png</key>
@ -316,26 +288,25 @@
<key type="filename">sprites/buildings/virtual_processor-stacker.png</key> <key type="filename">sprites/buildings/virtual_processor-stacker.png</key>
<key type="filename">sprites/buildings/virtual_processor-unstacker.png</key> <key type="filename">sprites/buildings/virtual_processor-unstacker.png</key>
<key type="filename">sprites/buildings/virtual_processor.png</key> <key type="filename">sprites/buildings/virtual_processor.png</key>
<key type="filename">sprites/buildings/wire_tunnel-coating.png</key>
<key type="filename">sprites/buildings/wire_tunnel.png</key> <key type="filename">sprites/buildings/wire_tunnel.png</key>
<key type="filename">sprites/misc/reader_overlay.png</key> <key type="filename">sprites/misc/reader_overlay.png</key>
<key type="filename">sprites/wires/lever_on.png</key> <key type="filename">sprites/wires/lever_on.png</key>
<key type="filename">sprites/wires/sets/color_cross.png</key>
<key type="filename">sprites/wires/sets/color_forward.png</key>
<key type="filename">sprites/wires/sets/color_split.png</key>
<key type="filename">sprites/wires/sets/color_turn.png</key>
<key type="filename">sprites/wires/sets/conflict_cross.png</key> <key type="filename">sprites/wires/sets/conflict_cross.png</key>
<key type="filename">sprites/wires/sets/conflict_forward.png</key> <key type="filename">sprites/wires/sets/conflict_forward.png</key>
<key type="filename">sprites/wires/sets/conflict_split.png</key> <key type="filename">sprites/wires/sets/conflict_split.png</key>
<key type="filename">sprites/wires/sets/conflict_turn.png</key> <key type="filename">sprites/wires/sets/conflict_turn.png</key>
<key type="filename">sprites/wires/sets/regular_cross.png</key> <key type="filename">sprites/wires/sets/first_cross.png</key>
<key type="filename">sprites/wires/sets/regular_forward.png</key> <key type="filename">sprites/wires/sets/first_forward.png</key>
<key type="filename">sprites/wires/sets/regular_split.png</key> <key type="filename">sprites/wires/sets/first_split.png</key>
<key type="filename">sprites/wires/sets/regular_turn.png</key> <key type="filename">sprites/wires/sets/first_turn.png</key>
<key type="filename">sprites/wires/sets/shape_cross.png</key> <key type="filename">sprites/wires/sets/second_cross.png</key>
<key type="filename">sprites/wires/sets/shape_forward.png</key> <key type="filename">sprites/wires/sets/second_forward.png</key>
<key type="filename">sprites/wires/sets/shape_split.png</key> <key type="filename">sprites/wires/sets/second_split.png</key>
<key type="filename">sprites/wires/sets/shape_turn.png</key> <key type="filename">sprites/wires/sets/second_turn.png</key>
<key type="filename">sprites/wires/sets/third_cross.png</key>
<key type="filename">sprites/wires/sets/third_forward.png</key>
<key type="filename">sprites/wires/sets/third_split.png</key>
<key type="filename">sprites/wires/sets/third_turn.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>
@ -350,13 +321,6 @@
<key>scale9FromFile</key> <key>scale9FromFile</key>
<false/> <false/>
</struct> </struct>
<key type="filename">sprites/blueprints/balancer.png</key>
<key type="filename">sprites/blueprints/cutter.png</key>
<key type="filename">sprites/blueprints/filter.png</key>
<key type="filename">sprites/blueprints/mixer.png</key>
<key type="filename">sprites/blueprints/painter-mirrored.png</key>
<key type="filename">sprites/blueprints/painter.png</key>
<key type="filename">sprites/blueprints/stacker.png</key>
<key type="filename">sprites/buildings/balancer.png</key> <key type="filename">sprites/buildings/balancer.png</key>
<key type="filename">sprites/buildings/filter.png</key> <key type="filename">sprites/buildings/filter.png</key>
<key type="filename">sprites/buildings/painter-mirrored.png</key> <key type="filename">sprites/buildings/painter-mirrored.png</key>
@ -374,20 +338,9 @@
<key>scale9FromFile</key> <key>scale9FromFile</key>
<false/> <false/>
</struct> </struct>
<key type="filename">sprites/blueprints/belt_left.png</key>
<key type="filename">sprites/blueprints/belt_right.png</key>
<key type="filename">sprites/blueprints/belt_top.png</key>
<key type="filename">sprites/blueprints/wire-cross.png</key>
<key type="filename">sprites/blueprints/wire-split.png</key>
<key type="filename">sprites/blueprints/wire-turn.png</key>
<key type="filename">sprites/blueprints/wire.png</key>
<key type="filename">sprites/buildings/belt_left.png</key> <key type="filename">sprites/buildings/belt_left.png</key>
<key type="filename">sprites/buildings/belt_right.png</key> <key type="filename">sprites/buildings/belt_right.png</key>
<key type="filename">sprites/buildings/belt_top.png</key> <key type="filename">sprites/buildings/belt_top.png</key>
<key type="filename">sprites/buildings/wire-cross.png</key>
<key type="filename">sprites/buildings/wire-split.png</key>
<key type="filename">sprites/buildings/wire-turn.png</key>
<key type="filename">sprites/buildings/wire.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>
@ -402,8 +355,6 @@
<key>scale9FromFile</key> <key>scale9FromFile</key>
<false/> <false/>
</struct> </struct>
<key type="filename">sprites/blueprints/cutter-quad.png</key>
<key type="filename">sprites/blueprints/painter-quad.png</key>
<key type="filename">sprites/buildings/cutter-quad.png</key> <key type="filename">sprites/buildings/cutter-quad.png</key>
<key type="filename">sprites/buildings/painter-quad.png</key> <key type="filename">sprites/buildings/painter-quad.png</key>
<struct type="IndividualSpriteSettings"> <struct type="IndividualSpriteSettings">
@ -420,24 +371,6 @@
<key>scale9FromFile</key> <key>scale9FromFile</key>
<false/> <false/>
</struct> </struct>
<key type="filename">sprites/blueprints/painter-double.png</key>
<key type="filename">sprites/blueprints/storage.png</key>
<key type="filename">sprites/buildings/painter-double.png</key>
<key type="filename">sprites/buildings/storage.png</key>
<struct type="IndividualSpriteSettings">
<key>pivotPoint</key>
<point_f>0.5,0.5</point_f>
<key>spriteScale</key>
<double>1</double>
<key>scale9Enabled</key>
<false/>
<key>scale9Borders</key>
<rect>96,96,192,192</rect>
<key>scale9Paddings</key>
<rect>96,96,192,192</rect>
<key>scale9FromFile</key>
<false/>
</struct>
<key type="filename">sprites/buildings/cutter.png</key> <key type="filename">sprites/buildings/cutter.png</key>
<key type="filename">sprites/buildings/mixer.png</key> <key type="filename">sprites/buildings/mixer.png</key>
<key type="filename">sprites/buildings/painter.png</key> <key type="filename">sprites/buildings/painter.png</key>
@ -493,6 +426,22 @@
<key>scale9FromFile</key> <key>scale9FromFile</key>
<false/> <false/>
</struct> </struct>
<key type="filename">sprites/buildings/painter-double.png</key>
<key type="filename">sprites/buildings/storage.png</key>
<struct type="IndividualSpriteSettings">
<key>pivotPoint</key>
<point_f>0.5,0.5</point_f>
<key>spriteScale</key>
<double>1</double>
<key>scale9Enabled</key>
<false/>
<key>scale9Borders</key>
<rect>96,96,192,192</rect>
<key>scale9Paddings</key>
<rect>96,96,192,192</rect>
<key>scale9FromFile</key>
<false/>
</struct>
<key type="filename">sprites/colors/blue.png</key> <key type="filename">sprites/colors/blue.png</key>
<key type="filename">sprites/colors/cyan.png</key> <key type="filename">sprites/colors/cyan.png</key>
<key type="filename">sprites/colors/green.png</key> <key type="filename">sprites/colors/green.png</key>

View File

@ -1,226 +1,213 @@
/** /**
* *
* Run `yarn global add canvas` first * Run `yarn global add canvas` first
*/ */
const { createCanvas } = require("canvas"); const { createCanvas } = require("canvas");
const fs = require("fs"); const fs = require("fs");
const path = require("path"); const path = require("path");
const outputFolder = path.join(__dirname, "..", "wires", "sets"); const outputFolder = path.join(__dirname, "..", "wires", "sets");
const dimensions = 192; const dimensions = 192;
const lineSize = 12; const lineSize = 14;
const lowerLineSize = 20; const lowerLineSize = 32;
function hexToRGB(h) { const variants = {
let r = 0, first: "#61ef6f",
g = 0, second: "#f0bd65",
b = 0; third: "#5fb2f1",
conflict: "#f74c4c",
// 3 digits };
if (h.length == 4) {
r = "0x" + h[1] + h[1]; function hexToRGB(h) {
g = "0x" + h[2] + h[2]; let r = 0,
b = "0x" + h[3] + h[3]; g = 0,
b = 0;
// 6 digits
} else if (h.length == 7) { // 3 digits
r = "0x" + h[1] + h[2]; if (h.length == 4) {
g = "0x" + h[3] + h[4]; r = "0x" + h[1] + h[1];
b = "0x" + h[5] + h[6]; g = "0x" + h[2] + h[2];
} b = "0x" + h[3] + h[3];
return [+r, +g, +b]; // 6 digits
} } else if (h.length == 7) {
r = "0x" + h[1] + h[2];
function RGBToHSL(r, g, b) { g = "0x" + h[3] + h[4];
// Make r, g, and b fractions of 1 b = "0x" + h[5] + h[6];
r /= 255; }
g /= 255;
b /= 255; return [+r, +g, +b];
}
// Find greatest and smallest channel values
let cmin = Math.min(r, g, b), function RGBToHSL(r, g, b) {
cmax = Math.max(r, g, b), // Make r, g, and b fractions of 1
delta = cmax - cmin, r /= 255;
h = 0, g /= 255;
s = 0, b /= 255;
l = 0;
// Calculate hue // Find greatest and smallest channel values
// No difference let cmin = Math.min(r, g, b),
if (delta == 0) h = 0; cmax = Math.max(r, g, b),
// Red is max delta = cmax - cmin,
else if (cmax == r) h = ((g - b) / delta) % 6; h = 0,
// Green is max s = 0,
else if (cmax == g) h = (b - r) / delta + 2; l = 0;
// Blue is max // Calculate hue
else h = (r - g) / delta + 4; // No difference
if (delta == 0) h = 0;
h = Math.round(h * 60); // Red is max
else if (cmax == r) h = ((g - b) / delta) % 6;
// Make negative hues positive behind 360° // Green is max
if (h < 0) h += 360; else if (cmax == g) h = (b - r) / delta + 2;
// Blue is max
// Calculate lightness else h = (r - g) / delta + 4;
l = (cmax + cmin) / 2;
h = Math.round(h * 60);
// Calculate saturation
s = delta == 0 ? 0 : delta / (1 - Math.abs(2 * l - 1)); // Make negative hues positive behind 360°
if (h < 0) h += 360;
// Multiply l and s by 100
s = +(s * 100).toFixed(1); // Calculate lightness
l = +(l * 100).toFixed(1); l = (cmax + cmin) / 2;
return [h, s, l]; // Calculate saturation
} s = delta == 0 ? 0 : delta / (1 - Math.abs(2 * l - 1));
function HSLToRGB(h, s, l) { // Multiply l and s by 100
// Must be fractions of 1 s = +(s * 100).toFixed(1);
s /= 100; l = +(l * 100).toFixed(1);
l /= 100;
return [h, s, l];
let c = (1 - Math.abs(2 * l - 1)) * s, }
x = c * (1 - Math.abs(((h / 60) % 2) - 1)),
m = l - c / 2, function HSLToRGB(h, s, l) {
r = 0, // Must be fractions of 1
g = 0, s /= 100;
b = 0; l /= 100;
if (0 <= h && h < 60) { let c = (1 - Math.abs(2 * l - 1)) * s,
r = c; x = c * (1 - Math.abs(((h / 60) % 2) - 1)),
g = x; m = l - c / 2,
b = 0; r = 0,
} else if (60 <= h && h < 120) { g = 0,
r = x; b = 0;
g = c;
b = 0; if (0 <= h && h < 60) {
} else if (120 <= h && h < 180) { r = c;
r = 0; g = x;
g = c; b = 0;
b = x; } else if (60 <= h && h < 120) {
} else if (180 <= h && h < 240) { r = x;
r = 0; g = c;
g = x; b = 0;
b = c; } else if (120 <= h && h < 180) {
} else if (240 <= h && h < 300) { r = 0;
r = x; g = c;
g = 0; b = x;
b = c; } else if (180 <= h && h < 240) {
} else if (300 <= h && h < 360) { r = 0;
r = c; g = x;
g = 0; b = c;
b = x; } else if (240 <= h && h < 300) {
} r = x;
r = Math.round((r + m) * 255); g = 0;
g = Math.round((g + m) * 255); b = c;
b = Math.round((b + m) * 255); } else if (300 <= h && h < 360) {
r = c;
return [r, g, b]; g = 0;
} b = x;
}
async function run() { r = Math.round((r + m) * 255);
console.log("Running"); g = Math.round((g + m) * 255);
b = Math.round((b + m) * 255);
const variants = {
regular: "#25fff2", return [r, g, b];
color: "#eba458", }
shape: "#8858eb",
conflict: "#ff3e3e", async function run() {
}; console.log("Running");
const promises = []; const promises = [];
for (const variantId in variants) { for (const variantId in variants) {
const variantColor = variants[variantId]; const variantColor = variants[variantId];
const variantHSL = RGBToHSL(...hexToRGB(variantColor)); const variantHSL = RGBToHSL(...hexToRGB(variantColor));
const darkenedColor = HSLToRGB(variantHSL[0], variantHSL[1] - 15, variantHSL[2] - 20); const darkenedColor = HSLToRGB(variantHSL[0], variantHSL[1] - 15, variantHSL[2] - 20);
const hexDarkenedColor = "rgb(" + darkenedColor.join(",") + ")"; const hexDarkenedColor = "rgb(" + darkenedColor.join(",") + ")";
console.log(variantColor, "->", hexToRGB(variantColor), variantHSL, "->", darkenedColor); console.log(variantColor, "->", hexToRGB(variantColor), variantHSL, "->", darkenedColor);
const parts = { const parts = {
forward: [[0.5, 0, 0.5, 1]], forward: [[0.5, 0, 0.5, 1]],
turn: [ turn: [
[0.5, 0.5, 0.5, 1], [0.5, 0.5, 0.5, 1],
[0.5, 0.5, 1, 0.5], [0.5, 0.5, 1, 0.5],
], ],
split: [ split: [
[0.5, 0.5, 0.5, 1], [0.5, 0.5, 0.5, 1],
[0, 0.5, 1, 0.5], [0, 0.5, 1, 0.5],
], ],
cross: [ cross: [
[0, 0.5, 1, 0.5], [0, 0.5, 1, 0.5],
[0.5, 0, 0.5, 1], [0.5, 0, 0.5, 1],
], ],
}; };
for (const partId in parts) { for (const partId in parts) {
const partLines = parts[partId]; const partLines = parts[partId];
const canvas = createCanvas(dimensions, dimensions); const canvas = createCanvas(dimensions, dimensions);
const context = canvas.getContext("2d"); const context = canvas.getContext("2d");
context.quality = "best"; context.quality = "best";
context.clearRect(0, 0, dimensions, dimensions); context.clearRect(0, 0, dimensions, dimensions);
context.strokeStyle = hexDarkenedColor; const lineCanvas = createCanvas(dimensions, dimensions);
context.lineWidth = lowerLineSize; const lineContext = lineCanvas.getContext("2d");
context.lineCap = "square"; lineContext.quality = "best";
context.imageSmoothingEnabled = false; lineContext.clearRect(0, 0, dimensions, dimensions);
lineContext.strokeStyle = hexDarkenedColor;
// Draw lower lines lineContext.lineWidth = lowerLineSize;
partLines.forEach(([x1, y1, x2, y2]) => { lineContext.lineCap = "square";
context.beginPath(); lineContext.imageSmoothingEnabled = false;
context.moveTo(x1 * dimensions, y1 * dimensions);
context.lineTo(x2 * dimensions, y2 * dimensions); // Draw lower lines
context.stroke(); partLines.forEach(([x1, y1, x2, y2]) => {
}); lineContext.beginPath();
lineContext.moveTo(x1 * dimensions, y1 * dimensions);
context.strokeStyle = variantColor; lineContext.lineTo(x2 * dimensions, y2 * dimensions);
context.lineWidth = lineSize; lineContext.stroke();
});
// Draw upper lines
partLines.forEach(([x1, y1, x2, y2]) => { context.globalAlpha = 0.4;
context.beginPath(); context.drawImage(lineCanvas, 0, 0, dimensions, dimensions);
context.moveTo(x1 * dimensions, y1 * dimensions);
context.lineTo(x2 * dimensions, y2 * dimensions); context.globalAlpha = 1;
context.stroke(); context.imageSmoothingEnabled = false;
}); context.lineCap = "square";
context.strokeStyle = variantColor;
const out = fs.createWriteStream(path.join(outputFolder, variantId + "_" + partId + ".png")); context.lineWidth = lineSize;
const stream = canvas.createPNGStream();
stream.pipe(out); // Draw upper lines
promises.push(new Promise(resolve => stream.on("end", resolve))); partLines.forEach(([x1, y1, x2, y2]) => {
} context.beginPath();
} context.moveTo(x1 * dimensions, y1 * dimensions);
context.lineTo(x2 * dimensions, y2 * dimensions);
console.log("Waiting for completion"); context.stroke();
await Promise.all(promises); });
// Also wait a bit more const out = fs.createWriteStream(path.join(outputFolder, variantId + "_" + partId + ".png"));
await new Promise(resolve => setTimeout(resolve, 1000)); const stream = canvas.createPNGStream();
stream.pipe(out);
console.log("Copying files to all locations"); promises.push(new Promise(resolve => stream.on("end", resolve)));
}
// // Copy other files }
fs.copyFileSync(
path.join(outputFolder, "regular_forward.png"), console.log("Waiting for completion");
path.join(__dirname, "..", "buildings", "wire.png") await Promise.all(promises);
);
fs.copyFileSync( console.log("Done!");
path.join(outputFolder, "regular_turn.png"), }
path.join(__dirname, "..", "buildings", "wire-turn.png")
); run();
fs.copyFileSync(
path.join(outputFolder, "regular_split.png"),
path.join(__dirname, "..", "buildings", "wire-split.png")
);
fs.copyFileSync(
path.join(outputFolder, "regular_cross.png"),
path.join(__dirname, "..", "buildings", "wire-cross.png")
);
console.log("Done!");
}
run();

View File

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

View File

Before

Width:  |  Height:  |  Size: 8.3 KiB

After

Width:  |  Height:  |  Size: 8.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

View File

Before

Width:  |  Height:  |  Size: 7.4 KiB

After

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 957 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 854 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 676 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

After

Width:  |  Height:  |  Size: 3.7 KiB

View File

Before

Width:  |  Height:  |  Size: 9.5 KiB

After

Width:  |  Height:  |  Size: 9.5 KiB

View File

Before

Width:  |  Height:  |  Size: 7.6 KiB

After

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

View File

Before

Width:  |  Height:  |  Size: 7.1 KiB

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 695 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 503 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 498 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 646 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.5 KiB

View File

@ -1,110 +1,92 @@
# Requirements: numpy, scipy, Pillow, # Requirements: numpy, scipy, Pillow,
from __future__ import print_function from __future__ import print_function
import sys import sys
import numpy as np import numpy as np
from scipy import ndimage from scipy import ndimage
from PIL import Image, ImageFilter, ImageChops from PIL import Image, ImageFilter, ImageChops
import math import math
from os import listdir from os import listdir
from os.path import isdir, isfile from os.path import isdir, isfile
roberts_cross_v = np.array([[0, 0, 0], generate_blueprint_sprite_v = np.array([[0, 0, 0],
[0, 1, 0], [0, 1, 0],
[0, 0, -1]]) [0, 0, -1]])
roberts_cross_h = np.array([[0, 0, 0], generate_blueprint_sprite_h = np.array([[0, 0, 0],
[0, 0, 1], [0, 0, 1],
[0, -1, 0]]) [0, -1, 0]])
def rgb2gray(rgb): def rgb2gray(rgb):
return np.dot(rgb[..., :3], [0.2989, 0.5870, 0.1140]) return np.dot(rgb[..., :3], [0.2989, 0.5870, 0.1140])
def process_image(data, outfilename, src_image):
img = Image.fromarray(np.asarray(
np.clip(data, 0, 255), dtype="uint8"), "L")
def save_image(data, outfilename, src_image): dest = Image.new("RGBA", (img.width, img.height))
img = Image.fromarray(np.asarray( src = img.load()
np.clip(data, 0, 255), dtype="uint8"), "L") dst = dest.load()
dest = Image.new("RGBA", (img.width, img.height))
src = img.load() realSrc = src_image.load()
dst = dest.load() mask = src_image.filter(ImageFilter.GaussianBlur(10)).load()
orig = src_image.load()
realSrc = src_image.load()
mask = src_image.filter(ImageFilter.GaussianBlur(10)).load() # isWire = "wire" in outfilename
orig = src_image.load() isWire = False
targetR = 104
isWire = "wire" in outfilename targetG = 200
targetB = 255
targetR = 104
targetG = 200 if isWire:
targetB = 255 targetR = 255
targetG = 104
if isWire: targetB = 232
targetR = 255
targetG = 104 for x in range(img.width):
targetB = 232 for y in range(img.height):
realpixl = realSrc[x, y]
for x in range(img.width): greyval = float(src[x, y])
for y in range(img.height): greyval = min(255.0, greyval)
realpixl = realSrc[x, y] greyval = math.pow(
greyval = float(src[x, y]) min(1, float(greyval / 255.0 * 1)), 1.5) * 255.0 * 1
greyval = min(255.0, greyval) greyval = max(0, greyval)
greyval = math.pow( alpha = mask[x, y][3] / 255.0 * 1
min(1, float(greyval / 255.0 * 1)), 1.5) * 255.0 * 1
greyval = max(0, greyval) edgeFactor = src[x, y] / 255.0
alpha = mask[x, y][3] / 255.0 * 1 noEdge = 1 - edgeFactor
edgeFactor = src[x, y] / 255.0 shadow = min(1, 1 - realpixl[3] / 255.0 - edgeFactor)
noEdge = 1 - edgeFactor noShadow = 1 - shadow
shadow = min(1, 1 - realpixl[3] / 255.0 - edgeFactor) dst[x, y] = (
noShadow = 1 - shadow min(255, int((realpixl[0] / 255.0 * 0.4 + 0.6) * targetR * 1.1)),
min(255, int((realpixl[1] / 255.0 * 0.4 + 0.6) * targetG * 1.1)),
dst[x, y] = ( min(255, int((realpixl[2] / 255.0 * 0.4 + 0.6) * targetB * 1.1)),
min(255, int((realpixl[0] / 255.0 * 0.4 + 0.6) * targetR * 1.1)), min(255, int(float(realpixl[3]) * (0.6 + 5 * edgeFactor))))
min(255, int((realpixl[1] / 255.0 * 0.4 + 0.6) * targetG * 1.1)),
min(255, int((realpixl[2] / 255.0 * 0.4 + 0.6) * targetB * 1.1)),
min(255, int(float(realpixl[3]) * (0.6 + 5 * edgeFactor)))) dest.save(outfilename)
dest.save(outfilename) def generate_blueprint_sprite(infilename, outfilename):
print("Processing", infilename)
img = Image.open(infilename)
def roberts_cross(infilename, outfilename): img.load()
print("Processing", infilename) img = img.filter(ImageFilter.GaussianBlur(0.5))
img = Image.open(infilename)
img.load() image = rgb2gray(np.asarray(img, dtype="int32"))
img = img.filter(ImageFilter.GaussianBlur(0.5)) vertical = ndimage.convolve(image, generate_blueprint_sprite_v)
horizontal = ndimage.convolve(image, generate_blueprint_sprite_h)
image = rgb2gray(np.asarray(img, dtype="int32")) output_image = np.sqrt(np.square(horizontal) + np.square(vertical))
vertical = ndimage.convolve(image, roberts_cross_v) process_image(output_image, outfilename, img)
horizontal = ndimage.convolve(image, roberts_cross_h)
output_image = np.sqrt(np.square(horizontal) + np.square(vertical))
save_image(output_image, outfilename, img) buildings = listdir("buildings")
for buildingId in buildings:
def generateUiPreview(srcPath, buildingId): if "hub" in buildingId:
print(srcPath, buildingId) continue
img = Image.open(srcPath) if "wire-" in buildingId:
img.load() continue
img.thumbnail((110, 110), Image.ANTIALIAS) generate_blueprint_sprite("buildings/" + buildingId + "", "blueprints/" + buildingId + "")
img.save("../res/ui/hud/building_previews/" + buildingId + ".png")
img = img.convert("LA")
data = img.load()
for x in range(img.width):
for y in range(img.height):
data[x, y] = (data[x, y][0], int(data[x, y][1] * 0.5))
img.save("../res/ui/hud/building_previews/" + buildingId + "_disabled.png")
buildings = listdir("buildings")
for buildingId in buildings:
if "hub" in buildingId:
continue
roberts_cross("buildings/" + buildingId + "", "blueprints/" + buildingId + "")

Binary file not shown.

Before

Width:  |  Height:  |  Size: 701 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 649 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 502 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 501 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 690 B

After

Width:  |  Height:  |  Size: 703 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 642 B

After

Width:  |  Height:  |  Size: 647 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 501 B

After

Width:  |  Height:  |  Size: 520 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 496 B

After

Width:  |  Height:  |  Size: 513 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 707 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 649 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 526 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 513 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 695 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 646 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 503 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 498 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 705 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 648 B

After

Width:  |  Height:  |  Size: 651 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 525 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 516 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 699 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 501 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 500 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 706 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 651 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 527 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 515 B

View File

@ -1,5 +1,6 @@
$buildings: belt, cutter, miner, mixer, painter, rotater, balancer, stacker, trash, underground_belt, wire, $buildings: belt, cutter, miner, mixer, painter, rotater, balancer, stacker, trash, underground_belt, wire,
constant_signal, logic_gate, lever, filter, wire_tunnel, display, virtual_processor, reader, storage; constant_signal, logic_gate, lever, filter, wire_tunnel, display, virtual_processor, reader, storage,
transistor, analyzer, comparator;
@each $building in $buildings { @each $building in $buildings {
[data-icon="building_icons/#{$building}.png"] { [data-icon="building_icons/#{$building}.png"] {
@ -8,10 +9,11 @@ $buildings: belt, cutter, miner, mixer, painter, rotater, balancer, stacker, tra
} }
} }
$buildingsAndVariants: belt, balancer, balancer-merger, balancer-splitter, underground_belt, $buildingsAndVariants: belt, balancer, underground_belt, underground_belt-tier2, miner, miner-chainable,
underground_belt-tier2, miner, miner-chainable, cutter, cutter-quad, rotater, rotater-ccw, stacker, mixer, cutter, cutter-quad, rotater, rotater-ccw, stacker, mixer, painter-double, painter-quad, trash, storage,
painter, painter-double, painter-quad, trash, storage, reader, rotater-rotate180, lever, display, reader, rotater-rotate180, display, constant_signal, wire, wire_tunnel, logic_gate-or, logic_gate-not,
constant_signal; logic_gate-xor, analyzer, virtual_processor-rotater, virtual_processor-unstacker,
virtual_processor-stacker, virtual_processor-painter;
@each $building in $buildingsAndVariants { @each $building in $buildingsAndVariants {
[data-icon="building_tutorials/#{$building}.png"] { [data-icon="building_tutorials/#{$building}.png"] {
/* @load-async */ /* @load-async */
@ -19,26 +21,57 @@ $buildingsAndVariants: belt, balancer, balancer-merger, balancer-splitter, under
} }
} }
// @TODO: New buildings (balancer, wires, etc)
// Special cases for mirrored vairants // Special cases for mirrored vairants
[data-icon="building_tutorials/painter.png"],
[data-icon="building_tutorials/painter-mirrored.png"] { [data-icon="building_tutorials/painter-mirrored.png"] {
/* @load-async */ /* @load-async */
background-image: uiResource("res/ui/building_tutorials/painter.png") !important; background-image: uiResource("res/ui/building_tutorials/painter.png") !important;
} }
[data-icon="building_tutorials/balancer-merger.png"],
[data-icon="building_tutorials/balancer-merger-inverse.png"] { [data-icon="building_tutorials/balancer-merger-inverse.png"] {
/* @load-async */ /* @load-async */
background-image: uiResource("res/ui/building_tutorials/balancer-merger.png") !important; background-image: uiResource("res/ui/building_tutorials/balancer-merger.png") !important;
} }
[data-icon="building_tutorials/balancer-splitter.png"],
[data-icon="building_tutorials/balancer-splitter-inverse.png"] { [data-icon="building_tutorials/balancer-splitter-inverse.png"] {
/* @load-async */ /* @load-async */
background-image: uiResource("res/ui/building_tutorials/balancer-splitter.png") !important; background-image: uiResource("res/ui/building_tutorials/balancer-splitter.png") !important;
} }
[data-icon="building_tutorials/filter.png"] {
[data-icon="building_tutorials/transistor.png"],
[data-icon="building_tutorials/transistor-mirrored.png"] {
/* @load-async */
background-image: uiResource("res/ui/building_tutorials/transistor.png") !important;
}
// Filter and lever share tutorials
[data-icon="building_tutorials/filter.png"],
[data-icon="building_tutorials/lever.png"] {
/* @load-async */ /* @load-async */
background-image: uiResource("res/ui/building_tutorials/lever.png") !important; background-image: uiResource("res/ui/building_tutorials/lever.png") !important;
} }
// Wire types share tutorials
[data-icon="building_tutorials/wire-second.png"],
[data-icon="building_tutorials/wire-third.png"] {
/* @load-async */
background-image: uiResource("res/ui/building_tutorials/wire-second.png") !important;
}
// Logic gate
[data-icon="building_tutorials/logic_gate.png"] {
/* @load-async */
background-image: uiResource("res/ui/building_tutorials/logic_gate-and.png") !important;
}
// Virtual processor
[data-icon="building_tutorials/virtual_processor.png"] {
/* @load-async */
background-image: uiResource("res/ui/building_tutorials/virtual_processor-cutter.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"] {

View File

@ -0,0 +1,79 @@
import { generateMatrixRotations } from "../../core/utils";
import { enumDirection, Vector } from "../../core/vector";
import { enumLogicGateType, LogicGateComponent } from "../components/logic_gate";
import { enumPinSlotType, WiredPinsComponent } from "../components/wired_pins";
import { Entity } from "../entity";
import { MetaBuilding } from "../meta_building";
import { GameRoot } from "../root";
const overlayMatrix = generateMatrixRotations([1, 1, 0, 1, 1, 1, 0, 1, 0]);
export class MetaAnalyzerBuilding extends MetaBuilding {
constructor() {
super("analyzer");
}
getSilhouetteColor() {
return "#3a52bc";
}
/**
* @param {GameRoot} root
*/
getIsUnlocked(root) {
// @todo
return true;
}
/** @returns {"wires"} **/
getLayer() {
return "wires";
}
getDimensions() {
return new Vector(1, 1);
}
getRenderPins() {
// We already have it included
return false;
}
getSpecialOverlayRenderMatrix(rotation, rotationVariant, variant) {
return overlayMatrix[rotation];
}
/**
* Creates the entity at the given location
* @param {Entity} entity
*/
setupEntityComponents(entity) {
entity.addComponent(
new WiredPinsComponent({
slots: [
{
pos: new Vector(0, 0),
direction: enumDirection.left,
type: enumPinSlotType.logicalEjector,
},
{
pos: new Vector(0, 0),
direction: enumDirection.right,
type: enumPinSlotType.logicalEjector,
},
{
pos: new Vector(0, 0),
direction: enumDirection.bottom,
type: enumPinSlotType.logicalAcceptor,
},
],
})
);
entity.addComponent(
new LogicGateComponent({
type: enumLogicGateType.analyzer,
})
);
}
}

View File

@ -0,0 +1,72 @@
import { enumDirection, Vector } from "../../core/vector";
import { enumLogicGateType, LogicGateComponent } from "../components/logic_gate";
import { enumPinSlotType, WiredPinsComponent } from "../components/wired_pins";
import { Entity } from "../entity";
import { MetaBuilding } from "../meta_building";
import { GameRoot } from "../root";
export class MetaComparatorBuilding extends MetaBuilding {
constructor() {
super("comparator");
}
getSilhouetteColor() {
return "#823cab";
}
/**
* @param {GameRoot} root
*/
getIsUnlocked(root) {
// @todo
return true;
}
/** @returns {"wires"} **/
getLayer() {
return "wires";
}
getDimensions() {
return new Vector(1, 1);
}
getRenderPins() {
// We already have it included
return false;
}
/**
* Creates the entity at the given location
* @param {Entity} entity
*/
setupEntityComponents(entity) {
entity.addComponent(
new WiredPinsComponent({
slots: [
{
pos: new Vector(0, 0),
direction: enumDirection.top,
type: enumPinSlotType.logicalEjector,
},
{
pos: new Vector(0, 0),
direction: enumDirection.left,
type: enumPinSlotType.logicalAcceptor,
},
{
pos: new Vector(0, 0),
direction: enumDirection.right,
type: enumPinSlotType.logicalAcceptor,
},
],
})
);
entity.addComponent(
new LogicGateComponent({
type: enumLogicGateType.compare,
})
);
}
}

View File

@ -4,6 +4,9 @@ import { Entity } from "../entity";
import { MetaBuilding } from "../meta_building"; import { MetaBuilding } from "../meta_building";
import { GameRoot } from "../root"; import { GameRoot } from "../root";
import { ConstantSignalComponent } from "../components/constant_signal"; import { ConstantSignalComponent } from "../components/constant_signal";
import { generateMatrixRotations } from "../../core/utils";
const overlayMatrix = generateMatrixRotations([0, 1, 0, 1, 1, 1, 1, 1, 1]);
export class MetaConstantSignalBuilding extends MetaBuilding { export class MetaConstantSignalBuilding extends MetaBuilding {
constructor() { constructor() {
@ -11,7 +14,7 @@ export class MetaConstantSignalBuilding extends MetaBuilding {
} }
getSilhouetteColor() { getSilhouetteColor() {
return "#2bafda"; return "#2b84fd";
} }
/** /**
@ -35,6 +38,10 @@ export class MetaConstantSignalBuilding extends MetaBuilding {
return false; return false;
} }
getSpecialOverlayRenderMatrix(rotation) {
return overlayMatrix[rotation];
}
/** /**
* Creates the entity at the given location * Creates the entity at the given location
* @param {Entity} entity * @param {Entity} entity

View File

@ -1,155 +1,151 @@
import { enumDirection, Vector } from "../../core/vector"; import { enumDirection, Vector } from "../../core/vector";
import { enumPinSlotType, WiredPinsComponent } from "../components/wired_pins"; import { enumPinSlotType, WiredPinsComponent } from "../components/wired_pins";
import { Entity } from "../entity"; import { Entity } from "../entity";
import { MetaBuilding, defaultBuildingVariant } from "../meta_building"; import { MetaBuilding, defaultBuildingVariant } from "../meta_building";
import { GameRoot } from "../root"; import { GameRoot } from "../root";
import { enumLogicGateType, LogicGateComponent } from "../components/logic_gate"; import { enumLogicGateType, LogicGateComponent } from "../components/logic_gate";
import { generateMatrixRotations } from "../../core/utils";
/** @enum {string} */
export const enumLogicGateVariants = { /** @enum {string} */
not: "not", export const enumLogicGateVariants = {
xor: "xor", not: "not",
or: "or", xor: "xor",
transistor: "transistor", or: "or",
}; };
/** @enum {string} */ /** @enum {string} */
export const enumVariantToGate = { export const enumVariantToGate = {
[defaultBuildingVariant]: enumLogicGateType.and, [defaultBuildingVariant]: enumLogicGateType.and,
[enumLogicGateVariants.not]: enumLogicGateType.not, [enumLogicGateVariants.not]: enumLogicGateType.not,
[enumLogicGateVariants.xor]: enumLogicGateType.xor, [enumLogicGateVariants.xor]: enumLogicGateType.xor,
[enumLogicGateVariants.or]: enumLogicGateType.or, [enumLogicGateVariants.or]: enumLogicGateType.or,
[enumLogicGateVariants.transistor]: enumLogicGateType.transistor, };
};
const overlayMatrices = {
export class MetaLogicGateBuilding extends MetaBuilding { [defaultBuildingVariant]: generateMatrixRotations([0, 1, 0, 1, 1, 1, 0, 1, 1]),
constructor() { [enumLogicGateVariants.xor]: generateMatrixRotations([0, 1, 0, 1, 1, 1, 0, 1, 1]),
super("logic_gate"); [enumLogicGateVariants.or]: generateMatrixRotations([0, 1, 0, 1, 1, 1, 0, 1, 1]),
} [enumLogicGateVariants.not]: generateMatrixRotations([0, 1, 0, 0, 1, 0, 0, 1, 0]),
};
getSilhouetteColor() {
return "#89dc60"; const colors = {
} [defaultBuildingVariant]: "#f48d41",
[enumLogicGateVariants.xor]: "#f4a241",
/** [enumLogicGateVariants.or]: "#f4d041",
* @param {GameRoot} root [enumLogicGateVariants.not]: "#f44184",
*/ };
getIsUnlocked(root) {
// @todo export class MetaLogicGateBuilding extends MetaBuilding {
return true; constructor() {
} super("logic_gate");
}
/** @returns {"wires"} **/
getLayer() { getSilhouetteColor(variant) {
return "wires"; return colors[variant];
} }
getDimensions() { /**
return new Vector(1, 1); * @param {GameRoot} root
} */
getIsUnlocked(root) {
getAvailableVariants() { // @todo
return [ return true;
defaultBuildingVariant, }
enumLogicGateVariants.not,
enumLogicGateVariants.xor, /** @returns {"wires"} **/
enumLogicGateVariants.or, getLayer() {
enumLogicGateVariants.transistor, return "wires";
]; }
}
getDimensions() {
getRenderPins() { return new Vector(1, 1);
// We already have it included }
return false;
} getSpecialOverlayRenderMatrix(rotation, rotationVariant, variant) {
return overlayMatrices[variant][rotation];
/** }
*
* @param {Entity} entity getAvailableVariants() {
* @param {number} rotationVariant return [
*/ defaultBuildingVariant,
updateVariants(entity, rotationVariant, variant) { enumLogicGateVariants.or,
const gateType = enumVariantToGate[variant]; enumLogicGateVariants.not,
entity.components.LogicGate.type = gateType; enumLogicGateVariants.xor,
];
const pinComp = entity.components.WiredPins; }
switch (gateType) { getRenderPins() {
case enumLogicGateType.and: // We already have it included
case enumLogicGateType.xor: return false;
case enumLogicGateType.or: { }
pinComp.setSlots([
{ /**
pos: new Vector(0, 0), *
direction: enumDirection.top, * @param {Entity} entity
type: enumPinSlotType.logicalEjector, * @param {number} rotationVariant
}, */
{ updateVariants(entity, rotationVariant, variant) {
pos: new Vector(0, 0), const gateType = enumVariantToGate[variant];
direction: enumDirection.left, entity.components.LogicGate.type = gateType;
type: enumPinSlotType.logicalAcceptor,
}, const pinComp = entity.components.WiredPins;
{
pos: new Vector(0, 0), switch (gateType) {
direction: enumDirection.right, case enumLogicGateType.and:
type: enumPinSlotType.logicalAcceptor, case enumLogicGateType.xor:
}, case enumLogicGateType.or: {
]); pinComp.setSlots([
break; {
} pos: new Vector(0, 0),
case enumLogicGateType.transistor: { direction: enumDirection.top,
pinComp.setSlots([ type: enumPinSlotType.logicalEjector,
{ },
pos: new Vector(0, 0), {
direction: enumDirection.top, pos: new Vector(0, 0),
type: enumPinSlotType.logicalEjector, direction: enumDirection.left,
}, type: enumPinSlotType.logicalAcceptor,
{ },
pos: new Vector(0, 0), {
direction: enumDirection.left, pos: new Vector(0, 0),
type: enumPinSlotType.logicalAcceptor, direction: enumDirection.right,
}, type: enumPinSlotType.logicalAcceptor,
{ },
pos: new Vector(0, 0), ]);
direction: enumDirection.bottom, break;
type: enumPinSlotType.logicalAcceptor, }
},
]); case enumLogicGateType.not: {
break; pinComp.setSlots([
} {
pos: new Vector(0, 0),
case enumLogicGateType.not: { direction: enumDirection.top,
pinComp.setSlots([ type: enumPinSlotType.logicalEjector,
{ },
pos: new Vector(0, 0), {
direction: enumDirection.top, pos: new Vector(0, 0),
type: enumPinSlotType.logicalEjector, direction: enumDirection.bottom,
}, type: enumPinSlotType.logicalAcceptor,
{ },
pos: new Vector(0, 0), ]);
direction: enumDirection.bottom, break;
type: enumPinSlotType.logicalAcceptor, }
},
]); default:
break; assertAlways("unknown logic gate type: " + gateType);
} }
}
default:
assertAlways("unknown logic gate type: " + gateType); /**
} * Creates the entity at the given location
} * @param {Entity} entity
*/
/** setupEntityComponents(entity) {
* Creates the entity at the given location entity.addComponent(
* @param {Entity} entity new WiredPinsComponent({
*/ slots: [],
setupEntityComponents(entity) { })
entity.addComponent( );
new WiredPinsComponent({
slots: [], entity.addComponent(new LogicGateComponent({}));
}) }
); }
entity.addComponent(new LogicGateComponent({}));
}
}

View File

@ -0,0 +1,101 @@
import { generateMatrixRotations } from "../../core/utils";
import { enumDirection, Vector } from "../../core/vector";
import { enumLogicGateType, LogicGateComponent } from "../components/logic_gate";
import { enumPinSlotType, WiredPinsComponent } from "../components/wired_pins";
import { Entity } from "../entity";
import { defaultBuildingVariant, MetaBuilding } from "../meta_building";
import { GameRoot } from "../root";
/** @enum {string} */
export const enumTransistorVariants = {
mirrored: "mirrored",
};
const overlayMatrices = {
[defaultBuildingVariant]: generateMatrixRotations([0, 1, 0, 1, 1, 0, 0, 1, 0]),
[enumTransistorVariants.mirrored]: generateMatrixRotations([0, 1, 0, 0, 1, 1, 0, 1, 0]),
};
export class MetaTransistorBuilding extends MetaBuilding {
constructor() {
super("transistor");
}
getSilhouetteColor() {
return "#bc3a61";
}
/**
* @param {GameRoot} root
*/
getIsUnlocked(root) {
// @todo
return true;
}
/** @returns {"wires"} **/
getLayer() {
return "wires";
}
getDimensions() {
return new Vector(1, 1);
}
getAvailableVariants() {
return [defaultBuildingVariant, enumTransistorVariants.mirrored];
}
getSpecialOverlayRenderMatrix(rotation, rotationVariant, variant) {
return overlayMatrices[variant][rotation];
}
getRenderPins() {
// We already have it included
return false;
}
/**
*
* @param {Entity} entity
* @param {number} rotationVariant
*/
updateVariants(entity, rotationVariant, variant) {
entity.components.WiredPins.slots[1].direction =
variant === enumTransistorVariants.mirrored ? enumDirection.right : enumDirection.left;
}
/**
* Creates the entity at the given location
* @param {Entity} entity
*/
setupEntityComponents(entity) {
entity.addComponent(
new WiredPinsComponent({
slots: [
{
pos: new Vector(0, 0),
direction: enumDirection.top,
type: enumPinSlotType.logicalEjector,
},
{
pos: new Vector(0, 0),
direction: enumDirection.left,
type: enumPinSlotType.logicalAcceptor,
},
{
pos: new Vector(0, 0),
direction: enumDirection.bottom,
type: enumPinSlotType.logicalAcceptor,
},
],
})
);
entity.addComponent(
new LogicGateComponent({
type: enumLogicGateType.transistor,
})
);
}
}

View File

@ -4,13 +4,15 @@ import { WiredPinsComponent, enumPinSlotType } from "../components/wired_pins";
import { Entity } from "../entity"; import { Entity } from "../entity";
import { defaultBuildingVariant, MetaBuilding } from "../meta_building"; import { defaultBuildingVariant, MetaBuilding } from "../meta_building";
import { GameRoot } from "../root"; import { GameRoot } from "../root";
import { MetaCutterBuilding } from "./cutter";
import { MetaPainterBuilding } from "./painter";
import { MetaRotaterBuilding } from "./rotater";
import { MetaStackerBuilding } from "./stacker";
/** @enum {string} */ /** @enum {string} */
export const enumVirtualProcessorVariants = { export const enumVirtualProcessorVariants = {
analyzer: "analyzer",
rotater: "rotater", rotater: "rotater",
unstacker: "unstacker", unstacker: "unstacker",
shapecompare: "shapecompare",
stacker: "stacker", stacker: "stacker",
painter: "painter", painter: "painter",
}; };
@ -18,21 +20,27 @@ export const enumVirtualProcessorVariants = {
/** @enum {string} */ /** @enum {string} */
export const enumVariantToGate = { export const enumVariantToGate = {
[defaultBuildingVariant]: enumLogicGateType.cutter, [defaultBuildingVariant]: enumLogicGateType.cutter,
[enumVirtualProcessorVariants.analyzer]: enumLogicGateType.analyzer,
[enumVirtualProcessorVariants.rotater]: enumLogicGateType.rotater, [enumVirtualProcessorVariants.rotater]: enumLogicGateType.rotater,
[enumVirtualProcessorVariants.unstacker]: enumLogicGateType.unstacker, [enumVirtualProcessorVariants.unstacker]: enumLogicGateType.unstacker,
[enumVirtualProcessorVariants.shapecompare]: enumLogicGateType.shapecompare,
[enumVirtualProcessorVariants.stacker]: enumLogicGateType.stacker, [enumVirtualProcessorVariants.stacker]: enumLogicGateType.stacker,
[enumVirtualProcessorVariants.painter]: enumLogicGateType.painter, [enumVirtualProcessorVariants.painter]: enumLogicGateType.painter,
}; };
const colors = {
[defaultBuildingVariant]: new MetaCutterBuilding().getSilhouetteColor(),
[enumVirtualProcessorVariants.rotater]: new MetaRotaterBuilding().getSilhouetteColor(),
[enumVirtualProcessorVariants.unstacker]: new MetaStackerBuilding().getSilhouetteColor(),
[enumVirtualProcessorVariants.stacker]: new MetaStackerBuilding().getSilhouetteColor(),
[enumVirtualProcessorVariants.painter]: new MetaPainterBuilding().getSilhouetteColor(),
};
export class MetaVirtualProcessorBuilding extends MetaBuilding { export class MetaVirtualProcessorBuilding extends MetaBuilding {
constructor() { constructor() {
super("virtual_processor"); super("virtual_processor");
} }
getSilhouetteColor() { getSilhouetteColor(variant) {
return "#823cab"; return colors[variant];
} }
/** /**
@ -56,11 +64,9 @@ export class MetaVirtualProcessorBuilding extends MetaBuilding {
return [ return [
defaultBuildingVariant, defaultBuildingVariant,
enumVirtualProcessorVariants.rotater, enumVirtualProcessorVariants.rotater,
enumVirtualProcessorVariants.unstacker,
enumVirtualProcessorVariants.analyzer,
enumVirtualProcessorVariants.stacker, enumVirtualProcessorVariants.stacker,
enumVirtualProcessorVariants.painter, enumVirtualProcessorVariants.painter,
enumVirtualProcessorVariants.shapecompare, enumVirtualProcessorVariants.unstacker,
]; ];
} }
@ -80,7 +86,6 @@ export class MetaVirtualProcessorBuilding extends MetaBuilding {
const pinComp = entity.components.WiredPins; const pinComp = entity.components.WiredPins;
switch (gateType) { switch (gateType) {
case enumLogicGateType.cutter: case enumLogicGateType.cutter:
case enumLogicGateType.analyzer:
case enumLogicGateType.unstacker: { case enumLogicGateType.unstacker: {
pinComp.setSlots([ pinComp.setSlots([
{ {
@ -116,26 +121,6 @@ export class MetaVirtualProcessorBuilding extends MetaBuilding {
]); ]);
break; break;
} }
case enumLogicGateType.shapecompare: {
pinComp.setSlots([
{
pos: new Vector(0, 0),
direction: enumDirection.top,
type: enumPinSlotType.logicalEjector,
},
{
pos: new Vector(0, 0),
direction: enumDirection.left,
type: enumPinSlotType.logicalAcceptor,
},
{
pos: new Vector(0, 0),
direction: enumDirection.right,
type: enumPinSlotType.logicalAcceptor,
},
]);
break;
}
case enumLogicGateType.stacker: case enumLogicGateType.stacker:
case enumLogicGateType.painter: { case enumLogicGateType.painter: {
pinComp.setSlots([ pinComp.setSlots([

View File

@ -1,263 +1,272 @@
import { Loader } from "../../core/loader"; import { Loader } from "../../core/loader";
import { generateMatrixRotations } from "../../core/utils"; import { generateMatrixRotations } from "../../core/utils";
import { enumDirection, enumDirectionToAngle, enumDirectionToVector, Vector } from "../../core/vector"; import { enumDirection, Vector } from "../../core/vector";
import { SOUNDS } from "../../platform/sound"; import { SOUNDS } from "../../platform/sound";
import { enumWireType, WireComponent } from "../components/wire"; import { enumWireType, enumWireVariant, WireComponent } from "../components/wire";
import { Entity } from "../entity"; import { Entity } from "../entity";
import { MetaBuilding } from "../meta_building"; import { defaultBuildingVariant, MetaBuilding } from "../meta_building";
import { GameRoot } from "../root"; import { GameRoot } from "../root";
export const arrayWireRotationVariantToType = [ export const arrayWireRotationVariantToType = [
enumWireType.regular, enumWireType.forward,
enumWireType.turn, enumWireType.turn,
enumWireType.split, enumWireType.split,
enumWireType.cross, enumWireType.cross,
]; ];
export const wireOverlayMatrices = { export const wireOverlayMatrices = {
[enumWireType.regular]: generateMatrixRotations([0, 1, 0, 0, 1, 0, 0, 1, 0]), [enumWireType.forward]: generateMatrixRotations([0, 1, 0, 0, 1, 0, 0, 1, 0]),
[enumWireType.split]: generateMatrixRotations([0, 0, 0, 1, 1, 1, 0, 1, 0]), [enumWireType.split]: generateMatrixRotations([0, 0, 0, 1, 1, 1, 0, 1, 0]),
[enumWireType.turn]: generateMatrixRotations([0, 0, 0, 0, 1, 1, 0, 1, 0]), [enumWireType.turn]: generateMatrixRotations([0, 0, 0, 0, 1, 1, 0, 1, 0]),
[enumWireType.cross]: generateMatrixRotations([0, 1, 0, 1, 1, 1, 0, 1, 0]), [enumWireType.cross]: generateMatrixRotations([0, 1, 0, 1, 1, 1, 0, 1, 0]),
}; };
export class MetaWireBuilding extends MetaBuilding { /** @enum {string} */
constructor() { export const wireVariants = {
super("wire"); second: "second",
} third: "third",
};
getHasDirectionLockAvailable() {
return true; const enumWireVariantToVariant = {
} [defaultBuildingVariant]: enumWireVariant.first,
[wireVariants.second]: enumWireVariant.second,
getSilhouetteColor() { [wireVariants.third]: enumWireVariant.third,
return "#25fff2"; };
}
export class MetaWireBuilding extends MetaBuilding {
getDimensions() { constructor() {
return new Vector(1, 1); super("wire");
} }
getStayInPlacementMode() { getHasDirectionLockAvailable() {
return true; return true;
} }
getPlacementSound() { getSilhouetteColor() {
return SOUNDS.placeBelt; return "#61ef6f";
} }
getRotateAutomaticallyWhilePlacing() { getAvailableVariants() {
return true; return [defaultBuildingVariant, wireVariants.second, wireVariants.third];
} }
/** @returns {"wires"} **/ getDimensions() {
getLayer() { return new Vector(1, 1);
return "wires"; }
}
getStayInPlacementMode() {
getSprite() { return true;
return null; }
}
getPlacementSound() {
getIsReplaceable() { return SOUNDS.placeBelt;
return true; }
}
getRotateAutomaticallyWhilePlacing() {
/** return true;
* @param {GameRoot} root }
*/
getIsUnlocked(root) { /** @returns {"wires"} **/
// @todo getLayer() {
return true; return "wires";
} }
/** getSprite() {
* Creates the entity at the given location return null;
* @param {Entity} entity }
*/
setupEntityComponents(entity) { getIsReplaceable() {
// @todo return true;
entity.addComponent(new WireComponent({})); }
}
/**
/** * @param {GameRoot} root
* */
* @param {Entity} entity getIsUnlocked(root) {
* @param {number} rotationVariant // @todo
*/ return true;
updateVariants(entity, rotationVariant) { }
entity.components.Wire.type = arrayWireRotationVariantToType[rotationVariant];
} /**
* Creates the entity at the given location
/** * @param {Entity} entity
* */
* @param {number} rotation setupEntityComponents(entity) {
* @param {number} rotationVariant entity.addComponent(new WireComponent({}));
* @param {string} variant }
* @param {Entity} entity
*/ /**
getSpecialOverlayRenderMatrix(rotation, rotationVariant, variant, entity) { *
return wireOverlayMatrices[entity.components.Wire.type][rotation]; * @param {Entity} entity
} * @param {number} rotationVariant
* @param {string} variant
getPreviewSprite(rotationVariant) { */
switch (arrayWireRotationVariantToType[rotationVariant]) { updateVariants(entity, rotationVariant, variant) {
case enumWireType.regular: { entity.components.Wire.type = arrayWireRotationVariantToType[rotationVariant];
return Loader.getSprite("sprites/buildings/wire.png"); entity.components.Wire.variant = enumWireVariantToVariant[variant];
} }
case enumWireType.turn: {
return Loader.getSprite("sprites/buildings/wire-turn.png"); /**
} *
case enumWireType.split: { * @param {number} rotation
return Loader.getSprite("sprites/buildings/wire-split.png"); * @param {number} rotationVariant
} * @param {string} variant
case enumWireType.cross: { * @param {Entity} entity
return Loader.getSprite("sprites/buildings/wire-cross.png"); */
} getSpecialOverlayRenderMatrix(rotation, rotationVariant, variant, entity) {
default: { return wireOverlayMatrices[entity.components.Wire.type][rotation];
assertAlways(false, "Invalid wire rotation variant"); }
}
} /**
} *
* @param {number} rotationVariant
getBlueprintSprite(rotationVariant) { * @param {string} variant
switch (arrayWireRotationVariantToType[rotationVariant]) { * @returns {import("../../core/draw_utils").AtlasSprite}
case enumWireType.regular: { */
return Loader.getSprite("sprites/blueprints/wire.png"); getPreviewSprite(rotationVariant, variant) {
} const wireVariant = enumWireVariantToVariant[variant];
case enumWireType.turn: { switch (arrayWireRotationVariantToType[rotationVariant]) {
return Loader.getSprite("sprites/blueprints/wire-turn.png"); case enumWireType.forward: {
} return Loader.getSprite("sprites/wires/sets/" + wireVariant + "_forward.png");
case enumWireType.split: { }
return Loader.getSprite("sprites/blueprints/wire-split.png"); case enumWireType.turn: {
} return Loader.getSprite("sprites/wires/sets/" + wireVariant + "_turn.png");
case enumWireType.cross: { }
return Loader.getSprite("sprites/blueprints/wire-cross.png"); case enumWireType.split: {
} return Loader.getSprite("sprites/wires/sets/" + wireVariant + "_split.png");
default: { }
assertAlways(false, "Invalid wire rotation variant"); case enumWireType.cross: {
} return Loader.getSprite("sprites/wires/sets/" + wireVariant + "_cross.png");
} }
} default: {
assertAlways(false, "Invalid wire rotation variant");
/** }
* Should compute the optimal rotation variant on the given tile }
* @param {object} param0 }
* @param {GameRoot} param0.root
* @param {Vector} param0.tile getBlueprintSprite(rotationVariant, variant) {
* @param {number} param0.rotation return this.getPreviewSprite(rotationVariant, variant);
* @param {string} param0.variant }
* @param {string} param0.layer
* @return {{ rotation: number, rotationVariant: number, connectedEntities?: Array<Entity> }} /**
*/ * Should compute the optimal rotation variant on the given tile
computeOptimalDirectionAndRotationVariantAtTile({ root, tile, rotation, variant, layer }) { * @param {object} param0
const connections = { * @param {GameRoot} param0.root
top: root.logic.computeWireEdgeStatus({ tile, rotation, edge: enumDirection.top }), * @param {Vector} param0.tile
right: root.logic.computeWireEdgeStatus({ tile, rotation, edge: enumDirection.right }), * @param {number} param0.rotation
bottom: root.logic.computeWireEdgeStatus({ tile, rotation, edge: enumDirection.bottom }), * @param {string} param0.variant
left: root.logic.computeWireEdgeStatus({ tile, rotation, edge: enumDirection.left }), * @param {string} param0.layer
}; * @return {{ rotation: number, rotationVariant: number, connectedEntities?: Array<Entity> }}
*/
let flag = 0; computeOptimalDirectionAndRotationVariantAtTile({ root, tile, rotation, variant, layer }) {
flag |= connections.top ? 0x1000 : 0; const wireVariant = enumWireVariantToVariant[variant];
flag |= connections.right ? 0x100 : 0; const connections = {
flag |= connections.bottom ? 0x10 : 0; top: root.logic.computeWireEdgeStatus({ tile, wireVariant, edge: enumDirection.top }),
flag |= connections.left ? 0x1 : 0; right: root.logic.computeWireEdgeStatus({ tile, wireVariant, edge: enumDirection.right }),
bottom: root.logic.computeWireEdgeStatus({ tile, wireVariant, edge: enumDirection.bottom }),
let targetType = enumWireType.regular; left: root.logic.computeWireEdgeStatus({ tile, wireVariant, edge: enumDirection.left }),
};
// First, reset rotation
rotation = 0; let flag = 0;
flag |= connections.top ? 0x1000 : 0;
switch (flag) { flag |= connections.right ? 0x100 : 0;
case 0x0000: flag |= connections.bottom ? 0x10 : 0;
// Nothing flag |= connections.left ? 0x1 : 0;
break;
let targetType = enumWireType.forward;
case 0x0001:
// Left // First, reset rotation
rotation += 90; rotation = 0;
break;
switch (flag) {
case 0x0010: case 0x0000:
// Bottom // Nothing
// END break;
break;
case 0x0001:
case 0x0011: // Left
// Bottom | Left rotation += 90;
targetType = enumWireType.turn; break;
rotation += 90;
break; case 0x0010:
// Bottom
case 0x0100: // END
// Right break;
rotation += 90;
break; case 0x0011:
// Bottom | Left
case 0x0101: targetType = enumWireType.turn;
// Right | Left rotation += 90;
rotation += 90; break;
break;
case 0x0100:
case 0x0110: // Right
// Right | Bottom rotation += 90;
targetType = enumWireType.turn; break;
break;
case 0x0101:
case 0x0111: // Right | Left
// Right | Bottom | Left rotation += 90;
targetType = enumWireType.split; break;
break;
case 0x0110:
case 0x1000: // Right | Bottom
// Top targetType = enumWireType.turn;
break; break;
case 0x1001: case 0x0111:
// Top | Left // Right | Bottom | Left
targetType = enumWireType.turn; targetType = enumWireType.split;
rotation += 180; break;
break;
case 0x1000:
case 0x1010: // Top
// Top | Bottom break;
break;
case 0x1001:
case 0x1011: // Top | Left
// Top | Bottom | Left targetType = enumWireType.turn;
targetType = enumWireType.split; rotation += 180;
rotation += 90; break;
break;
case 0x1010:
case 0x1100: // Top | Bottom
// Top | Right break;
targetType = enumWireType.turn;
rotation -= 90; case 0x1011:
break; // Top | Bottom | Left
targetType = enumWireType.split;
case 0x1101: rotation += 90;
// Top | Right | Left break;
targetType = enumWireType.split;
rotation += 180; case 0x1100:
break; // Top | Right
targetType = enumWireType.turn;
case 0x1110: rotation -= 90;
// Top | Right | Bottom break;
targetType = enumWireType.split;
rotation -= 90; case 0x1101:
break; // Top | Right | Left
targetType = enumWireType.split;
case 0x1111: rotation += 180;
// Top | Right | Bottom | Left break;
targetType = enumWireType.cross;
break; case 0x1110:
} // Top | Right | Bottom
targetType = enumWireType.split;
return { rotation -= 90;
// Clamp rotation break;
rotation: (rotation + 360 * 10) % 360,
rotationVariant: arrayWireRotationVariantToType.indexOf(targetType), case 0x1111:
}; // Top | Right | Bottom | Left
} targetType = enumWireType.cross;
} break;
}
return {
// Clamp rotation
rotation: (rotation + 360 * 10) % 360,
rotationVariant: arrayWireRotationVariantToType.indexOf(targetType),
};
}
}

View File

@ -1,87 +1,58 @@
import { Vector } from "../../core/vector"; import { generateMatrixRotations } from "../../core/utils";
import { Entity } from "../entity"; import { Vector } from "../../core/vector";
import { MetaBuilding, defaultBuildingVariant } from "../meta_building"; import { WireTunnelComponent } from "../components/wire_tunnel";
import { GameRoot } from "../root"; import { Entity } from "../entity";
import { WireTunnelComponent } from "../components/wire_tunnel"; import { MetaBuilding } from "../meta_building";
import { generateMatrixRotations } from "../../core/utils"; import { GameRoot } from "../root";
import { enumHubGoalRewards } from "../tutorial_goals";
/** @enum {string} */
export const enumWireTunnelVariants = { const wireTunnelOverlayMatrix = generateMatrixRotations([0, 1, 0, 1, 1, 1, 0, 1, 0]);
coating: "coating",
}; export class MetaWireTunnelBuilding extends MetaBuilding {
constructor() {
const wireTunnelOverlayMatrices = { super("wire_tunnel");
[defaultBuildingVariant]: generateMatrixRotations([0, 1, 0, 1, 1, 1, 0, 1, 0]), }
[enumWireTunnelVariants.coating]: generateMatrixRotations([0, 1, 0, 0, 1, 0, 0, 1, 0]),
}; getSilhouetteColor() {
return "#777a86";
export class MetaWireTunnelBuilding extends MetaBuilding { }
constructor() {
super("wire_tunnel"); /**
} * @param {GameRoot} root
*/
getSilhouetteColor() { getIsUnlocked(root) {
return "#777a86"; return root.hubGoals.isRewardUnlocked(enumHubGoalRewards.reward_wires_filters_and_levers);
} }
/** /**
* @param {GameRoot} root *
*/ * @param {number} rotation
getIsUnlocked(root) { * @param {number} rotationVariant
// @todo * @param {string} variant
return true; * @param {Entity} entity
} */
getSpecialOverlayRenderMatrix(rotation, rotationVariant, variant, entity) {
/** return wireTunnelOverlayMatrix[rotation];
* }
* @param {number} rotation
* @param {number} rotationVariant getIsRotateable() {
* @param {string} variant return false;
* @param {Entity} entity }
*/
getSpecialOverlayRenderMatrix(rotation, rotationVariant, variant, entity) { getDimensions() {
return wireTunnelOverlayMatrices[variant][rotation]; return new Vector(1, 1);
} }
getIsRotateable(variant) { /** @returns {"wires"} **/
return variant !== defaultBuildingVariant; getLayer() {
} return "wires";
}
getDimensions() {
return new Vector(1, 1); /**
} * Creates the entity at the given location
* @param {Entity} entity
getAvailableVariants() { */
return [defaultBuildingVariant, enumWireTunnelVariants.coating]; setupEntityComponents(entity) {
} entity.addComponent(new WireTunnelComponent({}));
}
/** @returns {"wires"} **/ }
getLayer() {
return "wires";
}
getRotateAutomaticallyWhilePlacing() {
return true;
}
getStayInPlacementMode() {
return true;
}
/**
* Creates the entity at the given location
* @param {Entity} entity
*/
setupEntityComponents(entity) {
entity.addComponent(new WireTunnelComponent({}));
}
/**
* @param {Entity} entity
* @param {number} rotationVariant
* @param {string} variant
*/
updateVariants(entity, rotationVariant, variant) {
entity.components.WireTunnel.multipleDirections = variant === defaultBuildingVariant;
}
}

View File

@ -12,7 +12,7 @@ export const enumLogicGateType = {
rotater: "rotater", rotater: "rotater",
unstacker: "unstacker", unstacker: "unstacker",
cutter: "cutter", cutter: "cutter",
shapecompare: "shapecompare", compare: "compare",
stacker: "stacker", stacker: "stacker",
painter: "painter", painter: "painter",
}; };

View File

@ -63,6 +63,14 @@ export class StaticMapEntityComponent extends Component {
return getBuildingDataFromCode(this.code).metaInstance; return getBuildingDataFromCode(this.code).metaInstance;
} }
/**
* Returns the buildings variant
* @returns {string}
*/
getVariant() {
return getBuildingDataFromCode(this.code).variant;
}
/** /**
* Copy the current state to another component * Copy the current state to another component
* @param {Component} otherComponent * @param {Component} otherComponent

View File

@ -2,12 +2,19 @@ import { Component } from "../component";
/** @enum {string} */ /** @enum {string} */
export const enumWireType = { export const enumWireType = {
regular: "regular", forward: "forward",
turn: "turn", turn: "turn",
split: "split", split: "split",
cross: "cross", cross: "cross",
}; };
/** @enum {string} */
export const enumWireVariant = {
first: "first",
second: "second",
third: "third",
};
export class WireComponent extends Component { export class WireComponent extends Component {
static getId() { static getId() {
return "Wire"; return "Wire";
@ -16,54 +23,21 @@ export class WireComponent extends Component {
/** /**
* @param {object} param0 * @param {object} param0
* @param {enumWireType=} param0.type * @param {enumWireType=} param0.type
* @param {enumWireVariant=} param0.variant
*/ */
constructor({ type = enumWireType.regular }) { constructor({ type = enumWireType.forward, variant = enumWireVariant.first }) {
super(); super();
this.type = type; this.type = type;
/**
* The variant of the wire, different variants do not connect
* @type {enumWireVariant}
*/
this.variant = variant;
/** /**
* @type {import("../systems/wire").WireNetwork} * @type {import("../systems/wire").WireNetwork}
*/ */
this.linkedNetwork = null; this.linkedNetwork = null;
} }
/**
* Returns the local connections
* @returns {import("../../core/utils").DirectionalObject}
*/
getLocalConnections() {
return {
top: true,
right: false,
bottom: true,
left: false,
};
// switch (this.type) {
// case enumWireType.regular:
// return {
// top: true,
// right: false,
// bottom: true,
// left: false,
// };
// case enumWireType.turn:
// return {
// top: false,
// right: true,
// bottom: true,
// left: false,
// };
// case enumWireType.split:
// return {
// top: false,
// right: true,
// bottom: true,
// left: true,
// };
// default:
// assertAlways(false, "Invalid wire type: " + this.type);
// }
}
} }

View File

@ -5,13 +5,8 @@ export class WireTunnelComponent extends Component {
return "WireTunnel"; return "WireTunnel";
} }
/** constructor() {
* @param {object} param0
* @param {boolean=} param0.multipleDirections
*/
constructor({ multipleDirections = true }) {
super(); super();
this.multipleDirections = multipleDirections;
/** /**
* Linked network, only if its not multiple directions * Linked network, only if its not multiple directions

View File

@ -5,6 +5,9 @@ import { MetaLogicGateBuilding } from "../../buildings/logic_gate";
import { MetaLeverBuilding } from "../../buildings/lever"; import { MetaLeverBuilding } from "../../buildings/lever";
import { MetaWireTunnelBuilding } from "../../buildings/wire_tunnel"; import { MetaWireTunnelBuilding } from "../../buildings/wire_tunnel";
import { MetaVirtualProcessorBuilding } from "../../buildings/virtual_processor"; import { MetaVirtualProcessorBuilding } from "../../buildings/virtual_processor";
import { MetaTransistorBuilding } from "../../buildings/transistor";
import { MetaAnalyzerBuilding } from "../../buildings/analyzer";
import { MetaComparatorBuilding } from "../../buildings/comparator";
export class HUDWiresToolbar extends HUDBaseToolbar { export class HUDWiresToolbar extends HUDBaseToolbar {
constructor(root) { constructor(root) {
@ -13,9 +16,12 @@ export class HUDWiresToolbar extends HUDBaseToolbar {
MetaWireBuilding, MetaWireBuilding,
MetaWireTunnelBuilding, MetaWireTunnelBuilding,
MetaConstantSignalBuilding, MetaConstantSignalBuilding,
MetaTransistorBuilding,
MetaLogicGateBuilding, MetaLogicGateBuilding,
MetaAnalyzerBuilding,
MetaLeverBuilding, MetaLeverBuilding,
MetaVirtualProcessorBuilding, MetaVirtualProcessorBuilding,
MetaComparatorBuilding,
], ],
visibilityCondition: () => visibilityCondition: () =>
!this.root.camera.getIsMapOverlayActive() && this.root.currentLayer === "wires", !this.root.camera.getIsMapOverlayActive() && this.root.currentLayer === "wires",

View File

@ -64,8 +64,11 @@ export const KEYMAPPINGS = {
wire: { keyCode: key("1") }, wire: { keyCode: key("1") },
wire_tunnel: { keyCode: key("2") }, wire_tunnel: { keyCode: key("2") },
constant_signal: { keyCode: key("3") }, constant_signal: { keyCode: key("3") },
transistor: { keyCode: key("6") },
logic_gate: { keyCode: key("4") }, logic_gate: { keyCode: key("4") },
virtual_processor: { keyCode: key("5") }, virtual_processor: { keyCode: key("5") },
analyzer: { keyCode: key("7") },
comparator: { keyCode: key("8") },
}, },
placement: { placement: {

View File

@ -1,23 +1,18 @@
import { globalConfig } from "../core/config";
import { createLogger } from "../core/logging"; import { createLogger } from "../core/logging";
import { STOP_PROPAGATION } from "../core/signal"; import { STOP_PROPAGATION } from "../core/signal";
import { round2Digits } from "../core/utils"; import { round2Digits } from "../core/utils";
import { enumDirection, enumDirectionToVector, enumInvertedDirections, Vector } from "../core/vector"; import { enumDirection, enumDirectionToVector, enumInvertedDirections, Vector } from "../core/vector";
import { getBuildingDataFromCode } from "./building_codes"; import { getBuildingDataFromCode } from "./building_codes";
import { enumWireVariant } from "./components/wire";
import { Entity } from "./entity"; import { Entity } from "./entity";
import { CHUNK_OVERLAY_RES } from "./map_chunk_view";
import { MetaBuilding } from "./meta_building"; import { MetaBuilding } from "./meta_building";
import { GameRoot } from "./root"; import { GameRoot } from "./root";
import { WireNetwork } from "./systems/wire"; import { WireNetwork } from "./systems/wire";
import { globalConfig } from "../core/config";
import { CHUNK_OVERLAY_RES } from "./map_chunk_view";
const logger = createLogger("ingame/logic"); const logger = createLogger("ingame/logic");
/** @enum {number} */
export const enumWireEdgeFlag = {
empty: 0,
connected: 2,
};
/** /**
* Typing helper * Typing helper
* @typedef {Array<{ * @typedef {Array<{
@ -193,28 +188,72 @@ export class GameLogic {
* *
* Computes the flag for a given tile * Computes the flag for a given tile
* @param {object} param0 * @param {object} param0
* @param {enumWireVariant} param0.wireVariant
* @param {Vector} param0.tile The tile to check at * @param {Vector} param0.tile The tile to check at
* @param {enumDirection} param0.edge The edge to check for * @param {enumDirection} param0.edge The edge to check for
* @param {number} param0.rotation The local tiles base rotation
*/ */
computeWireEdgeStatus({ tile, edge, rotation }) { computeWireEdgeStatus({ wireVariant, tile, edge }) {
const offset = enumDirectionToVector[edge]; const offset = enumDirectionToVector[edge];
const refTile = tile.add(offset); const targetTile = tile.add(offset);
// const angle = enumDirectionToAngle[edge];
// // First, check if this edge can be connected from locally // Search for relevant pins
// const canConnectLocally = rotation === angle || (rotation + 180) % 360 === angle; const pinEntities = this.root.map.getLayersContentsMultipleXY(targetTile.x, targetTile.y);
const neighbourStatus = this.getWireEdgeFlag(refTile, edge); // Go over all entities which could have a pin
for (let i = 0; i < pinEntities.length; ++i) {
const pinEntity = pinEntities[i];
const pinComp = pinEntity.components.WiredPins;
const staticComp = pinEntity.components.StaticMapEntity;
if (neighbourStatus === enumWireEdgeFlag.empty) { // Skip those who don't have pins
// It's empty, no point in connecting if (!pinComp) {
continue;
}
// Go over all pins
const pins = pinComp.slots;
for (let k = 0; k < pinComp.slots.length; ++k) {
const pinSlot = pins[k];
const pinLocation = staticComp.localTileToWorld(pinSlot.pos);
const pinDirection = staticComp.localDirectionToWorld(pinSlot.direction);
// Check if the pin has the right location
if (!pinLocation.equals(targetTile)) {
continue;
}
// Check if the pin has the right direction
if (pinDirection !== enumInvertedDirections[edge]) {
continue;
}
// Found a pin!
return true;
}
}
// Now check if there's a connectable entity on the wires layer
const targetEntity = this.root.map.getTileContent(targetTile, "wires");
if (!targetEntity) {
return false; return false;
} }
if (neighbourStatus === enumWireEdgeFlag.connected) { const targetStaticComp = targetEntity.components.StaticMapEntity;
// Check if its a crossing
const wireTunnelComp = targetEntity.components.WireTunnel;
if (wireTunnelComp) {
return true; return true;
} }
// Check if its a wire
const wiresComp = targetEntity.components.Wire;
if (!wiresComp) {
return false;
}
// It's connected if its the same variant
return wiresComp.variant === wireVariant;
} }
/** /**
@ -303,85 +342,7 @@ export class GameLogic {
return !!overlayMatrix[localPosition.x + localPosition.y * 3]; return !!overlayMatrix[localPosition.x + localPosition.y * 3];
} }
/** g(tile, edge) {}
* Gets the flag at the given tile
* @param {Vector} tile
* @param {enumDirection} edge
* @returns {enumWireEdgeFlag}
*/
getWireEdgeFlag(tile, edge) {
// Search for relevant pins
const pinEntities = this.root.map.getLayersContentsMultipleXY(tile.x, tile.y);
// Go over all entities which could have a pin
for (let i = 0; i < pinEntities.length; ++i) {
const pinEntity = pinEntities[i];
const pinComp = pinEntity.components.WiredPins;
const staticComp = pinEntity.components.StaticMapEntity;
// Skip those who don't have pins
if (!pinComp) {
continue;
}
// Go over all pins
const pins = pinComp.slots;
for (let k = 0; k < pinComp.slots.length; ++k) {
const pinSlot = pins[k];
const pinLocation = staticComp.localTileToWorld(pinSlot.pos);
const pinDirection = staticComp.localDirectionToWorld(pinSlot.direction);
// Check if the pin has the right location
if (!pinLocation.equals(tile)) {
continue;
}
// Check if the pin has the right direction
if (pinDirection !== enumInvertedDirections[edge]) {
continue;
}
// Found a pin!
return enumWireEdgeFlag.connected;
}
}
// Now check if there's a connectable wire
const targetEntity = this.root.map.getTileContent(tile, "wires");
if (!targetEntity) {
return enumWireEdgeFlag.empty;
}
const targetStaticComp = targetEntity.components.StaticMapEntity;
// Check if its a crossing
const wireTunnelComp = targetEntity.components.WireTunnel;
if (wireTunnelComp) {
// Check if the crossing is connected
if (wireTunnelComp.multipleDirections) {
return enumWireEdgeFlag.connected;
} else {
// Its a coating, check if it matches the direction
const referenceDirection = targetStaticComp.localDirectionToWorld(enumDirection.top);
return referenceDirection === edge || enumInvertedDirections[referenceDirection] === edge
? enumWireEdgeFlag.connected
: enumWireEdgeFlag.empty;
}
}
// Check if its a wire
const wiresComp = targetEntity.components.Wire;
if (!wiresComp) {
return enumWireEdgeFlag.empty;
}
// const refAngle = enumDirectionToAngle[edge];
// const refRotation = targetEntity.components.StaticMapEntity.originalRotation;
// const canConnectRemotely = refRotation === refAngle || (refRotation + 180) % 360 === refAngle;
// Actually connected
return enumWireEdgeFlag.connected;
}
/** /**
* Returns the acceptors and ejectors which affect the current tile * Returns the acceptors and ejectors which affect the current tile

View File

@ -1,30 +1,34 @@
import { gMetaBuildingRegistry } from "../core/global_registries"; import { gMetaBuildingRegistry } from "../core/global_registries";
import { createLogger } from "../core/logging"; import { createLogger } from "../core/logging";
import { T } from "../translations";
import { MetaAnalyzerBuilding } from "./buildings/analyzer";
import { enumBalancerVariants, MetaBalancerBuilding } from "./buildings/balancer";
import { MetaBeltBuilding } from "./buildings/belt"; import { MetaBeltBuilding } from "./buildings/belt";
import { MetaComparatorBuilding } from "./buildings/comparator";
import { MetaConstantSignalBuilding } from "./buildings/constant_signal";
import { enumCutterVariants, MetaCutterBuilding } from "./buildings/cutter"; import { enumCutterVariants, MetaCutterBuilding } from "./buildings/cutter";
import { MetaDisplayBuilding } from "./buildings/display";
import { MetaFilterBuilding } from "./buildings/filter";
import { MetaHubBuilding } from "./buildings/hub"; import { MetaHubBuilding } from "./buildings/hub";
import { MetaLeverBuilding } from "./buildings/lever";
import { enumLogicGateVariants, MetaLogicGateBuilding } from "./buildings/logic_gate";
import { enumMinerVariants, MetaMinerBuilding } from "./buildings/miner"; import { enumMinerVariants, MetaMinerBuilding } from "./buildings/miner";
import { MetaMixerBuilding } from "./buildings/mixer"; import { MetaMixerBuilding } from "./buildings/mixer";
import { enumPainterVariants, MetaPainterBuilding } from "./buildings/painter"; import { enumPainterVariants, MetaPainterBuilding } from "./buildings/painter";
import { MetaReaderBuilding } from "./buildings/reader";
import { enumRotaterVariants, MetaRotaterBuilding } from "./buildings/rotater"; import { enumRotaterVariants, MetaRotaterBuilding } from "./buildings/rotater";
import { enumBalancerVariants, MetaBalancerBuilding } from "./buildings/balancer";
import { MetaStackerBuilding } from "./buildings/stacker"; import { MetaStackerBuilding } from "./buildings/stacker";
import { MetaStorageBuilding } from "./buildings/storage";
import { MetaTransistorBuilding, enumTransistorVariants } from "./buildings/transistor";
import { MetaTrashBuilding } from "./buildings/trash"; import { MetaTrashBuilding } from "./buildings/trash";
import { enumUndergroundBeltVariants, MetaUndergroundBeltBuilding } from "./buildings/underground_belt"; import { enumUndergroundBeltVariants, MetaUndergroundBeltBuilding } from "./buildings/underground_belt";
import { enumVirtualProcessorVariants, MetaVirtualProcessorBuilding } from "./buildings/virtual_processor";
import { MetaWireBuilding } from "./buildings/wire"; import { MetaWireBuilding } from "./buildings/wire";
import { MetaWireTunnelBuilding } from "./buildings/wire_tunnel";
import { buildBuildingCodeCache, gBuildingVariants, registerBuildingVariant } from "./building_codes"; import { buildBuildingCodeCache, gBuildingVariants, registerBuildingVariant } from "./building_codes";
import { defaultBuildingVariant } from "./meta_building"; import { enumWireVariant } from "./components/wire";
import { MetaConstantSignalBuilding } from "./buildings/constant_signal";
import { MetaLogicGateBuilding, enumLogicGateVariants } from "./buildings/logic_gate";
import { MetaLeverBuilding } from "./buildings/lever";
import { MetaFilterBuilding } from "./buildings/filter";
import { MetaWireTunnelBuilding, enumWireTunnelVariants } from "./buildings/wire_tunnel";
import { MetaDisplayBuilding } from "./buildings/display";
import { MetaVirtualProcessorBuilding, enumVirtualProcessorVariants } from "./buildings/virtual_processor";
import { MetaReaderBuilding } from "./buildings/reader";
import { MetaStorageBuilding } from "./buildings/storage";
import { KEYMAPPINGS } from "./key_action_mapper"; import { KEYMAPPINGS } from "./key_action_mapper";
import { T } from "../translations"; import { defaultBuildingVariant } from "./meta_building";
const logger = createLogger("building_registry"); const logger = createLogger("building_registry");
@ -50,6 +54,9 @@ export function initMetaBuildingRegistry() {
gMetaBuildingRegistry.register(MetaDisplayBuilding); gMetaBuildingRegistry.register(MetaDisplayBuilding);
gMetaBuildingRegistry.register(MetaVirtualProcessorBuilding); gMetaBuildingRegistry.register(MetaVirtualProcessorBuilding);
gMetaBuildingRegistry.register(MetaReaderBuilding); gMetaBuildingRegistry.register(MetaReaderBuilding);
gMetaBuildingRegistry.register(MetaTransistorBuilding);
gMetaBuildingRegistry.register(MetaAnalyzerBuilding);
gMetaBuildingRegistry.register(MetaComparatorBuilding);
// Belt // Belt
registerBuildingVariant(1, MetaBeltBuilding, defaultBuildingVariant, 0); registerBuildingVariant(1, MetaBeltBuilding, defaultBuildingVariant, 0);
@ -109,6 +116,16 @@ export function initMetaBuildingRegistry() {
registerBuildingVariant(29, MetaWireBuilding, defaultBuildingVariant, 2); registerBuildingVariant(29, MetaWireBuilding, defaultBuildingVariant, 2);
registerBuildingVariant(30, MetaWireBuilding, defaultBuildingVariant, 3); registerBuildingVariant(30, MetaWireBuilding, defaultBuildingVariant, 3);
registerBuildingVariant(52, MetaWireBuilding, enumWireVariant.second, 0);
registerBuildingVariant(53, MetaWireBuilding, enumWireVariant.second, 1);
registerBuildingVariant(54, MetaWireBuilding, enumWireVariant.second, 2);
registerBuildingVariant(55, MetaWireBuilding, enumWireVariant.second, 3);
registerBuildingVariant(56, MetaWireBuilding, enumWireVariant.third, 0);
registerBuildingVariant(57, MetaWireBuilding, enumWireVariant.third, 1);
registerBuildingVariant(58, MetaWireBuilding, enumWireVariant.third, 2);
registerBuildingVariant(59, MetaWireBuilding, enumWireVariant.third, 3);
// Constant signal // Constant signal
registerBuildingVariant(31, MetaConstantSignalBuilding); registerBuildingVariant(31, MetaConstantSignalBuilding);
@ -117,7 +134,10 @@ export function initMetaBuildingRegistry() {
registerBuildingVariant(34, MetaLogicGateBuilding, enumLogicGateVariants.not); registerBuildingVariant(34, MetaLogicGateBuilding, enumLogicGateVariants.not);
registerBuildingVariant(35, MetaLogicGateBuilding, enumLogicGateVariants.xor); registerBuildingVariant(35, MetaLogicGateBuilding, enumLogicGateVariants.xor);
registerBuildingVariant(36, MetaLogicGateBuilding, enumLogicGateVariants.or); registerBuildingVariant(36, MetaLogicGateBuilding, enumLogicGateVariants.or);
registerBuildingVariant(38, MetaLogicGateBuilding, enumLogicGateVariants.transistor);
// Transistor
registerBuildingVariant(38, MetaTransistorBuilding, defaultBuildingVariant);
registerBuildingVariant(60, MetaTransistorBuilding, enumTransistorVariants.mirrored);
// Lever // Lever
registerBuildingVariant(33, MetaLeverBuilding); registerBuildingVariant(33, MetaLeverBuilding);
@ -127,20 +147,21 @@ export function initMetaBuildingRegistry() {
// Wire tunnel // Wire tunnel
registerBuildingVariant(39, MetaWireTunnelBuilding); registerBuildingVariant(39, MetaWireTunnelBuilding);
registerBuildingVariant(41, MetaWireTunnelBuilding, enumWireTunnelVariants.coating);
// Display // Display
registerBuildingVariant(40, MetaDisplayBuilding); registerBuildingVariant(40, MetaDisplayBuilding);
// Virtual Processor // Virtual Processor
registerBuildingVariant(42, MetaVirtualProcessorBuilding); registerBuildingVariant(42, MetaVirtualProcessorBuilding);
registerBuildingVariant(43, MetaVirtualProcessorBuilding, enumVirtualProcessorVariants.analyzer);
registerBuildingVariant(44, MetaVirtualProcessorBuilding, enumVirtualProcessorVariants.rotater); registerBuildingVariant(44, MetaVirtualProcessorBuilding, enumVirtualProcessorVariants.rotater);
registerBuildingVariant(45, MetaVirtualProcessorBuilding, enumVirtualProcessorVariants.unstacker); registerBuildingVariant(45, MetaVirtualProcessorBuilding, enumVirtualProcessorVariants.unstacker);
registerBuildingVariant(46, MetaVirtualProcessorBuilding, enumVirtualProcessorVariants.shapecompare);
registerBuildingVariant(50, MetaVirtualProcessorBuilding, enumVirtualProcessorVariants.stacker); registerBuildingVariant(50, MetaVirtualProcessorBuilding, enumVirtualProcessorVariants.stacker);
registerBuildingVariant(51, MetaVirtualProcessorBuilding, enumVirtualProcessorVariants.painter); registerBuildingVariant(51, MetaVirtualProcessorBuilding, enumVirtualProcessorVariants.painter);
// Analyzer
registerBuildingVariant(46, MetaComparatorBuilding);
registerBuildingVariant(43, MetaAnalyzerBuilding);
// Reader // Reader
registerBuildingVariant(49, MetaReaderBuilding); registerBuildingVariant(49, MetaReaderBuilding);

View File

@ -3,11 +3,9 @@ import { enumColors } from "../colors";
import { enumLogicGateType, LogicGateComponent } from "../components/logic_gate"; import { enumLogicGateType, LogicGateComponent } from "../components/logic_gate";
import { enumPinSlotType } from "../components/wired_pins"; import { enumPinSlotType } from "../components/wired_pins";
import { GameSystemWithFilter } from "../game_system_with_filter"; import { GameSystemWithFilter } from "../game_system_with_filter";
import { BOOL_FALSE_SINGLETON, BOOL_TRUE_SINGLETON, isTruthyItem, BooleanItem } from "../items/boolean_item"; import { BOOL_FALSE_SINGLETON, BOOL_TRUE_SINGLETON, isTruthyItem } from "../items/boolean_item";
import { COLOR_ITEM_SINGLETONS, ColorItem } from "../items/color_item"; import { COLOR_ITEM_SINGLETONS } from "../items/color_item";
import { ShapeDefinition } from "../shape_definition"; import { ShapeDefinition } from "../shape_definition";
import { ShapeItem } from "../items/shape_item";
import { enumInvertedDirections } from "../../core/vector";
export class LogicGateSystem extends GameSystemWithFilter { export class LogicGateSystem extends GameSystemWithFilter {
constructor(root) { constructor(root) {
@ -24,7 +22,7 @@ export class LogicGateSystem extends GameSystemWithFilter {
[enumLogicGateType.analyzer]: this.compute_ANALYZE.bind(this), [enumLogicGateType.analyzer]: this.compute_ANALYZE.bind(this),
[enumLogicGateType.cutter]: this.compute_CUT.bind(this), [enumLogicGateType.cutter]: this.compute_CUT.bind(this),
[enumLogicGateType.unstacker]: this.compute_UNSTACK.bind(this), [enumLogicGateType.unstacker]: this.compute_UNSTACK.bind(this),
[enumLogicGateType.shapecompare]: this.compute_SHAPECOMPARE.bind(this), [enumLogicGateType.compare]: this.compute_COMPARE.bind(this),
[enumLogicGateType.stacker]: this.compute_STACKER.bind(this), [enumLogicGateType.stacker]: this.compute_STACKER.bind(this),
[enumLogicGateType.painter]: this.compute_PAINTER.bind(this), [enumLogicGateType.painter]: this.compute_PAINTER.bind(this),
}; };
@ -318,7 +316,7 @@ export class LogicGateSystem extends GameSystemWithFilter {
* @param {Array<BaseItem|null>} parameters * @param {Array<BaseItem|null>} parameters
* @returns {BaseItem} * @returns {BaseItem}
*/ */
compute_SHAPECOMPARE(parameters) { compute_COMPARE(parameters) {
const itemA = parameters[0]; const itemA = parameters[0];
const itemB = parameters[1]; const itemB = parameters[1];

View File

@ -3,6 +3,7 @@ import { gMetaBuildingRegistry } from "../../core/global_registries";
import { Loader } from "../../core/loader"; import { Loader } from "../../core/loader";
import { createLogger } from "../../core/logging"; import { createLogger } from "../../core/logging";
import { Rectangle } from "../../core/rectangle"; import { Rectangle } from "../../core/rectangle";
import { AtlasSprite } from "../../core/sprites";
import { StaleAreaDetector } from "../../core/stale_area_detector"; import { StaleAreaDetector } from "../../core/stale_area_detector";
import { fastArrayDeleteValueIfContained } from "../../core/utils"; import { fastArrayDeleteValueIfContained } from "../../core/utils";
import { import {
@ -13,16 +14,15 @@ import {
Vector, Vector,
} from "../../core/vector"; } from "../../core/vector";
import { BaseItem } from "../base_item"; import { BaseItem } from "../base_item";
import { isTrueItem } from "../items/boolean_item";
import { arrayWireRotationVariantToType, MetaWireBuilding } from "../buildings/wire"; import { arrayWireRotationVariantToType, MetaWireBuilding } from "../buildings/wire";
import { getCodeFromBuildingData } from "../building_codes"; import { getCodeFromBuildingData } from "../building_codes";
import { enumWireType, WireComponent } from "../components/wire"; import { enumWireType, enumWireVariant, WireComponent } from "../components/wire";
import { enumPinSlotType, WiredPinsComponent } from "../components/wired_pins"; import { enumPinSlotType, WiredPinsComponent } from "../components/wired_pins";
import { WireTunnelComponent } from "../components/wire_tunnel"; import { WireTunnelComponent } from "../components/wire_tunnel";
import { Entity } from "../entity"; import { Entity } from "../entity";
import { GameSystemWithFilter } from "../game_system_with_filter"; import { GameSystemWithFilter } from "../game_system_with_filter";
import { isTruthyItem } from "../items/boolean_item";
import { MapChunkView } from "../map_chunk_view"; import { MapChunkView } from "../map_chunk_view";
import { defaultBuildingVariant } from "../meta_building";
const logger = createLogger("wires"); const logger = createLogger("wires");
@ -93,32 +93,22 @@ export class WireSystem extends GameSystemWithFilter {
constructor(root) { constructor(root) {
super(root, [WireComponent]); super(root, [WireComponent]);
this.wireSprites = { /**
regular: { * @type {Object<enumWireVariant, Object<enumWireType, AtlasSprite>>}
[enumWireType.regular]: Loader.getSprite("sprites/wires/sets/regular_forward.png"), */
[enumWireType.turn]: Loader.getSprite("sprites/wires/sets/regular_turn.png"), this.wireSprites = {};
[enumWireType.split]: Loader.getSprite("sprites/wires/sets/regular_split.png"),
[enumWireType.cross]: Loader.getSprite("sprites/wires/sets/regular_cross.png"), const variants = ["conflict", ...Object.keys(enumWireVariant)];
}, for (let i = 0; i < variants.length; ++i) {
conflict: { const wireVariant = variants[i];
[enumWireType.regular]: Loader.getSprite("sprites/wires/sets/conflict_forward.png"), const sprites = {};
[enumWireType.turn]: Loader.getSprite("sprites/wires/sets/conflict_turn.png"), for (const wireType in enumWireType) {
[enumWireType.split]: Loader.getSprite("sprites/wires/sets/conflict_split.png"), sprites[wireType] = Loader.getSprite(
[enumWireType.cross]: Loader.getSprite("sprites/wires/sets/conflict_cross.png"), "sprites/wires/sets/" + wireVariant + "_" + wireType + ".png"
}, );
shape: { }
[enumWireType.regular]: Loader.getSprite("sprites/wires/sets/shape_forward.png"), this.wireSprites[wireVariant] = sprites;
[enumWireType.turn]: Loader.getSprite("sprites/wires/sets/shape_turn.png"), }
[enumWireType.split]: Loader.getSprite("sprites/wires/sets/shape_split.png"),
[enumWireType.cross]: Loader.getSprite("sprites/wires/sets/shape_cross.png"),
},
color: {
[enumWireType.regular]: Loader.getSprite("sprites/wires/sets/color_forward.png"),
[enumWireType.turn]: Loader.getSprite("sprites/wires/sets/color_turn.png"),
[enumWireType.split]: Loader.getSprite("sprites/wires/sets/color_split.png"),
[enumWireType.cross]: Loader.getSprite("sprites/wires/sets/color_cross.png"),
},
};
this.root.signals.entityDestroyed.add(this.queuePlacementUpdate, this); this.root.signals.entityDestroyed.add(this.queuePlacementUpdate, this);
this.root.signals.entityAdded.add(this.queuePlacementUpdate, this); this.root.signals.entityAdded.add(this.queuePlacementUpdate, this);
@ -230,6 +220,13 @@ export class WireSystem extends GameSystemWithFilter {
}, },
]; ];
/**
* Once we occur a wire, we store its variant so we don't connect to
* mismatching ones
* @type {enumWireVariant}
*/
let variantMask = null;
while (entitiesToVisit.length > 0) { while (entitiesToVisit.length > 0) {
const nextData = entitiesToVisit.pop(); const nextData = entitiesToVisit.pop();
const nextEntity = nextData.entity; const nextEntity = nextData.entity;
@ -257,13 +254,18 @@ export class WireSystem extends GameSystemWithFilter {
); );
if (!wireComp.linkedNetwork) { if (!wireComp.linkedNetwork) {
// This one is new! :D if (variantMask && wireComp.variant !== variantMask) {
VERBOSE_WIRES && logger.log(" Visited new wire:", staticComp.origin.toString()); // Mismatching variant
wireComp.linkedNetwork = currentNetwork; } else {
currentNetwork.wires.push(nextEntity); // This one is new! :D
VERBOSE_WIRES && logger.log(" Visited new wire:", staticComp.origin.toString());
wireComp.linkedNetwork = currentNetwork;
currentNetwork.wires.push(nextEntity);
newSearchDirections = arrayAllDirections; newSearchDirections = arrayAllDirections;
newSearchTile = nextEntity.components.StaticMapEntity.origin; newSearchTile = nextEntity.components.StaticMapEntity.origin;
variantMask = wireComp.variant;
}
} }
} }
@ -319,7 +321,8 @@ export class WireSystem extends GameSystemWithFilter {
const newTargets = this.findSurroundingWireTargets( const newTargets = this.findSurroundingWireTargets(
newSearchTile, newSearchTile,
newSearchDirections, newSearchDirections,
currentNetwork currentNetwork,
variantMask
); );
VERBOSE_WIRES && logger.log(" Found", newTargets, "new targets to visit!"); VERBOSE_WIRES && logger.log(" Found", newTargets, "new targets to visit!");
@ -361,13 +364,21 @@ export class WireSystem extends GameSystemWithFilter {
* @param {Vector} initialTile * @param {Vector} initialTile
* @param {Array<enumDirection>} directions * @param {Array<enumDirection>} directions
* @param {WireNetwork} network * @param {WireNetwork} network
* @param {enumWireVariant=} variantMask Only accept connections to this mask
* @returns {Array<any>} * @returns {Array<any>}
*/ */
findSurroundingWireTargets(initialTile, directions, network) { findSurroundingWireTargets(initialTile, directions, network, variantMask = null) {
let result = []; let result = [];
VERBOSE_WIRES && VERBOSE_WIRES &&
logger.log(" Searching for new targets at", initialTile.toString(), "and d=", directions); logger.log(
" Searching for new targets at",
initialTile.toString(),
"and d=",
directions,
"with mask=",
variantMask
);
// Go over all directions we should search for // Go over all directions we should search for
for (let i = 0; i < directions.length; ++i) { for (let i = 0; i < directions.length; ++i) {
@ -399,7 +410,11 @@ export class WireSystem extends GameSystemWithFilter {
const wireComp = entity.components.Wire; const wireComp = entity.components.Wire;
// Check for wire // Check for wire
if (wireComp && !wireComp.linkedNetwork) { if (
wireComp &&
!wireComp.linkedNetwork &&
(!variantMask || wireComp.variant === variantMask)
) {
// Wires accept connections from everywhere // Wires accept connections from everywhere
result.push({ result.push({
entity, entity,
@ -449,17 +464,6 @@ export class WireSystem extends GameSystemWithFilter {
const staticComp = entity.components.StaticMapEntity; const staticComp = entity.components.StaticMapEntity;
if (
!tunnelComp.multipleDirections &&
!(
direction === staticComp.localDirectionToWorld(enumDirection.top) ||
direction === staticComp.localDirectionToWorld(enumDirection.bottom)
)
) {
// It's a coating, and it doesn't connect here
continue;
}
// Compute where this tunnel connects to // Compute where this tunnel connects to
const forwardedTile = staticComp.origin.add(offset); const forwardedTile = staticComp.origin.add(offset);
VERBOSE_WIRES && VERBOSE_WIRES &&
@ -570,8 +574,8 @@ export class WireSystem extends GameSystemWithFilter {
if (!wireComp.linkedNetwork) { if (!wireComp.linkedNetwork) {
// There is no network, it's empty // There is no network, it's empty
return { return {
spriteSet: this.wireSprites.regular, spriteSet: this.wireSprites[wireComp.variant],
opacity: 0.3, opacity: 0.5,
}; };
} }
@ -584,38 +588,9 @@ export class WireSystem extends GameSystemWithFilter {
}; };
} }
const value = network.currentValue;
if (!value) {
// There is no value stored
return {
spriteSet: this.wireSprites.regular,
opacity: 0.3,
};
}
const valueType = value.getItemType();
if (valueType === "shape") {
return {
spriteSet: this.wireSprites.shape,
opacity: 1,
};
} else if (valueType === "color") {
return {
spriteSet: this.wireSprites.color,
opacity: 1,
};
} else if (valueType === "boolean") {
return {
spriteSet: this.wireSprites.regular,
opacity: isTrueItem(value) ? 1 : 0.5,
};
} else {
assertAlways(false, "Unknown item type: " + valueType);
}
return { return {
spriteSet: this.wireSprites.regular, spriteSet: this.wireSprites[wireComp.variant],
opacity: 1, opacity: isTruthyItem(network.currentValue) ? 1 : 0.5,
}; };
} }
@ -641,9 +616,10 @@ export class WireSystem extends GameSystemWithFilter {
const staticComp = entity.components.StaticMapEntity; const staticComp = entity.components.StaticMapEntity;
parameters.context.globalAlpha = opacity; parameters.context.globalAlpha = opacity;
staticComp.drawSpriteOnBoundsClipped(parameters, sprite, 0); staticComp.drawSpriteOnBoundsClipped(parameters, sprite, 0);
parameters.context.globalAlpha = 1;
// DEBUG Rendering
if (G_IS_DEV && globalConfig.debug.renderWireRotations) { if (G_IS_DEV && globalConfig.debug.renderWireRotations) {
parameters.context.globalAlpha = 1;
parameters.context.fillStyle = "red"; parameters.context.fillStyle = "red";
parameters.context.font = "5px Tahoma"; parameters.context.font = "5px Tahoma";
parameters.context.fillText( parameters.context.fillText(
@ -691,6 +667,8 @@ export class WireSystem extends GameSystemWithFilter {
} }
} }
} }
parameters.context.globalAlpha = 1;
} }
/** /**
@ -746,6 +724,8 @@ export class WireSystem extends GameSystemWithFilter {
continue; continue;
} }
const variant = targetStaticComp.getVariant();
const { const {
rotation, rotation,
rotationVariant, rotationVariant,
@ -753,7 +733,7 @@ export class WireSystem extends GameSystemWithFilter {
root: this.root, root: this.root,
tile: new Vector(x, y), tile: new Vector(x, y),
rotation: targetStaticComp.originalRotation, rotation: targetStaticComp.originalRotation,
variant: defaultBuildingVariant, variant,
layer: targetEntity.layer, layer: targetEntity.layer,
}); });
@ -763,14 +743,10 @@ export class WireSystem extends GameSystemWithFilter {
if (targetStaticComp.rotation !== rotation || newType !== targetWireComp.type) { if (targetStaticComp.rotation !== rotation || newType !== targetWireComp.type) {
// Change stuff // Change stuff
targetStaticComp.rotation = rotation; targetStaticComp.rotation = rotation;
metaWire.updateVariants(targetEntity, rotationVariant, defaultBuildingVariant); metaWire.updateVariants(targetEntity, rotationVariant, variant);
// Update code as well // Update code as well
targetStaticComp.code = getCodeFromBuildingData( targetStaticComp.code = getCodeFromBuildingData(metaWire, variant, rotationVariant);
metaWire,
defaultBuildingVariant,
rotationVariant
);
// Make sure the chunks know about the update // Make sure the chunks know about the update
this.root.signals.entityChanged.dispatch(targetEntity); this.root.signals.entityChanged.dispatch(targetEntity);

View File

@ -566,16 +566,18 @@ buildings:
default: default:
name: &wire Wire name: &wire Wire
description: &wire_desc Allows to connect logical components and can transfer items, colors or boolean signals. description: &wire_desc Allows to connect logical components and can transfer items, colors or boolean signals.
second:
name: Wire (Type 2)
description: &wire_desc_second Allows to connect logical components and can transfer items, colors or boolean signals. Different colored wires do not connect.
third:
name: Wire (Type 3)
description: *wire_desc_second
wire_tunnel: wire_tunnel:
default: default:
name: &wire_tunnel Wire Tunnel name: &wire_tunnel Wire Tunnel
description: Allows to cross two wires without connecting them. description: Allows to cross two wires without connecting them.
coating:
name: Wire Insulation
description: Allows to pass through signals without connecting to other wires on the sides.
constant_signal: constant_signal:
default: default:
name: &constant_signal Constant Signal name: &constant_signal Constant Signal
@ -589,20 +591,25 @@ buildings:
logic_gate: logic_gate:
default: default:
name: &logic_gate AND Gate name: &logic_gate AND Gate
description: Emits a truthy boolean signal if both inputs are truthy. description: Emits a boolean "1" if both inputs are truthy.
not: not:
name: NOT name: NOT Gate
description: Inverts the given signal. description: Emits a boolean "1" if the input is not truthy.
xor: xor:
name: XOR name: XOR Gate
description: Emits a truthy signal if one of the inputs is truthy, but not both. description: Emits a boolean "1" if one of the inputs is truthy, but not both.
or: or:
name: OR name: OR Gate
description: Emits a truthy signal if one of the inputs is truthy. description: Emits a boolean "1" if one of the inputs is truthy.
transistor: transistor:
name: Gate default:
description: Only forwards the bottom input if the left input is true. name: &transistor Gate
description: &transistor_desc Forwards the bottom input if the side input is truthy (a shape, color or "1").
mirrored:
name: *transistor
description: *transistor_desc
filter: filter:
default: default:
@ -619,14 +626,20 @@ buildings:
name: &reader Belt Reader name: &reader Belt Reader
description: Allows to measure belt throughput. Outputs the last read item on the wires layer (once unlocked). description: Allows to measure belt throughput. Outputs the last read item on the wires layer (once unlocked).
analyzer:
default:
name: &analyzer Shape Analyzer
description: Analyzes the top right quadrant of the lowest layer of the shape and returns its shape and color.
comparator:
default:
name: &comparator Compare
description: Returns boolean "1" if both items are exactly equal. Can compare shapes, items and booleans.
virtual_processor: virtual_processor:
default: default:
name: &virtual_processor Virtual Cutter name: &virtual_processor Virtual Cutter
description: Virtually cuts the shape input from top to bottom and returns both halfs. description: Computes
analyzer:
name: Shape Analyzer
description: Analyzes the top right quadrant of the lowest layer of the shape and returns its shape and color
rotater: rotater:
name: Virtual Rotater name: Virtual Rotater
@ -636,10 +649,6 @@ buildings:
name: Virtual Unstacker name: Virtual Unstacker
description: Returns the topmost layer to the right, and the remaining ones on the left. description: Returns the topmost layer to the right, and the remaining ones on the left.
shapecompare:
name: Compare
description: Returns true if both items are exactly equal. Can compare shapes, items and booleans.
stacker: stacker:
name: Virtual Stacker name: Virtual Stacker
description: Virtually stacks the right shape onto the left. description: Virtually stacks the right shape onto the left.
@ -1040,6 +1049,9 @@ keybindings:
display: *display display: *display
reader: *reader reader: *reader
virtual_processor: *virtual_processor virtual_processor: *virtual_processor
transistor: *transistor
analyzer: *analyzer
comparator: *comparator
# --- # ---
pipette: Pipette pipette: Pipette