minerender 2.1.0-beta.6 → 2.1.0-beta.8

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.
Files changed (128) hide show
  1. package/README.md +10 -1
  2. package/dist/browser/esm/Materials.mjs +3 -1
  3. package/dist/browser/esm/Materials.mjs.map +1 -1
  4. package/dist/browser/esm/Ticker.mjs +3 -1
  5. package/dist/browser/esm/Ticker.mjs.map +1 -1
  6. package/dist/browser/esm/UVMapper.mjs +9 -9
  7. package/dist/browser/esm/UVMapper.mjs.map +1 -1
  8. package/dist/browser/esm/armor/Armor.mjs +84 -0
  9. package/dist/browser/esm/armor/Armor.mjs.map +1 -0
  10. package/dist/browser/esm/armor/index.mjs +3 -0
  11. package/dist/browser/esm/armor/index.mjs.map +1 -0
  12. package/dist/browser/esm/assets/AssetDefaults.mjs +8 -0
  13. package/dist/browser/esm/assets/AssetDefaults.mjs.map +1 -0
  14. package/dist/browser/esm/assets/AssetKey.mjs +1 -1
  15. package/dist/browser/esm/assets/AssetKey.mjs.map +1 -1
  16. package/dist/browser/esm/assets/AssetLoader.mjs +5 -5
  17. package/dist/browser/esm/assets/AssetLoader.mjs.map +1 -1
  18. package/dist/browser/esm/assets/Assets.mjs +1 -5
  19. package/dist/browser/esm/assets/Assets.mjs.map +1 -1
  20. package/dist/browser/esm/assets/BlockEntities.mjs +5 -1
  21. package/dist/browser/esm/assets/BlockEntities.mjs.map +1 -1
  22. package/dist/browser/esm/assets/BlockStates.mjs +1 -1
  23. package/dist/browser/esm/assets/BlockStates.mjs.map +1 -1
  24. package/dist/browser/esm/assets/Entities.mjs +40 -12
  25. package/dist/browser/esm/assets/Entities.mjs.map +1 -1
  26. package/dist/browser/esm/assets/MineRenderData.mjs +8 -17
  27. package/dist/browser/esm/assets/MineRenderData.mjs.map +1 -1
  28. package/dist/browser/esm/assets/ModelTextures.mjs +13 -7
  29. package/dist/browser/esm/assets/ModelTextures.mjs.map +1 -1
  30. package/dist/browser/esm/assets/Models.mjs +1 -1
  31. package/dist/browser/esm/assets/Models.mjs.map +1 -1
  32. package/dist/browser/esm/assets/_fonts/Unihex.mjs +5 -3
  33. package/dist/browser/esm/assets/_fonts/Unihex.mjs.map +1 -1
  34. package/dist/browser/esm/assets/_versions/DatasetVersions.mjs +22 -0
  35. package/dist/browser/esm/assets/_versions/DatasetVersions.mjs.map +1 -0
  36. package/dist/browser/esm/assets/index.mjs +1 -0
  37. package/dist/browser/esm/assets/index.mjs.map +1 -1
  38. package/dist/browser/esm/assets/source/HostedAssetSource.mjs +7 -8
  39. package/dist/browser/esm/assets/source/HostedAssetSource.mjs.map +1 -1
  40. package/dist/browser/esm/cache/Caching.mjs +8 -0
  41. package/dist/browser/esm/cache/Caching.mjs.map +1 -1
  42. package/dist/browser/esm/entity/scene/EntityObject.mjs +31 -5
  43. package/dist/browser/esm/entity/scene/EntityObject.mjs.map +1 -1
  44. package/dist/browser/esm/env/browser/BrowserCache.mjs +3 -3
  45. package/dist/browser/esm/env/browser/BrowserCache.mjs.map +1 -1
  46. package/dist/browser/esm/env/browser/BrowserEnv.mjs +11 -4
  47. package/dist/browser/esm/env/browser/BrowserEnv.mjs.map +1 -1
  48. package/dist/browser/esm/image/ImageLoader.mjs +3 -3
  49. package/dist/browser/esm/image/ImageLoader.mjs.map +1 -1
  50. package/dist/browser/esm/index.browser.d.mts +191 -22
  51. package/dist/browser/esm/index.browser.mjs.map +1 -1
  52. package/dist/browser/esm/index.mjs +1 -0
  53. package/dist/browser/esm/index.mjs.map +1 -1
  54. package/dist/browser/esm/inspector/SceneInspector.mjs +3 -3
  55. package/dist/browser/esm/inspector/SceneInspector.mjs.map +1 -1
  56. package/dist/browser/esm/instance/InstanceManager.mjs +4 -4
  57. package/dist/browser/esm/instance/InstanceManager.mjs.map +1 -1
  58. package/dist/browser/esm/model/ItemGlint.mjs +7 -6
  59. package/dist/browser/esm/model/ItemGlint.mjs.map +1 -1
  60. package/dist/browser/esm/model/block/scene/BlockObject.mjs +19 -6
  61. package/dist/browser/esm/model/block/scene/BlockObject.mjs.map +1 -1
  62. package/dist/browser/esm/model/multiblock/StructureParser.mjs +7 -4
  63. package/dist/browser/esm/model/multiblock/StructureParser.mjs.map +1 -1
  64. package/dist/browser/esm/model/scene/ModelObject.mjs +4 -4
  65. package/dist/browser/esm/model/scene/ModelObject.mjs.map +1 -1
  66. package/dist/browser/esm/nbt/NBTHelper.mjs +5 -2
  67. package/dist/browser/esm/nbt/NBTHelper.mjs.map +1 -1
  68. package/dist/browser/esm/renderer/Renderer.mjs +4 -2
  69. package/dist/browser/esm/renderer/Renderer.mjs.map +1 -1
  70. package/dist/browser/esm/renderer/SceneObject.mjs +0 -6
  71. package/dist/browser/esm/renderer/SceneObject.mjs.map +1 -1
  72. package/dist/browser/esm/request/Requests.mjs +3 -3
  73. package/dist/browser/esm/request/Requests.mjs.map +1 -1
  74. package/dist/browser/esm/scene/SceneDocument.mjs +35 -5
  75. package/dist/browser/esm/scene/SceneDocument.mjs.map +1 -1
  76. package/dist/browser/esm/scene/SceneDocumentLoader.mjs +14 -3
  77. package/dist/browser/esm/scene/SceneDocumentLoader.mjs.map +1 -1
  78. package/dist/browser/esm/skin/SkinGeometries.mjs +4 -1
  79. package/dist/browser/esm/skin/SkinGeometries.mjs.map +1 -1
  80. package/dist/browser/esm/skin/SkinPart.mjs +2 -0
  81. package/dist/browser/esm/skin/SkinPart.mjs.map +1 -1
  82. package/dist/browser/esm/skin/SkinTextureCoordinates.mjs +11 -1
  83. package/dist/browser/esm/skin/SkinTextureCoordinates.mjs.map +1 -1
  84. package/dist/browser/esm/skin/SkinTextures.mjs +1 -1
  85. package/dist/browser/esm/skin/SkinTextures.mjs.map +1 -1
  86. package/dist/browser/esm/skin/Skins.mjs +6 -4
  87. package/dist/browser/esm/skin/Skins.mjs.map +1 -1
  88. package/dist/browser/esm/skin/scene/SkinObject.mjs +119 -7
  89. package/dist/browser/esm/skin/scene/SkinObject.mjs.map +1 -1
  90. package/dist/browser/esm/texture/PalettedTextures.mjs +46 -0
  91. package/dist/browser/esm/texture/PalettedTextures.mjs.map +1 -0
  92. package/dist/browser/esm/texture/TextureLoader.mjs +4 -2
  93. package/dist/browser/esm/texture/TextureLoader.mjs.map +1 -1
  94. package/dist/browser/esm/texture/index.mjs +1 -0
  95. package/dist/browser/esm/texture/index.mjs.map +1 -1
  96. package/dist/browser/esm/util/log.mjs +75 -0
  97. package/dist/browser/esm/util/log.mjs.map +1 -1
  98. package/dist/browser/esm/util/performance.mjs.map +1 -1
  99. package/dist/browser/esm/util/util.mjs +0 -2
  100. package/dist/browser/esm/util/util.mjs.map +1 -1
  101. package/dist/browser/esm/world/Chunk.mjs +70 -38
  102. package/dist/browser/esm/world/Chunk.mjs.map +1 -1
  103. package/dist/browser/esm/world/MineRenderWorld.mjs +187 -60
  104. package/dist/browser/esm/world/MineRenderWorld.mjs.map +1 -1
  105. package/dist/browser/esm/world/SectionMesh.mjs +65 -9
  106. package/dist/browser/esm/world/SectionMesh.mjs.map +1 -1
  107. package/dist/browser/esm/world/SectionModels.mjs +21 -15
  108. package/dist/browser/esm/world/SectionModels.mjs.map +1 -1
  109. package/dist/browser/esm/world/SectionWorker.mjs +8 -2
  110. package/dist/browser/esm/world/SectionWorker.mjs.map +1 -1
  111. package/dist/browser/esm/world/WorldStreamer.mjs +129 -34
  112. package/dist/browser/esm/world/WorldStreamer.mjs.map +1 -1
  113. package/dist/browser/esm/world/_culling/BlockCulling.mjs +1 -1
  114. package/dist/browser/esm/world/_culling/BlockCulling.mjs.map +1 -1
  115. package/dist/browser/esm/world/_entities/WorldEntities.mjs +3 -1
  116. package/dist/browser/esm/world/_entities/WorldEntities.mjs.map +1 -1
  117. package/dist/browser/index.d.ts +191 -22
  118. package/dist/browser/index.js +4461 -3648
  119. package/dist/browser/index.js.map +1 -1
  120. package/dist/bundle.js +13482 -12651
  121. package/dist/bundle.js.map +1 -1
  122. package/dist/node/index.d.mts +179 -21
  123. package/dist/node/index.d.ts +179 -21
  124. package/dist/node/index.js +4495 -3666
  125. package/dist/node/index.js.map +1 -1
  126. package/dist/node/index.mjs +4412 -3586
  127. package/dist/node/index.mjs.map +1 -1
  128. package/package.json +2 -1
@@ -45,15 +45,21 @@ var ModelTextures = class {
45
45
  key.extension += ".mcmeta";
46
46
  }
47
47
  const keyStr = key.serialize();
48
- return Caching.textureMetaCache.get(keyStr, (k) => {
49
- return this.PERSISTENT_META_CACHE.getOrLoad(AssetLoader.persistentKey(keyStr), (k1) => {
50
- return AssetLoader.get(key, AssetParser.META).then((asset) => {
51
- if (asset)
52
- asset.key = key;
53
- return asset;
54
- });
48
+ const meta = await Caching.textureMetaCache.get(keyStr, (k) => {
49
+ return this.PERSISTENT_META_CACHE.getOrLoad(AssetLoader.persistentKey(keyStr), async (k1) => {
50
+ if (AssetLoader.persistentScope === "") {
51
+ const path = key.getFullPath();
52
+ const slash = path.lastIndexOf("/");
53
+ const listKey = new AssetKey(key.namespace, `${path.slice(0, slash + 1)}_list`, "textures", void 0, "assets", ".json", key.root);
54
+ const list = await Caching.listAssetCache.get(listKey.serialize(), () => AssetLoader.get(listKey, AssetParser.LIST)).catch(() => void 0);
55
+ if (list && !list.files.includes(`${path.slice(slash + 1)}${key.extension}`)) return Caching.MISSING;
56
+ }
57
+ const asset = await AssetLoader.get(key, AssetParser.META);
58
+ if (asset) asset.key = key;
59
+ return asset ?? Caching.MISSING;
55
60
  });
56
61
  });
62
+ return meta === Caching.MISSING ? void 0 : meta;
57
63
  }
58
64
  /** Clears persisted texture metadata. Use {@link Caching.clear} to discard in-memory textures and metadata. */
59
65
  static async clearCache() {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/assets/ModelTextures.ts"],"sourcesContent":["import { Maybe } from \"../util/util\";\nimport { TextureAsset } from \"../model/Model\";\nimport { Caching } from \"../cache/Caching\";\nimport { AssetLoader } from \"./AssetLoader\";\nimport { CompatImage } from \"../canvas/CanvasCompat\";\nimport { ImageLoader } from \"../image/ImageLoader\";\nimport { ExtractableImageData } from \"../ExtractableImageData\";\nimport { MinecraftTextureMeta } from \"../MinecraftTextureMeta\";\nimport { PersistentCache } from \"../cache/PersistentCache\";\nimport { AssetKey } from \"./AssetKey\";\nimport { AssetParser } from \"./source/parser/AssetParsers\";\n\n/** Loads texture pixels and `.mcmeta` files through the active asset sources. */\nexport class ModelTextures {\n\n private static _persistentMetaCache: PersistentCache | undefined;\n\n private static get PERSISTENT_META_CACHE(): PersistentCache {\n return this._persistentMetaCache ??= PersistentCache.open(\"minerender-texturemeta\");\n }\n\n /** Loads and decodes a texture into a readable canvas, or returns `undefined` when missing. */\n public static async get(key: AssetKey): Promise<Maybe<ExtractableImageData>> {\n const keyStr = key.serialize();\n const pending = this.preload(key);\n const cached = Caching.textureAssetCache.getIfPresent(keyStr);\n try {\n const asset = await pending;\n if (asset) {\n return await ImageLoader.infoToCanvasData(asset);\n }\n return undefined;\n } catch (err) {\n // Discard corrupt encoded bytes, but preserve any newer load for this key.\n if (cached && Caching.textureAssetCache.getIfPresent(keyStr) === cached) {\n Caching.textureAssetCache.invalidate(keyStr);\n }\n throw err;\n }\n }\n\n /** Fetches and caches encoded texture bytes without decoding the pixels. */\n public static async preload(key: AssetKey): Promise<Maybe<TextureAsset>> {\n const keyStr = key.serialize();\n return Caching.textureAssetCache.get(keyStr, k => {\n return AssetLoader.get<TextureAsset>(key, AssetParser.IMAGE).then(asset => {\n if (asset)\n asset.key = key;\n return asset;\n })\n })\n }\n\n /** Loads a texture's `.mcmeta` file, or returns `undefined` when no metadata file exists. */\n public static async getMeta(key: AssetKey): Promise<Maybe<MinecraftTextureMeta>> {\n if (!key.extension || !key.extension.endsWith(\".mcmeta\")) {\n key = Object.assign(new AssetKey(\"\", \"\"), key);\n key.extension += \".mcmeta\";\n }\n const keyStr = key.serialize();\n\n return Caching.textureMetaCache.get(keyStr, k => {\n return this.PERSISTENT_META_CACHE.getOrLoad(AssetLoader.persistentKey(keyStr), k1 => {\n return AssetLoader.get<MinecraftTextureMeta>(key, AssetParser.META).then(asset => {\n if (asset)\n asset.key = key;\n return asset;\n })\n })\n })\n }\n\n /** Clears persisted texture metadata. Use {@link Caching.clear} to discard in-memory textures and metadata. */\n public static async clearCache() {\n await this.PERSISTENT_META_CACHE.clear();\n }\n\n}\n"],"mappings":";AAEA,SAAS,eAAe;AACxB,SAAS,mBAAmB;AAE5B,SAAS,mBAAmB;AAG5B,SAAS,uBAAuB;AAChC,SAAS,gBAAgB;AACzB,SAAS,mBAAmB;AAGrB,IAAM,gBAAN,MAAoB;AAAA,EAIvB,WAAmB,wBAAyC;AACxD,WAAO,KAAK,yBAAL,KAAK,uBAAyB,gBAAgB,KAAK,wBAAwB;AAAA,EACtF;AAAA;AAAA,EAGA,aAAoB,IAAI,KAAqD;AACzE,UAAM,SAAS,IAAI,UAAU;AAC7B,UAAM,UAAU,KAAK,QAAQ,GAAG;AAChC,UAAM,SAAS,QAAQ,kBAAkB,aAAa,MAAM;AAC5D,QAAI;AACA,YAAM,QAAQ,MAAM;AACpB,UAAI,OAAO;AACP,eAAO,MAAM,YAAY,iBAAiB,KAAK;AAAA,MACnD;AACA,aAAO;AAAA,IACX,SAAS,KAAK;AAEV,UAAI,UAAU,QAAQ,kBAAkB,aAAa,MAAM,MAAM,QAAQ;AACrE,gBAAQ,kBAAkB,WAAW,MAAM;AAAA,MAC/C;AACA,YAAM;AAAA,IACV;AAAA,EACJ;AAAA;AAAA,EAGA,aAAoB,QAAQ,KAA6C;AACrE,UAAM,SAAS,IAAI,UAAU;AAC7B,WAAO,QAAQ,kBAAkB,IAAI,QAAQ,OAAK;AAC9C,aAAO,YAAY,IAAkB,KAAK,YAAY,KAAK,EAAE,KAAK,WAAS;AACvE,YAAI;AACA,gBAAM,MAAM;AAChB,eAAO;AAAA,MACX,CAAC;AAAA,IACL,CAAC;AAAA,EACL;AAAA;AAAA,EAGA,aAAoB,QAAQ,KAAqD;AAC7E,QAAI,CAAC,IAAI,aAAa,CAAC,IAAI,UAAU,SAAS,SAAS,GAAG;AACtD,YAAM,OAAO,OAAO,IAAI,SAAS,IAAI,EAAE,GAAG,GAAG;AAC7C,UAAI,aAAa;AAAA,IACrB;AACA,UAAM,SAAS,IAAI,UAAU;AAE7B,WAAO,QAAQ,iBAAiB,IAAI,QAAQ,OAAK;AAC7C,aAAO,KAAK,sBAAsB,UAAU,YAAY,cAAc,MAAM,GAAG,QAAM;AACjF,eAAO,YAAY,IAA0B,KAAK,YAAY,IAAI,EAAE,KAAK,WAAS;AAC9E,cAAI;AACA,kBAAM,MAAM;AAChB,iBAAO;AAAA,QACX,CAAC;AAAA,MACL,CAAC;AAAA,IACL,CAAC;AAAA,EACL;AAAA;AAAA,EAGA,aAAoB,aAAa;AAC7B,UAAM,KAAK,sBAAsB,MAAM;AAAA,EAC3C;AAEJ;","names":[]}
1
+ {"version":3,"sources":["../../../../src/assets/ModelTextures.ts"],"sourcesContent":["import { Maybe } from \"../util/util\";\nimport { TextureAsset } from \"../model/Model\";\nimport { Caching } from \"../cache/Caching\";\nimport { AssetLoader } from \"./AssetLoader\";\nimport { CompatImage } from \"../canvas/CanvasCompat\";\nimport { ImageLoader } from \"../image/ImageLoader\";\nimport { ExtractableImageData } from \"../ExtractableImageData\";\nimport { MinecraftTextureMeta } from \"../MinecraftTextureMeta\";\nimport { PersistentCache } from \"../cache/PersistentCache\";\nimport { AssetKey } from \"./AssetKey\";\nimport { AssetParser } from \"./source/parser/AssetParsers\";\nimport type { ListAsset } from \"../ListAsset\";\n\n/** Loads texture pixels and `.mcmeta` files through the active asset sources. */\nexport class ModelTextures {\n\n private static _persistentMetaCache: PersistentCache | undefined;\n\n private static get PERSISTENT_META_CACHE(): PersistentCache {\n return this._persistentMetaCache ??= PersistentCache.open(\"minerender-texturemeta\");\n }\n\n /** Loads and decodes a texture into a readable canvas, or returns `undefined` when missing. */\n public static async get(key: AssetKey): Promise<Maybe<ExtractableImageData>> {\n const keyStr = key.serialize();\n const pending = this.preload(key);\n const cached = Caching.textureAssetCache.getIfPresent(keyStr);\n try {\n const asset = await pending;\n if (asset) {\n return await ImageLoader.infoToCanvasData(asset);\n }\n return undefined;\n } catch (err) {\n // Discard corrupt encoded bytes, but preserve any newer load for this key.\n if (cached && Caching.textureAssetCache.getIfPresent(keyStr) === cached) {\n Caching.textureAssetCache.invalidate(keyStr);\n }\n throw err;\n }\n }\n\n /** Fetches and caches encoded texture bytes without decoding the pixels. */\n public static async preload(key: AssetKey): Promise<Maybe<TextureAsset>> {\n const keyStr = key.serialize();\n return Caching.textureAssetCache.get(keyStr, k => {\n return AssetLoader.get<TextureAsset>(key, AssetParser.IMAGE).then(asset => {\n if (asset)\n asset.key = key;\n return asset;\n })\n })\n }\n\n /** Loads a texture's `.mcmeta` file, or returns `undefined` when no metadata file exists. */\n public static async getMeta(key: AssetKey): Promise<Maybe<MinecraftTextureMeta>> {\n if (!key.extension || !key.extension.endsWith(\".mcmeta\")) {\n key = Object.assign(new AssetKey(\"\", \"\"), key);\n key.extension += \".mcmeta\";\n }\n const keyStr = key.serialize();\n\n const meta = await Caching.textureMetaCache.get(keyStr, k => {\n return this.PERSISTENT_META_CACHE.getOrLoad(AssetLoader.persistentKey(keyStr), async k1 => {\n if (AssetLoader.persistentScope === \"\") {\n const path = key.getFullPath();\n const slash = path.lastIndexOf(\"/\");\n const listKey = new AssetKey(key.namespace, `${path.slice(0, slash + 1)}_list`, \"textures\", undefined, \"assets\", \".json\", key.root);\n const list = await Caching.listAssetCache.get(listKey.serialize(), () => AssetLoader.get<ListAsset>(listKey, AssetParser.LIST)).catch(() => undefined);\n if (list && !list.files.includes(`${path.slice(slash + 1)}${key.extension}`)) return Caching.MISSING;\n }\n const asset = await AssetLoader.get<MinecraftTextureMeta>(key, AssetParser.META);\n if (asset) asset.key = key;\n return asset ?? Caching.MISSING;\n })\n });\n return meta === Caching.MISSING ? undefined : meta;\n }\n\n /** Clears persisted texture metadata. Use {@link Caching.clear} to discard in-memory textures and metadata. */\n public static async clearCache() {\n await this.PERSISTENT_META_CACHE.clear();\n }\n\n}\n"],"mappings":";AAEA,SAAS,eAAe;AACxB,SAAS,mBAAmB;AAE5B,SAAS,mBAAmB;AAG5B,SAAS,uBAAuB;AAChC,SAAS,gBAAgB;AACzB,SAAS,mBAAmB;AAIrB,IAAM,gBAAN,MAAoB;AAAA,EAIvB,WAAmB,wBAAyC;AACxD,WAAO,KAAK,yBAAL,KAAK,uBAAyB,gBAAgB,KAAK,wBAAwB;AAAA,EACtF;AAAA;AAAA,EAGA,aAAoB,IAAI,KAAqD;AACzE,UAAM,SAAS,IAAI,UAAU;AAC7B,UAAM,UAAU,KAAK,QAAQ,GAAG;AAChC,UAAM,SAAS,QAAQ,kBAAkB,aAAa,MAAM;AAC5D,QAAI;AACA,YAAM,QAAQ,MAAM;AACpB,UAAI,OAAO;AACP,eAAO,MAAM,YAAY,iBAAiB,KAAK;AAAA,MACnD;AACA,aAAO;AAAA,IACX,SAAS,KAAK;AAEV,UAAI,UAAU,QAAQ,kBAAkB,aAAa,MAAM,MAAM,QAAQ;AACrE,gBAAQ,kBAAkB,WAAW,MAAM;AAAA,MAC/C;AACA,YAAM;AAAA,IACV;AAAA,EACJ;AAAA;AAAA,EAGA,aAAoB,QAAQ,KAA6C;AACrE,UAAM,SAAS,IAAI,UAAU;AAC7B,WAAO,QAAQ,kBAAkB,IAAI,QAAQ,OAAK;AAC9C,aAAO,YAAY,IAAkB,KAAK,YAAY,KAAK,EAAE,KAAK,WAAS;AACvE,YAAI;AACA,gBAAM,MAAM;AAChB,eAAO;AAAA,MACX,CAAC;AAAA,IACL,CAAC;AAAA,EACL;AAAA;AAAA,EAGA,aAAoB,QAAQ,KAAqD;AAC7E,QAAI,CAAC,IAAI,aAAa,CAAC,IAAI,UAAU,SAAS,SAAS,GAAG;AACtD,YAAM,OAAO,OAAO,IAAI,SAAS,IAAI,EAAE,GAAG,GAAG;AAC7C,UAAI,aAAa;AAAA,IACrB;AACA,UAAM,SAAS,IAAI,UAAU;AAE7B,UAAM,OAAO,MAAM,QAAQ,iBAAiB,IAAI,QAAQ,OAAK;AACzD,aAAO,KAAK,sBAAsB,UAAU,YAAY,cAAc,MAAM,GAAG,OAAM,OAAM;AACvF,YAAI,YAAY,oBAAoB,IAAI;AACpC,gBAAM,OAAO,IAAI,YAAY;AAC7B,gBAAM,QAAQ,KAAK,YAAY,GAAG;AAClC,gBAAM,UAAU,IAAI,SAAS,IAAI,WAAW,GAAG,KAAK,MAAM,GAAG,QAAQ,CAAC,CAAC,SAAS,YAAY,QAAW,UAAU,SAAS,IAAI,IAAI;AAClI,gBAAM,OAAO,MAAM,QAAQ,eAAe,IAAI,QAAQ,UAAU,GAAG,MAAM,YAAY,IAAe,SAAS,YAAY,IAAI,CAAC,EAAE,MAAM,MAAM,MAAS;AACrJ,cAAI,QAAQ,CAAC,KAAK,MAAM,SAAS,GAAG,KAAK,MAAM,QAAQ,CAAC,CAAC,GAAG,IAAI,SAAS,EAAE,EAAG,QAAO,QAAQ;AAAA,QACjG;AACA,cAAM,QAAQ,MAAM,YAAY,IAA0B,KAAK,YAAY,IAAI;AAC/E,YAAI,MAAO,OAAM,MAAM;AACvB,eAAO,SAAS,QAAQ;AAAA,MAC5B,CAAC;AAAA,IACL,CAAC;AACD,WAAO,SAAS,QAAQ,UAAU,SAAY;AAAA,EAClD;AAAA;AAAA,EAGA,aAAoB,aAAa;AAC7B,UAAM,KAAK,sBAAsB,MAAM;AAAA,EAC3C;AAEJ;","names":[]}
@@ -3,7 +3,7 @@ import { Renames } from "./Renames.mjs";
3
3
  import { Caching } from "../cache/Caching.mjs";
4
4
  import { ModelMerger } from "../model/ModelMerger.mjs";
5
5
  import { AssetLoader } from "./AssetLoader.mjs";
6
- import { DEFAULT_NAMESPACE } from "./Assets.mjs";
6
+ import { DEFAULT_NAMESPACE } from "./AssetDefaults.mjs";
7
7
  import { PersistentCache } from "../cache/PersistentCache.mjs";
8
8
  import { AssetKey, isAssetKey, isResourceLocation } from "./AssetKey.mjs";
9
9
  import { AssetParser } from "./source/parser/AssetParsers.mjs";
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/assets/Models.ts"],"sourcesContent":["import { Renames } from \"./Renames\";\nimport { ItemModel, ItemTintSource, Model, SpecialItemRenderer } from \"../model/Model\";\nimport { Caching } from \"../cache/Caching\";\nimport { Maybe } from \"../util/util\";\nimport { ModelMerger } from \"../model/ModelMerger\";\nimport { AssetLoader } from \"./AssetLoader\";\nimport { DEFAULT_NAMESPACE } from \"./Assets\";\nimport { PersistentCache } from \"../cache/PersistentCache\";\nimport { AssetKey, isAssetKey, isResourceLocation } from \"./AssetKey\";\nimport { ListAsset } from \"../ListAsset\";\nimport { AssetParser } from \"./source/parser/AssetParsers\";\nimport { DisplayPosition } from \"../model/DisplayPosition\";\nimport { DYE_COLORS } from \"./BannerPatterns\";\nimport { ItemDefaults } from \"../model/ItemDefaults\";\nimport { MineRenderData } from \"./MineRenderData\";\nimport { ItemTints } from \"../model/ItemTints\";\n\n/** Caller-supplied item-preview state passed to {@link Models.getMerged}. */\nexport interface ItemModelContext {\n /** Context used by display-context selectors, overriding `properties`. Defaults to GUI. */\n displayContext?: DisplayPosition | \"none\";\n /** Explicit property overrides. Nodes with the same ID share one override, regardless of their parameters. */\n properties?: Record<string, boolean | string | number>;\n /** Supplied component JSON by ID, overriding built-in defaults. Component selectors compare structural JSON values. */\n components?: Record<string, unknown>;\n /** Stack count, as a nonnegative integer. Defaults to 1; items without listed defaults stack to 64. */\n count?: number;\n /** Item-model keys by reference-node ID, such as `minecraft:bundle/selected_item`. Unset references draw nothing. */\n itemReferences?: Record<string, AssetKey>;\n}\n\n/** Loads and caches Java block/item models, including inherited geometry and textures. */\nexport class Models {\n\n // Bump when the shape of cached item models changes.\n private static readonly ITEM_CACHE_VERSION = \"item-v8\";\n private static _persistentCache: PersistentCache | undefined;\n\n // opened lazily: touching the store at import time would hit IndexedDB/disk just for loading\n // the library, and would require an EnvProvider before any entry has had a chance to register\n private static get PERSISTENT_CACHE(): PersistentCache {\n return this._persistentCache ??= PersistentCache.open(\"minerender-models\");\n }\n\n /** Lists item filenames from the asset source's `_list.json`, with a legacy model-directory fallback. */\n public static async getItemList(): Promise<string[]> {\n const key = new AssetKey(DEFAULT_NAMESPACE, \"_list\", \"items\");\n const legacyKey = new AssetKey(DEFAULT_NAMESPACE, \"_list\", \"models\", \"item\");\n return Caching.listAssetCache.get(key.serialize(), async () => {\n return (await AssetLoader.getFirst<ListAsset>([key, legacyKey], AssetParser.LIST))?.asset;\n }).then(r => r?.files ?? []);\n }\n\n public static async loadAndMerge(key: AssetKey, context: ItemModelContext = {}): Promise<Maybe<Model>> {\n const model = key.type === \"item\" ? await this.getItemModel(key, context) : await this.getRaw(key);\n if (!model) {\n return undefined;\n }\n const merged = await ModelMerger.mergeWithParents(model);\n return merged;\n }\n\n private static async getItemModel(key: AssetKey, context: ItemModelContext = {}): Promise<Maybe<Model>> {\n const preview = this.snapshotContext(key, context);\n const dataKey = await this.applyDefaults(key, preview);\n return this.getPreparedItemModel(key, preview, dataKey);\n }\n\n private static async getPreparedItemModel(key: AssetKey, preview: Required<ItemModelContext>, dataKey: string): Promise<Maybe<Model>> {\n const itemId = `${key.namespace}:${key.path}`;\n const itemKey = new AssetKey(key.namespace, key.path, \"items\", undefined, key.rootType, \".json\", key.root);\n const cacheKey = itemKey.serialize() + this.contextKey(preview) + dataKey;\n const model = await this.PERSISTENT_CACHE.getOrLoad(`${this.ITEM_CACHE_VERSION}:${AssetLoader.persistentKey(cacheKey)}`, async () => {\n const result = await AssetLoader.getFirst<Model & { model?: ItemModelNode }>([itemKey, key], AssetParser.JSON);\n if (!result) return undefined;\n if (result.key.assetType !== \"items\") return { ...result.asset, key, itemId, components: preview.components } as ItemModel;\n\n const load = async (selected: SelectedItemModel): Promise<ItemModel> => {\n if (\"parts\" in selected) {\n return { key, itemId, parts: await Promise.all(selected.parts.map(load)) };\n }\n if (\"item\" in selected) {\n // Referenced items start with their own default stack state and references.\n const model = await this.getItemModel(selected.item, { displayContext: preview.displayContext });\n if (!model) throw new Error(`Item ${key.toNamespacedString()} references missing item ${selected.item.toNamespacedString()}`);\n return model as ItemModel;\n }\n const modelKey = AssetKey.parse(\"models\", selected.model);\n modelKey.root = key.root;\n const model = await this.getRaw(modelKey);\n if (!model) throw new Error(`Item ${key.toNamespacedString()} references missing model ${selected.model}`);\n // Relative texture paths belong to the referenced model's namespace.\n return { ...model, itemId, components: preview.components, ...(selected.special && { special: selected.special }), ...(selected.tints && { tints: selected.tints }) } as ItemModel;\n };\n const model = await load(this.selectItemModel(result.asset.model, key, preview));\n return model;\n });\n const restore = (model: ItemModel): ItemModel => ({\n ...model, key: Object.assign(new AssetKey(\"\", \"\"), model.key),\n ...(model.parts && { parts: model.parts.map(restore) })\n });\n return model ? restore(model) : undefined;\n }\n\n private static contextIdentifier(id: string): string {\n if (!isResourceLocation(id)) {\n throw new Error(`Invalid item-preview identifier: ${id}`);\n }\n return id.includes(\":\") ? id : `minecraft:${id}`;\n }\n\n /** @internal */\n public static componentValue(components: Record<string, unknown>, id: string): unknown {\n const normalized = this.contextIdentifier(id);\n const short = normalized.replace(/^minecraft:/, \"\");\n if (short !== normalized && Object.prototype.hasOwnProperty.call(components, short)\n && Object.prototype.hasOwnProperty.call(components, normalized)) {\n throw new Error(`Duplicate item-preview component: ${normalized}`);\n }\n return Object.prototype.hasOwnProperty.call(components, short) ? components[short] : components[normalized];\n }\n\n private static snapshotContext(key: AssetKey, context: ItemModelContext): Required<ItemModelContext> {\n const displayContext = context.displayContext ?? DisplayPosition.GUI;\n if (displayContext !== \"none\" && !Object.values(DisplayPosition).includes(displayContext)) {\n throw new Error(`Unsupported item display context: ${displayContext}`);\n }\n for (const map of [context.properties, context.components, context.itemReferences]) {\n if (map !== undefined && (!map || typeof map !== \"object\" || Array.isArray(map))) {\n throw new Error(\"Item-preview properties, components, and references must be objects keyed by identifier\");\n }\n }\n const count = context.count === undefined ? 1 : context.count;\n if (!Number.isSafeInteger(count) || count < 0) throw new Error(\"Item-preview count must be a nonnegative safe integer\");\n const properties: Required<ItemModelContext>[\"properties\"] = {};\n for (const [id, value] of Object.entries(context.properties ?? {})) {\n const property = this.contextIdentifier(id);\n if (![\"boolean\", \"string\", \"number\"].includes(typeof value) || typeof value === \"number\" && !Number.isFinite(value)) {\n throw new Error(`Item-preview property ${property} must be a boolean, string, or finite number`);\n }\n if (Object.prototype.hasOwnProperty.call(properties, property)) throw new Error(`Duplicate item-preview property: ${property}`);\n properties[property] = value;\n }\n const components: Record<string, unknown> = {};\n for (const [id, value] of Object.entries(context.components ?? {})) {\n const component = this.contextIdentifier(id);\n if (Object.prototype.hasOwnProperty.call(components, component)) throw new Error(`Duplicate item-preview component: ${component}`);\n components[component] = this.snapshotJson(value);\n }\n const itemReferences: Record<string, AssetKey> = {};\n for (const [id, value] of Object.entries(context.itemReferences ?? {})) {\n const reference = this.contextIdentifier(id);\n if (!isAssetKey(value) || value.assetType !== \"models\" || value.type !== \"item\") {\n throw new Error(`Item-preview reference ${reference} must be an item-model AssetKey`);\n }\n this.contextIdentifier(`${value.namespace}:${value.path}`);\n if (Object.prototype.hasOwnProperty.call(itemReferences, reference)) throw new Error(`Duplicate item-preview reference: ${reference}`);\n itemReferences[reference] = Object.assign(new AssetKey(\"\", \"\"), value, { root: value.root ?? key.root });\n }\n return { displayContext, properties, components, count, itemReferences };\n }\n\n private static async applyDefaults(key: AssetKey, preview: Required<ItemModelContext>): Promise<string> {\n if (key.type !== \"item\") return \"\";\n const resolved = await MineRenderData.resolve(key.root);\n const defaults = await ItemDefaults.get(`${key.namespace}:${key.path}`, key.root);\n preview.components = { ...defaults, ...preview.components };\n if (resolved.manifest.dataVersion < 3337 && key.namespace === DEFAULT_NAMESPACE\n && [\"potion\", \"splash_potion\", \"lingering_potion\"].includes(key.path)\n && !Object.prototype.hasOwnProperty.call(preview.components, \"minecraft:enchantment_glint_override\")\n && await ItemTints.hasPotionEffects(preview.components[\"minecraft:potion_contents\"], key.root)) {\n preview.components[\"minecraft:enchantment_glint_override\"] = true;\n }\n return `|data:${resolved.root}:${resolved.manifest.datasets.itemDefaults?.sha256}:${resolved.manifest.datasets.potionColors?.sha256}`;\n }\n\n private static contextKey(context: Required<ItemModelContext>): string {\n const itemReferences = Object.fromEntries(Object.entries(context.itemReferences).map(([id, key]) => [id, key.serialize()]));\n return `|${this.ITEM_CACHE_VERSION}:${JSON.stringify(this.snapshotJson({ ...context, itemReferences }))}`;\n }\n\n private static snapshotJson(value: unknown, ancestors = new Set<object>()): unknown {\n if (value === null || typeof value === \"string\" || typeof value === \"boolean\" || typeof value === \"number\" && Number.isFinite(value)) return value;\n if (typeof value !== \"object\" || ancestors.has(value) || !Array.isArray(value)\n && Object.getPrototypeOf(value) !== Object.prototype && Object.getPrototypeOf(value) !== null) {\n throw new Error(\"Item-preview components must contain finite JSON values without circular references\");\n }\n ancestors.add(value);\n const copy = Array.isArray(value) ? Array.from(value, entry => this.snapshotJson(entry, ancestors))\n : Object.fromEntries(Object.keys(value).sort().map(key => [key, this.snapshotJson((value as Record<string, unknown>)[key], ancestors)]));\n ancestors.delete(value);\n return copy;\n }\n\n private static propertyValue(node: ItemModelNode, context: Required<ItemModelContext>): unknown {\n const kind = node.type.replace(/^minecraft:/, \"\");\n const property = node.property ? this.contextIdentifier(node.property) : undefined;\n if (kind === \"select\" && property === \"minecraft:display_context\") return context.displayContext;\n if (property && Object.prototype.hasOwnProperty.call(context.properties, property)) return context.properties[property];\n const fallback = kind === \"condition\" ? false : kind === \"range_dispatch\" ? 0 : undefined;\n const component = (id: string) => context.components[this.contextIdentifier(id)];\n if (property === \"minecraft:custom_model_data\") {\n const index = node.index ?? 0;\n if (!Number.isSafeInteger(index) || index < 0) throw new Error(\"Item-model custom_model_data index must be a nonnegative integer\");\n const data = component(\"custom_model_data\");\n if (data === undefined) return fallback;\n if (!data || typeof data !== \"object\" || Array.isArray(data)) throw new Error(\"Item-preview custom_model_data must be an object\");\n const field = kind === \"condition\" ? \"flags\" : kind === \"select\" ? \"strings\" : \"floats\";\n const values = (data as Record<string, unknown>)[field];\n if (values === undefined) return fallback;\n if (!Array.isArray(values)) throw new Error(`Item-preview custom_model_data.${field} must be an array`);\n return index < values.length ? values[index] : fallback;\n }\n if (kind === \"condition\" && property === \"minecraft:has_component\") {\n if (node.ignore_default) throw new Error(\"Item-preview has_component with ignore_default requires an explicit properties override; default component comparisons are unsupported\");\n return Object.prototype.hasOwnProperty.call(context.components, this.contextIdentifier(node.component!));\n }\n if (kind === \"select\") {\n switch (property) {\n case \"minecraft:component\": return component(node.component!);\n case \"minecraft:block_state\": {\n const state = component(\"block_state\");\n if (state === undefined) return undefined;\n if (!state || typeof state !== \"object\" || Array.isArray(state)) throw new Error(\"Item-preview block_state must be an object\");\n if (typeof node.block_state_property !== \"string\") throw new Error(\"Item-model block_state requires block_state_property\");\n return Object.prototype.hasOwnProperty.call(state, node.block_state_property)\n ? (state as Record<string, unknown>)[node.block_state_property] : undefined;\n }\n case \"minecraft:charge_type\": {\n const projectiles = component(\"charged_projectiles\");\n if (projectiles === undefined) return \"none\";\n if (!Array.isArray(projectiles)) throw new Error(\"Item-preview charged_projectiles must be an array of item stacks\");\n const ids = projectiles.map(stack => {\n if (!stack || typeof stack !== \"object\" || Array.isArray(stack)) throw new Error(\"Item-preview charged_projectiles must contain item-stack objects\");\n return this.contextIdentifier((stack as { id: string }).id);\n });\n return !ids.length ? \"none\" : ids.includes(\"minecraft:firework_rocket\") ? \"rocket\" : \"arrow\";\n }\n }\n }\n if (kind === \"range_dispatch\" && (property === \"minecraft:damage\" || property === \"minecraft:count\")) {\n const damage = property === \"minecraft:damage\";\n const maximumComponent = component(damage ? \"max_damage\" : \"max_stack_size\");\n const maximum = maximumComponent === undefined ? damage ? 0 : 1 : maximumComponent;\n const damageComponent = component(\"damage\");\n const value = damage ? damageComponent === undefined ? 0 : damageComponent : context.count;\n if (typeof value !== \"number\" || typeof maximum !== \"number\" || maximum < 0) throw new Error(`Item-preview ${property} requires numeric components and a nonnegative maximum`);\n const clamped = Math.max(0, Math.min(maximum, value));\n return node.normalize === false ? clamped : clamped / maximum;\n }\n return fallback;\n }\n\n private static selectItemModel(node: ItemModelNode | undefined, key: AssetKey, context: Required<ItemModelContext>): SelectedItemModel {\n if (!node || typeof node.type !== \"string\") {\n throw new Error(`Unsupported item model definition for ${key.toNamespacedString()}`);\n }\n switch (node.type.replace(/^minecraft:/, \"\")) {\n case \"composite\":\n if (Array.isArray(node.models)) return { parts: node.models.map(child => this.selectItemModel(child, key, context)) };\n break;\n case \"bundle/selected_item\": {\n const item = context.itemReferences[\"minecraft:bundle/selected_item\"];\n return item ? { item } : { parts: [] };\n }\n case \"model\":\n if (typeof node.model === \"string\" && node.model) return { model: node.model, tints: node.tints };\n break;\n case \"special\": {\n if (!node.base || !node.model || typeof node.model !== \"object\") break;\n const special = node.model;\n switch (special.type) {\n case \"copper_golem_statue\":\n case \"minecraft:copper_golem_statue\":\n if (isResourceLocation(special.texture)\n && [\"standing\", \"sitting\", \"running\", \"star\"].includes(special.pose)) return { model: node.base, special };\n break;\n case \"banner\":\n case \"minecraft:banner\":\n if (typeof special.color === \"string\" && Object.prototype.hasOwnProperty.call(DYE_COLORS, special.color)) return { model: node.base, special };\n break;\n case \"shield\":\n case \"minecraft:shield\":\n case \"trident\":\n case \"minecraft:trident\":\n case \"conduit\":\n case \"minecraft:conduit\":\n case \"decorated_pot\":\n case \"minecraft:decorated_pot\":\n case \"player_head\":\n case \"minecraft:player_head\":\n return { model: node.base, special };\n case \"shulker_box\":\n case \"minecraft:shulker_box\":\n if (typeof special.texture === \"string\" && special.texture\n && (special.openness === undefined || typeof special.openness === \"number\" && Number.isFinite(special.openness))\n && (special.orientation === undefined || [\"down\", \"up\", \"north\", \"south\", \"west\", \"east\"].includes(special.orientation))) {\n return { model: node.base, special };\n }\n break;\n case \"chest\":\n case \"minecraft:chest\":\n case \"bed\":\n case \"minecraft:bed\":\n if (typeof special.texture === \"string\" && special.texture) return { model: node.base, special };\n break;\n case \"head\":\n case \"minecraft:head\":\n if (typeof special.kind === \"string\" && special.kind) return { model: node.base, special };\n break;\n }\n throw new Error(`Unsupported special item renderer ${special.type} for ${key.toNamespacedString()}`);\n }\n case \"condition\": {\n const value = this.propertyValue(node, context);\n if (typeof value !== \"boolean\") throw new Error(`Item-preview condition ${node.property} requires a boolean`);\n return this.selectItemModel(value ? node.on_true : node.on_false, key, context);\n }\n case \"select\": {\n const value = this.propertyValue(node, context);\n const component = node.property && this.contextIdentifier(node.property) === \"minecraft:component\";\n if (!component && value !== undefined && typeof value !== \"string\") throw new Error(`Item-preview selector ${node.property} requires a string`);\n const matches = (candidate: unknown) => component\n ? JSON.stringify(this.snapshotJson(candidate)) === JSON.stringify(this.snapshotJson(value)) : candidate === value;\n const selected = value === undefined ? undefined\n : node.cases?.find(entry => matches(entry.when) || Array.isArray(entry.when) && entry.when.some(matches))?.model;\n return this.selectItemModel(selected ?? node.fallback, key, context);\n }\n case \"range_dispatch\": {\n const value = this.propertyValue(node, context);\n if (typeof value !== \"number\") throw new Error(`Item-preview range ${node.property} requires a number`);\n if (Number.isNaN(value)) return this.selectItemModel(node.fallback, key, context);\n const scaled = value * (node.scale ?? 1);\n if (!Number.isFinite(scaled)) throw new Error(`Item-preview range ${node.property} requires a finite value and scale`);\n const selected = node.entries?.reduce<{ threshold: number; model: ItemModelNode } | undefined>((match, entry) => {\n return entry.threshold <= scaled && (!match || entry.threshold >= match.threshold) ? entry : match;\n }, undefined);\n return this.selectItemModel(selected?.model ?? node.fallback, key, context);\n }\n }\n throw new Error(`Unsupported item model ${node?.type ?? \"definition\"} for ${key.toNamespacedString()}`);\n }\n\n /** Loads one model file without resolving its parents. Returns `undefined` when the file is missing. */\n public static async getRaw(key: AssetKey): Promise<Maybe<Model>> {\n if (!key.assetType) {\n key.assetType = \"models\";\n }\n if (!key.extension) {\n key.extension = \".json\";\n }\n const keyStr = key.serialize();\n //TODO: maybe add the asset source to the key\n return Caching.rawModelCache.get(keyStr, k => {\n return this.PERSISTENT_CACHE.getOrLoad(AssetLoader.persistentKey(keyStr), k1 => {\n return AssetLoader.get<Model>(key, AssetParser.MODEL);\n })\n }).then(asset => {\n if (asset) {\n asset.key = key;\n }\n return asset;\n })\n }\n\n /**\n * Loads a model and resolves its parent chain. Returns `undefined` when the model is missing.\n * Item keys default to GUI context and a stack count of 1. Unresolved conditions are false and numeric properties are zero.\n * Versioned stack-size, durability, and glint defaults apply unless components override them.\n * Pass `context` to supply component values, property overrides, and item references for a preview.\n * Composite items retain independently merged children in `ItemModel.parts`.\n *\n * @param key - Model key, for example `AssetKey.parse(\"models\", \"minecraft:item/diamond_sword\")`.\n */\n public static async getMerged(key: AssetKey, context: ItemModelContext = {}): Promise<Maybe<Model>> {\n if (!key.assetType) {\n key.assetType = \"models\";\n }\n if (!key.extension) {\n key.extension = \".json\";\n }\n const preview = this.snapshotContext(key, context);\n if (key.type === \"item\") {\n const renamed = await Renames.key(\"items\", key);\n const replacement = renamed && await this.getMerged(renamed, preview);\n if (replacement) return replacement;\n }\n const dataKey = await this.applyDefaults(key, preview);\n const keyStr = AssetLoader.persistentKey(key.serialize() + (key.type === \"item\" ? this.contextKey(preview) + dataKey : \"\"));\n const model = await Caching.mergedModelCache.get(keyStr, async () => {\n //TODO: persistent cache\n const raw = key.type === \"item\" ? await this.getPreparedItemModel(key, preview, dataKey) : await this.getRaw(key);\n const merged = raw ? await ModelMerger.mergeWithParents(raw) : undefined;\n return merged;\n });\n return model;\n }\n\n /** Alias for {@link getMerged}. */\n public static async get(key: AssetKey, context: ItemModelContext = {}): Promise<Maybe<Model>> {\n return this.getMerged(key, context);\n }\n\n /** Clears persisted models. Use {@link Caching.clear} to also discard in-memory assets. */\n public static async clearCache() {\n return this.PERSISTENT_CACHE.clear();\n }\n\n}\n\ninterface ItemModelNode {\n type: string;\n model?: string | SpecialItemRenderer;\n tints?: ItemTintSource[];\n base?: string;\n property?: string;\n index?: number;\n component?: string;\n ignore_default?: boolean;\n normalize?: boolean;\n block_state_property?: string;\n on_false?: ItemModelNode;\n on_true?: ItemModelNode;\n fallback?: ItemModelNode;\n cases?: Array<{ when: unknown; model: ItemModelNode }>;\n entries?: Array<{ threshold: number; model: ItemModelNode }>;\n scale?: number;\n models?: ItemModelNode[];\n}\n\ntype SelectedItemModel = { model: string; special?: SpecialItemRenderer; tints?: ItemTintSource[] }\n | { parts: SelectedItemModel[] }\n | { item: AssetKey };\n"],"mappings":"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","names":["model"]}
1
+ {"version":3,"sources":["../../../../src/assets/Models.ts"],"sourcesContent":["import { Renames } from \"./Renames\";\nimport { ItemModel, ItemTintSource, Model, SpecialItemRenderer } from \"../model/Model\";\nimport { Caching } from \"../cache/Caching\";\nimport { Maybe } from \"../util/util\";\nimport { ModelMerger } from \"../model/ModelMerger\";\nimport { AssetLoader } from \"./AssetLoader\";\nimport { DEFAULT_NAMESPACE } from \"./AssetDefaults\";\nimport { PersistentCache } from \"../cache/PersistentCache\";\nimport { AssetKey, isAssetKey, isResourceLocation } from \"./AssetKey\";\nimport { ListAsset } from \"../ListAsset\";\nimport { AssetParser } from \"./source/parser/AssetParsers\";\nimport { DisplayPosition } from \"../model/DisplayPosition\";\nimport { DYE_COLORS } from \"./BannerPatterns\";\nimport { ItemDefaults } from \"../model/ItemDefaults\";\nimport { MineRenderData } from \"./MineRenderData\";\nimport { ItemTints } from \"../model/ItemTints\";\n\n/** Caller-supplied item-preview state passed to {@link Models.getMerged}. */\nexport interface ItemModelContext {\n /** Context used by display-context selectors, overriding `properties`. Defaults to GUI. */\n displayContext?: DisplayPosition | \"none\";\n /** Explicit property overrides. Nodes with the same ID share one override, regardless of their parameters. */\n properties?: Record<string, boolean | string | number>;\n /** Supplied component JSON by ID, overriding built-in defaults. Component selectors compare structural JSON values. */\n components?: Record<string, unknown>;\n /** Stack count, as a nonnegative integer. Defaults to 1; items without listed defaults stack to 64. */\n count?: number;\n /** Item-model keys by reference-node ID, such as `minecraft:bundle/selected_item`. Unset references draw nothing. */\n itemReferences?: Record<string, AssetKey>;\n}\n\n/** Loads and caches Java block/item models, including inherited geometry and textures. */\nexport class Models {\n\n // Bump when the shape of cached item models changes.\n private static readonly ITEM_CACHE_VERSION = \"item-v8\";\n private static _persistentCache: PersistentCache | undefined;\n\n // opened lazily: touching the store at import time would hit IndexedDB/disk just for loading\n // the library, and would require an EnvProvider before any entry has had a chance to register\n private static get PERSISTENT_CACHE(): PersistentCache {\n return this._persistentCache ??= PersistentCache.open(\"minerender-models\");\n }\n\n /** Lists item filenames from the asset source's `_list.json`, with a legacy model-directory fallback. */\n public static async getItemList(): Promise<string[]> {\n const key = new AssetKey(DEFAULT_NAMESPACE, \"_list\", \"items\");\n const legacyKey = new AssetKey(DEFAULT_NAMESPACE, \"_list\", \"models\", \"item\");\n return Caching.listAssetCache.get(key.serialize(), async () => {\n return (await AssetLoader.getFirst<ListAsset>([key, legacyKey], AssetParser.LIST))?.asset;\n }).then(r => r?.files ?? []);\n }\n\n public static async loadAndMerge(key: AssetKey, context: ItemModelContext = {}): Promise<Maybe<Model>> {\n const model = key.type === \"item\" ? await this.getItemModel(key, context) : await this.getRaw(key);\n if (!model) {\n return undefined;\n }\n const merged = await ModelMerger.mergeWithParents(model);\n return merged;\n }\n\n private static async getItemModel(key: AssetKey, context: ItemModelContext = {}): Promise<Maybe<Model>> {\n const preview = this.snapshotContext(key, context);\n const dataKey = await this.applyDefaults(key, preview);\n return this.getPreparedItemModel(key, preview, dataKey);\n }\n\n private static async getPreparedItemModel(key: AssetKey, preview: Required<ItemModelContext>, dataKey: string): Promise<Maybe<Model>> {\n const itemId = `${key.namespace}:${key.path}`;\n const itemKey = new AssetKey(key.namespace, key.path, \"items\", undefined, key.rootType, \".json\", key.root);\n const cacheKey = itemKey.serialize() + this.contextKey(preview) + dataKey;\n const model = await this.PERSISTENT_CACHE.getOrLoad(`${this.ITEM_CACHE_VERSION}:${AssetLoader.persistentKey(cacheKey)}`, async () => {\n const result = await AssetLoader.getFirst<Model & { model?: ItemModelNode }>([itemKey, key], AssetParser.JSON);\n if (!result) return undefined;\n if (result.key.assetType !== \"items\") return { ...result.asset, key, itemId, components: preview.components } as ItemModel;\n\n const load = async (selected: SelectedItemModel): Promise<ItemModel> => {\n if (\"parts\" in selected) {\n return { key, itemId, parts: await Promise.all(selected.parts.map(load)) };\n }\n if (\"item\" in selected) {\n // Referenced items start with their own default stack state and references.\n const model = await this.getItemModel(selected.item, { displayContext: preview.displayContext });\n if (!model) throw new Error(`Item ${key.toNamespacedString()} references missing item ${selected.item.toNamespacedString()}`);\n return model as ItemModel;\n }\n const modelKey = AssetKey.parse(\"models\", selected.model);\n modelKey.root = key.root;\n const model = await this.getRaw(modelKey);\n if (!model) throw new Error(`Item ${key.toNamespacedString()} references missing model ${selected.model}`);\n // Relative texture paths belong to the referenced model's namespace.\n return { ...model, itemId, components: preview.components, ...(selected.special && { special: selected.special }), ...(selected.tints && { tints: selected.tints }) } as ItemModel;\n };\n const model = await load(this.selectItemModel(result.asset.model, key, preview));\n return model;\n });\n const restore = (model: ItemModel): ItemModel => ({\n ...model, key: Object.assign(new AssetKey(\"\", \"\"), model.key),\n ...(model.parts && { parts: model.parts.map(restore) })\n });\n return model ? restore(model) : undefined;\n }\n\n private static contextIdentifier(id: string): string {\n if (!isResourceLocation(id)) {\n throw new Error(`Invalid item-preview identifier: ${id}`);\n }\n return id.includes(\":\") ? id : `minecraft:${id}`;\n }\n\n /** @internal */\n public static componentValue(components: Record<string, unknown>, id: string): unknown {\n const normalized = this.contextIdentifier(id);\n const short = normalized.replace(/^minecraft:/, \"\");\n if (short !== normalized && Object.prototype.hasOwnProperty.call(components, short)\n && Object.prototype.hasOwnProperty.call(components, normalized)) {\n throw new Error(`Duplicate item-preview component: ${normalized}`);\n }\n return Object.prototype.hasOwnProperty.call(components, short) ? components[short] : components[normalized];\n }\n\n private static snapshotContext(key: AssetKey, context: ItemModelContext): Required<ItemModelContext> {\n const displayContext = context.displayContext ?? DisplayPosition.GUI;\n if (displayContext !== \"none\" && !Object.values(DisplayPosition).includes(displayContext)) {\n throw new Error(`Unsupported item display context: ${displayContext}`);\n }\n for (const map of [context.properties, context.components, context.itemReferences]) {\n if (map !== undefined && (!map || typeof map !== \"object\" || Array.isArray(map))) {\n throw new Error(\"Item-preview properties, components, and references must be objects keyed by identifier\");\n }\n }\n const count = context.count === undefined ? 1 : context.count;\n if (!Number.isSafeInteger(count) || count < 0) throw new Error(\"Item-preview count must be a nonnegative safe integer\");\n const properties: Required<ItemModelContext>[\"properties\"] = {};\n for (const [id, value] of Object.entries(context.properties ?? {})) {\n const property = this.contextIdentifier(id);\n if (![\"boolean\", \"string\", \"number\"].includes(typeof value) || typeof value === \"number\" && !Number.isFinite(value)) {\n throw new Error(`Item-preview property ${property} must be a boolean, string, or finite number`);\n }\n if (Object.prototype.hasOwnProperty.call(properties, property)) throw new Error(`Duplicate item-preview property: ${property}`);\n properties[property] = value;\n }\n const components: Record<string, unknown> = {};\n for (const [id, value] of Object.entries(context.components ?? {})) {\n const component = this.contextIdentifier(id);\n if (Object.prototype.hasOwnProperty.call(components, component)) throw new Error(`Duplicate item-preview component: ${component}`);\n components[component] = this.snapshotJson(value);\n }\n const itemReferences: Record<string, AssetKey> = {};\n for (const [id, value] of Object.entries(context.itemReferences ?? {})) {\n const reference = this.contextIdentifier(id);\n if (!isAssetKey(value) || value.assetType !== \"models\" || value.type !== \"item\") {\n throw new Error(`Item-preview reference ${reference} must be an item-model AssetKey`);\n }\n this.contextIdentifier(`${value.namespace}:${value.path}`);\n if (Object.prototype.hasOwnProperty.call(itemReferences, reference)) throw new Error(`Duplicate item-preview reference: ${reference}`);\n itemReferences[reference] = Object.assign(new AssetKey(\"\", \"\"), value, { root: value.root ?? key.root });\n }\n return { displayContext, properties, components, count, itemReferences };\n }\n\n private static async applyDefaults(key: AssetKey, preview: Required<ItemModelContext>): Promise<string> {\n if (key.type !== \"item\") return \"\";\n const resolved = await MineRenderData.resolve(key.root);\n const defaults = await ItemDefaults.get(`${key.namespace}:${key.path}`, key.root);\n preview.components = { ...defaults, ...preview.components };\n if (resolved.manifest.dataVersion < 3337 && key.namespace === DEFAULT_NAMESPACE\n && [\"potion\", \"splash_potion\", \"lingering_potion\"].includes(key.path)\n && !Object.prototype.hasOwnProperty.call(preview.components, \"minecraft:enchantment_glint_override\")\n && await ItemTints.hasPotionEffects(preview.components[\"minecraft:potion_contents\"], key.root)) {\n preview.components[\"minecraft:enchantment_glint_override\"] = true;\n }\n return `|data:${resolved.root}:${resolved.manifest.datasets.itemDefaults?.sha256}:${resolved.manifest.datasets.potionColors?.sha256}`;\n }\n\n private static contextKey(context: Required<ItemModelContext>): string {\n const itemReferences = Object.fromEntries(Object.entries(context.itemReferences).map(([id, key]) => [id, key.serialize()]));\n return `|${this.ITEM_CACHE_VERSION}:${JSON.stringify(this.snapshotJson({ ...context, itemReferences }))}`;\n }\n\n private static snapshotJson(value: unknown, ancestors = new Set<object>()): unknown {\n if (value === null || typeof value === \"string\" || typeof value === \"boolean\" || typeof value === \"number\" && Number.isFinite(value)) return value;\n if (typeof value !== \"object\" || ancestors.has(value) || !Array.isArray(value)\n && Object.getPrototypeOf(value) !== Object.prototype && Object.getPrototypeOf(value) !== null) {\n throw new Error(\"Item-preview components must contain finite JSON values without circular references\");\n }\n ancestors.add(value);\n const copy = Array.isArray(value) ? Array.from(value, entry => this.snapshotJson(entry, ancestors))\n : Object.fromEntries(Object.keys(value).sort().map(key => [key, this.snapshotJson((value as Record<string, unknown>)[key], ancestors)]));\n ancestors.delete(value);\n return copy;\n }\n\n private static propertyValue(node: ItemModelNode, context: Required<ItemModelContext>): unknown {\n const kind = node.type.replace(/^minecraft:/, \"\");\n const property = node.property ? this.contextIdentifier(node.property) : undefined;\n if (kind === \"select\" && property === \"minecraft:display_context\") return context.displayContext;\n if (property && Object.prototype.hasOwnProperty.call(context.properties, property)) return context.properties[property];\n const fallback = kind === \"condition\" ? false : kind === \"range_dispatch\" ? 0 : undefined;\n const component = (id: string) => context.components[this.contextIdentifier(id)];\n if (property === \"minecraft:custom_model_data\") {\n const index = node.index ?? 0;\n if (!Number.isSafeInteger(index) || index < 0) throw new Error(\"Item-model custom_model_data index must be a nonnegative integer\");\n const data = component(\"custom_model_data\");\n if (data === undefined) return fallback;\n if (!data || typeof data !== \"object\" || Array.isArray(data)) throw new Error(\"Item-preview custom_model_data must be an object\");\n const field = kind === \"condition\" ? \"flags\" : kind === \"select\" ? \"strings\" : \"floats\";\n const values = (data as Record<string, unknown>)[field];\n if (values === undefined) return fallback;\n if (!Array.isArray(values)) throw new Error(`Item-preview custom_model_data.${field} must be an array`);\n return index < values.length ? values[index] : fallback;\n }\n if (kind === \"condition\" && property === \"minecraft:has_component\") {\n if (node.ignore_default) throw new Error(\"Item-preview has_component with ignore_default requires an explicit properties override; default component comparisons are unsupported\");\n return Object.prototype.hasOwnProperty.call(context.components, this.contextIdentifier(node.component!));\n }\n if (kind === \"select\") {\n switch (property) {\n case \"minecraft:component\": return component(node.component!);\n case \"minecraft:block_state\": {\n const state = component(\"block_state\");\n if (state === undefined) return undefined;\n if (!state || typeof state !== \"object\" || Array.isArray(state)) throw new Error(\"Item-preview block_state must be an object\");\n if (typeof node.block_state_property !== \"string\") throw new Error(\"Item-model block_state requires block_state_property\");\n return Object.prototype.hasOwnProperty.call(state, node.block_state_property)\n ? (state as Record<string, unknown>)[node.block_state_property] : undefined;\n }\n case \"minecraft:charge_type\": {\n const projectiles = component(\"charged_projectiles\");\n if (projectiles === undefined) return \"none\";\n if (!Array.isArray(projectiles)) throw new Error(\"Item-preview charged_projectiles must be an array of item stacks\");\n const ids = projectiles.map(stack => {\n if (!stack || typeof stack !== \"object\" || Array.isArray(stack)) throw new Error(\"Item-preview charged_projectiles must contain item-stack objects\");\n return this.contextIdentifier((stack as { id: string }).id);\n });\n return !ids.length ? \"none\" : ids.includes(\"minecraft:firework_rocket\") ? \"rocket\" : \"arrow\";\n }\n }\n }\n if (kind === \"range_dispatch\" && (property === \"minecraft:damage\" || property === \"minecraft:count\")) {\n const damage = property === \"minecraft:damage\";\n const maximumComponent = component(damage ? \"max_damage\" : \"max_stack_size\");\n const maximum = maximumComponent === undefined ? damage ? 0 : 1 : maximumComponent;\n const damageComponent = component(\"damage\");\n const value = damage ? damageComponent === undefined ? 0 : damageComponent : context.count;\n if (typeof value !== \"number\" || typeof maximum !== \"number\" || maximum < 0) throw new Error(`Item-preview ${property} requires numeric components and a nonnegative maximum`);\n const clamped = Math.max(0, Math.min(maximum, value));\n return node.normalize === false ? clamped : clamped / maximum;\n }\n return fallback;\n }\n\n private static selectItemModel(node: ItemModelNode | undefined, key: AssetKey, context: Required<ItemModelContext>): SelectedItemModel {\n if (!node || typeof node.type !== \"string\") {\n throw new Error(`Unsupported item model definition for ${key.toNamespacedString()}`);\n }\n switch (node.type.replace(/^minecraft:/, \"\")) {\n case \"composite\":\n if (Array.isArray(node.models)) return { parts: node.models.map(child => this.selectItemModel(child, key, context)) };\n break;\n case \"bundle/selected_item\": {\n const item = context.itemReferences[\"minecraft:bundle/selected_item\"];\n return item ? { item } : { parts: [] };\n }\n case \"model\":\n if (typeof node.model === \"string\" && node.model) return { model: node.model, tints: node.tints };\n break;\n case \"special\": {\n if (!node.base || !node.model || typeof node.model !== \"object\") break;\n const special = node.model;\n switch (special.type) {\n case \"copper_golem_statue\":\n case \"minecraft:copper_golem_statue\":\n if (isResourceLocation(special.texture)\n && [\"standing\", \"sitting\", \"running\", \"star\"].includes(special.pose)) return { model: node.base, special };\n break;\n case \"banner\":\n case \"minecraft:banner\":\n if (typeof special.color === \"string\" && Object.prototype.hasOwnProperty.call(DYE_COLORS, special.color)) return { model: node.base, special };\n break;\n case \"shield\":\n case \"minecraft:shield\":\n case \"trident\":\n case \"minecraft:trident\":\n case \"conduit\":\n case \"minecraft:conduit\":\n case \"decorated_pot\":\n case \"minecraft:decorated_pot\":\n case \"player_head\":\n case \"minecraft:player_head\":\n return { model: node.base, special };\n case \"shulker_box\":\n case \"minecraft:shulker_box\":\n if (typeof special.texture === \"string\" && special.texture\n && (special.openness === undefined || typeof special.openness === \"number\" && Number.isFinite(special.openness))\n && (special.orientation === undefined || [\"down\", \"up\", \"north\", \"south\", \"west\", \"east\"].includes(special.orientation))) {\n return { model: node.base, special };\n }\n break;\n case \"chest\":\n case \"minecraft:chest\":\n case \"bed\":\n case \"minecraft:bed\":\n if (typeof special.texture === \"string\" && special.texture) return { model: node.base, special };\n break;\n case \"head\":\n case \"minecraft:head\":\n if (typeof special.kind === \"string\" && special.kind) return { model: node.base, special };\n break;\n }\n throw new Error(`Unsupported special item renderer ${special.type} for ${key.toNamespacedString()}`);\n }\n case \"condition\": {\n const value = this.propertyValue(node, context);\n if (typeof value !== \"boolean\") throw new Error(`Item-preview condition ${node.property} requires a boolean`);\n return this.selectItemModel(value ? node.on_true : node.on_false, key, context);\n }\n case \"select\": {\n const value = this.propertyValue(node, context);\n const component = node.property && this.contextIdentifier(node.property) === \"minecraft:component\";\n if (!component && value !== undefined && typeof value !== \"string\") throw new Error(`Item-preview selector ${node.property} requires a string`);\n const matches = (candidate: unknown) => component\n ? JSON.stringify(this.snapshotJson(candidate)) === JSON.stringify(this.snapshotJson(value)) : candidate === value;\n const selected = value === undefined ? undefined\n : node.cases?.find(entry => matches(entry.when) || Array.isArray(entry.when) && entry.when.some(matches))?.model;\n return this.selectItemModel(selected ?? node.fallback, key, context);\n }\n case \"range_dispatch\": {\n const value = this.propertyValue(node, context);\n if (typeof value !== \"number\") throw new Error(`Item-preview range ${node.property} requires a number`);\n if (Number.isNaN(value)) return this.selectItemModel(node.fallback, key, context);\n const scaled = value * (node.scale ?? 1);\n if (!Number.isFinite(scaled)) throw new Error(`Item-preview range ${node.property} requires a finite value and scale`);\n const selected = node.entries?.reduce<{ threshold: number; model: ItemModelNode } | undefined>((match, entry) => {\n return entry.threshold <= scaled && (!match || entry.threshold >= match.threshold) ? entry : match;\n }, undefined);\n return this.selectItemModel(selected?.model ?? node.fallback, key, context);\n }\n }\n throw new Error(`Unsupported item model ${node?.type ?? \"definition\"} for ${key.toNamespacedString()}`);\n }\n\n /** Loads one model file without resolving its parents. Returns `undefined` when the file is missing. */\n public static async getRaw(key: AssetKey): Promise<Maybe<Model>> {\n if (!key.assetType) {\n key.assetType = \"models\";\n }\n if (!key.extension) {\n key.extension = \".json\";\n }\n const keyStr = key.serialize();\n //TODO: maybe add the asset source to the key\n return Caching.rawModelCache.get(keyStr, k => {\n return this.PERSISTENT_CACHE.getOrLoad(AssetLoader.persistentKey(keyStr), k1 => {\n return AssetLoader.get<Model>(key, AssetParser.MODEL);\n })\n }).then(asset => {\n if (asset) {\n asset.key = key;\n }\n return asset;\n })\n }\n\n /**\n * Loads a model and resolves its parent chain. Returns `undefined` when the model is missing.\n * Item keys default to GUI context and a stack count of 1. Unresolved conditions are false and numeric properties are zero.\n * Versioned stack-size, durability, and glint defaults apply unless components override them.\n * Pass `context` to supply component values, property overrides, and item references for a preview.\n * Composite items retain independently merged children in `ItemModel.parts`.\n *\n * @param key - Model key, for example `AssetKey.parse(\"models\", \"minecraft:item/diamond_sword\")`.\n */\n public static async getMerged(key: AssetKey, context: ItemModelContext = {}): Promise<Maybe<Model>> {\n if (!key.assetType) {\n key.assetType = \"models\";\n }\n if (!key.extension) {\n key.extension = \".json\";\n }\n const preview = this.snapshotContext(key, context);\n if (key.type === \"item\") {\n const renamed = await Renames.key(\"items\", key);\n const replacement = renamed && await this.getMerged(renamed, preview);\n if (replacement) return replacement;\n }\n const dataKey = await this.applyDefaults(key, preview);\n const keyStr = AssetLoader.persistentKey(key.serialize() + (key.type === \"item\" ? this.contextKey(preview) + dataKey : \"\"));\n const model = await Caching.mergedModelCache.get(keyStr, async () => {\n //TODO: persistent cache\n const raw = key.type === \"item\" ? await this.getPreparedItemModel(key, preview, dataKey) : await this.getRaw(key);\n const merged = raw ? await ModelMerger.mergeWithParents(raw) : undefined;\n return merged;\n });\n return model;\n }\n\n /** Alias for {@link getMerged}. */\n public static async get(key: AssetKey, context: ItemModelContext = {}): Promise<Maybe<Model>> {\n return this.getMerged(key, context);\n }\n\n /** Clears persisted models. Use {@link Caching.clear} to also discard in-memory assets. */\n public static async clearCache() {\n return this.PERSISTENT_CACHE.clear();\n }\n\n}\n\ninterface ItemModelNode {\n type: string;\n model?: string | SpecialItemRenderer;\n tints?: ItemTintSource[];\n base?: string;\n property?: string;\n index?: number;\n component?: string;\n ignore_default?: boolean;\n normalize?: boolean;\n block_state_property?: string;\n on_false?: ItemModelNode;\n on_true?: ItemModelNode;\n fallback?: ItemModelNode;\n cases?: Array<{ when: unknown; model: ItemModelNode }>;\n entries?: Array<{ threshold: number; model: ItemModelNode }>;\n scale?: number;\n models?: ItemModelNode[];\n}\n\ntype SelectedItemModel = { model: string; special?: SpecialItemRenderer; tints?: ItemTintSource[] }\n | { parts: SelectedItemModel[] }\n | { item: AssetKey };\n"],"mappings":"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","names":["model"]}
@@ -2,10 +2,12 @@
2
2
  import { TextWriter, Uint8ArrayReader, ZipReader } from "@zip.js/zip.js";
3
3
  import { AssetKey } from "../AssetKey.mjs";
4
4
  import { AssetLoader } from "../AssetLoader.mjs";
5
- import { DEFAULT_NAMESPACE } from "../Assets.mjs";
5
+ import { DEFAULT_NAMESPACE } from "../AssetDefaults.mjs";
6
6
  import { Caching } from "../../cache/Caching.mjs";
7
7
  import { AssetParser } from "../source/parser/AssetParsers.mjs";
8
8
  import { createCanvas } from "../../canvas/CanvasCompat.mjs";
9
+ import { logger } from "../../util/log.mjs";
10
+ var log = logger("Unihex");
9
11
  var ATLAS_SIZE = 512;
10
12
  var GLYPH_HEIGHT = 16;
11
13
  var UnihexAtlas = class {
@@ -93,7 +95,7 @@ async function parseUnihex(key) {
93
95
  }
94
96
  return { indices, rows, metrics };
95
97
  } catch (error) {
96
- console.warn(`Could not load Unihex file ${key.toNamespacedString()}`, error);
98
+ log.warn(`Could not load Unihex file ${key.toNamespacedString()}`, error);
97
99
  return void 0;
98
100
  }
99
101
  }
@@ -112,7 +114,7 @@ async function loadUnihex(provider, fontKey, characters) {
112
114
  return { ...override, from, to };
113
115
  });
114
116
  } catch (error) {
115
- console.warn(`Could not load Unihex file ${key.toNamespacedString()}`, error);
117
+ log.warn(`Could not load Unihex file ${key.toNamespacedString()}`, error);
116
118
  return glyphs;
117
119
  }
118
120
  const file = await Caching.unihexCache.get(key.serialize(), () => parseUnihex(key));
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../src/assets/_fonts/Unihex.ts"],"sourcesContent":["import { TextWriter, Uint8ArrayReader, ZipReader } from \"@zip.js/zip.js\";\nimport { AssetKey } from \"../AssetKey\";\nimport { AssetLoader } from \"../AssetLoader\";\nimport { DEFAULT_NAMESPACE } from \"../Assets\";\nimport { Caching } from \"../../cache/Caching\";\nimport { AssetParser } from \"../source/parser/AssetParsers\";\nimport { createCanvas, type CompatCanvas } from \"../../canvas/CanvasCompat\";\nimport type { BitmapGlyph } from \"../Fonts\";\nimport type { BinaryAsset } from \"../source/HostedAssetSource\";\n\nexport interface UnihexProvider {\n type: \"unihex\" | \"minecraft:unihex\";\n hex_file: string;\n size_overrides?: { from: string; to: string; left: number; right: number }[];\n}\n\ninterface HexGlyph {\n rows: Uint32Array;\n bitWidth: number;\n left: number;\n right: number;\n}\n\nexport interface UnihexFile {\n indices: Int32Array;\n rows: Uint32Array;\n metrics: Uint8Array;\n}\n\nconst ATLAS_SIZE = 512;\nconst GLYPH_HEIGHT = 16;\n\n/** Packs glyphs into shared pages only when their pixels or source rectangles are requested. */\nclass UnihexAtlas {\n private image?: CompatCanvas;\n private x = 0;\n private y = 0;\n\n public draw(glyph: HexGlyph): { image: CompatCanvas; x: number; y: number } {\n const width = glyph.right - glyph.left + 1;\n if (this.image && this.x + width > this.image.width) {\n this.x = 0;\n this.y += GLYPH_HEIGHT;\n }\n if (!this.image || this.y + GLYPH_HEIGHT > this.image.height || width > this.image.width) {\n this.image = createCanvas(Math.max(ATLAS_SIZE, width), ATLAS_SIZE);\n this.x = 0;\n this.y = 0;\n }\n const context = this.image.getContext(\"2d\") as CanvasRenderingContext2D;\n const pixels = context.createImageData(width, GLYPH_HEIGHT);\n for (let y = 0; y < GLYPH_HEIGHT; y++) {\n for (let x = 0; x < width; x++) {\n const column = glyph.left + x;\n if (column < 0 || column >= glyph.bitWidth || !(glyph.rows[y] >>> (glyph.bitWidth - column - 1) & 1)) continue;\n pixels.data.fill(255, (y * width + x) * 4, (y * width + x + 1) * 4);\n }\n }\n const result = { image: this.image, x: this.x, y: this.y };\n context.putImageData(pixels, this.x, this.y);\n this.x += width;\n return result;\n }\n}\n\nfunction readHex(text: string, filename: string, glyphs: Map<number, HexGlyph>): void {\n const lines = text.split(\"\\n\");\n if (lines[lines.length - 1] === \"\") lines.pop();\n lines.forEach((line, index) => {\n const match = /^([0-9A-F]{4,6}):([0-9A-F]+)$/.exec(line);\n if (!match || ![32, 64, 96, 128].includes(match[2].length)) {\n throw new Error(`Invalid Unihex record in ${filename} at line ${index + 1}`);\n }\n const codepoint = parseInt(match[1], 16);\n if (codepoint > 0x10ffff) throw new Error(`Invalid Unihex codepoint in ${filename} at line ${index + 1}`);\n const bitWidth = match[2].length / 4;\n const rowLength = bitWidth / 4;\n const rows = new Uint32Array(GLYPH_HEIGHT);\n let mask = 0;\n for (let y = 0; y < GLYPH_HEIGHT; y++) {\n rows[y] = parseInt(match[2].slice(y * rowLength, (y + 1) * rowLength), 16);\n mask |= rows[y];\n }\n let left = 0, right = bitWidth;\n if (mask) {\n while (!(mask >>> (bitWidth - left - 1) & 1)) left++;\n right = bitWidth - 1;\n while (!(mask >>> (bitWidth - right - 1) & 1)) right--;\n }\n glyphs.set(codepoint, { rows, bitWidth, left, right });\n });\n}\n\nconst atlases = new WeakMap<UnihexProvider, UnihexAtlas>();\n\nasync function parseUnihex(key: AssetKey): Promise<UnihexFile | undefined> {\n try {\n const asset = await AssetLoader.get<BinaryAsset>(key, AssetParser.BINARY);\n if (!asset) throw new Error(`Could not load Unihex archive ${key.toNamespacedString()}`);\n const records = new Map<number, HexGlyph>();\n const reader = new ZipReader(new Uint8ArrayReader(asset.data), { useWebWorkers: false, useCompressionStream: false });\n try {\n for (const entry of await reader.getEntries()) {\n if (!entry.directory && entry.filename.endsWith(\".hex\")) {\n readHex(await entry.getData!(new TextWriter(), { checkSignature: true }), entry.filename, records);\n }\n }\n } finally {\n await reader.close();\n }\n const indices = new Int32Array(0x110000).fill(-1);\n const rows = new Uint32Array(records.size * GLYPH_HEIGHT), metrics = new Uint8Array(records.size * 3);\n let index = 0;\n for (const [codepoint, record] of records) {\n indices[codepoint] = index;\n rows.set(record.rows, index * GLYPH_HEIGHT);\n metrics.set([record.bitWidth, record.left, record.right], index * 3);\n index++;\n }\n return { indices, rows, metrics };\n } catch (error) {\n console.warn(`Could not load Unihex file ${key.toNamespacedString()}`, error);\n return undefined;\n }\n}\n\n/** Resolves Unihex characters with vanilla metrics and lazily rasterized, half-resolution glyphs. */\nexport async function loadUnihex(provider: UnihexProvider, fontKey: AssetKey, characters: string): Promise<Map<string, BitmapGlyph>> {\n const origin = new AssetKey(DEFAULT_NAMESPACE, \"\", undefined, undefined, \"assets\", \"\", fontKey.root);\n const key = AssetKey.parse(\"font\", provider.hex_file, origin);\n // Archive references already include their directory beneath the namespace root.\n key.assetType = undefined;\n const glyphs = new Map<string, BitmapGlyph>();\n let overrides;\n try {\n overrides = (provider.size_overrides ?? []).map(override => {\n const from = override.from.codePointAt(0), to = override.to.codePointAt(0);\n if ([...override.from].length !== 1 || [...override.to].length !== 1 || from! >= to!\n || !Number.isInteger(override.left) || !Number.isInteger(override.right) || override.right < override.left) {\n throw new Error(`Invalid Unihex size override in font ${fontKey.toNamespacedString()}`);\n }\n return { ...override, from: from!, to: to! };\n });\n } catch (error) {\n console.warn(`Could not load Unihex file ${key.toNamespacedString()}`, error);\n return glyphs;\n }\n const file = await Caching.unihexCache.get(key.serialize(), () => parseUnihex(key));\n if (!file) return glyphs;\n let atlas = atlases.get(provider);\n if (!atlas) { atlas = new UnihexAtlas(); atlases.set(provider, atlas); }\n for (const character of characters) {\n const codepoint = character.codePointAt(0)!, index = file.indices[codepoint];\n if (index < 0) continue;\n const record = { rows: file.rows.subarray(index * GLYPH_HEIGHT, (index + 1) * GLYPH_HEIGHT),\n bitWidth: file.metrics[index * 3], left: file.metrics[index * 3 + 1], right: file.metrics[index * 3 + 2] };\n const override = overrides.find(range => codepoint >= range.from && codepoint <= range.to);\n if (override) { record.left = override.left; record.right = override.right; }\n const width = record.right - record.left + 1;\n let rendered: ReturnType<UnihexAtlas[\"draw\"]> | undefined;\n const render = () => rendered ??= atlas!.draw(record);\n glyphs.set(character, {\n get image() { return render().image; },\n get x() { return render().x; },\n get y() { return render().y; },\n width, height: GLYPH_HEIGHT, scale: 0.5, ascent: 7, advance: Math.floor(width / 2) + 1,\n boldOffset: 0.5, shadowOffset: 0.5\n });\n }\n return glyphs;\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../../../src/assets/_fonts/Unihex.ts"],"sourcesContent":["import { TextWriter, Uint8ArrayReader, ZipReader } from \"@zip.js/zip.js\";\nimport { AssetKey } from \"../AssetKey\";\nimport { AssetLoader } from \"../AssetLoader\";\nimport { DEFAULT_NAMESPACE } from \"../AssetDefaults\";\nimport { Caching } from \"../../cache/Caching\";\nimport { AssetParser } from \"../source/parser/AssetParsers\";\nimport { createCanvas, type CompatCanvas } from \"../../canvas/CanvasCompat\";\nimport type { BitmapGlyph } from \"../Fonts\";\nimport type { BinaryAsset } from \"../source/HostedAssetSource\";\nimport { logger } from \"../../util/log\";\n\nconst log = logger(\"Unihex\");\n\nexport interface UnihexProvider {\n type: \"unihex\" | \"minecraft:unihex\";\n hex_file: string;\n size_overrides?: { from: string; to: string; left: number; right: number }[];\n}\n\ninterface HexGlyph {\n rows: Uint32Array;\n bitWidth: number;\n left: number;\n right: number;\n}\n\nexport interface UnihexFile {\n indices: Int32Array;\n rows: Uint32Array;\n metrics: Uint8Array;\n}\n\nconst ATLAS_SIZE = 512;\nconst GLYPH_HEIGHT = 16;\n\n/** Packs glyphs into shared pages only when their pixels or source rectangles are requested. */\nclass UnihexAtlas {\n private image?: CompatCanvas;\n private x = 0;\n private y = 0;\n\n public draw(glyph: HexGlyph): { image: CompatCanvas; x: number; y: number } {\n const width = glyph.right - glyph.left + 1;\n if (this.image && this.x + width > this.image.width) {\n this.x = 0;\n this.y += GLYPH_HEIGHT;\n }\n if (!this.image || this.y + GLYPH_HEIGHT > this.image.height || width > this.image.width) {\n this.image = createCanvas(Math.max(ATLAS_SIZE, width), ATLAS_SIZE);\n this.x = 0;\n this.y = 0;\n }\n const context = this.image.getContext(\"2d\") as CanvasRenderingContext2D;\n const pixels = context.createImageData(width, GLYPH_HEIGHT);\n for (let y = 0; y < GLYPH_HEIGHT; y++) {\n for (let x = 0; x < width; x++) {\n const column = glyph.left + x;\n if (column < 0 || column >= glyph.bitWidth || !(glyph.rows[y] >>> (glyph.bitWidth - column - 1) & 1)) continue;\n pixels.data.fill(255, (y * width + x) * 4, (y * width + x + 1) * 4);\n }\n }\n const result = { image: this.image, x: this.x, y: this.y };\n context.putImageData(pixels, this.x, this.y);\n this.x += width;\n return result;\n }\n}\n\nfunction readHex(text: string, filename: string, glyphs: Map<number, HexGlyph>): void {\n const lines = text.split(\"\\n\");\n if (lines[lines.length - 1] === \"\") lines.pop();\n lines.forEach((line, index) => {\n const match = /^([0-9A-F]{4,6}):([0-9A-F]+)$/.exec(line);\n if (!match || ![32, 64, 96, 128].includes(match[2].length)) {\n throw new Error(`Invalid Unihex record in ${filename} at line ${index + 1}`);\n }\n const codepoint = parseInt(match[1], 16);\n if (codepoint > 0x10ffff) throw new Error(`Invalid Unihex codepoint in ${filename} at line ${index + 1}`);\n const bitWidth = match[2].length / 4;\n const rowLength = bitWidth / 4;\n const rows = new Uint32Array(GLYPH_HEIGHT);\n let mask = 0;\n for (let y = 0; y < GLYPH_HEIGHT; y++) {\n rows[y] = parseInt(match[2].slice(y * rowLength, (y + 1) * rowLength), 16);\n mask |= rows[y];\n }\n let left = 0, right = bitWidth;\n if (mask) {\n while (!(mask >>> (bitWidth - left - 1) & 1)) left++;\n right = bitWidth - 1;\n while (!(mask >>> (bitWidth - right - 1) & 1)) right--;\n }\n glyphs.set(codepoint, { rows, bitWidth, left, right });\n });\n}\n\nconst atlases = new WeakMap<UnihexProvider, UnihexAtlas>();\n\nasync function parseUnihex(key: AssetKey): Promise<UnihexFile | undefined> {\n try {\n const asset = await AssetLoader.get<BinaryAsset>(key, AssetParser.BINARY);\n if (!asset) throw new Error(`Could not load Unihex archive ${key.toNamespacedString()}`);\n const records = new Map<number, HexGlyph>();\n const reader = new ZipReader(new Uint8ArrayReader(asset.data), { useWebWorkers: false, useCompressionStream: false });\n try {\n for (const entry of await reader.getEntries()) {\n if (!entry.directory && entry.filename.endsWith(\".hex\")) {\n readHex(await entry.getData!(new TextWriter(), { checkSignature: true }), entry.filename, records);\n }\n }\n } finally {\n await reader.close();\n }\n const indices = new Int32Array(0x110000).fill(-1);\n const rows = new Uint32Array(records.size * GLYPH_HEIGHT), metrics = new Uint8Array(records.size * 3);\n let index = 0;\n for (const [codepoint, record] of records) {\n indices[codepoint] = index;\n rows.set(record.rows, index * GLYPH_HEIGHT);\n metrics.set([record.bitWidth, record.left, record.right], index * 3);\n index++;\n }\n return { indices, rows, metrics };\n } catch (error) {\n log.warn(`Could not load Unihex file ${key.toNamespacedString()}`, error);\n return undefined;\n }\n}\n\n/** Resolves Unihex characters with vanilla metrics and lazily rasterized, half-resolution glyphs. */\nexport async function loadUnihex(provider: UnihexProvider, fontKey: AssetKey, characters: string): Promise<Map<string, BitmapGlyph>> {\n const origin = new AssetKey(DEFAULT_NAMESPACE, \"\", undefined, undefined, \"assets\", \"\", fontKey.root);\n const key = AssetKey.parse(\"font\", provider.hex_file, origin);\n // Archive references already include their directory beneath the namespace root.\n key.assetType = undefined;\n const glyphs = new Map<string, BitmapGlyph>();\n let overrides;\n try {\n overrides = (provider.size_overrides ?? []).map(override => {\n const from = override.from.codePointAt(0), to = override.to.codePointAt(0);\n if ([...override.from].length !== 1 || [...override.to].length !== 1 || from! >= to!\n || !Number.isInteger(override.left) || !Number.isInteger(override.right) || override.right < override.left) {\n throw new Error(`Invalid Unihex size override in font ${fontKey.toNamespacedString()}`);\n }\n return { ...override, from: from!, to: to! };\n });\n } catch (error) {\n log.warn(`Could not load Unihex file ${key.toNamespacedString()}`, error);\n return glyphs;\n }\n const file = await Caching.unihexCache.get(key.serialize(), () => parseUnihex(key));\n if (!file) return glyphs;\n let atlas = atlases.get(provider);\n if (!atlas) { atlas = new UnihexAtlas(); atlases.set(provider, atlas); }\n for (const character of characters) {\n const codepoint = character.codePointAt(0)!, index = file.indices[codepoint];\n if (index < 0) continue;\n const record = { rows: file.rows.subarray(index * GLYPH_HEIGHT, (index + 1) * GLYPH_HEIGHT),\n bitWidth: file.metrics[index * 3], left: file.metrics[index * 3 + 1], right: file.metrics[index * 3 + 2] };\n const override = overrides.find(range => codepoint >= range.from && codepoint <= range.to);\n if (override) { record.left = override.left; record.right = override.right; }\n const width = record.right - record.left + 1;\n let rendered: ReturnType<UnihexAtlas[\"draw\"]> | undefined;\n const render = () => rendered ??= atlas!.draw(record);\n glyphs.set(character, {\n get image() { return render().image; },\n get x() { return render().x; },\n get y() { return render().y; },\n width, height: GLYPH_HEIGHT, scale: 0.5, ascent: 7, advance: Math.floor(width / 2) + 1,\n boldOffset: 0.5, shadowOffset: 0.5\n });\n }\n return glyphs;\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,22 @@
1
+ // src/assets/_versions/DatasetVersions.ts
2
+ var parseRelease = (value) => /^\d+\.\d+(?:\.\d+)?$/.test(value) ? value.split(".").map(Number) : void 0;
3
+ var compare = (left, right) => {
4
+ for (let i = 0; i < 3; i++) {
5
+ const difference = (left[i] ?? 0) - (right[i] ?? 0);
6
+ if (difference) return difference;
7
+ }
8
+ return 0;
9
+ };
10
+ var nearestRelease = (requestedVersion, published) => {
11
+ const requested = parseRelease(requestedVersion);
12
+ if (!requested) return void 0;
13
+ const versions = published.map((name) => ({ name, number: parseRelease(name) })).filter((entry) => !!entry.number).sort((left, right) => compare(left.number, right.number));
14
+ const sameLine = versions.filter((entry) => entry.number[0] === requested[0] && entry.number[1] === requested[1]);
15
+ const selected = sameLine.sort((left, right) => Math.abs((left.number[2] ?? 0) - (requested[2] ?? 0)) - Math.abs((right.number[2] ?? 0) - (requested[2] ?? 0)) || compare(left.number, right.number))[0] ?? versions.filter((entry) => compare(entry.number, requested) <= 0).pop() ?? versions[0];
16
+ return selected?.name;
17
+ };
18
+ export {
19
+ nearestRelease,
20
+ parseRelease
21
+ };
22
+ //# sourceMappingURL=DatasetVersions.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../src/assets/_versions/DatasetVersions.ts"],"sourcesContent":["/** Parses release versions; snapshots and other names yield undefined. */\nexport const parseRelease = (value: string): number[] | undefined => /^\\d+\\.\\d+(?:\\.\\d+)?$/.test(value) ? value.split(\".\").map(Number) : undefined;\nconst compare = (left: number[], right: number[]): number => {\n for (let i = 0; i < 3; i++) {\n const difference = (left[i] ?? 0) - (right[i] ?? 0);\n if (difference) return difference;\n }\n return 0;\n};\n\n/** Selects the nearest patch (older on ties), then the latest earlier release or oldest published release. */\nexport const nearestRelease = (requestedVersion: string, published: readonly string[]): string | undefined => {\n const requested = parseRelease(requestedVersion);\n if (!requested) return undefined;\n const versions = published.map(name => ({ name, number: parseRelease(name) }))\n .filter((entry): entry is { name: string; number: number[] } => !!entry.number)\n .sort((left, right) => compare(left.number, right.number));\n const sameLine = versions.filter(entry => entry.number[0] === requested[0] && entry.number[1] === requested[1]);\n const selected = sameLine.sort((left, right) => Math.abs((left.number[2] ?? 0) - (requested[2] ?? 0))\n - Math.abs((right.number[2] ?? 0) - (requested[2] ?? 0)) || compare(left.number, right.number))[0]\n ?? versions.filter(entry => compare(entry.number, requested) <= 0).pop()\n ?? versions[0];\n return selected?.name;\n};\n"],"mappings":";AACO,IAAM,eAAe,CAAC,UAAwC,uBAAuB,KAAK,KAAK,IAAI,MAAM,MAAM,GAAG,EAAE,IAAI,MAAM,IAAI;AACzI,IAAM,UAAU,CAAC,MAAgB,UAA4B;AACzD,WAAS,IAAI,GAAG,IAAI,GAAG,KAAK;AACxB,UAAM,cAAc,KAAK,CAAC,KAAK,MAAM,MAAM,CAAC,KAAK;AACjD,QAAI,WAAY,QAAO;AAAA,EAC3B;AACA,SAAO;AACX;AAGO,IAAM,iBAAiB,CAAC,kBAA0B,cAAqD;AAC1G,QAAM,YAAY,aAAa,gBAAgB;AAC/C,MAAI,CAAC,UAAW,QAAO;AACvB,QAAM,WAAW,UAAU,IAAI,WAAS,EAAE,MAAM,QAAQ,aAAa,IAAI,EAAE,EAAE,EACxE,OAAO,CAAC,UAAuD,CAAC,CAAC,MAAM,MAAM,EAC7E,KAAK,CAAC,MAAM,UAAU,QAAQ,KAAK,QAAQ,MAAM,MAAM,CAAC;AAC7D,QAAM,WAAW,SAAS,OAAO,WAAS,MAAM,OAAO,CAAC,MAAM,UAAU,CAAC,KAAK,MAAM,OAAO,CAAC,MAAM,UAAU,CAAC,CAAC;AAC9G,QAAM,WAAW,SAAS,KAAK,CAAC,MAAM,UAAU,KAAK,KAAK,KAAK,OAAO,CAAC,KAAK,MAAM,UAAU,CAAC,KAAK,EAAE,IAC9F,KAAK,KAAK,MAAM,OAAO,CAAC,KAAK,MAAM,UAAU,CAAC,KAAK,EAAE,KAAK,QAAQ,KAAK,QAAQ,MAAM,MAAM,CAAC,EAAE,CAAC,KAC9F,SAAS,OAAO,WAAS,QAAQ,MAAM,QAAQ,SAAS,KAAK,CAAC,EAAE,IAAI,KACpE,SAAS,CAAC;AACjB,SAAO,UAAU;AACrB;","names":[]}
@@ -1,4 +1,5 @@
1
1
  // src/assets/index.ts
2
+ export * from "./AssetDefaults.mjs";
2
3
  export * from "./AssetKey.mjs";
3
4
  export * from "./AssetLoader.mjs";
4
5
  export * from "./Assets.mjs";
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/assets/index.ts"],"sourcesContent":["// autogenerated\nexport * from './AssetKey';\nexport * from './AssetLoader';\nexport * from './Assets';\nexport * from './BannerPatterns';\nexport * from './Biomes';\nexport * from './BlockEntities';\nexport * from './BlockStates';\nexport * from './DecoratedPots';\nexport * from './Entities';\nexport * from './Fonts';\nexport * from './MineRenderData';\nexport * from './ModelTextures';\nexport * from './Models';\nexport * from './Renames';\nexport * from './source';\n"],"mappings":";AACA,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;","names":[]}
1
+ {"version":3,"sources":["../../../../src/assets/index.ts"],"sourcesContent":["// autogenerated\nexport * from './AssetDefaults';\nexport * from './AssetKey';\nexport * from './AssetLoader';\nexport * from './Assets';\nexport * from './BannerPatterns';\nexport * from './Biomes';\nexport * from './BlockEntities';\nexport * from './BlockStates';\nexport * from './DecoratedPots';\nexport * from './Entities';\nexport * from './Fonts';\nexport * from './MineRenderData';\nexport * from './ModelTextures';\nexport * from './Models';\nexport * from './Renames';\nexport * from './source';\n"],"mappings":";AACA,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;","names":[]}
@@ -1,16 +1,16 @@
1
1
  // src/assets/source/HostedAssetSource.ts
2
2
  import { AssetLoadError, AssetSource } from "./AssetSource.mjs";
3
- import { prefix } from "../../util/index.mjs";
3
+ import { logger } from "../../util/log.mjs";
4
4
  import { NBTHelper } from "../../nbt/index.mjs";
5
5
  import { ImageLoader } from "../../image/index.mjs";
6
6
  import { AssetKey } from "../AssetKey.mjs";
7
- import { DEFAULT_NAMESPACE } from "../Assets.mjs";
7
+ import { DEFAULT_NAMESPACE } from "../AssetDefaults.mjs";
8
8
  import { RequestError, Requests } from "../../request/index.mjs";
9
9
  import { AssetLoader } from "../AssetLoader.mjs";
10
10
  import { AssetParser } from "./parser/index.mjs";
11
11
  import { merge } from "../../util/_internal/merge.mjs";
12
12
  var BINARY_TIMEOUT = 6e4;
13
- var p = prefix("HostedAssetSource");
13
+ var log = logger("HostedAssetSource");
14
14
  var DEFAULT_OPTIONS = {
15
15
  retryDefaults: true
16
16
  };
@@ -22,14 +22,14 @@ var _HostedAssetSource = class _HostedAssetSource extends AssetSource {
22
22
  return direct;
23
23
  }
24
24
  if (key.namespace !== DEFAULT_NAMESPACE) {
25
- console.info(p, "Retrying", key, "with default namespace");
25
+ log.debug("Retrying", key, "with default namespace");
26
26
  const namespaceKey = new AssetKey(DEFAULT_NAMESPACE, key.path, key.assetType, key.type, key.rootType, key.extension, key.root);
27
27
  const namespaced = await this.load(namespaceKey, parser);
28
28
  if (typeof namespaced !== "undefined") {
29
29
  return namespaced;
30
30
  }
31
31
  if (typeof key.root !== "undefined" && key.root !== AssetLoader.ROOT || typeof this.root !== "undefined" && this.root !== AssetLoader.ROOT) {
32
- console.info(p, "Retrying", key, "with default root+namespace");
32
+ log.debug("Retrying", key, "with default root+namespace");
33
33
  const namespacedRootedKey = new AssetKey(DEFAULT_NAMESPACE, key.path, key.assetType, key.type, key.rootType, key.extension, AssetLoader.ROOT);
34
34
  const namespacedRooted = await this.load(namespacedRootedKey, parser);
35
35
  if (typeof namespacedRooted !== "undefined") {
@@ -37,7 +37,7 @@ var _HostedAssetSource = class _HostedAssetSource extends AssetSource {
37
37
  }
38
38
  }
39
39
  } else if (typeof key.root !== "undefined" && key.root !== AssetLoader.ROOT || typeof this.root !== "undefined" && this.root !== AssetLoader.ROOT) {
40
- console.info(p, "Retrying", key, "with default root");
40
+ log.debug("Retrying", key, "with default root");
41
41
  const rootKey = new AssetKey(key.namespace, key.path, key.assetType, key.type, key.rootType, key.extension, AssetLoader.ROOT);
42
42
  const rooted = await this.load(rootKey, parser);
43
43
  if (typeof rooted !== "undefined") {
@@ -47,9 +47,8 @@ var _HostedAssetSource = class _HostedAssetSource extends AssetSource {
47
47
  return void 0;
48
48
  }
49
49
  async load(key, parser) {
50
- console.info(p, "Loading", key);
51
50
  const url = `${this.assetBasePath(key)}${key.type !== void 0 ? key.type + "/" : ""}${key.path}${key.extension}`;
52
- console.debug(p, url);
51
+ log.debug("Loading", url);
53
52
  const request = { url };
54
53
  try {
55
54
  parser.config(request);
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../src/assets/source/HostedAssetSource.ts"],"sourcesContent":["import { AssetLoadError, AssetSource } from \"./AssetSource\";\nimport { BlockState, Model, TextureAsset } from \"../../model\";\nimport type { RequestConfig, RequestResponse } from \"../../request\";\nimport { Maybe, prefix } from \"../../util\";\nimport { MinecraftTextureMeta } from \"../../MinecraftTextureMeta\";\nimport { NBTAsset, NBTHelper } from \"../../nbt\";\nimport { ImageLoader } from \"../../image\";\nimport { ListAsset } from \"../../ListAsset\";\nimport { MinecraftAsset } from \"../../MinecraftAsset\";\nimport { AssetKey } from \"../AssetKey\";\nimport { DEFAULT_NAMESPACE } from \"../Assets\";\nimport { RequestError, Requests } from \"../../request\";\nimport { AssetLoader } from \"../AssetLoader\";\nimport { AssetParser } from \"./parser\";\nimport { ResponseParser } from \"./parser\";\nimport { merge } from \"../../util/_internal/merge\";\n\nconst BINARY_TIMEOUT = 60_000;\n\nconst p = prefix(\"HostedAssetSource\");\n\nconst DEFAULT_OPTIONS: HostedAssetSourceOptions = {\n retryDefaults: true\n}\n\n/** Loads assets over HTTP from a Minecraft directory tree rooted at the constructor's URL. */\nexport class HostedAssetSource extends AssetSource {\n\n static readonly MODEL: ResponseParser<Model> = {\n config(request: RequestConfig) {\n },\n parse(response: RequestResponse): Maybe<Model> {\n return response.data as Model;\n }\n }\n static readonly BLOCKSTATE: ResponseParser<BlockState> = {\n config(request: RequestConfig) {\n },\n parse(response: RequestResponse): Maybe<BlockState> {\n return response.data as BlockState;\n }\n }\n static readonly META: ResponseParser<MinecraftTextureMeta> = {\n config(request: RequestConfig) {\n // request.responseType = \"arraybuffer\";\n },\n parse(response: RequestResponse): Maybe<MinecraftTextureMeta> {\n return response.data as MinecraftTextureMeta;\n }\n }\n static readonly NBT: ResponseParser<NBTAsset> = {\n config(request: RequestConfig) {\n request.responseType = \"arraybuffer\";\n },\n parse(response: RequestResponse): Promise<Maybe<NBTAsset>> {\n return NBTHelper.fromBuffer(response.data);\n }\n }\n static readonly IMAGE: ResponseParser<TextureAsset> = {\n config(request: RequestConfig) {\n request.responseType = \"arraybuffer\";\n },\n async parse(response: RequestResponse): Promise<Maybe<TextureAsset>> {\n return await ImageLoader.processResponse(response) as TextureAsset;\n }\n }\n static readonly LIST: ResponseParser<ListAsset> = {\n config(request: RequestConfig) {\n },\n parse(response: RequestResponse): Maybe<ListAsset> {\n return response.data as ListAsset;\n }\n }\n static readonly JSON: ResponseParser<any> = {\n config(request: RequestConfig) {\n },\n parse(response: RequestResponse): Maybe<any> {\n return response.data;\n }\n }\n static readonly BINARY: ResponseParser<BinaryAsset> = {\n config(request: RequestConfig) {\n request.timeout = BINARY_TIMEOUT;\n request.responseType = \"arraybuffer\";\n },\n parse(response: RequestResponse): BinaryAsset {\n return { data: new Uint8Array(response.data as ArrayBuffer) };\n }\n }\n\n static readonly PARSER_MAP: Map<AssetParser, ResponseParser<any>> = new Map<AssetParser, ResponseParser<any>>([\n [AssetParser.MODEL, HostedAssetSource.MODEL],\n [AssetParser.BLOCKSTATE, HostedAssetSource.BLOCKSTATE],\n [AssetParser.META, HostedAssetSource.META],\n [AssetParser.NBT, HostedAssetSource.NBT],\n [AssetParser.IMAGE, HostedAssetSource.IMAGE],\n [AssetParser.LIST, HostedAssetSource.LIST],\n [AssetParser.JSON, HostedAssetSource.JSON],\n [AssetParser.BINARY, HostedAssetSource.BINARY],\n ]);\n\n /** Retries missing assets with the `minecraft` namespace and default root. Other failures reject. */\n public async loadOrRetryWithDefaults<T extends MinecraftAsset>(key: AssetKey, parser: ResponseParser<T>): Promise<Maybe<T>> {\n const direct = await this.load<T>(key, parser);\n if (typeof direct !== \"undefined\") {\n return direct;\n }\n if (key.namespace !== DEFAULT_NAMESPACE) {\n console.info(p, \"Retrying\", key, \"with default namespace\");\n // Try on the same host but with default minecraft: namespace\n const namespaceKey = new AssetKey(DEFAULT_NAMESPACE, key.path, key.assetType, key.type, key.rootType, key.extension, key.root);\n const namespaced = await this.load<T>(namespaceKey, parser);\n if (typeof namespaced !== \"undefined\") {\n return namespaced;\n }\n if ((typeof key.root !== \"undefined\" && key.root !== AssetLoader.ROOT) || (typeof this.root !== \"undefined\" && this.root !== AssetLoader.ROOT)) {\n console.info(p, \"Retrying\", key, \"with default root+namespace\");\n // Try both defaults\n const namespacedRootedKey = new AssetKey(DEFAULT_NAMESPACE, key.path, key.assetType, key.type, key.rootType, key.extension, AssetLoader.ROOT);\n const namespacedRooted = await this.load<T>(namespacedRootedKey, parser);\n if (typeof namespacedRooted !== \"undefined\") {\n return namespacedRooted;\n }\n }\n } else if ((typeof key.root !== \"undefined\" && key.root !== AssetLoader.ROOT) || (typeof this.root !== \"undefined\" && this.root !== AssetLoader.ROOT)) {\n console.info(p, \"Retrying\", key, \"with default root\");\n // Try on default root\n const rootKey = new AssetKey(key.namespace, key.path, key.assetType, key.type, key.rootType, key.extension, AssetLoader.ROOT);\n const rooted = await this.load<T>(rootKey, parser);\n if (typeof rooted !== \"undefined\") {\n return rooted;\n }\n }\n return undefined;\n }\n\n\n protected async load<T extends MinecraftAsset>(key: AssetKey, parser: ResponseParser<T>): Promise<Maybe<T>> {\n console.info(p, \"Loading\", key);\n const url = `${ this.assetBasePath(key) }${ key.type !== undefined ? key.type + '/' : '' }${ key.path }${ key.extension }`;\n console.debug(p, url);\n const request: RequestConfig = { url };\n try {\n parser.config(request);\n let response: RequestResponse;\n try {\n response = await Requests.mcAssetRequest(request);\n } catch (cause) {\n // HTTP 404 is the only request failure that permits source fallback.\n if (cause instanceof RequestError && cause.response?.status === 404) {\n return undefined;\n }\n throw cause;\n }\n if (response.data === undefined) {\n throw new Error(\"Asset response has no data\");\n }\n return await parser.parse(response);\n } catch (cause) {\n throw new AssetLoadError(this, key, request.url, cause);\n }\n }\n\n public assetBasePath(key: AssetKey) {\n return `${ key.root ?? this.root ?? AssetLoader.ROOT }/${ key.rootType !== undefined ? key.rootType + '/' : '' }${ key.namespace !== undefined ? key.namespace + '/' : '' }${ key.assetType !== undefined ? key.assetType + '/' : '' }`;\n }\n\n private readonly _root: string;\n private readonly _options: HostedAssetSourceOptions;\n\n /**\n * Creates a hosted source for {@link AssetLoader.addSource}.\n * Set `options.retryDefaults` to `false` to restrict lookups to the requested namespace and root.\n */\n public constructor(root: string, options?: Partial<HostedAssetSourceOptions>) {\n super();\n this._root = root;\n this._options = merge({}, DEFAULT_OPTIONS, options ?? {});\n }\n\n public get root(): string {\n return this._root;\n }\n\n public get cacheId(): string {\n return `hosted:${this._root}`;\n }\n\n public get options(): HostedAssetSourceOptions {\n return this._options;\n }\n\n public get<T extends MinecraftAsset>(key: AssetKey, parser: AssetParser): Promise<Maybe<T>> {\n const responseParser = HostedAssetSource.PARSER_MAP.get(parser) as ResponseParser<T>;\n if (this.options.retryDefaults && !(key.rootType === undefined && key.namespace === \"minerender-data\")) {\n return this.loadOrRetryWithDefaults(key, responseParser);\n }\n return this.load(key, responseParser);\n }\n\n}\n\ninterface HostedAssetSourceOptions {\n retryDefaults: boolean;\n}\n\n/** Encoded asset bytes loaded without JSON or image decoding. */\nexport interface BinaryAsset extends MinecraftAsset {\n data: Uint8Array;\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../../../src/assets/source/HostedAssetSource.ts"],"sourcesContent":["import { AssetLoadError, AssetSource } from \"./AssetSource\";\nimport { BlockState, Model, TextureAsset } from \"../../model\";\nimport type { RequestConfig, RequestResponse } from \"../../request\";\nimport { Maybe } from \"../../util\";\nimport { logger } from \"../../util/log\";\nimport { MinecraftTextureMeta } from \"../../MinecraftTextureMeta\";\nimport { NBTAsset, NBTHelper } from \"../../nbt\";\nimport { ImageLoader } from \"../../image\";\nimport { ListAsset } from \"../../ListAsset\";\nimport { MinecraftAsset } from \"../../MinecraftAsset\";\nimport { AssetKey } from \"../AssetKey\";\nimport { DEFAULT_NAMESPACE } from \"../AssetDefaults\";\nimport { RequestError, Requests } from \"../../request\";\nimport { AssetLoader } from \"../AssetLoader\";\nimport { AssetParser } from \"./parser\";\nimport { ResponseParser } from \"./parser\";\nimport { merge } from \"../../util/_internal/merge\";\n\nconst BINARY_TIMEOUT = 60_000;\n\nconst log = logger(\"HostedAssetSource\");\n\nconst DEFAULT_OPTIONS: HostedAssetSourceOptions = {\n retryDefaults: true\n}\n\n/** Loads assets over HTTP from a Minecraft directory tree rooted at the constructor's URL. */\nexport class HostedAssetSource extends AssetSource {\n\n static readonly MODEL: ResponseParser<Model> = {\n config(request: RequestConfig) {\n },\n parse(response: RequestResponse): Maybe<Model> {\n return response.data as Model;\n }\n }\n static readonly BLOCKSTATE: ResponseParser<BlockState> = {\n config(request: RequestConfig) {\n },\n parse(response: RequestResponse): Maybe<BlockState> {\n return response.data as BlockState;\n }\n }\n static readonly META: ResponseParser<MinecraftTextureMeta> = {\n config(request: RequestConfig) {\n // request.responseType = \"arraybuffer\";\n },\n parse(response: RequestResponse): Maybe<MinecraftTextureMeta> {\n return response.data as MinecraftTextureMeta;\n }\n }\n static readonly NBT: ResponseParser<NBTAsset> = {\n config(request: RequestConfig) {\n request.responseType = \"arraybuffer\";\n },\n parse(response: RequestResponse): Promise<Maybe<NBTAsset>> {\n return NBTHelper.fromBuffer(response.data);\n }\n }\n static readonly IMAGE: ResponseParser<TextureAsset> = {\n config(request: RequestConfig) {\n request.responseType = \"arraybuffer\";\n },\n async parse(response: RequestResponse): Promise<Maybe<TextureAsset>> {\n return await ImageLoader.processResponse(response) as TextureAsset;\n }\n }\n static readonly LIST: ResponseParser<ListAsset> = {\n config(request: RequestConfig) {\n },\n parse(response: RequestResponse): Maybe<ListAsset> {\n return response.data as ListAsset;\n }\n }\n static readonly JSON: ResponseParser<any> = {\n config(request: RequestConfig) {\n },\n parse(response: RequestResponse): Maybe<any> {\n return response.data;\n }\n }\n static readonly BINARY: ResponseParser<BinaryAsset> = {\n config(request: RequestConfig) {\n request.timeout = BINARY_TIMEOUT;\n request.responseType = \"arraybuffer\";\n },\n parse(response: RequestResponse): BinaryAsset {\n return { data: new Uint8Array(response.data as ArrayBuffer) };\n }\n }\n\n static readonly PARSER_MAP: Map<AssetParser, ResponseParser<any>> = new Map<AssetParser, ResponseParser<any>>([\n [AssetParser.MODEL, HostedAssetSource.MODEL],\n [AssetParser.BLOCKSTATE, HostedAssetSource.BLOCKSTATE],\n [AssetParser.META, HostedAssetSource.META],\n [AssetParser.NBT, HostedAssetSource.NBT],\n [AssetParser.IMAGE, HostedAssetSource.IMAGE],\n [AssetParser.LIST, HostedAssetSource.LIST],\n [AssetParser.JSON, HostedAssetSource.JSON],\n [AssetParser.BINARY, HostedAssetSource.BINARY],\n ]);\n\n /** Retries missing assets with the `minecraft` namespace and default root. Other failures reject. */\n public async loadOrRetryWithDefaults<T extends MinecraftAsset>(key: AssetKey, parser: ResponseParser<T>): Promise<Maybe<T>> {\n const direct = await this.load<T>(key, parser);\n if (typeof direct !== \"undefined\") {\n return direct;\n }\n if (key.namespace !== DEFAULT_NAMESPACE) {\n log.debug(\"Retrying\", key, \"with default namespace\");\n // Try on the same host but with default minecraft: namespace\n const namespaceKey = new AssetKey(DEFAULT_NAMESPACE, key.path, key.assetType, key.type, key.rootType, key.extension, key.root);\n const namespaced = await this.load<T>(namespaceKey, parser);\n if (typeof namespaced !== \"undefined\") {\n return namespaced;\n }\n if ((typeof key.root !== \"undefined\" && key.root !== AssetLoader.ROOT) || (typeof this.root !== \"undefined\" && this.root !== AssetLoader.ROOT)) {\n log.debug(\"Retrying\", key, \"with default root+namespace\");\n // Try both defaults\n const namespacedRootedKey = new AssetKey(DEFAULT_NAMESPACE, key.path, key.assetType, key.type, key.rootType, key.extension, AssetLoader.ROOT);\n const namespacedRooted = await this.load<T>(namespacedRootedKey, parser);\n if (typeof namespacedRooted !== \"undefined\") {\n return namespacedRooted;\n }\n }\n } else if ((typeof key.root !== \"undefined\" && key.root !== AssetLoader.ROOT) || (typeof this.root !== \"undefined\" && this.root !== AssetLoader.ROOT)) {\n log.debug(\"Retrying\", key, \"with default root\");\n // Try on default root\n const rootKey = new AssetKey(key.namespace, key.path, key.assetType, key.type, key.rootType, key.extension, AssetLoader.ROOT);\n const rooted = await this.load<T>(rootKey, parser);\n if (typeof rooted !== \"undefined\") {\n return rooted;\n }\n }\n return undefined;\n }\n\n\n protected async load<T extends MinecraftAsset>(key: AssetKey, parser: ResponseParser<T>): Promise<Maybe<T>> {\n const url = `${ this.assetBasePath(key) }${ key.type !== undefined ? key.type + '/' : '' }${ key.path }${ key.extension }`;\n log.debug(\"Loading\", url);\n const request: RequestConfig = { url };\n try {\n parser.config(request);\n let response: RequestResponse;\n try {\n response = await Requests.mcAssetRequest(request);\n } catch (cause) {\n // HTTP 404 is the only request failure that permits source fallback.\n if (cause instanceof RequestError && cause.response?.status === 404) {\n return undefined;\n }\n throw cause;\n }\n if (response.data === undefined) {\n throw new Error(\"Asset response has no data\");\n }\n return await parser.parse(response);\n } catch (cause) {\n throw new AssetLoadError(this, key, request.url, cause);\n }\n }\n\n public assetBasePath(key: AssetKey) {\n return `${ key.root ?? this.root ?? AssetLoader.ROOT }/${ key.rootType !== undefined ? key.rootType + '/' : '' }${ key.namespace !== undefined ? key.namespace + '/' : '' }${ key.assetType !== undefined ? key.assetType + '/' : '' }`;\n }\n\n private readonly _root: string;\n private readonly _options: HostedAssetSourceOptions;\n\n /**\n * Creates a hosted source for {@link AssetLoader.addSource}.\n * Set `options.retryDefaults` to `false` to restrict lookups to the requested namespace and root.\n */\n public constructor(root: string, options?: Partial<HostedAssetSourceOptions>) {\n super();\n this._root = root;\n this._options = merge({}, DEFAULT_OPTIONS, options ?? {});\n }\n\n public get root(): string {\n return this._root;\n }\n\n public get cacheId(): string {\n return `hosted:${this._root}`;\n }\n\n public get options(): HostedAssetSourceOptions {\n return this._options;\n }\n\n public get<T extends MinecraftAsset>(key: AssetKey, parser: AssetParser): Promise<Maybe<T>> {\n const responseParser = HostedAssetSource.PARSER_MAP.get(parser) as ResponseParser<T>;\n if (this.options.retryDefaults && !(key.rootType === undefined && key.namespace === \"minerender-data\")) {\n return this.loadOrRetryWithDefaults(key, responseParser);\n }\n return this.load(key, responseParser);\n }\n\n}\n\ninterface HostedAssetSourceOptions {\n retryDefaults: boolean;\n}\n\n/** Encoded asset bytes loaded without JSON or image decoding. */\nexport interface BinaryAsset extends MinecraftAsset {\n data: Uint8Array;\n}\n"],"mappings":"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","names":[]}
@@ -32,9 +32,12 @@ var _Caching = class _Caching {
32
32
  this.entityTextureCache,
33
33
  this.entityAnimationCache,
34
34
  this.blockEntityIndexCache,
35
+ this.entityDatasetVersionCache,
35
36
  this.fontCache,
36
37
  this.unihexCache,
37
38
  this.bannerPatternCache,
39
+ this.equipmentCache,
40
+ this.trimCache,
38
41
  this.mineRenderDataCache,
39
42
  this.usernameUuidCache,
40
43
  this.biomeCache
@@ -66,6 +69,8 @@ var _Caching = class _Caching {
66
69
  };
67
70
  }
68
71
  };
72
+ /** Cached in place of a missing asset. The caches drop `undefined` results, which would request the asset again. */
73
+ _Caching.MISSING = false;
69
74
  _Caching._generation = 0;
70
75
  _Caching.rawImageCache = Caches.builder().expireAfterWrite(Time.minutes(10)).expireAfterAccess(Time.minutes(5)).expirationInterval(Time.seconds(5)).buildAsync();
71
76
  _Caching.imageDataCache = Caches.builder().expireAfterWrite(Time.minutes(10)).expireAfterAccess(Time.minutes(5)).expirationInterval(Time.seconds(10)).buildAsync();
@@ -87,9 +92,12 @@ _Caching.entityModelCache = _Caching.createAssetCache();
87
92
  _Caching.entityTextureCache = _Caching.createAssetCache();
88
93
  _Caching.entityAnimationCache = _Caching.createAssetCache();
89
94
  _Caching.blockEntityIndexCache = _Caching.createAssetCache();
95
+ _Caching.entityDatasetVersionCache = _Caching.createAssetCache();
90
96
  _Caching.unihexCache = _Caching.createAssetCache();
91
97
  _Caching.fontCache = _Caching.createAssetCache();
92
98
  _Caching.bannerPatternCache = _Caching.createAssetCache();
99
+ _Caching.equipmentCache = _Caching.createAssetCache();
100
+ _Caching.trimCache = _Caching.createAssetCache();
93
101
  _Caching.mineRenderDataCache = _Caching.createAssetCache();
94
102
  _Caching.usernameUuidCache = Caches.builder().expireAfterWrite(Time.minutes(5)).expirationInterval(Time.seconds(30)).buildAsync();
95
103
  _Caching.biomeCache = _Caching.createAssetCache();