From 586cea0529e2303290ba9aec4e2931f2d147ad44 Mon Sep 17 00:00:00 2001 From: CodedSakura Date: Tue, 14 Jul 2026 09:27:22 +0300 Subject: [PATCH] move block-picker into it's own file --- scripts/block-picker.js | 199 ++++++++++++++++++++++++++++++++++++++++ scripts/main.js | 1 + scripts/planner.js | 194 +-------------------------------------- 3 files changed, 205 insertions(+), 189 deletions(-) create mode 100644 scripts/block-picker.js diff --git a/scripts/block-picker.js b/scripts/block-picker.js new file mode 100644 index 0000000..0e75aca --- /dev/null +++ b/scripts/block-picker.js @@ -0,0 +1,199 @@ +import { DomList } from "./dom-list.js"; +import { atlases, makeAtlasImage } from "./atlas.js"; +import { Filter } from "./filter.js"; +import { createTooltip, tooltipDataToPlain } from "./tooltip.js"; +import { emitEvent, listenTo } from "./events.js"; +import { getPlannerMultiblockType } from "./planner.js"; +import { registerLoadCallback } from "./main.js"; +import { lookupFromMetadata, resolveBlockName } from "./ncpf-utils.js"; + +registerLoadCallback(() => { + listenTo("config:end", buildBlockPicker); + listenTo("block-picker:filter:input", buildBlockPicker); +}); + +function buildBlockPicker() { + const filter = Filter.fromInput("block-picker:filter"); + + const grid = new DomList(document.getElementById("block-picker-list")); + grid.clear(); + + atlases.flatMap(a => a.metadata) + .filter(m => m.configuration === getPlannerMultiblockType() && m.configurationList === "blocks") + .forEach(m => { + const item = grid.makeItem(); + item.dataset.index = m.index.toString(10); + const tooltipData = [...getBlockTooltip(m)]; + item.dataset.tooltip = createTooltip(tooltipData).toString(10); + if (!filter.test(...tooltipDataToPlain(tooltipData))) { + item.classList.add("hidden"); + } + item.appendChild(makeAtlasImage(m.index)); + item.addEventListener("click", blockPickerClickEvent); + grid.addItem(item); + }); +} + +function blockPickerClickEvent(e) { + const blockPickerDom = document.getElementById("block-picker-list"); + const items = document.querySelectorAll("#block-picker-list [data-index]"); + if (e.currentTarget.dataset.active !== undefined) { + items.forEach(i => delete i.dataset.active); + blockPickerDom.dataset.activeItem = (-1).toString(10); + delete e.currentTarget.dataset.active; + emitEvent("block-picker:selection", -1); + emitEvent("block-picker:selection:clear"); + return; + } + items.forEach(i => delete i.dataset.active); + blockPickerDom.dataset.activeItem = e.currentTarget.dataset.index; + e.currentTarget.dataset.active = ""; + emitEvent("block-picker:selection", blockPickerDom.dataset.activeItem); +} + +function* getBlockTooltip(metadata) { + const data = lookupFromMetadata(metadata); + + if (!data) { + console.warn("failed to get data from metadata", metadata); + return; + } + + yield data.modules["plannerator:display_name"].display_name; + + let hasAdditionalData = false; + + if ("nuclearcraft:overhaul_sfr:heat_sink" in data.modules) { + hasAdditionalData = true; + const heatSink = data.modules["nuclearcraft:overhaul_sfr:heat_sink"]; + yield "Heatsink"; + if (heatSink.cooling) { + yield `Cooling: ${heatSink.cooling} H/t`; + } + if (heatSink.rules) { + for (const rule of heatSink.rules) { + yield "Requires " + parseRuleAsTooltip(rule, { configurationHint: metadata.configuration }); + } + } + } + + if ("nuclearcraft:overhaul_sfr:casing" in data.modules) { + hasAdditionalData = true; + yield "Casing"; + } + + if ("nuclearcraft:overhaul_sfr:controller" in data.modules) { + hasAdditionalData = true; + yield "Controller"; + } + + if ("nuclearcraft:overhaul_sfr:fuel_cell" in data.modules) { + hasAdditionalData = true; + yield "Fuel Cell"; + } + + if ("nuclearcraft:overhaul_sfr:port" in data.modules) { + hasAdditionalData = true; + if (data.modules["nuclearcraft:overhaul_sfr:port"].output) { + yield "Output Port"; + } else { + yield "Input Port"; + } + } + + if ("nuclearcraft:overhaul_sfr:irradiator" in data.modules) { + hasAdditionalData = true; + yield "Irradiator"; + } + + if ("nuclearcraft:overhaul_sfr:conductor" in data.modules) { + hasAdditionalData = true; + yield "Conductor"; + } + + if ("nuclearcraft:overhaul_sfr:moderator" in data.modules) { + hasAdditionalData = true; + const moderator = data.modules["nuclearcraft:overhaul_sfr:moderator"]; + yield "Moderator"; + yield `Flux: ${moderator.flux}`; + yield `Efficiency: ${moderator.efficiency}`; + } + + if ("nuclearcraft:overhaul_sfr:reflector" in data.modules) { + hasAdditionalData = true; + const reflector = data.modules["nuclearcraft:overhaul_sfr:reflector"]; + yield "Reflector"; + yield `Efficiency: ${reflector.efficiency}`; + yield `Reflectivity: ${reflector.reflectivity}`; + } + + if ("nuclearcraft:overhaul_sfr:neutron_shield" in data.modules) { + hasAdditionalData = true; + const shield = data.modules["nuclearcraft:overhaul_sfr:neutron_shield"]; + yield "Neutron Shield"; + yield `Efficiency: ${shield.efficiency}`; + yield `Heat per Flux: ${shield.heat_per_flux}`; + } + + if (!hasAdditionalData) { + console.log("unknown block", data); + } + + yield { + type: "italics", + text: metadata.configurationAddon.name, + }; +} + +function parseRuleAsTooltip(rule, props) { + switch (rule.type) { + case "and": + return rule.rules.map(r => parseRuleAsTooltip(r, props)).join(" AND "); + + case "or": + return rule.rules.map(r => parseRuleAsTooltip(r, props)).join(" OR "); + + case "between": { + const block = resolveBlockName(rule.block, props); + if (!block) { + console.warn("could not find block %o", rule.block); + return "???"; + } + if (rule.min === rule.max) { + return `exactly ${rule.min} ${block}`; + } else if (rule.max === 6) { + return `at least ${rule.min} ${block}`; + } else if (rule.min === 0) { + return `no more than ${rule.max} ${block}`; + } else { + return `between ${rule.min} and ${rule.max} ${block}`; + } + } + + case "axial": { + const block = resolveBlockName(rule.block, props); + if (!block) { + console.warn("could not find block %o", rule.block); + return "???"; + } + if (rule.min === rule.max) { + return `exactly ${rule.min} axial ${block}`; + } else if (rule.max === 3) { + return `at least ${rule.min} axial ${block}`; + } else if (rule.min === 0) { + return `no more than ${rule.max} axial ${block}`; + } else { + return `between ${rule.min} and ${rule.max} axial ${block}`; + } + } + + default: + console.warn("unknown rule: %o", rule); + return "???"; + } +} + +export function getBlockPickerActiveItem() { + const blockPickerDom = document.getElementById("block-picker-list"); + return Number(blockPickerDom.dataset.activeItem); +} diff --git a/scripts/main.js b/scripts/main.js index c0040b5..34e48d6 100644 --- a/scripts/main.js +++ b/scripts/main.js @@ -1,4 +1,5 @@ import "./atlas.js"; +import "./block-picker.js"; import { loadConfiguration } from "./configuration.js"; import "./dialogs.js"; import "./dom-list.js"; diff --git a/scripts/planner.js b/scripts/planner.js index 894c970..7270aa3 100644 --- a/scripts/planner.js +++ b/scripts/planner.js @@ -1,13 +1,11 @@ -import { atlases, makeAtlasImage } from "./atlas.js"; +import { makeAtlasImage } from "./atlas.js"; import { DomList } from "./dom-list.js"; import { getElements } from "./dom-utils.js"; import { emitEvent, listenTo } from "./events.js"; -import { Filter } from "./filter.js"; import { initialize3dArray } from "./js-utils.js"; import { recall, save } from "./storage.js"; -import { createTooltip, tooltipDataToPlain } from "./tooltip.js"; -import { lookupFromMetadata, resolveBlockName } from "./ncpf-utils.js"; import { registerLoadCallback } from "./main.js"; +import { getBlockPickerActiveItem } from "./block-picker.js"; const zoomOptions = [ 0.5, 1, 2, 3, 4, 5 ]; const zoomDefault = 2; @@ -16,14 +14,10 @@ const zoomStorageKey = "zoom-size"; let suppressHover = false; let multiblockSize = [9, 7, 9]; // width (screen x), height (xy grids), depth (screen y) let multiblockType = "nuclearcraft:overhaul_sfr"; -let activeItem = -1; registerLoadCallback(() => { - listenTo("config:end", buildBlockPicker); listenTo("config:end", buildPlanner); - listenTo("block-picker:filter:input", buildBlockPicker); - listenTo("planner:toggle-casing", e => { const planner = document.getElementById("planner"); planner.dataset.casing = e.detail.state ? "show" : "hide"; @@ -77,6 +71,7 @@ registerLoadCallback(() => { save(zoomStorageKey, scale); }); + listenTo("block-picker:selection", clearSelectedCells); document.addEventListener("keydown", e => { @@ -87,44 +82,6 @@ registerLoadCallback(() => { }); }); -function buildBlockPicker() { - const filter = Filter.fromInput("block-picker:filter"); - - const grid = new DomList(document.getElementById("block-picker-list")); - grid.clear(); - - atlases.flatMap(a => a.metadata) - .filter(m => m.configuration === multiblockType && m.configurationList === "blocks") - .forEach(m => { - const item = grid.makeItem(); - item.dataset.index = m.index.toString(10); - const tooltipData = [...getBlockTooltip(m)]; - item.dataset.tooltip = createTooltip(tooltipData).toString(10); - if (!filter.test(...tooltipDataToPlain(tooltipData))) { - item.classList.add("hidden"); - } - item.appendChild(makeAtlasImage(m.index)); - item.addEventListener("click", blockPickerClickEvent); - grid.addItem(item); - }); -} - -function blockPickerClickEvent(e) { - const items = document.querySelectorAll("#block-picker-list [data-index]"); - if (e.currentTarget.dataset.active !== undefined) { - items.forEach(i => delete i.dataset.active); - activeItem = -1; - delete e.currentTarget.dataset.active; - emitEvent("block-picker:selection", activeItem); - emitEvent("block-picker:selection:clear"); - return; - } - items.forEach(i => delete i.dataset.active); - activeItem = Number(e.currentTarget.dataset.index); - e.currentTarget.dataset.active = ""; - emitEvent("block-picker:selection", activeItem); -} - function buildPlanner(textures) { // handle case when 1st argument is event if (!Array.isArray(textures)) textures = undefined; @@ -176,7 +133,7 @@ function buildPlanner(textures) { function cellHoverEvent(e) { if (suppressHover) return; - if (activeItem === -1) return; + if (getBlockPickerActiveItem() === -1) return; if (document.body.dataset.resizing) return; const cells = document.querySelectorAll("#planner [data-x]"); @@ -219,6 +176,7 @@ function cellClickEvent(e) { return; } + const activeItem = getBlockPickerActiveItem(); if (activeItem === -1) { cellSelectEvent(e); return; @@ -339,145 +297,3 @@ export function getPlannerCellDom(x, y, z) { export const getPlannerMultiblockType = () => multiblockType; export const getPlannerMultiblockSize = () => multiblockSize; - -function* getBlockTooltip(metadata) { - const data = lookupFromMetadata(metadata); - - if (!data) { - console.warn("failed to get data from metadata", metadata); - return; - } - - yield data.modules["plannerator:display_name"].display_name; - - let hasAdditionalData = false; - - if ("nuclearcraft:overhaul_sfr:heat_sink" in data.modules) { - hasAdditionalData = true; - const heatSink = data.modules["nuclearcraft:overhaul_sfr:heat_sink"]; - yield "Heatsink"; - if (heatSink.cooling) { - yield `Cooling: ${heatSink.cooling} H/t`; - } - if (heatSink.rules) { - for (const rule of heatSink.rules) { - yield "Requires " + parseRuleAsTooltip(rule, { configurationHint: metadata.configuration }); - } - } - } - - if ("nuclearcraft:overhaul_sfr:casing" in data.modules) { - hasAdditionalData = true; - yield "Casing"; - } - - if ("nuclearcraft:overhaul_sfr:controller" in data.modules) { - hasAdditionalData = true; - yield "Controller"; - } - - if ("nuclearcraft:overhaul_sfr:fuel_cell" in data.modules) { - hasAdditionalData = true; - yield "Fuel Cell"; - } - - if ("nuclearcraft:overhaul_sfr:port" in data.modules) { - hasAdditionalData = true; - if (data.modules["nuclearcraft:overhaul_sfr:port"].output) { - yield "Output Port"; - } else { - yield "Input Port"; - } - } - - if ("nuclearcraft:overhaul_sfr:irradiator" in data.modules) { - hasAdditionalData = true; - yield "Irradiator"; - } - - if ("nuclearcraft:overhaul_sfr:conductor" in data.modules) { - hasAdditionalData = true; - yield "Conductor"; - } - - if ("nuclearcraft:overhaul_sfr:moderator" in data.modules) { - hasAdditionalData = true; - const moderator = data.modules["nuclearcraft:overhaul_sfr:moderator"]; - yield "Moderator"; - yield `Flux: ${moderator.flux}`; - yield `Efficiency: ${moderator.efficiency}`; - } - - if ("nuclearcraft:overhaul_sfr:reflector" in data.modules) { - hasAdditionalData = true; - const reflector = data.modules["nuclearcraft:overhaul_sfr:reflector"]; - yield "Reflector"; - yield `Efficiency: ${reflector.efficiency}`; - yield `Reflectivity: ${reflector.reflectivity}`; - } - - if ("nuclearcraft:overhaul_sfr:neutron_shield" in data.modules) { - hasAdditionalData = true; - const shield = data.modules["nuclearcraft:overhaul_sfr:neutron_shield"]; - yield "Neutron Shield"; - yield `Efficiency: ${shield.efficiency}`; - yield `Heat per Flux: ${shield.heat_per_flux}`; - } - - if (!hasAdditionalData) { - console.log("unknown block", data); - } - - yield { - type: "italics", - text: metadata.configurationAddon.name, - }; -} - -function parseRuleAsTooltip(rule, props) { - switch (rule.type) { - case "and": - return rule.rules.map(r => parseRuleAsTooltip(r, props)).join(" AND "); - - case "or": - return rule.rules.map(r => parseRuleAsTooltip(r, props)).join(" OR "); - - case "between": { - const block = resolveBlockName(rule.block, props); - if (!block) { - console.warn("could not find block %o", rule.block); - return "???"; - } - if (rule.min === rule.max) { - return `exactly ${rule.min} ${block}`; - } else if (rule.max === 6) { - return `at least ${rule.min} ${block}`; - } else if (rule.min === 0) { - return `no more than ${rule.max} ${block}`; - } else { - return `between ${rule.min} and ${rule.max} ${block}`; - } - } - - case "axial": { - const block = resolveBlockName(rule.block, props); - if (!block) { - console.warn("could not find block %o", rule.block); - return "???"; - } - if (rule.min === rule.max) { - return `exactly ${rule.min} axial ${block}`; - } else if (rule.max === 3) { - return `at least ${rule.min} axial ${block}`; - } else if (rule.min === 0) { - return `no more than ${rule.max} axial ${block}`; - } else { - return `between ${rule.min} and ${rule.max} axial ${block}`; - } - } - - default: - console.warn("unknown rule: %o", rule); - return "???"; - } -}