Compare commits

...

2 Commits

Author SHA1 Message Date
CodedSakura 4fb19ada79 fix issue with stale metadata throwing errors 2026-08-11 15:38:36 +03:00
CodedSakura bf66f5ea31 fix moderator line validation 2026-08-11 15:27:18 +03:00
9 changed files with 84 additions and 41 deletions

View File

@ -1,5 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="GitSharedSettings">
<option name="FORCE_PUSH_PROHIBITED_PATTERNS">
<list />
</option>
<option name="synchronizeBranchProtectionRules" value="false" />
</component>
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
</component>

View File

@ -0,0 +1 @@
{"addons":[],"configuration":{"nuclearcraft:overhaul_sfr":{"blocks":[{"name":"nuclearcraft:solid_fission_controller","type":"legacy_block"},{"name":"nuclearcraft:fission_vent","type":"legacy_block","blockstate":{"active":false}},{"name":"nuclearcraft:fission_vent","type":"legacy_block","blockstate":{"active":true}},{"name":"nuclearcraft:fission_casing","type":"legacy_block"},{"name":"nuclearcraft:fission_glass","type":"legacy_block"},{"metadata":2,"name":"nuclearcraft:fission_source","type":"legacy_block","blockstate":{"type":"californium"}},{"name":"nuclearcraft:solid_fission_cell","type":"legacy_block","modules":{"ncpf:block_recipes":{"recipes":[{"oredict":"ingotHEU233ZA","type":"oredict"}]}}},{"name":"nuclearcraft:fission_cell_port","type":"legacy_block","blockstate":{"active":false},"modules":{"ncpf:block_recipes":{"recipes":[{"oredict":"ingotHEU233ZA","type":"oredict"}]}}},{"name":"nuclearcraft:fission_cell_port","type":"legacy_block","blockstate":{"active":true},"modules":{"ncpf:block_recipes":{"recipes":[{"oredict":"ingotHEU233ZA","type":"oredict"}]}}},{"name":"nuclearcraft:heavy_water_moderator","type":"legacy_block"},{"metadata":0,"name":"nuclearcraft:fission_shield","type":"legacy_block","blockstate":{"active":false,"type":"boron_silver"}},{"metadata":0,"name":"nuclearcraft:fission_shield","type":"legacy_block","blockstate":{"active":true,"type":"boron_silver"}}],"coolant_recipes":[{"elements":[{"name":"water","type":"legacy_fluid"},{"name":"condensate_water","type":"legacy_fluid"}],"type":"list"}]}},"designs":[{"design":[[[3,3,3,3,3,3,3,3,3],[3,0,1,2,7,8,4,4,3],[3,4,4,4,4,4,4,4,3],[3,4,4,4,4,4,4,4,3],[3,4,4,4,4,4,4,4,3],[3,4,4,4,4,4,4,4,3],[3,3,3,3,3,3,3,3,3]],[[3,5,4,4,4,4,4,4,3],[4,6,-1,-1,-1,6,-1,-1,4],[4,-1,-1,-1,-1,-1,-1,-1,4],[4,-1,-1,-1,-1,-1,-1,-1,4],[4,-1,-1,-1,-1,-1,-1,-1,4],[4,-1,-1,-1,-1,-1,-1,-1,4],[3,4,4,4,4,4,4,4,3]],[[3,4,4,4,4,4,4,4,3],[4,9,-1,-1,-1,9,-1,-1,4],[4,-1,-1,-1,-1,-1,-1,-1,4],[4,-1,-1,-1,-1,-1,-1,-1,4],[4,-1,-1,-1,-1,-1,-1,-1,4],[4,-1,-1,-1,-1,-1,-1,-1,4],[3,4,4,4,4,4,4,4,3]],[[3,4,4,4,4,4,4,4,3],[4,10,-1,-1,-1,10,-1,-1,4],[4,-1,-1,-1,-1,-1,-1,-1,4],[4,-1,-1,-1,-1,-1,-1,-1,4],[4,-1,-1,-1,-1,-1,-1,-1,4],[4,-1,-1,-1,-1,-1,-1,-1,4],[3,4,4,4,4,4,4,4,3]],[[3,4,4,4,4,4,4,4,3],[4,9,-1,-1,-1,9,-1,-1,4],[4,-1,-1,-1,-1,-1,-1,-1,4],[4,-1,-1,-1,-1,-1,-1,-1,4],[4,-1,-1,-1,-1,-1,-1,-1,4],[4,-1,-1,-1,-1,-1,-1,-1,4],[3,4,4,4,4,4,4,4,3]],[[3,4,4,4,4,4,4,4,3],[4,6,9,11,9,6,-1,-1,4],[4,-1,-1,-1,-1,-1,-1,-1,4],[4,-1,-1,-1,-1,-1,-1,-1,4],[4,-1,-1,-1,-1,-1,-1,-1,4],[4,-1,-1,-1,-1,-1,-1,-1,4],[3,4,4,4,4,4,4,4,3]],[[3,4,4,4,4,4,4,4,3],[4,-1,-1,-1,-1,-1,-1,-1,4],[4,-1,-1,-1,-1,-1,-1,-1,4],[4,-1,-1,-1,-1,-1,-1,-1,4],[4,-1,-1,-1,-1,-1,-1,-1,4],[4,-1,-1,-1,-1,-1,-1,-1,4],[3,4,4,4,4,4,4,4,3]],[[3,4,4,4,4,4,4,4,3],[4,-1,-1,-1,-1,-1,-1,-1,4],[4,-1,-1,-1,-1,-1,-1,-1,4],[4,-1,-1,-1,-1,-1,-1,-1,4],[4,-1,-1,-1,-1,-1,-1,-1,4],[4,-1,-1,-1,-1,-1,-1,-1,4],[3,4,4,4,4,4,4,4,3]],[[3,3,3,3,3,3,3,3,3],[3,4,4,4,4,4,4,4,3],[3,4,4,4,4,4,4,4,3],[3,4,4,4,4,4,4,4,3],[3,4,4,4,4,4,4,4,3],[3,4,4,4,4,4,4,4,3],[3,3,3,3,3,3,3,3,3]]],"block_recipes":[[[0,0]],[[0,0]],[[0,0]]],"type":"nuclearcraft:overhaul_sfr","coolant_recipe":0,"dimensions":[9,7,9]}],"version":1}

View File

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

View File

@ -39,7 +39,7 @@ registerLoadCallback(() => {
});
awaitEvent("config:end").then(() => {
void loadExampleFile("Pandora's Fission Reactor");
void loadExampleFile("shield test");
});
queueMicrotask(() => emitEvent("dev-mode:end"));

View File

@ -18,6 +18,8 @@ export function setDomMetadata(domNode, data) {
export function setCellMetadata(node, key, value) {
if (!node.dataset.metadata) {
node.dataset.metadata = createMetadata({ [key]: value }).toString(10);
} else if (!metadata[Number(node.dataset.metadata)]) {
metadata[Number(node.dataset.metadata)] = { [key]: value };
} else {
metadata[Number(node.dataset.metadata)][key] = value;
}
@ -38,6 +40,7 @@ export function getMetadata(id) {
return metadata[id];
}
export function getCellMetadata(node, key) {
if (!node.dataset.metadata) return null;
return metadata[Number(node.dataset.metadata)][key];
}
@ -53,6 +56,7 @@ export function deleteMetadata(id) {
}
export function clearCellMetadata(node, key) {
if (!node.dataset.metadata) return;
if (!metadata[Number(node.dataset.metadata)]) return;
delete metadata[Number(node.dataset.metadata)][key];
processCellOverlays(node, key, false);
}

View File

@ -3,6 +3,8 @@ import { getAtlasIndexFromMetadata, makeAtlasImage } from "./atlas.js";
export function processCellOverlays(node, key = null, added = null) {
if (key) {
node.replaceChildren(...node.querySelectorAll(`:scope > *:not([data-overlay="${key}"])`));
const metadata = getCellMetadata(node, key);
const atlasIndex = getAtlasIndexFromMetadata(metadata);
if (atlasIndex && atlasIndex !== -1) {
@ -12,15 +14,10 @@ export function processCellOverlays(node, key = null, added = null) {
node.appendChild(overlayNode);
}
if (key === "active" && metadata) {
if (key === "active" && added) {
const overlayNode = makeAtlasImage(-1);
overlayNode.dataset.overlay = key;
overlayNode.classList.add("planner--overlay");
node.appendChild(overlayNode);
}
if (key === "active" && !metadata) {
const overlayNode = makeAtlasImage(-1);
overlayNode.dataset.overlay = "inactive";
overlayNode.dataset.active = metadata ? "true" : "false";
overlayNode.classList.add("planner--overlay");
node.appendChild(overlayNode);
}

View File

@ -6,7 +6,7 @@ import { initialize3dArray } from "./js-utils.js";
import { recall, save } from "./storage.js";
import { registerLoadCallback } from "./main.js";
import { getBlockPickerActiveItem, getBlockPickerRecipe } from "./block-picker.js";
import { clearCellMetadata, getMetadata, setCellMetadata } from "./metadata.js";
import { clearCellMetadata, deleteMetadata, getMetadata, setCellMetadata } from "./metadata.js";
import { retainTooltipHover } from "./tooltip.js";
import { checkEquivalence, lookupFromMetadata, parseRuleAsString } from "./ncpf-utils.js";
@ -250,13 +250,14 @@ function cellClickEvent(e) {
if (e.target.tile === "-1") return;
e.target.dataset.previewRemove = "yes";
clearCellMetadata(e.target, "block_recipe");
deleteMetadata(e.target);
} else if (e.buttons === 1) {
// add
if (e.target.dataset.preview === activeItem.toString(10)) return;
e.target.dataset.preview = activeItem.toString(10);
e.target.replaceChildren(makeAtlasImage(activeItem));
deleteMetadata(e.target);
const pickerRecipe = getBlockPickerRecipe();
if (pickerRecipe) {
setCellMetadata(e.target, "block_recipe", pickerRecipe);

View File

@ -7,11 +7,14 @@ import {
getPlannerMultiblockType
} from "./planner.js";
import { checkEquivalence, findFullEntry, findFullEntryFromAtlasMetadata } from "./ncpf-utils.js";
import { deleteMetadata, getMetadata, setCellMetadata, setDomMetadata } from "./metadata.js";
import { clearCellMetadata, deleteMetadata, getMetadata, setCellMetadata, setDomMetadata } from "./metadata.js";
import { registerLoadCallback } from "./main.js";
import { getAtlasMetadata } from "./atlas.js";
import { initialize3dArray } from "./js-utils.js";
const SFR_MODERATOR_MAX_LEN = 3;
const SFR_MODERATOR_REFLECTOR_MAX_LEN = 2;
registerLoadCallback(() => {
listenTo("fileLoad:end", runSolver);
listenTo("planner:cell:change", runSolver);
@ -95,7 +98,8 @@ async function debugBlockSolver(data) {
}
export async function runSolver() {
emitEvent("solver:begin")
const startTime = performance.now()
emitEvent("solver:begin");
const multiblockType = getPlannerMultiblockType();
@ -107,6 +111,7 @@ export async function runSolver() {
.map(idx => [idx, getAtlasMetadata(idx)])
.map(([idx, md]) => [idx, findFullEntry("blocks", md, { configurationHint: multiblockType })]));
plannerBlocks.forEach(v => v.tile = tileMap[v.tile]);
plannerBlocks.forEach(v => clearCellMetadata(v.dom, "active"));
const plannerBlocksGrid = initialize3dArray(...getPlannerMultiblockSize());
plannerBlocks.forEach(b => {
@ -158,6 +163,7 @@ export async function runSolver() {
}
setCellMetadata(cell.dom, "primer", cell.primer);
});
console.log(fuelCells)
await debugBlockSolver("primed");
@ -167,46 +173,70 @@ export async function runSolver() {
while (activeCellIndex < activeCells.length) {
const cell = activeCells[activeCellIndex];
if (!cell.axes) return; // ignore bad cells
Object.keys(sixAxes).map((name, i) => {
let moderatorSum = 0;
Object.keys(sixAxes).map((directionName, i) => {
let valid = false;
let moderatorPath = [];
let length = 0;
let reflectMultiplier = 1;
let reflect = false;
let fluxDestination;
for (const block of cell.axes[i]) {
if (!block) break;
if (block.tile.modules["nuclearcraft:overhaul_sfr:moderator"]) {
moderatorSum += block.tile.modules["nuclearcraft:overhaul_sfr:moderator"].flux;
moderatorPath.push(block);
seenModerators.add(block);
if (!block.flux) {
block.flux = {};
}
block.flux[name] = moderatorSum;
length += 1;
continue;
}
if (block.tile.modules["nuclearcraft:overhaul_sfr:neutron_shield"]) {
length += 1;
continue;
}
if (block.tile.modules["nuclearcraft:overhaul_sfr:fuel_cell"] || block.tile.modules["nuclearcraft:overhaul_sfr:irradiator"]) {
block.flux = (block.flux ?? 0) + moderatorSum;
valid = length <= SFR_MODERATOR_MAX_LEN;
fluxDestination = block;
}
if (block.tile.modules["nuclearcraft:overhaul_sfr:reflector"]) {
const backAxis = name.replace(/^[+-]/, s => s === "+" ? "-" : "+");
for (const blockBack of moderatorPath.toReversed()) {
moderatorSum += blockBack.tile.modules["nuclearcraft:overhaul_sfr:moderator"].flux;
moderatorPath.push(blockBack);
blockBack.flux[backAxis] = moderatorSum;
}
cell.flux = (cell.flux ?? 0) + moderatorSum;
}
if (block.tile.modules["nuclearcraft:overhaul_sfr:fuel_cell"] && !block.active) {
if (!block.recipe) break; // FIXME
const fuelStats = block.recipe.modules["nuclearcraft:overhaul_sfr:fuel_stats"];
if (fuelStats.criticality <= block.flux) {
block.active = true;
activeCells.push(block);
}
valid = length <= SFR_MODERATOR_REFLECTOR_MAX_LEN;
reflect = true;
reflectMultiplier = block.tile.modules["nuclearcraft:overhaul_sfr:reflector"].reflectivity;
console.log(reflectMultiplier)
fluxDestination = cell;
}
break;
}
if (moderatorPath.length > 0) {
moderatorPath[0].active = true;
if (moderatorPath.length < 1) {
valid = false;
}
if (!valid) return;
moderatorPath[0].active = true;
let totalFlux = 0;
for (const mod of moderatorPath) {
totalFlux += mod.tile.modules["nuclearcraft:overhaul_sfr:moderator"].flux;
if (!mod.flux) {
mod.flux = {};
}
mod.flux[directionName] = totalFlux;
}
if (reflect) {
totalFlux *= reflectMultiplier;
const backAxis = directionName.replace(/^[+-]/, s => s === "+" ? "-" : "+");
for (const mod of moderatorPath.toReversed()) {
totalFlux += mod.tile.modules["nuclearcraft:overhaul_sfr:moderator"].flux * reflectMultiplier;
mod.flux[backAxis] = totalFlux;
}
}
fluxDestination.flux = (fluxDestination.flux ?? 0) + totalFlux;
if (fluxDestination.tile.modules["nuclearcraft:overhaul_sfr:fuel_cell"] && !fluxDestination.active) {
if (!fluxDestination.recipe) return; // FIXME
const fuelStats = fluxDestination.recipe.modules["nuclearcraft:overhaul_sfr:fuel_stats"];
if (fuelStats.criticality <= fluxDestination.flux) {
fluxDestination.active = true;
activeCells.push(fluxDestination);
}
}
});
@ -249,7 +279,8 @@ export async function runSolver() {
if (n.tile.modules) {
return n.tile.modules["nuclearcraft:overhaul_sfr:reflector"]
|| n.tile.modules["nuclearcraft:overhaul_sfr:irradiator"]
|| n.tile.modules["nuclearcraft:overhaul_sfr:casing"];
|| n.tile.modules["nuclearcraft:overhaul_sfr:casing"]
|| n.tile.modules["nuclearcraft:overhaul_sfr:neutron_shield"];
}
return false;
});
@ -277,6 +308,9 @@ export async function runSolver() {
await debugBlockSolver("heatsinks");
}
const endTime = performance.now()
console.log(`Solver took ${endTime - startTime}ms`);
}
function checkHeatSinkRule(hs, rule, activeNeighbors) {

View File

@ -271,11 +271,11 @@ input:not([type="checkbox"]):not([type="radio"]):not([type="file"]) {
.planner--cell > .planner--overlay[data-overlay="block_recipe"] {
transform: scale(var(--recipe-scale-factor, 0.8));
}
#planner .planner--cell > .planner--overlay[data-overlay="active"] {
#planner .planner--cell > .planner--overlay[data-overlay="active"][data-active="true"] {
outline-offset: calc(var(--scale-factor) * -1px);
outline: calc(var(--scale-factor) * 1px) solid var(--cell-active-outline, #0f08);
}
#planner .planner--cell > .planner--overlay[data-overlay="inactive"] {
#planner .planner--cell > .planner--overlay[data-overlay="active"][data-active="false"] {
outline-offset: calc(var(--scale-factor) * -1px);
outline: calc(var(--scale-factor) * 1px) solid var(--cell-inactive-outline, #f008);
}