import { awaitEvent, emitEvent, listenTo } from "./events.js"; import { findFullEntry, stripEntryToMinimums } from "./ncpf-utils.js"; import { getPlannerMultiblockSize, getPlannerMultiblockType, loadPlanner, readPlannerTiles } from "./planner.js"; import { getAtlasIndexFromMetadata, getAtlasMetadata } from "./atlas.js"; import { resetSolver } from "./solver.js"; export function initializeFileEvents() { listenTo("file:load", () => showOpenFileDialog()); listenTo("file:new", () => {}); listenTo("file:save", () => saveFile("test")); } export function showOpenFileDialog() { const input = document.createElement("input"); input.type = "file"; input.accept = ".ncpf.json"; input.addEventListener("change", async () => { const data = await new Promise(resolve => { const reader = new FileReader(); reader.addEventListener("load", () => { resolve(JSON.parse(reader.result)); }); reader.readAsText(input.files[0]); }); void loadFile(data); }); input.click(); } export async function loadExampleFile(filename) { const data = await fetch(`./examples/${filename}.ncpf.json`) .then(data => data.json()); return loadFile(data); } export async function loadFile(data) { console.log(data); if (!data.designs) throw new Error("invalid file"); if (data.designs.length === 0) throw new Error("no designs"); let design = data.designs[0]; if (data.designs.length > 1) { const prepChoice = awaitEvent("fileLoad:chooseDesign:choice"); emitEvent("fileLoad:chooseDesign", data); const res = await prepChoice; design = data.designs[res.detail]; } if (!design) throw new Error("no design"); const blocks = data.configuration[design.type].blocks .map(block => getAtlasIndexFromMetadata(block, design.type, "blocks")); const designWithAtlas = design.design.map(a => a.map(b => b.map(c => c === -1 ? -1 : blocks[c]))); loadPlanner(design.dimensions, design.type, designWithAtlas); resetSolver(design); } export async function saveFile(name) { const multiblockType = getPlannerMultiblockType(); const designAsAtlas = readPlannerTiles(); const designBlocksAtlasMap = Object.fromEntries( [...new Set(designAsAtlas.flat(3))] .filter(v => v !== -1) .sort((a, b) => a - b) .map((ai, di) => [ ai, { ...getAtlasMetadata(ai), designIndex: di } ]) ); const designAsBlocks = designAsAtlas .map(xPlane => xPlane .map(yRow => yRow.map(atlasIndex => designBlocksAtlasMap[atlasIndex])) ); const designAsBlockIndices = designAsBlocks .map(xPlane => xPlane.map(yRow => yRow.map(b => b?.designIndex ?? -1))); const designBlocksWithRecipes = designAsBlocks .map(xPlane => xPlane .map(yRow => yRow .map(block => { if (!block) return; return findFullEntry("blocks", block, { configurationHint: multiblockType }); }) .filter(b => b && b.modules && "ncpf:block_recipes" in b.modules) ) .filter(r => r.length > 0) ) .filter(p => p.length > 0); console.log("designBlocksWithRecipes", designBlocksWithRecipes) const minimizedBlocks = Object.entries(designBlocksAtlasMap) .sort(([a], [b]) => a - b) .map(([, m]) => stripEntryToMinimums(m)); const data = { addons: [], configurations: { [multiblockType]: { blocks: minimizedBlocks, coolant_recipes: [], // FIXME }, }, designs: [ { block_recipes: [], // FIXME coolant_recipe: 0, // FIXME design: designAsBlockIndices, dimensions: getPlannerMultiblockSize(), type: multiblockType, }, ], version: 1, }; console.log(designBlocksAtlasMap); console.log(data); }