minerender 2.1.0-alpha.92 → 2.1.0-alpha.93
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/browser/index.d.mts +11 -6
- package/dist/browser/index.d.ts +11 -6
- package/dist/browser/index.js +234 -190
- package/dist/browser/index.js.map +1 -1
- package/dist/browser/index.mjs +234 -190
- package/dist/browser/index.mjs.map +1 -1
- package/dist/bundle.js +246 -197
- package/dist/bundle.js.map +1 -1
- package/dist/node/index.d.mts +11 -6
- package/dist/node/index.d.ts +11 -6
- package/dist/node/index.js +235 -190
- package/dist/node/index.js.map +1 -1
- package/dist/node/index.mjs +234 -190
- package/dist/node/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/browser/index.js
CHANGED
|
@@ -18872,6 +18872,7 @@ __export(index_browser_exports, {
|
|
|
18872
18872
|
prefix: () => prefix,
|
|
18873
18873
|
probeImageSize: () => probeImageSize,
|
|
18874
18874
|
registerBrowserEnv: () => registerBrowserEnv,
|
|
18875
|
+
resolveLegacyBlock: () => resolveLegacyBlock,
|
|
18875
18876
|
sampleEntityAnimation: () => sampleEntityAnimation,
|
|
18876
18877
|
sampleEntityKeyframes: () => sampleEntityKeyframes,
|
|
18877
18878
|
sampleFluid: () => sampleFluid,
|
|
@@ -23900,158 +23901,6 @@ function isBlockObject(obj) {
|
|
|
23900
23901
|
init_FluidGeometry();
|
|
23901
23902
|
init_FluidModelObject();
|
|
23902
23903
|
|
|
23903
|
-
// src/model/multiblock/LitematicaParser.ts
|
|
23904
|
-
init_MineRenderError();
|
|
23905
|
-
var LitematicaParser = class {
|
|
23906
|
-
/**
|
|
23907
|
-
* Parses decoded NBT, preserving subregion placement and omitting air.
|
|
23908
|
-
* Later entries in regions replace earlier cells, including with air.
|
|
23909
|
-
* Size encloses all region bounds; positions retain the schematic origin.
|
|
23910
|
-
* Metadata and scheduled ticks are not imported. Named regions can be placed individually.
|
|
23911
|
-
*/
|
|
23912
|
-
static async parse(nbt) {
|
|
23913
|
-
const tags = nbt.value;
|
|
23914
|
-
const version2 = integer2(tags.Version, "Version");
|
|
23915
|
-
if (version2 < 5 || version2 > 7) throw new MineRenderError(`Unsupported Litematica version ${version2}; expected 5, 6, or 7`);
|
|
23916
|
-
const dataVersion = tags.MinecraftDataVersion === void 0 ? void 0 : integer2(tags.MinecraftDataVersion, "MinecraftDataVersion");
|
|
23917
|
-
const blocks = /* @__PURE__ */ new Map();
|
|
23918
|
-
const regions = [];
|
|
23919
|
-
const min = [Infinity, Infinity, Infinity];
|
|
23920
|
-
const max = [-Infinity, -Infinity, -Infinity];
|
|
23921
|
-
for (const [name, tag] of Object.entries(compound(tags.Regions, "Regions"))) {
|
|
23922
|
-
const region = readRegion(compound(tag, `region ${name}`), name, dataVersion, blocks);
|
|
23923
|
-
regions.push(region);
|
|
23924
|
-
for (let axis = 0; axis < 3; axis++) {
|
|
23925
|
-
const start = minimum(region.position[axis], region.signedSize[axis]);
|
|
23926
|
-
min[axis] = Math.min(min[axis], start);
|
|
23927
|
-
max[axis] = Math.max(max[axis], start + region.size[axis]);
|
|
23928
|
-
}
|
|
23929
|
-
}
|
|
23930
|
-
return {
|
|
23931
|
-
size: regions.length ? min.map((value, axis) => max[axis] - value) : [0, 0, 0],
|
|
23932
|
-
blocks: [...blocks.values()],
|
|
23933
|
-
entities: regions.flatMap((region) => region.entities ?? []),
|
|
23934
|
-
dataVersion,
|
|
23935
|
-
regions
|
|
23936
|
-
};
|
|
23937
|
-
}
|
|
23938
|
-
};
|
|
23939
|
-
function readRegion(tags, name, dataVersion, combined) {
|
|
23940
|
-
const position = blockPosition(compound(tags.Position, `region ${name} Position`));
|
|
23941
|
-
const signedSize = blockPosition(compound(tags.Size, `region ${name} Size`));
|
|
23942
|
-
if (signedSize.some((value) => value === 0)) throw new MineRenderError(`Litematica region ${name} dimensions must be nonzero`);
|
|
23943
|
-
const size = signedSize.map(Math.abs);
|
|
23944
|
-
const min = position.map((value, axis) => minimum(value, signedSize[axis]));
|
|
23945
|
-
const [width, height, length] = size;
|
|
23946
|
-
const volume = width * height * length;
|
|
23947
|
-
const palette = compounds(tags.BlockStatePalette, "BlockStatePalette").map(blockState);
|
|
23948
|
-
if (!palette.length) throw new MineRenderError(`Litematica region ${name} has no block palette`);
|
|
23949
|
-
const bits = Math.max(2, Math.ceil(Math.log2(palette.length)));
|
|
23950
|
-
if (!Number.isSafeInteger(volume * bits)) throw new MineRenderError(`Litematica region ${name} volume is too large`);
|
|
23951
|
-
const packed = tags.BlockStates;
|
|
23952
|
-
const expected = Math.ceil(volume * bits / 64);
|
|
23953
|
-
if (packed?.type !== "longArray" || !Array.isArray(packed.value) || packed.value.length !== expected) {
|
|
23954
|
-
throw new MineRenderError(`Litematica region ${name} BlockStates must contain ${expected} longs`);
|
|
23955
|
-
}
|
|
23956
|
-
const words = packed.value.map((pair) => {
|
|
23957
|
-
if (!Array.isArray(pair) || pair.length !== 2 || !pair.every((value) => Number.isInteger(value) && value >= -2147483648 && value <= 4294967295)) {
|
|
23958
|
-
throw new MineRenderError(`Litematica region ${name} has an invalid BlockStates long`);
|
|
23959
|
-
}
|
|
23960
|
-
return [pair[0] >>> 0, pair[1] >>> 0];
|
|
23961
|
-
});
|
|
23962
|
-
const blockEntities = /* @__PURE__ */ new Map();
|
|
23963
|
-
for (const tile of compounds(tags.TileEntities, "TileEntities")) {
|
|
23964
|
-
const pos = blockPosition(tile);
|
|
23965
|
-
if (pos.some((value2, axis) => value2 < 0 || value2 >= size[axis])) {
|
|
23966
|
-
throw new MineRenderError(`Litematica region ${name} block entity is outside its dimensions`);
|
|
23967
|
-
}
|
|
23968
|
-
const index = pos[0] + pos[2] * width + pos[1] * width * length;
|
|
23969
|
-
if (blockEntities.has(index)) throw new MineRenderError(`Duplicate Litematica block entity at index ${index}`);
|
|
23970
|
-
const value = { ...tile };
|
|
23971
|
-
for (const [axis, key] of ["x", "y", "z"].entries()) value[key] = { type: "int", value: pos[axis] + min[axis] };
|
|
23972
|
-
blockEntities.set(index, { type: "compound", value });
|
|
23973
|
-
}
|
|
23974
|
-
const blocks = [];
|
|
23975
|
-
const mask = 2 ** bits - 1;
|
|
23976
|
-
for (let index = 0; index < volume; index++) {
|
|
23977
|
-
const word = Math.floor(index * bits / 64);
|
|
23978
|
-
const shift = index * bits % 64;
|
|
23979
|
-
const [high, low] = words[word];
|
|
23980
|
-
let value = shift < 32 ? low >>> shift : high >>> shift - 32;
|
|
23981
|
-
if (shift < 32 && shift + bits > 32) value |= high << 32 - shift;
|
|
23982
|
-
if (shift + bits > 64) value |= words[word + 1][1] << 64 - shift;
|
|
23983
|
-
const id = (value & mask) >>> 0;
|
|
23984
|
-
const state = palette[id];
|
|
23985
|
-
if (!state) throw new MineRenderError(`Litematica region ${name} palette index ${id} does not exist`);
|
|
23986
|
-
const pos = [
|
|
23987
|
-
index % width + min[0],
|
|
23988
|
-
Math.floor(index / (width * length)) + min[1],
|
|
23989
|
-
Math.floor(index / width) % length + min[2]
|
|
23990
|
-
];
|
|
23991
|
-
const key = pos.join(",");
|
|
23992
|
-
if (["minecraft:air", "minecraft:cave_air", "minecraft:void_air"].includes(state.type)) {
|
|
23993
|
-
combined.delete(key);
|
|
23994
|
-
continue;
|
|
23995
|
-
}
|
|
23996
|
-
const block = { type: state.type, properties: { ...state.properties }, position: pos, nbt: blockEntities.get(index) };
|
|
23997
|
-
blocks.push(block);
|
|
23998
|
-
combined.set(key, block);
|
|
23999
|
-
}
|
|
24000
|
-
const entities = compounds(tags.Entities, "Entities").map((entity) => {
|
|
24001
|
-
const pos = entity.Pos;
|
|
24002
|
-
if (pos?.type !== "list" || pos.value.type !== "double" || pos.value.value.length !== 3 || !pos.value.value.every(Number.isFinite)) {
|
|
24003
|
-
throw new MineRenderError(`Litematica region ${name} entity Pos must contain three doubles`);
|
|
24004
|
-
}
|
|
24005
|
-
const absolute = pos.value.value.map((value2, axis) => value2 + position[axis]);
|
|
24006
|
-
const value = { ...entity, Pos: { type: "list", value: { type: "double", value: [...absolute] } } };
|
|
24007
|
-
return { position: absolute, nbt: { type: "compound", value } };
|
|
24008
|
-
});
|
|
24009
|
-
return { name, position, signedSize, size, blocks, entities, dataVersion };
|
|
24010
|
-
}
|
|
24011
|
-
function minimum(position, size) {
|
|
24012
|
-
return position + Math.min(0, size + 1);
|
|
24013
|
-
}
|
|
24014
|
-
function integer2(tag, name) {
|
|
24015
|
-
if (tag?.type !== "int" || !Number.isInteger(tag.value) || tag.value < -2147483648 || tag.value > 2147483647) {
|
|
24016
|
-
throw new MineRenderError(`Litematica ${name} must be an int`);
|
|
24017
|
-
}
|
|
24018
|
-
return tag.value;
|
|
24019
|
-
}
|
|
24020
|
-
function compound(tag, name) {
|
|
24021
|
-
if (tag?.type !== "compound" || !tag.value || typeof tag.value !== "object" || Array.isArray(tag.value)) {
|
|
24022
|
-
throw new MineRenderError(`Litematica ${name} must be a compound`);
|
|
24023
|
-
}
|
|
24024
|
-
return tag.value;
|
|
24025
|
-
}
|
|
24026
|
-
function blockPosition(tags) {
|
|
24027
|
-
return ["x", "y", "z"].map((axis) => integer2(tags[axis], axis));
|
|
24028
|
-
}
|
|
24029
|
-
function compounds(tag, name) {
|
|
24030
|
-
if (tag === void 0) return [];
|
|
24031
|
-
if (tag.type === "list" && Array.isArray(tag.value.value)) {
|
|
24032
|
-
if (tag.value.value.length === 0) return [];
|
|
24033
|
-
if (tag.value.type === "compound") return tag.value.value;
|
|
24034
|
-
}
|
|
24035
|
-
throw new MineRenderError(`Litematica ${name} must be a compound list`);
|
|
24036
|
-
}
|
|
24037
|
-
function blockState(tags) {
|
|
24038
|
-
const name = tags.Name;
|
|
24039
|
-
if (name?.type !== "string" || !/^(?:[a-z0-9_.-]+:)?[a-z0-9_./-]+$/.test(name.value)) {
|
|
24040
|
-
throw new MineRenderError("Litematica palette entry must have a block Name");
|
|
24041
|
-
}
|
|
24042
|
-
const properties = {};
|
|
24043
|
-
if (tags.Properties !== void 0) {
|
|
24044
|
-
for (const [key, tag] of Object.entries(compound(tags.Properties, "block Properties"))) {
|
|
24045
|
-
if (tag?.type !== "string") throw new MineRenderError("Litematica block properties must be strings");
|
|
24046
|
-
Object.defineProperty(properties, key, { value: tag.value, enumerable: true, writable: true, configurable: true });
|
|
24047
|
-
}
|
|
24048
|
-
}
|
|
24049
|
-
return { type: name.value.includes(":") ? name.value : `minecraft:${name.value}`, properties };
|
|
24050
|
-
}
|
|
24051
|
-
|
|
24052
|
-
// src/model/multiblock/SchematicParser.ts
|
|
24053
|
-
init_MineRenderError();
|
|
24054
|
-
|
|
24055
23904
|
// src/model/multiblock/legacyBlocks.json
|
|
24056
23905
|
var legacyBlocks_default = {
|
|
24057
23906
|
__comment: "Block mappings from res/idsToNames.json (WorldEdit legacy.json); block names and cauldrons updated for Minecraft 1.21.11. Source: https://github.com/sk89q/WorldEdit/blob/master/worldedit-core/src/main/resources/com/sk89q/worldedit/world/registry/legacy.json",
|
|
@@ -24895,12 +24744,20 @@ var legacyBlocks_default = {
|
|
|
24895
24744
|
"131:15": "minecraft:tripwire_hook[powered=true,attached=true,facing=east]",
|
|
24896
24745
|
"132:0": "minecraft:tripwire[disarmed=false,east=false,powered=false,south=false,north=false,west=false,attached=false]",
|
|
24897
24746
|
"132:1": "minecraft:tripwire[disarmed=false,east=false,powered=true,south=false,north=false,west=false,attached=false]",
|
|
24747
|
+
"132:2": "minecraft:tripwire[disarmed=false,east=false,powered=false,south=false,north=false,west=false,attached=false]",
|
|
24748
|
+
"132:3": "minecraft:tripwire[disarmed=false,east=false,powered=true,south=false,north=false,west=false,attached=false]",
|
|
24898
24749
|
"132:4": "minecraft:tripwire[disarmed=false,east=false,powered=false,south=false,north=false,west=false,attached=true]",
|
|
24899
24750
|
"132:5": "minecraft:tripwire[disarmed=false,east=false,powered=true,south=false,north=false,west=false,attached=true]",
|
|
24751
|
+
"132:6": "minecraft:tripwire[disarmed=false,east=false,powered=false,south=false,north=false,west=false,attached=true]",
|
|
24752
|
+
"132:7": "minecraft:tripwire[disarmed=false,east=false,powered=true,south=false,north=false,west=false,attached=true]",
|
|
24900
24753
|
"132:8": "minecraft:tripwire[disarmed=true,east=false,powered=false,south=false,north=false,west=false,attached=false]",
|
|
24901
24754
|
"132:9": "minecraft:tripwire[disarmed=true,east=false,powered=true,south=false,north=false,west=false,attached=false]",
|
|
24755
|
+
"132:10": "minecraft:tripwire[disarmed=true,east=false,powered=false,south=false,north=false,west=false,attached=false]",
|
|
24756
|
+
"132:11": "minecraft:tripwire[disarmed=true,east=false,powered=true,south=false,north=false,west=false,attached=false]",
|
|
24902
24757
|
"132:12": "minecraft:tripwire[disarmed=true,east=false,powered=false,south=false,north=false,west=false,attached=true]",
|
|
24903
24758
|
"132:13": "minecraft:tripwire[disarmed=true,east=false,powered=true,south=false,north=false,west=false,attached=true]",
|
|
24759
|
+
"132:14": "minecraft:tripwire[disarmed=true,east=false,powered=false,south=false,north=false,west=false,attached=true]",
|
|
24760
|
+
"132:15": "minecraft:tripwire[disarmed=true,east=false,powered=true,south=false,north=false,west=false,attached=true]",
|
|
24904
24761
|
"133:0": "minecraft:emerald_block",
|
|
24905
24762
|
"134:0": "minecraft:spruce_stairs[half=bottom,shape=outer_right,facing=east]",
|
|
24906
24763
|
"134:1": "minecraft:spruce_stairs[half=bottom,shape=outer_right,facing=west]",
|
|
@@ -25741,7 +25598,175 @@ var legacyBlocks_default = {
|
|
|
25741
25598
|
}
|
|
25742
25599
|
};
|
|
25743
25600
|
|
|
25601
|
+
// src/model/multiblock/LegacyBlocks.ts
|
|
25602
|
+
function resolveLegacyBlock(id, metadata, customMappings = {}, lenient = false) {
|
|
25603
|
+
const mapping = legacyBlocks_default.blocks;
|
|
25604
|
+
const key = `${id}:${metadata}`;
|
|
25605
|
+
let mapped = customMappings[key] ?? mapping[key];
|
|
25606
|
+
if (!mapped && lenient) mapped = customMappings[`${id}:0`] ?? mapping[`${id}:0`];
|
|
25607
|
+
if (!mapped) return void 0;
|
|
25608
|
+
const [type, state] = mapped.split("[");
|
|
25609
|
+
const properties = {};
|
|
25610
|
+
if (state) {
|
|
25611
|
+
for (const property of state.slice(0, -1).split(",")) {
|
|
25612
|
+
const [key2, value] = property.split("=");
|
|
25613
|
+
properties[key2] = value;
|
|
25614
|
+
}
|
|
25615
|
+
}
|
|
25616
|
+
return { type, properties };
|
|
25617
|
+
}
|
|
25618
|
+
|
|
25619
|
+
// src/model/multiblock/LitematicaParser.ts
|
|
25620
|
+
init_MineRenderError();
|
|
25621
|
+
var LitematicaParser = class {
|
|
25622
|
+
/**
|
|
25623
|
+
* Parses decoded NBT, preserving subregion placement and omitting air.
|
|
25624
|
+
* Later entries in regions replace earlier cells, including with air.
|
|
25625
|
+
* Size encloses all region bounds; positions retain the schematic origin.
|
|
25626
|
+
* Metadata and scheduled ticks are not imported. Named regions can be placed individually.
|
|
25627
|
+
*/
|
|
25628
|
+
static async parse(nbt) {
|
|
25629
|
+
const tags = nbt.value;
|
|
25630
|
+
const version2 = integer2(tags.Version, "Version");
|
|
25631
|
+
if (version2 < 5 || version2 > 7) throw new MineRenderError(`Unsupported Litematica version ${version2}; expected 5, 6, or 7`);
|
|
25632
|
+
const dataVersion = tags.MinecraftDataVersion === void 0 ? void 0 : integer2(tags.MinecraftDataVersion, "MinecraftDataVersion");
|
|
25633
|
+
const blocks = /* @__PURE__ */ new Map();
|
|
25634
|
+
const regions = [];
|
|
25635
|
+
const min = [Infinity, Infinity, Infinity];
|
|
25636
|
+
const max = [-Infinity, -Infinity, -Infinity];
|
|
25637
|
+
for (const [name, tag] of Object.entries(compound(tags.Regions, "Regions"))) {
|
|
25638
|
+
const region = readRegion(compound(tag, `region ${name}`), name, dataVersion, blocks);
|
|
25639
|
+
regions.push(region);
|
|
25640
|
+
for (let axis = 0; axis < 3; axis++) {
|
|
25641
|
+
const start = minimum(region.position[axis], region.signedSize[axis]);
|
|
25642
|
+
min[axis] = Math.min(min[axis], start);
|
|
25643
|
+
max[axis] = Math.max(max[axis], start + region.size[axis]);
|
|
25644
|
+
}
|
|
25645
|
+
}
|
|
25646
|
+
return {
|
|
25647
|
+
size: regions.length ? min.map((value, axis) => max[axis] - value) : [0, 0, 0],
|
|
25648
|
+
blocks: [...blocks.values()],
|
|
25649
|
+
entities: regions.flatMap((region) => region.entities ?? []),
|
|
25650
|
+
dataVersion,
|
|
25651
|
+
regions
|
|
25652
|
+
};
|
|
25653
|
+
}
|
|
25654
|
+
};
|
|
25655
|
+
function readRegion(tags, name, dataVersion, combined) {
|
|
25656
|
+
const position = blockPosition(compound(tags.Position, `region ${name} Position`));
|
|
25657
|
+
const signedSize = blockPosition(compound(tags.Size, `region ${name} Size`));
|
|
25658
|
+
if (signedSize.some((value) => value === 0)) throw new MineRenderError(`Litematica region ${name} dimensions must be nonzero`);
|
|
25659
|
+
const size = signedSize.map(Math.abs);
|
|
25660
|
+
const min = position.map((value, axis) => minimum(value, signedSize[axis]));
|
|
25661
|
+
const [width, height, length] = size;
|
|
25662
|
+
const volume = width * height * length;
|
|
25663
|
+
const palette = compounds(tags.BlockStatePalette, "BlockStatePalette").map(blockState);
|
|
25664
|
+
if (!palette.length) throw new MineRenderError(`Litematica region ${name} has no block palette`);
|
|
25665
|
+
const bits = Math.max(2, Math.ceil(Math.log2(palette.length)));
|
|
25666
|
+
if (!Number.isSafeInteger(volume * bits)) throw new MineRenderError(`Litematica region ${name} volume is too large`);
|
|
25667
|
+
const packed = tags.BlockStates;
|
|
25668
|
+
const expected = Math.ceil(volume * bits / 64);
|
|
25669
|
+
if (packed?.type !== "longArray" || !Array.isArray(packed.value) || packed.value.length !== expected) {
|
|
25670
|
+
throw new MineRenderError(`Litematica region ${name} BlockStates must contain ${expected} longs`);
|
|
25671
|
+
}
|
|
25672
|
+
const words = packed.value.map((pair) => {
|
|
25673
|
+
if (!Array.isArray(pair) || pair.length !== 2 || !pair.every((value) => Number.isInteger(value) && value >= -2147483648 && value <= 4294967295)) {
|
|
25674
|
+
throw new MineRenderError(`Litematica region ${name} has an invalid BlockStates long`);
|
|
25675
|
+
}
|
|
25676
|
+
return [pair[0] >>> 0, pair[1] >>> 0];
|
|
25677
|
+
});
|
|
25678
|
+
const blockEntities = /* @__PURE__ */ new Map();
|
|
25679
|
+
for (const tile of compounds(tags.TileEntities, "TileEntities")) {
|
|
25680
|
+
const pos = blockPosition(tile);
|
|
25681
|
+
if (pos.some((value2, axis) => value2 < 0 || value2 >= size[axis])) {
|
|
25682
|
+
throw new MineRenderError(`Litematica region ${name} block entity is outside its dimensions`);
|
|
25683
|
+
}
|
|
25684
|
+
const index = pos[0] + pos[2] * width + pos[1] * width * length;
|
|
25685
|
+
if (blockEntities.has(index)) throw new MineRenderError(`Duplicate Litematica block entity at index ${index}`);
|
|
25686
|
+
const value = { ...tile };
|
|
25687
|
+
for (const [axis, key] of ["x", "y", "z"].entries()) value[key] = { type: "int", value: pos[axis] + min[axis] };
|
|
25688
|
+
blockEntities.set(index, { type: "compound", value });
|
|
25689
|
+
}
|
|
25690
|
+
const blocks = [];
|
|
25691
|
+
const mask = 2 ** bits - 1;
|
|
25692
|
+
for (let index = 0; index < volume; index++) {
|
|
25693
|
+
const word = Math.floor(index * bits / 64);
|
|
25694
|
+
const shift = index * bits % 64;
|
|
25695
|
+
const [high, low] = words[word];
|
|
25696
|
+
let value = shift < 32 ? low >>> shift : high >>> shift - 32;
|
|
25697
|
+
if (shift < 32 && shift + bits > 32) value |= high << 32 - shift;
|
|
25698
|
+
if (shift + bits > 64) value |= words[word + 1][1] << 64 - shift;
|
|
25699
|
+
const id = (value & mask) >>> 0;
|
|
25700
|
+
const state = palette[id];
|
|
25701
|
+
if (!state) throw new MineRenderError(`Litematica region ${name} palette index ${id} does not exist`);
|
|
25702
|
+
const pos = [
|
|
25703
|
+
index % width + min[0],
|
|
25704
|
+
Math.floor(index / (width * length)) + min[1],
|
|
25705
|
+
Math.floor(index / width) % length + min[2]
|
|
25706
|
+
];
|
|
25707
|
+
const key = pos.join(",");
|
|
25708
|
+
if (["minecraft:air", "minecraft:cave_air", "minecraft:void_air"].includes(state.type)) {
|
|
25709
|
+
combined.delete(key);
|
|
25710
|
+
continue;
|
|
25711
|
+
}
|
|
25712
|
+
const block = { type: state.type, properties: { ...state.properties }, position: pos, nbt: blockEntities.get(index) };
|
|
25713
|
+
blocks.push(block);
|
|
25714
|
+
combined.set(key, block);
|
|
25715
|
+
}
|
|
25716
|
+
const entities = compounds(tags.Entities, "Entities").map((entity) => {
|
|
25717
|
+
const pos = entity.Pos;
|
|
25718
|
+
if (pos?.type !== "list" || pos.value.type !== "double" || pos.value.value.length !== 3 || !pos.value.value.every(Number.isFinite)) {
|
|
25719
|
+
throw new MineRenderError(`Litematica region ${name} entity Pos must contain three doubles`);
|
|
25720
|
+
}
|
|
25721
|
+
const absolute = pos.value.value.map((value2, axis) => value2 + position[axis]);
|
|
25722
|
+
const value = { ...entity, Pos: { type: "list", value: { type: "double", value: [...absolute] } } };
|
|
25723
|
+
return { position: absolute, nbt: { type: "compound", value } };
|
|
25724
|
+
});
|
|
25725
|
+
return { name, position, signedSize, size, blocks, entities, dataVersion };
|
|
25726
|
+
}
|
|
25727
|
+
function minimum(position, size) {
|
|
25728
|
+
return position + Math.min(0, size + 1);
|
|
25729
|
+
}
|
|
25730
|
+
function integer2(tag, name) {
|
|
25731
|
+
if (tag?.type !== "int" || !Number.isInteger(tag.value) || tag.value < -2147483648 || tag.value > 2147483647) {
|
|
25732
|
+
throw new MineRenderError(`Litematica ${name} must be an int`);
|
|
25733
|
+
}
|
|
25734
|
+
return tag.value;
|
|
25735
|
+
}
|
|
25736
|
+
function compound(tag, name) {
|
|
25737
|
+
if (tag?.type !== "compound" || !tag.value || typeof tag.value !== "object" || Array.isArray(tag.value)) {
|
|
25738
|
+
throw new MineRenderError(`Litematica ${name} must be a compound`);
|
|
25739
|
+
}
|
|
25740
|
+
return tag.value;
|
|
25741
|
+
}
|
|
25742
|
+
function blockPosition(tags) {
|
|
25743
|
+
return ["x", "y", "z"].map((axis) => integer2(tags[axis], axis));
|
|
25744
|
+
}
|
|
25745
|
+
function compounds(tag, name) {
|
|
25746
|
+
if (tag === void 0) return [];
|
|
25747
|
+
if (tag.type === "list" && Array.isArray(tag.value.value)) {
|
|
25748
|
+
if (tag.value.value.length === 0) return [];
|
|
25749
|
+
if (tag.value.type === "compound") return tag.value.value;
|
|
25750
|
+
}
|
|
25751
|
+
throw new MineRenderError(`Litematica ${name} must be a compound list`);
|
|
25752
|
+
}
|
|
25753
|
+
function blockState(tags) {
|
|
25754
|
+
const name = tags.Name;
|
|
25755
|
+
if (name?.type !== "string" || !/^(?:[a-z0-9_.-]+:)?[a-z0-9_./-]+$/.test(name.value)) {
|
|
25756
|
+
throw new MineRenderError("Litematica palette entry must have a block Name");
|
|
25757
|
+
}
|
|
25758
|
+
const properties = {};
|
|
25759
|
+
if (tags.Properties !== void 0) {
|
|
25760
|
+
for (const [key, tag] of Object.entries(compound(tags.Properties, "block Properties"))) {
|
|
25761
|
+
if (tag?.type !== "string") throw new MineRenderError("Litematica block properties must be strings");
|
|
25762
|
+
Object.defineProperty(properties, key, { value: tag.value, enumerable: true, writable: true, configurable: true });
|
|
25763
|
+
}
|
|
25764
|
+
}
|
|
25765
|
+
return { type: name.value.includes(":") ? name.value : `minecraft:${name.value}`, properties };
|
|
25766
|
+
}
|
|
25767
|
+
|
|
25744
25768
|
// src/model/multiblock/SchematicParser.ts
|
|
25769
|
+
init_MineRenderError();
|
|
25745
25770
|
var SchematicParser = class {
|
|
25746
25771
|
/**
|
|
25747
25772
|
* Parses a legacy schematic using custom mappings before the bundled defaults.
|
|
@@ -25783,35 +25808,21 @@ var SchematicParser = class {
|
|
|
25783
25808
|
tileEntities.set((y * length + z) * width + x, { type: "compound", value: tile });
|
|
25784
25809
|
}
|
|
25785
25810
|
const blocks = [];
|
|
25786
|
-
const mapping = legacyBlocks_default.blocks;
|
|
25787
25811
|
for (let index = 0; index < volume; index++) {
|
|
25788
25812
|
const packed = addBlocks?.value[index >> 1] ?? 0;
|
|
25789
25813
|
const high = packed >> (index & 1) * 4 & 15;
|
|
25790
25814
|
const id = high << 8 | ids.value[index] & 255;
|
|
25791
25815
|
const metadata = data.value[index] & 255;
|
|
25792
|
-
const
|
|
25793
|
-
|
|
25794
|
-
if (!mapped && options.lenient) {
|
|
25795
|
-
mapped = customMappings[`${id}:0`] ?? mapping[`${id}:0`];
|
|
25796
|
-
}
|
|
25797
|
-
if (!mapped) {
|
|
25816
|
+
const block = resolveLegacyBlock(id, metadata, customMappings, options.lenient);
|
|
25817
|
+
if (!block) {
|
|
25798
25818
|
if (options.lenient) {
|
|
25799
25819
|
continue;
|
|
25800
25820
|
}
|
|
25801
25821
|
throw new MineRenderError(`Unsupported legacy block ${id}:${metadata} at schematic index ${index}`);
|
|
25802
25822
|
}
|
|
25803
|
-
|
|
25804
|
-
if (type === "minecraft:air") continue;
|
|
25805
|
-
const properties = {};
|
|
25806
|
-
if (state) {
|
|
25807
|
-
for (const property of state.slice(0, -1).split(",")) {
|
|
25808
|
-
const [key2, value] = property.split("=");
|
|
25809
|
-
properties[key2] = value;
|
|
25810
|
-
}
|
|
25811
|
-
}
|
|
25823
|
+
if (block.type === "minecraft:air") continue;
|
|
25812
25824
|
blocks.push({
|
|
25813
|
-
|
|
25814
|
-
properties,
|
|
25825
|
+
...block,
|
|
25815
25826
|
position: [index % width, Math.floor(index / (width * length)), Math.floor(index / width) % length],
|
|
25816
25827
|
nbt: tileEntities.get(index)
|
|
25817
25828
|
});
|
|
@@ -29303,28 +29314,34 @@ var AnvilParser = class {
|
|
|
29303
29314
|
if (expected && (chunk.x !== expected.x || chunk.z !== expected.z)) {
|
|
29304
29315
|
throw new MineRenderError(`Anvil chunk coordinates do not match external file c.${expected.x}.${expected.z}.mcc`);
|
|
29305
29316
|
}
|
|
29317
|
+
const numericStates = /* @__PURE__ */ new Map();
|
|
29306
29318
|
for (const section of this.compounds(level.sections ?? level.Sections, "sections")) {
|
|
29307
29319
|
const y = this.integer(section.Y, "section Y");
|
|
29320
|
+
let data2;
|
|
29308
29321
|
if (section.Blocks || section.Data || section.Add) {
|
|
29309
|
-
|
|
29310
|
-
|
|
29311
|
-
|
|
29312
|
-
|
|
29313
|
-
}
|
|
29314
|
-
|
|
29315
|
-
|
|
29316
|
-
|
|
29317
|
-
|
|
29318
|
-
|
|
29319
|
-
const
|
|
29320
|
-
|
|
29321
|
-
|
|
29322
|
-
const
|
|
29323
|
-
|
|
29324
|
-
|
|
29322
|
+
if (section.Palette || section.BlockStates || section.block_states) {
|
|
29323
|
+
throw new MineRenderError(`Anvil section ${y} mixes numeric and paletted block states`);
|
|
29324
|
+
}
|
|
29325
|
+
data2 = this.numericSection(section, y, options, numericStates);
|
|
29326
|
+
} else {
|
|
29327
|
+
if (section.block_states && section.block_states.type !== "compound") {
|
|
29328
|
+
throw new MineRenderError("Anvil block_states must be a compound");
|
|
29329
|
+
}
|
|
29330
|
+
const modern = section.block_states?.type === "compound" ? section.block_states.value : void 0;
|
|
29331
|
+
const paletteTag = modern ? modern.palette : section.Palette;
|
|
29332
|
+
const palette = paletteTag?.type === "list" && paletteTag.value.type === "string" ? paletteTag.value.value : this.compounds(paletteTag, "block palette");
|
|
29333
|
+
data2 = new ChunkData();
|
|
29334
|
+
if (palette.length) {
|
|
29335
|
+
const states = palette.map((entry) => this.block(entry));
|
|
29336
|
+
const indices = this.unpack(modern ? modern.data : section.BlockStates, states.length, !!modern, dataVersion);
|
|
29337
|
+
for (let index = 0; index < 4096; index++) {
|
|
29338
|
+
const state = states[indices[index]];
|
|
29339
|
+
if (!state) throw new MineRenderError(`Anvil palette index ${indices[index]} is out of range`);
|
|
29340
|
+
if (!ChunkData.isAir(state)) data2.set(index, state);
|
|
29341
|
+
}
|
|
29342
|
+
} else if (modern || section.Palette || section.BlockStates) {
|
|
29343
|
+
throw new MineRenderError("Anvil section has block states without a palette");
|
|
29325
29344
|
}
|
|
29326
|
-
} else if (modern || section.Palette || section.BlockStates) {
|
|
29327
|
-
throw new MineRenderError("Anvil section has block states without a palette");
|
|
29328
29345
|
}
|
|
29329
29346
|
if (chunk.sections.some((section2) => section2.y === y)) throw new MineRenderError(`Duplicate Anvil section Y ${y}`);
|
|
29330
29347
|
chunk.sections.push({ y, data: data2 });
|
|
@@ -29352,6 +29369,33 @@ var AnvilParser = class {
|
|
|
29352
29369
|
}
|
|
29353
29370
|
return chunk;
|
|
29354
29371
|
}
|
|
29372
|
+
static numericSection(section, y, options, states) {
|
|
29373
|
+
const bytes = (name, length, optional = false) => {
|
|
29374
|
+
const tag = section[name];
|
|
29375
|
+
if (!tag && optional) return void 0;
|
|
29376
|
+
if (tag?.type !== "byteArray" || !Array.isArray(tag.value) || tag.value.length !== length) {
|
|
29377
|
+
throw new MineRenderError(`Anvil section ${y} ${name} must contain ${length} bytes`);
|
|
29378
|
+
}
|
|
29379
|
+
return tag.value;
|
|
29380
|
+
};
|
|
29381
|
+
const ids = bytes("Blocks", 4096);
|
|
29382
|
+
const metadata = bytes("Data", 2048, true);
|
|
29383
|
+
const extra = bytes("Add", 2048, true);
|
|
29384
|
+
const data = new ChunkData();
|
|
29385
|
+
for (let index = 0; index < 4096; index++) {
|
|
29386
|
+
const shift = (index & 1) * 4;
|
|
29387
|
+
const id = ids[index] & 255 | ((extra?.[index >> 1] ?? 0) >> shift & 15) << 8;
|
|
29388
|
+
const value = (metadata?.[index >> 1] ?? 0) >> shift & 15;
|
|
29389
|
+
const key = id * 16 + value;
|
|
29390
|
+
if (!states.has(key)) states.set(key, resolveLegacyBlock(id, value, options.legacyMappings, options.lenient));
|
|
29391
|
+
const block = states.get(key);
|
|
29392
|
+
if (!block && !options.lenient) {
|
|
29393
|
+
throw new MineRenderError(`Unsupported legacy block ${id}:${value} at Anvil section ${y} index ${index}`);
|
|
29394
|
+
}
|
|
29395
|
+
if (block && !ChunkData.isAir(block)) data.set(index, block);
|
|
29396
|
+
}
|
|
29397
|
+
return data;
|
|
29398
|
+
}
|
|
29355
29399
|
static compounds(tag, name) {
|
|
29356
29400
|
if (!tag) return [];
|
|
29357
29401
|
if (tag.type !== "list" || tag.value.type !== "compound" && tag.value.value.length !== 0) {
|
|
@@ -29434,7 +29478,7 @@ var AnvilWorldSource = class {
|
|
|
29434
29478
|
this.cachedBytes = 0;
|
|
29435
29479
|
this.maxCachedRegions = options.maxCachedRegions ?? 4;
|
|
29436
29480
|
this.maxCachedBytes = options.maxCachedBytes ?? 64 * 1024 * 1024;
|
|
29437
|
-
this.
|
|
29481
|
+
this.parseOptions = { readExternalChunk: options.readExternalChunk, legacyMappings: options.legacyMappings, lenient: options.lenient };
|
|
29438
29482
|
for (const [name, value] of Object.entries({ maxCachedRegions: this.maxCachedRegions, maxCachedBytes: this.maxCachedBytes })) {
|
|
29439
29483
|
if (!Number.isSafeInteger(value) || value < 0) throw new RangeError(`${name} must be a nonnegative safe integer`);
|
|
29440
29484
|
}
|
|
@@ -29449,8 +29493,8 @@ var AnvilWorldSource = class {
|
|
|
29449
29493
|
signal?.throwIfAborted();
|
|
29450
29494
|
if (!data) return void 0;
|
|
29451
29495
|
const chunk = await AnvilParser.parseChunk(data, x - regionX * 32, z - regionZ * 32, {
|
|
29496
|
+
...this.parseOptions,
|
|
29452
29497
|
region: { x: regionX, z: regionZ },
|
|
29453
|
-
readExternalChunk: this.readExternalChunk,
|
|
29454
29498
|
signal
|
|
29455
29499
|
});
|
|
29456
29500
|
signal?.throwIfAborted();
|