204 lines
6.3 KiB
JavaScript
204 lines
6.3 KiB
JavaScript
import { configuration } from "./configuration.js";
|
|
import { objectKeepKeys } from "./js-utils.js";
|
|
import { DevError } from "./errors.js";
|
|
|
|
export function checkEquivalence(a, b) {
|
|
if (!a || !b || !a.type || !b.type || a.type !== b.type) return false;
|
|
switch (a.type) {
|
|
case "legacy_block":
|
|
return a.name === b.name
|
|
&& a.metadata === b.metadata
|
|
&& (a.blockstate === undefined && b.blockstate === undefined
|
|
|| JSON.stringify(a.blockstate) === JSON.stringify(b.blockstate));
|
|
|
|
case "legacy_fluid":
|
|
return a.name === b.name;
|
|
|
|
case "legacy_item":
|
|
return a.name === b.name
|
|
&& a.metadata === b.metadata;
|
|
|
|
case "oredict":
|
|
return a.oredict === b.oredict;
|
|
|
|
case "list":
|
|
return a.elements.length === b.elements.length &&
|
|
a.elements.every((aE, i) => checkEquivalence(aE, b.elements[i]));
|
|
|
|
default:
|
|
console.warn("unknown type", a.type, a, b);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
export function stripEntryToMinimums(entry) {
|
|
if (!entry.type) throw new DevError("must have a type");
|
|
switch (entry.type) {
|
|
case "legacy_block":
|
|
return objectKeepKeys(entry, "type", "name", "metadata", "blockstate");
|
|
|
|
case "legacy_fluid":
|
|
return objectKeepKeys(entry, "type", "name");
|
|
|
|
case "oredict":
|
|
return objectKeepKeys(entry, "type", "oredict");
|
|
|
|
case "list":
|
|
return {
|
|
type: entry.type,
|
|
elements: entry.elements.map(stripEntryToMinimums),
|
|
};
|
|
}
|
|
throw new DevError(`unknown entry type ${entry.type}`);
|
|
}
|
|
|
|
export function findFullEntry(type, entry, { configurationHint, all = false } = {}) {
|
|
const possibleEntries = [
|
|
...Object.entries(configuration.configuration),
|
|
...configuration.addons.flatMap(a => Object.entries(a.configuration)),
|
|
]
|
|
.filter(([k, v]) => (!configurationHint || k === configurationHint) && type in v)
|
|
.flatMap(([, v]) => v[type]);
|
|
if (all) {
|
|
return possibleEntries.filter(other => checkEquivalence(entry, other));
|
|
}
|
|
return possibleEntries.find(other => checkEquivalence(entry, other));
|
|
}
|
|
|
|
export function findFullEntryFromAtlasMetadata(metadata, options = {}) {
|
|
return findFullEntry(
|
|
metadata.configurationList,
|
|
metadata,
|
|
{
|
|
configurationHint: metadata.configuration,
|
|
...options,
|
|
},
|
|
);
|
|
}
|
|
|
|
export function findFullEntryAnywhere(entry, { configurationHint } = {}) {
|
|
const possibleEntries = [
|
|
...Object.entries(configuration.configuration),
|
|
...configuration.addons.flatMap(a => Object.entries(a.configuration)),
|
|
]
|
|
.filter(([k]) => (!configurationHint || k === configurationHint))
|
|
.flatMap(([, v]) => Object.entries(v)
|
|
.flatMap(([k, v]) => k === "modules" ? [
|
|
...("plannerator:global_elements" in v
|
|
? [["plannerator:global_elements", v["plannerator:global_elements"].elements]]
|
|
: []),
|
|
] : [[k, v]]))
|
|
.flatMap(([t, v]) => v.map(e => [t, e]));
|
|
const findResult = possibleEntries.find(([, other]) => checkEquivalence(entry, other));
|
|
if (!findResult) {
|
|
console.log("did not find", entry, "in", possibleEntries);
|
|
return null;
|
|
}
|
|
const [ type, foundEntry ] = findResult;
|
|
return { type, entry: foundEntry };
|
|
}
|
|
|
|
export function resolveBlockName(block, { configurationHint }) {
|
|
|
|
if (block.type === "module") {
|
|
switch (block.name) {
|
|
case "nuclearcraft:overhaul_sfr:fuel_cell":
|
|
return "Fuel Cell";
|
|
|
|
case "nuclearcraft:overhaul_sfr:moderator":
|
|
return "Moderator";
|
|
|
|
case "nuclearcraft:overhaul_sfr:casing":
|
|
return "Casing";
|
|
|
|
case "nuclearcraft:overhaul_sfr:reflector":
|
|
return "Reflector";
|
|
|
|
case "nuclearcraft:overhaul_sfr:neutron_shield":
|
|
return "Neutron Shield";
|
|
|
|
case "nuclearcraft:overhaul_sfr:irradiator":
|
|
return "Irradiator";
|
|
|
|
default:
|
|
console.warn("unknown module", block);
|
|
return null;
|
|
}
|
|
}
|
|
|
|
const possibleBlocks = [
|
|
...Object.entries(configuration.configuration),
|
|
...configuration.addons.flatMap(a => Object.entries(a.configuration)),
|
|
]
|
|
.filter(([k, v]) => (!configurationHint || k === configurationHint) && "blocks" in v)
|
|
.flatMap(([, v]) => v.blocks);
|
|
|
|
const entry = possibleBlocks.find(other => checkEquivalence(block, other));
|
|
if (!entry) return null;
|
|
|
|
return entry.modules["plannerator:display_name"].display_name;
|
|
}
|
|
|
|
export function lookupFromMetadata(metadata) {
|
|
if (!metadata.configuration || !metadata.configurationList || !metadata.type)
|
|
return null;
|
|
|
|
const possibleEntries = [
|
|
...Object.entries(configuration.configuration),
|
|
...configuration.addons.flatMap(a => Object.entries(a.configuration)),
|
|
]
|
|
.filter(([k, v]) => k === metadata.configuration && metadata.configurationList in v)
|
|
.flatMap(([, v]) => v[metadata.configurationList])
|
|
.filter(v => v.type === metadata.type);
|
|
|
|
return possibleEntries.find(other => checkEquivalence(metadata, other));
|
|
}
|
|
|
|
export function parseRuleAsString(rule, props = { configurationHint: null }) {
|
|
switch (rule.type) {
|
|
case "and":
|
|
return rule.rules.map(r => parseRuleAsString(r, props)).join(" AND ");
|
|
|
|
case "or":
|
|
return rule.rules.map(r => parseRuleAsString(r, props)).join(" OR ");
|
|
|
|
case "between": {
|
|
const block = resolveBlockName(rule.block, props);
|
|
if (!block) {
|
|
console.warn("could not find block %o", rule.block);
|
|
return "???";
|
|
}
|
|
if (rule.min === rule.max) {
|
|
return `exactly ${rule.min} ${block}`;
|
|
} else if (rule.max === 6) {
|
|
return `at least ${rule.min} ${block}`;
|
|
} else if (rule.min === 0) {
|
|
return `no more than ${rule.max} ${block}`;
|
|
} else {
|
|
return `between ${rule.min} and ${rule.max} ${block}`;
|
|
}
|
|
}
|
|
|
|
case "axial": {
|
|
const block = resolveBlockName(rule.block, props);
|
|
if (!block) {
|
|
console.warn("could not find block %o", rule.block);
|
|
return "???";
|
|
}
|
|
if (rule.min === rule.max) {
|
|
return `exactly ${rule.min} axial ${block}`;
|
|
} else if (rule.max === 3) {
|
|
return `at least ${rule.min} axial ${block}`;
|
|
} else if (rule.min === 0) {
|
|
return `no more than ${rule.max} axial ${block}`;
|
|
} else {
|
|
return `between ${rule.min} and ${rule.max} axial ${block}`;
|
|
}
|
|
}
|
|
|
|
default:
|
|
console.warn("unknown rule: %o", rule);
|
|
return "???";
|
|
}
|
|
}
|