minerender 2.1.0-alpha.79 → 2.1.0-alpha.80

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.
@@ -1490,6 +1490,7 @@ var init_ModelMerger = __esm({
1490
1490
  }
1491
1491
  merged.hierarchy = models.map((m) => m.parent).filter((p10) => `${p10}`);
1492
1492
  merged.hierarchy.push(`${merged.parent}`);
1493
+ if (model.components) merged.components = model.components;
1493
1494
  return merged;
1494
1495
  }
1495
1496
  static async collectAllParents(model) {
@@ -1565,10 +1566,10 @@ var init_Models = __esm({
1565
1566
  const preview = this.snapshotContext(key, context);
1566
1567
  const itemKey = new AssetKey(key.namespace, key.path, "items", void 0, key.rootType, ".json", key.root);
1567
1568
  const cacheKey = itemKey.serialize() + this.contextKey(preview);
1568
- const model = await this.PERSISTENT_CACHE.getOrLoad(`item-v3:${AssetLoader.persistentKey(cacheKey)}`, async () => {
1569
+ const model = await this.PERSISTENT_CACHE.getOrLoad(`item-v4:${AssetLoader.persistentKey(cacheKey)}`, async () => {
1569
1570
  const result = await AssetLoader.getFirst([itemKey, key], "json" /* JSON */);
1570
1571
  if (!result) return void 0;
1571
- if (result.key.assetType !== "items") return { ...result.asset, key };
1572
+ if (result.key.assetType !== "items") return { ...result.asset, key, components: preview.components };
1572
1573
  const load = async (selected) => {
1573
1574
  if ("parts" in selected) {
1574
1575
  return { key, parts: await Promise.all(selected.parts.map(load)) };
@@ -1582,7 +1583,7 @@ var init_Models = __esm({
1582
1583
  modelKey.root = key.root;
1583
1584
  const model2 = await this.getRaw(modelKey);
1584
1585
  if (!model2) throw new Error(`Item ${key.toNamespacedString()} references missing model ${selected.model}`);
1585
- return { ...model2, ...selected.special && { special: selected.special }, ...selected.tints && { tints: selected.tints } };
1586
+ return { ...model2, components: preview.components, ...selected.special && { special: selected.special }, ...selected.tints && { tints: selected.tints } };
1586
1587
  };
1587
1588
  return load(this.selectItemModel(result.asset.model, key, preview));
1588
1589
  });
@@ -1640,7 +1641,7 @@ var init_Models = __esm({
1640
1641
  }
1641
1642
  static contextKey(context) {
1642
1643
  const itemReferences = Object.fromEntries(Object.entries(context.itemReferences).map(([id, key]) => [id, key.serialize()]));
1643
- return `|item-v3:${JSON.stringify(this.snapshotJson({ ...context, itemReferences }))}`;
1644
+ return `|item-v4:${JSON.stringify(this.snapshotJson({ ...context, itemReferences }))}`;
1644
1645
  }
1645
1646
  static snapshotJson(value, ancestors = /* @__PURE__ */ new Set()) {
1646
1647
  if (value === null || typeof value === "string" || typeof value === "boolean" || typeof value === "number" && Number.isFinite(value)) return value;
@@ -5579,6 +5580,7 @@ var init_ItemTints = __esm({
5579
5580
  static async get(model, tints) {
5580
5581
  const sources = model.tints;
5581
5582
  if (!sources?.length) return tints;
5583
+ const components = model.components ?? {};
5582
5584
  const colors = { ...tints };
5583
5585
  await Promise.all(sources.map(async (source, index) => {
5584
5586
  if (colors[index] !== void 0) return;
@@ -5593,27 +5595,71 @@ var init_ItemTints = __esm({
5593
5595
  break;
5594
5596
  case "dye":
5595
5597
  case "minecraft:dye":
5598
+ colors[index] = this.colorOrDefault(components["minecraft:dyed_color"], source.default, true);
5599
+ break;
5596
5600
  case "potion":
5597
- case "minecraft:potion":
5601
+ case "minecraft:potion": {
5602
+ const value = typeof components["minecraft:potion_contents"] === "string" ? void 0 : this.componentField(components, "potion_contents", "custom_color");
5603
+ colors[index] = this.colorOrDefault(value, source.default);
5604
+ break;
5605
+ }
5598
5606
  case "map_color":
5599
5607
  case "minecraft:map_color":
5608
+ colors[index] = this.colorOrDefault(components["minecraft:map_color"], source.default);
5609
+ break;
5600
5610
  case "firework":
5601
- case "minecraft:firework":
5611
+ case "minecraft:firework": {
5612
+ const values = this.componentField(components, "firework_explosion", "colors");
5613
+ if (values !== void 0 && !Array.isArray(values)) throw new MineRenderError("Item tint firework_explosion.colors must be an array");
5614
+ if (!values?.length) {
5615
+ colors[index] = this.rgb(source.default);
5616
+ break;
5617
+ }
5618
+ const rgb = values.map((value) => this.componentColor(value));
5619
+ const red = Math.floor(rgb.reduce((sum, color2) => sum + (color2 >> 16 & 255), 0) / rgb.length);
5620
+ const green = Math.floor(rgb.reduce((sum, color2) => sum + (color2 >> 8 & 255), 0) / rgb.length);
5621
+ const blue = Math.floor(rgb.reduce((sum, color2) => sum + (color2 & 255), 0) / rgb.length);
5622
+ colors[index] = red << 16 | green << 8 | blue;
5623
+ break;
5624
+ }
5602
5625
  case "team":
5603
5626
  case "minecraft:team":
5604
- case "custom_model_data":
5605
- case "minecraft:custom_model_data":
5606
5627
  colors[index] = this.rgb(source.default);
5607
5628
  break;
5629
+ case "custom_model_data":
5630
+ case "minecraft:custom_model_data": {
5631
+ const colorIndex = source.index ?? 0;
5632
+ if (!Number.isSafeInteger(colorIndex) || colorIndex < 0) throw new MineRenderError("Item tint custom_model_data index must be a nonnegative integer");
5633
+ const values = this.componentField(components, "custom_model_data", "colors");
5634
+ if (values !== void 0 && !Array.isArray(values)) throw new MineRenderError("Item tint custom_model_data.colors must be an array");
5635
+ colors[index] = this.colorOrDefault(values?.[colorIndex], source.default, true);
5636
+ break;
5637
+ }
5608
5638
  default:
5609
5639
  throw new MineRenderError(`Unsupported item tint source ${source.type}`);
5610
5640
  }
5611
5641
  }));
5612
5642
  return colors;
5613
5643
  }
5644
+ static componentField(components, id, field) {
5645
+ const value = components[`minecraft:${id}`];
5646
+ if (value === void 0) return void 0;
5647
+ if (!value || typeof value !== "object" || Array.isArray(value)) throw new MineRenderError(`Item tint ${id} must be an object`);
5648
+ return value[field];
5649
+ }
5650
+ static colorOrDefault(value, fallback, allowTriple = false) {
5651
+ return value === void 0 ? this.rgb(fallback) : this.componentColor(value, allowTriple);
5652
+ }
5653
+ static componentColor(value, allowTriple = false) {
5654
+ if (typeof value === "number" && Number.isInteger(value) && value >= -2147483648 && value <= 2147483647) return this.rgb(value);
5655
+ if (allowTriple && Array.isArray(value) && value.length === 3 && value.every((channel) => typeof channel === "number" && Number.isFinite(channel))) {
5656
+ return this.rgb(value) & 16777215;
5657
+ }
5658
+ throw new MineRenderError(`Item tint component color must be a packed integer${allowTriple ? " or RGB triple" : ""}`);
5659
+ }
5614
5660
  static rgb(color2) {
5615
5661
  if (!Array.isArray(color2)) return color2 & 16777215;
5616
- const [red, green, blue] = color2.map((channel) => Math.floor(Math.fround(Math.fround(channel) * 255)));
5662
+ const [red, green, blue] = color2.map((channel) => Math.floor(Math.fround(Math.fround(channel) * 255)) & 255);
5617
5663
  return red << 16 | green << 8 | blue;
5618
5664
  }
5619
5665
  };
@@ -9977,7 +10023,7 @@ var GuiObject = class extends SceneObject {
9977
10023
  }
9978
10024
  async createItem(layer, index) {
9979
10025
  const key = typeof layer.item === "string" ? AssetKey.parse("models", layer.item) : layer.item;
9980
- const model = await Models.getMerged(key);
10026
+ const model = await Models.getMerged(key, { ...layer.context, displayContext: "gui" /* GUI */ });
9981
10027
  if (!model) throw new Error(`Could not load GUI item ${key.toNamespacedString()}`);
9982
10028
  const item = new ModelObject(model, {
9983
10029
  displayPosition: "gui" /* GUI */,
@@ -14006,6 +14052,7 @@ var _MineRenderScene = class _MineRenderScene extends Scene4 {
14006
14052
  async addSceneObject(asset2, objectSupplier, _options, parent = this) {
14007
14053
  this.dirty = true;
14008
14054
  const obj = await objectSupplier();
14055
+ if (isModelObject(obj)) obj.options.tints = await ItemTints.get(obj.originalModel, obj.options.tints);
14009
14056
  if (obj?.options?.instanceMeshes && asset2.key && asset2.key?.assetType === "models") {
14010
14057
  let key = asset2.key.serialize();
14011
14058
  if (isModelObject(obj)) {
@@ -14039,7 +14086,6 @@ var _MineRenderScene = class _MineRenderScene extends Scene4 {
14039
14086
  * @returns The model, or a reference to one placement of a shared model.
14040
14087
  */
14041
14088
  async addModel(model, options, parent = this) {
14042
- options = { ...options, tints: await ItemTints.get(model, options?.tints) };
14043
14089
  return this.addSceneObject(model, () => new ModelObject(model, options), options, parent);
14044
14090
  }
14045
14091
  /**