minerender 2.1.0-alpha.88 → 2.1.0-alpha.89
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 -1
- package/dist/browser/index.d.ts +11 -1
- package/dist/browser/index.js +189 -37
- package/dist/browser/index.js.map +1 -1
- package/dist/browser/index.mjs +189 -37
- package/dist/browser/index.mjs.map +1 -1
- package/dist/bundle.js +197 -42
- package/dist/bundle.js.map +1 -1
- package/dist/node/index.d.mts +11 -1
- package/dist/node/index.d.ts +11 -1
- package/dist/node/index.js +190 -37
- package/dist/node/index.js.map +1 -1
- package/dist/node/index.mjs +189 -37
- package/dist/node/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/node/index.mjs
CHANGED
|
@@ -23238,46 +23238,46 @@ function matchesCondition(condition, state) {
|
|
|
23238
23238
|
}
|
|
23239
23239
|
var BlockStateResolver = class {
|
|
23240
23240
|
/** Loads vanilla property defaults, falling back to preview values inferred from the blockstate file. */
|
|
23241
|
-
static async defaults(
|
|
23242
|
-
const defaults =
|
|
23241
|
+
static async defaults(blockState2) {
|
|
23242
|
+
const defaults = blockState2.key ? await BlockStates.getDefaultState(blockState2.key) : void 0;
|
|
23243
23243
|
const state = {};
|
|
23244
23244
|
if (defaults && Object.keys(defaults).length > 0) {
|
|
23245
23245
|
for (const key in defaults) state[key] = defaults[key].default;
|
|
23246
|
-
} else if (
|
|
23247
|
-
const variant = Object.keys(
|
|
23246
|
+
} else if (blockState2.variants) {
|
|
23247
|
+
const variant = Object.keys(blockState2.variants)[0];
|
|
23248
23248
|
if (variant) {
|
|
23249
23249
|
for (const property of variant.split(",")) {
|
|
23250
23250
|
const [key, value] = property.split("=");
|
|
23251
23251
|
state[key] = value;
|
|
23252
23252
|
}
|
|
23253
23253
|
}
|
|
23254
|
-
} else if (
|
|
23255
|
-
const condition =
|
|
23254
|
+
} else if (blockState2.multipart) {
|
|
23255
|
+
const condition = blockState2.multipart.map((part) => part.when).find((when) => when !== void 0 && Object.values(when).every((value) => typeof value === "string"));
|
|
23256
23256
|
for (const [key, value] of Object.entries(condition ?? {})) state[key] = value.split("|")[0];
|
|
23257
23257
|
}
|
|
23258
23258
|
return state;
|
|
23259
23259
|
}
|
|
23260
23260
|
/** Selects matching models. Supply `choose` to control selection within each alternatives array. */
|
|
23261
|
-
static select(
|
|
23262
|
-
return this.matching(
|
|
23261
|
+
static select(blockState2, state, choose = this.choose) {
|
|
23262
|
+
return this.matching(blockState2, state).map(choose);
|
|
23263
23263
|
}
|
|
23264
23264
|
/** Returns matching model groups before choosing weighted alternatives. */
|
|
23265
|
-
static matching(
|
|
23265
|
+
static matching(blockState2, state) {
|
|
23266
23266
|
const out = [];
|
|
23267
|
-
if (
|
|
23268
|
-
if (Object.keys(
|
|
23269
|
-
out.push(
|
|
23267
|
+
if (blockState2.variants) {
|
|
23268
|
+
if (Object.keys(blockState2.variants).length === 1 && "" in blockState2.variants) {
|
|
23269
|
+
out.push(blockState2.variants[""]);
|
|
23270
23270
|
} else {
|
|
23271
|
-
for (const variantKey in
|
|
23271
|
+
for (const variantKey in blockState2.variants) {
|
|
23272
23272
|
const matches = variantKey.split(",").every((property) => {
|
|
23273
23273
|
const [key, value] = property.split("=");
|
|
23274
23274
|
return `${state[key]}` === `${value}`;
|
|
23275
23275
|
});
|
|
23276
|
-
if (matches) out.push(
|
|
23276
|
+
if (matches) out.push(blockState2.variants[variantKey]);
|
|
23277
23277
|
}
|
|
23278
23278
|
}
|
|
23279
|
-
} else if (
|
|
23280
|
-
for (const part of
|
|
23279
|
+
} else if (blockState2.multipart) {
|
|
23280
|
+
for (const part of blockState2.multipart) {
|
|
23281
23281
|
if (part.apply && (!part.when || matchesCondition(part.when, state))) {
|
|
23282
23282
|
out.push(part.apply);
|
|
23283
23283
|
}
|
|
@@ -23405,9 +23405,9 @@ init_ModelCulling();
|
|
|
23405
23405
|
init_FluidGeometry();
|
|
23406
23406
|
init_Entities();
|
|
23407
23407
|
var BlockObject = class _BlockObject extends SceneObject {
|
|
23408
|
-
constructor(
|
|
23408
|
+
constructor(blockState2, options) {
|
|
23409
23409
|
super(options);
|
|
23410
|
-
this.blockState =
|
|
23410
|
+
this.blockState = blockState2;
|
|
23411
23411
|
this.isBlockObject = true;
|
|
23412
23412
|
this._previousState = {};
|
|
23413
23413
|
this._state = {};
|
|
@@ -25587,6 +25587,157 @@ function compoundList(tags, name) {
|
|
|
25587
25587
|
throw new MineRenderError(`Schematic ${name} must be a compound list`);
|
|
25588
25588
|
}
|
|
25589
25589
|
|
|
25590
|
+
// src/model/multiblock/SpongeSchematicParser.ts
|
|
25591
|
+
init_MineRenderError();
|
|
25592
|
+
var SpongeSchematicParser = class {
|
|
25593
|
+
/**
|
|
25594
|
+
* Parses decoded NBT with a local block palette, omitting air blocks.
|
|
25595
|
+
* Applies Offset to block and entity positions; size remains the source dimensions.
|
|
25596
|
+
* Biomes and metadata are not imported, and DataVersion does not trigger migration.
|
|
25597
|
+
*/
|
|
25598
|
+
static async parse(nbt) {
|
|
25599
|
+
const tags = nbt.value.Schematic === void 0 ? nbt.value : compound(nbt.value.Schematic, "Schematic");
|
|
25600
|
+
const version2 = integer2(tags.Version, "Version");
|
|
25601
|
+
if (version2 !== 2 && version2 !== 3) {
|
|
25602
|
+
throw new MineRenderError(`Unsupported Sponge schematic version ${version2}; expected 2 or 3`);
|
|
25603
|
+
}
|
|
25604
|
+
const dataVersion = integer2(tags.DataVersion, "DataVersion");
|
|
25605
|
+
const size = ["Width", "Height", "Length"].map((name) => {
|
|
25606
|
+
const tag = tags[name];
|
|
25607
|
+
if (tag?.type !== "short" || !Number.isInteger(tag.value) || tag.value < -32768 || tag.value > 65535 || tag.value === 0) {
|
|
25608
|
+
throw new MineRenderError(`Sponge schematic ${name} must be a positive unsigned short`);
|
|
25609
|
+
}
|
|
25610
|
+
return tag.value & 65535;
|
|
25611
|
+
});
|
|
25612
|
+
const offset = tags.Offset === void 0 ? [0, 0, 0] : intPosition(tags.Offset, "Offset");
|
|
25613
|
+
const blocks = [];
|
|
25614
|
+
const container = version2 === 2 ? tags : tags.Blocks === void 0 ? void 0 : compound(tags.Blocks, "Blocks");
|
|
25615
|
+
if (container) {
|
|
25616
|
+
const paletteTag = container.Palette;
|
|
25617
|
+
if (!paletteTag) throw new MineRenderError("Sponge schematic requires a local Palette; global block IDs are not supported");
|
|
25618
|
+
const palette = /* @__PURE__ */ new Map();
|
|
25619
|
+
const paletteMax = version2 === 2 && tags.PaletteMax !== void 0 ? integer2(tags.PaletteMax, "PaletteMax") : void 0;
|
|
25620
|
+
if (paletteMax !== void 0 && paletteMax <= 0) throw new MineRenderError("Sponge schematic PaletteMax must be positive");
|
|
25621
|
+
for (const [state, tag] of Object.entries(compound(paletteTag, "Palette"))) {
|
|
25622
|
+
const id = integer2(tag, "Palette index");
|
|
25623
|
+
if (id < 0 || palette.has(id) || paletteMax !== void 0 && id >= paletteMax) {
|
|
25624
|
+
throw new MineRenderError(`Invalid or duplicate Sponge schematic palette index ${id}`);
|
|
25625
|
+
}
|
|
25626
|
+
palette.set(id, blockState(state));
|
|
25627
|
+
}
|
|
25628
|
+
const [width, height, length] = size;
|
|
25629
|
+
const volume = width * height * length;
|
|
25630
|
+
const data = container[version2 === 2 ? "BlockData" : "Data"];
|
|
25631
|
+
if (data?.type !== "byteArray" || !Array.isArray(data.value) || data.value.length < volume) {
|
|
25632
|
+
throw new MineRenderError(`Sponge schematic block data must contain ${volume} varints`);
|
|
25633
|
+
}
|
|
25634
|
+
const blockEntities = /* @__PURE__ */ new Map();
|
|
25635
|
+
for (const entity of compoundList2(container, "BlockEntities")) {
|
|
25636
|
+
const pos = intPosition(entity.Pos, "BlockEntities Pos");
|
|
25637
|
+
if (pos.some((value2, axis) => value2 < 0 || value2 >= size[axis])) {
|
|
25638
|
+
throw new MineRenderError("Sponge schematic block entity position is outside its dimensions");
|
|
25639
|
+
}
|
|
25640
|
+
const index = pos[0] + pos[2] * width + pos[1] * width * length;
|
|
25641
|
+
if (blockEntities.has(index)) throw new MineRenderError(`Duplicate Sponge schematic block entity at index ${index}`);
|
|
25642
|
+
const value = entityData(entity, version2);
|
|
25643
|
+
for (const [axis, name] of ["x", "y", "z"].entries()) {
|
|
25644
|
+
value[name] = { type: "int", value: pos[axis] + offset[axis] };
|
|
25645
|
+
}
|
|
25646
|
+
blockEntities.set(index, { type: "compound", value });
|
|
25647
|
+
}
|
|
25648
|
+
let cursor = 0;
|
|
25649
|
+
for (let index = 0; index < volume; index++) {
|
|
25650
|
+
let id = 0;
|
|
25651
|
+
for (let shift = 0; ; shift += 7) {
|
|
25652
|
+
const byte = data.value[cursor++];
|
|
25653
|
+
if (!Number.isInteger(byte) || byte < -128 || byte > 255) {
|
|
25654
|
+
throw new MineRenderError(`Invalid or truncated Sponge schematic varint at index ${index}`);
|
|
25655
|
+
}
|
|
25656
|
+
const unsigned = byte & 255;
|
|
25657
|
+
if (shift === 28 && unsigned > 7) {
|
|
25658
|
+
throw new MineRenderError(`Sponge schematic varint exceeds a nonnegative int at index ${index}`);
|
|
25659
|
+
}
|
|
25660
|
+
id += (unsigned & 127) * 2 ** shift;
|
|
25661
|
+
if ((unsigned & 128) === 0) break;
|
|
25662
|
+
}
|
|
25663
|
+
const state = palette.get(id);
|
|
25664
|
+
if (!state) throw new MineRenderError(`Sponge schematic palette index ${id} does not exist`);
|
|
25665
|
+
if (["minecraft:air", "minecraft:cave_air", "minecraft:void_air"].includes(state.type)) continue;
|
|
25666
|
+
blocks.push({
|
|
25667
|
+
type: state.type,
|
|
25668
|
+
properties: { ...state.properties },
|
|
25669
|
+
position: [
|
|
25670
|
+
index % width + offset[0],
|
|
25671
|
+
Math.floor(index / (width * length)) + offset[1],
|
|
25672
|
+
Math.floor(index / width) % length + offset[2]
|
|
25673
|
+
],
|
|
25674
|
+
nbt: blockEntities.get(index)
|
|
25675
|
+
});
|
|
25676
|
+
}
|
|
25677
|
+
if (cursor !== data.value.length) throw new MineRenderError("Sponge schematic block data has trailing bytes");
|
|
25678
|
+
}
|
|
25679
|
+
const entities = compoundList2(tags, "Entities").map((entity) => {
|
|
25680
|
+
const pos = entity.Pos;
|
|
25681
|
+
if (pos?.type !== "list" || pos.value.type !== "double" || pos.value.value.length !== 3 || !pos.value.value.every(Number.isFinite)) {
|
|
25682
|
+
throw new MineRenderError("Sponge schematic entity Pos must contain three doubles");
|
|
25683
|
+
}
|
|
25684
|
+
const position = pos.value.value.map((value2, axis) => value2 + offset[axis]);
|
|
25685
|
+
const value = entityData(entity, version2);
|
|
25686
|
+
value.Pos = { type: "list", value: { type: "double", value: [...position] } };
|
|
25687
|
+
return { position, nbt: { type: "compound", value } };
|
|
25688
|
+
});
|
|
25689
|
+
return { size, blocks, entities, dataVersion };
|
|
25690
|
+
}
|
|
25691
|
+
};
|
|
25692
|
+
function integer2(tag, name) {
|
|
25693
|
+
if (tag?.type !== "int" || !Number.isInteger(tag.value) || tag.value < -2147483648 || tag.value > 2147483647) {
|
|
25694
|
+
throw new MineRenderError(`Sponge schematic ${name} must be an int`);
|
|
25695
|
+
}
|
|
25696
|
+
return tag.value;
|
|
25697
|
+
}
|
|
25698
|
+
function compound(tag, name) {
|
|
25699
|
+
if (tag?.type !== "compound" || !tag.value || typeof tag.value !== "object" || Array.isArray(tag.value)) {
|
|
25700
|
+
throw new MineRenderError(`Sponge schematic ${name} must be a compound`);
|
|
25701
|
+
}
|
|
25702
|
+
return tag.value;
|
|
25703
|
+
}
|
|
25704
|
+
function intPosition(tag, name) {
|
|
25705
|
+
if (tag?.type !== "intArray" || !Array.isArray(tag.value) || tag.value.length !== 3 || !tag.value.every((value) => Number.isInteger(value) && value >= -2147483648 && value <= 2147483647)) {
|
|
25706
|
+
throw new MineRenderError(`Sponge schematic ${name} must contain three ints`);
|
|
25707
|
+
}
|
|
25708
|
+
return [...tag.value];
|
|
25709
|
+
}
|
|
25710
|
+
function compoundList2(tags, name) {
|
|
25711
|
+
const tag = tags[name];
|
|
25712
|
+
if (tag === void 0) return [];
|
|
25713
|
+
if (tag.type === "list" && Array.isArray(tag.value.value)) {
|
|
25714
|
+
if (tag.value.value.length === 0) return [];
|
|
25715
|
+
if (tag.value.type === "compound") return tag.value.value;
|
|
25716
|
+
}
|
|
25717
|
+
throw new MineRenderError(`Sponge schematic ${name} must be a compound list`);
|
|
25718
|
+
}
|
|
25719
|
+
function blockState(state) {
|
|
25720
|
+
const match = /^((?:[a-z0-9_.-]+:)?[a-z0-9_./-]+)(?:\[([^\[\]]*)\])?$/.exec(state);
|
|
25721
|
+
if (!match) throw new MineRenderError(`Invalid Sponge schematic block state ${state}`);
|
|
25722
|
+
const properties = {};
|
|
25723
|
+
if (match[2]) {
|
|
25724
|
+
for (const entry of match[2].split(",")) {
|
|
25725
|
+
const pair = /^([a-z0-9_]+)=([^\s=,\[\]]+)$/.exec(entry);
|
|
25726
|
+
if (!pair || Object.prototype.hasOwnProperty.call(properties, pair[1])) throw new MineRenderError(`Invalid Sponge schematic block state ${state}`);
|
|
25727
|
+
Object.defineProperty(properties, pair[1], { value: pair[2], enumerable: true, writable: true, configurable: true });
|
|
25728
|
+
}
|
|
25729
|
+
}
|
|
25730
|
+
return { type: match[1].includes(":") ? match[1] : `minecraft:${match[1]}`, properties };
|
|
25731
|
+
}
|
|
25732
|
+
function entityData(entity, version2) {
|
|
25733
|
+
const id = entity.Id;
|
|
25734
|
+
if (id?.type !== "string" || !id.value) throw new MineRenderError("Sponge schematic entity Id must be a nonempty string");
|
|
25735
|
+
const { Id, Pos, ...extra } = entity;
|
|
25736
|
+
const value = version2 === 2 ? extra : entity.Data === void 0 ? {} : { ...compound(entity.Data, "entity Data") };
|
|
25737
|
+
value.id = { type: "string", value: id.value.includes(":") ? id.value : `minecraft:${id.value}` };
|
|
25738
|
+
return value;
|
|
25739
|
+
}
|
|
25740
|
+
|
|
25590
25741
|
// src/model/multiblock/StructureParser.ts
|
|
25591
25742
|
init_MineRenderError();
|
|
25592
25743
|
var StructureParser = class {
|
|
@@ -26814,8 +26965,8 @@ var MineRenderScene = class _MineRenderScene extends Scene4 {
|
|
|
26814
26965
|
* Set `options.initialState` to choose block properties such as `facing` or `axis`.
|
|
26815
26966
|
* Use the returned object's `setPosition` method to move all of its model parts.
|
|
26816
26967
|
*/
|
|
26817
|
-
async addBlock(
|
|
26818
|
-
return this.addSceneObject(
|
|
26968
|
+
async addBlock(blockState2, options, parent = this) {
|
|
26969
|
+
return this.addSceneObject(blockState2, () => new BlockObject(blockState2, options), options, parent);
|
|
26819
26970
|
}
|
|
26820
26971
|
/**
|
|
26821
26972
|
* Loads a skin and adds an initialized player model.
|
|
@@ -29027,18 +29178,18 @@ var SectionModels = class {
|
|
|
29027
29178
|
if (!Number.isInteger(maxAtlasSize) || maxAtlasSize < 1) throw new RangeError("maxAtlasSize must be a positive integer");
|
|
29028
29179
|
}
|
|
29029
29180
|
/** Returns a cube template, or `undefined` when the block requires an individual render object. */
|
|
29030
|
-
async get(
|
|
29031
|
-
if (!
|
|
29032
|
-
let states = this.states.get(
|
|
29033
|
-
if (!states) this.states.set(
|
|
29181
|
+
async get(blockState2, properties = {}) {
|
|
29182
|
+
if (!blockState2.variants || blockState2.multipart) return void 0;
|
|
29183
|
+
let states = this.states.get(blockState2);
|
|
29184
|
+
if (!states) this.states.set(blockState2, states = /* @__PURE__ */ new Map());
|
|
29034
29185
|
const key = JSON.stringify(Object.entries(properties).sort(([a], [b]) => a.localeCompare(b)));
|
|
29035
|
-
const prepared = await cached(states, key, () => this.prepare(
|
|
29186
|
+
const prepared = await cached(states, key, () => this.prepare(blockState2, properties));
|
|
29036
29187
|
if (!prepared) return void 0;
|
|
29037
29188
|
return prepared.templates.get(BlockStateResolver.choose(prepared.variants));
|
|
29038
29189
|
}
|
|
29039
|
-
async prepare(
|
|
29040
|
-
const state = { ...await BlockStateResolver.defaults(
|
|
29041
|
-
const groups = BlockStateResolver.matching(
|
|
29190
|
+
async prepare(blockState2, properties) {
|
|
29191
|
+
const state = { ...await BlockStateResolver.defaults(blockState2), ...properties };
|
|
29192
|
+
const groups = BlockStateResolver.matching(blockState2, state);
|
|
29042
29193
|
if (groups.length !== 1) return void 0;
|
|
29043
29194
|
const variants = groups[0];
|
|
29044
29195
|
const choices = Array.isArray(variants) ? variants : [variants];
|
|
@@ -29050,7 +29201,7 @@ var SectionModels = class {
|
|
|
29050
29201
|
const atlas = await UVMapper.getAtlas(model);
|
|
29051
29202
|
const rotation = BlockStateResolver.rotation(variant);
|
|
29052
29203
|
if (!atlas || atlas.hasAnimation || !ModelCulling.isOpaqueFullCube(atlas) || atlas.image.width > this.maxAtlasSize || atlas.image.height > this.maxAtlasSize || ModelCulling.toLocalMask(63, rotation) !== 63) return void 0;
|
|
29053
|
-
const tints = await BlockTints.get(
|
|
29204
|
+
const tints = await BlockTints.get(blockState2.key, state, model);
|
|
29054
29205
|
let models = this.models.get(model);
|
|
29055
29206
|
if (!models) this.models.set(model, models = /* @__PURE__ */ new Map());
|
|
29056
29207
|
const key = JSON.stringify([rotation.x, rotation.y, rotation.z, variant.uvlock, tints]);
|
|
@@ -29757,10 +29908,10 @@ var Chunk = class _Chunk {
|
|
|
29757
29908
|
if (resolutions.has(key)) continue;
|
|
29758
29909
|
const stored = { type: block.type, properties: block.properties ? { ...block.properties } : void 0 };
|
|
29759
29910
|
const resolved = (async () => {
|
|
29760
|
-
const
|
|
29761
|
-
const perBlock = !
|
|
29762
|
-
if (!perBlock) await this.sectionModels.get(
|
|
29763
|
-
return { blockState, perBlock };
|
|
29911
|
+
const blockState2 = await BlockStates.get(AssetKey.parse("blockstates", stored.type));
|
|
29912
|
+
const perBlock = !blockState2 || !this.sectionModels || !!getFluidKind(blockState2.key, stored.properties) || !!(blockState2.key && BlockEntities.entry(await BlockEntities.getIndex(blockState2.key.root), blockState2.key.toNamespacedString()));
|
|
29913
|
+
if (!perBlock) await this.sectionModels.get(blockState2, stored.properties);
|
|
29914
|
+
return { blockState: blockState2, perBlock };
|
|
29764
29915
|
})();
|
|
29765
29916
|
resolutions.set(key, resolved);
|
|
29766
29917
|
void resolved.catch(() => void 0);
|
|
@@ -29785,17 +29936,17 @@ var Chunk = class _Chunk {
|
|
|
29785
29936
|
if (!readBlock) continue;
|
|
29786
29937
|
const stored = readBlock();
|
|
29787
29938
|
const key = ChunkData.paletteKey(stored);
|
|
29788
|
-
const { blockState, perBlock } = await resolutions.get(key);
|
|
29789
|
-
if (!
|
|
29939
|
+
const { blockState: blockState2, perBlock } = await resolutions.get(key);
|
|
29940
|
+
if (!blockState2) {
|
|
29790
29941
|
this.data.set(index, void 0);
|
|
29791
29942
|
continue;
|
|
29792
29943
|
}
|
|
29793
|
-
const template = perBlock ? void 0 : await this.sectionModels.get(
|
|
29944
|
+
const template = perBlock ? void 0 : await this.sectionModels.get(blockState2, stored.properties);
|
|
29794
29945
|
if (template) {
|
|
29795
29946
|
this.sectionBlocks.set(index, { index, template, cullMask: 0 });
|
|
29796
29947
|
this.meshDirty = true;
|
|
29797
29948
|
} else {
|
|
29798
|
-
object3 = await this.scene.addBlock(
|
|
29949
|
+
object3 = await this.scene.addBlock(blockState2, {
|
|
29799
29950
|
mergeMeshes: true,
|
|
29800
29951
|
instanceMeshes: true,
|
|
29801
29952
|
maxInstanceCount: 2e3,
|
|
@@ -30201,6 +30352,7 @@ export {
|
|
|
30201
30352
|
SkinTextures,
|
|
30202
30353
|
Skins,
|
|
30203
30354
|
SpecialItems,
|
|
30355
|
+
SpongeSchematicParser,
|
|
30204
30356
|
StructureParser,
|
|
30205
30357
|
TextureAtlas,
|
|
30206
30358
|
TextureLoader,
|