minerender 2.1.0-alpha.133 → 2.1.0-alpha.135

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 (47) hide show
  1. package/dist/browser/esm/Materials.mjs +3 -2
  2. package/dist/browser/esm/Materials.mjs.map +1 -1
  3. package/dist/browser/esm/assets/AssetDefaults.mjs +8 -0
  4. package/dist/browser/esm/assets/AssetDefaults.mjs.map +1 -0
  5. package/dist/browser/esm/assets/AssetKey.mjs +1 -1
  6. package/dist/browser/esm/assets/AssetKey.mjs.map +1 -1
  7. package/dist/browser/esm/assets/AssetLoader.mjs +1 -1
  8. package/dist/browser/esm/assets/AssetLoader.mjs.map +1 -1
  9. package/dist/browser/esm/assets/Assets.mjs +1 -5
  10. package/dist/browser/esm/assets/Assets.mjs.map +1 -1
  11. package/dist/browser/esm/assets/BlockStates.mjs +1 -1
  12. package/dist/browser/esm/assets/BlockStates.mjs.map +1 -1
  13. package/dist/browser/esm/assets/Entities.mjs +1 -1
  14. package/dist/browser/esm/assets/Entities.mjs.map +1 -1
  15. package/dist/browser/esm/assets/Models.mjs +1 -1
  16. package/dist/browser/esm/assets/Models.mjs.map +1 -1
  17. package/dist/browser/esm/assets/_fonts/Unihex.mjs +1 -1
  18. package/dist/browser/esm/assets/_fonts/Unihex.mjs.map +1 -1
  19. package/dist/browser/esm/assets/index.mjs +1 -0
  20. package/dist/browser/esm/assets/index.mjs.map +1 -1
  21. package/dist/browser/esm/assets/source/HostedAssetSource.mjs +1 -1
  22. package/dist/browser/esm/assets/source/HostedAssetSource.mjs.map +1 -1
  23. package/dist/browser/esm/env/browser/section.worker.mjs +5 -3
  24. package/dist/browser/esm/env/browser/section.worker.mjs.map +1 -1
  25. package/dist/browser/esm/index.browser.d.mts +5 -2
  26. package/dist/browser/esm/model/scene/ModelObject.mjs +4 -0
  27. package/dist/browser/esm/model/scene/ModelObject.mjs.map +1 -1
  28. package/dist/browser/esm/world/SectionGeometry.mjs +5 -3
  29. package/dist/browser/esm/world/SectionGeometry.mjs.map +1 -1
  30. package/dist/browser/esm/world/SectionMesh.mjs +4 -0
  31. package/dist/browser/esm/world/SectionMesh.mjs.map +1 -1
  32. package/dist/browser/esm/world/SectionModels.mjs +2 -2
  33. package/dist/browser/esm/world/SectionModels.mjs.map +1 -1
  34. package/dist/browser/esm/world/_culling/BlockCulling.mjs +1 -1
  35. package/dist/browser/esm/world/_culling/BlockCulling.mjs.map +1 -1
  36. package/dist/browser/index.d.ts +5 -2
  37. package/dist/browser/index.js +2725 -2710
  38. package/dist/browser/index.js.map +1 -1
  39. package/dist/bundle.js +7825 -7807
  40. package/dist/bundle.js.map +1 -1
  41. package/dist/node/index.d.mts +5 -2
  42. package/dist/node/index.d.ts +5 -2
  43. package/dist/node/index.js +2746 -2731
  44. package/dist/node/index.js.map +1 -1
  45. package/dist/node/index.mjs +2735 -2720
  46. package/dist/node/index.mjs.map +1 -1
  47. package/package.json +1 -1
@@ -139,6 +139,7 @@ var Materials = class _Materials {
139
139
  static createShadedCanvasMaterial(canvas, transparent = false, shade = false, boundUvs = false) {
140
140
  const vertShader = `
141
141
  uniform bool SHADE;
142
+ attribute float shade;
142
143
 
143
144
  // Keep MSAA edge pixels from sampling outside the face's atlas region.
144
145
  #if __VERSION__ >= 300
@@ -161,7 +162,7 @@ var Materials = class _Materials {
161
162
  void main()
162
163
  {
163
164
 
164
- if (SHADE) {
165
+ if (SHADE && shade > 0.5) {
165
166
 
166
167
  #ifdef USE_INSTANCING
167
168
  vec3 N = vec3( modelMatrix * instanceMatrix * vec4(normal, 0.0) );
@@ -270,7 +271,7 @@ var Materials = class _Materials {
270
271
  side: transparent ? DoubleSide : FrontSide,
271
272
  alphaTest: 0.5
272
273
  });
273
- Object.assign(material.defaultAttributeValues, { uvBounds: [0, 0, 1, 1] });
274
+ Object.assign(material.defaultAttributeValues, { shade: [1], uvBounds: [0, 0, 1, 1] });
274
275
  return material;
275
276
  } catch (e) {
276
277
  console.warn(e);
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/Materials.ts"],"sourcesContent":["import { MaterialKey, serializeMaterialKey } from \"./cache/CacheKey\";\nimport { Color, ColorRepresentation, CustomBlending, DoubleSide, OneFactor, OneMinusSrcAlphaFactor, RepeatWrapping, FrontSide, Material, MeshBasicMaterial, MeshLambertMaterial, MeshPhongMaterial, MeshStandardMaterial, ShaderChunk, ShaderMaterial } from \"three\";\nimport { Textures } from \"./texture/Textures\";\nimport { TextureLoader } from \"./texture/TextureLoader\";\nimport { Caching } from \"./cache/Caching\";\nimport { AssetKey } from \"./assets/AssetKey\";\nimport type { EntityRenderMode } from \"./entity/EntityModel\";\n\n/** Creates Minecraft model, entity, and GUI materials, with shared caches for image materials. */\nexport class Materials {\n\n /** Shared checkerboard material, created on first access. */\n public static get MISSING_TEXTURE(): Material {\n return Caching.materialCache.get(\"builtin:missing-texture\", () => new MeshBasicMaterial({\n map: Textures.getMissing(),\n alphaTest: 0.5\n }))!;\n }\n\n public static createImage(key: MaterialKey): Material {\n //TODO: type from key\n const transparent = key.transparent || false;\n return new MeshBasicMaterial({\n map: Textures.getImage(key.texture),\n transparent: transparent,\n side: transparent ? DoubleSide : FrontSide,\n alphaTest: 0.5\n });\n //TODO: params\n }\n\n\n public static createBasicCanvasMaterial(canvas: HTMLCanvasElement, transparent: boolean = false, shade: boolean = false): Material {\n if (shade) {\n return new MeshStandardMaterial({\n map: Textures.createCanvasTexture(canvas),\n transparent: transparent,\n side: transparent ? DoubleSide : FrontSide,\n alphaTest: 0.5,\n\n })\n }\n return new MeshBasicMaterial({\n map: Textures.createCanvasTexture(canvas),\n transparent: transparent,\n side: transparent ? DoubleSide : FrontSide,\n alphaTest: 0.5,\n\n })\n }\n\n /** Whether vanilla's render type for the mode culls back faces. */\n public static entityModeCulls(mode: EntityRenderMode = \"cutout\"): boolean {\n return mode === \"cutout_cull\" || mode === \"solid\" || mode === \"eyes\" || mode === \"water_mask\";\n }\n\n /** UV offset per tick of entity age for the scrolling modes, as vanilla's texture matrix applies it. */\n public static entityModeScroll(mode: EntityRenderMode = \"cutout\"): [number, number] | undefined {\n if (mode === \"energy_swirl\") return [0.01, 0.01];\n if (mode === \"breeze_wind\") return [0.02, 0];\n return undefined;\n }\n\n /**\n * Entity material for one of vanilla's render types. Entities are unlit here, so the lit and full-bright modes\n * differ only in blending and depth state. Culling is not a material property: {@link entityModeCulls} decides\n * whether the geometry gets inward faces.\n */\n public static createEntityCanvasMaterial(canvas: HTMLCanvasElement, mode: EntityRenderMode = \"cutout\", tint?: ColorRepresentation): MeshBasicMaterial {\n const material = Materials.createBasicCanvasMaterial(canvas) as MeshBasicMaterial;\n switch (mode) {\n case \"cutout\":\n case \"cutout_cull\":\n break;\n case \"cutout_z_offset\":\n material.polygonOffset = true;\n material.polygonOffsetFactor = -1;\n material.polygonOffsetUnits = -10;\n break;\n case \"solid\":\n material.alphaTest = 0;\n break;\n case \"translucent\":\n case \"breeze_wind\":\n material.transparent = true;\n material.alphaTest = 0.1;\n break;\n case \"translucent_emissive\":\n material.transparent = true;\n material.alphaTest = 0.1;\n material.depthWrite = false;\n break;\n case \"eyes\":\n case \"no_outline\":\n material.transparent = true;\n material.alphaTest = 0;\n material.depthWrite = false;\n break;\n case \"energy_swirl\":\n material.transparent = true;\n material.alphaTest = 0.1;\n material.blending = CustomBlending;\n material.blendSrc = OneFactor;\n material.blendDst = OneFactor;\n // The canvas is premultiplied: a glow pixel needs alpha, or browsers and image exports drop it wherever\n // nothing opaque is behind it. Its brightness serves as coverage, so the glow stays visible outside the body.\n material.blendSrcAlpha = OneFactor;\n material.blendDstAlpha = OneMinusSrcAlphaFactor;\n material.onBeforeCompile = shader => {\n shader.fragmentShader = shader.fragmentShader.replace(\"#include <dithering_fragment>\",\n \"gl_FragColor.a = max(gl_FragColor.r, max(gl_FragColor.g, gl_FragColor.b));\\n#include <dithering_fragment>\");\n };\n material.customProgramCacheKey = () => \"energy_swirl\";\n // Vanilla submits the swirl with half-grey vertex colour.\n material.color.set(0x808080);\n break;\n case \"water_mask\":\n material.alphaTest = 0;\n material.colorWrite = false;\n break;\n }\n if (Materials.entityModeScroll(mode)) {\n material.map!.wrapS = material.map!.wrapT = RepeatWrapping;\n }\n if (tint !== undefined) material.color.multiply(new Color(tint));\n return material;\n }\n\n /** Creates an unlit, transparent GUI material without depth writes or tone mapping. */\n public static createGuiCanvasMaterial(canvas: HTMLCanvasElement): MeshBasicMaterial {\n const material = new MeshBasicMaterial({\n map: Textures.createCanvasTexture(canvas),\n transparent: true,\n depthWrite: false,\n side: DoubleSide,\n toneMapped: false\n });\n material.onBeforeCompile = shader => {\n // Keep MSAA edge pixels inside the layer's cropped texture region.\n for (const [stage, direction] of [[\"vertex\", \"out\"], [\"fragment\", \"in\"]] as const) {\n const chunk = `uv_pars_${stage}` as const;\n shader[`${stage}Shader`] = shader[`${stage}Shader`].replace(`#include <${chunk}>`,\n ShaderChunk[chunk].replace(\"varying vec2 vMapUv;\", `\n #if __VERSION__ >= 300\n centroid ${direction} vec2 vMapUv;\n #else\n varying vec2 vMapUv;\n #endif\n `));\n }\n };\n return material;\n }\n\n public static createShadedCanvasMaterial(canvas: HTMLCanvasElement, transparent: boolean = false, shade:boolean=false, boundUvs: boolean = false):Material {\n //TODO\n // this might help https://github.com/JannisX11/blockbench/blob/1701f764641376414d29100c4f6c7cd74997fad8/js/preview/canvas.js#L62\n\n\n // Based on https://github.com/JannisX11/blockbench/blob/cc73aa8a9c0494fd9fe1cee4d062d060af4db06d/js/texturing/textures.js#L59\n // + support for instanced meshes\n const vertShader =`\n uniform bool SHADE;\n \n // Keep MSAA edge pixels from sampling outside the face's atlas region.\n #if __VERSION__ >= 300\n centroid out vec2 vUv;\n #else\n varying vec2 vUv;\n #endif\n #ifdef BOUND_UVS\n attribute vec4 uvBounds;\n flat out vec4 vUvBounds;\n #endif\n varying vec3 vTint;\n varying float light;\n varying float lift;\n\n float AMBIENT = 0.5;\n float XFAC = -0.15;\n float ZFAC = 0.05;\n\n void main()\n {\n\n if (SHADE) {\n\n #ifdef USE_INSTANCING\n vec3 N = vec3( modelMatrix * instanceMatrix * vec4(normal, 0.0) );\n #else\n vec3 N = vec3( modelMatrix * vec4(normal, 0.0) );\n #endif\n\n float yLight = (1.0+N.y) * 0.5;\n light = yLight * (1.0-AMBIENT) + N.x*N.x * XFAC + N.z*N.z * ZFAC + AMBIENT;\n\n } else {\n\n light = 1.0;\n\n } \n\n if (color.b > 1.1) {\n lift = 0.1;\n } else {\n lift = 0.0;\n }\n \n vUv = uv;\n #ifdef BOUND_UVS\n vUvBounds = uvBounds;\n #endif\n vTint = color;\n \n vec4 mvPosition = vec4(position, 1.0);\n #ifdef USE_INSTANCING\n mvPosition = instanceMatrix * mvPosition;\n #endif\n mvPosition = modelViewMatrix * mvPosition;\n gl_Position = projectionMatrix * mvPosition;\n \n }\n `\n const fragShader = `\n #ifdef GL_ES\n precision highp float;\n #endif\n\n uniform sampler2D map;\n\n uniform bool SHADE;\n uniform bool EMISSIVE;\n uniform float BRIGHTNESS;\n\n #if __VERSION__ >= 300\n centroid in vec2 vUv;\n #else\n varying vec2 vUv;\n #endif\n #ifdef BOUND_UVS\n flat in vec4 vUvBounds;\n #endif\n varying vec3 vTint;\n varying float light;\n varying float lift;\n\n void main(void)\n {\n #ifdef BOUND_UVS\n // Keep edge samples inside their texture even without centroid interpolation.\n vec2 mapUv = clamp(vUv, vUvBounds.xy, vUvBounds.zw);\n #else\n vec2 mapUv = vUv;\n #endif\n vec4 color = texture2D(map, mapUv);\n color.rgb *= vTint;\n \n if (color.a < 0.01) discard;\n\n if (EMISSIVE == false) {\n\n gl_FragColor = vec4(lift + color.rgb * light * BRIGHTNESS, color.a);\n\n } else {\n\n float light2 = (light * BRIGHTNESS) + (1.0 - light * BRIGHTNESS) * (1.0 - color.a);\n gl_FragColor = vec4(lift + color.rgb * light2, 1.0);\n\n }\n\n #include <tonemapping_fragment>\n #include <colorspace_fragment>\n }\n `\n //TODO: this does add the MC-like shading, but breaks when stuff is instanced (can't updated position)\n // https://medium.com/@pailhead011/instancing-with-three-js-part-2-3be34ae83c57 might help with that\n\n try {\n const material = new ShaderMaterial({\n defines: boundUvs ? { BOUND_UVS: true } : {},\n uniforms: {\n SHADE: { value: true },\n BRIGHTNESS: { value: 1 },\n EMISSIVE:{value:false},\n base: { value: new Color(0xc1c1c1)/*TODO*/ },\n map: {value:Textures.createCanvasTexture(canvas)}\n },\n vertexShader: vertShader,\n fragmentShader: fragShader,\n vertexColors: true,\n transparent: transparent,\n side: transparent ? DoubleSide : FrontSide,\n alphaTest: 0.5,\n });\n Object.assign(material.defaultAttributeValues, { uvBounds: [0, 0, 1, 1] });\n return material;\n } catch (e) {\n console.warn(e)\n }\n\n // fallback\n return this.createBasicCanvasMaterial(canvas, transparent, shade);\n }\n\n /** Returns a shared image material. Use {@link createImage} for a separate material instance. */\n public static getImage(key: MaterialKey): Material {\n const keyStr = serializeMaterialKey(key);\n const map = (Caching.materialCache.peek(keyStr) as MeshBasicMaterial | undefined)?.map;\n if (map && TextureLoader.hasFailed(map)) {\n Caching.materialCache.invalidate(keyStr);\n }\n return Caching.materialCache.get(keyStr, k => {\n return Materials.createImage(key);\n })!;\n }\n\n public static needsUpdate(mat: Material) {\n mat.needsUpdate = true;\n\n if (mat.type === 'ShaderMaterial') {\n let mat1=mat as ShaderMaterial;\n if (\"map\" in mat1.uniforms) {\n mat1.uniforms.map.value.needsUpdate = true;\n }\n }\n if (mat.type === 'MeshBasicMaterial' || mat.type === 'MeshStandardMaterial') {\n let mat1 = mat as (MeshBasicMaterial | MeshStandardMaterial);\n if (mat1.map) {\n mat1.map.needsUpdate = true;\n }\n }\n }\n\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../src/Materials.ts"],"sourcesContent":["import { MaterialKey, serializeMaterialKey } from \"./cache/CacheKey\";\nimport { Color, ColorRepresentation, CustomBlending, DoubleSide, OneFactor, OneMinusSrcAlphaFactor, RepeatWrapping, FrontSide, Material, MeshBasicMaterial, MeshLambertMaterial, MeshPhongMaterial, MeshStandardMaterial, ShaderChunk, ShaderMaterial } from \"three\";\nimport { Textures } from \"./texture/Textures\";\nimport { TextureLoader } from \"./texture/TextureLoader\";\nimport { Caching } from \"./cache/Caching\";\nimport { AssetKey } from \"./assets/AssetKey\";\nimport type { EntityRenderMode } from \"./entity/EntityModel\";\n\n/** Creates Minecraft model, entity, and GUI materials, with shared caches for image materials. */\nexport class Materials {\n\n /** Shared checkerboard material, created on first access. */\n public static get MISSING_TEXTURE(): Material {\n return Caching.materialCache.get(\"builtin:missing-texture\", () => new MeshBasicMaterial({\n map: Textures.getMissing(),\n alphaTest: 0.5\n }))!;\n }\n\n public static createImage(key: MaterialKey): Material {\n //TODO: type from key\n const transparent = key.transparent || false;\n return new MeshBasicMaterial({\n map: Textures.getImage(key.texture),\n transparent: transparent,\n side: transparent ? DoubleSide : FrontSide,\n alphaTest: 0.5\n });\n //TODO: params\n }\n\n\n public static createBasicCanvasMaterial(canvas: HTMLCanvasElement, transparent: boolean = false, shade: boolean = false): Material {\n if (shade) {\n return new MeshStandardMaterial({\n map: Textures.createCanvasTexture(canvas),\n transparent: transparent,\n side: transparent ? DoubleSide : FrontSide,\n alphaTest: 0.5,\n\n })\n }\n return new MeshBasicMaterial({\n map: Textures.createCanvasTexture(canvas),\n transparent: transparent,\n side: transparent ? DoubleSide : FrontSide,\n alphaTest: 0.5,\n\n })\n }\n\n /** Whether vanilla's render type for the mode culls back faces. */\n public static entityModeCulls(mode: EntityRenderMode = \"cutout\"): boolean {\n return mode === \"cutout_cull\" || mode === \"solid\" || mode === \"eyes\" || mode === \"water_mask\";\n }\n\n /** UV offset per tick of entity age for the scrolling modes, as vanilla's texture matrix applies it. */\n public static entityModeScroll(mode: EntityRenderMode = \"cutout\"): [number, number] | undefined {\n if (mode === \"energy_swirl\") return [0.01, 0.01];\n if (mode === \"breeze_wind\") return [0.02, 0];\n return undefined;\n }\n\n /**\n * Entity material for one of vanilla's render types. Entities are unlit here, so the lit and full-bright modes\n * differ only in blending and depth state. Culling is not a material property: {@link entityModeCulls} decides\n * whether the geometry gets inward faces.\n */\n public static createEntityCanvasMaterial(canvas: HTMLCanvasElement, mode: EntityRenderMode = \"cutout\", tint?: ColorRepresentation): MeshBasicMaterial {\n const material = Materials.createBasicCanvasMaterial(canvas) as MeshBasicMaterial;\n switch (mode) {\n case \"cutout\":\n case \"cutout_cull\":\n break;\n case \"cutout_z_offset\":\n material.polygonOffset = true;\n material.polygonOffsetFactor = -1;\n material.polygonOffsetUnits = -10;\n break;\n case \"solid\":\n material.alphaTest = 0;\n break;\n case \"translucent\":\n case \"breeze_wind\":\n material.transparent = true;\n material.alphaTest = 0.1;\n break;\n case \"translucent_emissive\":\n material.transparent = true;\n material.alphaTest = 0.1;\n material.depthWrite = false;\n break;\n case \"eyes\":\n case \"no_outline\":\n material.transparent = true;\n material.alphaTest = 0;\n material.depthWrite = false;\n break;\n case \"energy_swirl\":\n material.transparent = true;\n material.alphaTest = 0.1;\n material.blending = CustomBlending;\n material.blendSrc = OneFactor;\n material.blendDst = OneFactor;\n // The canvas is premultiplied: a glow pixel needs alpha, or browsers and image exports drop it wherever\n // nothing opaque is behind it. Its brightness serves as coverage, so the glow stays visible outside the body.\n material.blendSrcAlpha = OneFactor;\n material.blendDstAlpha = OneMinusSrcAlphaFactor;\n material.onBeforeCompile = shader => {\n shader.fragmentShader = shader.fragmentShader.replace(\"#include <dithering_fragment>\",\n \"gl_FragColor.a = max(gl_FragColor.r, max(gl_FragColor.g, gl_FragColor.b));\\n#include <dithering_fragment>\");\n };\n material.customProgramCacheKey = () => \"energy_swirl\";\n // Vanilla submits the swirl with half-grey vertex colour.\n material.color.set(0x808080);\n break;\n case \"water_mask\":\n material.alphaTest = 0;\n material.colorWrite = false;\n break;\n }\n if (Materials.entityModeScroll(mode)) {\n material.map!.wrapS = material.map!.wrapT = RepeatWrapping;\n }\n if (tint !== undefined) material.color.multiply(new Color(tint));\n return material;\n }\n\n /** Creates an unlit, transparent GUI material without depth writes or tone mapping. */\n public static createGuiCanvasMaterial(canvas: HTMLCanvasElement): MeshBasicMaterial {\n const material = new MeshBasicMaterial({\n map: Textures.createCanvasTexture(canvas),\n transparent: true,\n depthWrite: false,\n side: DoubleSide,\n toneMapped: false\n });\n material.onBeforeCompile = shader => {\n // Keep MSAA edge pixels inside the layer's cropped texture region.\n for (const [stage, direction] of [[\"vertex\", \"out\"], [\"fragment\", \"in\"]] as const) {\n const chunk = `uv_pars_${stage}` as const;\n shader[`${stage}Shader`] = shader[`${stage}Shader`].replace(`#include <${chunk}>`,\n ShaderChunk[chunk].replace(\"varying vec2 vMapUv;\", `\n #if __VERSION__ >= 300\n centroid ${direction} vec2 vMapUv;\n #else\n varying vec2 vMapUv;\n #endif\n `));\n }\n };\n return material;\n }\n\n public static createShadedCanvasMaterial(canvas: HTMLCanvasElement, transparent: boolean = false, shade:boolean=false, boundUvs: boolean = false):Material {\n //TODO\n // this might help https://github.com/JannisX11/blockbench/blob/1701f764641376414d29100c4f6c7cd74997fad8/js/preview/canvas.js#L62\n\n\n // Based on https://github.com/JannisX11/blockbench/blob/cc73aa8a9c0494fd9fe1cee4d062d060af4db06d/js/texturing/textures.js#L59\n // + support for instanced meshes\n const vertShader =`\n uniform bool SHADE;\n attribute float shade;\n \n // Keep MSAA edge pixels from sampling outside the face's atlas region.\n #if __VERSION__ >= 300\n centroid out vec2 vUv;\n #else\n varying vec2 vUv;\n #endif\n #ifdef BOUND_UVS\n attribute vec4 uvBounds;\n flat out vec4 vUvBounds;\n #endif\n varying vec3 vTint;\n varying float light;\n varying float lift;\n\n float AMBIENT = 0.5;\n float XFAC = -0.15;\n float ZFAC = 0.05;\n\n void main()\n {\n\n if (SHADE && shade > 0.5) {\n\n #ifdef USE_INSTANCING\n vec3 N = vec3( modelMatrix * instanceMatrix * vec4(normal, 0.0) );\n #else\n vec3 N = vec3( modelMatrix * vec4(normal, 0.0) );\n #endif\n\n float yLight = (1.0+N.y) * 0.5;\n light = yLight * (1.0-AMBIENT) + N.x*N.x * XFAC + N.z*N.z * ZFAC + AMBIENT;\n\n } else {\n\n light = 1.0;\n\n } \n\n if (color.b > 1.1) {\n lift = 0.1;\n } else {\n lift = 0.0;\n }\n \n vUv = uv;\n #ifdef BOUND_UVS\n vUvBounds = uvBounds;\n #endif\n vTint = color;\n \n vec4 mvPosition = vec4(position, 1.0);\n #ifdef USE_INSTANCING\n mvPosition = instanceMatrix * mvPosition;\n #endif\n mvPosition = modelViewMatrix * mvPosition;\n gl_Position = projectionMatrix * mvPosition;\n \n }\n `\n const fragShader = `\n #ifdef GL_ES\n precision highp float;\n #endif\n\n uniform sampler2D map;\n\n uniform bool SHADE;\n uniform bool EMISSIVE;\n uniform float BRIGHTNESS;\n\n #if __VERSION__ >= 300\n centroid in vec2 vUv;\n #else\n varying vec2 vUv;\n #endif\n #ifdef BOUND_UVS\n flat in vec4 vUvBounds;\n #endif\n varying vec3 vTint;\n varying float light;\n varying float lift;\n\n void main(void)\n {\n #ifdef BOUND_UVS\n // Keep edge samples inside their texture even without centroid interpolation.\n vec2 mapUv = clamp(vUv, vUvBounds.xy, vUvBounds.zw);\n #else\n vec2 mapUv = vUv;\n #endif\n vec4 color = texture2D(map, mapUv);\n color.rgb *= vTint;\n \n if (color.a < 0.01) discard;\n\n if (EMISSIVE == false) {\n\n gl_FragColor = vec4(lift + color.rgb * light * BRIGHTNESS, color.a);\n\n } else {\n\n float light2 = (light * BRIGHTNESS) + (1.0 - light * BRIGHTNESS) * (1.0 - color.a);\n gl_FragColor = vec4(lift + color.rgb * light2, 1.0);\n\n }\n\n #include <tonemapping_fragment>\n #include <colorspace_fragment>\n }\n `\n //TODO: this does add the MC-like shading, but breaks when stuff is instanced (can't updated position)\n // https://medium.com/@pailhead011/instancing-with-three-js-part-2-3be34ae83c57 might help with that\n\n try {\n const material = new ShaderMaterial({\n defines: boundUvs ? { BOUND_UVS: true } : {},\n uniforms: {\n SHADE: { value: true },\n BRIGHTNESS: { value: 1 },\n EMISSIVE:{value:false},\n base: { value: new Color(0xc1c1c1)/*TODO*/ },\n map: {value:Textures.createCanvasTexture(canvas)}\n },\n vertexShader: vertShader,\n fragmentShader: fragShader,\n vertexColors: true,\n transparent: transparent,\n side: transparent ? DoubleSide : FrontSide,\n alphaTest: 0.5,\n });\n Object.assign(material.defaultAttributeValues, { shade: [1], uvBounds: [0, 0, 1, 1] });\n return material;\n } catch (e) {\n console.warn(e)\n }\n\n // fallback\n return this.createBasicCanvasMaterial(canvas, transparent, shade);\n }\n\n /** Returns a shared image material. Use {@link createImage} for a separate material instance. */\n public static getImage(key: MaterialKey): Material {\n const keyStr = serializeMaterialKey(key);\n const map = (Caching.materialCache.peek(keyStr) as MeshBasicMaterial | undefined)?.map;\n if (map && TextureLoader.hasFailed(map)) {\n Caching.materialCache.invalidate(keyStr);\n }\n return Caching.materialCache.get(keyStr, k => {\n return Materials.createImage(key);\n })!;\n }\n\n public static needsUpdate(mat: Material) {\n mat.needsUpdate = true;\n\n if (mat.type === 'ShaderMaterial') {\n let mat1=mat as ShaderMaterial;\n if (\"map\" in mat1.uniforms) {\n mat1.uniforms.map.value.needsUpdate = true;\n }\n }\n if (mat.type === 'MeshBasicMaterial' || mat.type === 'MeshStandardMaterial') {\n let mat1 = mat as (MeshBasicMaterial | MeshStandardMaterial);\n if (mat1.map) {\n mat1.map.needsUpdate = true;\n }\n }\n }\n\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,8 @@
1
+ // src/assets/AssetDefaults.ts
2
+ var DEFAULT_ROOT = "https://assets.mcasset.cloud/1.21.11";
3
+ var DEFAULT_NAMESPACE = "minecraft";
4
+ export {
5
+ DEFAULT_NAMESPACE,
6
+ DEFAULT_ROOT
7
+ };
8
+ //# sourceMappingURL=AssetDefaults.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/assets/AssetDefaults.ts"],"sourcesContent":["// Kept free of imports: AssetLoader reads DEFAULT_ROOT in a static initializer, and Assets.ts sits in an import\n// cycle with AssetLoader, so code-split bundles could run that initializer before the constant was assigned.\nexport const DEFAULT_ROOT = \"https://assets.mcasset.cloud/1.21.11\";\nexport const DEFAULT_NAMESPACE = \"minecraft\";\n"],"mappings":";AAEO,IAAM,eAAe;AACrB,IAAM,oBAAoB;","names":[]}
@@ -1,5 +1,5 @@
1
1
  // src/assets/AssetKey.ts
2
- import { DEFAULT_NAMESPACE } from "./Assets.mjs";
2
+ import { DEFAULT_NAMESPACE } from "./AssetDefaults.mjs";
3
3
  import { AssetLoader } from "./AssetLoader.mjs";
4
4
  var BasicAssetKey = class {
5
5
  constructor(namespaceOrKey, path) {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/assets/AssetKey.ts"],"sourcesContent":["import { Serializable } from \"../Serializable\";\nimport { DEFAULT_NAMESPACE } from \"./Assets\";\nimport { AssetLoader } from \"./AssetLoader\";\n\nexport type AssetType = \"models\" | \"textures\" | \"blockstates\" | string;\n\n/** A Minecraft namespace and path, such as `minecraft` and `zombie`. */\nexport class BasicAssetKey implements Serializable {\n\n readonly namespace: string;\n readonly path: string;\n\n constructor(key: BasicAssetKey);\n constructor(namespace: string, path: string);\n constructor(namespaceOrKey: string | BasicAssetKey, path?: string) {\n if (path) {\n this.namespace = namespaceOrKey as string;\n this.path = path;\n } else {\n this.namespace = (namespaceOrKey as BasicAssetKey).namespace;\n this.path = (namespaceOrKey as BasicAssetKey).path\n }\n }\n\n toNamespacedString() {\n return this.namespace + \":\" + this.path;\n }\n\n toString() {\n return this.toNamespacedString();\n }\n\n serialize(): string {\n return this.toString();\n }\n}\n\n// TODO: rewrite this to be less dumb\n/** Locates an asset by namespace, directory, extension, and optional asset root. */\nexport class AssetKey extends BasicAssetKey {\n\n public readonly isAssetKey: true = true;\n\n /**\n * Creates a key from separate path components. Use {@link parse} for a combined reference.\n *\n * @param assetType - Asset directory, such as `models`, `textures`, or `blockstates`.\n * @param type - Subdirectory, such as `block` or `item`.\n * @param rootType - Top-level directory, usually `assets` or `data`.\n * @param root - Base URL override for hosted asset sources.\n */\n constructor(\n readonly namespace: string, readonly path: string,\n public assetType?: AssetType,\n public type?: string,\n public rootType: \"assets\" | \"data\" | string = \"assets\",\n public extension: \".json\" | \".png\" | string = \".json\",\n public root?: string,\n ) {\n super(namespace, path);\n }\n\n\n /**\n * Parses an asset reference such as `minecraft:block/stone`.\n * A missing namespace defaults to the origin's namespace or `minecraft`.\n *\n * @param assetType - Asset category, such as `models` or `textures`.\n * @param str - Path with an optional namespace and file extension.\n * @param origin - Supplies the asset root, default namespace, and non-texture extension.\n * @returns A key with the matching extension removed from its path. Textures use `.png`;\n * other assets use the origin's extension or `.json`.\n */\n public static parse(assetType: AssetType, str: string, origin?: AssetKey): AssetKey {\n let namespace = origin?.namespace || DEFAULT_NAMESPACE;\n if (str.includes(\":\")) {\n let split = str.split(\"\\:\");\n namespace = split[0];\n str = split[1];\n }\n\n let split = str.split(\"\\/\");\n let type: string | undefined = undefined;\n if (split.length > 1) {\n type = split[0];\n split.shift();\n }\n let path = split.join(\"/\");\n\n const extension = assetType === \"textures\" ? \".png\" :\n origin?.extension ?? \".json\";\n if (extension && path.endsWith(extension)) {\n path = path.slice(0, -extension.length);\n }\n\n return new AssetKey(namespace, path, assetType, type, \"assets\", extension, origin?.root);\n }\n\n toString(): string {\n let a = [\n this.root ?? AssetLoader.ROOT,\n this.rootType ?? \"__rootType__\",\n this.assetType ?? \"__assetType__\",\n this.type ?? \"__type__\",\n this.namespace,\n this.path\n ];\n return a.join(\"/\");\n }\n\n /** Joins the type subdirectory and path without adding a namespace or file extension. */\n getFullPath() {\n let p: string[] = [];\n if (this.type) {\n p.push(this.type);\n }\n p.push(this.path);\n return p.join(\"/\");\n }\n\n toNamespacedString() {\n return this.namespace + \":\" + this.getFullPath();\n }\n\n /** Returns a cache identifier that includes the explicit root or {@link AssetLoader.ROOT}. */\n serialize(): string {\n return this.toString();\n }\n}\n\nexport function isResourceLocation(value: unknown): value is string {\n return typeof value === \"string\" && /^(?:[a-z0-9_.-]+:)?[a-z0-9_./-]+$/.test(value);\n}\n\nexport function isBasicAssetKey(obj: any): obj is BasicAssetKey {\n return obj !== null && typeof obj === \"object\"\n && typeof obj.namespace === \"string\" && typeof obj.path === \"string\";\n}\n\nexport function isAssetKey(obj: any): obj is AssetKey {\n return isBasicAssetKey(obj) && (<AssetKey>obj).isAssetKey === true;\n}\n"],"mappings":";AACA,SAAS,yBAAyB;AAClC,SAAS,mBAAmB;AAKrB,IAAM,gBAAN,MAA4C;AAAA,EAO/C,YAAY,gBAAwC,MAAe;AAC/D,QAAI,MAAM;AACN,WAAK,YAAY;AACjB,WAAK,OAAO;AAAA,IAChB,OAAO;AACH,WAAK,YAAa,eAAiC;AACnD,WAAK,OAAQ,eAAiC;AAAA,IAClD;AAAA,EACJ;AAAA,EAEA,qBAAqB;AACjB,WAAO,KAAK,YAAY,MAAM,KAAK;AAAA,EACvC;AAAA,EAEA,WAAW;AACP,WAAO,KAAK,mBAAmB;AAAA,EACnC;AAAA,EAEA,YAAoB;AAChB,WAAO,KAAK,SAAS;AAAA,EACzB;AACJ;AAIO,IAAM,WAAN,MAAM,kBAAiB,cAAc;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYxC,YACa,WAA4B,MAC9B,WACA,MACA,WAAuC,UACvC,YAAuC,SACvC,MACT;AACE,UAAM,WAAW,IAAI;AAPZ;AAA4B;AAC9B;AACA;AACA;AACA;AACA;AAhBX,SAAgB,aAAmB;AAAA,EAmBnC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,OAAc,MAAM,WAAsB,KAAa,QAA6B;AAChF,QAAI,YAAY,QAAQ,aAAa;AACrC,QAAI,IAAI,SAAS,GAAG,GAAG;AACnB,UAAIA,SAAQ,IAAI,MAAM,GAAI;AAC1B,kBAAYA,OAAM,CAAC;AACnB,YAAMA,OAAM,CAAC;AAAA,IACjB;AAEA,QAAI,QAAQ,IAAI,MAAM,GAAI;AAC1B,QAAI,OAA2B;AAC/B,QAAI,MAAM,SAAS,GAAG;AAClB,aAAO,MAAM,CAAC;AACd,YAAM,MAAM;AAAA,IAChB;AACA,QAAI,OAAO,MAAM,KAAK,GAAG;AAEzB,UAAM,YAAY,cAAc,aAAa,SACzC,QAAQ,aAAa;AACzB,QAAI,aAAa,KAAK,SAAS,SAAS,GAAG;AACvC,aAAO,KAAK,MAAM,GAAG,CAAC,UAAU,MAAM;AAAA,IAC1C;AAEA,WAAO,IAAI,UAAS,WAAW,MAAM,WAAW,MAAM,UAAU,WAAW,QAAQ,IAAI;AAAA,EAC3F;AAAA,EAEA,WAAmB;AACf,QAAI,IAAI;AAAA,MACJ,KAAK,QAAQ,YAAY;AAAA,MACzB,KAAK,YAAY;AAAA,MACjB,KAAK,aAAa;AAAA,MAClB,KAAK,QAAQ;AAAA,MACb,KAAK;AAAA,MACL,KAAK;AAAA,IACT;AACA,WAAO,EAAE,KAAK,GAAG;AAAA,EACrB;AAAA;AAAA,EAGA,cAAc;AACV,QAAI,IAAc,CAAC;AACnB,QAAI,KAAK,MAAM;AACX,QAAE,KAAK,KAAK,IAAI;AAAA,IACpB;AACA,MAAE,KAAK,KAAK,IAAI;AAChB,WAAO,EAAE,KAAK,GAAG;AAAA,EACrB;AAAA,EAEA,qBAAqB;AACjB,WAAO,KAAK,YAAY,MAAM,KAAK,YAAY;AAAA,EACnD;AAAA;AAAA,EAGA,YAAoB;AAChB,WAAO,KAAK,SAAS;AAAA,EACzB;AACJ;AAEO,SAAS,mBAAmB,OAAiC;AAChE,SAAO,OAAO,UAAU,YAAY,oCAAoC,KAAK,KAAK;AACtF;AAEO,SAAS,gBAAgB,KAAgC;AAC5D,SAAO,QAAQ,QAAQ,OAAO,QAAQ,YAC/B,OAAO,IAAI,cAAc,YAAY,OAAO,IAAI,SAAS;AACpE;AAEO,SAAS,WAAW,KAA2B;AAClD,SAAO,gBAAgB,GAAG,KAAgB,IAAK,eAAe;AAClE;","names":["split"]}
1
+ {"version":3,"sources":["../../../../src/assets/AssetKey.ts"],"sourcesContent":["import { Serializable } from \"../Serializable\";\nimport { DEFAULT_NAMESPACE } from \"./AssetDefaults\";\nimport { AssetLoader } from \"./AssetLoader\";\n\nexport type AssetType = \"models\" | \"textures\" | \"blockstates\" | string;\n\n/** A Minecraft namespace and path, such as `minecraft` and `zombie`. */\nexport class BasicAssetKey implements Serializable {\n\n readonly namespace: string;\n readonly path: string;\n\n constructor(key: BasicAssetKey);\n constructor(namespace: string, path: string);\n constructor(namespaceOrKey: string | BasicAssetKey, path?: string) {\n if (path) {\n this.namespace = namespaceOrKey as string;\n this.path = path;\n } else {\n this.namespace = (namespaceOrKey as BasicAssetKey).namespace;\n this.path = (namespaceOrKey as BasicAssetKey).path\n }\n }\n\n toNamespacedString() {\n return this.namespace + \":\" + this.path;\n }\n\n toString() {\n return this.toNamespacedString();\n }\n\n serialize(): string {\n return this.toString();\n }\n}\n\n// TODO: rewrite this to be less dumb\n/** Locates an asset by namespace, directory, extension, and optional asset root. */\nexport class AssetKey extends BasicAssetKey {\n\n public readonly isAssetKey: true = true;\n\n /**\n * Creates a key from separate path components. Use {@link parse} for a combined reference.\n *\n * @param assetType - Asset directory, such as `models`, `textures`, or `blockstates`.\n * @param type - Subdirectory, such as `block` or `item`.\n * @param rootType - Top-level directory, usually `assets` or `data`.\n * @param root - Base URL override for hosted asset sources.\n */\n constructor(\n readonly namespace: string, readonly path: string,\n public assetType?: AssetType,\n public type?: string,\n public rootType: \"assets\" | \"data\" | string = \"assets\",\n public extension: \".json\" | \".png\" | string = \".json\",\n public root?: string,\n ) {\n super(namespace, path);\n }\n\n\n /**\n * Parses an asset reference such as `minecraft:block/stone`.\n * A missing namespace defaults to the origin's namespace or `minecraft`.\n *\n * @param assetType - Asset category, such as `models` or `textures`.\n * @param str - Path with an optional namespace and file extension.\n * @param origin - Supplies the asset root, default namespace, and non-texture extension.\n * @returns A key with the matching extension removed from its path. Textures use `.png`;\n * other assets use the origin's extension or `.json`.\n */\n public static parse(assetType: AssetType, str: string, origin?: AssetKey): AssetKey {\n let namespace = origin?.namespace || DEFAULT_NAMESPACE;\n if (str.includes(\":\")) {\n let split = str.split(\"\\:\");\n namespace = split[0];\n str = split[1];\n }\n\n let split = str.split(\"\\/\");\n let type: string | undefined = undefined;\n if (split.length > 1) {\n type = split[0];\n split.shift();\n }\n let path = split.join(\"/\");\n\n const extension = assetType === \"textures\" ? \".png\" :\n origin?.extension ?? \".json\";\n if (extension && path.endsWith(extension)) {\n path = path.slice(0, -extension.length);\n }\n\n return new AssetKey(namespace, path, assetType, type, \"assets\", extension, origin?.root);\n }\n\n toString(): string {\n let a = [\n this.root ?? AssetLoader.ROOT,\n this.rootType ?? \"__rootType__\",\n this.assetType ?? \"__assetType__\",\n this.type ?? \"__type__\",\n this.namespace,\n this.path\n ];\n return a.join(\"/\");\n }\n\n /** Joins the type subdirectory and path without adding a namespace or file extension. */\n getFullPath() {\n let p: string[] = [];\n if (this.type) {\n p.push(this.type);\n }\n p.push(this.path);\n return p.join(\"/\");\n }\n\n toNamespacedString() {\n return this.namespace + \":\" + this.getFullPath();\n }\n\n /** Returns a cache identifier that includes the explicit root or {@link AssetLoader.ROOT}. */\n serialize(): string {\n return this.toString();\n }\n}\n\nexport function isResourceLocation(value: unknown): value is string {\n return typeof value === \"string\" && /^(?:[a-z0-9_.-]+:)?[a-z0-9_./-]+$/.test(value);\n}\n\nexport function isBasicAssetKey(obj: any): obj is BasicAssetKey {\n return obj !== null && typeof obj === \"object\"\n && typeof obj.namespace === \"string\" && typeof obj.path === \"string\";\n}\n\nexport function isAssetKey(obj: any): obj is AssetKey {\n return isBasicAssetKey(obj) && (<AssetKey>obj).isAssetKey === true;\n}\n"],"mappings":";AACA,SAAS,yBAAyB;AAClC,SAAS,mBAAmB;AAKrB,IAAM,gBAAN,MAA4C;AAAA,EAO/C,YAAY,gBAAwC,MAAe;AAC/D,QAAI,MAAM;AACN,WAAK,YAAY;AACjB,WAAK,OAAO;AAAA,IAChB,OAAO;AACH,WAAK,YAAa,eAAiC;AACnD,WAAK,OAAQ,eAAiC;AAAA,IAClD;AAAA,EACJ;AAAA,EAEA,qBAAqB;AACjB,WAAO,KAAK,YAAY,MAAM,KAAK;AAAA,EACvC;AAAA,EAEA,WAAW;AACP,WAAO,KAAK,mBAAmB;AAAA,EACnC;AAAA,EAEA,YAAoB;AAChB,WAAO,KAAK,SAAS;AAAA,EACzB;AACJ;AAIO,IAAM,WAAN,MAAM,kBAAiB,cAAc;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYxC,YACa,WAA4B,MAC9B,WACA,MACA,WAAuC,UACvC,YAAuC,SACvC,MACT;AACE,UAAM,WAAW,IAAI;AAPZ;AAA4B;AAC9B;AACA;AACA;AACA;AACA;AAhBX,SAAgB,aAAmB;AAAA,EAmBnC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,OAAc,MAAM,WAAsB,KAAa,QAA6B;AAChF,QAAI,YAAY,QAAQ,aAAa;AACrC,QAAI,IAAI,SAAS,GAAG,GAAG;AACnB,UAAIA,SAAQ,IAAI,MAAM,GAAI;AAC1B,kBAAYA,OAAM,CAAC;AACnB,YAAMA,OAAM,CAAC;AAAA,IACjB;AAEA,QAAI,QAAQ,IAAI,MAAM,GAAI;AAC1B,QAAI,OAA2B;AAC/B,QAAI,MAAM,SAAS,GAAG;AAClB,aAAO,MAAM,CAAC;AACd,YAAM,MAAM;AAAA,IAChB;AACA,QAAI,OAAO,MAAM,KAAK,GAAG;AAEzB,UAAM,YAAY,cAAc,aAAa,SACzC,QAAQ,aAAa;AACzB,QAAI,aAAa,KAAK,SAAS,SAAS,GAAG;AACvC,aAAO,KAAK,MAAM,GAAG,CAAC,UAAU,MAAM;AAAA,IAC1C;AAEA,WAAO,IAAI,UAAS,WAAW,MAAM,WAAW,MAAM,UAAU,WAAW,QAAQ,IAAI;AAAA,EAC3F;AAAA,EAEA,WAAmB;AACf,QAAI,IAAI;AAAA,MACJ,KAAK,QAAQ,YAAY;AAAA,MACzB,KAAK,YAAY;AAAA,MACjB,KAAK,aAAa;AAAA,MAClB,KAAK,QAAQ;AAAA,MACb,KAAK;AAAA,MACL,KAAK;AAAA,IACT;AACA,WAAO,EAAE,KAAK,GAAG;AAAA,EACrB;AAAA;AAAA,EAGA,cAAc;AACV,QAAI,IAAc,CAAC;AACnB,QAAI,KAAK,MAAM;AACX,QAAE,KAAK,KAAK,IAAI;AAAA,IACpB;AACA,MAAE,KAAK,KAAK,IAAI;AAChB,WAAO,EAAE,KAAK,GAAG;AAAA,EACrB;AAAA,EAEA,qBAAqB;AACjB,WAAO,KAAK,YAAY,MAAM,KAAK,YAAY;AAAA,EACnD;AAAA;AAAA,EAGA,YAAoB;AAChB,WAAO,KAAK,SAAS;AAAA,EACzB;AACJ;AAEO,SAAS,mBAAmB,OAAiC;AAChE,SAAO,OAAO,UAAU,YAAY,oCAAoC,KAAK,KAAK;AACtF;AAEO,SAAS,gBAAgB,KAAgC;AAC5D,SAAO,QAAQ,QAAQ,OAAO,QAAQ,YAC/B,OAAO,IAAI,cAAc,YAAY,OAAO,IAAI,SAAS;AACpE;AAEO,SAAS,WAAW,KAA2B;AAClD,SAAO,gBAAgB,GAAG,KAAgB,IAAK,eAAe;AAClE;","names":["split"]}
@@ -1,5 +1,5 @@
1
1
  // src/assets/AssetLoader.ts
2
- import { DEFAULT_ROOT } from "./Assets.mjs";
2
+ import { DEFAULT_ROOT } from "./AssetDefaults.mjs";
3
3
  import { AssetKey } from "./AssetKey.mjs";
4
4
  import { prefix } from "../util/log.mjs";
5
5
  import { HostedAssetSource } from "./source/index.mjs";
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/assets/AssetLoader.ts"],"sourcesContent":["import { Model, TextureAsset } from \"../model/Model\";\nimport { Maybe } from \"../util/util\";\nimport { Requests } from \"../request/Requests\";\nimport { MinecraftAsset } from \"../MinecraftAsset\";\nimport { ImageInfo, ImageLoader } from \"../image/ImageLoader\";\nimport { MinecraftTextureMeta } from \"../MinecraftTextureMeta\";\nimport { BlockState } from \"../model/block/BlockState\";\nimport { DEFAULT_NAMESPACE, DEFAULT_ROOT } from \"./Assets\";\nimport { ListAsset } from \"../ListAsset\";\nimport { AssetKey } from \"./AssetKey\";\nimport { NBTAsset, NBTHelper } from \"../nbt/NBTHelper\";\nimport { prefix } from \"../util/log\";\nimport { AssetSource } from \"./source/AssetSource\";\nimport { AssetParser } from \"./source/parser/AssetParsers\";\nimport { HostedAssetSource } from \"./source\";\nimport { Caching } from \"../cache/Caching\";\n\nconst p = prefix(\"AssetLoader\");\n\n\n/** Loads assets from a shared, ordered registry of hosted sources and resource packs. */\nexport class AssetLoader {\n\n /** Default asset base URL. Use {@link setVersion} to select a Minecraft version. */\n static ROOT: string = DEFAULT_ROOT;\n\n private static sources: AssetSourceReference[] | undefined;\n\n private static get _SOURCES(): AssetSourceReference[] {\n return this.sources ??= [{ key: \"mcassets\", source: new HostedAssetSource(this.ROOT, { retryDefaults: false }) }];\n }\n\n private static set _SOURCES(sources: AssetSourceReference[]) {\n this.sources = sources;\n }\n\n /** Used when a registered source cannot identify its content, so nothing persists past this session. */\n private static readonly SESSION_SCOPE = `session:${Date.now().toString(36)}:${Math.random().toString(36).slice(2)}`;\n\n public static get version(): string {\n return this.ROOT.substring(this.ROOT.lastIndexOf(\"/\") + 1);\n }\n\n /** Selects an mcasset.cloud version, updates the vanilla source, and clears in-memory caches. */\n public static setVersion(version: string): void {\n this.ROOT = `https://assets.mcasset.cloud/${version}`;\n const source = new HostedAssetSource(this.ROOT, { retryDefaults: false });\n const index = this._SOURCES.findIndex(s => s.key === \"mcassets\");\n if (index !== -1) {\n this._SOURCES[index] = { key: \"mcassets\", source };\n } else {\n this.addSource(\"mcassets\", source);\n }\n Caching.clear();\n }\n\n /**\n * Scope for persistent cache keys. Empty with only the default vanilla source, so its\n * entries stay valid across sessions; otherwise it names every added source (resource packs,\n * mirrors) so their results never masquerade as vanilla assets after a reload.\n */\n public static get persistentScope(): string {\n const parts: string[] = [];\n for (const { key, source } of this._SOURCES) {\n const id = source.cacheId;\n if (key === \"mcassets\" && id === `hosted:${this.ROOT}`) continue;\n if (id === undefined) return this.SESSION_SCOPE;\n parts.push(`${key}=${id}`);\n }\n return parts.join(\"|\");\n }\n\n /** Prefixes a persistent cache key with the current source scope. */\n public static persistentKey(key: string): string {\n const scope = this.persistentScope;\n return scope ? `${scope}\\n${key}` : key;\n }\n\n /**\n * Registers a source at the highest priority.\n * Call {@link Caching.clear} after changing sources to discard previously loaded assets.\n *\n * @param key - Name used to replace or remove this source.\n * @param override - Removes the first source with this name before adding the new one.\n */\n public static addSource(key: string, source: AssetSource, override: boolean = true) {\n if (override) {\n const existing = this.removeSource(key);\n if (existing) {\n console.log(p, \"Removed existing AssetSource\", key);\n }\n }\n\n this._SOURCES.unshift({key, source});\n console.log(p, \"Added AssetSource\", key);\n }\n\n /** Removes and returns the first source with this name. Call {@link Caching.clear} to reload assets. */\n public static removeSource(key: string): Maybe<AssetSource> {\n const index = this._SOURCES.findIndex(s => s.key === key);\n if (index != -1) {\n const spliced = this._SOURCES.splice(index, 1);\n if (spliced.length > 0) {\n return spliced[0].source;\n }\n }\n return undefined;\n }\n\n /** Loads from all sources and returns defined results in priority order. Any source failure rejects the call. */\n public static async getAll<T extends MinecraftAsset>(key: AssetKey, parser: AssetParser | string): Promise<T[]> {\n const sources = [...this._SOURCES];\n const results: T[] = [];\n for (const { source } of sources) {\n const asset = await source.get<T>(key, parser);\n if (asset != undefined) results.push(asset);\n if (await source.blocks(key)) break;\n }\n return results;\n }\n\n /** Returns the first defined result in source-priority order, without merging assets. */\n public static async get<T extends MinecraftAsset>(key: AssetKey, parser: AssetParser | string): Promise<Maybe<T>> {\n const keys = [key];\n if (key.rootType === \"data\" && (key.assetType === \"structure\" || key.assetType === \"structures\")) {\n keys.push(new AssetKey(key.namespace, key.path,\n key.assetType === \"structure\" ? \"structures\" : \"structure\",\n key.type, key.rootType, key.extension, key.root));\n }\n return (await this.getFirst<T>(keys, parser))?.asset;\n }\n\n /** Tries each path within a source before considering lower-priority sources. */\n public static async getFirst<T extends MinecraftAsset>(keys: readonly AssetKey[], parser: AssetParser | string): Promise<Maybe<{ key: AssetKey; asset: T }>> {\n // Source changes affect later lookups, not the priority of an in-flight lookup.\n const sources = [...this._SOURCES];\n let remaining = [...keys];\n for (const source of sources) {\n for (const key of remaining) {\n const result = await source.source.get<T>(key, parser);\n if (result !== undefined) {\n return { key, asset: result };\n }\n }\n const blocked = await Promise.all(remaining.map(key => source.source.blocks(key)));\n remaining = remaining.filter((_, index) => !blocked[index]);\n if (!remaining.length) break;\n }\n return undefined;\n }\n\n}\n\ninterface AssetSourceReference {\n key: string;\n source: AssetSource;\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../../src/assets/AssetLoader.ts"],"sourcesContent":["import { Model, TextureAsset } from \"../model/Model\";\nimport { Maybe } from \"../util/util\";\nimport { Requests } from \"../request/Requests\";\nimport { MinecraftAsset } from \"../MinecraftAsset\";\nimport { ImageInfo, ImageLoader } from \"../image/ImageLoader\";\nimport { MinecraftTextureMeta } from \"../MinecraftTextureMeta\";\nimport { BlockState } from \"../model/block/BlockState\";\nimport { DEFAULT_NAMESPACE, DEFAULT_ROOT } from \"./AssetDefaults\";\nimport { ListAsset } from \"../ListAsset\";\nimport { AssetKey } from \"./AssetKey\";\nimport { NBTAsset, NBTHelper } from \"../nbt/NBTHelper\";\nimport { prefix } from \"../util/log\";\nimport { AssetSource } from \"./source/AssetSource\";\nimport { AssetParser } from \"./source/parser/AssetParsers\";\nimport { HostedAssetSource } from \"./source\";\nimport { Caching } from \"../cache/Caching\";\n\nconst p = prefix(\"AssetLoader\");\n\n\n/** Loads assets from a shared, ordered registry of hosted sources and resource packs. */\nexport class AssetLoader {\n\n /** Default asset base URL. Use {@link setVersion} to select a Minecraft version. */\n static ROOT: string = DEFAULT_ROOT;\n\n private static sources: AssetSourceReference[] | undefined;\n\n private static get _SOURCES(): AssetSourceReference[] {\n return this.sources ??= [{ key: \"mcassets\", source: new HostedAssetSource(this.ROOT, { retryDefaults: false }) }];\n }\n\n private static set _SOURCES(sources: AssetSourceReference[]) {\n this.sources = sources;\n }\n\n /** Used when a registered source cannot identify its content, so nothing persists past this session. */\n private static readonly SESSION_SCOPE = `session:${Date.now().toString(36)}:${Math.random().toString(36).slice(2)}`;\n\n public static get version(): string {\n return this.ROOT.substring(this.ROOT.lastIndexOf(\"/\") + 1);\n }\n\n /** Selects an mcasset.cloud version, updates the vanilla source, and clears in-memory caches. */\n public static setVersion(version: string): void {\n this.ROOT = `https://assets.mcasset.cloud/${version}`;\n const source = new HostedAssetSource(this.ROOT, { retryDefaults: false });\n const index = this._SOURCES.findIndex(s => s.key === \"mcassets\");\n if (index !== -1) {\n this._SOURCES[index] = { key: \"mcassets\", source };\n } else {\n this.addSource(\"mcassets\", source);\n }\n Caching.clear();\n }\n\n /**\n * Scope for persistent cache keys. Empty with only the default vanilla source, so its\n * entries stay valid across sessions; otherwise it names every added source (resource packs,\n * mirrors) so their results never masquerade as vanilla assets after a reload.\n */\n public static get persistentScope(): string {\n const parts: string[] = [];\n for (const { key, source } of this._SOURCES) {\n const id = source.cacheId;\n if (key === \"mcassets\" && id === `hosted:${this.ROOT}`) continue;\n if (id === undefined) return this.SESSION_SCOPE;\n parts.push(`${key}=${id}`);\n }\n return parts.join(\"|\");\n }\n\n /** Prefixes a persistent cache key with the current source scope. */\n public static persistentKey(key: string): string {\n const scope = this.persistentScope;\n return scope ? `${scope}\\n${key}` : key;\n }\n\n /**\n * Registers a source at the highest priority.\n * Call {@link Caching.clear} after changing sources to discard previously loaded assets.\n *\n * @param key - Name used to replace or remove this source.\n * @param override - Removes the first source with this name before adding the new one.\n */\n public static addSource(key: string, source: AssetSource, override: boolean = true) {\n if (override) {\n const existing = this.removeSource(key);\n if (existing) {\n console.log(p, \"Removed existing AssetSource\", key);\n }\n }\n\n this._SOURCES.unshift({key, source});\n console.log(p, \"Added AssetSource\", key);\n }\n\n /** Removes and returns the first source with this name. Call {@link Caching.clear} to reload assets. */\n public static removeSource(key: string): Maybe<AssetSource> {\n const index = this._SOURCES.findIndex(s => s.key === key);\n if (index != -1) {\n const spliced = this._SOURCES.splice(index, 1);\n if (spliced.length > 0) {\n return spliced[0].source;\n }\n }\n return undefined;\n }\n\n /** Loads from all sources and returns defined results in priority order. Any source failure rejects the call. */\n public static async getAll<T extends MinecraftAsset>(key: AssetKey, parser: AssetParser | string): Promise<T[]> {\n const sources = [...this._SOURCES];\n const results: T[] = [];\n for (const { source } of sources) {\n const asset = await source.get<T>(key, parser);\n if (asset != undefined) results.push(asset);\n if (await source.blocks(key)) break;\n }\n return results;\n }\n\n /** Returns the first defined result in source-priority order, without merging assets. */\n public static async get<T extends MinecraftAsset>(key: AssetKey, parser: AssetParser | string): Promise<Maybe<T>> {\n const keys = [key];\n if (key.rootType === \"data\" && (key.assetType === \"structure\" || key.assetType === \"structures\")) {\n keys.push(new AssetKey(key.namespace, key.path,\n key.assetType === \"structure\" ? \"structures\" : \"structure\",\n key.type, key.rootType, key.extension, key.root));\n }\n return (await this.getFirst<T>(keys, parser))?.asset;\n }\n\n /** Tries each path within a source before considering lower-priority sources. */\n public static async getFirst<T extends MinecraftAsset>(keys: readonly AssetKey[], parser: AssetParser | string): Promise<Maybe<{ key: AssetKey; asset: T }>> {\n // Source changes affect later lookups, not the priority of an in-flight lookup.\n const sources = [...this._SOURCES];\n let remaining = [...keys];\n for (const source of sources) {\n for (const key of remaining) {\n const result = await source.source.get<T>(key, parser);\n if (result !== undefined) {\n return { key, asset: result };\n }\n }\n const blocked = await Promise.all(remaining.map(key => source.source.blocks(key)));\n remaining = remaining.filter((_, index) => !blocked[index]);\n if (!remaining.length) break;\n }\n return undefined;\n }\n\n}\n\ninterface AssetSourceReference {\n key: string;\n source: AssetSource;\n}\n"],"mappings":"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","names":[]}
@@ -2,8 +2,6 @@
2
2
  import { Models } from "./Models.mjs";
3
3
  import { BlockStates } from "./BlockStates.mjs";
4
4
  import { AssetKey } from "./AssetKey.mjs";
5
- var DEFAULT_ROOT = "https://assets.mcasset.cloud/1.21.11";
6
- var DEFAULT_NAMESPACE = "minecraft";
7
5
  var Assets = class {
8
6
  /**
9
7
  * @deprecated
@@ -21,8 +19,6 @@ var Assets = class {
21
19
  }
22
20
  };
23
21
  export {
24
- Assets,
25
- DEFAULT_NAMESPACE,
26
- DEFAULT_ROOT
22
+ Assets
27
23
  };
28
24
  //# sourceMappingURL=Assets.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/assets/Assets.ts"],"sourcesContent":["import { Models } from \"./Models\";\nimport { Model } from \"../model/Model\";\nimport { Maybe } from \"../util/util\";\nimport { BlockState } from \"../model/block/BlockState\";\nimport { BlockStates } from \"./BlockStates\";\nimport { AssetKey, AssetType } from \"./AssetKey\";\n\nexport const DEFAULT_ROOT = \"https://assets.mcasset.cloud/1.21.11\";\nexport const DEFAULT_NAMESPACE = \"minecraft\";\n\n/** Convenience accessors for model and blockstate loading. */\nexport class Assets {\n\n /**\n * @deprecated\n */\n public static parseAssetKey(assetType: AssetType, str: string, origin?: AssetKey): AssetKey {\n return AssetKey.parse(assetType, str, origin);\n }\n\n /** Loads a model with its parent chain resolved. See {@link Models.getMerged}. */\n public static async getModel(key: AssetKey): Promise<Maybe<Model>> {\n return Models.getMerged(key);\n }\n\n /** Loads a blockstate definition. See {@link BlockStates.get}. */\n public static async getBlockState(key: AssetKey): Promise<Maybe<BlockState>> {\n return BlockStates.get(key);\n }\n\n}\n"],"mappings":";AAAA,SAAS,cAAc;AAIvB,SAAS,mBAAmB;AAC5B,SAAS,gBAA2B;AAE7B,IAAM,eAAe;AACrB,IAAM,oBAAoB;AAG1B,IAAM,SAAN,MAAa;AAAA;AAAA;AAAA;AAAA,EAKhB,OAAc,cAAc,WAAsB,KAAa,QAA6B;AACxF,WAAO,SAAS,MAAM,WAAW,KAAK,MAAM;AAAA,EAChD;AAAA;AAAA,EAGA,aAAoB,SAAS,KAAsC;AAC/D,WAAO,OAAO,UAAU,GAAG;AAAA,EAC/B;AAAA;AAAA,EAGA,aAAoB,cAAc,KAA2C;AACzE,WAAO,YAAY,IAAI,GAAG;AAAA,EAC9B;AAEJ;","names":[]}
1
+ {"version":3,"sources":["../../../../src/assets/Assets.ts"],"sourcesContent":["import { Models } from \"./Models\";\nimport { Model } from \"../model/Model\";\nimport { Maybe } from \"../util/util\";\nimport { BlockState } from \"../model/block/BlockState\";\nimport { BlockStates } from \"./BlockStates\";\nimport { AssetKey, AssetType } from \"./AssetKey\";\n\n/** Convenience accessors for model and blockstate loading. */\nexport class Assets {\n\n /**\n * @deprecated\n */\n public static parseAssetKey(assetType: AssetType, str: string, origin?: AssetKey): AssetKey {\n return AssetKey.parse(assetType, str, origin);\n }\n\n /** Loads a model with its parent chain resolved. See {@link Models.getMerged}. */\n public static async getModel(key: AssetKey): Promise<Maybe<Model>> {\n return Models.getMerged(key);\n }\n\n /** Loads a blockstate definition. See {@link BlockStates.get}. */\n public static async getBlockState(key: AssetKey): Promise<Maybe<BlockState>> {\n return BlockStates.get(key);\n }\n\n}\n"],"mappings":";AAAA,SAAS,cAAc;AAIvB,SAAS,mBAAmB;AAC5B,SAAS,gBAA2B;AAG7B,IAAM,SAAN,MAAa;AAAA;AAAA;AAAA;AAAA,EAKhB,OAAc,cAAc,WAAsB,KAAa,QAA6B;AACxF,WAAO,SAAS,MAAM,WAAW,KAAK,MAAM;AAAA,EAChD;AAAA;AAAA,EAGA,aAAoB,SAAS,KAAsC;AAC/D,WAAO,OAAO,UAAU,GAAG;AAAA,EAC/B;AAAA;AAAA,EAGA,aAAoB,cAAc,KAA2C;AACzE,WAAO,YAAY,IAAI,GAAG;AAAA,EAC9B;AAEJ;","names":[]}
@@ -1,7 +1,7 @@
1
1
  // src/assets/BlockStates.ts
2
2
  import { Caching } from "../cache/Caching.mjs";
3
3
  import { AssetLoader } from "./AssetLoader.mjs";
4
- import { DEFAULT_NAMESPACE } from "./Assets.mjs";
4
+ import { DEFAULT_NAMESPACE } from "./AssetDefaults.mjs";
5
5
  import { AssetKey } from "./AssetKey.mjs";
6
6
  import { PersistentCache } from "../cache/PersistentCache.mjs";
7
7
  import { AssetParser } from "./source/parser/AssetParsers.mjs";
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/assets/BlockStates.ts"],"sourcesContent":["import { Maybe } from \"../util/util\";\nimport { BlockState } from \"../model/block/BlockState\";\nimport { Caching } from \"../cache/Caching\";\nimport { AssetLoader } from \"./AssetLoader\";\nimport { DEFAULT_NAMESPACE } from \"./Assets\";\nimport { BlockStatePropertyDefaults } from \"../model/block/BlockStateProperties\";\nimport { AssetKey } from \"./AssetKey\";\nimport { PersistentCache } from \"../cache/PersistentCache\";\nimport { AssetParser } from \"./source/parser/AssetParsers\";\nimport { ListAsset } from \"../ListAsset\";\nimport { MinecraftAsset } from \"../MinecraftAsset\";\nimport { Renames } from \"./Renames\";\nimport { MineRenderData } from \"./MineRenderData\";\n\n/** Loads blockstate definitions and the property defaults used to select block models. */\nexport class BlockStates {\n\n private static _persistentCache: PersistentCache | undefined;\n\n private static get PERSISTENT_CACHE(): PersistentCache {\n return this._persistentCache ??= PersistentCache.open(\"minerender-blockstates\");\n }\n\n // BlockState names are hardcoded\n /** Returns blockstate filenames from the selected version's `_list.json`, or an empty list. */\n public static async getList(): Promise<string[]> {\n const key = new AssetKey(\n DEFAULT_NAMESPACE,\n \"_list\",\n \"blockstates\",\n undefined,\n \"assets\",\n \".json\",\n AssetLoader.ROOT\n );\n return Caching.listAssetCache.get(key.serialize(), () => {\n return AssetLoader.get<ListAsset>(key, AssetParser.LIST);\n }).then(r => r?.files ?? []);\n }\n\n public static async getDefaultStates(root?: string): Promise<Maybe<DefaultBlockStates>> {\n return MineRenderData.get(\"blockStates\", root);\n }\n\n /** Looks up vanilla property definitions for the key's block path, or returns `undefined`. */\n public static async getDefaultState(key: AssetKey): Promise<Maybe<BlockStatePropertyDefaults>> {\n const defaultStates = await this.getDefaultStates(key.root);\n if (!defaultStates) {\n return undefined;\n }\n return defaultStates[key.toNamespacedString()] as BlockStatePropertyDefaults;\n }\n\n /** Loads a cached blockstate definition for {@link MineRenderScene.addBlock}, or returns `undefined`. */\n public static async get(key: AssetKey): Promise<Maybe<BlockState>> {\n if (!key.assetType) {\n key.assetType = \"blockstates\";\n }\n if (!key.extension) {\n key.extension = \".json\";\n }\n // An ID from an older version loads its replacement. The registry fallback can select a table\n // newer than the assets, so a missing replacement keeps the original ID.\n const renamed = await Renames.key(\"blocks\", key);\n const replacement = renamed && await this.get(renamed);\n if (replacement) return replacement;\n const keyStr = key.serialize();\n return Caching.blockStateCache.get(keyStr, k => {\n return this.PERSISTENT_CACHE.getOrLoad(AssetLoader.persistentKey(keyStr), k1 => {\n return AssetLoader.get<BlockState>(key, AssetParser.BLOCKSTATE);\n })\n }).then(asset => {\n if (asset) {\n asset.key = key;\n }\n return asset;\n })\n }\n\n public static getAll(keys: AssetKey[] | Iterable<AssetKey>): Promise<Maybe<BlockState>[]> {\n const promises: Promise<Maybe<BlockState>>[] = [];\n for (let key of keys) {\n promises.push(this.get(key));\n }\n return Promise.all(promises);\n }\n\n /** Clears persisted blockstates. Use {@link Caching.clear} to also discard in-memory assets. */\n public static async clearCache() {\n await this.PERSISTENT_CACHE.clear();\n }\n\n}\n\nexport class DefaultBlockStates implements MinecraftAsset {\n [k: string]: BlockStatePropertyDefaults;\n}\n"],"mappings":";AAEA,SAAS,eAAe;AACxB,SAAS,mBAAmB;AAC5B,SAAS,yBAAyB;AAElC,SAAS,gBAAgB;AACzB,SAAS,uBAAuB;AAChC,SAAS,mBAAmB;AAG5B,SAAS,eAAe;AACxB,SAAS,sBAAsB;AAGxB,IAAM,cAAN,MAAkB;AAAA,EAIrB,WAAmB,mBAAoC;AACnD,WAAO,KAAK,qBAAL,KAAK,mBAAqB,gBAAgB,KAAK,wBAAwB;AAAA,EAClF;AAAA;AAAA;AAAA,EAIA,aAAoB,UAA6B;AAC7C,UAAM,MAAM,IAAI;AAAA,MACZ;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,YAAY;AAAA,IAChB;AACA,WAAO,QAAQ,eAAe,IAAI,IAAI,UAAU,GAAG,MAAM;AACrD,aAAO,YAAY,IAAe,KAAK,YAAY,IAAI;AAAA,IAC3D,CAAC,EAAE,KAAK,OAAK,GAAG,SAAS,CAAC,CAAC;AAAA,EAC/B;AAAA,EAEA,aAAoB,iBAAiB,MAAmD;AACpF,WAAO,eAAe,IAAI,eAAe,IAAI;AAAA,EACjD;AAAA;AAAA,EAGA,aAAoB,gBAAgB,KAA2D;AAC3F,UAAM,gBAAgB,MAAM,KAAK,iBAAiB,IAAI,IAAI;AAC1D,QAAI,CAAC,eAAe;AAChB,aAAO;AAAA,IACX;AACA,WAAO,cAAc,IAAI,mBAAmB,CAAC;AAAA,EACjD;AAAA;AAAA,EAGA,aAAoB,IAAI,KAA2C;AAC/D,QAAI,CAAC,IAAI,WAAW;AAChB,UAAI,YAAY;AAAA,IACpB;AACA,QAAI,CAAC,IAAI,WAAW;AAChB,UAAI,YAAY;AAAA,IACpB;AAGA,UAAM,UAAU,MAAM,QAAQ,IAAI,UAAU,GAAG;AAC/C,UAAM,cAAc,WAAW,MAAM,KAAK,IAAI,OAAO;AACrD,QAAI,YAAa,QAAO;AACxB,UAAM,SAAS,IAAI,UAAU;AAC7B,WAAO,QAAQ,gBAAgB,IAAI,QAAQ,OAAK;AAC5C,aAAO,KAAK,iBAAiB,UAAU,YAAY,cAAc,MAAM,GAAG,QAAM;AAC5E,eAAO,YAAY,IAAgB,KAAK,YAAY,UAAU;AAAA,MAClE,CAAC;AAAA,IACL,CAAC,EAAE,KAAK,WAAS;AACb,UAAI,OAAO;AACP,cAAM,MAAM;AAAA,MAChB;AACA,aAAO;AAAA,IACX,CAAC;AAAA,EACL;AAAA,EAEA,OAAc,OAAO,MAAqE;AACtF,UAAM,WAAyC,CAAC;AAChD,aAAS,OAAO,MAAM;AAClB,eAAS,KAAK,KAAK,IAAI,GAAG,CAAC;AAAA,IAC/B;AACA,WAAO,QAAQ,IAAI,QAAQ;AAAA,EAC/B;AAAA;AAAA,EAGA,aAAoB,aAAa;AAC7B,UAAM,KAAK,iBAAiB,MAAM;AAAA,EACtC;AAEJ;AAEO,IAAM,qBAAN,MAAmD;AAE1D;","names":[]}
1
+ {"version":3,"sources":["../../../../src/assets/BlockStates.ts"],"sourcesContent":["import { Maybe } from \"../util/util\";\nimport { BlockState } from \"../model/block/BlockState\";\nimport { Caching } from \"../cache/Caching\";\nimport { AssetLoader } from \"./AssetLoader\";\nimport { DEFAULT_NAMESPACE } from \"./AssetDefaults\";\nimport { BlockStatePropertyDefaults } from \"../model/block/BlockStateProperties\";\nimport { AssetKey } from \"./AssetKey\";\nimport { PersistentCache } from \"../cache/PersistentCache\";\nimport { AssetParser } from \"./source/parser/AssetParsers\";\nimport { ListAsset } from \"../ListAsset\";\nimport { MinecraftAsset } from \"../MinecraftAsset\";\nimport { Renames } from \"./Renames\";\nimport { MineRenderData } from \"./MineRenderData\";\n\n/** Loads blockstate definitions and the property defaults used to select block models. */\nexport class BlockStates {\n\n private static _persistentCache: PersistentCache | undefined;\n\n private static get PERSISTENT_CACHE(): PersistentCache {\n return this._persistentCache ??= PersistentCache.open(\"minerender-blockstates\");\n }\n\n // BlockState names are hardcoded\n /** Returns blockstate filenames from the selected version's `_list.json`, or an empty list. */\n public static async getList(): Promise<string[]> {\n const key = new AssetKey(\n DEFAULT_NAMESPACE,\n \"_list\",\n \"blockstates\",\n undefined,\n \"assets\",\n \".json\",\n AssetLoader.ROOT\n );\n return Caching.listAssetCache.get(key.serialize(), () => {\n return AssetLoader.get<ListAsset>(key, AssetParser.LIST);\n }).then(r => r?.files ?? []);\n }\n\n public static async getDefaultStates(root?: string): Promise<Maybe<DefaultBlockStates>> {\n return MineRenderData.get(\"blockStates\", root);\n }\n\n /** Looks up vanilla property definitions for the key's block path, or returns `undefined`. */\n public static async getDefaultState(key: AssetKey): Promise<Maybe<BlockStatePropertyDefaults>> {\n const defaultStates = await this.getDefaultStates(key.root);\n if (!defaultStates) {\n return undefined;\n }\n return defaultStates[key.toNamespacedString()] as BlockStatePropertyDefaults;\n }\n\n /** Loads a cached blockstate definition for {@link MineRenderScene.addBlock}, or returns `undefined`. */\n public static async get(key: AssetKey): Promise<Maybe<BlockState>> {\n if (!key.assetType) {\n key.assetType = \"blockstates\";\n }\n if (!key.extension) {\n key.extension = \".json\";\n }\n // An ID from an older version loads its replacement. The registry fallback can select a table\n // newer than the assets, so a missing replacement keeps the original ID.\n const renamed = await Renames.key(\"blocks\", key);\n const replacement = renamed && await this.get(renamed);\n if (replacement) return replacement;\n const keyStr = key.serialize();\n return Caching.blockStateCache.get(keyStr, k => {\n return this.PERSISTENT_CACHE.getOrLoad(AssetLoader.persistentKey(keyStr), k1 => {\n return AssetLoader.get<BlockState>(key, AssetParser.BLOCKSTATE);\n })\n }).then(asset => {\n if (asset) {\n asset.key = key;\n }\n return asset;\n })\n }\n\n public static getAll(keys: AssetKey[] | Iterable<AssetKey>): Promise<Maybe<BlockState>[]> {\n const promises: Promise<Maybe<BlockState>>[] = [];\n for (let key of keys) {\n promises.push(this.get(key));\n }\n return Promise.all(promises);\n }\n\n /** Clears persisted blockstates. Use {@link Caching.clear} to also discard in-memory assets. */\n public static async clearCache() {\n await this.PERSISTENT_CACHE.clear();\n }\n\n}\n\nexport class DefaultBlockStates implements MinecraftAsset {\n [k: string]: BlockStatePropertyDefaults;\n}\n"],"mappings":";AAEA,SAAS,eAAe;AACxB,SAAS,mBAAmB;AAC5B,SAAS,yBAAyB;AAElC,SAAS,gBAAgB;AACzB,SAAS,uBAAuB;AAChC,SAAS,mBAAmB;AAG5B,SAAS,eAAe;AACxB,SAAS,sBAAsB;AAGxB,IAAM,cAAN,MAAkB;AAAA,EAIrB,WAAmB,mBAAoC;AACnD,WAAO,KAAK,qBAAL,KAAK,mBAAqB,gBAAgB,KAAK,wBAAwB;AAAA,EAClF;AAAA;AAAA;AAAA,EAIA,aAAoB,UAA6B;AAC7C,UAAM,MAAM,IAAI;AAAA,MACZ;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,YAAY;AAAA,IAChB;AACA,WAAO,QAAQ,eAAe,IAAI,IAAI,UAAU,GAAG,MAAM;AACrD,aAAO,YAAY,IAAe,KAAK,YAAY,IAAI;AAAA,IAC3D,CAAC,EAAE,KAAK,OAAK,GAAG,SAAS,CAAC,CAAC;AAAA,EAC/B;AAAA,EAEA,aAAoB,iBAAiB,MAAmD;AACpF,WAAO,eAAe,IAAI,eAAe,IAAI;AAAA,EACjD;AAAA;AAAA,EAGA,aAAoB,gBAAgB,KAA2D;AAC3F,UAAM,gBAAgB,MAAM,KAAK,iBAAiB,IAAI,IAAI;AAC1D,QAAI,CAAC,eAAe;AAChB,aAAO;AAAA,IACX;AACA,WAAO,cAAc,IAAI,mBAAmB,CAAC;AAAA,EACjD;AAAA;AAAA,EAGA,aAAoB,IAAI,KAA2C;AAC/D,QAAI,CAAC,IAAI,WAAW;AAChB,UAAI,YAAY;AAAA,IACpB;AACA,QAAI,CAAC,IAAI,WAAW;AAChB,UAAI,YAAY;AAAA,IACpB;AAGA,UAAM,UAAU,MAAM,QAAQ,IAAI,UAAU,GAAG;AAC/C,UAAM,cAAc,WAAW,MAAM,KAAK,IAAI,OAAO;AACrD,QAAI,YAAa,QAAO;AACxB,UAAM,SAAS,IAAI,UAAU;AAC7B,WAAO,QAAQ,gBAAgB,IAAI,QAAQ,OAAK;AAC5C,aAAO,KAAK,iBAAiB,UAAU,YAAY,cAAc,MAAM,GAAG,QAAM;AAC5E,eAAO,YAAY,IAAgB,KAAK,YAAY,UAAU;AAAA,MAClE,CAAC;AAAA,IACL,CAAC,EAAE,KAAK,WAAS;AACb,UAAI,OAAO;AACP,cAAM,MAAM;AAAA,MAChB;AACA,aAAO;AAAA,IACX,CAAC;AAAA,EACL;AAAA,EAEA,OAAc,OAAO,MAAqE;AACtF,UAAM,WAAyC,CAAC;AAChD,aAAS,OAAO,MAAM;AAClB,eAAS,KAAK,KAAK,IAAI,GAAG,CAAC;AAAA,IAC/B;AACA,WAAO,QAAQ,IAAI,QAAQ;AAAA,EAC/B;AAAA;AAAA,EAGA,aAAoB,aAAa;AAC7B,UAAM,KAAK,iBAAiB,MAAM;AAAA,EACtC;AAEJ;AAEO,IAAM,qBAAN,MAAmD;AAE1D;","names":[]}
@@ -3,7 +3,7 @@ import { AssetKey, isAssetKey } from "./AssetKey.mjs";
3
3
  import { AssetLoader } from "./AssetLoader.mjs";
4
4
  import { AssetParser } from "./source/index.mjs";
5
5
  import { Caching } from "../cache/Caching.mjs";
6
- import { DEFAULT_NAMESPACE } from "./Assets.mjs";
6
+ import { DEFAULT_NAMESPACE } from "./AssetDefaults.mjs";
7
7
  import { MineRenderError } from "../error/MineRenderError.mjs";
8
8
  import { ModelTextures } from "./ModelTextures.mjs";
9
9
  var Entities = class {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/assets/Entities.ts"],"sourcesContent":["import { AssetKey, BasicAssetKey, isAssetKey } from \"./AssetKey\";\nimport type { EntityLayer, EntityModel, EntityModelFile, EntityModelPass } from \"../entity/EntityModel\";\nimport type { EntityAnimation, EntityAnimationFile } from \"../entity/EntityAnimation\";\nimport { AssetLoader } from \"./AssetLoader\";\nimport { AssetParser } from \"./source\";\nimport { Maybe } from \"../util\";\nimport { Caching } from \"../cache/Caching\";\nimport { DEFAULT_NAMESPACE } from \"./Assets\";\nimport type { ListAsset } from \"../ListAsset\";\nimport { MineRenderError } from \"../error/MineRenderError\";\nimport { ModelTextures } from \"./ModelTextures\";\nimport type { MinecraftAsset } from \"../MinecraftAsset\";\n\n/** Loads entity and block-entity geometry, texture selections, and animation clips from the dataset. */\nexport class Entities {\n\n /** Lists model paths in the `minecraft` namespace, including subdirectories and excluding `.json`. */\n public static async getEntityList(): Promise<string[]> {\n const collect = async (path: string): Promise<string[]> => {\n const prefix = path ? `${path}/` : \"\";\n const key = new AssetKey(DEFAULT_NAMESPACE, `${prefix}_list`, undefined, undefined, \"entity-models\", \".json\");\n const list = await Caching.listAssetCache.get(key.serialize(), () => AssetLoader.get<ListAsset>(key, AssetParser.LIST));\n if (!list) return [];\n const files = list.files.filter(file => file.endsWith(\".json\") && file !== \"_list.json\")\n .map(file => `${prefix}${file.slice(0, -5)}`);\n const children = await Promise.all(list.directories.map(directory => collect(`${prefix}${directory}`)));\n return [...files, ...children.flat()];\n };\n return collect(\"\");\n }\n\n private static async getModelFile(modelKey: BasicAssetKey): Promise<Maybe<EntityModelFile>> {\n const path = isAssetKey(modelKey) ? modelKey.getFullPath() : modelKey.path;\n const key = new AssetKey(modelKey.namespace, path, undefined, undefined, \"entity-models\", \".json\", isAssetKey(modelKey) ? modelKey.root : undefined);\n return Caching.entityModelCache.get(key.serialize(), () => AssetLoader.get<EntityModelFile>(key, AssetParser.JSON));\n }\n\n /** Returns selectable geometry-layer names, or an empty list when the model is missing. */\n public static async getLayerList(modelKey: BasicAssetKey): Promise<string[]> {\n return Object.keys((await this.getModelFile(modelKey))?.layers ?? {});\n }\n\n /** The dataset's extra draws on top of `main`; their `when` labels are the states `EntityModelOptions.when` can enable. */\n public static async getPassList(modelKey: BasicAssetKey): Promise<EntityModelPass[]> {\n return (await this.getModelFile(modelKey))?.passes ?? [];\n }\n\n /**\n * Loads the layers and textures to pass to {@link MineRenderScene.addEntity}.\n * By default, selects `main`, unconditional passes, and passes enabled by `options.when`.\n *\n * @param modelKey - Dataset model, such as `new BasicAssetKey(\"minecraft\", \"zombie\")`.\n * @param textureKey - Texture override for the first selected layer.\n * @param options - Layer selection, conditional passes, and per-layer texture overrides.\n * @returns The selected model, or `undefined` when its dataset file is missing.\n */\n public static async getEntity(modelKey: BasicAssetKey, textureKey?: BasicAssetKey, options?: EntityModelOptions): Promise<Maybe<EntityModel>> {\n const model = await this.getModelFile(modelKey);\n if (!model) return undefined;\n // Without an explicit selection, draw what vanilla draws: main, then the passes enabled for the requested state.\n const passes = options?.layers || options?.layer !== undefined ? [] :\n (model.passes ?? []).filter(pass => pass.when === undefined || options?.when?.includes(pass.when));\n const draws: EntityModelPass[] = [...new Set(options?.layers ?? [options?.layer ?? \"main\"])].map(layer => ({ layer }));\n if (draws.length === 0) throw new MineRenderError(`Entity ${model.id} requires at least one layer`);\n draws.push(...passes);\n const names: string[] = [];\n const selected = draws.map(pass => {\n const layer = model.layers[pass.layer];\n if (!layer) {\n throw new MineRenderError(`Entity ${model.id} has no layer \"${pass.layer}\". Available layers: ${Object.keys(model.layers).join(\", \")}`);\n }\n // A pass may draw geometry that is already selected with another texture.\n let name = pass.layer;\n for (let n = 2; names.includes(name); n++) name = `${pass.layer}#${n}`;\n names.push(name);\n return { name, layer, pass };\n });\n const layers: Record<string, EntityLayer> = Object.fromEntries(await Promise.all(selected.map(async ({ name, layer, pass }, index) => {\n const override = options?.textures?.[name] ?? (index === 0 ? textureKey : undefined);\n const textureLocation = pass.textureLocation ?? layer.textureLocation;\n let texture: Maybe<AssetKey>;\n if (override) {\n const path = isAssetKey(override) ? override.getFullPath() : override.path;\n texture = isAssetKey(override) && override.assetType === \"textures\" && path.startsWith(\"entity/\")\n ? override\n : new AssetKey(override.namespace, path, \"textures\", \"entity\", \"assets\", \".png\", isAssetKey(override) ? override.root : undefined);\n } else if (textureLocation !== undefined) {\n texture = AssetKey.parse(\"textures\", textureLocation.replace(/^([^:]+:)?textures\\//, \"$1\"));\n if (isAssetKey(modelKey)) texture.root = modelKey.root;\n } else {\n texture = await this.resolveTexture(modelKey);\n }\n const render = pass.render ?? layer.render;\n return [name, { key: override ?? modelKey, texture, layer, ...(render && { render }), ...(pass.tint && { tint: pass.tint }) }];\n })));\n return { ...layers[names[0]], id: model.id, layers, ...(model.transform && { transform: model.transform }) };\n }\n\n /**\n * Native and sampled vanilla clips by name, or undefined when the model or selected version has none.\n */\n public static async getAnimations(modelKey: BasicAssetKey): Promise<Maybe<Record<string, EntityAnimation>>> {\n const path = isAssetKey(modelKey) ? modelKey.getFullPath() : modelKey.path;\n const key = new AssetKey(modelKey.namespace, path, undefined, undefined, \"entity-models/animations\", \".json\", isAssetKey(modelKey) ? modelKey.root : undefined);\n const file = await Caching.entityAnimationCache.get(key.serialize(), () => AssetLoader.get<EntityAnimationFile>(key, AssetParser.JSON));\n return file?.animations;\n }\n\n /** Finds a fallback texture using the model path, its directory, and vanilla variant data. */\n public static async resolveTexture(modelKey: BasicAssetKey): Promise<Maybe<AssetKey>> {\n const path = isAssetKey(modelKey) ? modelKey.getFullPath() : modelKey.path;\n const root = isAssetKey(modelKey) ? modelKey.root : undefined;\n const key = new AssetKey(modelKey.namespace, path, undefined, undefined, \"entity-models\", \".json\", root);\n return Caching.entityTextureCache.get(key.serialize(), async () => {\n const name = path.split(\"/\").pop()!;\n for (const candidate of [path, `${path}/${name}`]) {\n const texture = new AssetKey(modelKey.namespace, candidate, \"textures\", \"entity\", \"assets\", \".png\", root);\n if (await ModelTextures.get(texture)) return texture;\n }\n const listKey = new AssetKey(modelKey.namespace, \"_list\", `${name}_variant`, undefined, \"data\", \".json\", root);\n const list = await AssetLoader.get<ListAsset>(listKey, AssetParser.LIST);\n const files = list?.files.filter(file => file.endsWith(\".json\") && file !== \"_list.json\");\n const file = files?.find(file => file === \"temperate.json\") ?? files?.[0];\n if (!file) return undefined;\n const variantKey = new AssetKey(modelKey.namespace, file.slice(0, -5), `${name}_variant`, undefined, \"data\", \".json\", root);\n const variant = await AssetLoader.get<EntityVariant>(variantKey, AssetParser.JSON);\n const assets = variant?.assets;\n const textureId = variant?.asset_id ?? (typeof assets?.wild === \"string\" ? assets.wild :\n Object.values(assets ?? {}).find(value => typeof value === \"string\"));\n if (typeof textureId !== \"string\") return undefined;\n const texture = AssetKey.parse(\"textures\", textureId);\n texture.root = root;\n return texture;\n });\n }\n\n /** @deprecated Use getEntityList(); block entities share the entity dataset. */\n public static getBlockList(): Promise<string[]> {\n return this.getEntityList();\n }\n\n /** @deprecated Use getEntity(); block entities share the entity dataset. */\n public static getBlock(modelKey: BasicAssetKey, textureKey?: BasicAssetKey, options?: EntityModelOptions): Promise<Maybe<EntityModel>> {\n return this.getEntity(modelKey, textureKey, options);\n }\n\n}\n\n/** Selection settings passed as the third argument to {@link Entities.getEntity}. */\nexport interface EntityModelOptions {\n /** Selects one geometry layer without dataset passes. `layers` takes precedence when supplied. */\n layer?: string;\n /** Layer names in draw order; an explicit selection draws exactly these layers and no dataset passes. */\n layers?: string[];\n /**\n * Entity states that enable the dataset's conditional passes, e.g. `[\"powered\"]` for a charged creeper.\n * Without `layer`/`layers`, `main` and every unconditional pass are always drawn.\n */\n when?: string[];\n /** Per-layer texture overrides, keyed like `EntityModel.layers`. The positional texture key applies to the first selected layer. */\n textures?: Record<string, BasicAssetKey>;\n}\n\ninterface EntityVariant extends MinecraftAsset {\n asset_id?: string;\n assets?: Record<string, unknown>;\n}\n"],"mappings":"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","names":["texture","file"]}
1
+ {"version":3,"sources":["../../../../src/assets/Entities.ts"],"sourcesContent":["import { AssetKey, BasicAssetKey, isAssetKey } from \"./AssetKey\";\nimport type { EntityLayer, EntityModel, EntityModelFile, EntityModelPass } from \"../entity/EntityModel\";\nimport type { EntityAnimation, EntityAnimationFile } from \"../entity/EntityAnimation\";\nimport { AssetLoader } from \"./AssetLoader\";\nimport { AssetParser } from \"./source\";\nimport { Maybe } from \"../util\";\nimport { Caching } from \"../cache/Caching\";\nimport { DEFAULT_NAMESPACE } from \"./AssetDefaults\";\nimport type { ListAsset } from \"../ListAsset\";\nimport { MineRenderError } from \"../error/MineRenderError\";\nimport { ModelTextures } from \"./ModelTextures\";\nimport type { MinecraftAsset } from \"../MinecraftAsset\";\n\n/** Loads entity and block-entity geometry, texture selections, and animation clips from the dataset. */\nexport class Entities {\n\n /** Lists model paths in the `minecraft` namespace, including subdirectories and excluding `.json`. */\n public static async getEntityList(): Promise<string[]> {\n const collect = async (path: string): Promise<string[]> => {\n const prefix = path ? `${path}/` : \"\";\n const key = new AssetKey(DEFAULT_NAMESPACE, `${prefix}_list`, undefined, undefined, \"entity-models\", \".json\");\n const list = await Caching.listAssetCache.get(key.serialize(), () => AssetLoader.get<ListAsset>(key, AssetParser.LIST));\n if (!list) return [];\n const files = list.files.filter(file => file.endsWith(\".json\") && file !== \"_list.json\")\n .map(file => `${prefix}${file.slice(0, -5)}`);\n const children = await Promise.all(list.directories.map(directory => collect(`${prefix}${directory}`)));\n return [...files, ...children.flat()];\n };\n return collect(\"\");\n }\n\n private static async getModelFile(modelKey: BasicAssetKey): Promise<Maybe<EntityModelFile>> {\n const path = isAssetKey(modelKey) ? modelKey.getFullPath() : modelKey.path;\n const key = new AssetKey(modelKey.namespace, path, undefined, undefined, \"entity-models\", \".json\", isAssetKey(modelKey) ? modelKey.root : undefined);\n return Caching.entityModelCache.get(key.serialize(), () => AssetLoader.get<EntityModelFile>(key, AssetParser.JSON));\n }\n\n /** Returns selectable geometry-layer names, or an empty list when the model is missing. */\n public static async getLayerList(modelKey: BasicAssetKey): Promise<string[]> {\n return Object.keys((await this.getModelFile(modelKey))?.layers ?? {});\n }\n\n /** The dataset's extra draws on top of `main`; their `when` labels are the states `EntityModelOptions.when` can enable. */\n public static async getPassList(modelKey: BasicAssetKey): Promise<EntityModelPass[]> {\n return (await this.getModelFile(modelKey))?.passes ?? [];\n }\n\n /**\n * Loads the layers and textures to pass to {@link MineRenderScene.addEntity}.\n * By default, selects `main`, unconditional passes, and passes enabled by `options.when`.\n *\n * @param modelKey - Dataset model, such as `new BasicAssetKey(\"minecraft\", \"zombie\")`.\n * @param textureKey - Texture override for the first selected layer.\n * @param options - Layer selection, conditional passes, and per-layer texture overrides.\n * @returns The selected model, or `undefined` when its dataset file is missing.\n */\n public static async getEntity(modelKey: BasicAssetKey, textureKey?: BasicAssetKey, options?: EntityModelOptions): Promise<Maybe<EntityModel>> {\n const model = await this.getModelFile(modelKey);\n if (!model) return undefined;\n // Without an explicit selection, draw what vanilla draws: main, then the passes enabled for the requested state.\n const passes = options?.layers || options?.layer !== undefined ? [] :\n (model.passes ?? []).filter(pass => pass.when === undefined || options?.when?.includes(pass.when));\n const draws: EntityModelPass[] = [...new Set(options?.layers ?? [options?.layer ?? \"main\"])].map(layer => ({ layer }));\n if (draws.length === 0) throw new MineRenderError(`Entity ${model.id} requires at least one layer`);\n draws.push(...passes);\n const names: string[] = [];\n const selected = draws.map(pass => {\n const layer = model.layers[pass.layer];\n if (!layer) {\n throw new MineRenderError(`Entity ${model.id} has no layer \"${pass.layer}\". Available layers: ${Object.keys(model.layers).join(\", \")}`);\n }\n // A pass may draw geometry that is already selected with another texture.\n let name = pass.layer;\n for (let n = 2; names.includes(name); n++) name = `${pass.layer}#${n}`;\n names.push(name);\n return { name, layer, pass };\n });\n const layers: Record<string, EntityLayer> = Object.fromEntries(await Promise.all(selected.map(async ({ name, layer, pass }, index) => {\n const override = options?.textures?.[name] ?? (index === 0 ? textureKey : undefined);\n const textureLocation = pass.textureLocation ?? layer.textureLocation;\n let texture: Maybe<AssetKey>;\n if (override) {\n const path = isAssetKey(override) ? override.getFullPath() : override.path;\n texture = isAssetKey(override) && override.assetType === \"textures\" && path.startsWith(\"entity/\")\n ? override\n : new AssetKey(override.namespace, path, \"textures\", \"entity\", \"assets\", \".png\", isAssetKey(override) ? override.root : undefined);\n } else if (textureLocation !== undefined) {\n texture = AssetKey.parse(\"textures\", textureLocation.replace(/^([^:]+:)?textures\\//, \"$1\"));\n if (isAssetKey(modelKey)) texture.root = modelKey.root;\n } else {\n texture = await this.resolveTexture(modelKey);\n }\n const render = pass.render ?? layer.render;\n return [name, { key: override ?? modelKey, texture, layer, ...(render && { render }), ...(pass.tint && { tint: pass.tint }) }];\n })));\n return { ...layers[names[0]], id: model.id, layers, ...(model.transform && { transform: model.transform }) };\n }\n\n /**\n * Native and sampled vanilla clips by name, or undefined when the model or selected version has none.\n */\n public static async getAnimations(modelKey: BasicAssetKey): Promise<Maybe<Record<string, EntityAnimation>>> {\n const path = isAssetKey(modelKey) ? modelKey.getFullPath() : modelKey.path;\n const key = new AssetKey(modelKey.namespace, path, undefined, undefined, \"entity-models/animations\", \".json\", isAssetKey(modelKey) ? modelKey.root : undefined);\n const file = await Caching.entityAnimationCache.get(key.serialize(), () => AssetLoader.get<EntityAnimationFile>(key, AssetParser.JSON));\n return file?.animations;\n }\n\n /** Finds a fallback texture using the model path, its directory, and vanilla variant data. */\n public static async resolveTexture(modelKey: BasicAssetKey): Promise<Maybe<AssetKey>> {\n const path = isAssetKey(modelKey) ? modelKey.getFullPath() : modelKey.path;\n const root = isAssetKey(modelKey) ? modelKey.root : undefined;\n const key = new AssetKey(modelKey.namespace, path, undefined, undefined, \"entity-models\", \".json\", root);\n return Caching.entityTextureCache.get(key.serialize(), async () => {\n const name = path.split(\"/\").pop()!;\n for (const candidate of [path, `${path}/${name}`]) {\n const texture = new AssetKey(modelKey.namespace, candidate, \"textures\", \"entity\", \"assets\", \".png\", root);\n if (await ModelTextures.get(texture)) return texture;\n }\n const listKey = new AssetKey(modelKey.namespace, \"_list\", `${name}_variant`, undefined, \"data\", \".json\", root);\n const list = await AssetLoader.get<ListAsset>(listKey, AssetParser.LIST);\n const files = list?.files.filter(file => file.endsWith(\".json\") && file !== \"_list.json\");\n const file = files?.find(file => file === \"temperate.json\") ?? files?.[0];\n if (!file) return undefined;\n const variantKey = new AssetKey(modelKey.namespace, file.slice(0, -5), `${name}_variant`, undefined, \"data\", \".json\", root);\n const variant = await AssetLoader.get<EntityVariant>(variantKey, AssetParser.JSON);\n const assets = variant?.assets;\n const textureId = variant?.asset_id ?? (typeof assets?.wild === \"string\" ? assets.wild :\n Object.values(assets ?? {}).find(value => typeof value === \"string\"));\n if (typeof textureId !== \"string\") return undefined;\n const texture = AssetKey.parse(\"textures\", textureId);\n texture.root = root;\n return texture;\n });\n }\n\n /** @deprecated Use getEntityList(); block entities share the entity dataset. */\n public static getBlockList(): Promise<string[]> {\n return this.getEntityList();\n }\n\n /** @deprecated Use getEntity(); block entities share the entity dataset. */\n public static getBlock(modelKey: BasicAssetKey, textureKey?: BasicAssetKey, options?: EntityModelOptions): Promise<Maybe<EntityModel>> {\n return this.getEntity(modelKey, textureKey, options);\n }\n\n}\n\n/** Selection settings passed as the third argument to {@link Entities.getEntity}. */\nexport interface EntityModelOptions {\n /** Selects one geometry layer without dataset passes. `layers` takes precedence when supplied. */\n layer?: string;\n /** Layer names in draw order; an explicit selection draws exactly these layers and no dataset passes. */\n layers?: string[];\n /**\n * Entity states that enable the dataset's conditional passes, e.g. `[\"powered\"]` for a charged creeper.\n * Without `layer`/`layers`, `main` and every unconditional pass are always drawn.\n */\n when?: string[];\n /** Per-layer texture overrides, keyed like `EntityModel.layers`. The positional texture key applies to the first selected layer. */\n textures?: Record<string, BasicAssetKey>;\n}\n\ninterface EntityVariant extends MinecraftAsset {\n asset_id?: string;\n assets?: Record<string, unknown>;\n}\n"],"mappings":"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","names":["texture","file"]}
@@ -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";