Add virtual shape processing buildings
BIN
res/ui/building_icons/virtual_processor.png
Normal file
After Width: | Height: | Size: 7.7 KiB |
Before Width: | Height: | Size: 1.1 MiB After Width: | Height: | Size: 1.2 MiB |
Before Width: | Height: | Size: 238 KiB After Width: | Height: | Size: 254 KiB |
Before Width: | Height: | Size: 567 KiB After Width: | Height: | Size: 601 KiB |
@ -277,6 +277,7 @@
|
|||||||
<key type="filename">sprites/blueprints/underground_belt_entry.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-tier2.png</key>
|
||||||
<key type="filename">sprites/blueprints/underground_belt_exit.png</key>
|
<key type="filename">sprites/blueprints/underground_belt_exit.png</key>
|
||||||
|
<key type="filename">sprites/blueprints/wire_tunnel-coating.png</key>
|
||||||
<key type="filename">sprites/blueprints/wire_tunnel.png</key>
|
<key type="filename">sprites/blueprints/wire_tunnel.png</key>
|
||||||
<key type="filename">sprites/buildings/constant_signal.png</key>
|
<key type="filename">sprites/buildings/constant_signal.png</key>
|
||||||
<key type="filename">sprites/buildings/display.png</key>
|
<key type="filename">sprites/buildings/display.png</key>
|
||||||
@ -295,6 +296,7 @@
|
|||||||
<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>
|
||||||
<key type="filename">sprites/buildings/underground_belt_exit.png</key>
|
<key type="filename">sprites/buildings/underground_belt_exit.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/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_cross.png</key>
|
||||||
@ -533,6 +535,8 @@
|
|||||||
</struct>
|
</struct>
|
||||||
<key type="filename">sprites/wires/boolean_false.png</key>
|
<key type="filename">sprites/wires/boolean_false.png</key>
|
||||||
<key type="filename">sprites/wires/boolean_true.png</key>
|
<key type="filename">sprites/wires/boolean_true.png</key>
|
||||||
|
<key type="filename">sprites/wires/network_conflict.png</key>
|
||||||
|
<key type="filename">sprites/wires/network_empty.png</key>
|
||||||
<key type="filename">sprites/wires/wires_preview.png</key>
|
<key type="filename">sprites/wires/wires_preview.png</key>
|
||||||
<struct type="IndividualSpriteSettings">
|
<struct type="IndividualSpriteSettings">
|
||||||
<key>pivotPoint</key>
|
<key>pivotPoint</key>
|
||||||
|
BIN
res_raw/sprites/blueprints/virtual_processor-analyzer.png
Normal file
After Width: | Height: | Size: 12 KiB |
BIN
res_raw/sprites/blueprints/virtual_processor-rotater.png
Normal file
After Width: | Height: | Size: 11 KiB |
BIN
res_raw/sprites/blueprints/virtual_processor-shapecompare.png
Normal file
After Width: | Height: | Size: 8.3 KiB |
BIN
res_raw/sprites/blueprints/virtual_processor-unstacker.png
Normal file
After Width: | Height: | Size: 11 KiB |
BIN
res_raw/sprites/blueprints/virtual_processor.png
Normal file
After Width: | Height: | Size: 13 KiB |
BIN
res_raw/sprites/buildings/virtual_processor-analyzer.png
Normal file
After Width: | Height: | Size: 9.5 KiB |
BIN
res_raw/sprites/buildings/virtual_processor-rotater.png
Normal file
After Width: | Height: | Size: 9.3 KiB |
BIN
res_raw/sprites/buildings/virtual_processor-shapecompare.png
Normal file
After Width: | Height: | Size: 7.6 KiB |
BIN
res_raw/sprites/buildings/virtual_processor-unstacker.png
Normal file
After Width: | Height: | Size: 8.8 KiB |
BIN
res_raw/sprites/buildings/virtual_processor.png
Normal file
After Width: | Height: | Size: 10 KiB |
@ -1,38 +1,38 @@
|
|||||||
$buildings: belt, cutter, miner, mixer, painter, rotater, splitter, stacker, trash, underground_belt, wire,
|
$buildings: belt, cutter, miner, mixer, painter, rotater, splitter, stacker, trash, underground_belt, wire,
|
||||||
constant_signal, logic_gate, lever, filter, wire_tunnel, display;
|
constant_signal, logic_gate, lever, filter, wire_tunnel, display, virtual_processor;
|
||||||
|
|
||||||
@each $building in $buildings {
|
@each $building in $buildings {
|
||||||
[data-icon="building_icons/#{$building}.png"] {
|
[data-icon="building_icons/#{$building}.png"] {
|
||||||
background-image: uiResource("res/ui/building_icons/#{$building}.png") !important;
|
background-image: uiResource("res/ui/building_icons/#{$building}.png") !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$buildingsAndVariants: belt, splitter, splitter-compact, splitter-compact-inverse, underground_belt,
|
$buildingsAndVariants: belt, splitter, splitter-compact, splitter-compact-inverse, underground_belt,
|
||||||
underground_belt-tier2, miner, miner-chainable, cutter, cutter-quad, rotater, rotater-ccw, rotater-fl,
|
underground_belt-tier2, miner, miner-chainable, cutter, cutter-quad, rotater, rotater-ccw, rotater-fl,
|
||||||
stacker, mixer, painter, painter-double, painter-quad, trash, trash-storage;
|
stacker, mixer, painter, painter-double, painter-quad, trash, trash-storage;
|
||||||
@each $building in $buildingsAndVariants {
|
@each $building in $buildingsAndVariants {
|
||||||
[data-icon="building_tutorials/#{$building}.png"] {
|
[data-icon="building_tutorials/#{$building}.png"] {
|
||||||
background-image: uiResource("res/ui/building_tutorials/#{$building}.png") !important;
|
background-image: uiResource("res/ui/building_tutorials/#{$building}.png") !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Special case
|
// Special case
|
||||||
[data-icon="building_tutorials/painter-mirrored.png"] {
|
[data-icon="building_tutorials/painter-mirrored.png"] {
|
||||||
background-image: uiResource("res/ui/building_tutorials/painter.png") !important;
|
background-image: uiResource("res/ui/building_tutorials/painter.png") !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
$icons: notification_saved, notification_success, notification_upgrade;
|
$icons: notification_saved, notification_success, notification_upgrade;
|
||||||
@each $icon in $icons {
|
@each $icon in $icons {
|
||||||
[data-icon="icons/#{$icon}.png"] {
|
[data-icon="icons/#{$icon}.png"] {
|
||||||
background-image: uiResource("res/ui/icons/#{$icon}.png") !important;
|
background-image: uiResource("res/ui/icons/#{$icon}.png") !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$languages: en, de, cs, da, et, es-419, fr, it, pt-BR, sv, tr, el, ru, uk, zh-TW, zh-CN, nb, mt-MT, ar, nl, vi,
|
$languages: en, de, cs, da, et, es-419, fr, it, pt-BR, sv, tr, el, ru, uk, zh-TW, zh-CN, nb, mt-MT, ar, nl, vi,
|
||||||
th, hu, pl, ja, kor, no, pt-PT;
|
th, hu, pl, ja, kor, no, pt-PT;
|
||||||
|
|
||||||
@each $language in $languages {
|
@each $language in $languages {
|
||||||
[data-languageicon="#{$language}"] {
|
[data-languageicon="#{$language}"] {
|
||||||
background-image: uiResource("languages/#{$language}.svg") !important;
|
background-image: uiResource("languages/#{$language}.svg") !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
151
src/js/game/buildings/virtual_processor.js
Normal file
@ -0,0 +1,151 @@
|
|||||||
|
import { Vector, enumDirection } from "../../core/vector";
|
||||||
|
import { LogicGateComponent, enumLogicGateType } from "../components/logic_gate";
|
||||||
|
import { WiredPinsComponent, enumPinSlotType } from "../components/wired_pins";
|
||||||
|
import { Entity } from "../entity";
|
||||||
|
import { defaultBuildingVariant, MetaBuilding } from "../meta_building";
|
||||||
|
import { GameRoot } from "../root";
|
||||||
|
|
||||||
|
/** @enum {string} */
|
||||||
|
export const enumVirtualProcessorVariants = {
|
||||||
|
analyzer: "analyzer",
|
||||||
|
rotater: "rotater",
|
||||||
|
unstacker: "unstacker",
|
||||||
|
shapecompare: "shapecompare",
|
||||||
|
};
|
||||||
|
|
||||||
|
/** @enum {string} */
|
||||||
|
export const enumVariantToGate = {
|
||||||
|
[defaultBuildingVariant]: enumLogicGateType.cutter,
|
||||||
|
[enumVirtualProcessorVariants.analyzer]: enumLogicGateType.analyzer,
|
||||||
|
[enumVirtualProcessorVariants.rotater]: enumLogicGateType.rotater,
|
||||||
|
[enumVirtualProcessorVariants.unstacker]: enumLogicGateType.unstacker,
|
||||||
|
[enumVirtualProcessorVariants.shapecompare]: enumLogicGateType.shapecompare,
|
||||||
|
};
|
||||||
|
|
||||||
|
export class MetaVirtualProcessorBuilding extends MetaBuilding {
|
||||||
|
constructor() {
|
||||||
|
super("virtual_processor");
|
||||||
|
}
|
||||||
|
|
||||||
|
getSilhouetteColor() {
|
||||||
|
return "#823cab";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {GameRoot} root
|
||||||
|
*/
|
||||||
|
getIsUnlocked(root) {
|
||||||
|
// @todo
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @returns {"wires"} **/
|
||||||
|
getLayer() {
|
||||||
|
return "wires";
|
||||||
|
}
|
||||||
|
|
||||||
|
getDimensions() {
|
||||||
|
return new Vector(1, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
getAvailableVariants() {
|
||||||
|
return [
|
||||||
|
defaultBuildingVariant,
|
||||||
|
enumVirtualProcessorVariants.rotater,
|
||||||
|
enumVirtualProcessorVariants.unstacker,
|
||||||
|
enumVirtualProcessorVariants.analyzer,
|
||||||
|
enumVirtualProcessorVariants.shapecompare,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
getRenderPins() {
|
||||||
|
// We already have it included
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {Entity} entity
|
||||||
|
* @param {number} rotationVariant
|
||||||
|
*/
|
||||||
|
updateVariants(entity, rotationVariant, variant) {
|
||||||
|
const gateType = enumVariantToGate[variant];
|
||||||
|
entity.components.LogicGate.type = gateType;
|
||||||
|
const pinComp = entity.components.WiredPins;
|
||||||
|
switch (gateType) {
|
||||||
|
case enumLogicGateType.cutter:
|
||||||
|
case enumLogicGateType.analyzer:
|
||||||
|
case enumLogicGateType.unstacker: {
|
||||||
|
pinComp.setSlots([
|
||||||
|
{
|
||||||
|
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,
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case enumLogicGateType.rotater: {
|
||||||
|
pinComp.setSlots([
|
||||||
|
{
|
||||||
|
pos: new Vector(0, 0),
|
||||||
|
direction: enumDirection.top,
|
||||||
|
type: enumPinSlotType.logicalEjector,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pos: new Vector(0, 0),
|
||||||
|
direction: enumDirection.bottom,
|
||||||
|
type: enumPinSlotType.logicalAcceptor,
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
assertAlways("unknown logic gate type: " + gateType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates the entity at the given location
|
||||||
|
* @param {Entity} entity
|
||||||
|
*/
|
||||||
|
setupEntityComponents(entity) {
|
||||||
|
entity.addComponent(
|
||||||
|
new WiredPinsComponent({
|
||||||
|
slots: [],
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
entity.addComponent(new LogicGateComponent({}));
|
||||||
|
}
|
||||||
|
}
|
@ -1,30 +1,36 @@
|
|||||||
import { Component } from "../component";
|
import { Component } from "../component";
|
||||||
|
|
||||||
/** @enum {string} */
|
/** @enum {string} */
|
||||||
export const enumLogicGateType = {
|
export const enumLogicGateType = {
|
||||||
and: "and",
|
and: "and",
|
||||||
not: "not",
|
not: "not",
|
||||||
xor: "xor",
|
xor: "xor",
|
||||||
or: "or",
|
or: "or",
|
||||||
transistor: "transistor",
|
transistor: "transistor",
|
||||||
};
|
|
||||||
|
analyzer: "analyzer",
|
||||||
export class LogicGateComponent extends Component {
|
rotater: "rotater",
|
||||||
static getId() {
|
unstacker: "unstacker",
|
||||||
return "LogicGate";
|
cutter: "cutter",
|
||||||
}
|
shapecompare: "shapecompare",
|
||||||
|
};
|
||||||
duplicateWithoutContents() {
|
|
||||||
return new LogicGateComponent({ type: this.type });
|
export class LogicGateComponent extends Component {
|
||||||
}
|
static getId() {
|
||||||
|
return "LogicGate";
|
||||||
/**
|
}
|
||||||
*
|
|
||||||
* @param {object} param0
|
duplicateWithoutContents() {
|
||||||
* @param {enumLogicGateType=} param0.type
|
return new LogicGateComponent({ type: this.type });
|
||||||
*/
|
}
|
||||||
constructor({ type = enumLogicGateType.and }) {
|
|
||||||
super();
|
/**
|
||||||
this.type = type;
|
*
|
||||||
}
|
* @param {object} param0
|
||||||
}
|
* @param {enumLogicGateType=} param0.type
|
||||||
|
*/
|
||||||
|
constructor({ type = enumLogicGateType.and }) {
|
||||||
|
super();
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,25 +1,27 @@
|
|||||||
import { HUDBaseToolbar } from "./base_toolbar";
|
import { HUDBaseToolbar } from "./base_toolbar";
|
||||||
import { MetaWireBuilding } from "../../buildings/wire";
|
import { MetaWireBuilding } from "../../buildings/wire";
|
||||||
import { MetaConstantSignalBuilding } from "../../buildings/constant_signal";
|
import { MetaConstantSignalBuilding } from "../../buildings/constant_signal";
|
||||||
import { MetaLogicGateBuilding } from "../../buildings/logic_gate";
|
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";
|
||||||
const supportedBuildings = [
|
|
||||||
MetaWireBuilding,
|
const supportedBuildings = [
|
||||||
MetaWireTunnelBuilding,
|
MetaWireBuilding,
|
||||||
MetaConstantSignalBuilding,
|
MetaWireTunnelBuilding,
|
||||||
MetaLogicGateBuilding,
|
MetaConstantSignalBuilding,
|
||||||
MetaLeverBuilding,
|
MetaLogicGateBuilding,
|
||||||
];
|
MetaLeverBuilding,
|
||||||
|
MetaVirtualProcessorBuilding,
|
||||||
export class HUDWiresToolbar extends HUDBaseToolbar {
|
];
|
||||||
constructor(root) {
|
|
||||||
super(root, {
|
export class HUDWiresToolbar extends HUDBaseToolbar {
|
||||||
supportedBuildings,
|
constructor(root) {
|
||||||
visibilityCondition: () =>
|
super(root, {
|
||||||
!this.root.camera.getIsMapOverlayActive() && this.root.currentLayer === "wires",
|
supportedBuildings,
|
||||||
htmlElementId: "ingame_HUD_wires_toolbar",
|
visibilityCondition: () =>
|
||||||
});
|
!this.root.camera.getIsMapOverlayActive() && this.root.currentLayer === "wires",
|
||||||
}
|
htmlElementId: "ingame_HUD_wires_toolbar",
|
||||||
}
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,456 +1,457 @@
|
|||||||
/* typehints:start */
|
/* typehints:start */
|
||||||
import { GameRoot } from "./root";
|
import { GameRoot } from "./root";
|
||||||
import { InputReceiver } from "../core/input_receiver";
|
import { InputReceiver } from "../core/input_receiver";
|
||||||
import { Application } from "../application";
|
import { Application } from "../application";
|
||||||
/* typehints:end */
|
/* typehints:end */
|
||||||
|
|
||||||
import { Signal, STOP_PROPAGATION } from "../core/signal";
|
import { Signal, STOP_PROPAGATION } from "../core/signal";
|
||||||
import { IS_MOBILE } from "../core/config";
|
import { IS_MOBILE } from "../core/config";
|
||||||
import { T } from "../translations";
|
import { T } from "../translations";
|
||||||
function key(str) {
|
function key(str) {
|
||||||
return str.toUpperCase().charCodeAt(0);
|
return str.toUpperCase().charCodeAt(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
export const KEYMAPPINGS = {
|
export const KEYMAPPINGS = {
|
||||||
general: {
|
general: {
|
||||||
confirm: { keyCode: 13 }, // enter
|
confirm: { keyCode: 13 }, // enter
|
||||||
back: { keyCode: 27, builtin: true }, // escape
|
back: { keyCode: 27, builtin: true }, // escape
|
||||||
},
|
},
|
||||||
|
|
||||||
ingame: {
|
ingame: {
|
||||||
menuOpenShop: { keyCode: key("F") },
|
menuOpenShop: { keyCode: key("F") },
|
||||||
menuOpenStats: { keyCode: key("G") },
|
menuOpenStats: { keyCode: key("G") },
|
||||||
menuClose: { keyCode: key("Q") },
|
menuClose: { keyCode: key("Q") },
|
||||||
|
|
||||||
toggleHud: { keyCode: 113 }, // F2
|
toggleHud: { keyCode: 113 }, // F2
|
||||||
exportScreenshot: { keyCode: 114 }, // F3PS
|
exportScreenshot: { keyCode: 114 }, // F3PS
|
||||||
toggleFPSInfo: { keyCode: 115 }, // F4
|
toggleFPSInfo: { keyCode: 115 }, // F4
|
||||||
|
|
||||||
switchLayers: { keyCode: key("Y") },
|
switchLayers: { keyCode: key("Y") },
|
||||||
},
|
},
|
||||||
|
|
||||||
navigation: {
|
navigation: {
|
||||||
mapMoveUp: { keyCode: key("W") },
|
mapMoveUp: { keyCode: key("W") },
|
||||||
mapMoveRight: { keyCode: key("D") },
|
mapMoveRight: { keyCode: key("D") },
|
||||||
mapMoveDown: { keyCode: key("S") },
|
mapMoveDown: { keyCode: key("S") },
|
||||||
mapMoveLeft: { keyCode: key("A") },
|
mapMoveLeft: { keyCode: key("A") },
|
||||||
mapMoveFaster: { keyCode: 16 }, //shift
|
mapMoveFaster: { keyCode: 16 }, //shift
|
||||||
|
|
||||||
centerMap: { keyCode: 32 }, // SPACE
|
centerMap: { keyCode: 32 }, // SPACE
|
||||||
mapZoomIn: { keyCode: 187, repeated: true }, // "+"
|
mapZoomIn: { keyCode: 187, repeated: true }, // "+"
|
||||||
mapZoomOut: { keyCode: 189, repeated: true }, // "-"
|
mapZoomOut: { keyCode: 189, repeated: true }, // "-"
|
||||||
|
|
||||||
createMarker: { keyCode: key("M") },
|
createMarker: { keyCode: key("M") },
|
||||||
},
|
},
|
||||||
|
|
||||||
buildings: {
|
buildings: {
|
||||||
belt: { keyCode: key("1") },
|
belt: { keyCode: key("1") },
|
||||||
splitter: { keyCode: key("2") },
|
splitter: { keyCode: key("2") },
|
||||||
underground_belt: { keyCode: key("3") },
|
underground_belt: { keyCode: key("3") },
|
||||||
miner: { keyCode: key("4") },
|
miner: { keyCode: key("4") },
|
||||||
cutter: { keyCode: key("5") },
|
cutter: { keyCode: key("5") },
|
||||||
rotater: { keyCode: key("6") },
|
rotater: { keyCode: key("6") },
|
||||||
stacker: { keyCode: key("7") },
|
stacker: { keyCode: key("7") },
|
||||||
mixer: { keyCode: key("8") },
|
mixer: { keyCode: key("8") },
|
||||||
painter: { keyCode: key("9") },
|
painter: { keyCode: key("9") },
|
||||||
trash: { keyCode: key("0") },
|
trash: { keyCode: key("0") },
|
||||||
|
|
||||||
lever: { keyCode: key("L") },
|
lever: { keyCode: key("L") },
|
||||||
filter: { keyCode: key("B") },
|
filter: { keyCode: key("B") },
|
||||||
display: { keyCode: key("N") },
|
display: { keyCode: key("N") },
|
||||||
|
|
||||||
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") },
|
||||||
logic_gate: { keyCode: key("4") },
|
logic_gate: { keyCode: key("4") },
|
||||||
},
|
virtual_processor: { keyCode: key("5") },
|
||||||
|
},
|
||||||
placement: {
|
|
||||||
pipette: { keyCode: key("Q") },
|
placement: {
|
||||||
rotateWhilePlacing: { keyCode: key("R") },
|
pipette: { keyCode: key("Q") },
|
||||||
rotateInverseModifier: { keyCode: 16 }, // SHIFT
|
rotateWhilePlacing: { keyCode: key("R") },
|
||||||
cycleBuildingVariants: { keyCode: key("T") },
|
rotateInverseModifier: { keyCode: 16 }, // SHIFT
|
||||||
cycleBuildings: { keyCode: 9 }, // TAB
|
cycleBuildingVariants: { keyCode: key("T") },
|
||||||
switchDirectionLockSide: { keyCode: key("R") },
|
cycleBuildings: { keyCode: 9 }, // TAB
|
||||||
},
|
switchDirectionLockSide: { keyCode: key("R") },
|
||||||
|
},
|
||||||
massSelect: {
|
|
||||||
massSelectStart: { keyCode: 17 }, // CTRL
|
massSelect: {
|
||||||
massSelectSelectMultiple: { keyCode: 16 }, // SHIFT
|
massSelectStart: { keyCode: 17 }, // CTRL
|
||||||
massSelectCopy: { keyCode: key("C") },
|
massSelectSelectMultiple: { keyCode: 16 }, // SHIFT
|
||||||
massSelectCut: { keyCode: key("X") },
|
massSelectCopy: { keyCode: key("C") },
|
||||||
confirmMassDelete: { keyCode: 46 }, // DEL
|
massSelectCut: { keyCode: key("X") },
|
||||||
pasteLastBlueprint: { keyCode: key("V") },
|
confirmMassDelete: { keyCode: 46 }, // DEL
|
||||||
},
|
pasteLastBlueprint: { keyCode: key("V") },
|
||||||
|
},
|
||||||
placementModifiers: {
|
|
||||||
lockBeltDirection: { keyCode: 16 }, // SHIFT
|
placementModifiers: {
|
||||||
placementDisableAutoOrientation: { keyCode: 17 }, // CTRL
|
lockBeltDirection: { keyCode: 16 }, // SHIFT
|
||||||
placeMultiple: { keyCode: 16 }, // SHIFT
|
placementDisableAutoOrientation: { keyCode: 17 }, // CTRL
|
||||||
placeInverse: { keyCode: 18 }, // ALT
|
placeMultiple: { keyCode: 16 }, // SHIFT
|
||||||
},
|
placeInverse: { keyCode: 18 }, // ALT
|
||||||
};
|
},
|
||||||
|
};
|
||||||
// Assign ids
|
|
||||||
for (const categoryId in KEYMAPPINGS) {
|
// Assign ids
|
||||||
for (const mappingId in KEYMAPPINGS[categoryId]) {
|
for (const categoryId in KEYMAPPINGS) {
|
||||||
KEYMAPPINGS[categoryId][mappingId].id = mappingId;
|
for (const mappingId in KEYMAPPINGS[categoryId]) {
|
||||||
}
|
KEYMAPPINGS[categoryId][mappingId].id = mappingId;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
export const KEYCODE_LMB = 1;
|
|
||||||
export const KEYCODE_MMB = 2;
|
export const KEYCODE_LMB = 1;
|
||||||
export const KEYCODE_RMB = 3;
|
export const KEYCODE_MMB = 2;
|
||||||
|
export const KEYCODE_RMB = 3;
|
||||||
/**
|
|
||||||
* Returns a keycode -> string
|
/**
|
||||||
* @param {number} code
|
* Returns a keycode -> string
|
||||||
* @returns {string}
|
* @param {number} code
|
||||||
*/
|
* @returns {string}
|
||||||
export function getStringForKeyCode(code) {
|
*/
|
||||||
switch (code) {
|
export function getStringForKeyCode(code) {
|
||||||
case KEYCODE_LMB:
|
switch (code) {
|
||||||
return "LMB";
|
case KEYCODE_LMB:
|
||||||
case KEYCODE_MMB:
|
return "LMB";
|
||||||
return "MMB";
|
case KEYCODE_MMB:
|
||||||
case KEYCODE_RMB:
|
return "MMB";
|
||||||
return "RMB";
|
case KEYCODE_RMB:
|
||||||
case 4:
|
return "RMB";
|
||||||
return "MB4";
|
case 4:
|
||||||
case 5:
|
return "MB4";
|
||||||
return "MB5";
|
case 5:
|
||||||
case 8:
|
return "MB5";
|
||||||
return "⌫";
|
case 8:
|
||||||
case 9:
|
return "⌫";
|
||||||
return T.global.keys.tab;
|
case 9:
|
||||||
case 13:
|
return T.global.keys.tab;
|
||||||
return "⏎";
|
case 13:
|
||||||
case 16:
|
return "⏎";
|
||||||
return "⇪";
|
case 16:
|
||||||
case 17:
|
return "⇪";
|
||||||
return T.global.keys.control;
|
case 17:
|
||||||
case 18:
|
return T.global.keys.control;
|
||||||
return T.global.keys.alt;
|
case 18:
|
||||||
case 19:
|
return T.global.keys.alt;
|
||||||
return "PAUSE";
|
case 19:
|
||||||
case 20:
|
return "PAUSE";
|
||||||
return "CAPS";
|
case 20:
|
||||||
case 27:
|
return "CAPS";
|
||||||
return T.global.keys.escape;
|
case 27:
|
||||||
case 32:
|
return T.global.keys.escape;
|
||||||
return T.global.keys.space;
|
case 32:
|
||||||
case 33:
|
return T.global.keys.space;
|
||||||
return "PGUP";
|
case 33:
|
||||||
case 34:
|
return "PGUP";
|
||||||
return "PGDOWN";
|
case 34:
|
||||||
case 35:
|
return "PGDOWN";
|
||||||
return "END";
|
case 35:
|
||||||
case 36:
|
return "END";
|
||||||
return "HOME";
|
case 36:
|
||||||
case 37:
|
return "HOME";
|
||||||
return "⬅";
|
case 37:
|
||||||
case 38:
|
return "⬅";
|
||||||
return "⬆";
|
case 38:
|
||||||
case 39:
|
return "⬆";
|
||||||
return "➡";
|
case 39:
|
||||||
case 40:
|
return "➡";
|
||||||
return "⬇";
|
case 40:
|
||||||
case 44:
|
return "⬇";
|
||||||
return "PRNT";
|
case 44:
|
||||||
case 45:
|
return "PRNT";
|
||||||
return "INS";
|
case 45:
|
||||||
case 46:
|
return "INS";
|
||||||
return "DEL";
|
case 46:
|
||||||
case 93:
|
return "DEL";
|
||||||
return "SEL";
|
case 93:
|
||||||
case 96:
|
return "SEL";
|
||||||
return "NUM 0";
|
case 96:
|
||||||
case 97:
|
return "NUM 0";
|
||||||
return "NUM 1";
|
case 97:
|
||||||
case 98:
|
return "NUM 1";
|
||||||
return "NUM 2";
|
case 98:
|
||||||
case 99:
|
return "NUM 2";
|
||||||
return "NUM 3";
|
case 99:
|
||||||
case 100:
|
return "NUM 3";
|
||||||
return "NUM 4";
|
case 100:
|
||||||
case 101:
|
return "NUM 4";
|
||||||
return "NUM 5";
|
case 101:
|
||||||
case 102:
|
return "NUM 5";
|
||||||
return "NUM 6";
|
case 102:
|
||||||
case 103:
|
return "NUM 6";
|
||||||
return "NUM 7";
|
case 103:
|
||||||
case 104:
|
return "NUM 7";
|
||||||
return "NUM 8";
|
case 104:
|
||||||
case 105:
|
return "NUM 8";
|
||||||
return "NUM 9";
|
case 105:
|
||||||
case 106:
|
return "NUM 9";
|
||||||
return "*";
|
case 106:
|
||||||
case 107:
|
return "*";
|
||||||
return "+";
|
case 107:
|
||||||
case 109:
|
return "+";
|
||||||
return "-";
|
case 109:
|
||||||
case 110:
|
return "-";
|
||||||
return ".";
|
case 110:
|
||||||
case 111:
|
return ".";
|
||||||
return "/";
|
case 111:
|
||||||
case 112:
|
return "/";
|
||||||
return "F1";
|
case 112:
|
||||||
case 113:
|
return "F1";
|
||||||
return "F2";
|
case 113:
|
||||||
case 114:
|
return "F2";
|
||||||
return "F3";
|
case 114:
|
||||||
case 115:
|
return "F3";
|
||||||
return "F4";
|
case 115:
|
||||||
case 116:
|
return "F4";
|
||||||
return "F4";
|
case 116:
|
||||||
case 117:
|
return "F4";
|
||||||
return "F5";
|
case 117:
|
||||||
case 118:
|
return "F5";
|
||||||
return "F6";
|
case 118:
|
||||||
case 119:
|
return "F6";
|
||||||
return "F7";
|
case 119:
|
||||||
case 120:
|
return "F7";
|
||||||
return "F8";
|
case 120:
|
||||||
case 121:
|
return "F8";
|
||||||
return "F9";
|
case 121:
|
||||||
case 122:
|
return "F9";
|
||||||
return "F10";
|
case 122:
|
||||||
case 123:
|
return "F10";
|
||||||
return "F11";
|
case 123:
|
||||||
case 124:
|
return "F11";
|
||||||
return "F12";
|
case 124:
|
||||||
|
return "F12";
|
||||||
case 144:
|
|
||||||
return "NUMLOCK";
|
case 144:
|
||||||
case 145:
|
return "NUMLOCK";
|
||||||
return "SCRLOCK";
|
case 145:
|
||||||
case 182:
|
return "SCRLOCK";
|
||||||
return "COMP";
|
case 182:
|
||||||
case 183:
|
return "COMP";
|
||||||
return "CALC";
|
case 183:
|
||||||
case 186:
|
return "CALC";
|
||||||
return ";";
|
case 186:
|
||||||
case 187:
|
return ";";
|
||||||
return "+";
|
case 187:
|
||||||
case 188:
|
return "+";
|
||||||
return ",";
|
case 188:
|
||||||
case 189:
|
return ",";
|
||||||
return "-";
|
case 189:
|
||||||
case 191:
|
return "-";
|
||||||
return "/";
|
case 191:
|
||||||
case 219:
|
return "/";
|
||||||
return "[";
|
case 219:
|
||||||
case 220:
|
return "[";
|
||||||
return "\\";
|
case 220:
|
||||||
case 221:
|
return "\\";
|
||||||
return "]";
|
case 221:
|
||||||
case 222:
|
return "]";
|
||||||
return "'";
|
case 222:
|
||||||
}
|
return "'";
|
||||||
|
}
|
||||||
return String.fromCharCode(code);
|
|
||||||
}
|
return String.fromCharCode(code);
|
||||||
|
}
|
||||||
export class Keybinding {
|
|
||||||
/**
|
export class Keybinding {
|
||||||
*
|
/**
|
||||||
* @param {KeyActionMapper} keyMapper
|
*
|
||||||
* @param {Application} app
|
* @param {KeyActionMapper} keyMapper
|
||||||
* @param {object} param0
|
* @param {Application} app
|
||||||
* @param {number} param0.keyCode
|
* @param {object} param0
|
||||||
* @param {boolean=} param0.builtin
|
* @param {number} param0.keyCode
|
||||||
* @param {boolean=} param0.repeated
|
* @param {boolean=} param0.builtin
|
||||||
*/
|
* @param {boolean=} param0.repeated
|
||||||
constructor(keyMapper, app, { keyCode, builtin = false, repeated = false }) {
|
*/
|
||||||
assert(keyCode && Number.isInteger(keyCode), "Invalid key code: " + keyCode);
|
constructor(keyMapper, app, { keyCode, builtin = false, repeated = false }) {
|
||||||
this.keyMapper = keyMapper;
|
assert(keyCode && Number.isInteger(keyCode), "Invalid key code: " + keyCode);
|
||||||
this.app = app;
|
this.keyMapper = keyMapper;
|
||||||
this.keyCode = keyCode;
|
this.app = app;
|
||||||
this.builtin = builtin;
|
this.keyCode = keyCode;
|
||||||
this.repeated = repeated;
|
this.builtin = builtin;
|
||||||
|
this.repeated = repeated;
|
||||||
this.signal = new Signal();
|
|
||||||
this.toggled = new Signal();
|
this.signal = new Signal();
|
||||||
}
|
this.toggled = new Signal();
|
||||||
|
}
|
||||||
/**
|
|
||||||
* Returns whether this binding is currently pressed
|
/**
|
||||||
* @returns {boolean}
|
* Returns whether this binding is currently pressed
|
||||||
*/
|
* @returns {boolean}
|
||||||
get pressed() {
|
*/
|
||||||
// Check if the key is down
|
get pressed() {
|
||||||
if (this.app.inputMgr.keysDown.has(this.keyCode)) {
|
// Check if the key is down
|
||||||
// Check if it is the top reciever
|
if (this.app.inputMgr.keysDown.has(this.keyCode)) {
|
||||||
const reciever = this.keyMapper.inputReceiver;
|
// Check if it is the top reciever
|
||||||
return this.app.inputMgr.getTopReciever() === reciever;
|
const reciever = this.keyMapper.inputReceiver;
|
||||||
}
|
return this.app.inputMgr.getTopReciever() === reciever;
|
||||||
return false;
|
}
|
||||||
}
|
return false;
|
||||||
|
}
|
||||||
/**
|
|
||||||
* Adds an event listener
|
/**
|
||||||
* @param {function() : void} receiver
|
* Adds an event listener
|
||||||
* @param {object=} scope
|
* @param {function() : void} receiver
|
||||||
*/
|
* @param {object=} scope
|
||||||
add(receiver, scope = null) {
|
*/
|
||||||
this.signal.add(receiver, scope);
|
add(receiver, scope = null) {
|
||||||
}
|
this.signal.add(receiver, scope);
|
||||||
|
}
|
||||||
/**
|
|
||||||
* @param {Element} elem
|
/**
|
||||||
* @returns {HTMLElement} the created element, or null if the keybindings are not shown
|
* @param {Element} elem
|
||||||
* */
|
* @returns {HTMLElement} the created element, or null if the keybindings are not shown
|
||||||
appendLabelToElement(elem) {
|
* */
|
||||||
if (IS_MOBILE) {
|
appendLabelToElement(elem) {
|
||||||
return null;
|
if (IS_MOBILE) {
|
||||||
}
|
return null;
|
||||||
const spacer = document.createElement("code");
|
}
|
||||||
spacer.classList.add("keybinding");
|
const spacer = document.createElement("code");
|
||||||
spacer.innerHTML = getStringForKeyCode(this.keyCode);
|
spacer.classList.add("keybinding");
|
||||||
elem.appendChild(spacer);
|
spacer.innerHTML = getStringForKeyCode(this.keyCode);
|
||||||
return spacer;
|
elem.appendChild(spacer);
|
||||||
}
|
return spacer;
|
||||||
|
}
|
||||||
/**
|
|
||||||
* Returns the key code as a nice string
|
/**
|
||||||
*/
|
* Returns the key code as a nice string
|
||||||
getKeyCodeString() {
|
*/
|
||||||
return getStringForKeyCode(this.keyCode);
|
getKeyCodeString() {
|
||||||
}
|
return getStringForKeyCode(this.keyCode);
|
||||||
|
}
|
||||||
/**
|
|
||||||
* Remvoes all signal receivers
|
/**
|
||||||
*/
|
* Remvoes all signal receivers
|
||||||
clearSignalReceivers() {
|
*/
|
||||||
this.signal.removeAll();
|
clearSignalReceivers() {
|
||||||
}
|
this.signal.removeAll();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
export class KeyActionMapper {
|
|
||||||
/**
|
export class KeyActionMapper {
|
||||||
*
|
/**
|
||||||
* @param {GameRoot} root
|
*
|
||||||
* @param {InputReceiver} inputReciever
|
* @param {GameRoot} root
|
||||||
*/
|
* @param {InputReceiver} inputReciever
|
||||||
constructor(root, inputReciever) {
|
*/
|
||||||
this.root = root;
|
constructor(root, inputReciever) {
|
||||||
this.inputReceiver = inputReciever;
|
this.root = root;
|
||||||
|
this.inputReceiver = inputReciever;
|
||||||
inputReciever.keydown.add(this.handleKeydown, this);
|
|
||||||
inputReciever.keyup.add(this.handleKeyup, this);
|
inputReciever.keydown.add(this.handleKeydown, this);
|
||||||
|
inputReciever.keyup.add(this.handleKeyup, this);
|
||||||
/** @type {Object.<string, Keybinding>} */
|
|
||||||
this.keybindings = {};
|
/** @type {Object.<string, Keybinding>} */
|
||||||
|
this.keybindings = {};
|
||||||
const overrides = root.app.settings.getKeybindingOverrides();
|
|
||||||
|
const overrides = root.app.settings.getKeybindingOverrides();
|
||||||
for (const category in KEYMAPPINGS) {
|
|
||||||
for (const key in KEYMAPPINGS[category]) {
|
for (const category in KEYMAPPINGS) {
|
||||||
let payload = Object.assign({}, KEYMAPPINGS[category][key]);
|
for (const key in KEYMAPPINGS[category]) {
|
||||||
if (overrides[key]) {
|
let payload = Object.assign({}, KEYMAPPINGS[category][key]);
|
||||||
payload.keyCode = overrides[key];
|
if (overrides[key]) {
|
||||||
}
|
payload.keyCode = overrides[key];
|
||||||
|
}
|
||||||
this.keybindings[key] = new Keybinding(this, this.root.app, payload);
|
|
||||||
}
|
this.keybindings[key] = new Keybinding(this, this.root.app, payload);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
inputReciever.pageBlur.add(this.onPageBlur, this);
|
|
||||||
inputReciever.destroyed.add(this.cleanup, this);
|
inputReciever.pageBlur.add(this.onPageBlur, this);
|
||||||
}
|
inputReciever.destroyed.add(this.cleanup, this);
|
||||||
|
}
|
||||||
/**
|
|
||||||
* Returns all keybindings starting with the given id
|
/**
|
||||||
* @param {string} pattern
|
* Returns all keybindings starting with the given id
|
||||||
* @returns {Array<Keybinding>}
|
* @param {string} pattern
|
||||||
*/
|
* @returns {Array<Keybinding>}
|
||||||
getKeybindingsStartingWith(pattern) {
|
*/
|
||||||
let result = [];
|
getKeybindingsStartingWith(pattern) {
|
||||||
for (const key in this.keybindings) {
|
let result = [];
|
||||||
if (key.startsWith(pattern)) {
|
for (const key in this.keybindings) {
|
||||||
result.push(this.keybindings[key]);
|
if (key.startsWith(pattern)) {
|
||||||
}
|
result.push(this.keybindings[key]);
|
||||||
}
|
}
|
||||||
return result;
|
}
|
||||||
}
|
return result;
|
||||||
|
}
|
||||||
/**
|
|
||||||
* Forwards the given events to the other mapper (used in tooltips)
|
/**
|
||||||
* @param {KeyActionMapper} receiver
|
* Forwards the given events to the other mapper (used in tooltips)
|
||||||
* @param {Array<string>} bindings
|
* @param {KeyActionMapper} receiver
|
||||||
*/
|
* @param {Array<string>} bindings
|
||||||
forward(receiver, bindings) {
|
*/
|
||||||
for (let i = 0; i < bindings.length; ++i) {
|
forward(receiver, bindings) {
|
||||||
const key = bindings[i];
|
for (let i = 0; i < bindings.length; ++i) {
|
||||||
this.keybindings[key].signal.add((...args) => receiver.keybindings[key].signal.dispatch(...args));
|
const key = bindings[i];
|
||||||
}
|
this.keybindings[key].signal.add((...args) => receiver.keybindings[key].signal.dispatch(...args));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
cleanup() {
|
|
||||||
for (const key in this.keybindings) {
|
cleanup() {
|
||||||
this.keybindings[key].signal.removeAll();
|
for (const key in this.keybindings) {
|
||||||
}
|
this.keybindings[key].signal.removeAll();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
onPageBlur() {
|
|
||||||
// Reset all down states
|
onPageBlur() {
|
||||||
// Find mapping
|
// Reset all down states
|
||||||
for (const key in this.keybindings) {
|
// Find mapping
|
||||||
/** @type {Keybinding} */
|
for (const key in this.keybindings) {
|
||||||
const binding = this.keybindings[key];
|
/** @type {Keybinding} */
|
||||||
}
|
const binding = this.keybindings[key];
|
||||||
}
|
}
|
||||||
|
}
|
||||||
/**
|
|
||||||
* Internal keydown handler
|
/**
|
||||||
* @param {object} param0
|
* Internal keydown handler
|
||||||
* @param {number} param0.keyCode
|
* @param {object} param0
|
||||||
* @param {boolean} param0.shift
|
* @param {number} param0.keyCode
|
||||||
* @param {boolean} param0.alt
|
* @param {boolean} param0.shift
|
||||||
* @param {boolean=} param0.initial
|
* @param {boolean} param0.alt
|
||||||
*/
|
* @param {boolean=} param0.initial
|
||||||
handleKeydown({ keyCode, shift, alt, initial }) {
|
*/
|
||||||
let stop = false;
|
handleKeydown({ keyCode, shift, alt, initial }) {
|
||||||
|
let stop = false;
|
||||||
// Find mapping
|
|
||||||
for (const key in this.keybindings) {
|
// Find mapping
|
||||||
/** @type {Keybinding} */
|
for (const key in this.keybindings) {
|
||||||
const binding = this.keybindings[key];
|
/** @type {Keybinding} */
|
||||||
if (binding.keyCode === keyCode && (initial || binding.repeated)) {
|
const binding = this.keybindings[key];
|
||||||
/** @type {Signal} */
|
if (binding.keyCode === keyCode && (initial || binding.repeated)) {
|
||||||
const signal = this.keybindings[key].signal;
|
/** @type {Signal} */
|
||||||
if (signal.dispatch() === STOP_PROPAGATION) {
|
const signal = this.keybindings[key].signal;
|
||||||
return;
|
if (signal.dispatch() === STOP_PROPAGATION) {
|
||||||
}
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (stop) {
|
|
||||||
return STOP_PROPAGATION;
|
if (stop) {
|
||||||
}
|
return STOP_PROPAGATION;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
/**
|
|
||||||
* Internal keyup handler
|
/**
|
||||||
* @param {object} param0
|
* Internal keyup handler
|
||||||
* @param {number} param0.keyCode
|
* @param {object} param0
|
||||||
* @param {boolean} param0.shift
|
* @param {number} param0.keyCode
|
||||||
* @param {boolean} param0.alt
|
* @param {boolean} param0.shift
|
||||||
*/
|
* @param {boolean} param0.alt
|
||||||
handleKeyup({ keyCode, shift, alt }) {
|
*/
|
||||||
// Empty
|
handleKeyup({ keyCode, shift, alt }) {
|
||||||
}
|
// Empty
|
||||||
|
}
|
||||||
/**
|
|
||||||
* Returns a given keybinding
|
/**
|
||||||
* @param {{ keyCode: number }} binding
|
* Returns a given keybinding
|
||||||
* @returns {Keybinding}
|
* @param {{ keyCode: number }} binding
|
||||||
*/
|
* @returns {Keybinding}
|
||||||
getBinding(binding) {
|
*/
|
||||||
// @ts-ignore
|
getBinding(binding) {
|
||||||
const id = binding.id;
|
// @ts-ignore
|
||||||
assert(id, "Not a valid keybinding: " + JSON.stringify(binding));
|
const id = binding.id;
|
||||||
assert(this.keybindings[id], "Keybinding " + id + " not known!");
|
assert(id, "Not a valid keybinding: " + JSON.stringify(binding));
|
||||||
return this.keybindings[id];
|
assert(this.keybindings[id], "Keybinding " + id + " not known!");
|
||||||
}
|
return this.keybindings[id];
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
@ -1,162 +1,171 @@
|
|||||||
import { gMetaBuildingRegistry } from "../core/global_registries";
|
import { gMetaBuildingRegistry } from "../core/global_registries";
|
||||||
import { createLogger } from "../core/logging";
|
import { createLogger } from "../core/logging";
|
||||||
import { MetaBeltBuilding } from "./buildings/belt";
|
import { MetaBeltBuilding } from "./buildings/belt";
|
||||||
import { MetaBeltBaseBuilding } from "./buildings/belt_base";
|
import { MetaBeltBaseBuilding } from "./buildings/belt_base";
|
||||||
import { enumCutterVariants, MetaCutterBuilding } from "./buildings/cutter";
|
import { enumCutterVariants, MetaCutterBuilding } from "./buildings/cutter";
|
||||||
import { MetaHubBuilding } from "./buildings/hub";
|
import { MetaHubBuilding } from "./buildings/hub";
|
||||||
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 { enumRotaterVariants, MetaRotaterBuilding } from "./buildings/rotater";
|
import { enumRotaterVariants, MetaRotaterBuilding } from "./buildings/rotater";
|
||||||
import { enumSplitterVariants, MetaSplitterBuilding } from "./buildings/splitter";
|
import { enumSplitterVariants, MetaSplitterBuilding } from "./buildings/splitter";
|
||||||
import { MetaStackerBuilding } from "./buildings/stacker";
|
import { MetaStackerBuilding } from "./buildings/stacker";
|
||||||
import { enumTrashVariants, MetaTrashBuilding } from "./buildings/trash";
|
import { enumTrashVariants, MetaTrashBuilding } from "./buildings/trash";
|
||||||
import { enumUndergroundBeltVariants, MetaUndergroundBeltBuilding } from "./buildings/underground_belt";
|
import { enumUndergroundBeltVariants, MetaUndergroundBeltBuilding } from "./buildings/underground_belt";
|
||||||
import { MetaWireBuilding } from "./buildings/wire";
|
import { MetaWireBuilding } from "./buildings/wire";
|
||||||
import { gBuildingVariants, registerBuildingVariant } from "./building_codes";
|
import { gBuildingVariants, registerBuildingVariant } from "./building_codes";
|
||||||
import { defaultBuildingVariant } from "./meta_building";
|
import { defaultBuildingVariant } from "./meta_building";
|
||||||
import { MetaConstantSignalBuilding } from "./buildings/constant_signal";
|
import { MetaConstantSignalBuilding } from "./buildings/constant_signal";
|
||||||
import { MetaLogicGateBuilding, enumLogicGateVariants } from "./buildings/logic_gate";
|
import { MetaLogicGateBuilding, enumLogicGateVariants } from "./buildings/logic_gate";
|
||||||
import { MetaLeverBuilding } from "./buildings/lever";
|
import { MetaLeverBuilding } from "./buildings/lever";
|
||||||
import { MetaFilterBuilding } from "./buildings/filter";
|
import { MetaFilterBuilding } from "./buildings/filter";
|
||||||
import { MetaWireTunnelBuilding, enumWireTunnelVariants } from "./buildings/wire_tunnel";
|
import { MetaWireTunnelBuilding, enumWireTunnelVariants } from "./buildings/wire_tunnel";
|
||||||
import { MetaDisplayBuilding } from "./buildings/display";
|
import { MetaDisplayBuilding } from "./buildings/display";
|
||||||
|
import { MetaVirtualProcessorBuilding, enumVirtualProcessorVariants } from "./buildings/virtual_processor";
|
||||||
const logger = createLogger("building_registry");
|
|
||||||
|
const logger = createLogger("building_registry");
|
||||||
export function initMetaBuildingRegistry() {
|
|
||||||
gMetaBuildingRegistry.register(MetaSplitterBuilding);
|
export function initMetaBuildingRegistry() {
|
||||||
gMetaBuildingRegistry.register(MetaMinerBuilding);
|
gMetaBuildingRegistry.register(MetaSplitterBuilding);
|
||||||
gMetaBuildingRegistry.register(MetaCutterBuilding);
|
gMetaBuildingRegistry.register(MetaMinerBuilding);
|
||||||
gMetaBuildingRegistry.register(MetaRotaterBuilding);
|
gMetaBuildingRegistry.register(MetaCutterBuilding);
|
||||||
gMetaBuildingRegistry.register(MetaStackerBuilding);
|
gMetaBuildingRegistry.register(MetaRotaterBuilding);
|
||||||
gMetaBuildingRegistry.register(MetaMixerBuilding);
|
gMetaBuildingRegistry.register(MetaStackerBuilding);
|
||||||
gMetaBuildingRegistry.register(MetaPainterBuilding);
|
gMetaBuildingRegistry.register(MetaMixerBuilding);
|
||||||
gMetaBuildingRegistry.register(MetaTrashBuilding);
|
gMetaBuildingRegistry.register(MetaPainterBuilding);
|
||||||
gMetaBuildingRegistry.register(MetaBeltBuilding);
|
gMetaBuildingRegistry.register(MetaTrashBuilding);
|
||||||
gMetaBuildingRegistry.register(MetaUndergroundBeltBuilding);
|
gMetaBuildingRegistry.register(MetaBeltBuilding);
|
||||||
gMetaBuildingRegistry.register(MetaHubBuilding);
|
gMetaBuildingRegistry.register(MetaUndergroundBeltBuilding);
|
||||||
gMetaBuildingRegistry.register(MetaWireBuilding);
|
gMetaBuildingRegistry.register(MetaHubBuilding);
|
||||||
gMetaBuildingRegistry.register(MetaConstantSignalBuilding);
|
gMetaBuildingRegistry.register(MetaWireBuilding);
|
||||||
gMetaBuildingRegistry.register(MetaLogicGateBuilding);
|
gMetaBuildingRegistry.register(MetaConstantSignalBuilding);
|
||||||
gMetaBuildingRegistry.register(MetaLeverBuilding);
|
gMetaBuildingRegistry.register(MetaLogicGateBuilding);
|
||||||
gMetaBuildingRegistry.register(MetaFilterBuilding);
|
gMetaBuildingRegistry.register(MetaLeverBuilding);
|
||||||
gMetaBuildingRegistry.register(MetaWireTunnelBuilding);
|
gMetaBuildingRegistry.register(MetaFilterBuilding);
|
||||||
gMetaBuildingRegistry.register(MetaDisplayBuilding);
|
gMetaBuildingRegistry.register(MetaWireTunnelBuilding);
|
||||||
|
gMetaBuildingRegistry.register(MetaDisplayBuilding);
|
||||||
// Belt
|
gMetaBuildingRegistry.register(MetaVirtualProcessorBuilding);
|
||||||
registerBuildingVariant(1, MetaBeltBaseBuilding, defaultBuildingVariant, 0);
|
|
||||||
registerBuildingVariant(2, MetaBeltBaseBuilding, defaultBuildingVariant, 1);
|
// Belt
|
||||||
registerBuildingVariant(3, MetaBeltBaseBuilding, defaultBuildingVariant, 2);
|
registerBuildingVariant(1, MetaBeltBaseBuilding, defaultBuildingVariant, 0);
|
||||||
|
registerBuildingVariant(2, MetaBeltBaseBuilding, defaultBuildingVariant, 1);
|
||||||
// Splitter
|
registerBuildingVariant(3, MetaBeltBaseBuilding, defaultBuildingVariant, 2);
|
||||||
registerBuildingVariant(4, MetaSplitterBuilding);
|
|
||||||
registerBuildingVariant(5, MetaSplitterBuilding, enumSplitterVariants.compact);
|
// Splitter
|
||||||
registerBuildingVariant(6, MetaSplitterBuilding, enumSplitterVariants.compactInverse);
|
registerBuildingVariant(4, MetaSplitterBuilding);
|
||||||
|
registerBuildingVariant(5, MetaSplitterBuilding, enumSplitterVariants.compact);
|
||||||
// Miner
|
registerBuildingVariant(6, MetaSplitterBuilding, enumSplitterVariants.compactInverse);
|
||||||
registerBuildingVariant(7, MetaMinerBuilding);
|
|
||||||
registerBuildingVariant(8, MetaMinerBuilding, enumMinerVariants.chainable);
|
// Miner
|
||||||
|
registerBuildingVariant(7, MetaMinerBuilding);
|
||||||
// Cutter
|
registerBuildingVariant(8, MetaMinerBuilding, enumMinerVariants.chainable);
|
||||||
registerBuildingVariant(9, MetaCutterBuilding);
|
|
||||||
registerBuildingVariant(10, MetaCutterBuilding, enumCutterVariants.quad);
|
// Cutter
|
||||||
|
registerBuildingVariant(9, MetaCutterBuilding);
|
||||||
// Rotater
|
registerBuildingVariant(10, MetaCutterBuilding, enumCutterVariants.quad);
|
||||||
registerBuildingVariant(11, MetaRotaterBuilding);
|
|
||||||
registerBuildingVariant(12, MetaRotaterBuilding, enumRotaterVariants.ccw);
|
// Rotater
|
||||||
registerBuildingVariant(13, MetaRotaterBuilding, enumRotaterVariants.fl);
|
registerBuildingVariant(11, MetaRotaterBuilding);
|
||||||
|
registerBuildingVariant(12, MetaRotaterBuilding, enumRotaterVariants.ccw);
|
||||||
// Stacker
|
registerBuildingVariant(13, MetaRotaterBuilding, enumRotaterVariants.fl);
|
||||||
registerBuildingVariant(14, MetaStackerBuilding);
|
|
||||||
|
// Stacker
|
||||||
// Mixer
|
registerBuildingVariant(14, MetaStackerBuilding);
|
||||||
registerBuildingVariant(15, MetaMixerBuilding);
|
|
||||||
|
// Mixer
|
||||||
// Painter
|
registerBuildingVariant(15, MetaMixerBuilding);
|
||||||
registerBuildingVariant(16, MetaPainterBuilding);
|
|
||||||
registerBuildingVariant(17, MetaPainterBuilding, enumPainterVariants.mirrored);
|
// Painter
|
||||||
registerBuildingVariant(18, MetaPainterBuilding, enumPainterVariants.double);
|
registerBuildingVariant(16, MetaPainterBuilding);
|
||||||
registerBuildingVariant(19, MetaPainterBuilding, enumPainterVariants.quad);
|
registerBuildingVariant(17, MetaPainterBuilding, enumPainterVariants.mirrored);
|
||||||
|
registerBuildingVariant(18, MetaPainterBuilding, enumPainterVariants.double);
|
||||||
// Trash
|
registerBuildingVariant(19, MetaPainterBuilding, enumPainterVariants.quad);
|
||||||
registerBuildingVariant(20, MetaTrashBuilding);
|
|
||||||
registerBuildingVariant(21, MetaTrashBuilding, enumTrashVariants.storage);
|
// Trash
|
||||||
|
registerBuildingVariant(20, MetaTrashBuilding);
|
||||||
// Underground belt
|
registerBuildingVariant(21, MetaTrashBuilding, enumTrashVariants.storage);
|
||||||
registerBuildingVariant(22, MetaUndergroundBeltBuilding, defaultBuildingVariant, 0);
|
|
||||||
registerBuildingVariant(23, MetaUndergroundBeltBuilding, defaultBuildingVariant, 1);
|
// Underground belt
|
||||||
registerBuildingVariant(24, MetaUndergroundBeltBuilding, enumUndergroundBeltVariants.tier2, 0);
|
registerBuildingVariant(22, MetaUndergroundBeltBuilding, defaultBuildingVariant, 0);
|
||||||
registerBuildingVariant(25, MetaUndergroundBeltBuilding, enumUndergroundBeltVariants.tier2, 1);
|
registerBuildingVariant(23, MetaUndergroundBeltBuilding, defaultBuildingVariant, 1);
|
||||||
|
registerBuildingVariant(24, MetaUndergroundBeltBuilding, enumUndergroundBeltVariants.tier2, 0);
|
||||||
// Hub
|
registerBuildingVariant(25, MetaUndergroundBeltBuilding, enumUndergroundBeltVariants.tier2, 1);
|
||||||
registerBuildingVariant(26, MetaHubBuilding);
|
|
||||||
|
// Hub
|
||||||
// Wire
|
registerBuildingVariant(26, MetaHubBuilding);
|
||||||
registerBuildingVariant(27, MetaWireBuilding, defaultBuildingVariant, 0);
|
|
||||||
registerBuildingVariant(28, MetaWireBuilding, defaultBuildingVariant, 1);
|
// Wire
|
||||||
registerBuildingVariant(29, MetaWireBuilding, defaultBuildingVariant, 2);
|
registerBuildingVariant(27, MetaWireBuilding, defaultBuildingVariant, 0);
|
||||||
registerBuildingVariant(30, MetaWireBuilding, defaultBuildingVariant, 3);
|
registerBuildingVariant(28, MetaWireBuilding, defaultBuildingVariant, 1);
|
||||||
|
registerBuildingVariant(29, MetaWireBuilding, defaultBuildingVariant, 2);
|
||||||
// Constant signal
|
registerBuildingVariant(30, MetaWireBuilding, defaultBuildingVariant, 3);
|
||||||
registerBuildingVariant(31, MetaConstantSignalBuilding);
|
|
||||||
|
// Constant signal
|
||||||
// Logic gate
|
registerBuildingVariant(31, MetaConstantSignalBuilding);
|
||||||
registerBuildingVariant(32, MetaLogicGateBuilding);
|
|
||||||
registerBuildingVariant(34, MetaLogicGateBuilding, enumLogicGateVariants.not);
|
// Logic gate
|
||||||
registerBuildingVariant(35, MetaLogicGateBuilding, enumLogicGateVariants.xor);
|
registerBuildingVariant(32, MetaLogicGateBuilding);
|
||||||
registerBuildingVariant(36, MetaLogicGateBuilding, enumLogicGateVariants.or);
|
registerBuildingVariant(34, MetaLogicGateBuilding, enumLogicGateVariants.not);
|
||||||
registerBuildingVariant(38, MetaLogicGateBuilding, enumLogicGateVariants.transistor);
|
registerBuildingVariant(35, MetaLogicGateBuilding, enumLogicGateVariants.xor);
|
||||||
|
registerBuildingVariant(36, MetaLogicGateBuilding, enumLogicGateVariants.or);
|
||||||
// Lever
|
registerBuildingVariant(38, MetaLogicGateBuilding, enumLogicGateVariants.transistor);
|
||||||
registerBuildingVariant(33, MetaLeverBuilding);
|
|
||||||
|
// Lever
|
||||||
// Filter
|
registerBuildingVariant(33, MetaLeverBuilding);
|
||||||
registerBuildingVariant(37, MetaFilterBuilding);
|
|
||||||
|
// Filter
|
||||||
// Wire tunnel
|
registerBuildingVariant(37, MetaFilterBuilding);
|
||||||
registerBuildingVariant(39, MetaWireTunnelBuilding);
|
|
||||||
registerBuildingVariant(41, MetaWireTunnelBuilding, enumWireTunnelVariants.coating);
|
// Wire tunnel
|
||||||
|
registerBuildingVariant(39, MetaWireTunnelBuilding);
|
||||||
// Display
|
registerBuildingVariant(41, MetaWireTunnelBuilding, enumWireTunnelVariants.coating);
|
||||||
registerBuildingVariant(40, MetaDisplayBuilding);
|
|
||||||
|
// Display
|
||||||
// Propagate instances
|
registerBuildingVariant(40, MetaDisplayBuilding);
|
||||||
for (const key in gBuildingVariants) {
|
|
||||||
gBuildingVariants[key].metaInstance = gMetaBuildingRegistry.findByClass(
|
// Virtual Processor
|
||||||
gBuildingVariants[key].metaClass
|
registerBuildingVariant(42, MetaVirtualProcessorBuilding);
|
||||||
);
|
registerBuildingVariant(43, MetaVirtualProcessorBuilding, enumVirtualProcessorVariants.analyzer);
|
||||||
}
|
registerBuildingVariant(44, MetaVirtualProcessorBuilding, enumVirtualProcessorVariants.rotater);
|
||||||
|
registerBuildingVariant(45, MetaVirtualProcessorBuilding, enumVirtualProcessorVariants.unstacker);
|
||||||
for (const key in gBuildingVariants) {
|
registerBuildingVariant(46, MetaVirtualProcessorBuilding, enumVirtualProcessorVariants.shapecompare);
|
||||||
const variant = gBuildingVariants[key];
|
|
||||||
assert(variant.metaClass, "Variant has no meta: " + key);
|
// Propagate instances
|
||||||
|
for (const key in gBuildingVariants) {
|
||||||
if (typeof variant.rotationVariant === "undefined") {
|
gBuildingVariants[key].metaInstance = gMetaBuildingRegistry.findByClass(
|
||||||
variant.rotationVariant = 0;
|
gBuildingVariants[key].metaClass
|
||||||
}
|
);
|
||||||
if (typeof variant.variant === "undefined") {
|
}
|
||||||
variant.variant = defaultBuildingVariant;
|
|
||||||
}
|
for (const key in gBuildingVariants) {
|
||||||
}
|
const variant = gBuildingVariants[key];
|
||||||
|
assert(variant.metaClass, "Variant has no meta: " + key);
|
||||||
logger.log("Registered", gMetaBuildingRegistry.getNumEntries(), "buildings");
|
|
||||||
logger.log("Registered", Object.keys(gBuildingVariants).length, "building codes");
|
if (typeof variant.rotationVariant === "undefined") {
|
||||||
}
|
variant.rotationVariant = 0;
|
||||||
|
}
|
||||||
/**
|
if (typeof variant.variant === "undefined") {
|
||||||
* Once all sprites are loaded, propagates the cache
|
variant.variant = defaultBuildingVariant;
|
||||||
*/
|
}
|
||||||
export function initBuildingCodesAfterResourcesLoaded() {
|
}
|
||||||
logger.log("Propagating sprite cache");
|
|
||||||
for (const key in gBuildingVariants) {
|
logger.log("Registered", gMetaBuildingRegistry.getNumEntries(), "buildings");
|
||||||
const variant = gBuildingVariants[key];
|
logger.log("Registered", Object.keys(gBuildingVariants).length, "building codes");
|
||||||
|
}
|
||||||
variant.sprite = variant.metaInstance.getSprite(variant.rotationVariant, variant.variant);
|
|
||||||
variant.blueprintSprite = variant.metaInstance.getBlueprintSprite(
|
/**
|
||||||
variant.rotationVariant,
|
* Once all sprites are loaded, propagates the cache
|
||||||
variant.variant
|
*/
|
||||||
);
|
export function initBuildingCodesAfterResourcesLoaded() {
|
||||||
variant.silhouetteColor = variant.metaInstance.getSilhouetteColor();
|
logger.log("Propagating sprite cache");
|
||||||
}
|
for (const key in gBuildingVariants) {
|
||||||
}
|
const variant = gBuildingVariants[key];
|
||||||
|
|
||||||
|
variant.sprite = variant.metaInstance.getSprite(variant.rotationVariant, variant.variant);
|
||||||
|
variant.blueprintSprite = variant.metaInstance.getBlueprintSprite(
|
||||||
|
variant.rotationVariant,
|
||||||
|
variant.variant
|
||||||
|
);
|
||||||
|
variant.silhouetteColor = variant.metaInstance.getSilhouetteColor();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,180 +1,318 @@
|
|||||||
import { LogicGateComponent, enumLogicGateType } from "../components/logic_gate";
|
import { BaseItem } from "../base_item";
|
||||||
import { GameSystemWithFilter } from "../game_system_with_filter";
|
import { enumColors } from "../colors";
|
||||||
import { BaseItem } from "../base_item";
|
import { enumLogicGateType, LogicGateComponent } from "../components/logic_gate";
|
||||||
import { enumPinSlotType } from "../components/wired_pins";
|
import { enumPinSlotType } from "../components/wired_pins";
|
||||||
import { BOOL_TRUE_SINGLETON, BOOL_FALSE_SINGLETON, BooleanItem } from "../items/boolean_item";
|
import { GameSystemWithFilter } from "../game_system_with_filter";
|
||||||
import { enumItemProcessorTypes } from "../components/item_processor";
|
import { BOOL_FALSE_SINGLETON, BOOL_TRUE_SINGLETON, BooleanItem } from "../items/boolean_item";
|
||||||
|
import { COLOR_ITEM_SINGLETONS } from "../items/color_item";
|
||||||
export class LogicGateSystem extends GameSystemWithFilter {
|
import { ShapeDefinition } from "../shape_definition";
|
||||||
constructor(root) {
|
import { ShapeItem } from "../items/shape_item";
|
||||||
super(root, [LogicGateComponent]);
|
|
||||||
|
export class LogicGateSystem extends GameSystemWithFilter {
|
||||||
this.boundOperations = {
|
constructor(root) {
|
||||||
[enumLogicGateType.and]: this.compute_AND.bind(this),
|
super(root, [LogicGateComponent]);
|
||||||
[enumLogicGateType.not]: this.compute_NOT.bind(this),
|
|
||||||
[enumLogicGateType.xor]: this.compute_XOR.bind(this),
|
this.boundOperations = {
|
||||||
[enumLogicGateType.or]: this.compute_OR.bind(this),
|
[enumLogicGateType.and]: this.compute_AND.bind(this),
|
||||||
[enumLogicGateType.transistor]: this.compute_IF.bind(this),
|
[enumLogicGateType.not]: this.compute_NOT.bind(this),
|
||||||
};
|
[enumLogicGateType.xor]: this.compute_XOR.bind(this),
|
||||||
}
|
[enumLogicGateType.or]: this.compute_OR.bind(this),
|
||||||
|
[enumLogicGateType.transistor]: this.compute_IF.bind(this),
|
||||||
update() {
|
|
||||||
for (let i = 0; i < this.allEntities.length; ++i) {
|
[enumLogicGateType.rotater]: this.compute_ROTATE.bind(this),
|
||||||
const entity = this.allEntities[i];
|
[enumLogicGateType.analyzer]: this.compute_ANALYZE.bind(this),
|
||||||
const logicComp = entity.components.LogicGate;
|
[enumLogicGateType.cutter]: this.compute_CUT.bind(this),
|
||||||
const slotComp = entity.components.WiredPins;
|
[enumLogicGateType.unstacker]: this.compute_UNSTACK.bind(this),
|
||||||
|
[enumLogicGateType.shapecompare]: this.compute_SHAPECOMPARE.bind(this),
|
||||||
const slotValues = [];
|
};
|
||||||
|
}
|
||||||
for (let i = 0; i < slotComp.slots.length; ++i) {
|
|
||||||
const slot = slotComp.slots[i];
|
update() {
|
||||||
if (slot.type !== enumPinSlotType.logicalAcceptor) {
|
for (let i = 0; i < this.allEntities.length; ++i) {
|
||||||
continue;
|
const entity = this.allEntities[i];
|
||||||
}
|
const logicComp = entity.components.LogicGate;
|
||||||
if (slot.linkedNetwork) {
|
const slotComp = entity.components.WiredPins;
|
||||||
slotValues.push(slot.linkedNetwork.currentValue);
|
|
||||||
} else {
|
const slotValues = [];
|
||||||
slotValues.push(null);
|
|
||||||
}
|
for (let i = 0; i < slotComp.slots.length; ++i) {
|
||||||
}
|
const slot = slotComp.slots[i];
|
||||||
|
if (slot.type !== enumPinSlotType.logicalAcceptor) {
|
||||||
const result = this.boundOperations[logicComp.type](slotValues);
|
continue;
|
||||||
|
}
|
||||||
// @TODO: For now we hardcode the value to always be slot 0
|
if (slot.linkedNetwork) {
|
||||||
assert(
|
slotValues.push(slot.linkedNetwork.currentValue);
|
||||||
slotValues.length === slotComp.slots.length - 1,
|
} else {
|
||||||
"Bad slot config, should have N acceptor slots and 1 ejector"
|
slotValues.push(null);
|
||||||
);
|
}
|
||||||
assert(slotComp.slots[0].type === enumPinSlotType.logicalEjector, "Slot 0 should be ejector");
|
}
|
||||||
|
|
||||||
slotComp.slots[0].value = result;
|
const result = this.boundOperations[logicComp.type](slotValues);
|
||||||
}
|
|
||||||
}
|
if (Array.isArray(result)) {
|
||||||
|
let resultIndex = 0;
|
||||||
/**
|
for (let i = 0; i < slotComp.slots.length; ++i) {
|
||||||
* @param {Array<BaseItem|null>} parameters
|
const slot = slotComp.slots[i];
|
||||||
* @returns {BaseItem}
|
if (slot.type !== enumPinSlotType.logicalEjector) {
|
||||||
*/
|
continue;
|
||||||
compute_AND(parameters) {
|
}
|
||||||
assert(parameters.length === 2, "bad parameter count for AND");
|
slot.value = result[resultIndex++];
|
||||||
|
}
|
||||||
const param1 = parameters[0];
|
} else {
|
||||||
const param2 = parameters[1];
|
// @TODO: For now we hardcode the value to always be slot 0
|
||||||
if (!param1 || !param2) {
|
assert(
|
||||||
// Not enough params
|
slotValues.length === slotComp.slots.length - 1,
|
||||||
return BOOL_FALSE_SINGLETON;
|
"Bad slot config, should have N acceptor slots and 1 ejector"
|
||||||
}
|
);
|
||||||
|
assert(slotComp.slots[0].type === enumPinSlotType.logicalEjector, "Slot 0 should be ejector");
|
||||||
const itemType = param1.getItemType();
|
slotComp.slots[0].value = result;
|
||||||
|
}
|
||||||
if (itemType !== param2.getItemType()) {
|
}
|
||||||
// Differing type
|
}
|
||||||
return BOOL_FALSE_SINGLETON;
|
|
||||||
}
|
/**
|
||||||
|
* @param {Array<BaseItem|null>} parameters
|
||||||
if (itemType === "boolean") {
|
* @returns {BaseItem}
|
||||||
return /** @type {BooleanItem} */ (param1).value && /** @type {BooleanItem} */ (param2).value
|
*/
|
||||||
? BOOL_TRUE_SINGLETON
|
compute_AND(parameters) {
|
||||||
: BOOL_FALSE_SINGLETON;
|
assert(parameters.length === 2, "bad parameter count for AND");
|
||||||
}
|
|
||||||
|
const param1 = parameters[0];
|
||||||
return BOOL_FALSE_SINGLETON;
|
const param2 = parameters[1];
|
||||||
}
|
if (!param1 || !param2) {
|
||||||
|
// Not enough params
|
||||||
/**
|
return BOOL_FALSE_SINGLETON;
|
||||||
* @param {Array<BaseItem|null>} parameters
|
}
|
||||||
* @returns {BaseItem}
|
|
||||||
*/
|
const itemType = param1.getItemType();
|
||||||
compute_NOT(parameters) {
|
|
||||||
const item = parameters[0];
|
if (itemType !== param2.getItemType()) {
|
||||||
if (!item) {
|
// Differing type
|
||||||
return BOOL_TRUE_SINGLETON;
|
return BOOL_FALSE_SINGLETON;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (item.getItemType() !== "boolean") {
|
if (itemType === "boolean") {
|
||||||
// Not a boolean actually
|
return /** @type {BooleanItem} */ (param1).value && /** @type {BooleanItem} */ (param2).value
|
||||||
return BOOL_FALSE_SINGLETON;
|
? BOOL_TRUE_SINGLETON
|
||||||
}
|
: BOOL_FALSE_SINGLETON;
|
||||||
|
}
|
||||||
const value = /** @type {BooleanItem} */ (item).value;
|
|
||||||
return value ? BOOL_FALSE_SINGLETON : BOOL_TRUE_SINGLETON;
|
return BOOL_FALSE_SINGLETON;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {Array<BaseItem|null>} parameters
|
* @param {Array<BaseItem|null>} parameters
|
||||||
* @returns {BaseItem}
|
* @returns {BaseItem}
|
||||||
*/
|
*/
|
||||||
compute_XOR(parameters) {
|
compute_NOT(parameters) {
|
||||||
assert(parameters.length === 2, "bad parameter count for XOR");
|
const item = parameters[0];
|
||||||
|
if (!item) {
|
||||||
const param1 = parameters[0];
|
return BOOL_TRUE_SINGLETON;
|
||||||
const param2 = parameters[1];
|
}
|
||||||
if (!param1 && !param2) {
|
|
||||||
// Not enough params
|
if (item.getItemType() !== "boolean") {
|
||||||
return BOOL_FALSE_SINGLETON;
|
// Not a boolean actually
|
||||||
}
|
return BOOL_FALSE_SINGLETON;
|
||||||
|
}
|
||||||
// Check for the right types
|
|
||||||
if (param1 && param1.getItemType() !== "boolean") {
|
const value = /** @type {BooleanItem} */ (item).value;
|
||||||
return BOOL_FALSE_SINGLETON;
|
return value ? BOOL_FALSE_SINGLETON : BOOL_TRUE_SINGLETON;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (param2 && param2.getItemType() !== "boolean") {
|
/**
|
||||||
return BOOL_FALSE_SINGLETON;
|
* @param {Array<BaseItem|null>} parameters
|
||||||
}
|
* @returns {BaseItem}
|
||||||
|
*/
|
||||||
const valueParam1 = param1 ? /** @type {BooleanItem} */ (param1).value : 0;
|
compute_XOR(parameters) {
|
||||||
const valueParam2 = param2 ? /** @type {BooleanItem} */ (param2).value : 0;
|
assert(parameters.length === 2, "bad parameter count for XOR");
|
||||||
|
|
||||||
return valueParam1 ^ valueParam2 ? BOOL_TRUE_SINGLETON : BOOL_FALSE_SINGLETON;
|
const param1 = parameters[0];
|
||||||
}
|
const param2 = parameters[1];
|
||||||
|
if (!param1 && !param2) {
|
||||||
/**
|
// Not enough params
|
||||||
* @param {Array<BaseItem|null>} parameters
|
return BOOL_FALSE_SINGLETON;
|
||||||
* @returns {BaseItem}
|
}
|
||||||
*/
|
|
||||||
compute_OR(parameters) {
|
// Check for the right types
|
||||||
assert(parameters.length === 2, "bad parameter count for OR");
|
if (param1 && param1.getItemType() !== "boolean") {
|
||||||
|
return BOOL_FALSE_SINGLETON;
|
||||||
const param1 = parameters[0];
|
}
|
||||||
const param2 = parameters[1];
|
|
||||||
if (!param1 && !param2) {
|
if (param2 && param2.getItemType() !== "boolean") {
|
||||||
// Not enough params
|
return BOOL_FALSE_SINGLETON;
|
||||||
return BOOL_FALSE_SINGLETON;
|
}
|
||||||
}
|
|
||||||
|
const valueParam1 = param1 ? /** @type {BooleanItem} */ (param1).value : 0;
|
||||||
const valueParam1 =
|
const valueParam2 = param2 ? /** @type {BooleanItem} */ (param2).value : 0;
|
||||||
param1 && param1.getItemType() === "boolean" ? /** @type {BooleanItem} */ (param1).value : 0;
|
|
||||||
const valueParam2 =
|
return valueParam1 ^ valueParam2 ? BOOL_TRUE_SINGLETON : BOOL_FALSE_SINGLETON;
|
||||||
param2 && param2.getItemType() === "boolean" ? /** @type {BooleanItem} */ (param2).value : 0;
|
}
|
||||||
|
|
||||||
return valueParam1 || valueParam2 ? BOOL_TRUE_SINGLETON : BOOL_FALSE_SINGLETON;
|
/**
|
||||||
}
|
* @param {Array<BaseItem|null>} parameters
|
||||||
|
* @returns {BaseItem}
|
||||||
/**
|
*/
|
||||||
* @param {Array<BaseItem|null>} parameters
|
compute_OR(parameters) {
|
||||||
* @returns {BaseItem}
|
assert(parameters.length === 2, "bad parameter count for OR");
|
||||||
*/
|
|
||||||
compute_IF(parameters) {
|
const param1 = parameters[0];
|
||||||
assert(parameters.length === 2, "bad parameter count for IF");
|
const param2 = parameters[1];
|
||||||
|
if (!param1 && !param2) {
|
||||||
const flag = parameters[0];
|
// Not enough params
|
||||||
const value = parameters[1];
|
return BOOL_FALSE_SINGLETON;
|
||||||
if (!flag || !value) {
|
}
|
||||||
// Not enough params
|
|
||||||
return null;
|
const valueParam1 =
|
||||||
}
|
param1 && param1.getItemType() === "boolean" ? /** @type {BooleanItem} */ (param1).value : 0;
|
||||||
|
const valueParam2 =
|
||||||
if (flag.getItemType() !== "boolean") {
|
param2 && param2.getItemType() === "boolean" ? /** @type {BooleanItem} */ (param2).value : 0;
|
||||||
// Flag is not a boolean
|
|
||||||
return null;
|
return valueParam1 || valueParam2 ? BOOL_TRUE_SINGLETON : BOOL_FALSE_SINGLETON;
|
||||||
}
|
}
|
||||||
|
|
||||||
// pass through item
|
/**
|
||||||
if (/** @type {BooleanItem} */ (flag).value) {
|
* @param {Array<BaseItem|null>} parameters
|
||||||
return value;
|
* @returns {BaseItem}
|
||||||
}
|
*/
|
||||||
|
compute_IF(parameters) {
|
||||||
return null;
|
assert(parameters.length === 2, "bad parameter count for IF");
|
||||||
}
|
|
||||||
}
|
const flag = parameters[0];
|
||||||
|
const value = parameters[1];
|
||||||
|
if (!flag || !value) {
|
||||||
|
// Not enough params
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flag.getItemType() !== "boolean") {
|
||||||
|
// Flag is not a boolean
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// pass through item
|
||||||
|
if (/** @type {BooleanItem} */ (flag).value) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Array<BaseItem|null>} parameters
|
||||||
|
* @returns {BaseItem}
|
||||||
|
*/
|
||||||
|
compute_ROTATE(parameters) {
|
||||||
|
const item = parameters[0];
|
||||||
|
if (!item || item.getItemType() !== "shape") {
|
||||||
|
// Not a shape
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const definition = /** @type {ShapeItem} */ (item).definition;
|
||||||
|
const rotatedDefinition = this.root.shapeDefinitionMgr.shapeActionRotateCW(definition);
|
||||||
|
return this.root.shapeDefinitionMgr.getShapeItemFromDefinition(rotatedDefinition);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Array<BaseItem|null>} parameters
|
||||||
|
* @returns {[BaseItem, BaseItem]}
|
||||||
|
*/
|
||||||
|
compute_ANALYZE(parameters) {
|
||||||
|
const item = parameters[0];
|
||||||
|
if (!item || item.getItemType() !== "shape") {
|
||||||
|
// Not a shape
|
||||||
|
return [null, null];
|
||||||
|
}
|
||||||
|
|
||||||
|
const definition = /** @type {ShapeItem} */ (item).definition;
|
||||||
|
const lowerLayer = /** @type {import("../shape_definition").ShapeLayer} */ (definition.layers[0]);
|
||||||
|
const topRightContent = lowerLayer[0];
|
||||||
|
|
||||||
|
if (!topRightContent) {
|
||||||
|
return [null, null];
|
||||||
|
}
|
||||||
|
|
||||||
|
const newDefinition = new ShapeDefinition({
|
||||||
|
layers: [
|
||||||
|
[
|
||||||
|
{ subShape: topRightContent.subShape, color: enumColors.uncolored },
|
||||||
|
{ subShape: topRightContent.subShape, color: enumColors.uncolored },
|
||||||
|
{ subShape: topRightContent.subShape, color: enumColors.uncolored },
|
||||||
|
{ subShape: topRightContent.subShape, color: enumColors.uncolored },
|
||||||
|
],
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
return [
|
||||||
|
COLOR_ITEM_SINGLETONS[topRightContent.color],
|
||||||
|
this.root.shapeDefinitionMgr.getShapeItemFromDefinition(newDefinition),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Array<BaseItem|null>} parameters
|
||||||
|
* @returns {[BaseItem, BaseItem]}
|
||||||
|
*/
|
||||||
|
compute_CUT(parameters) {
|
||||||
|
const item = parameters[0];
|
||||||
|
if (!item || item.getItemType() !== "shape") {
|
||||||
|
// Not a shape
|
||||||
|
return [null, null];
|
||||||
|
}
|
||||||
|
|
||||||
|
const definition = /** @type {ShapeItem} */ (item).definition;
|
||||||
|
const result = this.root.shapeDefinitionMgr.shapeActionCutHalf(definition);
|
||||||
|
return [
|
||||||
|
this.root.shapeDefinitionMgr.getShapeItemFromDefinition(result[0]),
|
||||||
|
this.root.shapeDefinitionMgr.getShapeItemFromDefinition(result[1]),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Array<BaseItem|null>} parameters
|
||||||
|
* @returns {[BaseItem, BaseItem]}
|
||||||
|
*/
|
||||||
|
compute_UNSTACK(parameters) {
|
||||||
|
const item = parameters[0];
|
||||||
|
if (!item || item.getItemType() !== "shape") {
|
||||||
|
// Not a shape
|
||||||
|
return [null, null];
|
||||||
|
}
|
||||||
|
|
||||||
|
const definition = /** @type {ShapeItem} */ (item).definition;
|
||||||
|
const layers = /** @type {Array<import("../shape_definition").ShapeLayer>} */ (definition.layers);
|
||||||
|
|
||||||
|
const upperLayerDefinition = new ShapeDefinition({
|
||||||
|
layers: [layers[layers.length - 1]],
|
||||||
|
});
|
||||||
|
|
||||||
|
const lowerLayers = layers.slice(0, layers.length - 1);
|
||||||
|
const lowerLayerDefinition =
|
||||||
|
lowerLayers.length > 0 ? new ShapeDefinition({ layers: lowerLayers }) : null;
|
||||||
|
|
||||||
|
return [
|
||||||
|
lowerLayerDefinition
|
||||||
|
? this.root.shapeDefinitionMgr.getShapeItemFromDefinition(lowerLayerDefinition)
|
||||||
|
: null,
|
||||||
|
this.root.shapeDefinitionMgr.getShapeItemFromDefinition(upperLayerDefinition),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Array<BaseItem|null>} parameters
|
||||||
|
* @returns {BaseItem}
|
||||||
|
*/
|
||||||
|
compute_SHAPECOMPARE(parameters) {
|
||||||
|
const itemA = parameters[0];
|
||||||
|
const itemB = parameters[1];
|
||||||
|
|
||||||
|
return itemA &&
|
||||||
|
itemB &&
|
||||||
|
itemA.getItemType() === "shape" &&
|
||||||
|
itemB.getItemType() === "shape" &&
|
||||||
|
/** @type {ShapeItem} */ (itemA).definition.getHash() ===
|
||||||
|
/** @type {ShapeItem} */ (itemB).definition.getHash()
|
||||||
|
? BOOL_TRUE_SINGLETON
|
||||||
|
: BOOL_FALSE_SINGLETON;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -312,7 +312,6 @@ ingame:
|
|||||||
black: Schwarz
|
black: Schwarz
|
||||||
uncolored: Farblos
|
uncolored: Farblos
|
||||||
|
|
||||||
|
|
||||||
# Everything related to placing buildings (I.e. as soon as you selected a building
|
# Everything related to placing buildings (I.e. as soon as you selected a building
|
||||||
# from the toolbar)
|
# from the toolbar)
|
||||||
buildingPlacement:
|
buildingPlacement:
|
||||||
@ -424,7 +423,6 @@ ingame:
|
|||||||
1_3_expand: >-
|
1_3_expand: >-
|
||||||
Dies ist <strong>KEIN</strong> Idle-Game! Baue mehr Extrahierer und Förderbänder, um das Ziel schneller zu erreichen.<br><br>Tipp: Halte <strong>UMSCH</strong>, um mehrere Gebäude zu platzieren und nutze <strong>R</strong> um sie zu rotieren.
|
Dies ist <strong>KEIN</strong> Idle-Game! Baue mehr Extrahierer und Förderbänder, um das Ziel schneller zu erreichen.<br><br>Tipp: Halte <strong>UMSCH</strong>, um mehrere Gebäude zu platzieren und nutze <strong>R</strong> um sie zu rotieren.
|
||||||
|
|
||||||
|
|
||||||
# All shop upgrades
|
# All shop upgrades
|
||||||
shopUpgrades:
|
shopUpgrades:
|
||||||
belt:
|
belt:
|
||||||
@ -564,7 +562,6 @@ buildings:
|
|||||||
name: Kabelverbinder
|
name: Kabelverbinder
|
||||||
description: Verbindet zwei Energiekabel zu einem.
|
description: Verbindet zwei Energiekabel zu einem.
|
||||||
|
|
||||||
|
|
||||||
storyRewards:
|
storyRewards:
|
||||||
# Those are the rewards gained from completing the store
|
# Those are the rewards gained from completing the store
|
||||||
reward_cutter_and_trash:
|
reward_cutter_and_trash:
|
||||||
@ -837,7 +834,6 @@ keybindings:
|
|||||||
Modifikator: stattdessen gegen den UZS rotieren
|
Modifikator: stattdessen gegen den UZS rotieren
|
||||||
cycleBuildingVariants: Variante wählen
|
cycleBuildingVariants: Variante wählen
|
||||||
confirmMassDelete: Massenlöschung bestätigen
|
confirmMassDelete: Massenlöschung bestätigen
|
||||||
pasteLastBlueprint: Letzte Blaupause einfügen
|
|
||||||
cycleBuildings: Gebäude rotieren
|
cycleBuildings: Gebäude rotieren
|
||||||
lockBeltDirection: Bandplaner aktivieren
|
lockBeltDirection: Bandplaner aktivieren
|
||||||
switchDirectionLockSide: >-
|
switchDirectionLockSide: >-
|
||||||
@ -852,14 +848,6 @@ keybindings:
|
|||||||
placeMultiple: Im Platziermodus bleiben
|
placeMultiple: Im Platziermodus bleiben
|
||||||
placeInverse: Automatische Förderbandorientierung invertieren
|
placeInverse: Automatische Förderbandorientierung invertieren
|
||||||
pasteLastBlueprint: Letzte Blaupause einfügen
|
pasteLastBlueprint: Letzte Blaupause einfügen
|
||||||
massSelectCut: Areal ausschneiden
|
|
||||||
exportScreenshot: Ganze Fabrik als Foto exportieren
|
|
||||||
mapMoveFaster: Schneller bewegen
|
|
||||||
lockBeltDirection: Bandplaner aktivieren
|
|
||||||
switchDirectionLockSide: "Planer: Seite wechseln"
|
|
||||||
pipette: Pipette
|
|
||||||
menuClose: Close Menu
|
|
||||||
switchLayers: Switch layers
|
|
||||||
advanced_processor: Farbinvertierer
|
advanced_processor: Farbinvertierer
|
||||||
energy_generator: Energiegenerator
|
energy_generator: Energiegenerator
|
||||||
wire: Energiekabel
|
wire: Energiekabel
|
||||||
|