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.
@@ -1540,6 +1540,7 @@ var init_ModelMerger = __esm({
1540
1540
  }
1541
1541
  merged.hierarchy = models.map((m) => m.parent).filter((p10) => `${p10}`);
1542
1542
  merged.hierarchy.push(`${merged.parent}`);
1543
+ if (model.components) merged.components = model.components;
1543
1544
  return merged;
1544
1545
  }
1545
1546
  static async collectAllParents(model) {
@@ -1615,10 +1616,10 @@ var init_Models = __esm({
1615
1616
  const preview = this.snapshotContext(key, context);
1616
1617
  const itemKey = new AssetKey(key.namespace, key.path, "items", void 0, key.rootType, ".json", key.root);
1617
1618
  const cacheKey = itemKey.serialize() + this.contextKey(preview);
1618
- const model = await this.PERSISTENT_CACHE.getOrLoad(`item-v3:${AssetLoader.persistentKey(cacheKey)}`, async () => {
1619
+ const model = await this.PERSISTENT_CACHE.getOrLoad(`item-v4:${AssetLoader.persistentKey(cacheKey)}`, async () => {
1619
1620
  const result = await AssetLoader.getFirst([itemKey, key], "json" /* JSON */);
1620
1621
  if (!result) return void 0;
1621
- if (result.key.assetType !== "items") return { ...result.asset, key };
1622
+ if (result.key.assetType !== "items") return { ...result.asset, key, components: preview.components };
1622
1623
  const load = async (selected) => {
1623
1624
  if ("parts" in selected) {
1624
1625
  return { key, parts: await Promise.all(selected.parts.map(load)) };
@@ -1632,7 +1633,7 @@ var init_Models = __esm({
1632
1633
  modelKey.root = key.root;
1633
1634
  const model2 = await this.getRaw(modelKey);
1634
1635
  if (!model2) throw new Error(`Item ${key.toNamespacedString()} references missing model ${selected.model}`);
1635
- return { ...model2, ...selected.special && { special: selected.special }, ...selected.tints && { tints: selected.tints } };
1636
+ return { ...model2, components: preview.components, ...selected.special && { special: selected.special }, ...selected.tints && { tints: selected.tints } };
1636
1637
  };
1637
1638
  return load(this.selectItemModel(result.asset.model, key, preview));
1638
1639
  });
@@ -1690,7 +1691,7 @@ var init_Models = __esm({
1690
1691
  }
1691
1692
  static contextKey(context) {
1692
1693
  const itemReferences = Object.fromEntries(Object.entries(context.itemReferences).map(([id, key]) => [id, key.serialize()]));
1693
- return `|item-v3:${JSON.stringify(this.snapshotJson({ ...context, itemReferences }))}`;
1694
+ return `|item-v4:${JSON.stringify(this.snapshotJson({ ...context, itemReferences }))}`;
1694
1695
  }
1695
1696
  static snapshotJson(value, ancestors = /* @__PURE__ */ new Set()) {
1696
1697
  if (value === null || typeof value === "string" || typeof value === "boolean" || typeof value === "number" && Number.isFinite(value)) return value;
@@ -5670,6 +5671,7 @@ var init_ItemTints = __esm({
5670
5671
  static async get(model, tints) {
5671
5672
  const sources = model.tints;
5672
5673
  if (!sources?.length) return tints;
5674
+ const components = model.components ?? {};
5673
5675
  const colors = { ...tints };
5674
5676
  await Promise.all(sources.map(async (source, index) => {
5675
5677
  if (colors[index] !== void 0) return;
@@ -5684,27 +5686,71 @@ var init_ItemTints = __esm({
5684
5686
  break;
5685
5687
  case "dye":
5686
5688
  case "minecraft:dye":
5689
+ colors[index] = this.colorOrDefault(components["minecraft:dyed_color"], source.default, true);
5690
+ break;
5687
5691
  case "potion":
5688
- case "minecraft:potion":
5692
+ case "minecraft:potion": {
5693
+ const value = typeof components["minecraft:potion_contents"] === "string" ? void 0 : this.componentField(components, "potion_contents", "custom_color");
5694
+ colors[index] = this.colorOrDefault(value, source.default);
5695
+ break;
5696
+ }
5689
5697
  case "map_color":
5690
5698
  case "minecraft:map_color":
5699
+ colors[index] = this.colorOrDefault(components["minecraft:map_color"], source.default);
5700
+ break;
5691
5701
  case "firework":
5692
- case "minecraft:firework":
5702
+ case "minecraft:firework": {
5703
+ const values = this.componentField(components, "firework_explosion", "colors");
5704
+ if (values !== void 0 && !Array.isArray(values)) throw new MineRenderError("Item tint firework_explosion.colors must be an array");
5705
+ if (!values?.length) {
5706
+ colors[index] = this.rgb(source.default);
5707
+ break;
5708
+ }
5709
+ const rgb = values.map((value) => this.componentColor(value));
5710
+ const red = Math.floor(rgb.reduce((sum, color2) => sum + (color2 >> 16 & 255), 0) / rgb.length);
5711
+ const green = Math.floor(rgb.reduce((sum, color2) => sum + (color2 >> 8 & 255), 0) / rgb.length);
5712
+ const blue = Math.floor(rgb.reduce((sum, color2) => sum + (color2 & 255), 0) / rgb.length);
5713
+ colors[index] = red << 16 | green << 8 | blue;
5714
+ break;
5715
+ }
5693
5716
  case "team":
5694
5717
  case "minecraft:team":
5695
- case "custom_model_data":
5696
- case "minecraft:custom_model_data":
5697
5718
  colors[index] = this.rgb(source.default);
5698
5719
  break;
5720
+ case "custom_model_data":
5721
+ case "minecraft:custom_model_data": {
5722
+ const colorIndex = source.index ?? 0;
5723
+ if (!Number.isSafeInteger(colorIndex) || colorIndex < 0) throw new MineRenderError("Item tint custom_model_data index must be a nonnegative integer");
5724
+ const values = this.componentField(components, "custom_model_data", "colors");
5725
+ if (values !== void 0 && !Array.isArray(values)) throw new MineRenderError("Item tint custom_model_data.colors must be an array");
5726
+ colors[index] = this.colorOrDefault(values?.[colorIndex], source.default, true);
5727
+ break;
5728
+ }
5699
5729
  default:
5700
5730
  throw new MineRenderError(`Unsupported item tint source ${source.type}`);
5701
5731
  }
5702
5732
  }));
5703
5733
  return colors;
5704
5734
  }
5735
+ static componentField(components, id, field) {
5736
+ const value = components[`minecraft:${id}`];
5737
+ if (value === void 0) return void 0;
5738
+ if (!value || typeof value !== "object" || Array.isArray(value)) throw new MineRenderError(`Item tint ${id} must be an object`);
5739
+ return value[field];
5740
+ }
5741
+ static colorOrDefault(value, fallback, allowTriple = false) {
5742
+ return value === void 0 ? this.rgb(fallback) : this.componentColor(value, allowTriple);
5743
+ }
5744
+ static componentColor(value, allowTriple = false) {
5745
+ if (typeof value === "number" && Number.isInteger(value) && value >= -2147483648 && value <= 2147483647) return this.rgb(value);
5746
+ if (allowTriple && Array.isArray(value) && value.length === 3 && value.every((channel) => typeof channel === "number" && Number.isFinite(channel))) {
5747
+ return this.rgb(value) & 16777215;
5748
+ }
5749
+ throw new MineRenderError(`Item tint component color must be a packed integer${allowTriple ? " or RGB triple" : ""}`);
5750
+ }
5705
5751
  static rgb(color2) {
5706
5752
  if (!Array.isArray(color2)) return color2 & 16777215;
5707
- const [red, green, blue] = color2.map((channel) => Math.floor(Math.fround(Math.fround(channel) * 255)));
5753
+ const [red, green, blue] = color2.map((channel) => Math.floor(Math.fround(Math.fround(channel) * 255)) & 255);
5708
5754
  return red << 16 | green << 8 | blue;
5709
5755
  }
5710
5756
  };
@@ -10031,7 +10077,7 @@ var GuiObject = class extends SceneObject {
10031
10077
  }
10032
10078
  async createItem(layer, index) {
10033
10079
  const key = typeof layer.item === "string" ? AssetKey.parse("models", layer.item) : layer.item;
10034
- const model = await Models.getMerged(key);
10080
+ const model = await Models.getMerged(key, { ...layer.context, displayContext: "gui" /* GUI */ });
10035
10081
  if (!model) throw new Error(`Could not load GUI item ${key.toNamespacedString()}`);
10036
10082
  const item = new ModelObject(model, {
10037
10083
  displayPosition: "gui" /* GUI */,
@@ -14064,6 +14110,7 @@ var MineRenderScene = class _MineRenderScene extends Scene4 {
14064
14110
  async addSceneObject(asset2, objectSupplier, _options, parent = this) {
14065
14111
  this.dirty = true;
14066
14112
  const obj = await objectSupplier();
14113
+ if (isModelObject(obj)) obj.options.tints = await ItemTints.get(obj.originalModel, obj.options.tints);
14067
14114
  if (obj?.options?.instanceMeshes && asset2.key && asset2.key?.assetType === "models") {
14068
14115
  let key = asset2.key.serialize();
14069
14116
  if (isModelObject(obj)) {
@@ -14097,7 +14144,6 @@ var MineRenderScene = class _MineRenderScene extends Scene4 {
14097
14144
  * @returns The model, or a reference to one placement of a shared model.
14098
14145
  */
14099
14146
  async addModel(model, options, parent = this) {
14100
- options = { ...options, tints: await ItemTints.get(model, options?.tints) };
14101
14147
  return this.addSceneObject(model, () => new ModelObject(model, options), options, parent);
14102
14148
  }
14103
14149
  /**