minerender 2.1.0-alpha.82 → 2.1.0-alpha.83

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.
@@ -300,6 +300,9 @@ var init_Caching = __esm({
300
300
  static {
301
301
  this.fontCache = _Caching.createAssetCache();
302
302
  }
303
+ static {
304
+ this.bannerPatternCache = _Caching.createAssetCache();
305
+ }
303
306
  static createAssetCache() {
304
307
  return Caches.builder().expireAfterWrite(Time.minutes(10)).expireAfterAccess(Time.minutes(5)).expirationInterval(Time.seconds(30)).buildAsync();
305
308
  }
@@ -327,7 +330,8 @@ var init_Caching = __esm({
327
330
  this.entityTextureCache,
328
331
  this.entityAnimationCache,
329
332
  this.blockEntityIndexCache,
330
- this.fontCache
333
+ this.fontCache,
334
+ this.bannerPatternCache
331
335
  ];
332
336
  }
333
337
  /** Invalidates in-memory entries so later lookups reload them. Persisted entries are retained. */
@@ -991,6 +995,7 @@ var init_Materials = __esm({
991
995
  material.depthWrite = false;
992
996
  break;
993
997
  case "eyes":
998
+ case "no_outline":
994
999
  material.transparent = true;
995
1000
  material.alphaTest = 0;
996
1001
  material.depthWrite = false;
@@ -1579,6 +1584,79 @@ var init_AssetParsers = __esm({
1579
1584
  }
1580
1585
  });
1581
1586
 
1587
+ // src/assets/BannerPatterns.ts
1588
+ var DYE_COLORS, BannerPatterns;
1589
+ var init_BannerPatterns = __esm({
1590
+ "src/assets/BannerPatterns.ts"() {
1591
+ init_AssetKey();
1592
+ init_AssetLoader();
1593
+ init_AssetParsers();
1594
+ init_Caching();
1595
+ DYE_COLORS = Object.freeze({
1596
+ white: 16383998,
1597
+ orange: 16351261,
1598
+ magenta: 13061821,
1599
+ light_blue: 3847130,
1600
+ yellow: 16701501,
1601
+ lime: 8439583,
1602
+ pink: 15961002,
1603
+ gray: 4673362,
1604
+ light_gray: 10329495,
1605
+ cyan: 1481884,
1606
+ purple: 8991416,
1607
+ blue: 3949738,
1608
+ brown: 8606770,
1609
+ green: 6192150,
1610
+ red: 11546150,
1611
+ black: 1908001
1612
+ });
1613
+ BannerPatterns = class {
1614
+ /** Lists namespaced pattern IDs from the selected namespace's data directory. */
1615
+ static async getList(namespace = "minecraft", root) {
1616
+ const collect = async (path) => {
1617
+ const prefix2 = path ? `${path}/` : "";
1618
+ const key = new AssetKey(namespace, `${prefix2}_list`, "banner_pattern", void 0, "data", ".json", root);
1619
+ const list2 = await Caching.listAssetCache.get(key.serialize(), () => AssetLoader.get(key, "list" /* LIST */));
1620
+ if (!list2) return [];
1621
+ const files = list2.files.filter((file) => file.endsWith(".json") && file !== "_list.json").map((file) => `${namespace}:${prefix2}${file.slice(0, -5)}`);
1622
+ const children = await Promise.all(list2.directories.map((directory) => collect(`${prefix2}${directory}`)));
1623
+ return [...files, ...children.flat()];
1624
+ };
1625
+ return collect("");
1626
+ }
1627
+ /** Returns the named dye's sRGB value, rejecting unknown colors. */
1628
+ static getColor(color2) {
1629
+ if (typeof color2 !== "string" || !Object.prototype.hasOwnProperty.call(DYE_COLORS, color2)) throw new Error(`Unsupported dye color ${color2}`);
1630
+ return DYE_COLORS[color2];
1631
+ }
1632
+ /** Resolves the first 16 layers of a `banner_patterns` component, preserving their order. */
1633
+ static async getLayers(value, target, root) {
1634
+ if (value === void 0) return [];
1635
+ if (!Array.isArray(value)) throw new Error("banner_patterns must be an array");
1636
+ return Promise.all(value.slice(0, 16).map(async (layer) => {
1637
+ if (!layer || typeof layer !== "object" || Array.isArray(layer)) throw new Error("Each banner pattern requires a pattern and dye color");
1638
+ const color2 = this.getColor(layer.color);
1639
+ let pattern2 = layer.pattern;
1640
+ if (typeof pattern2 === "string") {
1641
+ const id = this.identifier(pattern2);
1642
+ const key = new AssetKey(id.namespace, id.getFullPath(), "banner_pattern", void 0, "data", ".json", root);
1643
+ pattern2 = await Caching.bannerPatternCache.get(key.serialize(), () => AssetLoader.get(key, "json" /* JSON */));
1644
+ if (!pattern2) throw new Error(`Missing banner pattern ${layer.pattern}`);
1645
+ }
1646
+ if (!pattern2 || typeof pattern2 !== "object" || Array.isArray(pattern2) || typeof pattern2.translation_key !== "string") throw new Error("Banner patterns require asset_id and translation_key");
1647
+ const asset2 = this.identifier(pattern2.asset_id);
1648
+ return { color: color2, texture: new AssetKey(asset2.namespace, `${target}/${asset2.getFullPath()}`, "textures", "entity", "assets", ".png", root) };
1649
+ }));
1650
+ }
1651
+ static identifier(value) {
1652
+ if (typeof value !== "string" || !/^(?:[a-z0-9_.-]+:)?[a-z0-9_./-]+$/.test(value)) throw new Error(`Invalid banner-pattern identifier ${value}`);
1653
+ const [namespace, path] = value.includes(":") ? value.split(":") : ["minecraft", value];
1654
+ return new AssetKey(namespace, path);
1655
+ }
1656
+ };
1657
+ }
1658
+ });
1659
+
1582
1660
  // src/assets/Models.ts
1583
1661
  var Models;
1584
1662
  var init_Models = __esm({
@@ -1591,6 +1669,7 @@ var init_Models = __esm({
1591
1669
  init_AssetKey();
1592
1670
  init_AssetParsers();
1593
1671
  init_DisplayPosition();
1672
+ init_BannerPatterns();
1594
1673
  Models = class _Models {
1595
1674
  // opened lazily: touching the store at import time would hit IndexedDB/disk just for loading
1596
1675
  // the library, and would require an EnvProvider before any entry has had a chance to register
@@ -1780,6 +1859,13 @@ var init_Models = __esm({
1780
1859
  if (!node.base || !node.model || typeof node.model !== "object") break;
1781
1860
  const special = node.model;
1782
1861
  switch (special.type) {
1862
+ case "banner":
1863
+ case "minecraft:banner":
1864
+ if (typeof special.color === "string" && Object.prototype.hasOwnProperty.call(DYE_COLORS, special.color)) return { model: node.base, special };
1865
+ break;
1866
+ case "shield":
1867
+ case "minecraft:shield":
1868
+ return { model: node.base, special };
1783
1869
  case "shulker_box":
1784
1870
  case "minecraft:shulker_box":
1785
1871
  if (typeof special.texture === "string" && special.texture && (special.openness === void 0 || typeof special.openness === "number" && Number.isFinite(special.openness)) && (special.orientation === void 0 || ["down", "up", "north", "south", "west", "east"].includes(special.orientation))) {
@@ -5531,9 +5617,11 @@ var init_SpecialItems = __esm({
5531
5617
  "src/model/SpecialItems.ts"() {
5532
5618
  init_AssetKey();
5533
5619
  init_Entities();
5620
+ init_BannerPatterns();
5621
+ init_ModelTextures();
5534
5622
  SpecialItems = class {
5535
5623
  /** Resolves the static entity parts drawn by a special item renderer, in model units. */
5536
- static async getParts(special, root) {
5624
+ static async getParts(special, root, components = {}) {
5537
5625
  const texture = (id, directory) => {
5538
5626
  const key = AssetKey.parse("textures", id);
5539
5627
  return new AssetKey(
@@ -5546,13 +5634,60 @@ var init_SpecialItems = __esm({
5546
5634
  root
5547
5635
  );
5548
5636
  };
5549
- const load = async (id, textureKey, transform, rotations = {}) => {
5637
+ const load = async (id, textureKey, transform, rotations = {}, layers = ["main"]) => {
5550
5638
  const key = new AssetKey("minecraft", id, void 0, void 0, "entity-models", ".json", root);
5551
- const model = await Entities.getEntity(key, textureKey, { layer: "main" });
5639
+ const model = await Entities.getEntity(key, textureKey, layers.length === 1 ? { layer: layers[0] } : {
5640
+ layers,
5641
+ textures: textureKey ? Object.fromEntries(layers.map((name) => [name, textureKey])) : void 0
5642
+ });
5552
5643
  if (!model) throw new Error(`Missing entity model minecraft:${id} for special item ${special.type}`);
5553
5644
  return { model, transform, rotations };
5554
5645
  };
5555
5646
  switch (special.type) {
5647
+ case "minecraft:banner":
5648
+ case "banner":
5649
+ case "minecraft:shield":
5650
+ case "shield": {
5651
+ const banner = special.type === "banner" || special.type === "minecraft:banner";
5652
+ const color2 = banner ? BannerPatterns.getColor(special.color) : components["minecraft:base_color"] === void 0 ? void 0 : BannerPatterns.getColor(components["minecraft:base_color"]);
5653
+ const patterns = await BannerPatterns.getLayers(components["minecraft:banner_patterns"], banner ? "banner" : "shield", root);
5654
+ const patterned = banner || color2 !== void 0 || patterns.length > 0;
5655
+ const baseTexture = texture(banner ? "banner_base" : patterned ? "shield_base" : "shield_base_nopattern", "");
5656
+ const transform = banner ? new Matrix48().makeTranslation(8, 0, 8).multiply(new Matrix48().makeScale(2 / 3, -2 / 3, -2 / 3)) : new Matrix48().makeScale(1, -1, -1);
5657
+ const part = await load(banner ? "standing_banner" : "shield", baseTexture, transform, {}, banner ? ["main", "flag"] : ["main"]);
5658
+ const layers = Object.fromEntries(Object.entries(part.model.layers ?? { main: part.model }).map(([name, layer]) => [name, { ...layer, render: "solid" }]));
5659
+ let overlay2;
5660
+ if (banner) {
5661
+ const flagLayer = layers.flag;
5662
+ const flag = flagLayer?.layer.root.children.flag;
5663
+ if (!flag) throw new Error("Banner entity model is missing its flag layer");
5664
+ overlay2 = { ...flagLayer.layer, root: { ...flagLayer.layer.root, children: {
5665
+ ...flagLayer.layer.root.children,
5666
+ flag: { ...flag, pose: { ...flag.pose, rotation: [-25e-4 * Math.PI, flag.pose.rotation[1], flag.pose.rotation[2]] } }
5667
+ } } };
5668
+ layers.flag = { ...flagLayer, layer: overlay2 };
5669
+ } else {
5670
+ const main = layers.main.layer;
5671
+ const plate = main.root.children.plate;
5672
+ if (!plate) throw new Error("Shield entity model is missing its plate");
5673
+ overlay2 = { ...main, root: { ...main.root, cubes: [], children: { plate } } };
5674
+ }
5675
+ const tints = {};
5676
+ if (patterned) {
5677
+ const draws = [{ texture: texture(`${banner ? "banner" : "shield"}/base`, ""), color: color2 ?? DYE_COLORS.white }, ...patterns];
5678
+ draws.forEach((draw, index) => {
5679
+ const name = index === 0 ? "pattern_base" : `pattern_${index - 1}`;
5680
+ layers[name] = { key: draw.texture, texture: draw.texture, layer: overlay2, render: "no_outline", tint: name };
5681
+ tints[name] = draw.color;
5682
+ });
5683
+ }
5684
+ await Promise.all([...new Map(Object.values(layers).map((layer) => [layer.texture.serialize(), layer.texture])).values()].map(async (key) => {
5685
+ if (!await ModelTextures.preload(key)) throw new Error(`Missing special item texture ${key.toNamespacedString()}`);
5686
+ }));
5687
+ part.model = { ...part.model, ...layers.main, layers };
5688
+ part.tints = tints;
5689
+ return [part];
5690
+ }
5556
5691
  case "minecraft:chest":
5557
5692
  case "chest": {
5558
5693
  const angle = -(special.openness ?? 0) * Math.PI / 2;
@@ -5850,12 +5985,12 @@ var init_ModelObject = __esm({
5850
5985
  this.options.tints = await ItemTints.get(this.originalModel, this.options.tints);
5851
5986
  const special = this.originalModel.special;
5852
5987
  if (special) {
5853
- const parts2 = await SpecialItems.getParts(special, this.originalModel.key?.root);
5988
+ const parts2 = await SpecialItems.getParts(special, this.originalModel.key?.root, this.originalModel.components);
5854
5989
  const transform = this.options.displayPosition ? DisplayTransforms.getMatrix(this.originalModel.display, this.options.displayPosition) : new Matrix49();
5855
5990
  transform.multiply(new Matrix49().makeTranslation(-8, -8, -8));
5856
5991
  try {
5857
5992
  for (const part of parts2) {
5858
- const object3 = new EntityObject(part.model, { flip: false, wireframe: this.options.wireframe });
5993
+ const object3 = new EntityObject(part.model, { flip: false, wireframe: this.options.wireframe, tints: part.tints });
5859
5994
  object3.matrix.copy(transform).multiply(part.transform);
5860
5995
  object3.matrixWorldNeedsUpdate = true;
5861
5996
  object3.matrixAutoUpdate = false;
@@ -6439,6 +6574,7 @@ function shutdown() {
6439
6574
  init_AssetKey();
6440
6575
  init_AssetLoader();
6441
6576
  init_Assets();
6577
+ init_BannerPatterns();
6442
6578
 
6443
6579
  // src/assets/BlockEntities.ts
6444
6580
  init_AssetKey();
@@ -16854,6 +16990,7 @@ export {
16854
16990
  Axis,
16855
16991
  BUILTIN_ENTITY,
16856
16992
  BUILTIN_GENERATED,
16993
+ BannerPatterns,
16857
16994
  BasicAssetKey,
16858
16995
  BatchedExecutor,
16859
16996
  BlockEntities,
@@ -16876,6 +17013,7 @@ export {
16876
17013
  DEFAULT_ROOT,
16877
17014
  DEFAULT_UV,
16878
17015
  DISPLAY_POSITIONS,
17016
+ DYE_COLORS,
16879
17017
  DefaultBlockStates,
16880
17018
  DisplayPosition,
16881
17019
  DisplayTransforms,