import { registerLoadCallback } from "./main.js"; import { listenTo } from "./events.js"; import { configuration } from "./configuration.js"; import { getPlannerDom, getPlannerMultiblockType, getSelectedCells } from "./planner.js"; import { DomList } from "./dom-list.js"; import { getAtlasIndexFromMetadata, getAtlasMetadata, makeAtlasImage } from "./atlas.js"; import { getSolverMetadata, setSolverMetadata } from "./solver.js"; import { findFullEntry, findFullEntryAnywhere, lookupFromMetadata } from "./ncpf-utils.js"; import { createTooltip, setTooltip, tooltipDataToPlain } from "./tooltip.js"; import { Filter } from "./filter.js"; import { debounce } from "./dom-utils.js"; const defaultRecipes = { ["nuclearcraft:overhaul_sfr"]: { coolant_recipe: { elements: [ { name: "water", type: "legacy_fluid" }, { name: "condensate_water", type: "legacy_fluid" }, ], type: "list", }, }, }; registerLoadCallback(() => { listenTo([ "config:end", "solver:reset:done" ], rescanDesignRecipes); listenTo([ "planner:selection:removed", "planner:selection:added"], rescanSelectionRecipes); }); function rescanDesignRecipes() { console.log("rescan recipes"); console.log(configuration); const multiblockType = getPlannerMultiblockType(); const configs = [ ...Object.entries(configuration.configuration), ...configuration.addons.flatMap(a => Object.entries(a.configuration)), ].filter(([type]) => type === multiblockType); const designRecipes = new DomList( document.getElementById("recipe-selector:design"), document.getElementById("recipe-selector:template"), ); designRecipes.clear(); if (multiblockType === "nuclearcraft:overhaul_sfr") { const coolantRecipes = configs.filter(([, v]) => "coolant_recipes" in v && v.coolant_recipes.length > 0) .flatMap(([, v]) => v.coolant_recipes); const designItem = designRecipes.makeItem(); designItem.querySelectorAll('[data-text="recipe:type"]') .forEach(e => e.innerText = "Coolant Recipe"); const plannerDom = getPlannerDom(); const plannerMetadata = getSolverMetadata(plannerDom); let selectedRecipe = plannerMetadata?.coolant_recipe; if (!plannerMetadata) { selectedRecipe = defaultRecipes["nuclearcraft:overhaul_sfr"].coolant_recipe; setSolverMetadata(plannerDom, { coolant_recipe: selectedRecipe, }); } selectedRecipe = findFullEntry("coolant_recipes", selectedRecipe, { configurationHint: multiblockType }); function updateSelectedRecipe() { const selectedRecipeName = selectedRecipe.modules["plannerator:display_name"].display_name; const selectedAtlasId = getAtlasIndexFromMetadata(selectedRecipe, multiblockType, "coolant_recipes"); const metadata = getAtlasMetadata(selectedAtlasId); designItem.querySelectorAll('[data-text="recipe:selected"]') .forEach(e => e.innerText = selectedRecipeName); designItem.querySelectorAll('[data-atlas="recipe:selected"]') .forEach(e => e.replaceChildren(makeAtlasImage(selectedAtlasId))); designItem.querySelectorAll('.recipe--selected') .forEach(e => setTooltip(e, [...getRecipeTooltip(selectedRecipe, metadata)])); } updateSelectedRecipe(); function handleDismiss() { console.log("dismiss"); designItem.classList.remove("selecting"); window.removeEventListener("click", handleDismiss); } designItem.addEventListener("click", e => e.stopPropagation()); const filterElem = designItem.querySelector('[data-input="recipe:filter"]'); function updateRecipeList() { const filter = Filter.fromInput(filterElem); const recipeList = new DomList(designItem.querySelector(":scope > .select")); recipeList.clear(); for (let i = 0; i < coolantRecipes.length; i++) { const recipe = coolantRecipes[i]; const recipeItem = recipeList.makeItem(); const recipeName = recipe.modules["plannerator:display_name"].display_name; const atlasId = getAtlasIndexFromMetadata(recipe, multiblockType, "coolant_recipes"); const metadata = getAtlasMetadata(atlasId); recipeItem.querySelectorAll('[data-text="recipe:item"]') .forEach(e => e.innerText = recipeName); recipeItem.querySelectorAll('[data-atlas="recipe:item"]') .forEach(e => e.replaceChildren(makeAtlasImage(atlasId))); recipeItem.addEventListener("click", () => { handleDismiss(); selectedRecipe = recipe; updateSelectedRecipe(); setSolverMetadata(plannerDom, { coolant_recipe: selectedRecipe, }); }); const tooltipData = [...getRecipeTooltip(recipe, metadata)]; setTooltip(recipeItem, tooltipData); if (!filter.test(recipeName, ...tooltipDataToPlain(tooltipData))) { recipeItem.classList.add("hidden"); } recipeList.addItem(recipeItem); } } updateRecipeList(); filterElem.addEventListener("input", debounce(updateRecipeList)); designItem.querySelectorAll(':scope > .recipe--selected').forEach(e => { e.addEventListener("click", () => { designItem.classList.add("selecting"); designItem.querySelector('[autofocus]').focus(); window.addEventListener("click", handleDismiss); }); }); designRecipes.addItem(designItem); } } function rescanSelectionRecipes() { const selectedCells = getSelectedCells(); const selectedTiles = new Set(selectedCells.map(v => Number(v.dataset.tile))); const designRecipes = new DomList( document.getElementById("recipe-selector:selection"), document.getElementById("recipe-selector:template"), ); designRecipes.clear(); if (selectedTiles.size !== 1 || selectedTiles.has(-1)) { return; } const multiblockType = getPlannerMultiblockType(); const tileMetadata = getAtlasMetadata(selectedCells[0].dataset.tile); const tile = findFullEntry("blocks", tileMetadata, { configurationHint: multiblockType }); if (!tile.modules || !tile.modules["ncpf:block_recipes"]) { return; } console.log(tile); } function* getRecipeTooltip(recipe, metadata) { const multiblockType = getPlannerMultiblockType(); let hasAdditionalData = false; if ("nuclearcraft:overhaul_sfr:coolant_recipe_stats" in recipe.modules) { hasAdditionalData = true; const stats = recipe.modules["nuclearcraft:overhaul_sfr:coolant_recipe_stats"]; const { entry: output, type } = findFullEntryAnywhere(stats.output, { configurationHint: multiblockType }); const outputName = output.modules["plannerator:display_name"].display_name; const atlasId = getAtlasIndexFromMetadata(output, multiblockType, type); yield `Heat: ${stats.heat}`; yield `Output:` yield `Ratio ${stats.output_ratio}`; yield { type: "item", atlasIndex: atlasId, name: outputName, }; } if (!hasAdditionalData) { console.log("unknown recipe", recipe, metadata); } yield { type: "italics", text: metadata.configurationAddon.name, }; }