198 lines
6.3 KiB
JavaScript
198 lines
6.3 KiB
JavaScript
import { awaitEvent, emitEvent, listenTo } from "./events.js";
|
|
import { checkEquivalence, findFullEntry, stripEntryToMinimums } from "./ncpf-utils.js";
|
|
import {
|
|
getPlannerDom,
|
|
getPlannerMultiblockSize,
|
|
getPlannerMultiblockType,
|
|
loadPlanner,
|
|
readPlannerCellData
|
|
} from "./planner.js";
|
|
import { getAtlasIndexFromMetadata, getAtlasMetadata } from "./atlas.js";
|
|
import { getSolverMetadata, resetSolver } from "./solver.js";
|
|
import { registerLoadCallback } from "./main.js";
|
|
|
|
registerLoadCallback(() => {
|
|
listenTo("file:load", () => showOpenFileDialog());
|
|
listenTo("file:new", () => {});
|
|
listenTo("file:save", () => saveFile());
|
|
});
|
|
|
|
export function showOpenFileDialog() {
|
|
const input = document.createElement("input");
|
|
input.type = "file";
|
|
input.accept = ".ncpf.json";
|
|
input.addEventListener("change", async () => {
|
|
const basename = input.files[0].name.split(/[/\\]/).pop();
|
|
const filename = basename.replace(/\.json$/, "").replace(/\.ncpf$/, "");
|
|
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, filename);
|
|
});
|
|
input.click();
|
|
}
|
|
|
|
export async function loadExampleFile(filename) {
|
|
const data = await fetch(`./examples/${filename}.ncpf.json`)
|
|
.then(data => data.json());
|
|
return loadFile(data);
|
|
// return loadFile(data, filename);
|
|
}
|
|
|
|
export async function loadFile(data, name) {
|
|
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, data.configuration[design.type]);
|
|
|
|
if (name) {
|
|
getPlannerDom().dataset.name = name;
|
|
}
|
|
|
|
console.log("load file", data);
|
|
}
|
|
|
|
export async function saveFile(name = undefined) {
|
|
if (!name) {
|
|
name = getPlannerDom().dataset.name;
|
|
}
|
|
|
|
if (!name) {
|
|
emitEvent("fileSave:nameDesign");
|
|
const nameEvent = await awaitEvent("fileSave:nameDesign:named");
|
|
name = nameEvent.detail;
|
|
}
|
|
|
|
if (!name) {
|
|
return;
|
|
}
|
|
|
|
const multiblockType = getPlannerMultiblockType();
|
|
|
|
const designAsCellData = readPlannerCellData();
|
|
const designAsAtlas = designAsCellData
|
|
.map(xPlane => xPlane.map(yRow => yRow.map(c => Number(c.tile))));
|
|
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 minimizedBlocks = Object.entries(designBlocksAtlasMap)
|
|
.sort(([a], [b]) => a - b)
|
|
.map(([, m]) => stripEntryToMinimums(m));
|
|
|
|
const blockRecipes = designAsBlocks
|
|
.map((xPlane, x) => xPlane
|
|
.map((yRow, y) => yRow
|
|
.map((block, z) => {
|
|
if (!block) return;
|
|
const fullBlock = findFullEntry(
|
|
"blocks",
|
|
block,
|
|
{ configurationHint: multiblockType },
|
|
);
|
|
if (!fullBlock || !fullBlock.modules || !("ncpf:block_recipes" in fullBlock.modules)) return;
|
|
|
|
const designIndex = designBlocksAtlasMap[Number(designAsCellData[x][y][z].tile)].designIndex;
|
|
const solverMetadata = getSolverMetadata(designAsCellData[x][y][z].solverMetadata);
|
|
const minimizedBlock = minimizedBlocks[designIndex];
|
|
let recipeIndex = -1;
|
|
|
|
if (multiblockType === "nuclearcraft:overhaul_sfr") {
|
|
if (!minimizedBlock.modules) {
|
|
minimizedBlock.modules = {};
|
|
}
|
|
if (!minimizedBlock.modules["ncpf:block_recipes"]) {
|
|
minimizedBlock.modules["ncpf:block_recipes"] = {
|
|
recipes: [],
|
|
};
|
|
}
|
|
const recipes = minimizedBlock.modules["ncpf:block_recipes"].recipes;
|
|
const recipe = solverMetadata["block_recipe"];
|
|
recipeIndex = recipes.findIndex(r => checkEquivalence(r, recipe));
|
|
if (recipeIndex === -1) {
|
|
recipes.push(stripEntryToMinimums(recipe));
|
|
recipeIndex = recipes.length - 1;
|
|
}
|
|
}
|
|
|
|
return recipeIndex;
|
|
})
|
|
.filter(b => b != null)
|
|
)
|
|
.filter(r => r.length > 0)
|
|
)
|
|
.filter(p => p.length > 0);
|
|
|
|
let fileData = null;
|
|
|
|
if (multiblockType === "nuclearcraft:overhaul_sfr") {
|
|
const coolantRecipes = [];
|
|
let coolantRecipeIndex;
|
|
const plannerMetadata = getSolverMetadata(getPlannerDom());
|
|
|
|
coolantRecipes.push(stripEntryToMinimums(plannerMetadata.coolant_recipe));
|
|
coolantRecipeIndex = 0;
|
|
|
|
fileData = {
|
|
addons: [],
|
|
configuration: {
|
|
[multiblockType]: {
|
|
blocks: minimizedBlocks,
|
|
coolant_recipes: coolantRecipes,
|
|
},
|
|
},
|
|
designs: [
|
|
{
|
|
block_recipes: blockRecipes,
|
|
coolant_recipe: coolantRecipeIndex,
|
|
design: designAsBlockIndices,
|
|
dimensions: getPlannerMultiblockSize(),
|
|
type: multiblockType,
|
|
},
|
|
],
|
|
version: 1,
|
|
};
|
|
}
|
|
|
|
console.log(`save file (${name})`, fileData);
|
|
|
|
if (fileData) {
|
|
const blob = new Blob([ JSON.stringify(fileData) ], {
|
|
type: "application/json",
|
|
});
|
|
const a = document.createElement("a");
|
|
a.href = URL.createObjectURL(blob);
|
|
a.download = `${name}.ncpf.json`;
|
|
a.click();
|
|
}
|
|
}
|