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/node/index.js
CHANGED
|
@@ -18963,6 +18963,7 @@ __export(index_node_exports, {
|
|
|
18963
18963
|
parseSceneDocument: () => parseSceneDocument,
|
|
18964
18964
|
prefix: () => prefix,
|
|
18965
18965
|
registerNodeEnv: () => registerNodeEnv,
|
|
18966
|
+
resolveLegacyBlock: () => resolveLegacyBlock,
|
|
18966
18967
|
sampleEntityAnimation: () => sampleEntityAnimation,
|
|
18967
18968
|
sampleEntityKeyframes: () => sampleEntityKeyframes,
|
|
18968
18969
|
sampleFluid: () => sampleFluid,
|
|
@@ -23945,158 +23946,6 @@ function isBlockObject(obj) {
|
|
|
23945
23946
|
init_FluidGeometry();
|
|
23946
23947
|
init_FluidModelObject();
|
|
23947
23948
|
|
|
23948
|
-
// src/model/multiblock/LitematicaParser.ts
|
|
23949
|
-
init_MineRenderError();
|
|
23950
|
-
var LitematicaParser = class {
|
|
23951
|
-
/**
|
|
23952
|
-
* Parses decoded NBT, preserving subregion placement and omitting air.
|
|
23953
|
-
* Later entries in regions replace earlier cells, including with air.
|
|
23954
|
-
* Size encloses all region bounds; positions retain the schematic origin.
|
|
23955
|
-
* Metadata and scheduled ticks are not imported. Named regions can be placed individually.
|
|
23956
|
-
*/
|
|
23957
|
-
static async parse(nbt) {
|
|
23958
|
-
const tags = nbt.value;
|
|
23959
|
-
const version2 = integer2(tags.Version, "Version");
|
|
23960
|
-
if (version2 < 5 || version2 > 7) throw new MineRenderError(`Unsupported Litematica version ${version2}; expected 5, 6, or 7`);
|
|
23961
|
-
const dataVersion = tags.MinecraftDataVersion === void 0 ? void 0 : integer2(tags.MinecraftDataVersion, "MinecraftDataVersion");
|
|
23962
|
-
const blocks = /* @__PURE__ */ new Map();
|
|
23963
|
-
const regions = [];
|
|
23964
|
-
const min = [Infinity, Infinity, Infinity];
|
|
23965
|
-
const max = [-Infinity, -Infinity, -Infinity];
|
|
23966
|
-
for (const [name, tag] of Object.entries(compound(tags.Regions, "Regions"))) {
|
|
23967
|
-
const region = readRegion(compound(tag, `region ${name}`), name, dataVersion, blocks);
|
|
23968
|
-
regions.push(region);
|
|
23969
|
-
for (let axis = 0; axis < 3; axis++) {
|
|
23970
|
-
const start = minimum(region.position[axis], region.signedSize[axis]);
|
|
23971
|
-
min[axis] = Math.min(min[axis], start);
|
|
23972
|
-
max[axis] = Math.max(max[axis], start + region.size[axis]);
|
|
23973
|
-
}
|
|
23974
|
-
}
|
|
23975
|
-
return {
|
|
23976
|
-
size: regions.length ? min.map((value, axis) => max[axis] - value) : [0, 0, 0],
|
|
23977
|
-
blocks: [...blocks.values()],
|
|
23978
|
-
entities: regions.flatMap((region) => region.entities ?? []),
|
|
23979
|
-
dataVersion,
|
|
23980
|
-
regions
|
|
23981
|
-
};
|
|
23982
|
-
}
|
|
23983
|
-
};
|
|
23984
|
-
function readRegion(tags, name, dataVersion, combined) {
|
|
23985
|
-
const position = blockPosition(compound(tags.Position, `region ${name} Position`));
|
|
23986
|
-
const signedSize = blockPosition(compound(tags.Size, `region ${name} Size`));
|
|
23987
|
-
if (signedSize.some((value) => value === 0)) throw new MineRenderError(`Litematica region ${name} dimensions must be nonzero`);
|
|
23988
|
-
const size = signedSize.map(Math.abs);
|
|
23989
|
-
const min = position.map((value, axis) => minimum(value, signedSize[axis]));
|
|
23990
|
-
const [width, height, length] = size;
|
|
23991
|
-
const volume = width * height * length;
|
|
23992
|
-
const palette = compounds(tags.BlockStatePalette, "BlockStatePalette").map(blockState);
|
|
23993
|
-
if (!palette.length) throw new MineRenderError(`Litematica region ${name} has no block palette`);
|
|
23994
|
-
const bits = Math.max(2, Math.ceil(Math.log2(palette.length)));
|
|
23995
|
-
if (!Number.isSafeInteger(volume * bits)) throw new MineRenderError(`Litematica region ${name} volume is too large`);
|
|
23996
|
-
const packed = tags.BlockStates;
|
|
23997
|
-
const expected = Math.ceil(volume * bits / 64);
|
|
23998
|
-
if (packed?.type !== "longArray" || !Array.isArray(packed.value) || packed.value.length !== expected) {
|
|
23999
|
-
throw new MineRenderError(`Litematica region ${name} BlockStates must contain ${expected} longs`);
|
|
24000
|
-
}
|
|
24001
|
-
const words = packed.value.map((pair) => {
|
|
24002
|
-
if (!Array.isArray(pair) || pair.length !== 2 || !pair.every((value) => Number.isInteger(value) && value >= -2147483648 && value <= 4294967295)) {
|
|
24003
|
-
throw new MineRenderError(`Litematica region ${name} has an invalid BlockStates long`);
|
|
24004
|
-
}
|
|
24005
|
-
return [pair[0] >>> 0, pair[1] >>> 0];
|
|
24006
|
-
});
|
|
24007
|
-
const blockEntities = /* @__PURE__ */ new Map();
|
|
24008
|
-
for (const tile of compounds(tags.TileEntities, "TileEntities")) {
|
|
24009
|
-
const pos = blockPosition(tile);
|
|
24010
|
-
if (pos.some((value2, axis) => value2 < 0 || value2 >= size[axis])) {
|
|
24011
|
-
throw new MineRenderError(`Litematica region ${name} block entity is outside its dimensions`);
|
|
24012
|
-
}
|
|
24013
|
-
const index = pos[0] + pos[2] * width + pos[1] * width * length;
|
|
24014
|
-
if (blockEntities.has(index)) throw new MineRenderError(`Duplicate Litematica block entity at index ${index}`);
|
|
24015
|
-
const value = { ...tile };
|
|
24016
|
-
for (const [axis, key] of ["x", "y", "z"].entries()) value[key] = { type: "int", value: pos[axis] + min[axis] };
|
|
24017
|
-
blockEntities.set(index, { type: "compound", value });
|
|
24018
|
-
}
|
|
24019
|
-
const blocks = [];
|
|
24020
|
-
const mask = 2 ** bits - 1;
|
|
24021
|
-
for (let index = 0; index < volume; index++) {
|
|
24022
|
-
const word = Math.floor(index * bits / 64);
|
|
24023
|
-
const shift = index * bits % 64;
|
|
24024
|
-
const [high, low] = words[word];
|
|
24025
|
-
let value = shift < 32 ? low >>> shift : high >>> shift - 32;
|
|
24026
|
-
if (shift < 32 && shift + bits > 32) value |= high << 32 - shift;
|
|
24027
|
-
if (shift + bits > 64) value |= words[word + 1][1] << 64 - shift;
|
|
24028
|
-
const id = (value & mask) >>> 0;
|
|
24029
|
-
const state = palette[id];
|
|
24030
|
-
if (!state) throw new MineRenderError(`Litematica region ${name} palette index ${id} does not exist`);
|
|
24031
|
-
const pos = [
|
|
24032
|
-
index % width + min[0],
|
|
24033
|
-
Math.floor(index / (width * length)) + min[1],
|
|
24034
|
-
Math.floor(index / width) % length + min[2]
|
|
24035
|
-
];
|
|
24036
|
-
const key = pos.join(",");
|
|
24037
|
-
if (["minecraft:air", "minecraft:cave_air", "minecraft:void_air"].includes(state.type)) {
|
|
24038
|
-
combined.delete(key);
|
|
24039
|
-
continue;
|
|
24040
|
-
}
|
|
24041
|
-
const block = { type: state.type, properties: { ...state.properties }, position: pos, nbt: blockEntities.get(index) };
|
|
24042
|
-
blocks.push(block);
|
|
24043
|
-
combined.set(key, block);
|
|
24044
|
-
}
|
|
24045
|
-
const entities = compounds(tags.Entities, "Entities").map((entity) => {
|
|
24046
|
-
const pos = entity.Pos;
|
|
24047
|
-
if (pos?.type !== "list" || pos.value.type !== "double" || pos.value.value.length !== 3 || !pos.value.value.every(Number.isFinite)) {
|
|
24048
|
-
throw new MineRenderError(`Litematica region ${name} entity Pos must contain three doubles`);
|
|
24049
|
-
}
|
|
24050
|
-
const absolute = pos.value.value.map((value2, axis) => value2 + position[axis]);
|
|
24051
|
-
const value = { ...entity, Pos: { type: "list", value: { type: "double", value: [...absolute] } } };
|
|
24052
|
-
return { position: absolute, nbt: { type: "compound", value } };
|
|
24053
|
-
});
|
|
24054
|
-
return { name, position, signedSize, size, blocks, entities, dataVersion };
|
|
24055
|
-
}
|
|
24056
|
-
function minimum(position, size) {
|
|
24057
|
-
return position + Math.min(0, size + 1);
|
|
24058
|
-
}
|
|
24059
|
-
function integer2(tag, name) {
|
|
24060
|
-
if (tag?.type !== "int" || !Number.isInteger(tag.value) || tag.value < -2147483648 || tag.value > 2147483647) {
|
|
24061
|
-
throw new MineRenderError(`Litematica ${name} must be an int`);
|
|
24062
|
-
}
|
|
24063
|
-
return tag.value;
|
|
24064
|
-
}
|
|
24065
|
-
function compound(tag, name) {
|
|
24066
|
-
if (tag?.type !== "compound" || !tag.value || typeof tag.value !== "object" || Array.isArray(tag.value)) {
|
|
24067
|
-
throw new MineRenderError(`Litematica ${name} must be a compound`);
|
|
24068
|
-
}
|
|
24069
|
-
return tag.value;
|
|
24070
|
-
}
|
|
24071
|
-
function blockPosition(tags) {
|
|
24072
|
-
return ["x", "y", "z"].map((axis) => integer2(tags[axis], axis));
|
|
24073
|
-
}
|
|
24074
|
-
function compounds(tag, name) {
|
|
24075
|
-
if (tag === void 0) return [];
|
|
24076
|
-
if (tag.type === "list" && Array.isArray(tag.value.value)) {
|
|
24077
|
-
if (tag.value.value.length === 0) return [];
|
|
24078
|
-
if (tag.value.type === "compound") return tag.value.value;
|
|
24079
|
-
}
|
|
24080
|
-
throw new MineRenderError(`Litematica ${name} must be a compound list`);
|
|
24081
|
-
}
|
|
24082
|
-
function blockState(tags) {
|
|
24083
|
-
const name = tags.Name;
|
|
24084
|
-
if (name?.type !== "string" || !/^(?:[a-z0-9_.-]+:)?[a-z0-9_./-]+$/.test(name.value)) {
|
|
24085
|
-
throw new MineRenderError("Litematica palette entry must have a block Name");
|
|
24086
|
-
}
|
|
24087
|
-
const properties = {};
|
|
24088
|
-
if (tags.Properties !== void 0) {
|
|
24089
|
-
for (const [key, tag] of Object.entries(compound(tags.Properties, "block Properties"))) {
|
|
24090
|
-
if (tag?.type !== "string") throw new MineRenderError("Litematica block properties must be strings");
|
|
24091
|
-
Object.defineProperty(properties, key, { value: tag.value, enumerable: true, writable: true, configurable: true });
|
|
24092
|
-
}
|
|
24093
|
-
}
|
|
24094
|
-
return { type: name.value.includes(":") ? name.value : `minecraft:${name.value}`, properties };
|
|
24095
|
-
}
|
|
24096
|
-
|
|
24097
|
-
// src/model/multiblock/SchematicParser.ts
|
|
24098
|
-
init_MineRenderError();
|
|
24099
|
-
|
|
24100
23949
|
// src/model/multiblock/legacyBlocks.json
|
|
24101
23950
|
var legacyBlocks_default = {
|
|
24102
23951
|
__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",
|
|
@@ -24940,12 +24789,20 @@ var legacyBlocks_default = {
|
|
|
24940
24789
|
"131:15": "minecraft:tripwire_hook[powered=true,attached=true,facing=east]",
|
|
24941
24790
|
"132:0": "minecraft:tripwire[disarmed=false,east=false,powered=false,south=false,north=false,west=false,attached=false]",
|
|
24942
24791
|
"132:1": "minecraft:tripwire[disarmed=false,east=false,powered=true,south=false,north=false,west=false,attached=false]",
|
|
24792
|
+
"132:2": "minecraft:tripwire[disarmed=false,east=false,powered=false,south=false,north=false,west=false,attached=false]",
|
|
24793
|
+
"132:3": "minecraft:tripwire[disarmed=false,east=false,powered=true,south=false,north=false,west=false,attached=false]",
|
|
24943
24794
|
"132:4": "minecraft:tripwire[disarmed=false,east=false,powered=false,south=false,north=false,west=false,attached=true]",
|
|
24944
24795
|
"132:5": "minecraft:tripwire[disarmed=false,east=false,powered=true,south=false,north=false,west=false,attached=true]",
|
|
24796
|
+
"132:6": "minecraft:tripwire[disarmed=false,east=false,powered=false,south=false,north=false,west=false,attached=true]",
|
|
24797
|
+
"132:7": "minecraft:tripwire[disarmed=false,east=false,powered=true,south=false,north=false,west=false,attached=true]",
|
|
24945
24798
|
"132:8": "minecraft:tripwire[disarmed=true,east=false,powered=false,south=false,north=false,west=false,attached=false]",
|
|
24946
24799
|
"132:9": "minecraft:tripwire[disarmed=true,east=false,powered=true,south=false,north=false,west=false,attached=false]",
|
|
24800
|
+
"132:10": "minecraft:tripwire[disarmed=true,east=false,powered=false,south=false,north=false,west=false,attached=false]",
|
|
24801
|
+
"132:11": "minecraft:tripwire[disarmed=true,east=false,powered=true,south=false,north=false,west=false,attached=false]",
|
|
24947
24802
|
"132:12": "minecraft:tripwire[disarmed=true,east=false,powered=false,south=false,north=false,west=false,attached=true]",
|
|
24948
24803
|
"132:13": "minecraft:tripwire[disarmed=true,east=false,powered=true,south=false,north=false,west=false,attached=true]",
|
|
24804
|
+
"132:14": "minecraft:tripwire[disarmed=true,east=false,powered=false,south=false,north=false,west=false,attached=true]",
|
|
24805
|
+
"132:15": "minecraft:tripwire[disarmed=true,east=false,powered=true,south=false,north=false,west=false,attached=true]",
|
|
24949
24806
|
"133:0": "minecraft:emerald_block",
|
|
24950
24807
|
"134:0": "minecraft:spruce_stairs[half=bottom,shape=outer_right,facing=east]",
|
|
24951
24808
|
"134:1": "minecraft:spruce_stairs[half=bottom,shape=outer_right,facing=west]",
|
|
@@ -25786,7 +25643,175 @@ var legacyBlocks_default = {
|
|
|
25786
25643
|
}
|
|
25787
25644
|
};
|
|
25788
25645
|
|
|
25646
|
+
// src/model/multiblock/LegacyBlocks.ts
|
|
25647
|
+
function resolveLegacyBlock(id, metadata, customMappings = {}, lenient = false) {
|
|
25648
|
+
const mapping = legacyBlocks_default.blocks;
|
|
25649
|
+
const key = `${id}:${metadata}`;
|
|
25650
|
+
let mapped = customMappings[key] ?? mapping[key];
|
|
25651
|
+
if (!mapped && lenient) mapped = customMappings[`${id}:0`] ?? mapping[`${id}:0`];
|
|
25652
|
+
if (!mapped) return void 0;
|
|
25653
|
+
const [type, state] = mapped.split("[");
|
|
25654
|
+
const properties = {};
|
|
25655
|
+
if (state) {
|
|
25656
|
+
for (const property of state.slice(0, -1).split(",")) {
|
|
25657
|
+
const [key2, value] = property.split("=");
|
|
25658
|
+
properties[key2] = value;
|
|
25659
|
+
}
|
|
25660
|
+
}
|
|
25661
|
+
return { type, properties };
|
|
25662
|
+
}
|
|
25663
|
+
|
|
25664
|
+
// src/model/multiblock/LitematicaParser.ts
|
|
25665
|
+
init_MineRenderError();
|
|
25666
|
+
var LitematicaParser = class {
|
|
25667
|
+
/**
|
|
25668
|
+
* Parses decoded NBT, preserving subregion placement and omitting air.
|
|
25669
|
+
* Later entries in regions replace earlier cells, including with air.
|
|
25670
|
+
* Size encloses all region bounds; positions retain the schematic origin.
|
|
25671
|
+
* Metadata and scheduled ticks are not imported. Named regions can be placed individually.
|
|
25672
|
+
*/
|
|
25673
|
+
static async parse(nbt) {
|
|
25674
|
+
const tags = nbt.value;
|
|
25675
|
+
const version2 = integer2(tags.Version, "Version");
|
|
25676
|
+
if (version2 < 5 || version2 > 7) throw new MineRenderError(`Unsupported Litematica version ${version2}; expected 5, 6, or 7`);
|
|
25677
|
+
const dataVersion = tags.MinecraftDataVersion === void 0 ? void 0 : integer2(tags.MinecraftDataVersion, "MinecraftDataVersion");
|
|
25678
|
+
const blocks = /* @__PURE__ */ new Map();
|
|
25679
|
+
const regions = [];
|
|
25680
|
+
const min = [Infinity, Infinity, Infinity];
|
|
25681
|
+
const max = [-Infinity, -Infinity, -Infinity];
|
|
25682
|
+
for (const [name, tag] of Object.entries(compound(tags.Regions, "Regions"))) {
|
|
25683
|
+
const region = readRegion(compound(tag, `region ${name}`), name, dataVersion, blocks);
|
|
25684
|
+
regions.push(region);
|
|
25685
|
+
for (let axis = 0; axis < 3; axis++) {
|
|
25686
|
+
const start = minimum(region.position[axis], region.signedSize[axis]);
|
|
25687
|
+
min[axis] = Math.min(min[axis], start);
|
|
25688
|
+
max[axis] = Math.max(max[axis], start + region.size[axis]);
|
|
25689
|
+
}
|
|
25690
|
+
}
|
|
25691
|
+
return {
|
|
25692
|
+
size: regions.length ? min.map((value, axis) => max[axis] - value) : [0, 0, 0],
|
|
25693
|
+
blocks: [...blocks.values()],
|
|
25694
|
+
entities: regions.flatMap((region) => region.entities ?? []),
|
|
25695
|
+
dataVersion,
|
|
25696
|
+
regions
|
|
25697
|
+
};
|
|
25698
|
+
}
|
|
25699
|
+
};
|
|
25700
|
+
function readRegion(tags, name, dataVersion, combined) {
|
|
25701
|
+
const position = blockPosition(compound(tags.Position, `region ${name} Position`));
|
|
25702
|
+
const signedSize = blockPosition(compound(tags.Size, `region ${name} Size`));
|
|
25703
|
+
if (signedSize.some((value) => value === 0)) throw new MineRenderError(`Litematica region ${name} dimensions must be nonzero`);
|
|
25704
|
+
const size = signedSize.map(Math.abs);
|
|
25705
|
+
const min = position.map((value, axis) => minimum(value, signedSize[axis]));
|
|
25706
|
+
const [width, height, length] = size;
|
|
25707
|
+
const volume = width * height * length;
|
|
25708
|
+
const palette = compounds(tags.BlockStatePalette, "BlockStatePalette").map(blockState);
|
|
25709
|
+
if (!palette.length) throw new MineRenderError(`Litematica region ${name} has no block palette`);
|
|
25710
|
+
const bits = Math.max(2, Math.ceil(Math.log2(palette.length)));
|
|
25711
|
+
if (!Number.isSafeInteger(volume * bits)) throw new MineRenderError(`Litematica region ${name} volume is too large`);
|
|
25712
|
+
const packed = tags.BlockStates;
|
|
25713
|
+
const expected = Math.ceil(volume * bits / 64);
|
|
25714
|
+
if (packed?.type !== "longArray" || !Array.isArray(packed.value) || packed.value.length !== expected) {
|
|
25715
|
+
throw new MineRenderError(`Litematica region ${name} BlockStates must contain ${expected} longs`);
|
|
25716
|
+
}
|
|
25717
|
+
const words = packed.value.map((pair) => {
|
|
25718
|
+
if (!Array.isArray(pair) || pair.length !== 2 || !pair.every((value) => Number.isInteger(value) && value >= -2147483648 && value <= 4294967295)) {
|
|
25719
|
+
throw new MineRenderError(`Litematica region ${name} has an invalid BlockStates long`);
|
|
25720
|
+
}
|
|
25721
|
+
return [pair[0] >>> 0, pair[1] >>> 0];
|
|
25722
|
+
});
|
|
25723
|
+
const blockEntities = /* @__PURE__ */ new Map();
|
|
25724
|
+
for (const tile of compounds(tags.TileEntities, "TileEntities")) {
|
|
25725
|
+
const pos = blockPosition(tile);
|
|
25726
|
+
if (pos.some((value2, axis) => value2 < 0 || value2 >= size[axis])) {
|
|
25727
|
+
throw new MineRenderError(`Litematica region ${name} block entity is outside its dimensions`);
|
|
25728
|
+
}
|
|
25729
|
+
const index = pos[0] + pos[2] * width + pos[1] * width * length;
|
|
25730
|
+
if (blockEntities.has(index)) throw new MineRenderError(`Duplicate Litematica block entity at index ${index}`);
|
|
25731
|
+
const value = { ...tile };
|
|
25732
|
+
for (const [axis, key] of ["x", "y", "z"].entries()) value[key] = { type: "int", value: pos[axis] + min[axis] };
|
|
25733
|
+
blockEntities.set(index, { type: "compound", value });
|
|
25734
|
+
}
|
|
25735
|
+
const blocks = [];
|
|
25736
|
+
const mask = 2 ** bits - 1;
|
|
25737
|
+
for (let index = 0; index < volume; index++) {
|
|
25738
|
+
const word = Math.floor(index * bits / 64);
|
|
25739
|
+
const shift = index * bits % 64;
|
|
25740
|
+
const [high, low] = words[word];
|
|
25741
|
+
let value = shift < 32 ? low >>> shift : high >>> shift - 32;
|
|
25742
|
+
if (shift < 32 && shift + bits > 32) value |= high << 32 - shift;
|
|
25743
|
+
if (shift + bits > 64) value |= words[word + 1][1] << 64 - shift;
|
|
25744
|
+
const id = (value & mask) >>> 0;
|
|
25745
|
+
const state = palette[id];
|
|
25746
|
+
if (!state) throw new MineRenderError(`Litematica region ${name} palette index ${id} does not exist`);
|
|
25747
|
+
const pos = [
|
|
25748
|
+
index % width + min[0],
|
|
25749
|
+
Math.floor(index / (width * length)) + min[1],
|
|
25750
|
+
Math.floor(index / width) % length + min[2]
|
|
25751
|
+
];
|
|
25752
|
+
const key = pos.join(",");
|
|
25753
|
+
if (["minecraft:air", "minecraft:cave_air", "minecraft:void_air"].includes(state.type)) {
|
|
25754
|
+
combined.delete(key);
|
|
25755
|
+
continue;
|
|
25756
|
+
}
|
|
25757
|
+
const block = { type: state.type, properties: { ...state.properties }, position: pos, nbt: blockEntities.get(index) };
|
|
25758
|
+
blocks.push(block);
|
|
25759
|
+
combined.set(key, block);
|
|
25760
|
+
}
|
|
25761
|
+
const entities = compounds(tags.Entities, "Entities").map((entity) => {
|
|
25762
|
+
const pos = entity.Pos;
|
|
25763
|
+
if (pos?.type !== "list" || pos.value.type !== "double" || pos.value.value.length !== 3 || !pos.value.value.every(Number.isFinite)) {
|
|
25764
|
+
throw new MineRenderError(`Litematica region ${name} entity Pos must contain three doubles`);
|
|
25765
|
+
}
|
|
25766
|
+
const absolute = pos.value.value.map((value2, axis) => value2 + position[axis]);
|
|
25767
|
+
const value = { ...entity, Pos: { type: "list", value: { type: "double", value: [...absolute] } } };
|
|
25768
|
+
return { position: absolute, nbt: { type: "compound", value } };
|
|
25769
|
+
});
|
|
25770
|
+
return { name, position, signedSize, size, blocks, entities, dataVersion };
|
|
25771
|
+
}
|
|
25772
|
+
function minimum(position, size) {
|
|
25773
|
+
return position + Math.min(0, size + 1);
|
|
25774
|
+
}
|
|
25775
|
+
function integer2(tag, name) {
|
|
25776
|
+
if (tag?.type !== "int" || !Number.isInteger(tag.value) || tag.value < -2147483648 || tag.value > 2147483647) {
|
|
25777
|
+
throw new MineRenderError(`Litematica ${name} must be an int`);
|
|
25778
|
+
}
|
|
25779
|
+
return tag.value;
|
|
25780
|
+
}
|
|
25781
|
+
function compound(tag, name) {
|
|
25782
|
+
if (tag?.type !== "compound" || !tag.value || typeof tag.value !== "object" || Array.isArray(tag.value)) {
|
|
25783
|
+
throw new MineRenderError(`Litematica ${name} must be a compound`);
|
|
25784
|
+
}
|
|
25785
|
+
return tag.value;
|
|
25786
|
+
}
|
|
25787
|
+
function blockPosition(tags) {
|
|
25788
|
+
return ["x", "y", "z"].map((axis) => integer2(tags[axis], axis));
|
|
25789
|
+
}
|
|
25790
|
+
function compounds(tag, name) {
|
|
25791
|
+
if (tag === void 0) return [];
|
|
25792
|
+
if (tag.type === "list" && Array.isArray(tag.value.value)) {
|
|
25793
|
+
if (tag.value.value.length === 0) return [];
|
|
25794
|
+
if (tag.value.type === "compound") return tag.value.value;
|
|
25795
|
+
}
|
|
25796
|
+
throw new MineRenderError(`Litematica ${name} must be a compound list`);
|
|
25797
|
+
}
|
|
25798
|
+
function blockState(tags) {
|
|
25799
|
+
const name = tags.Name;
|
|
25800
|
+
if (name?.type !== "string" || !/^(?:[a-z0-9_.-]+:)?[a-z0-9_./-]+$/.test(name.value)) {
|
|
25801
|
+
throw new MineRenderError("Litematica palette entry must have a block Name");
|
|
25802
|
+
}
|
|
25803
|
+
const properties = {};
|
|
25804
|
+
if (tags.Properties !== void 0) {
|
|
25805
|
+
for (const [key, tag] of Object.entries(compound(tags.Properties, "block Properties"))) {
|
|
25806
|
+
if (tag?.type !== "string") throw new MineRenderError("Litematica block properties must be strings");
|
|
25807
|
+
Object.defineProperty(properties, key, { value: tag.value, enumerable: true, writable: true, configurable: true });
|
|
25808
|
+
}
|
|
25809
|
+
}
|
|
25810
|
+
return { type: name.value.includes(":") ? name.value : `minecraft:${name.value}`, properties };
|
|
25811
|
+
}
|
|
25812
|
+
|
|
25789
25813
|
// src/model/multiblock/SchematicParser.ts
|
|
25814
|
+
init_MineRenderError();
|
|
25790
25815
|
var SchematicParser = class {
|
|
25791
25816
|
/**
|
|
25792
25817
|
* Parses a legacy schematic using custom mappings before the bundled defaults.
|
|
@@ -25828,35 +25853,21 @@ var SchematicParser = class {
|
|
|
25828
25853
|
tileEntities.set((y * length + z) * width + x, { type: "compound", value: tile });
|
|
25829
25854
|
}
|
|
25830
25855
|
const blocks = [];
|
|
25831
|
-
const mapping = legacyBlocks_default.blocks;
|
|
25832
25856
|
for (let index = 0; index < volume; index++) {
|
|
25833
25857
|
const packed = addBlocks?.value[index >> 1] ?? 0;
|
|
25834
25858
|
const high = packed >> (index & 1) * 4 & 15;
|
|
25835
25859
|
const id = high << 8 | ids.value[index] & 255;
|
|
25836
25860
|
const metadata = data.value[index] & 255;
|
|
25837
|
-
const
|
|
25838
|
-
|
|
25839
|
-
if (!mapped && options.lenient) {
|
|
25840
|
-
mapped = customMappings[`${id}:0`] ?? mapping[`${id}:0`];
|
|
25841
|
-
}
|
|
25842
|
-
if (!mapped) {
|
|
25861
|
+
const block = resolveLegacyBlock(id, metadata, customMappings, options.lenient);
|
|
25862
|
+
if (!block) {
|
|
25843
25863
|
if (options.lenient) {
|
|
25844
25864
|
continue;
|
|
25845
25865
|
}
|
|
25846
25866
|
throw new MineRenderError(`Unsupported legacy block ${id}:${metadata} at schematic index ${index}`);
|
|
25847
25867
|
}
|
|
25848
|
-
|
|
25849
|
-
if (type === "minecraft:air") continue;
|
|
25850
|
-
const properties = {};
|
|
25851
|
-
if (state) {
|
|
25852
|
-
for (const property of state.slice(0, -1).split(",")) {
|
|
25853
|
-
const [key2, value] = property.split("=");
|
|
25854
|
-
properties[key2] = value;
|
|
25855
|
-
}
|
|
25856
|
-
}
|
|
25868
|
+
if (block.type === "minecraft:air") continue;
|
|
25857
25869
|
blocks.push({
|
|
25858
|
-
|
|
25859
|
-
properties,
|
|
25870
|
+
...block,
|
|
25860
25871
|
position: [index % width, Math.floor(index / (width * length)), Math.floor(index / width) % length],
|
|
25861
25872
|
nbt: tileEntities.get(index)
|
|
25862
25873
|
});
|
|
@@ -29350,28 +29361,34 @@ var AnvilParser = class {
|
|
|
29350
29361
|
if (expected && (chunk.x !== expected.x || chunk.z !== expected.z)) {
|
|
29351
29362
|
throw new MineRenderError(`Anvil chunk coordinates do not match external file c.${expected.x}.${expected.z}.mcc`);
|
|
29352
29363
|
}
|
|
29364
|
+
const numericStates = /* @__PURE__ */ new Map();
|
|
29353
29365
|
for (const section of this.compounds(level.sections ?? level.Sections, "sections")) {
|
|
29354
29366
|
const y = this.integer(section.Y, "section Y");
|
|
29367
|
+
let data2;
|
|
29355
29368
|
if (section.Blocks || section.Data || section.Add) {
|
|
29356
|
-
|
|
29357
|
-
|
|
29358
|
-
|
|
29359
|
-
|
|
29360
|
-
}
|
|
29361
|
-
|
|
29362
|
-
|
|
29363
|
-
|
|
29364
|
-
|
|
29365
|
-
|
|
29366
|
-
const
|
|
29367
|
-
|
|
29368
|
-
|
|
29369
|
-
const
|
|
29370
|
-
|
|
29371
|
-
|
|
29369
|
+
if (section.Palette || section.BlockStates || section.block_states) {
|
|
29370
|
+
throw new MineRenderError(`Anvil section ${y} mixes numeric and paletted block states`);
|
|
29371
|
+
}
|
|
29372
|
+
data2 = this.numericSection(section, y, options, numericStates);
|
|
29373
|
+
} else {
|
|
29374
|
+
if (section.block_states && section.block_states.type !== "compound") {
|
|
29375
|
+
throw new MineRenderError("Anvil block_states must be a compound");
|
|
29376
|
+
}
|
|
29377
|
+
const modern = section.block_states?.type === "compound" ? section.block_states.value : void 0;
|
|
29378
|
+
const paletteTag = modern ? modern.palette : section.Palette;
|
|
29379
|
+
const palette = paletteTag?.type === "list" && paletteTag.value.type === "string" ? paletteTag.value.value : this.compounds(paletteTag, "block palette");
|
|
29380
|
+
data2 = new ChunkData();
|
|
29381
|
+
if (palette.length) {
|
|
29382
|
+
const states = palette.map((entry) => this.block(entry));
|
|
29383
|
+
const indices = this.unpack(modern ? modern.data : section.BlockStates, states.length, !!modern, dataVersion);
|
|
29384
|
+
for (let index = 0; index < 4096; index++) {
|
|
29385
|
+
const state = states[indices[index]];
|
|
29386
|
+
if (!state) throw new MineRenderError(`Anvil palette index ${indices[index]} is out of range`);
|
|
29387
|
+
if (!ChunkData.isAir(state)) data2.set(index, state);
|
|
29388
|
+
}
|
|
29389
|
+
} else if (modern || section.Palette || section.BlockStates) {
|
|
29390
|
+
throw new MineRenderError("Anvil section has block states without a palette");
|
|
29372
29391
|
}
|
|
29373
|
-
} else if (modern || section.Palette || section.BlockStates) {
|
|
29374
|
-
throw new MineRenderError("Anvil section has block states without a palette");
|
|
29375
29392
|
}
|
|
29376
29393
|
if (chunk.sections.some((section2) => section2.y === y)) throw new MineRenderError(`Duplicate Anvil section Y ${y}`);
|
|
29377
29394
|
chunk.sections.push({ y, data: data2 });
|
|
@@ -29399,6 +29416,33 @@ var AnvilParser = class {
|
|
|
29399
29416
|
}
|
|
29400
29417
|
return chunk;
|
|
29401
29418
|
}
|
|
29419
|
+
static numericSection(section, y, options, states) {
|
|
29420
|
+
const bytes = (name, length, optional = false) => {
|
|
29421
|
+
const tag = section[name];
|
|
29422
|
+
if (!tag && optional) return void 0;
|
|
29423
|
+
if (tag?.type !== "byteArray" || !Array.isArray(tag.value) || tag.value.length !== length) {
|
|
29424
|
+
throw new MineRenderError(`Anvil section ${y} ${name} must contain ${length} bytes`);
|
|
29425
|
+
}
|
|
29426
|
+
return tag.value;
|
|
29427
|
+
};
|
|
29428
|
+
const ids = bytes("Blocks", 4096);
|
|
29429
|
+
const metadata = bytes("Data", 2048, true);
|
|
29430
|
+
const extra = bytes("Add", 2048, true);
|
|
29431
|
+
const data = new ChunkData();
|
|
29432
|
+
for (let index = 0; index < 4096; index++) {
|
|
29433
|
+
const shift = (index & 1) * 4;
|
|
29434
|
+
const id = ids[index] & 255 | ((extra?.[index >> 1] ?? 0) >> shift & 15) << 8;
|
|
29435
|
+
const value = (metadata?.[index >> 1] ?? 0) >> shift & 15;
|
|
29436
|
+
const key = id * 16 + value;
|
|
29437
|
+
if (!states.has(key)) states.set(key, resolveLegacyBlock(id, value, options.legacyMappings, options.lenient));
|
|
29438
|
+
const block = states.get(key);
|
|
29439
|
+
if (!block && !options.lenient) {
|
|
29440
|
+
throw new MineRenderError(`Unsupported legacy block ${id}:${value} at Anvil section ${y} index ${index}`);
|
|
29441
|
+
}
|
|
29442
|
+
if (block && !ChunkData.isAir(block)) data.set(index, block);
|
|
29443
|
+
}
|
|
29444
|
+
return data;
|
|
29445
|
+
}
|
|
29402
29446
|
static compounds(tag, name) {
|
|
29403
29447
|
if (!tag) return [];
|
|
29404
29448
|
if (tag.type !== "list" || tag.value.type !== "compound" && tag.value.value.length !== 0) {
|
|
@@ -29481,7 +29525,7 @@ var AnvilWorldSource = class {
|
|
|
29481
29525
|
this.cachedBytes = 0;
|
|
29482
29526
|
this.maxCachedRegions = options.maxCachedRegions ?? 4;
|
|
29483
29527
|
this.maxCachedBytes = options.maxCachedBytes ?? 64 * 1024 * 1024;
|
|
29484
|
-
this.
|
|
29528
|
+
this.parseOptions = { readExternalChunk: options.readExternalChunk, legacyMappings: options.legacyMappings, lenient: options.lenient };
|
|
29485
29529
|
for (const [name, value] of Object.entries({ maxCachedRegions: this.maxCachedRegions, maxCachedBytes: this.maxCachedBytes })) {
|
|
29486
29530
|
if (!Number.isSafeInteger(value) || value < 0) throw new RangeError(`${name} must be a nonnegative safe integer`);
|
|
29487
29531
|
}
|
|
@@ -29496,8 +29540,8 @@ var AnvilWorldSource = class {
|
|
|
29496
29540
|
signal?.throwIfAborted();
|
|
29497
29541
|
if (!data) return void 0;
|
|
29498
29542
|
const chunk = await AnvilParser.parseChunk(data, x - regionX * 32, z - regionZ * 32, {
|
|
29543
|
+
...this.parseOptions,
|
|
29499
29544
|
region: { x: regionX, z: regionZ },
|
|
29500
|
-
readExternalChunk: this.readExternalChunk,
|
|
29501
29545
|
signal
|
|
29502
29546
|
});
|
|
29503
29547
|
signal?.throwIfAborted();
|
|
@@ -30879,6 +30923,7 @@ var WorldStreamer = class {
|
|
|
30879
30923
|
parseSceneDocument,
|
|
30880
30924
|
prefix,
|
|
30881
30925
|
registerNodeEnv,
|
|
30926
|
+
resolveLegacyBlock,
|
|
30882
30927
|
sampleEntityAnimation,
|
|
30883
30928
|
sampleEntityKeyframes,
|
|
30884
30929
|
sampleFluid,
|