import { emitEvent, listenTo } from "./events.js"; import { getPlannerCellDom, getPlannerCellsDom, getPlannerDom, getPlannerMultiblockSize, getPlannerMultiblockType } from "./planner.js"; import { checkEquivalence, findFullEntry, findFullEntryFromAtlasMetadata } from "./ncpf-utils.js"; import { getMetadata, setCellMetadata, setDomMetadata } from "./metadata.js"; import { registerLoadCallback } from "./main.js"; import { getAtlasMetadata } from "./atlas.js"; import { initialize3dArray } from "./js-utils.js"; registerLoadCallback(() => { listenTo("fileLoad:end", runSolver); listenTo("planner:cell:change", runSolver); }); export function resetSolver(design = undefined, designConfiguration) { const planner = getPlannerDom(); if (design && designConfiguration) { planner.dataset.type = design.type; if (design.type === "nuclearcraft:overhaul_sfr") { // design has coolant_recipe and block_recipes const designCoolantRecipe = designConfiguration.coolant_recipes[design.coolant_recipe]; const fullCoolantRecipe = findFullEntry( "coolant_recipes", designCoolantRecipe, { configurationHint: design.type }, ); setDomMetadata(planner, { coolant_recipe: fullCoolantRecipe }); const designBlockRecipes = design.block_recipes.flat(3); for (let x = 0; x < design.dimensions[0]; x++) { for (let y = 0; y < design.dimensions[1]; y++) { for (let z = 0; z < design.dimensions[2]; z++) { const block = designConfiguration.blocks[design.design[x][y][z]]; if (!block || !block.modules || !block.modules["ncpf:block_recipes"]) continue; const blockRecipeIndex = designBlockRecipes.shift(); const blockRecipe = block.modules["ncpf:block_recipes"].recipes[blockRecipeIndex]; setCellMetadata(getPlannerCellDom(x, y, z), "block_recipe", blockRecipe); } } } } } emitEvent("solver:reset:done"); } const sixAxes = [ {x: -1, y: 0, z: 0}, {x: 0, y: -1, z: 0}, {x: 0, y: 0, z: -1}, {x: 1, y: 0, z: 0}, {x: 0, y: 1, z: 0}, {x: 0, y: 0, z: 1}, ] function *travelUntil(grid, { x, y, z }, {x: dirX = 0, y: dirY = 0, z: dirZ = 0}, shouldStop = (pos) => false) { x = Number(x); y = Number(y); z = Number(z); while (!shouldStop({x, y, z}) && x > 0 && y > 0 && z > 0 && x < grid.length - 1 && y < grid[0].length - 1 && z < grid[0][0].length - 1) { x += dirX; y += dirY; z += dirZ; yield grid[x][y][z]; } } export function runSolver() { emitEvent("solver:begin") const multiblockType = getPlannerMultiblockType(); const plannerBlocks = getPlannerCellsDom() .map(b => ({ dom: b, ...b.dataset })) .filter(b => b.tile !== "-1") .map(b => (b.metadata ? { ...b, metadata: getMetadata(b.metadata) } : b)); const tileMap = Object.fromEntries([...new Set(plannerBlocks.map(b => b.tile))] .map(idx => [idx, getAtlasMetadata(idx)]) .map(([idx, md]) => [idx, findFullEntry("blocks", md, { configurationHint: multiblockType })])); plannerBlocks.forEach(v => v.tile = tileMap[v.tile]); const plannerBlocksGrid = initialize3dArray(...getPlannerMultiblockSize()); plannerBlocks.forEach(b => { plannerBlocksGrid[b.x][b.y][b.z] = b; }); if (multiblockType === "nuclearcraft:overhaul_sfr") { const fuelCells = plannerBlocks.filter(b => b.tile.modules && b.tile.modules["nuclearcraft:overhaul_sfr:fuel_cell"]); // const neutronSources = plannerBlocks.filter(b => b.tile.modules && b.tile.modules["nuclearcraft:overhaul_sfr:neutron_source"]); // const reflectors = plannerBlocks.filter(b => b.tile.modules && b.tile.modules["nuclearcraft:overhaul_sfr:reflector"]); // const shields = plannerBlocks.filter(b => b.tile.modules && b.tile.modules["nuclearcraft:overhaul_sfr:neutron_shield"]); // const moderators = plannerBlocks.filter(b => b.tile.modules && b.tile.modules["nuclearcraft:overhaul_sfr:moderator"]); // const coolers = plannerBlocks.filter(b => b.tile.modules && b.tile.modules["nuclearcraft:overhaul_sfr:heat_sink"]); // const irradiators = plannerBlocks.filter(b => b.tile.modules && b.tile.modules["nuclearcraft:overhaul_sfr:irradiator"]); // const conductors = plannerBlocks.filter(b => b.tile.modules && b.tile.modules["nuclearcraft:overhaul_sfr:conductor"]); fuelCells.forEach(cell => { const recipeList = cell.tile.modules["ncpf:block_recipes"].recipes; cell.recipe = recipeList.find(r => checkEquivalence(r, cell.metadata.block_recipe)); cell.axes = sixAxes.map(dir => [...travelUntil( plannerBlocksGrid, cell, dir, ({x, y, z}) => { const block = plannerBlocksGrid[x][y][z]; if (block === cell) { return false; } if (!block) { return false; } if (block.tile.modules) { if (block.tile.modules["nuclearcraft:overhaul_sfr:fuel_cell"]) return true; if (block.tile.modules["nuclearcraft:overhaul_sfr:reflector"]) return true; } return false; } )]); if (cell.recipe.modules["nuclearcraft:overhaul_sfr:fuel_stats"].self_priming) { cell.primer = cell; } else if (cell.axes.some(a => (a[a.length - 1]?.tile?.modules ?? {})["nuclearcraft:overhaul_sfr:neutron_source"])) { const primerAxis = cell.axes.find(a => (a[a.length - 1]?.tile?.modules ?? {})["nuclearcraft:overhaul_sfr:neutron_source"]); cell.primer = primerAxis[primerAxis.length - 1]; } }); console.log(fuelCells); } }