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.
@@ -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(blockState) {
23242
- const defaults = blockState.key ? await BlockStates.getDefaultState(blockState.key) : void 0;
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 (blockState.variants) {
23247
- const variant = Object.keys(blockState.variants)[0];
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 (blockState.multipart) {
23255
- const condition = blockState.multipart.map((part) => part.when).find((when) => when !== void 0 && Object.values(when).every((value) => typeof value === "string"));
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(blockState, state, choose = this.choose) {
23262
- return this.matching(blockState, state).map(choose);
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(blockState, state) {
23265
+ static matching(blockState2, state) {
23266
23266
  const out = [];
23267
- if (blockState.variants) {
23268
- if (Object.keys(blockState.variants).length === 1 && "" in blockState.variants) {
23269
- out.push(blockState.variants[""]);
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 blockState.variants) {
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(blockState.variants[variantKey]);
23276
+ if (matches) out.push(blockState2.variants[variantKey]);
23277
23277
  }
23278
23278
  }
23279
- } else if (blockState.multipart) {
23280
- for (const part of blockState.multipart) {
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(blockState, options) {
23408
+ constructor(blockState2, options) {
23409
23409
  super(options);
23410
- this.blockState = 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(blockState, options, parent = this) {
26818
- return this.addSceneObject(blockState, () => new BlockObject(blockState, options), options, parent);
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(blockState, properties = {}) {
29031
- if (!blockState.variants || blockState.multipart) return void 0;
29032
- let states = this.states.get(blockState);
29033
- if (!states) this.states.set(blockState, states = /* @__PURE__ */ new Map());
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(blockState, properties));
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(blockState, properties) {
29040
- const state = { ...await BlockStateResolver.defaults(blockState), ...properties };
29041
- const groups = BlockStateResolver.matching(blockState, state);
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(blockState.key, state, model);
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 blockState = await BlockStates.get(AssetKey.parse("blockstates", stored.type));
29761
- const perBlock = !blockState || !this.sectionModels || !!getFluidKind(blockState.key, stored.properties) || !!(blockState.key && BlockEntities.entry(await BlockEntities.getIndex(blockState.key.root), blockState.key.toNamespacedString()));
29762
- if (!perBlock) await this.sectionModels.get(blockState, stored.properties);
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 (!blockState) {
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(blockState, stored.properties);
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(blockState, {
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,