minerender 2.1.0-beta.6 → 2.1.0-beta.7

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 (80) hide show
  1. package/dist/browser/esm/Materials.mjs +3 -1
  2. package/dist/browser/esm/Materials.mjs.map +1 -1
  3. package/dist/browser/esm/Ticker.mjs +3 -1
  4. package/dist/browser/esm/Ticker.mjs.map +1 -1
  5. package/dist/browser/esm/UVMapper.mjs +9 -9
  6. package/dist/browser/esm/UVMapper.mjs.map +1 -1
  7. package/dist/browser/esm/assets/AssetDefaults.mjs +8 -0
  8. package/dist/browser/esm/assets/AssetDefaults.mjs.map +1 -0
  9. package/dist/browser/esm/assets/AssetKey.mjs +1 -1
  10. package/dist/browser/esm/assets/AssetKey.mjs.map +1 -1
  11. package/dist/browser/esm/assets/AssetLoader.mjs +5 -5
  12. package/dist/browser/esm/assets/AssetLoader.mjs.map +1 -1
  13. package/dist/browser/esm/assets/Assets.mjs +1 -5
  14. package/dist/browser/esm/assets/Assets.mjs.map +1 -1
  15. package/dist/browser/esm/assets/BlockEntities.mjs +3 -1
  16. package/dist/browser/esm/assets/BlockEntities.mjs.map +1 -1
  17. package/dist/browser/esm/assets/BlockStates.mjs +1 -1
  18. package/dist/browser/esm/assets/BlockStates.mjs.map +1 -1
  19. package/dist/browser/esm/assets/Entities.mjs +1 -1
  20. package/dist/browser/esm/assets/Entities.mjs.map +1 -1
  21. package/dist/browser/esm/assets/Models.mjs +1 -1
  22. package/dist/browser/esm/assets/Models.mjs.map +1 -1
  23. package/dist/browser/esm/assets/_fonts/Unihex.mjs +5 -3
  24. package/dist/browser/esm/assets/_fonts/Unihex.mjs.map +1 -1
  25. package/dist/browser/esm/assets/index.mjs +1 -0
  26. package/dist/browser/esm/assets/index.mjs.map +1 -1
  27. package/dist/browser/esm/assets/source/HostedAssetSource.mjs +7 -8
  28. package/dist/browser/esm/assets/source/HostedAssetSource.mjs.map +1 -1
  29. package/dist/browser/esm/env/browser/BrowserCache.mjs +3 -3
  30. package/dist/browser/esm/env/browser/BrowserCache.mjs.map +1 -1
  31. package/dist/browser/esm/image/ImageLoader.mjs +3 -3
  32. package/dist/browser/esm/image/ImageLoader.mjs.map +1 -1
  33. package/dist/browser/esm/index.browser.d.mts +64 -11
  34. package/dist/browser/esm/inspector/SceneInspector.mjs +3 -3
  35. package/dist/browser/esm/inspector/SceneInspector.mjs.map +1 -1
  36. package/dist/browser/esm/instance/InstanceManager.mjs +4 -4
  37. package/dist/browser/esm/instance/InstanceManager.mjs.map +1 -1
  38. package/dist/browser/esm/model/block/scene/BlockObject.mjs +3 -1
  39. package/dist/browser/esm/model/block/scene/BlockObject.mjs.map +1 -1
  40. package/dist/browser/esm/model/multiblock/StructureParser.mjs +7 -4
  41. package/dist/browser/esm/model/multiblock/StructureParser.mjs.map +1 -1
  42. package/dist/browser/esm/model/scene/ModelObject.mjs +4 -4
  43. package/dist/browser/esm/model/scene/ModelObject.mjs.map +1 -1
  44. package/dist/browser/esm/nbt/NBTHelper.mjs +5 -2
  45. package/dist/browser/esm/nbt/NBTHelper.mjs.map +1 -1
  46. package/dist/browser/esm/renderer/Renderer.mjs +4 -2
  47. package/dist/browser/esm/renderer/Renderer.mjs.map +1 -1
  48. package/dist/browser/esm/renderer/SceneObject.mjs +0 -6
  49. package/dist/browser/esm/renderer/SceneObject.mjs.map +1 -1
  50. package/dist/browser/esm/request/Requests.mjs +3 -3
  51. package/dist/browser/esm/request/Requests.mjs.map +1 -1
  52. package/dist/browser/esm/skin/Skins.mjs +6 -4
  53. package/dist/browser/esm/skin/Skins.mjs.map +1 -1
  54. package/dist/browser/esm/texture/TextureLoader.mjs +4 -2
  55. package/dist/browser/esm/texture/TextureLoader.mjs.map +1 -1
  56. package/dist/browser/esm/util/log.mjs +75 -0
  57. package/dist/browser/esm/util/log.mjs.map +1 -1
  58. package/dist/browser/esm/util/performance.mjs.map +1 -1
  59. package/dist/browser/esm/world/Chunk.mjs +8 -5
  60. package/dist/browser/esm/world/Chunk.mjs.map +1 -1
  61. package/dist/browser/esm/world/MineRenderWorld.mjs +96 -54
  62. package/dist/browser/esm/world/MineRenderWorld.mjs.map +1 -1
  63. package/dist/browser/esm/world/WorldStreamer.mjs +21 -20
  64. package/dist/browser/esm/world/WorldStreamer.mjs.map +1 -1
  65. package/dist/browser/esm/world/_culling/BlockCulling.mjs +1 -1
  66. package/dist/browser/esm/world/_culling/BlockCulling.mjs.map +1 -1
  67. package/dist/browser/esm/world/_entities/WorldEntities.mjs +3 -1
  68. package/dist/browser/esm/world/_entities/WorldEntities.mjs.map +1 -1
  69. package/dist/browser/index.d.ts +64 -11
  70. package/dist/browser/index.js +3071 -2956
  71. package/dist/browser/index.js.map +1 -1
  72. package/dist/bundle.js +6095 -5975
  73. package/dist/bundle.js.map +1 -1
  74. package/dist/node/index.d.mts +64 -11
  75. package/dist/node/index.d.ts +64 -11
  76. package/dist/node/index.js +3095 -2978
  77. package/dist/node/index.js.map +1 -1
  78. package/dist/node/index.mjs +3087 -2971
  79. package/dist/node/index.mjs.map +1 -1
  80. package/package.json +1 -1
@@ -4,6 +4,8 @@ import { Color, CustomBlending, DoubleSide, OneFactor, OneMinusSrcAlphaFactor, R
4
4
  import { Textures } from "./texture/Textures.mjs";
5
5
  import { TextureLoader } from "./texture/TextureLoader.mjs";
6
6
  import { Caching } from "./cache/Caching.mjs";
7
+ import { logger } from "./util/log.mjs";
8
+ var log = logger("Materials");
7
9
  var Materials = class _Materials {
8
10
  /** Shared checkerboard material, created on first access. */
9
11
  static get MISSING_TEXTURE() {
@@ -274,7 +276,7 @@ var Materials = class _Materials {
274
276
  Object.assign(material.defaultAttributeValues, { shade: [1], uvBounds: [0, 0, 1, 1] });
275
277
  return material;
276
278
  } catch (e) {
277
- console.warn(e);
279
+ log.warn(e);
278
280
  }
279
281
  return this.createBasicCanvasMaterial(canvas, transparent, shade);
280
282
  }
@@ -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 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":[]}
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\";\nimport { logger } from \"./util/log\";\n\nconst log = logger(\"Materials\");\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 log.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,4 +1,6 @@
1
1
  // src/Ticker.ts
2
+ import { logger } from "./util/log.mjs";
3
+ var log = logger("Ticker");
2
4
  var _Ticker = class _Ticker {
3
5
  static schedule(fn, ms) {
4
6
  const handle = setInterval(fn, ms);
@@ -16,7 +18,7 @@ var _Ticker = class _Ticker {
16
18
  try {
17
19
  t();
18
20
  } catch (e) {
19
- console.warn(e);
21
+ log.warn(e);
20
22
  }
21
23
  });
22
24
  _Ticker.oneSecondTicks++;
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/Ticker.ts"],"sourcesContent":["/** A synchronous callback registered with {@link Ticker.add}. */\nexport interface TickerFunction {\n (): void;\n}\n\ntype IntervalHandle = ReturnType<typeof setInterval>;\n\n/**\n * Shared 20-per-second tick loop, used for things like animated texture frames.\n *\n * The timers are started lazily by {@link Ticker.add} and unref'd where the platform supports it -\n * importing MineRender must never on its own keep a Node process alive.\n */\nexport class Ticker {\n\n public static readonly TPS = 20;\n\n private static counter: number = 0;\n private static readonly _tickers: Map<number, TickerFunction> = new Map<number, TickerFunction>();\n\n private static interval: IntervalHandle | undefined;\n private static oneSecondTicksTracker: IntervalHandle | undefined;\n private static fiveSecondTicksTracker: IntervalHandle | undefined;\n\n private static oneSecondTps = 0;\n private static oneSecondTicks = 0;\n\n private static fiveSecondTps = 0;\n private static fiveSecondTicks = 0;\n\n private static schedule(fn: () => void, ms: number): IntervalHandle {\n const handle = setInterval(fn, ms);\n // Node's Timeout keeps the event loop alive unless unref'd; browsers return a plain number\n const unref = (handle as { unref?: () => void }).unref;\n if (typeof unref === \"function\") {\n unref.call(handle);\n }\n return handle;\n }\n\n /** Starts or resumes the shared tick loop. Repeated calls have no effect. */\n public static start(): void {\n if (this.interval) return;\n\n this.interval = this.schedule(() => {\n Ticker._tickers.forEach(t => {\n try {\n t();\n } catch (e) {\n console.warn(e);\n }\n });\n Ticker.oneSecondTicks++;\n Ticker.fiveSecondTicks++;\n }, 1000 / this.TPS);\n\n this.oneSecondTicksTracker = this.schedule(() => {\n Ticker.oneSecondTps = Ticker.oneSecondTicks;\n Ticker.oneSecondTicks = 0;\n }, 1000);\n\n this.fiveSecondTicksTracker = this.schedule(() => {\n Ticker.fiveSecondTps = Ticker.fiveSecondTicks / 5;\n Ticker.fiveSecondTicks = 0;\n }, 1000 * 5);\n }\n\n /** Pauses the loop while retaining callbacks for a later {@link start}. */\n public static stop(): void {\n if (this.interval) clearInterval(this.interval);\n if (this.oneSecondTicksTracker) clearInterval(this.oneSecondTicksTracker);\n if (this.fiveSecondTicksTracker) clearInterval(this.fiveSecondTicksTracker);\n this.interval = undefined;\n this.oneSecondTicksTracker = undefined;\n this.fiveSecondTicksTracker = undefined;\n }\n\n /** Registers a callback, starts the loop if needed, and returns an ID for {@link remove}. */\n public static add(tick: TickerFunction): number {\n this.start();\n const c = this.counter++;\n this._tickers.set(c, tick);\n return c;\n }\n\n /** Removes a callback by ID and stops the timers when no callbacks remain. */\n public static remove(c?: number) {\n // note: plain `if (c)` used to drop id 0, i.e. the very first registered ticker\n if (typeof c === \"number\") this._tickers.delete(c);\n if (!this._tickers.size) this.stop();\n }\n\n public static get tickers(): Map<number, TickerFunction> {\n return this._tickers;\n }\n\n public static get tpsOneSecond() {\n return this.oneSecondTps;\n }\n\n public static get tpsFiveSeconds() {\n return this.fiveSecondTps;\n }\n\n /** Stops the loop and removes all registered callbacks. */\n public static dispose() {\n this.stop();\n this._tickers.clear();\n }\n\n}\n"],"mappings":";AAaO,IAAM,UAAN,MAAM,QAAO;AAAA,EAiBhB,OAAe,SAAS,IAAgB,IAA4B;AAChE,UAAM,SAAS,YAAY,IAAI,EAAE;AAEjC,UAAM,QAAS,OAAkC;AACjD,QAAI,OAAO,UAAU,YAAY;AAC7B,YAAM,KAAK,MAAM;AAAA,IACrB;AACA,WAAO;AAAA,EACX;AAAA;AAAA,EAGA,OAAc,QAAc;AACxB,QAAI,KAAK,SAAU;AAEnB,SAAK,WAAW,KAAK,SAAS,MAAM;AAChC,cAAO,SAAS,QAAQ,OAAK;AACzB,YAAI;AACA,YAAE;AAAA,QACN,SAAS,GAAG;AACR,kBAAQ,KAAK,CAAC;AAAA,QAClB;AAAA,MACJ,CAAC;AACD,cAAO;AACP,cAAO;AAAA,IACX,GAAG,MAAO,KAAK,GAAG;AAElB,SAAK,wBAAwB,KAAK,SAAS,MAAM;AAC7C,cAAO,eAAe,QAAO;AAC7B,cAAO,iBAAiB;AAAA,IAC5B,GAAG,GAAI;AAEP,SAAK,yBAAyB,KAAK,SAAS,MAAM;AAC9C,cAAO,gBAAgB,QAAO,kBAAkB;AAChD,cAAO,kBAAkB;AAAA,IAC7B,GAAG,MAAO,CAAC;AAAA,EACf;AAAA;AAAA,EAGA,OAAc,OAAa;AACvB,QAAI,KAAK,SAAU,eAAc,KAAK,QAAQ;AAC9C,QAAI,KAAK,sBAAuB,eAAc,KAAK,qBAAqB;AACxE,QAAI,KAAK,uBAAwB,eAAc,KAAK,sBAAsB;AAC1E,SAAK,WAAW;AAChB,SAAK,wBAAwB;AAC7B,SAAK,yBAAyB;AAAA,EAClC;AAAA;AAAA,EAGA,OAAc,IAAI,MAA8B;AAC5C,SAAK,MAAM;AACX,UAAM,IAAI,KAAK;AACf,SAAK,SAAS,IAAI,GAAG,IAAI;AACzB,WAAO;AAAA,EACX;AAAA;AAAA,EAGA,OAAc,OAAO,GAAY;AAE7B,QAAI,OAAO,MAAM,SAAU,MAAK,SAAS,OAAO,CAAC;AACjD,QAAI,CAAC,KAAK,SAAS,KAAM,MAAK,KAAK;AAAA,EACvC;AAAA,EAEA,WAAkB,UAAuC;AACrD,WAAO,KAAK;AAAA,EAChB;AAAA,EAEA,WAAkB,eAAe;AAC7B,WAAO,KAAK;AAAA,EAChB;AAAA,EAEA,WAAkB,iBAAiB;AAC/B,WAAO,KAAK;AAAA,EAChB;AAAA;AAAA,EAGA,OAAc,UAAU;AACpB,SAAK,KAAK;AACV,SAAK,SAAS,MAAM;AAAA,EACxB;AAEJ;AAjGa,QAEc,MAAM;AAFpB,QAIM,UAAkB;AAJxB,QAKe,WAAwC,oBAAI,IAA4B;AALvF,QAWM,eAAe;AAXrB,QAYM,iBAAiB;AAZvB,QAcM,gBAAgB;AAdtB,QAeM,kBAAkB;AAf9B,IAAM,SAAN;","names":[]}
1
+ {"version":3,"sources":["../../../src/Ticker.ts"],"sourcesContent":["import { logger } from \"./util/log\";\n\nconst log = logger(\"Ticker\");\n\n/** A synchronous callback registered with {@link Ticker.add}. */\nexport interface TickerFunction {\n (): void;\n}\n\ntype IntervalHandle = ReturnType<typeof setInterval>;\n\n/**\n * Shared 20-per-second tick loop, used for things like animated texture frames.\n *\n * The timers are started lazily by {@link Ticker.add} and unref'd where the platform supports it -\n * importing MineRender must never on its own keep a Node process alive.\n */\nexport class Ticker {\n\n public static readonly TPS = 20;\n\n private static counter: number = 0;\n private static readonly _tickers: Map<number, TickerFunction> = new Map<number, TickerFunction>();\n\n private static interval: IntervalHandle | undefined;\n private static oneSecondTicksTracker: IntervalHandle | undefined;\n private static fiveSecondTicksTracker: IntervalHandle | undefined;\n\n private static oneSecondTps = 0;\n private static oneSecondTicks = 0;\n\n private static fiveSecondTps = 0;\n private static fiveSecondTicks = 0;\n\n private static schedule(fn: () => void, ms: number): IntervalHandle {\n const handle = setInterval(fn, ms);\n // Node's Timeout keeps the event loop alive unless unref'd; browsers return a plain number\n const unref = (handle as { unref?: () => void }).unref;\n if (typeof unref === \"function\") {\n unref.call(handle);\n }\n return handle;\n }\n\n /** Starts or resumes the shared tick loop. Repeated calls have no effect. */\n public static start(): void {\n if (this.interval) return;\n\n this.interval = this.schedule(() => {\n Ticker._tickers.forEach(t => {\n try {\n t();\n } catch (e) {\n log.warn(e);\n }\n });\n Ticker.oneSecondTicks++;\n Ticker.fiveSecondTicks++;\n }, 1000 / this.TPS);\n\n this.oneSecondTicksTracker = this.schedule(() => {\n Ticker.oneSecondTps = Ticker.oneSecondTicks;\n Ticker.oneSecondTicks = 0;\n }, 1000);\n\n this.fiveSecondTicksTracker = this.schedule(() => {\n Ticker.fiveSecondTps = Ticker.fiveSecondTicks / 5;\n Ticker.fiveSecondTicks = 0;\n }, 1000 * 5);\n }\n\n /** Pauses the loop while retaining callbacks for a later {@link start}. */\n public static stop(): void {\n if (this.interval) clearInterval(this.interval);\n if (this.oneSecondTicksTracker) clearInterval(this.oneSecondTicksTracker);\n if (this.fiveSecondTicksTracker) clearInterval(this.fiveSecondTicksTracker);\n this.interval = undefined;\n this.oneSecondTicksTracker = undefined;\n this.fiveSecondTicksTracker = undefined;\n }\n\n /** Registers a callback, starts the loop if needed, and returns an ID for {@link remove}. */\n public static add(tick: TickerFunction): number {\n this.start();\n const c = this.counter++;\n this._tickers.set(c, tick);\n return c;\n }\n\n /** Removes a callback by ID and stops the timers when no callbacks remain. */\n public static remove(c?: number) {\n // note: plain `if (c)` used to drop id 0, i.e. the very first registered ticker\n if (typeof c === \"number\") this._tickers.delete(c);\n if (!this._tickers.size) this.stop();\n }\n\n public static get tickers(): Map<number, TickerFunction> {\n return this._tickers;\n }\n\n public static get tpsOneSecond() {\n return this.oneSecondTps;\n }\n\n public static get tpsFiveSeconds() {\n return this.fiveSecondTps;\n }\n\n /** Stops the loop and removes all registered callbacks. */\n public static dispose() {\n this.stop();\n this._tickers.clear();\n }\n\n}\n"],"mappings":";AAAA,SAAS,cAAc;AAEvB,IAAM,MAAM,OAAO,QAAQ;AAepB,IAAM,UAAN,MAAM,QAAO;AAAA,EAiBhB,OAAe,SAAS,IAAgB,IAA4B;AAChE,UAAM,SAAS,YAAY,IAAI,EAAE;AAEjC,UAAM,QAAS,OAAkC;AACjD,QAAI,OAAO,UAAU,YAAY;AAC7B,YAAM,KAAK,MAAM;AAAA,IACrB;AACA,WAAO;AAAA,EACX;AAAA;AAAA,EAGA,OAAc,QAAc;AACxB,QAAI,KAAK,SAAU;AAEnB,SAAK,WAAW,KAAK,SAAS,MAAM;AAChC,cAAO,SAAS,QAAQ,OAAK;AACzB,YAAI;AACA,YAAE;AAAA,QACN,SAAS,GAAG;AACR,cAAI,KAAK,CAAC;AAAA,QACd;AAAA,MACJ,CAAC;AACD,cAAO;AACP,cAAO;AAAA,IACX,GAAG,MAAO,KAAK,GAAG;AAElB,SAAK,wBAAwB,KAAK,SAAS,MAAM;AAC7C,cAAO,eAAe,QAAO;AAC7B,cAAO,iBAAiB;AAAA,IAC5B,GAAG,GAAI;AAEP,SAAK,yBAAyB,KAAK,SAAS,MAAM;AAC9C,cAAO,gBAAgB,QAAO,kBAAkB;AAChD,cAAO,kBAAkB;AAAA,IAC7B,GAAG,MAAO,CAAC;AAAA,EACf;AAAA;AAAA,EAGA,OAAc,OAAa;AACvB,QAAI,KAAK,SAAU,eAAc,KAAK,QAAQ;AAC9C,QAAI,KAAK,sBAAuB,eAAc,KAAK,qBAAqB;AACxE,QAAI,KAAK,uBAAwB,eAAc,KAAK,sBAAsB;AAC1E,SAAK,WAAW;AAChB,SAAK,wBAAwB;AAC7B,SAAK,yBAAyB;AAAA,EAClC;AAAA;AAAA,EAGA,OAAc,IAAI,MAA8B;AAC5C,SAAK,MAAM;AACX,UAAM,IAAI,KAAK;AACf,SAAK,SAAS,IAAI,GAAG,IAAI;AACzB,WAAO;AAAA,EACX;AAAA;AAAA,EAGA,OAAc,OAAO,GAAY;AAE7B,QAAI,OAAO,MAAM,SAAU,MAAK,SAAS,OAAO,CAAC;AACjD,QAAI,CAAC,KAAK,SAAS,KAAM,MAAK,KAAK;AAAA,EACvC;AAAA,EAEA,WAAkB,UAAuC;AACrD,WAAO,KAAK;AAAA,EAChB;AAAA,EAEA,WAAkB,eAAe;AAC7B,WAAO,KAAK;AAAA,EAChB;AAAA,EAEA,WAAkB,iBAAiB;AAC/B,WAAO,KAAK;AAAA,EAChB;AAAA;AAAA,EAGA,OAAc,UAAU;AACpB,SAAK,KAAK;AACV,SAAK,SAAS,MAAM;AAAA,EACxB;AAEJ;AAjGa,QAEc,MAAM;AAFpB,QAIM,UAAkB;AAJxB,QAKe,WAAwC,oBAAI,IAA4B;AALvF,QAWM,eAAe;AAXrB,QAYM,iBAAiB;AAZvB,QAcM,gBAAgB;AAdtB,QAeM,kBAAkB;AAf9B,IAAM,SAAN;","names":[]}
@@ -9,9 +9,9 @@ import { Caching } from "./cache/Caching.mjs";
9
9
  import { Textures } from "./texture/Textures.mjs";
10
10
  import { AssetKey } from "./assets/AssetKey.mjs";
11
11
  import { ModelGenerator } from "./model/ModelGenerator.mjs";
12
- import { prefix } from "./util/log.mjs";
12
+ import { logger } from "./util/log.mjs";
13
13
  import { DEFAULT_UV, makeUv, makeUvCoords, setFaceUvInArray, setCubeFaceUvInArray, addCubeFaceUvToArray, facesToUvArray } from "./util/_internal/cubeUv.mjs";
14
- var p = prefix("UVMapper");
14
+ var log = logger("UVMapper");
15
15
  var X = 0;
16
16
  var Y = 1;
17
17
  var Z = 2;
@@ -244,7 +244,7 @@ var UVMapper = class {
244
244
  model.elements = originalModel.elements.map((element) => ({ ...element }));
245
245
  }
246
246
  const isItemModel = !("elements" in model);
247
- console.debug(p, "Creating Atlas for", model.key);
247
+ log.debug("Creating Atlas for", model.key);
248
248
  if (model.textures) {
249
249
  const promises = [];
250
250
  const uniqueTextureNames = [];
@@ -258,7 +258,7 @@ var UVMapper = class {
258
258
  const assetKey = AssetKey.parse("textures", textureValue, model.key);
259
259
  promises.push(ModelTextures.get(assetKey).then((asset) => {
260
260
  if (!asset) {
261
- console.warn(p, "Missing texture", assetKey);
261
+ log.warn("Missing texture", assetKey);
262
262
  return;
263
263
  }
264
264
  textureMap[textureKey] = new WrappedImage(asset);
@@ -270,7 +270,7 @@ var UVMapper = class {
270
270
  }
271
271
  await Promise.all(promises);
272
272
  const textureCount = uniqueTextureNames.length;
273
- console.debug(p, "Creating Atlas for", textureCount, "textures");
273
+ log.debug("Creating Atlas for", textureCount, "textures");
274
274
  this.fillMissingTextureKeys(model.textures, textureMap);
275
275
  this.fillMissingTextureKeys(model.textures, metaMap);
276
276
  const sizes = {};
@@ -301,7 +301,7 @@ var UVMapper = class {
301
301
  this.fillMissingTextureKeys(model.textures, sizes);
302
302
  const s = Math.ceil(Math.sqrt(textureCount + 1));
303
303
  const size = Math.ceil(s * maxWidth);
304
- console.debug(p, "Atlas size:", size);
304
+ log.debug("Atlas size:", size);
305
305
  const squaredSize = size * size;
306
306
  const image = new CanvasImage(size, size);
307
307
  const missing = Textures.getMissing().image;
@@ -380,7 +380,7 @@ var UVMapper = class {
380
380
  }
381
381
  this.fillMissingTextureKeys(model.textures, positions);
382
382
  if (isItemModel) {
383
- console.debug(p, "Generating item model for", model);
383
+ log.debug("Generating item model for", model);
384
384
  model.elements = [];
385
385
  for (let layerName of ModelGenerator.ITEM_LAYERS) {
386
386
  const textureImage = textureMap[layerName];
@@ -396,7 +396,7 @@ var UVMapper = class {
396
396
  ), layerName));
397
397
  }
398
398
  }
399
- console.debug(p, "Item model elements", model.elements);
399
+ log.debug("Item model elements", model.elements);
400
400
  }
401
401
  if (!model.elements) {
402
402
  }
@@ -453,7 +453,7 @@ var UVMapper = class {
453
453
  hasTranslucency
454
454
  );
455
455
  } else {
456
- console.warn(p, "Model does not have any textures", model);
456
+ log.warn("Model does not have any textures", model);
457
457
  }
458
458
  return void 0;
459
459
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/UVMapper.ts"],"sourcesContent":["import { BoxGeometry, BufferAttribute, Euler, Float32BufferAttribute, Vector2, Vector3, Vector4 } from \"three\";\nimport { DoubleArray, Model, QuadArray, TextureAsset } from \"./model/Model\";\nimport { ModelElement, ModelFaces } from \"./model/ModelElement\";\nimport { CUBE_FACES, CubeFace } from \"./CubeFace\";\nimport { ModelTextures } from \"./assets/ModelTextures\";\nimport { Assets } from \"./assets/Assets\";\nimport { Maybe, toRadians } from \"./util/util\";\nimport { WrappedImage } from \"./WrappedImage\";\nimport { CanvasImage } from \"./canvas/CanvasImage\";\nimport { TextureAtlas } from \"./texture/TextureAtlas\";\nimport { Caching } from \"./cache/Caching\";\nimport { Textures } from \"./texture/Textures\";\nimport { AnimatorFunction } from \"./AnimatorFunction\";\nimport { MinecraftTextureMeta } from \"./MinecraftTextureMeta\";\nimport { AssetKey } from \"./assets/AssetKey\";\nimport { ModelGenerator } from \"./model/ModelGenerator\";\nimport { prefix } from \"./util/log\";\nimport { DEFAULT_UV, makeUv, makeUvCoords, setFaceUvInArray, setCubeFaceUvInArray, addCubeFaceUvToArray, facesToUvArray } from \"./util/_internal/cubeUv\";\n\nconst p = prefix(\"UVMapper\");\n\nexport { DEFAULT_UV };\nconst X = 0;\nconst Y = 1;\nconst Z = 2;\n\n// Each face's right/down axes in Minecraft's top-origin UV coordinates.\nconst FACE_UV_AXES: Record<CubeFace, [Vector3, Vector3]> = {\n east: [new Vector3(0, 0, -1), new Vector3(0, -1, 0)],\n west: [new Vector3(0, 0, 1), new Vector3(0, -1, 0)],\n up: [new Vector3(1, 0, 0), new Vector3(0, 0, 1)],\n down: [new Vector3(1, 0, 0), new Vector3(0, 0, -1)],\n south: [new Vector3(1, 0, 0), new Vector3(0, -1, 0)],\n north: [new Vector3(-1, 0, 0), new Vector3(0, -1, 0)]\n};\n\n/*\n * - Minecraft Block UVs are from the top-left to bottom-right\n * - three.js UVs are from the bottom-left to top-right\n * - canvas coordinates are from the top-left to bottom-right\n */\n\n// noinspection PointlessArithmeticExpressionJS\n/** Maps Minecraft face coordinates to Three.js UVs and builds per-model texture atlases. */\nexport class UVMapper {\n\n protected static makeUv(uvCoord: number, originalTextureSize: number, actualTextureSize: number): number {\n return makeUv(uvCoord, originalTextureSize, actualTextureSize);\n }\n\n protected static makeUvCoords([originalTextureWidth, originalTextureHeight]: DoubleArray, [actualTextureWidth, actualTextureHeight]: DoubleArray, [x1, y1, x2, y2]: QuadArray): QuadArray {\n return makeUvCoords([originalTextureWidth, originalTextureHeight], [actualTextureWidth, actualTextureHeight], [x1, y1, x2, y2]);\n }\n\n\n public static rotateSingleUv([u, v]: DoubleArray, [px, py]: DoubleArray, radians: number): DoubleArray {\n const sin = Math.sin(radians);\n const cos = Math.cos(radians);\n\n u -= px;\n v -= py;\n\n const uc = u;\n const vc = v;\n\n u = cos * uc - sin * vc;\n v = cos * vc + sin * uc;\n\n u += px;\n v += py;\n\n // return [parseFloat(u.toFixed(8)), parseFloat(v.toFixed(8))];\n return [u, v];\n }\n\n public static addCubeFaceUvToArray(array: number[], faceIndex: number, originalTextureSize: DoubleArray, actualTextureSize: DoubleArray, originalCoords: QuadArray) {\n return addCubeFaceUvToArray(array, faceIndex, originalTextureSize, actualTextureSize, originalCoords);\n }\n\n public static setCubeFaceUvInArray(array: number[], faceIndex: number, [u1, v1, u2, v2]: QuadArray) {\n return setCubeFaceUvInArray(array, faceIndex, [u1, v1, u2, v2]);\n }\n\n public static setFaceUvInArrayV(array: number[], faceIndex: number, uvs: QuadArray<Vector2>) {\n array[((faceIndex + 0) * 2) + 0] = uvs[0].x;\n array[((faceIndex + 0) * 2) + 1] = uvs[0].y;\n\n array[((faceIndex + 1) * 2) + 0] = uvs[1].x;\n array[((faceIndex + 1) * 2) + 1] = uvs[1].y;\n\n array[((faceIndex + 2) * 2) + 0] = uvs[2].x;\n array[((faceIndex + 2) * 2) + 1] = uvs[2].y;\n\n array[((faceIndex + 3) * 2) + 0] = uvs[3].x;\n array[((faceIndex + 3) * 2) + 1] = uvs[3].y;\n }\n\n public static setFaceUvInArray(array: number[], faceIndex: number, uvs: QuadArray<DoubleArray>) {\n return setFaceUvInArray(array, faceIndex, uvs);\n }\n\n public static setCubeFaceUvAttribute(attributes: BufferAttribute, faceIndex: number, originalTextureSize: DoubleArray, actualTextureSize: DoubleArray, originalCoords: QuadArray): void {\n const uv = this.makeUvCoords(originalTextureSize, actualTextureSize, originalCoords);\n this.setCubeFaceUvInAttribute(attributes, faceIndex, uv);\n }\n\n public static setCubeFaceUvInAttribute(attributes: BufferAttribute, faceIndex: number, [u1, v1, u2, v2]: QuadArray) {\n attributes.setXY(faceIndex + 0, u1, v1);\n attributes.setXY(faceIndex + 1, u2, v1);\n attributes.setXY(faceIndex + 2, u1, v2);\n attributes.setXY(faceIndex + 3, u2, v2);\n }\n\n public static setCubeUvs(geometry: BoxGeometry, originalTextureSize: DoubleArray, actualTextureSize: DoubleArray, faces: ModelFaces): void {\n const attributes = geometry.getAttribute(\"uv\") as BufferAttribute;\n for (let faceIndex = 0; faceIndex < CUBE_FACES.length; faceIndex++) {\n let faceName = CUBE_FACES[faceIndex];\n let face = faces[faceName];\n if (!face) continue;\n if (!face.uv) {\n face.uv = DEFAULT_UV;\n }\n\n this.setCubeFaceUvAttribute(attributes, faceIndex * 4, originalTextureSize, actualTextureSize, face.uv);\n }\n }\n\n public static facesToUvArray(faces: ModelFaces, originalTextureSize: DoubleArray, actualTextureSize: DoubleArray): number[] {\n return facesToUvArray(faces, originalTextureSize, actualTextureSize);\n }\n\n public static facesToUv(faces: ModelFaces, originalTextureSize: DoubleArray, actualTextureSize: DoubleArray): Float32BufferAttribute {\n return new Float32BufferAttribute(this.facesToUvArray(faces, originalTextureSize, actualTextureSize), 2);\n }\n\n /** Bounds texture sampling to texel centres without changing cropped face UVs. */\n public static setAtlasUvBounds(geometry: BoxGeometry, faces: ModelFaces, atlas: TextureAtlas): void {\n const uv = geometry.getAttribute(\"uv\");\n const bounds = new Float32Array(uv.count * 4);\n for (const [faceIndex, faceName] of CUBE_FACES.entries()) {\n const texture = faces[faceName]?.texture?.substring(1);\n const position = texture && atlas.positions[texture];\n const size = texture && atlas.sizes[texture];\n let minU = Infinity, minV = Infinity, maxU = -Infinity, maxV = -Infinity;\n if (position && size) {\n minU = position[0] / atlas.image.width;\n maxU = (position[0] + size[0]) / atlas.image.width;\n minV = 1 - (position[1] + size[1]) / atlas.image.height;\n maxV = 1 - position[1] / atlas.image.height;\n } else {\n for (let corner = 0; corner < 4; corner++) {\n const index = faceIndex * 4 + corner;\n minU = Math.min(minU, uv.getX(index));\n minV = Math.min(minV, uv.getY(index));\n maxU = Math.max(maxU, uv.getX(index));\n maxV = Math.max(maxV, uv.getY(index));\n }\n }\n const insetU = Math.min(0.5 / atlas.image.width, (maxU - minU) / 2);\n const insetV = Math.min(0.5 / atlas.image.height, (maxV - minV) / 2);\n for (let corner = 0; corner < 4; corner++) {\n bounds.set([minU + insetU, minV + insetV, maxU - insetU, maxV - insetV], (faceIndex * 4 + corner) * 4);\n }\n }\n geometry.setAttribute(\"uvBounds\", new Float32BufferAttribute(bounds, 4));\n }\n\n public static lockUvs(geometry: BoxGeometry, faces: ModelFaces, atlas: TextureAtlas, rotation: Euler): void {\n const uv = geometry.getAttribute(\"uv\") as BufferAttribute;\n for (let faceIndex = 0; faceIndex < CUBE_FACES.length; faceIndex++) {\n const faceName = CUBE_FACES[faceIndex];\n const texture = faces[faceName]?.texture?.substring(1);\n const position = texture && atlas.positions[texture];\n const size = texture && atlas.sizes[texture];\n if (!position || !size) continue;\n\n const [sourceU, sourceV] = FACE_UV_AXES[faceName];\n const uAxis = sourceU.clone().applyEuler(rotation);\n const vAxis = sourceV.clone().applyEuler(rotation);\n const normal = vAxis.clone().cross(uAxis);\n const targetFace = CUBE_FACES.find(name => {\n const [u, v] = FACE_UV_AXES[name];\n return v.clone().cross(u).dot(normal) > 0.5;\n })!;\n const [targetU, targetV] = FACE_UV_AXES[targetFace];\n const uu = Math.round(targetU.dot(uAxis));\n const uvCross = Math.round(targetU.dot(vAxis));\n const vu = Math.round(targetV.dot(uAxis));\n const vv = Math.round(targetV.dot(vAxis));\n\n // Rotate about the full texture center, not the cropped face or atlas center.\n for (let corner = 0; corner < 4; corner++) {\n const index = faceIndex * 4 + corner;\n const u = (uv.getX(index) * atlas.image.width - position[0]) / size[0] - 0.5;\n const v = ((1 - uv.getY(index)) * atlas.image.height - position[1]) / size[1] - 0.5;\n const lockedU = uu * u + uvCross * v + 0.5;\n const lockedV = vu * u + vv * v + 0.5;\n uv.setXY(index,\n (position[0] + lockedU * size[0]) / atlas.image.width,\n 1 - (position[1] + lockedV * size[1]) / atlas.image.height);\n }\n }\n uv.needsUpdate = true;\n }\n\n /** Returns the shared atlas for a keyed, merged model, creating it on first use. */\n public static async getAtlas(model: Model): Promise<Maybe<TextureAtlas>> {\n const keyStr = model.key!.serialize();\n return Caching.modelTextureAtlasCache.get(keyStr, k => {\n return this.createAtlas(model);\n })\n }\n\n public static fillMissingTextureKeys<T>(textures: ModelTextures, target: { [k: string]: T }): { [k: string]: T } {\n for (const key in textures) {\n // Follow references such as \"#all\" -> \"#texture\" to the variable that names a texture.\n let name = key;\n const seen = new Set<string>();\n while (textures[name]?.startsWith(\"#\") && !seen.has(name)) {\n seen.add(name);\n name = textures[name].substr(1);\n }\n if (name !== key) target[key] = target[name];\n }\n return target;\n }\n\n // https://yeleha.co/3qlboGS\n protected static getFallbackUv(element: ModelElement, faceName: CubeFace): QuadArray {\n switch (faceName) {\n case CubeFace.DOWN:\n return [element.from[X], 16 - element.to[Z], element.to[X], 16 - element.from[Z]];\n case CubeFace.UP:\n return [element.from[X], element.from[Z], element.to[X], element.to[Z]];\n case CubeFace.NORTH:\n default:\n return [16 - element.to[X], 16 - element.to[Y], 16 - element.from[X], 16 - element.from[Y]];\n case CubeFace.SOUTH:\n return [element.from[X], 16 - element.to[Y], element.to[X], 16 - element.from[Y]];\n case CubeFace.WEST:\n return [element.from[Z], 16 - element.to[Y], element.to[Z], 16 - element.from[Y]];\n case CubeFace.EAST:\n return [16 - element.to[Z], 16 - element.to[Y], 16 - element.from[Z], 16 - element.from[Y]];\n }\n }\n\n protected static expandAndRotateMcUvs([u1, v1, u2, v2]: QuadArray, rotation: number = 0, actualWidth: number, actualHeight: number): QuadArray<Vector2> {\n // Resize coordinates to actual texture size\n const scaleU = actualWidth / 16;\n const scaleV = actualHeight / 16;\n u1 *= scaleU;\n v1 *= scaleV;\n u2 *= scaleU;\n v2 *= scaleV;\n\n let tl: Vector2 = new Vector2(u1, v1);// top left\n let tr: Vector2 = new Vector2(u2, v1);// top right\n let bl: Vector2 = new Vector2(u1, v2);// bottom left\n let br: Vector2 = new Vector2(u2, v2);// bottom right\n\n switch (rotation) {\n case 0:\n case 360:\n default:\n break;\n case 90:\n tl = new Vector2(u1, v2);\n tr = new Vector2(u1, v1);\n bl = new Vector2(u2, v2);\n br = new Vector2(u2, v1);\n break;\n case 180:\n tl = new Vector2(u2, v2);\n tr = new Vector2(u1, v2);\n bl = new Vector2(u2, v1);\n br = new Vector2(u1, v1);\n break;\n case 270:\n tl = new Vector2(u2, v1);\n tr = new Vector2(u2, v2);\n bl = new Vector2(u1, v1);\n br = new Vector2(u1, v2);\n break;\n }\n\n return [tl, tr, bl, br];\n }\n\n /**\n * Combines model textures and animation metadata into an atlas.\n * Mapped UVs are stored on copies of the model's elements, available through the returned atlas.\n * Returns `undefined` for models without a texture map.\n */\n public static async createAtlas(originalModel: Model): Promise<Maybe<TextureAtlas>> {\n const textureMap: { [key: string]: Maybe<WrappedImage>; } = {};\n const metaMap: { [key: string]: Maybe<MinecraftTextureMeta>; } = {};\n const model = {...originalModel};\n // Merged models share element objects with their cached parents (cube, cube_all, ...), so the\n // baked UVs below must go onto this atlas's own copies, not onto objects other atlases read.\n if (originalModel.elements) {\n model.elements = originalModel.elements.map(element => ({ ...element }));\n }\n const isItemModel = !(\"elements\" in model);\n\n console.debug(p, \"Creating Atlas for\", model.key);\n\n if (model.textures) {\n const promises: Promise<void>[] = [];\n const uniqueTextureNames: string[] = []; // TODO: make these actually unique\n const textureReferences: { [k: string]: string; } = {};\n for (let textureKey in model.textures) {\n let textureValue = model.textures[textureKey];\n if (textureValue.startsWith(\"#\")) {\n textureReferences[textureKey] = textureValue.substr(1);\n } else {\n uniqueTextureNames.push(textureKey);\n const assetKey = AssetKey.parse(\"textures\", textureValue, model.key);\n promises.push(ModelTextures.get(assetKey).then(asset => {\n if (!asset) {\n console.warn(p, \"Missing texture\", assetKey)\n return;\n }\n textureMap[textureKey] = new WrappedImage(asset);\n }));\n promises.push(ModelTextures.getMeta(assetKey).then(meta => {\n metaMap[textureKey] = meta;\n }))\n }\n }\n await Promise.all(promises);\n const textureCount = uniqueTextureNames.length;\n console.debug(p, \"Creating Atlas for\", textureCount, \"textures\");\n // console.log(model.textures)\n\n this.fillMissingTextureKeys(model.textures, textureMap);\n this.fillMissingTextureKeys(model.textures, metaMap);\n\n const sizes: { [texture: string]: DoubleArray; } = {};\n const frames: { [texture: string]: { index: number; time: number }[] } = {};\n\n // Find largest texture dimensions\n let maxWidth = 0;\n for (let textureKey of uniqueTextureNames) {\n let texture = textureMap[textureKey];\n if (!texture) continue;\n const animation = metaMap[textureKey]?.animation;\n let width = texture.width, height = texture.height;\n if (animation) {\n const square = Math.min(width, height);\n width = animation.width ?? (animation.height === undefined ? square : width);\n height = animation.height ?? (animation.width === undefined ? square : height);\n if (!Number.isInteger(width) || !Number.isInteger(height) || width <= 0 || height <= 0\n || texture.width % width || texture.height % height) {\n throw new RangeError(`Invalid animation frame dimensions for ${textureKey}`);\n }\n const count = (texture.width / width) * (texture.height / height);\n const time = animation.frametime ?? 1;\n frames[textureKey] = (animation.frames ?? Array.from({ length: count }, (_, index) => index))\n .map(frame => typeof frame === \"number\" ? { index: frame, time } : { index: frame.index, time: frame.time ?? time });\n if (!frames[textureKey].length || frames[textureKey].some(frame => !Number.isInteger(frame.index)\n || frame.index < 0 || frame.index >= count || !Number.isInteger(frame.time) || frame.time < 1)) {\n throw new RangeError(`Invalid animation frames for ${textureKey}`);\n }\n }\n sizes[textureKey] = [width, height];\n maxWidth = Math.max(maxWidth, width, height);\n }\n this.fillMissingTextureKeys(model.textures, sizes);\n\n // console.log(\"sizes\", sizes);\n\n const s = (Math.ceil(Math.sqrt(textureCount + 1))); // +1 for transparency\n const size = Math.ceil(s * maxWidth)\n console.debug(p, \"Atlas size:\", size);\n // console.log(\"size: \" + size);\n const squaredSize = size * size;\n\n const image = new CanvasImage(size, size);\n const missing = Textures.getMissing().image;\n const missingPixels = image.context.createImageData(missing.width, missing.height);\n missingPixels.data.set(missing.data!);\n image.putData(missingPixels, 0, 0);\n // The top-left atlas cell keeps absent model faces transparent.\n image.context.clearRect(0, 0, maxWidth, maxWidth);\n\n const positions: { [texture: string]: DoubleArray; } = {};\n\n let hasTransparency = false;\n let hasTranslucency = false;\n\n let hasAnimation = false;\n const animatorFunctions: { [texture: string]: AnimatorFunction; } = {};\n\n // Draw all textures onto a single image\n let tx = 1; // start one over to leave room for the transparent space\n let ty = 0;\n for (let textureIndex = 0; textureIndex < uniqueTextureNames.length; textureIndex++) {\n let textureKey = uniqueTextureNames[textureIndex];\n let texture = textureMap[textureKey];\n let x = tx * maxWidth;\n let y = ty * maxWidth;\n if (texture) {\n positions[textureKey] = [x, y];\n const [width, height] = sizes[textureKey];\n const sequence = frames[textureKey];\n const getFrameData = (index: number) => {\n const columns = texture!.width / width;\n return texture!.getSectionData((index % columns) * width,\n Math.floor(index / columns) * height, width, height);\n };\n const firstFrame = getFrameData(sequence?.[0].index ?? 0);\n image.putData(firstFrame, x, y);\n\n if (texture.hasTransparency) {\n hasTransparency = true;\n }\n if (texture.hasTranslucency) {\n hasTranslucency = true;\n }\n\n if (sequence && sequence.some(frame => frame.index !== sequence[0].index)) {\n hasAnimation = true;\n let t = 0;\n let f = 0;\n const interpolated = metaMap[textureKey]?.animation?.interpolate\n ? image.context.createImageData(width, height) : undefined;\n let currentFrame = firstFrame;\n let nextFrame = interpolated ? getFrameData(sequence[1].index) : firstFrame;\n\n animatorFunctions[textureKey] = () => {\n if (++t >= sequence[f].time) {\n t = 0;\n const previous = sequence[f].index;\n f = (f + 1) % sequence.length;\n if (interpolated) {\n currentFrame = nextFrame;\n nextFrame = getFrameData(sequence[(f + 1) % sequence.length].index);\n }\n if (sequence[f].index === previous) return false;\n image.putData(interpolated ? currentFrame : getFrameData(sequence[f].index), x, y);\n return true;\n }\n if (!interpolated || sequence[f].index === sequence[(f + 1) % sequence.length].index) return false;\n // Vanilla encodes the atlas shader's interpolation progress in thousandths.\n const progress = Math.floor(Math.fround(Math.fround(t / sequence[f].time) * 1000)) / 1000;\n for (let i = 0; i < interpolated.data.length; i++) {\n interpolated.data[i] = currentFrame.data[i] + (nextFrame.data[i] - currentFrame.data[i]) * progress;\n }\n image.putData(interpolated, x, y);\n return true;\n };\n }\n }\n tx++;\n if (tx >= s) {\n tx = 0;\n ty++;\n }\n }\n this.fillMissingTextureKeys(model.textures, positions);\n\n // console.log(\"positions\", positions);\n\n if (isItemModel) {\n console.debug(p, \"Generating item model for\", model);\n model.elements = [];\n for (let layerName of ModelGenerator.ITEM_LAYERS) {\n const textureImage = textureMap[layerName];\n if (textureImage) {\n // Outline the frame that was drawn into the atlas, not the whole animation strip.\n const [width, height] = sizes[layerName];\n const frame = frames[layerName]?.[0].index ?? 0;\n const columns = textureImage.width / width;\n model.elements.push(...ModelGenerator.generateItemModel(textureImage.getSectionData(\n (frame % columns) * width, Math.floor(frame / columns) * height, width, height), layerName))\n }\n }\n console.debug(p, \"Item model elements\", model.elements)\n }\n\n if (!model.elements) {\n //TODO: default elements\n }\n\n // Adjust UV positions\n if (model.elements) {\n for (let elementIndex = 0; elementIndex < model.elements.length; elementIndex++) {\n let element = model.elements[elementIndex];\n let uv: number[] = [];\n // Set default uvs to missing texture\n for (let i = 0; i < CUBE_FACES.length; i++) {\n this.setCubeFaceUvInArray(uv, i * 4, [0, 0, 8 / size, 8 / size])\n }\n for (let faceIndex = 0; faceIndex < CUBE_FACES.length; faceIndex++) {\n let faceName = CUBE_FACES[faceIndex];\n // console.log(faceName)\n let face = element.faces[faceName];\n if (!face) {\n // set uv transparent\n this.setCubeFaceUvInArray(uv, faceIndex * 4, [0, 1, 8 / size, (size - 8) / size])\n continue;\n }\n // Keep the missing-texture UVs when no texture is referenced.\n if (!face.texture) continue;\n if (!face.uv) {\n face.uv = this.getFallbackUv(element, faceName);\n }\n\n const faceTexture = face.texture.substr(1); // remove #\n const texPosition = positions[faceTexture] || [0, 0];\n const texSize = sizes[faceTexture] || [16, 16];\n\n let texPosV = new Vector2(texPosition[0], texPosition[1]);\n\n const [tl, tr, bl, br] = this.expandAndRotateMcUvs(face.uv, face.rotation, texSize[0], texSize[1]);\n\n // move to atlas position\n tl.add(texPosV);\n tr.add(texPosV);\n bl.add(texPosV);\n br.add(texPosV);\n\n // divide to 0-1\n tl.divideScalar(size);\n tr.divideScalar(size);\n bl.divideScalar(size);\n br.divideScalar(size);\n\n // flip y coordinates\n tl.y = 1 - tl.y;\n tr.y = 1 - tr.y;\n bl.y = 1 - bl.y;\n br.y = 1 - br.y;\n\n let uvs: QuadArray<Vector2> = [tl, tr, bl, br];\n // console.log(\"uvs\", uvs);\n this.setFaceUvInArrayV(uv, faceIndex * 4, uvs);\n }\n\n element.mappedUv = uv;\n }\n } else {\n //TODO: item model\n }\n\n return new TextureAtlas(\n model,\n image,\n sizes,\n positions,\n hasAnimation,\n animatorFunctions,\n hasTransparency,\n hasTranslucency\n );\n } else {\n console.warn(p, \"Model does not have any textures\", model);\n }\n return undefined;\n }\n\n}\n\n// Based on net.minecraft.client.renderer.block.model.BlockFaceUV\n/** Stores a Minecraft face's UV rectangle and its rotation in degrees. */\nexport class MinecraftFaceUV {\n\n constructor(readonly uv: QuadArray = [0, 0, 16, 16], readonly rotation: number = 0) {\n }\n\n getU(index: number): number {\n const shiftedIndex = this.getShiftedIndex(index);\n return this.uv[shiftedIndex !== 0 && index !== 1 ? 2 : 0];\n }\n\n getV(index: number): number {\n const shiftedIndex = this.getShiftedIndex(index);\n return this.uv[shiftedIndex !== 0 && index !== 3 ? 3 : 1];\n }\n\n protected getShiftedIndex(index: number): number {\n return (index + this.rotation / 90) % 40;\n }\n\n protected getReverseIndex(index: number): number {\n return (index + 4 - this.rotation / 90) % 4;\n }\n\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../src/UVMapper.ts"],"sourcesContent":["import { BoxGeometry, BufferAttribute, Euler, Float32BufferAttribute, Vector2, Vector3, Vector4 } from \"three\";\nimport { DoubleArray, Model, QuadArray, TextureAsset } from \"./model/Model\";\nimport { ModelElement, ModelFaces } from \"./model/ModelElement\";\nimport { CUBE_FACES, CubeFace } from \"./CubeFace\";\nimport { ModelTextures } from \"./assets/ModelTextures\";\nimport { Assets } from \"./assets/Assets\";\nimport { Maybe, toRadians } from \"./util/util\";\nimport { WrappedImage } from \"./WrappedImage\";\nimport { CanvasImage } from \"./canvas/CanvasImage\";\nimport { TextureAtlas } from \"./texture/TextureAtlas\";\nimport { Caching } from \"./cache/Caching\";\nimport { Textures } from \"./texture/Textures\";\nimport { AnimatorFunction } from \"./AnimatorFunction\";\nimport { MinecraftTextureMeta } from \"./MinecraftTextureMeta\";\nimport { AssetKey } from \"./assets/AssetKey\";\nimport { ModelGenerator } from \"./model/ModelGenerator\";\nimport { logger } from \"./util/log\";\nimport { DEFAULT_UV, makeUv, makeUvCoords, setFaceUvInArray, setCubeFaceUvInArray, addCubeFaceUvToArray, facesToUvArray } from \"./util/_internal/cubeUv\";\n\nconst log = logger(\"UVMapper\");\n\nexport { DEFAULT_UV };\nconst X = 0;\nconst Y = 1;\nconst Z = 2;\n\n// Each face's right/down axes in Minecraft's top-origin UV coordinates.\nconst FACE_UV_AXES: Record<CubeFace, [Vector3, Vector3]> = {\n east: [new Vector3(0, 0, -1), new Vector3(0, -1, 0)],\n west: [new Vector3(0, 0, 1), new Vector3(0, -1, 0)],\n up: [new Vector3(1, 0, 0), new Vector3(0, 0, 1)],\n down: [new Vector3(1, 0, 0), new Vector3(0, 0, -1)],\n south: [new Vector3(1, 0, 0), new Vector3(0, -1, 0)],\n north: [new Vector3(-1, 0, 0), new Vector3(0, -1, 0)]\n};\n\n/*\n * - Minecraft Block UVs are from the top-left to bottom-right\n * - three.js UVs are from the bottom-left to top-right\n * - canvas coordinates are from the top-left to bottom-right\n */\n\n// noinspection PointlessArithmeticExpressionJS\n/** Maps Minecraft face coordinates to Three.js UVs and builds per-model texture atlases. */\nexport class UVMapper {\n\n protected static makeUv(uvCoord: number, originalTextureSize: number, actualTextureSize: number): number {\n return makeUv(uvCoord, originalTextureSize, actualTextureSize);\n }\n\n protected static makeUvCoords([originalTextureWidth, originalTextureHeight]: DoubleArray, [actualTextureWidth, actualTextureHeight]: DoubleArray, [x1, y1, x2, y2]: QuadArray): QuadArray {\n return makeUvCoords([originalTextureWidth, originalTextureHeight], [actualTextureWidth, actualTextureHeight], [x1, y1, x2, y2]);\n }\n\n\n public static rotateSingleUv([u, v]: DoubleArray, [px, py]: DoubleArray, radians: number): DoubleArray {\n const sin = Math.sin(radians);\n const cos = Math.cos(radians);\n\n u -= px;\n v -= py;\n\n const uc = u;\n const vc = v;\n\n u = cos * uc - sin * vc;\n v = cos * vc + sin * uc;\n\n u += px;\n v += py;\n\n // return [parseFloat(u.toFixed(8)), parseFloat(v.toFixed(8))];\n return [u, v];\n }\n\n public static addCubeFaceUvToArray(array: number[], faceIndex: number, originalTextureSize: DoubleArray, actualTextureSize: DoubleArray, originalCoords: QuadArray) {\n return addCubeFaceUvToArray(array, faceIndex, originalTextureSize, actualTextureSize, originalCoords);\n }\n\n public static setCubeFaceUvInArray(array: number[], faceIndex: number, [u1, v1, u2, v2]: QuadArray) {\n return setCubeFaceUvInArray(array, faceIndex, [u1, v1, u2, v2]);\n }\n\n public static setFaceUvInArrayV(array: number[], faceIndex: number, uvs: QuadArray<Vector2>) {\n array[((faceIndex + 0) * 2) + 0] = uvs[0].x;\n array[((faceIndex + 0) * 2) + 1] = uvs[0].y;\n\n array[((faceIndex + 1) * 2) + 0] = uvs[1].x;\n array[((faceIndex + 1) * 2) + 1] = uvs[1].y;\n\n array[((faceIndex + 2) * 2) + 0] = uvs[2].x;\n array[((faceIndex + 2) * 2) + 1] = uvs[2].y;\n\n array[((faceIndex + 3) * 2) + 0] = uvs[3].x;\n array[((faceIndex + 3) * 2) + 1] = uvs[3].y;\n }\n\n public static setFaceUvInArray(array: number[], faceIndex: number, uvs: QuadArray<DoubleArray>) {\n return setFaceUvInArray(array, faceIndex, uvs);\n }\n\n public static setCubeFaceUvAttribute(attributes: BufferAttribute, faceIndex: number, originalTextureSize: DoubleArray, actualTextureSize: DoubleArray, originalCoords: QuadArray): void {\n const uv = this.makeUvCoords(originalTextureSize, actualTextureSize, originalCoords);\n this.setCubeFaceUvInAttribute(attributes, faceIndex, uv);\n }\n\n public static setCubeFaceUvInAttribute(attributes: BufferAttribute, faceIndex: number, [u1, v1, u2, v2]: QuadArray) {\n attributes.setXY(faceIndex + 0, u1, v1);\n attributes.setXY(faceIndex + 1, u2, v1);\n attributes.setXY(faceIndex + 2, u1, v2);\n attributes.setXY(faceIndex + 3, u2, v2);\n }\n\n public static setCubeUvs(geometry: BoxGeometry, originalTextureSize: DoubleArray, actualTextureSize: DoubleArray, faces: ModelFaces): void {\n const attributes = geometry.getAttribute(\"uv\") as BufferAttribute;\n for (let faceIndex = 0; faceIndex < CUBE_FACES.length; faceIndex++) {\n let faceName = CUBE_FACES[faceIndex];\n let face = faces[faceName];\n if (!face) continue;\n if (!face.uv) {\n face.uv = DEFAULT_UV;\n }\n\n this.setCubeFaceUvAttribute(attributes, faceIndex * 4, originalTextureSize, actualTextureSize, face.uv);\n }\n }\n\n public static facesToUvArray(faces: ModelFaces, originalTextureSize: DoubleArray, actualTextureSize: DoubleArray): number[] {\n return facesToUvArray(faces, originalTextureSize, actualTextureSize);\n }\n\n public static facesToUv(faces: ModelFaces, originalTextureSize: DoubleArray, actualTextureSize: DoubleArray): Float32BufferAttribute {\n return new Float32BufferAttribute(this.facesToUvArray(faces, originalTextureSize, actualTextureSize), 2);\n }\n\n /** Bounds texture sampling to texel centres without changing cropped face UVs. */\n public static setAtlasUvBounds(geometry: BoxGeometry, faces: ModelFaces, atlas: TextureAtlas): void {\n const uv = geometry.getAttribute(\"uv\");\n const bounds = new Float32Array(uv.count * 4);\n for (const [faceIndex, faceName] of CUBE_FACES.entries()) {\n const texture = faces[faceName]?.texture?.substring(1);\n const position = texture && atlas.positions[texture];\n const size = texture && atlas.sizes[texture];\n let minU = Infinity, minV = Infinity, maxU = -Infinity, maxV = -Infinity;\n if (position && size) {\n minU = position[0] / atlas.image.width;\n maxU = (position[0] + size[0]) / atlas.image.width;\n minV = 1 - (position[1] + size[1]) / atlas.image.height;\n maxV = 1 - position[1] / atlas.image.height;\n } else {\n for (let corner = 0; corner < 4; corner++) {\n const index = faceIndex * 4 + corner;\n minU = Math.min(minU, uv.getX(index));\n minV = Math.min(minV, uv.getY(index));\n maxU = Math.max(maxU, uv.getX(index));\n maxV = Math.max(maxV, uv.getY(index));\n }\n }\n const insetU = Math.min(0.5 / atlas.image.width, (maxU - minU) / 2);\n const insetV = Math.min(0.5 / atlas.image.height, (maxV - minV) / 2);\n for (let corner = 0; corner < 4; corner++) {\n bounds.set([minU + insetU, minV + insetV, maxU - insetU, maxV - insetV], (faceIndex * 4 + corner) * 4);\n }\n }\n geometry.setAttribute(\"uvBounds\", new Float32BufferAttribute(bounds, 4));\n }\n\n public static lockUvs(geometry: BoxGeometry, faces: ModelFaces, atlas: TextureAtlas, rotation: Euler): void {\n const uv = geometry.getAttribute(\"uv\") as BufferAttribute;\n for (let faceIndex = 0; faceIndex < CUBE_FACES.length; faceIndex++) {\n const faceName = CUBE_FACES[faceIndex];\n const texture = faces[faceName]?.texture?.substring(1);\n const position = texture && atlas.positions[texture];\n const size = texture && atlas.sizes[texture];\n if (!position || !size) continue;\n\n const [sourceU, sourceV] = FACE_UV_AXES[faceName];\n const uAxis = sourceU.clone().applyEuler(rotation);\n const vAxis = sourceV.clone().applyEuler(rotation);\n const normal = vAxis.clone().cross(uAxis);\n const targetFace = CUBE_FACES.find(name => {\n const [u, v] = FACE_UV_AXES[name];\n return v.clone().cross(u).dot(normal) > 0.5;\n })!;\n const [targetU, targetV] = FACE_UV_AXES[targetFace];\n const uu = Math.round(targetU.dot(uAxis));\n const uvCross = Math.round(targetU.dot(vAxis));\n const vu = Math.round(targetV.dot(uAxis));\n const vv = Math.round(targetV.dot(vAxis));\n\n // Rotate about the full texture center, not the cropped face or atlas center.\n for (let corner = 0; corner < 4; corner++) {\n const index = faceIndex * 4 + corner;\n const u = (uv.getX(index) * atlas.image.width - position[0]) / size[0] - 0.5;\n const v = ((1 - uv.getY(index)) * atlas.image.height - position[1]) / size[1] - 0.5;\n const lockedU = uu * u + uvCross * v + 0.5;\n const lockedV = vu * u + vv * v + 0.5;\n uv.setXY(index,\n (position[0] + lockedU * size[0]) / atlas.image.width,\n 1 - (position[1] + lockedV * size[1]) / atlas.image.height);\n }\n }\n uv.needsUpdate = true;\n }\n\n /** Returns the shared atlas for a keyed, merged model, creating it on first use. */\n public static async getAtlas(model: Model): Promise<Maybe<TextureAtlas>> {\n const keyStr = model.key!.serialize();\n return Caching.modelTextureAtlasCache.get(keyStr, k => {\n return this.createAtlas(model);\n })\n }\n\n public static fillMissingTextureKeys<T>(textures: ModelTextures, target: { [k: string]: T }): { [k: string]: T } {\n for (const key in textures) {\n // Follow references such as \"#all\" -> \"#texture\" to the variable that names a texture.\n let name = key;\n const seen = new Set<string>();\n while (textures[name]?.startsWith(\"#\") && !seen.has(name)) {\n seen.add(name);\n name = textures[name].substr(1);\n }\n if (name !== key) target[key] = target[name];\n }\n return target;\n }\n\n // https://yeleha.co/3qlboGS\n protected static getFallbackUv(element: ModelElement, faceName: CubeFace): QuadArray {\n switch (faceName) {\n case CubeFace.DOWN:\n return [element.from[X], 16 - element.to[Z], element.to[X], 16 - element.from[Z]];\n case CubeFace.UP:\n return [element.from[X], element.from[Z], element.to[X], element.to[Z]];\n case CubeFace.NORTH:\n default:\n return [16 - element.to[X], 16 - element.to[Y], 16 - element.from[X], 16 - element.from[Y]];\n case CubeFace.SOUTH:\n return [element.from[X], 16 - element.to[Y], element.to[X], 16 - element.from[Y]];\n case CubeFace.WEST:\n return [element.from[Z], 16 - element.to[Y], element.to[Z], 16 - element.from[Y]];\n case CubeFace.EAST:\n return [16 - element.to[Z], 16 - element.to[Y], 16 - element.from[Z], 16 - element.from[Y]];\n }\n }\n\n protected static expandAndRotateMcUvs([u1, v1, u2, v2]: QuadArray, rotation: number = 0, actualWidth: number, actualHeight: number): QuadArray<Vector2> {\n // Resize coordinates to actual texture size\n const scaleU = actualWidth / 16;\n const scaleV = actualHeight / 16;\n u1 *= scaleU;\n v1 *= scaleV;\n u2 *= scaleU;\n v2 *= scaleV;\n\n let tl: Vector2 = new Vector2(u1, v1);// top left\n let tr: Vector2 = new Vector2(u2, v1);// top right\n let bl: Vector2 = new Vector2(u1, v2);// bottom left\n let br: Vector2 = new Vector2(u2, v2);// bottom right\n\n switch (rotation) {\n case 0:\n case 360:\n default:\n break;\n case 90:\n tl = new Vector2(u1, v2);\n tr = new Vector2(u1, v1);\n bl = new Vector2(u2, v2);\n br = new Vector2(u2, v1);\n break;\n case 180:\n tl = new Vector2(u2, v2);\n tr = new Vector2(u1, v2);\n bl = new Vector2(u2, v1);\n br = new Vector2(u1, v1);\n break;\n case 270:\n tl = new Vector2(u2, v1);\n tr = new Vector2(u2, v2);\n bl = new Vector2(u1, v1);\n br = new Vector2(u1, v2);\n break;\n }\n\n return [tl, tr, bl, br];\n }\n\n /**\n * Combines model textures and animation metadata into an atlas.\n * Mapped UVs are stored on copies of the model's elements, available through the returned atlas.\n * Returns `undefined` for models without a texture map.\n */\n public static async createAtlas(originalModel: Model): Promise<Maybe<TextureAtlas>> {\n const textureMap: { [key: string]: Maybe<WrappedImage>; } = {};\n const metaMap: { [key: string]: Maybe<MinecraftTextureMeta>; } = {};\n const model = {...originalModel};\n // Merged models share element objects with their cached parents (cube, cube_all, ...), so the\n // baked UVs below must go onto this atlas's own copies, not onto objects other atlases read.\n if (originalModel.elements) {\n model.elements = originalModel.elements.map(element => ({ ...element }));\n }\n const isItemModel = !(\"elements\" in model);\n\n log.debug(\"Creating Atlas for\", model.key);\n\n if (model.textures) {\n const promises: Promise<void>[] = [];\n const uniqueTextureNames: string[] = []; // TODO: make these actually unique\n const textureReferences: { [k: string]: string; } = {};\n for (let textureKey in model.textures) {\n let textureValue = model.textures[textureKey];\n if (textureValue.startsWith(\"#\")) {\n textureReferences[textureKey] = textureValue.substr(1);\n } else {\n uniqueTextureNames.push(textureKey);\n const assetKey = AssetKey.parse(\"textures\", textureValue, model.key);\n promises.push(ModelTextures.get(assetKey).then(asset => {\n if (!asset) {\n log.warn(\"Missing texture\", assetKey)\n return;\n }\n textureMap[textureKey] = new WrappedImage(asset);\n }));\n promises.push(ModelTextures.getMeta(assetKey).then(meta => {\n metaMap[textureKey] = meta;\n }))\n }\n }\n await Promise.all(promises);\n const textureCount = uniqueTextureNames.length;\n log.debug(\"Creating Atlas for\", textureCount, \"textures\");\n\n this.fillMissingTextureKeys(model.textures, textureMap);\n this.fillMissingTextureKeys(model.textures, metaMap);\n\n const sizes: { [texture: string]: DoubleArray; } = {};\n const frames: { [texture: string]: { index: number; time: number }[] } = {};\n\n // Find largest texture dimensions\n let maxWidth = 0;\n for (let textureKey of uniqueTextureNames) {\n let texture = textureMap[textureKey];\n if (!texture) continue;\n const animation = metaMap[textureKey]?.animation;\n let width = texture.width, height = texture.height;\n if (animation) {\n const square = Math.min(width, height);\n width = animation.width ?? (animation.height === undefined ? square : width);\n height = animation.height ?? (animation.width === undefined ? square : height);\n if (!Number.isInteger(width) || !Number.isInteger(height) || width <= 0 || height <= 0\n || texture.width % width || texture.height % height) {\n throw new RangeError(`Invalid animation frame dimensions for ${textureKey}`);\n }\n const count = (texture.width / width) * (texture.height / height);\n const time = animation.frametime ?? 1;\n frames[textureKey] = (animation.frames ?? Array.from({ length: count }, (_, index) => index))\n .map(frame => typeof frame === \"number\" ? { index: frame, time } : { index: frame.index, time: frame.time ?? time });\n if (!frames[textureKey].length || frames[textureKey].some(frame => !Number.isInteger(frame.index)\n || frame.index < 0 || frame.index >= count || !Number.isInteger(frame.time) || frame.time < 1)) {\n throw new RangeError(`Invalid animation frames for ${textureKey}`);\n }\n }\n sizes[textureKey] = [width, height];\n maxWidth = Math.max(maxWidth, width, height);\n }\n this.fillMissingTextureKeys(model.textures, sizes);\n\n\n const s = (Math.ceil(Math.sqrt(textureCount + 1))); // +1 for transparency\n const size = Math.ceil(s * maxWidth)\n log.debug(\"Atlas size:\", size);\n const squaredSize = size * size;\n\n const image = new CanvasImage(size, size);\n const missing = Textures.getMissing().image;\n const missingPixels = image.context.createImageData(missing.width, missing.height);\n missingPixels.data.set(missing.data!);\n image.putData(missingPixels, 0, 0);\n // The top-left atlas cell keeps absent model faces transparent.\n image.context.clearRect(0, 0, maxWidth, maxWidth);\n\n const positions: { [texture: string]: DoubleArray; } = {};\n\n let hasTransparency = false;\n let hasTranslucency = false;\n\n let hasAnimation = false;\n const animatorFunctions: { [texture: string]: AnimatorFunction; } = {};\n\n // Draw all textures onto a single image\n let tx = 1; // start one over to leave room for the transparent space\n let ty = 0;\n for (let textureIndex = 0; textureIndex < uniqueTextureNames.length; textureIndex++) {\n let textureKey = uniqueTextureNames[textureIndex];\n let texture = textureMap[textureKey];\n let x = tx * maxWidth;\n let y = ty * maxWidth;\n if (texture) {\n positions[textureKey] = [x, y];\n const [width, height] = sizes[textureKey];\n const sequence = frames[textureKey];\n const getFrameData = (index: number) => {\n const columns = texture!.width / width;\n return texture!.getSectionData((index % columns) * width,\n Math.floor(index / columns) * height, width, height);\n };\n const firstFrame = getFrameData(sequence?.[0].index ?? 0);\n image.putData(firstFrame, x, y);\n\n if (texture.hasTransparency) {\n hasTransparency = true;\n }\n if (texture.hasTranslucency) {\n hasTranslucency = true;\n }\n\n if (sequence && sequence.some(frame => frame.index !== sequence[0].index)) {\n hasAnimation = true;\n let t = 0;\n let f = 0;\n const interpolated = metaMap[textureKey]?.animation?.interpolate\n ? image.context.createImageData(width, height) : undefined;\n let currentFrame = firstFrame;\n let nextFrame = interpolated ? getFrameData(sequence[1].index) : firstFrame;\n\n animatorFunctions[textureKey] = () => {\n if (++t >= sequence[f].time) {\n t = 0;\n const previous = sequence[f].index;\n f = (f + 1) % sequence.length;\n if (interpolated) {\n currentFrame = nextFrame;\n nextFrame = getFrameData(sequence[(f + 1) % sequence.length].index);\n }\n if (sequence[f].index === previous) return false;\n image.putData(interpolated ? currentFrame : getFrameData(sequence[f].index), x, y);\n return true;\n }\n if (!interpolated || sequence[f].index === sequence[(f + 1) % sequence.length].index) return false;\n // Vanilla encodes the atlas shader's interpolation progress in thousandths.\n const progress = Math.floor(Math.fround(Math.fround(t / sequence[f].time) * 1000)) / 1000;\n for (let i = 0; i < interpolated.data.length; i++) {\n interpolated.data[i] = currentFrame.data[i] + (nextFrame.data[i] - currentFrame.data[i]) * progress;\n }\n image.putData(interpolated, x, y);\n return true;\n };\n }\n }\n tx++;\n if (tx >= s) {\n tx = 0;\n ty++;\n }\n }\n this.fillMissingTextureKeys(model.textures, positions);\n\n\n if (isItemModel) {\n log.debug(\"Generating item model for\", model);\n model.elements = [];\n for (let layerName of ModelGenerator.ITEM_LAYERS) {\n const textureImage = textureMap[layerName];\n if (textureImage) {\n // Outline the frame that was drawn into the atlas, not the whole animation strip.\n const [width, height] = sizes[layerName];\n const frame = frames[layerName]?.[0].index ?? 0;\n const columns = textureImage.width / width;\n model.elements.push(...ModelGenerator.generateItemModel(textureImage.getSectionData(\n (frame % columns) * width, Math.floor(frame / columns) * height, width, height), layerName))\n }\n }\n log.debug(\"Item model elements\", model.elements)\n }\n\n if (!model.elements) {\n //TODO: default elements\n }\n\n // Adjust UV positions\n if (model.elements) {\n for (let elementIndex = 0; elementIndex < model.elements.length; elementIndex++) {\n let element = model.elements[elementIndex];\n let uv: number[] = [];\n // Set default uvs to missing texture\n for (let i = 0; i < CUBE_FACES.length; i++) {\n this.setCubeFaceUvInArray(uv, i * 4, [0, 0, 8 / size, 8 / size])\n }\n for (let faceIndex = 0; faceIndex < CUBE_FACES.length; faceIndex++) {\n let faceName = CUBE_FACES[faceIndex];\n let face = element.faces[faceName];\n if (!face) {\n // set uv transparent\n this.setCubeFaceUvInArray(uv, faceIndex * 4, [0, 1, 8 / size, (size - 8) / size])\n continue;\n }\n // Keep the missing-texture UVs when no texture is referenced.\n if (!face.texture) continue;\n if (!face.uv) {\n face.uv = this.getFallbackUv(element, faceName);\n }\n\n const faceTexture = face.texture.substr(1); // remove #\n const texPosition = positions[faceTexture] || [0, 0];\n const texSize = sizes[faceTexture] || [16, 16];\n\n let texPosV = new Vector2(texPosition[0], texPosition[1]);\n\n const [tl, tr, bl, br] = this.expandAndRotateMcUvs(face.uv, face.rotation, texSize[0], texSize[1]);\n\n // move to atlas position\n tl.add(texPosV);\n tr.add(texPosV);\n bl.add(texPosV);\n br.add(texPosV);\n\n // divide to 0-1\n tl.divideScalar(size);\n tr.divideScalar(size);\n bl.divideScalar(size);\n br.divideScalar(size);\n\n // flip y coordinates\n tl.y = 1 - tl.y;\n tr.y = 1 - tr.y;\n bl.y = 1 - bl.y;\n br.y = 1 - br.y;\n\n let uvs: QuadArray<Vector2> = [tl, tr, bl, br];\n this.setFaceUvInArrayV(uv, faceIndex * 4, uvs);\n }\n\n element.mappedUv = uv;\n }\n } else {\n //TODO: item model\n }\n\n return new TextureAtlas(\n model,\n image,\n sizes,\n positions,\n hasAnimation,\n animatorFunctions,\n hasTransparency,\n hasTranslucency\n );\n } else {\n log.warn(\"Model does not have any textures\", model);\n }\n return undefined;\n }\n\n}\n\n// Based on net.minecraft.client.renderer.block.model.BlockFaceUV\n/** Stores a Minecraft face's UV rectangle and its rotation in degrees. */\nexport class MinecraftFaceUV {\n\n constructor(readonly uv: QuadArray = [0, 0, 16, 16], readonly rotation: number = 0) {\n }\n\n getU(index: number): number {\n const shiftedIndex = this.getShiftedIndex(index);\n return this.uv[shiftedIndex !== 0 && index !== 1 ? 2 : 0];\n }\n\n getV(index: number): number {\n const shiftedIndex = this.getShiftedIndex(index);\n return this.uv[shiftedIndex !== 0 && index !== 3 ? 3 : 1];\n }\n\n protected getShiftedIndex(index: number): number {\n return (index + this.rotation / 90) % 40;\n }\n\n protected getReverseIndex(index: number): number {\n return (index + 4 - this.rotation / 90) % 4;\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,10 +1,10 @@
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
- import { prefix } from "../util/log.mjs";
4
+ import { logger } from "../util/log.mjs";
5
5
  import { HostedAssetSource } from "./source/index.mjs";
6
6
  import { Caching } from "../cache/Caching.mjs";
7
- var p = prefix("AssetLoader");
7
+ var log = logger("AssetLoader");
8
8
  var AssetLoader = class {
9
9
  static get _SOURCES() {
10
10
  return this.sources ?? (this.sources = [{ key: "mcassets", source: new HostedAssetSource(this.ROOT, { retryDefaults: false }) }]);
@@ -59,11 +59,11 @@ ${key}` : key;
59
59
  if (override) {
60
60
  const existing = this.removeSource(key);
61
61
  if (existing) {
62
- console.log(p, "Removed existing AssetSource", key);
62
+ log.info("Removed existing AssetSource", key);
63
63
  }
64
64
  }
65
65
  this._SOURCES.unshift({ key, source });
66
- console.log(p, "Added AssetSource", key);
66
+ log.info("Added AssetSource", key);
67
67
  }
68
68
  /** Removes and returns the first source with this name. Call {@link Caching.clear} to reload assets. */
69
69
  static removeSource(key) {
@@ -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 { logger } 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 log = logger(\"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 log.info(\"Removed existing AssetSource\", key);\n }\n }\n\n this._SOURCES.unshift({key, source});\n log.info(\"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