diff --git a/res_raw/sounds/sfx/copy.wav b/res_raw/sounds/sfx/copy.wav new file mode 100644 index 00000000..c595b90a Binary files /dev/null and b/res_raw/sounds/sfx/copy.wav differ diff --git a/src/js/game/base_item.js b/src/js/game/base_item.js index 7271c75f..0075e6c1 100644 --- a/src/js/game/base_item.js +++ b/src/js/game/base_item.js @@ -28,6 +28,15 @@ export class BaseItem extends BasicSerializableObject { return "shape"; } + /** + * Returns a string id of the item + * @returns {string} + */ + getAsCopyableKey() { + abstract; + return ""; + } + /** * Returns if the item equals the other itme * @param {BaseItem} other diff --git a/src/js/game/blueprint.js b/src/js/game/blueprint.js index a37ea20d..c26fb12f 100644 --- a/src/js/game/blueprint.js +++ b/src/js/game/blueprint.js @@ -1,12 +1,11 @@ +import { globalConfig } from "../core/config"; import { DrawParameters } from "../core/draw_parameters"; -import { Loader } from "../core/loader"; import { createLogger } from "../core/logging"; +import { findNiceIntegerValue } from "../core/utils"; import { Vector } from "../core/vector"; import { Entity } from "./entity"; import { GameRoot } from "./root"; -import { findNiceIntegerValue } from "../core/utils"; import { blueprintShape } from "./upgrades"; -import { globalConfig } from "../core/config"; const logger = createLogger("blueprint"); diff --git a/src/js/game/hud/parts/wires_overlay.js b/src/js/game/hud/parts/wires_overlay.js index 7d856d5f..4d382d2b 100644 --- a/src/js/game/hud/parts/wires_overlay.js +++ b/src/js/game/hud/parts/wires_overlay.js @@ -1,13 +1,14 @@ import { makeOffscreenBuffer } from "../../../core/buffer_utils"; import { globalConfig } from "../../../core/config"; import { DrawParameters } from "../../../core/draw_parameters"; -import { KEYMAPPINGS } from "../../key_action_mapper"; -import { THEME } from "../../theme"; -import { BaseHUDPart } from "../base_hud_part"; import { Loader } from "../../../core/loader"; import { lerp } from "../../../core/utils"; +import { SOUNDS } from "../../../platform/sound"; +import { KEYMAPPINGS } from "../../key_action_mapper"; import { enumHubGoalRewards } from "../../tutorial_goals"; +import { BaseHUDPart } from "../base_hud_part"; +const copy = require("clipboard-copy"); const wiresBackgroundDpi = 4; export class HUDWiresOverlay extends BaseHUDPart { @@ -16,6 +17,7 @@ export class HUDWiresOverlay extends BaseHUDPart { initialize() { // Probably not the best location, but the one which makes most sense this.root.keyMapper.getBinding(KEYMAPPINGS.ingame.switchLayers).add(this.switchLayers, this); + this.root.keyMapper.getBinding(KEYMAPPINGS.placement.copyWireValue).add(this.copyWireValue, this); this.generateTilePattern(); @@ -57,6 +59,46 @@ export class HUDWiresOverlay extends BaseHUDPart { this.currentAlpha = lerp(this.currentAlpha, desiredAlpha, 0.12); } + /** + * Copies the wires value below the cursor + */ + copyWireValue() { + if (this.root.currentLayer !== "wires") { + return; + } + + const mousePos = this.root.app.mousePosition; + if (!mousePos) { + return; + } + + const tile = this.root.camera.screenToWorld(mousePos).toTileSpace(); + const contents = this.root.map.getLayerContentXY(tile.x, tile.y, "wires"); + if (!contents) { + return; + } + + let value = null; + if (contents.components.Wire) { + const network = contents.components.Wire.linkedNetwork; + if (network && network.hasValue()) { + value = network.currentValue; + } + } + + if (contents.components.ConstantSignal) { + value = contents.components.ConstantSignal.signal; + } + + if (value) { + copy(value.getAsCopyableKey()); + this.root.soundProxy.playUi(SOUNDS.copy); + } else { + copy(""); + this.root.soundProxy.playUiError(); + } + } + /** * * @param {DrawParameters} parameters diff --git a/src/js/game/items/boolean_item.js b/src/js/game/items/boolean_item.js index 4ccd1241..9ee3e3e5 100644 --- a/src/js/game/items/boolean_item.js +++ b/src/js/game/items/boolean_item.js @@ -26,6 +26,13 @@ export class BooleanItem extends BaseItem { return "boolean"; } + /** + * @returns {string} + */ + getAsCopyableKey() { + return this.value ? "1" : "0"; + } + /** * @param {number} value */ diff --git a/src/js/game/items/color_item.js b/src/js/game/items/color_item.js index ab53bbef..fb7f1701 100644 --- a/src/js/game/items/color_item.js +++ b/src/js/game/items/color_item.js @@ -28,6 +28,13 @@ export class ColorItem extends BaseItem { return "color"; } + /** + * @returns {string} + */ + getAsCopyableKey() { + return this.color; + } + /** * @param {BaseItem} other */ diff --git a/src/js/game/items/shape_item.js b/src/js/game/items/shape_item.js index 9dbd225a..d61b8f2e 100644 --- a/src/js/game/items/shape_item.js +++ b/src/js/game/items/shape_item.js @@ -27,6 +27,13 @@ export class ShapeItem extends BaseItem { return "shape"; } + /** + * @returns {string} + */ + getAsCopyableKey() { + return this.definition.getHash(); + } + /** * @param {BaseItem} other */ diff --git a/src/js/game/key_action_mapper.js b/src/js/game/key_action_mapper.js index dbd0642f..e3779be1 100644 --- a/src/js/game/key_action_mapper.js +++ b/src/js/game/key_action_mapper.js @@ -82,6 +82,8 @@ export const KEYMAPPINGS = { cycleBuildingVariants: { keyCode: key("T") }, cycleBuildings: { keyCode: 9 }, // TAB switchDirectionLockSide: { keyCode: key("R") }, + + copyWireValue: { keyCode: key("Z") }, }, massSelect: { diff --git a/src/js/platform/sound.js b/src/js/platform/sound.js index 0678abcf..1fceaf3e 100644 --- a/src/js/platform/sound.js +++ b/src/js/platform/sound.js @@ -25,6 +25,7 @@ export const SOUNDS = { destroyBuilding: "destroy_building", placeBuilding: "place_building", placeBelt: "place_belt", + copy: "copy", }; export const MUSIC = { diff --git a/translations/base-en.yaml b/translations/base-en.yaml index 90a7f59c..2acaa510 100644 --- a/translations/base-en.yaml +++ b/translations/base-en.yaml @@ -1070,7 +1070,8 @@ keybindings: lockBeltDirection: Enable belt planner switchDirectionLockSide: >- Planner: Switch side - + copyWireValue: >- + Wires: Copy value below cursor massSelectStart: Hold and drag to start massSelectSelectMultiple: Select multiple areas massSelectCopy: Copy area