minerender 2.1.0-alpha.82 → 2.1.0-alpha.84

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.
@@ -260,7 +260,8 @@ var init_Caching = __esm({
260
260
  this.entityTextureCache,
261
261
  this.entityAnimationCache,
262
262
  this.blockEntityIndexCache,
263
- this.fontCache
263
+ this.fontCache,
264
+ this.bannerPatternCache
264
265
  ];
265
266
  }
266
267
  /** Invalidates in-memory entries so later lookups reload them. Persisted entries are retained. */
@@ -309,6 +310,7 @@ var init_Caching = __esm({
309
310
  _Caching.entityAnimationCache = _Caching.createAssetCache();
310
311
  _Caching.blockEntityIndexCache = _Caching.createAssetCache();
311
312
  _Caching.fontCache = _Caching.createAssetCache();
313
+ _Caching.bannerPatternCache = _Caching.createAssetCache();
312
314
  Caching = _Caching;
313
315
  }
314
316
  });
@@ -941,6 +943,7 @@ var init_Materials = __esm({
941
943
  material.depthWrite = false;
942
944
  break;
943
945
  case "eyes":
946
+ case "no_outline":
944
947
  material.transparent = true;
945
948
  material.alphaTest = 0;
946
949
  material.depthWrite = false;
@@ -1529,6 +1532,79 @@ var init_AssetParsers = __esm({
1529
1532
  }
1530
1533
  });
1531
1534
 
1535
+ // src/assets/BannerPatterns.ts
1536
+ var DYE_COLORS, BannerPatterns;
1537
+ var init_BannerPatterns = __esm({
1538
+ "src/assets/BannerPatterns.ts"() {
1539
+ init_AssetKey();
1540
+ init_AssetLoader();
1541
+ init_AssetParsers();
1542
+ init_Caching();
1543
+ DYE_COLORS = Object.freeze({
1544
+ white: 16383998,
1545
+ orange: 16351261,
1546
+ magenta: 13061821,
1547
+ light_blue: 3847130,
1548
+ yellow: 16701501,
1549
+ lime: 8439583,
1550
+ pink: 15961002,
1551
+ gray: 4673362,
1552
+ light_gray: 10329495,
1553
+ cyan: 1481884,
1554
+ purple: 8991416,
1555
+ blue: 3949738,
1556
+ brown: 8606770,
1557
+ green: 6192150,
1558
+ red: 11546150,
1559
+ black: 1908001
1560
+ });
1561
+ BannerPatterns = class {
1562
+ /** Lists namespaced pattern IDs from the selected namespace's data directory. */
1563
+ static async getList(namespace = "minecraft", root) {
1564
+ const collect = async (path) => {
1565
+ const prefix2 = path ? `${path}/` : "";
1566
+ const key = new AssetKey(namespace, `${prefix2}_list`, "banner_pattern", void 0, "data", ".json", root);
1567
+ const list2 = await Caching.listAssetCache.get(key.serialize(), () => AssetLoader.get(key, "list" /* LIST */));
1568
+ if (!list2) return [];
1569
+ const files = list2.files.filter((file) => file.endsWith(".json") && file !== "_list.json").map((file) => `${namespace}:${prefix2}${file.slice(0, -5)}`);
1570
+ const children = await Promise.all(list2.directories.map((directory) => collect(`${prefix2}${directory}`)));
1571
+ return [...files, ...children.flat()];
1572
+ };
1573
+ return collect("");
1574
+ }
1575
+ /** Returns the named dye's sRGB value, rejecting unknown colors. */
1576
+ static getColor(color2) {
1577
+ if (typeof color2 !== "string" || !Object.prototype.hasOwnProperty.call(DYE_COLORS, color2)) throw new Error(`Unsupported dye color ${color2}`);
1578
+ return DYE_COLORS[color2];
1579
+ }
1580
+ /** Resolves the first 16 layers of a `banner_patterns` component, preserving their order. */
1581
+ static async getLayers(value, target, root) {
1582
+ if (value === void 0) return [];
1583
+ if (!Array.isArray(value)) throw new Error("banner_patterns must be an array");
1584
+ return Promise.all(value.slice(0, 16).map(async (layer) => {
1585
+ if (!layer || typeof layer !== "object" || Array.isArray(layer)) throw new Error("Each banner pattern requires a pattern and dye color");
1586
+ const color2 = this.getColor(layer.color);
1587
+ let pattern2 = layer.pattern;
1588
+ if (typeof pattern2 === "string") {
1589
+ const id = this.identifier(pattern2);
1590
+ const key = new AssetKey(id.namespace, id.getFullPath(), "banner_pattern", void 0, "data", ".json", root);
1591
+ pattern2 = await Caching.bannerPatternCache.get(key.serialize(), () => AssetLoader.get(key, "json" /* JSON */));
1592
+ if (!pattern2) throw new Error(`Missing banner pattern ${layer.pattern}`);
1593
+ }
1594
+ if (!pattern2 || typeof pattern2 !== "object" || Array.isArray(pattern2) || typeof pattern2.translation_key !== "string") throw new Error("Banner patterns require asset_id and translation_key");
1595
+ const asset2 = this.identifier(pattern2.asset_id);
1596
+ return { color: color2, texture: new AssetKey(asset2.namespace, `${target}/${asset2.getFullPath()}`, "textures", "entity", "assets", ".png", root) };
1597
+ }));
1598
+ }
1599
+ static identifier(value) {
1600
+ if (typeof value !== "string" || !/^(?:[a-z0-9_.-]+:)?[a-z0-9_./-]+$/.test(value)) throw new Error(`Invalid banner-pattern identifier ${value}`);
1601
+ const [namespace, path] = value.includes(":") ? value.split(":") : ["minecraft", value];
1602
+ return new AssetKey(namespace, path);
1603
+ }
1604
+ };
1605
+ }
1606
+ });
1607
+
1532
1608
  // src/assets/Models.ts
1533
1609
  var Models;
1534
1610
  var init_Models = __esm({
@@ -1541,6 +1617,7 @@ var init_Models = __esm({
1541
1617
  init_AssetKey();
1542
1618
  init_AssetParsers();
1543
1619
  init_DisplayPosition();
1620
+ init_BannerPatterns();
1544
1621
  Models = class _Models {
1545
1622
  // opened lazily: touching the store at import time would hit IndexedDB/disk just for loading
1546
1623
  // the library, and would require an EnvProvider before any entry has had a chance to register
@@ -1730,6 +1807,17 @@ var init_Models = __esm({
1730
1807
  if (!node.base || !node.model || typeof node.model !== "object") break;
1731
1808
  const special = node.model;
1732
1809
  switch (special.type) {
1810
+ case "banner":
1811
+ case "minecraft:banner":
1812
+ if (typeof special.color === "string" && Object.prototype.hasOwnProperty.call(DYE_COLORS, special.color)) return { model: node.base, special };
1813
+ break;
1814
+ case "shield":
1815
+ case "minecraft:shield":
1816
+ case "trident":
1817
+ case "minecraft:trident":
1818
+ case "conduit":
1819
+ case "minecraft:conduit":
1820
+ return { model: node.base, special };
1733
1821
  case "shulker_box":
1734
1822
  case "minecraft:shulker_box":
1735
1823
  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))) {
@@ -5440,9 +5528,11 @@ var init_SpecialItems = __esm({
5440
5528
  "src/model/SpecialItems.ts"() {
5441
5529
  init_AssetKey();
5442
5530
  init_Entities();
5531
+ init_BannerPatterns();
5532
+ init_ModelTextures();
5443
5533
  SpecialItems = class {
5444
5534
  /** Resolves the static entity parts drawn by a special item renderer, in model units. */
5445
- static async getParts(special, root) {
5535
+ static async getParts(special, root, components = {}) {
5446
5536
  const texture = (id, directory) => {
5447
5537
  const key = AssetKey.parse("textures", id);
5448
5538
  return new AssetKey(
@@ -5455,13 +5545,77 @@ var init_SpecialItems = __esm({
5455
5545
  root
5456
5546
  );
5457
5547
  };
5458
- const load = async (id, textureKey, transform, rotations = {}) => {
5548
+ const load = async (id, textureKey, transform, rotations = {}, layers = ["main"]) => {
5459
5549
  const key = new AssetKey("minecraft", id, void 0, void 0, "entity-models", ".json", root);
5460
- const model = await Entities.getEntity(key, textureKey, { layer: "main" });
5550
+ const model = await Entities.getEntity(key, textureKey, layers.length === 1 ? { layer: layers[0] } : {
5551
+ layers,
5552
+ textures: textureKey ? Object.fromEntries(layers.map((name) => [name, textureKey])) : void 0
5553
+ });
5461
5554
  if (!model) throw new Error(`Missing entity model minecraft:${id} for special item ${special.type}`);
5462
5555
  return { model, transform, rotations };
5463
5556
  };
5464
5557
  switch (special.type) {
5558
+ case "minecraft:trident":
5559
+ case "trident":
5560
+ case "minecraft:conduit":
5561
+ case "conduit": {
5562
+ const trident = special.type === "trident" || special.type === "minecraft:trident";
5563
+ const part = await load(
5564
+ trident ? "trident" : "conduit",
5565
+ texture(trident ? "trident" : "conduit/base", ""),
5566
+ trident ? new Matrix48().makeScale(1, -1, -1) : new Matrix48().makeTranslation(8, 8, 8),
5567
+ {},
5568
+ trident ? ["main"] : ["shell"]
5569
+ );
5570
+ part.model = { ...part.model, render: "solid", layers: part.model.layers && Object.fromEntries(
5571
+ Object.entries(part.model.layers).map(([name, layer]) => [name, { ...layer, render: "solid" }])
5572
+ ) };
5573
+ return [part];
5574
+ }
5575
+ case "minecraft:banner":
5576
+ case "banner":
5577
+ case "minecraft:shield":
5578
+ case "shield": {
5579
+ const banner = special.type === "banner" || special.type === "minecraft:banner";
5580
+ const color2 = banner ? BannerPatterns.getColor(special.color) : components["minecraft:base_color"] === void 0 ? void 0 : BannerPatterns.getColor(components["minecraft:base_color"]);
5581
+ const patterns = await BannerPatterns.getLayers(components["minecraft:banner_patterns"], banner ? "banner" : "shield", root);
5582
+ const patterned = banner || color2 !== void 0 || patterns.length > 0;
5583
+ const baseTexture = texture(banner ? "banner_base" : patterned ? "shield_base" : "shield_base_nopattern", "");
5584
+ 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);
5585
+ const part = await load(banner ? "standing_banner" : "shield", baseTexture, transform, {}, banner ? ["main", "flag"] : ["main"]);
5586
+ const layers = Object.fromEntries(Object.entries(part.model.layers ?? { main: part.model }).map(([name, layer]) => [name, { ...layer, render: "solid" }]));
5587
+ let overlay2;
5588
+ if (banner) {
5589
+ const flagLayer = layers.flag;
5590
+ const flag = flagLayer?.layer.root.children.flag;
5591
+ if (!flag) throw new Error("Banner entity model is missing its flag layer");
5592
+ overlay2 = { ...flagLayer.layer, root: { ...flagLayer.layer.root, children: {
5593
+ ...flagLayer.layer.root.children,
5594
+ flag: { ...flag, pose: { ...flag.pose, rotation: [-25e-4 * Math.PI, flag.pose.rotation[1], flag.pose.rotation[2]] } }
5595
+ } } };
5596
+ layers.flag = { ...flagLayer, layer: overlay2 };
5597
+ } else {
5598
+ const main = layers.main.layer;
5599
+ const plate = main.root.children.plate;
5600
+ if (!plate) throw new Error("Shield entity model is missing its plate");
5601
+ overlay2 = { ...main, root: { ...main.root, cubes: [], children: { plate } } };
5602
+ }
5603
+ const tints = {};
5604
+ if (patterned) {
5605
+ const draws = [{ texture: texture(`${banner ? "banner" : "shield"}/base`, ""), color: color2 ?? DYE_COLORS.white }, ...patterns];
5606
+ draws.forEach((draw, index) => {
5607
+ const name = index === 0 ? "pattern_base" : `pattern_${index - 1}`;
5608
+ layers[name] = { key: draw.texture, texture: draw.texture, layer: overlay2, render: "no_outline", tint: name };
5609
+ tints[name] = draw.color;
5610
+ });
5611
+ }
5612
+ await Promise.all([...new Map(Object.values(layers).map((layer) => [layer.texture.serialize(), layer.texture])).values()].map(async (key) => {
5613
+ if (!await ModelTextures.preload(key)) throw new Error(`Missing special item texture ${key.toNamespacedString()}`);
5614
+ }));
5615
+ part.model = { ...part.model, ...layers.main, layers };
5616
+ part.tints = tints;
5617
+ return [part];
5618
+ }
5465
5619
  case "minecraft:chest":
5466
5620
  case "chest": {
5467
5621
  const angle = -(special.openness ?? 0) * Math.PI / 2;
@@ -5756,12 +5910,12 @@ var init_ModelObject = __esm({
5756
5910
  this.options.tints = await ItemTints.get(this.originalModel, this.options.tints);
5757
5911
  const special = this.originalModel.special;
5758
5912
  if (special) {
5759
- const parts2 = await SpecialItems.getParts(special, this.originalModel.key?.root);
5913
+ const parts2 = await SpecialItems.getParts(special, this.originalModel.key?.root, this.originalModel.components);
5760
5914
  const transform = this.options.displayPosition ? DisplayTransforms.getMatrix(this.originalModel.display, this.options.displayPosition) : new Matrix49();
5761
5915
  transform.multiply(new Matrix49().makeTranslation(-8, -8, -8));
5762
5916
  try {
5763
5917
  for (const part of parts2) {
5764
- const object3 = new EntityObject(part.model, { flip: false, wireframe: this.options.wireframe });
5918
+ const object3 = new EntityObject(part.model, { flip: false, wireframe: this.options.wireframe, tints: part.tints });
5765
5919
  object3.matrix.copy(transform).multiply(part.transform);
5766
5920
  object3.matrixWorldNeedsUpdate = true;
5767
5921
  object3.matrixAutoUpdate = false;
@@ -6385,6 +6539,7 @@ function shutdown() {
6385
6539
  init_AssetKey();
6386
6540
  init_AssetLoader();
6387
6541
  init_Assets();
6542
+ init_BannerPatterns();
6388
6543
 
6389
6544
  // src/assets/BlockEntities.ts
6390
6545
  init_AssetKey();
@@ -16797,6 +16952,7 @@ export {
16797
16952
  Axis,
16798
16953
  BUILTIN_ENTITY,
16799
16954
  BUILTIN_GENERATED,
16955
+ BannerPatterns,
16800
16956
  BasicAssetKey,
16801
16957
  BatchedExecutor,
16802
16958
  BlockEntities,
@@ -16821,6 +16977,7 @@ export {
16821
16977
  DEFAULT_ROOT,
16822
16978
  DEFAULT_UV,
16823
16979
  DISPLAY_POSITIONS,
16980
+ DYE_COLORS,
16824
16981
  DefaultBlockStates,
16825
16982
  DisplayPosition,
16826
16983
  DisplayTransforms,