begin implementing planner

This commit is contained in:
CodedSakura 2026-07-31 19:27:30 +03:00
parent 88e1b6e7b7
commit 617db13cb4
5 changed files with 117 additions and 26 deletions

View File

@ -126,7 +126,7 @@
</section> </section>
</aside> </aside>
<footer> <footer>
<div>pre-alpha 1.6</div> <div>alpha 1.7</div>
<div> <div>
<a href="https://discord.gg/Eq72HwPqfg">Discord server</a> <a href="https://discord.gg/Eq72HwPqfg">Discord server</a>
</div> </div>

View File

@ -9,17 +9,17 @@ function createMetadata(data) {
return id; return id;
} }
export function setDomMetadata(domNode, data) { export function setDomMetadata(domNode, data) {
if (domNode.dataset.solverMetadata) { if (domNode.dataset.metadata) {
metadata[Number(domNode.dataset.solverMetadata)] = data; metadata[Number(domNode.dataset.metadata)] = data;
return; return;
} }
domNode.dataset.solverMetadata = createMetadata(data).toString(10); domNode.dataset.metadata = createMetadata(data).toString(10);
} }
export function setCellMetadata(node, key, value) { export function setCellMetadata(node, key, value) {
if (!node.dataset.solverMetadata) { if (!node.dataset.metadata) {
node.dataset.solverMetadata = createMetadata({ [key]: value }).toString(10); node.dataset.metadata = createMetadata({ [key]: value }).toString(10);
} else { } else {
metadata[Number(node.dataset.solverMetadata)][key] = value; metadata[Number(node.dataset.metadata)][key] = value;
} }
processCellOverlays(node, key, true); processCellOverlays(node, key, true);
} }
@ -27,8 +27,8 @@ export function setCellMetadata(node, key, value) {
export function getMetadata(id) { export function getMetadata(id) {
if (typeof id === "object") { if (typeof id === "object") {
// assume DOM element // assume DOM element
if (id.dataset && id.dataset.solverMetadata) { if (id.dataset && id.dataset.metadata) {
return getMetadata(id.dataset.solverMetadata); return getMetadata(id.dataset.metadata);
} }
return null; return null;
} }
@ -38,21 +38,21 @@ export function getMetadata(id) {
return metadata[id]; return metadata[id];
} }
export function getCellMetadata(node, key) { export function getCellMetadata(node, key) {
return metadata[Number(node.dataset.solverMetadata)][key]; return metadata[Number(node.dataset.metadata)][key];
} }
export function deleteMetadata(id) { export function deleteMetadata(id) {
if (typeof id === "object") { if (typeof id === "object") {
// assume DOM object // assume DOM object
if (id.dataset && id.dataset.solverMetadata) { if (id.dataset && id.dataset.metadata) {
clearCellOverlays(id); clearCellOverlays(id);
return deleteMetadata(id.dataset.solverMetadata); return deleteMetadata(id.dataset.metadata);
} }
} }
delete metadata[id]; delete metadata[id];
} }
export function clearCellMetadata(node, key) { export function clearCellMetadata(node, key) {
if (!node.dataset.solverMetadata) return; if (!node.dataset.metadata) return;
delete metadata[Number(node.dataset.solverMetadata)][key]; delete metadata[Number(node.dataset.metadata)][key];
processCellOverlays(node, key, false); processCellOverlays(node, key, false);
} }

View File

@ -324,7 +324,7 @@ export function getPlannerDom() {
return document.getElementById("planner"); return document.getElementById("planner");
} }
export function getPlannerCellsDom() { export function getPlannerCellsDom() {
return document.querySelectorAll("#planner [data-tile]"); return [...document.querySelectorAll("#planner [data-tile]")];
} }
export function getPlannerCellDom(x, y, z) { export function getPlannerCellDom(x, y, z) {
return document.querySelector(`#planner [data-x="${x}"][data-y="${y}"][data-z="${z}"]`); return document.querySelector(`#planner [data-x="${x}"][data-y="${y}"][data-z="${z}"]`);

View File

@ -88,7 +88,6 @@ function initializeRecipePicker({
const filter = Filter.fromInput(filterElem); const filter = Filter.fromInput(filterElem);
const recipeList = new DomList(parent.querySelector(":scope > .select")); const recipeList = new DomList(parent.querySelector(":scope > .select"));
recipeList.clear(); recipeList.clear();
console.log(recipes);
for (let i = 0; i < recipes.length; i++) { for (let i = 0; i < recipes.length; i++) {
const recipe = recipes[i]; const recipe = recipes[i];
const recipeItem = recipeList.makeItem(); const recipeItem = recipeList.makeItem();
@ -131,9 +130,6 @@ function initializeRecipePicker({
} }
function rescanDesignRecipes() { function rescanDesignRecipes() {
console.log("rescan recipes");
console.log(configuration);
const multiblockType = getPlannerMultiblockType(); const multiblockType = getPlannerMultiblockType();
const configs = [ const configs = [
@ -198,8 +194,6 @@ function rescanSelectionRecipes() {
const tileMetadata = getAtlasMetadata(selectedCells.length > 0 ? selectedCells[0].dataset.tile : pickerTile); const tileMetadata = getAtlasMetadata(selectedCells.length > 0 ? selectedCells[0].dataset.tile : pickerTile);
const tiles = findFullEntryFromAtlasMetadata(tileMetadata, { all: true }); const tiles = findFullEntryFromAtlasMetadata(tileMetadata, { all: true });
console.log(tiles);
if (!tiles[0] || !tiles[0].modules || !tiles[0].modules["ncpf:block_recipes"]) { if (!tiles[0] || !tiles[0].modules || !tiles[0].modules["ncpf:block_recipes"]) {
return; return;
} }
@ -207,7 +201,6 @@ function rescanSelectionRecipes() {
const cellRecipes = selectedCells.map(v => getMetadata(v)?.block_recipe); const cellRecipes = selectedCells.map(v => getMetadata(v)?.block_recipe);
const recipeSet = cellRecipes.some(v => v); const recipeSet = cellRecipes.some(v => v);
const recipeAllSame = cellRecipes.every(v => v === cellRecipes[0] || checkEquivalence(v, cellRecipes[0])); const recipeAllSame = cellRecipes.every(v => v === cellRecipes[0] || checkEquivalence(v, cellRecipes[0]));
console.log(">", cellRecipes, recipeSet, recipeAllSame);
const recipes = tiles.flatMap(t => t.modules["ncpf:block_recipes"].recipes); const recipes = tiles.flatMap(t => t.modules["ncpf:block_recipes"].recipes);

View File

@ -1,7 +1,21 @@
import { emitEvent } from "./events.js"; import { emitEvent, listenTo } from "./events.js";
import { getPlannerCellDom, getPlannerDom } from "./planner.js"; import {
import { findFullEntry } from "./ncpf-utils.js"; getPlannerCellDom,
import { setCellMetadata, setDomMetadata } from "./metadata.js"; 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) { export function resetSolver(design = undefined, designConfiguration) {
const planner = getPlannerDom(); const planner = getPlannerDom();
@ -34,3 +48,87 @@ export function resetSolver(design = undefined, designConfiguration) {
emitEvent("solver:reset:done"); 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);
}
}