minerender 2.1.0-beta.5 → 2.1.0-beta.6
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.
- package/dist/browser/esm/Materials.mjs +3 -2
- package/dist/browser/esm/Materials.mjs.map +1 -1
- package/dist/browser/esm/assets/Fonts.mjs +31 -4
- package/dist/browser/esm/assets/Fonts.mjs.map +1 -1
- package/dist/browser/esm/assets/_fonts/Unihex.mjs +166 -0
- package/dist/browser/esm/assets/_fonts/Unihex.mjs.map +1 -0
- package/dist/browser/esm/assets/source/HostedAssetSource.mjs +12 -1
- package/dist/browser/esm/assets/source/HostedAssetSource.mjs.map +1 -1
- package/dist/browser/esm/assets/source/parser/AssetParsers.mjs +1 -0
- package/dist/browser/esm/assets/source/parser/AssetParsers.mjs.map +1 -1
- package/dist/browser/esm/cache/Caching.mjs +2 -0
- package/dist/browser/esm/cache/Caching.mjs.map +1 -1
- package/dist/browser/esm/entity/scene/EntityAnimationPlayer.mjs +62 -11
- package/dist/browser/esm/entity/scene/EntityAnimationPlayer.mjs.map +1 -1
- package/dist/browser/esm/entity/scene/EntityObject.mjs +53 -20
- package/dist/browser/esm/entity/scene/EntityObject.mjs.map +1 -1
- package/dist/browser/esm/env/browser/section.worker.mjs +5 -3
- package/dist/browser/esm/env/browser/section.worker.mjs.map +1 -1
- package/dist/browser/esm/gui/GuiText.mjs +4 -3
- package/dist/browser/esm/gui/GuiText.mjs.map +1 -1
- package/dist/browser/esm/index.browser.d.mts +52 -10
- package/dist/browser/esm/model/scene/ModelObject.mjs +4 -0
- package/dist/browser/esm/model/scene/ModelObject.mjs.map +1 -1
- package/dist/browser/esm/util/model.mjs +7 -7
- package/dist/browser/esm/util/model.mjs.map +1 -1
- package/dist/browser/esm/world/SectionGeometry.mjs +5 -3
- package/dist/browser/esm/world/SectionGeometry.mjs.map +1 -1
- package/dist/browser/esm/world/SectionMesh.mjs +4 -0
- package/dist/browser/esm/world/SectionMesh.mjs.map +1 -1
- package/dist/browser/esm/world/SectionModels.mjs +2 -2
- package/dist/browser/esm/world/SectionModels.mjs.map +1 -1
- package/dist/browser/index.d.ts +52 -10
- package/dist/browser/index.js +382 -73
- package/dist/browser/index.js.map +1 -1
- package/dist/bundle.js +425 -73
- package/dist/bundle.js.map +1 -1
- package/dist/node/index.d.mts +52 -10
- package/dist/node/index.d.ts +52 -10
- package/dist/node/index.js +387 -73
- package/dist/node/index.js.map +1 -1
- package/dist/node/index.mjs +386 -73
- package/dist/node/index.mjs.map +1 -1
- package/package.json +1 -1
|
@@ -139,6 +139,7 @@ var Materials = class _Materials {
|
|
|
139
139
|
static createShadedCanvasMaterial(canvas, transparent = false, shade = false, boundUvs = false) {
|
|
140
140
|
const vertShader = `
|
|
141
141
|
uniform bool SHADE;
|
|
142
|
+
attribute float shade;
|
|
142
143
|
|
|
143
144
|
// Keep MSAA edge pixels from sampling outside the face's atlas region.
|
|
144
145
|
#if __VERSION__ >= 300
|
|
@@ -161,7 +162,7 @@ var Materials = class _Materials {
|
|
|
161
162
|
void main()
|
|
162
163
|
{
|
|
163
164
|
|
|
164
|
-
if (SHADE) {
|
|
165
|
+
if (SHADE && shade > 0.5) {
|
|
165
166
|
|
|
166
167
|
#ifdef USE_INSTANCING
|
|
167
168
|
vec3 N = vec3( modelMatrix * instanceMatrix * vec4(normal, 0.0) );
|
|
@@ -270,7 +271,7 @@ var Materials = class _Materials {
|
|
|
270
271
|
side: transparent ? DoubleSide : FrontSide,
|
|
271
272
|
alphaTest: 0.5
|
|
272
273
|
});
|
|
273
|
-
Object.assign(material.defaultAttributeValues, { uvBounds: [0, 0, 1, 1] });
|
|
274
|
+
Object.assign(material.defaultAttributeValues, { shade: [1], uvBounds: [0, 0, 1, 1] });
|
|
274
275
|
return material;
|
|
275
276
|
} catch (e) {
|
|
276
277
|
console.warn(e);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/Materials.ts"],"sourcesContent":["import { MaterialKey, serializeMaterialKey } from \"./cache/CacheKey\";\nimport { Color, ColorRepresentation, CustomBlending, DoubleSide, OneFactor, OneMinusSrcAlphaFactor, RepeatWrapping, FrontSide, Material, MeshBasicMaterial, MeshLambertMaterial, MeshPhongMaterial, MeshStandardMaterial, ShaderChunk, ShaderMaterial } from \"three\";\nimport { Textures } from \"./texture/Textures\";\nimport { TextureLoader } from \"./texture/TextureLoader\";\nimport { Caching } from \"./cache/Caching\";\nimport { AssetKey } from \"./assets/AssetKey\";\nimport type { EntityRenderMode } from \"./entity/EntityModel\";\n\n/** Creates Minecraft model, entity, and GUI materials, with shared caches for image materials. */\nexport class Materials {\n\n /** Shared checkerboard material, created on first access. */\n public static get MISSING_TEXTURE(): Material {\n return Caching.materialCache.get(\"builtin:missing-texture\", () => new MeshBasicMaterial({\n map: Textures.getMissing(),\n alphaTest: 0.5\n }))!;\n }\n\n public static createImage(key: MaterialKey): Material {\n //TODO: type from key\n const transparent = key.transparent || false;\n return new MeshBasicMaterial({\n map: Textures.getImage(key.texture),\n transparent: transparent,\n side: transparent ? DoubleSide : FrontSide,\n alphaTest: 0.5\n });\n //TODO: params\n }\n\n\n public static createBasicCanvasMaterial(canvas: HTMLCanvasElement, transparent: boolean = false, shade: boolean = false): Material {\n if (shade) {\n return new MeshStandardMaterial({\n map: Textures.createCanvasTexture(canvas),\n transparent: transparent,\n side: transparent ? DoubleSide : FrontSide,\n alphaTest: 0.5,\n\n })\n }\n return new MeshBasicMaterial({\n map: Textures.createCanvasTexture(canvas),\n transparent: transparent,\n side: transparent ? DoubleSide : FrontSide,\n alphaTest: 0.5,\n\n })\n }\n\n /** Whether vanilla's render type for the mode culls back faces. */\n public static entityModeCulls(mode: EntityRenderMode = \"cutout\"): boolean {\n return mode === \"cutout_cull\" || mode === \"solid\" || mode === \"eyes\" || mode === \"water_mask\";\n }\n\n /** UV offset per tick of entity age for the scrolling modes, as vanilla's texture matrix applies it. */\n public static entityModeScroll(mode: EntityRenderMode = \"cutout\"): [number, number] | undefined {\n if (mode === \"energy_swirl\") return [0.01, 0.01];\n if (mode === \"breeze_wind\") return [0.02, 0];\n return undefined;\n }\n\n /**\n * Entity material for one of vanilla's render types. Entities are unlit here, so the lit and full-bright modes\n * differ only in blending and depth state. Culling is not a material property: {@link entityModeCulls} decides\n * whether the geometry gets inward faces.\n */\n public static createEntityCanvasMaterial(canvas: HTMLCanvasElement, mode: EntityRenderMode = \"cutout\", tint?: ColorRepresentation): MeshBasicMaterial {\n const material = Materials.createBasicCanvasMaterial(canvas) as MeshBasicMaterial;\n switch (mode) {\n case \"cutout\":\n case \"cutout_cull\":\n break;\n case \"cutout_z_offset\":\n material.polygonOffset = true;\n material.polygonOffsetFactor = -1;\n material.polygonOffsetUnits = -10;\n break;\n case \"solid\":\n material.alphaTest = 0;\n break;\n case \"translucent\":\n case \"breeze_wind\":\n material.transparent = true;\n material.alphaTest = 0.1;\n break;\n case \"translucent_emissive\":\n material.transparent = true;\n material.alphaTest = 0.1;\n material.depthWrite = false;\n break;\n case \"eyes\":\n case \"no_outline\":\n material.transparent = true;\n material.alphaTest = 0;\n material.depthWrite = false;\n break;\n case \"energy_swirl\":\n material.transparent = true;\n material.alphaTest = 0.1;\n material.blending = CustomBlending;\n material.blendSrc = OneFactor;\n material.blendDst = OneFactor;\n // The canvas is premultiplied: a glow pixel needs alpha, or browsers and image exports drop it wherever\n // nothing opaque is behind it. Its brightness serves as coverage, so the glow stays visible outside the body.\n material.blendSrcAlpha = OneFactor;\n material.blendDstAlpha = OneMinusSrcAlphaFactor;\n material.onBeforeCompile = shader => {\n shader.fragmentShader = shader.fragmentShader.replace(\"#include <dithering_fragment>\",\n \"gl_FragColor.a = max(gl_FragColor.r, max(gl_FragColor.g, gl_FragColor.b));\\n#include <dithering_fragment>\");\n };\n material.customProgramCacheKey = () => \"energy_swirl\";\n // Vanilla submits the swirl with half-grey vertex colour.\n material.color.set(0x808080);\n break;\n case \"water_mask\":\n material.alphaTest = 0;\n material.colorWrite = false;\n break;\n }\n if (Materials.entityModeScroll(mode)) {\n material.map!.wrapS = material.map!.wrapT = RepeatWrapping;\n }\n if (tint !== undefined) material.color.multiply(new Color(tint));\n return material;\n }\n\n /** Creates an unlit, transparent GUI material without depth writes or tone mapping. */\n public static createGuiCanvasMaterial(canvas: HTMLCanvasElement): MeshBasicMaterial {\n const material = new MeshBasicMaterial({\n map: Textures.createCanvasTexture(canvas),\n transparent: true,\n depthWrite: false,\n side: DoubleSide,\n toneMapped: false\n });\n material.onBeforeCompile = shader => {\n // Keep MSAA edge pixels inside the layer's cropped texture region.\n for (const [stage, direction] of [[\"vertex\", \"out\"], [\"fragment\", \"in\"]] as const) {\n const chunk = `uv_pars_${stage}` as const;\n shader[`${stage}Shader`] = shader[`${stage}Shader`].replace(`#include <${chunk}>`,\n ShaderChunk[chunk].replace(\"varying vec2 vMapUv;\", `\n #if __VERSION__ >= 300\n centroid ${direction} vec2 vMapUv;\n #else\n varying vec2 vMapUv;\n #endif\n `));\n }\n };\n return material;\n }\n\n public static createShadedCanvasMaterial(canvas: HTMLCanvasElement, transparent: boolean = false, shade:boolean=false, boundUvs: boolean = false):Material {\n //TODO\n // this might help https://github.com/JannisX11/blockbench/blob/1701f764641376414d29100c4f6c7cd74997fad8/js/preview/canvas.js#L62\n\n\n // Based on https://github.com/JannisX11/blockbench/blob/cc73aa8a9c0494fd9fe1cee4d062d060af4db06d/js/texturing/textures.js#L59\n // + support for instanced meshes\n const vertShader =`\n uniform bool SHADE;\n \n // Keep MSAA edge pixels from sampling outside the face's atlas region.\n #if __VERSION__ >= 300\n centroid out vec2 vUv;\n #else\n varying vec2 vUv;\n #endif\n #ifdef BOUND_UVS\n attribute vec4 uvBounds;\n flat out vec4 vUvBounds;\n #endif\n varying vec3 vTint;\n varying float light;\n varying float lift;\n\n float AMBIENT = 0.5;\n float XFAC = -0.15;\n float ZFAC = 0.05;\n\n void main()\n {\n\n if (SHADE) {\n\n #ifdef USE_INSTANCING\n vec3 N = vec3( modelMatrix * instanceMatrix * vec4(normal, 0.0) );\n #else\n vec3 N = vec3( modelMatrix * vec4(normal, 0.0) );\n #endif\n\n float yLight = (1.0+N.y) * 0.5;\n light = yLight * (1.0-AMBIENT) + N.x*N.x * XFAC + N.z*N.z * ZFAC + AMBIENT;\n\n } else {\n\n light = 1.0;\n\n } \n\n if (color.b > 1.1) {\n lift = 0.1;\n } else {\n lift = 0.0;\n }\n \n vUv = uv;\n #ifdef BOUND_UVS\n vUvBounds = uvBounds;\n #endif\n vTint = color;\n \n vec4 mvPosition = vec4(position, 1.0);\n #ifdef USE_INSTANCING\n mvPosition = instanceMatrix * mvPosition;\n #endif\n mvPosition = modelViewMatrix * mvPosition;\n gl_Position = projectionMatrix * mvPosition;\n \n }\n `\n const fragShader = `\n #ifdef GL_ES\n precision highp float;\n #endif\n\n uniform sampler2D map;\n\n uniform bool SHADE;\n uniform bool EMISSIVE;\n uniform float BRIGHTNESS;\n\n #if __VERSION__ >= 300\n centroid in vec2 vUv;\n #else\n varying vec2 vUv;\n #endif\n #ifdef BOUND_UVS\n flat in vec4 vUvBounds;\n #endif\n varying vec3 vTint;\n varying float light;\n varying float lift;\n\n void main(void)\n {\n #ifdef BOUND_UVS\n // Keep edge samples inside their texture even without centroid interpolation.\n vec2 mapUv = clamp(vUv, vUvBounds.xy, vUvBounds.zw);\n #else\n vec2 mapUv = vUv;\n #endif\n vec4 color = texture2D(map, mapUv);\n color.rgb *= vTint;\n \n if (color.a < 0.01) discard;\n\n if (EMISSIVE == false) {\n\n gl_FragColor = vec4(lift + color.rgb * light * BRIGHTNESS, color.a);\n\n } else {\n\n float light2 = (light * BRIGHTNESS) + (1.0 - light * BRIGHTNESS) * (1.0 - color.a);\n gl_FragColor = vec4(lift + color.rgb * light2, 1.0);\n\n }\n\n #include <tonemapping_fragment>\n #include <colorspace_fragment>\n }\n `\n //TODO: this does add the MC-like shading, but breaks when stuff is instanced (can't updated position)\n // https://medium.com/@pailhead011/instancing-with-three-js-part-2-3be34ae83c57 might help with that\n\n try {\n const material = new ShaderMaterial({\n defines: boundUvs ? { BOUND_UVS: true } : {},\n uniforms: {\n SHADE: { value: true },\n BRIGHTNESS: { value: 1 },\n EMISSIVE:{value:false},\n base: { value: new Color(0xc1c1c1)/*TODO*/ },\n map: {value:Textures.createCanvasTexture(canvas)}\n },\n vertexShader: vertShader,\n fragmentShader: fragShader,\n vertexColors: true,\n transparent: transparent,\n side: transparent ? DoubleSide : FrontSide,\n alphaTest: 0.5,\n });\n Object.assign(material.defaultAttributeValues, { uvBounds: [0, 0, 1, 1] });\n return material;\n } catch (e) {\n console.warn(e)\n }\n\n // fallback\n return this.createBasicCanvasMaterial(canvas, transparent, shade);\n }\n\n /** Returns a shared image material. Use {@link createImage} for a separate material instance. */\n public static getImage(key: MaterialKey): Material {\n const keyStr = serializeMaterialKey(key);\n const map = (Caching.materialCache.peek(keyStr) as MeshBasicMaterial | undefined)?.map;\n if (map && TextureLoader.hasFailed(map)) {\n Caching.materialCache.invalidate(keyStr);\n }\n return Caching.materialCache.get(keyStr, k => {\n return Materials.createImage(key);\n })!;\n }\n\n public static needsUpdate(mat: Material) {\n mat.needsUpdate = true;\n\n if (mat.type === 'ShaderMaterial') {\n let mat1=mat as ShaderMaterial;\n if (\"map\" in mat1.uniforms) {\n mat1.uniforms.map.value.needsUpdate = true;\n }\n }\n if (mat.type === 'MeshBasicMaterial' || mat.type === 'MeshStandardMaterial') {\n let mat1 = mat as (MeshBasicMaterial | MeshStandardMaterial);\n if (mat1.map) {\n mat1.map.needsUpdate = true;\n }\n }\n }\n\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../src/Materials.ts"],"sourcesContent":["import { MaterialKey, serializeMaterialKey } from \"./cache/CacheKey\";\nimport { Color, ColorRepresentation, CustomBlending, DoubleSide, OneFactor, OneMinusSrcAlphaFactor, RepeatWrapping, FrontSide, Material, MeshBasicMaterial, MeshLambertMaterial, MeshPhongMaterial, MeshStandardMaterial, ShaderChunk, ShaderMaterial } from \"three\";\nimport { Textures } from \"./texture/Textures\";\nimport { TextureLoader } from \"./texture/TextureLoader\";\nimport { Caching } from \"./cache/Caching\";\nimport { AssetKey } from \"./assets/AssetKey\";\nimport type { EntityRenderMode } from \"./entity/EntityModel\";\n\n/** Creates Minecraft model, entity, and GUI materials, with shared caches for image materials. */\nexport class Materials {\n\n /** Shared checkerboard material, created on first access. */\n public static get MISSING_TEXTURE(): Material {\n return Caching.materialCache.get(\"builtin:missing-texture\", () => new MeshBasicMaterial({\n map: Textures.getMissing(),\n alphaTest: 0.5\n }))!;\n }\n\n public static createImage(key: MaterialKey): Material {\n //TODO: type from key\n const transparent = key.transparent || false;\n return new MeshBasicMaterial({\n map: Textures.getImage(key.texture),\n transparent: transparent,\n side: transparent ? DoubleSide : FrontSide,\n alphaTest: 0.5\n });\n //TODO: params\n }\n\n\n public static createBasicCanvasMaterial(canvas: HTMLCanvasElement, transparent: boolean = false, shade: boolean = false): Material {\n if (shade) {\n return new MeshStandardMaterial({\n map: Textures.createCanvasTexture(canvas),\n transparent: transparent,\n side: transparent ? DoubleSide : FrontSide,\n alphaTest: 0.5,\n\n })\n }\n return new MeshBasicMaterial({\n map: Textures.createCanvasTexture(canvas),\n transparent: transparent,\n side: transparent ? DoubleSide : FrontSide,\n alphaTest: 0.5,\n\n })\n }\n\n /** Whether vanilla's render type for the mode culls back faces. */\n public static entityModeCulls(mode: EntityRenderMode = \"cutout\"): boolean {\n return mode === \"cutout_cull\" || mode === \"solid\" || mode === \"eyes\" || mode === \"water_mask\";\n }\n\n /** UV offset per tick of entity age for the scrolling modes, as vanilla's texture matrix applies it. */\n public static entityModeScroll(mode: EntityRenderMode = \"cutout\"): [number, number] | undefined {\n if (mode === \"energy_swirl\") return [0.01, 0.01];\n if (mode === \"breeze_wind\") return [0.02, 0];\n return undefined;\n }\n\n /**\n * Entity material for one of vanilla's render types. Entities are unlit here, so the lit and full-bright modes\n * differ only in blending and depth state. Culling is not a material property: {@link entityModeCulls} decides\n * whether the geometry gets inward faces.\n */\n public static createEntityCanvasMaterial(canvas: HTMLCanvasElement, mode: EntityRenderMode = \"cutout\", tint?: ColorRepresentation): MeshBasicMaterial {\n const material = Materials.createBasicCanvasMaterial(canvas) as MeshBasicMaterial;\n switch (mode) {\n case \"cutout\":\n case \"cutout_cull\":\n break;\n case \"cutout_z_offset\":\n material.polygonOffset = true;\n material.polygonOffsetFactor = -1;\n material.polygonOffsetUnits = -10;\n break;\n case \"solid\":\n material.alphaTest = 0;\n break;\n case \"translucent\":\n case \"breeze_wind\":\n material.transparent = true;\n material.alphaTest = 0.1;\n break;\n case \"translucent_emissive\":\n material.transparent = true;\n material.alphaTest = 0.1;\n material.depthWrite = false;\n break;\n case \"eyes\":\n case \"no_outline\":\n material.transparent = true;\n material.alphaTest = 0;\n material.depthWrite = false;\n break;\n case \"energy_swirl\":\n material.transparent = true;\n material.alphaTest = 0.1;\n material.blending = CustomBlending;\n material.blendSrc = OneFactor;\n material.blendDst = OneFactor;\n // The canvas is premultiplied: a glow pixel needs alpha, or browsers and image exports drop it wherever\n // nothing opaque is behind it. Its brightness serves as coverage, so the glow stays visible outside the body.\n material.blendSrcAlpha = OneFactor;\n material.blendDstAlpha = OneMinusSrcAlphaFactor;\n material.onBeforeCompile = shader => {\n shader.fragmentShader = shader.fragmentShader.replace(\"#include <dithering_fragment>\",\n \"gl_FragColor.a = max(gl_FragColor.r, max(gl_FragColor.g, gl_FragColor.b));\\n#include <dithering_fragment>\");\n };\n material.customProgramCacheKey = () => \"energy_swirl\";\n // Vanilla submits the swirl with half-grey vertex colour.\n material.color.set(0x808080);\n break;\n case \"water_mask\":\n material.alphaTest = 0;\n material.colorWrite = false;\n break;\n }\n if (Materials.entityModeScroll(mode)) {\n material.map!.wrapS = material.map!.wrapT = RepeatWrapping;\n }\n if (tint !== undefined) material.color.multiply(new Color(tint));\n return material;\n }\n\n /** Creates an unlit, transparent GUI material without depth writes or tone mapping. */\n public static createGuiCanvasMaterial(canvas: HTMLCanvasElement): MeshBasicMaterial {\n const material = new MeshBasicMaterial({\n map: Textures.createCanvasTexture(canvas),\n transparent: true,\n depthWrite: false,\n side: DoubleSide,\n toneMapped: false\n });\n material.onBeforeCompile = shader => {\n // Keep MSAA edge pixels inside the layer's cropped texture region.\n for (const [stage, direction] of [[\"vertex\", \"out\"], [\"fragment\", \"in\"]] as const) {\n const chunk = `uv_pars_${stage}` as const;\n shader[`${stage}Shader`] = shader[`${stage}Shader`].replace(`#include <${chunk}>`,\n ShaderChunk[chunk].replace(\"varying vec2 vMapUv;\", `\n #if __VERSION__ >= 300\n centroid ${direction} vec2 vMapUv;\n #else\n varying vec2 vMapUv;\n #endif\n `));\n }\n };\n return material;\n }\n\n public static createShadedCanvasMaterial(canvas: HTMLCanvasElement, transparent: boolean = false, shade:boolean=false, boundUvs: boolean = false):Material {\n //TODO\n // this might help https://github.com/JannisX11/blockbench/blob/1701f764641376414d29100c4f6c7cd74997fad8/js/preview/canvas.js#L62\n\n\n // Based on https://github.com/JannisX11/blockbench/blob/cc73aa8a9c0494fd9fe1cee4d062d060af4db06d/js/texturing/textures.js#L59\n // + support for instanced meshes\n const vertShader =`\n uniform bool SHADE;\n attribute float shade;\n \n // Keep MSAA edge pixels from sampling outside the face's atlas region.\n #if __VERSION__ >= 300\n centroid out vec2 vUv;\n #else\n varying vec2 vUv;\n #endif\n #ifdef BOUND_UVS\n attribute vec4 uvBounds;\n flat out vec4 vUvBounds;\n #endif\n varying vec3 vTint;\n varying float light;\n varying float lift;\n\n float AMBIENT = 0.5;\n float XFAC = -0.15;\n float ZFAC = 0.05;\n\n void main()\n {\n\n if (SHADE && shade > 0.5) {\n\n #ifdef USE_INSTANCING\n vec3 N = vec3( modelMatrix * instanceMatrix * vec4(normal, 0.0) );\n #else\n vec3 N = vec3( modelMatrix * vec4(normal, 0.0) );\n #endif\n\n float yLight = (1.0+N.y) * 0.5;\n light = yLight * (1.0-AMBIENT) + N.x*N.x * XFAC + N.z*N.z * ZFAC + AMBIENT;\n\n } else {\n\n light = 1.0;\n\n } \n\n if (color.b > 1.1) {\n lift = 0.1;\n } else {\n lift = 0.0;\n }\n \n vUv = uv;\n #ifdef BOUND_UVS\n vUvBounds = uvBounds;\n #endif\n vTint = color;\n \n vec4 mvPosition = vec4(position, 1.0);\n #ifdef USE_INSTANCING\n mvPosition = instanceMatrix * mvPosition;\n #endif\n mvPosition = modelViewMatrix * mvPosition;\n gl_Position = projectionMatrix * mvPosition;\n \n }\n `\n const fragShader = `\n #ifdef GL_ES\n precision highp float;\n #endif\n\n uniform sampler2D map;\n\n uniform bool SHADE;\n uniform bool EMISSIVE;\n uniform float BRIGHTNESS;\n\n #if __VERSION__ >= 300\n centroid in vec2 vUv;\n #else\n varying vec2 vUv;\n #endif\n #ifdef BOUND_UVS\n flat in vec4 vUvBounds;\n #endif\n varying vec3 vTint;\n varying float light;\n varying float lift;\n\n void main(void)\n {\n #ifdef BOUND_UVS\n // Keep edge samples inside their texture even without centroid interpolation.\n vec2 mapUv = clamp(vUv, vUvBounds.xy, vUvBounds.zw);\n #else\n vec2 mapUv = vUv;\n #endif\n vec4 color = texture2D(map, mapUv);\n color.rgb *= vTint;\n \n if (color.a < 0.01) discard;\n\n if (EMISSIVE == false) {\n\n gl_FragColor = vec4(lift + color.rgb * light * BRIGHTNESS, color.a);\n\n } else {\n\n float light2 = (light * BRIGHTNESS) + (1.0 - light * BRIGHTNESS) * (1.0 - color.a);\n gl_FragColor = vec4(lift + color.rgb * light2, 1.0);\n\n }\n\n #include <tonemapping_fragment>\n #include <colorspace_fragment>\n }\n `\n //TODO: this does add the MC-like shading, but breaks when stuff is instanced (can't updated position)\n // https://medium.com/@pailhead011/instancing-with-three-js-part-2-3be34ae83c57 might help with that\n\n try {\n const material = new ShaderMaterial({\n defines: boundUvs ? { BOUND_UVS: true } : {},\n uniforms: {\n SHADE: { value: true },\n BRIGHTNESS: { value: 1 },\n EMISSIVE:{value:false},\n base: { value: new Color(0xc1c1c1)/*TODO*/ },\n map: {value:Textures.createCanvasTexture(canvas)}\n },\n vertexShader: vertShader,\n fragmentShader: fragShader,\n vertexColors: true,\n transparent: transparent,\n side: transparent ? DoubleSide : FrontSide,\n alphaTest: 0.5,\n });\n Object.assign(material.defaultAttributeValues, { shade: [1], uvBounds: [0, 0, 1, 1] });\n return material;\n } catch (e) {\n console.warn(e)\n }\n\n // fallback\n return this.createBasicCanvasMaterial(canvas, transparent, shade);\n }\n\n /** Returns a shared image material. Use {@link createImage} for a separate material instance. */\n public static getImage(key: MaterialKey): Material {\n const keyStr = serializeMaterialKey(key);\n const map = (Caching.materialCache.peek(keyStr) as MeshBasicMaterial | undefined)?.map;\n if (map && TextureLoader.hasFailed(map)) {\n Caching.materialCache.invalidate(keyStr);\n }\n return Caching.materialCache.get(keyStr, k => {\n return Materials.createImage(key);\n })!;\n }\n\n public static needsUpdate(mat: Material) {\n mat.needsUpdate = true;\n\n if (mat.type === 'ShaderMaterial') {\n let mat1=mat as ShaderMaterial;\n if (\"map\" in mat1.uniforms) {\n mat1.uniforms.map.value.needsUpdate = true;\n }\n }\n if (mat.type === 'MeshBasicMaterial' || mat.type === 'MeshStandardMaterial') {\n let mat1 = mat as (MeshBasicMaterial | MeshStandardMaterial);\n if (mat1.map) {\n mat1.map.needsUpdate = true;\n }\n }\n }\n\n}\n"],"mappings":"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","names":[]}
|
|
@@ -5,7 +5,7 @@ import { AssetParser } from "./source/parser/AssetParsers.mjs";
|
|
|
5
5
|
import { ModelTextures } from "./ModelTextures.mjs";
|
|
6
6
|
import { Caching } from "../cache/Caching.mjs";
|
|
7
7
|
var Fonts = class {
|
|
8
|
-
/** Combines font definitions in source-priority order.
|
|
8
|
+
/** Combines font definitions in source-priority order. TrueType providers are skipped. */
|
|
9
9
|
static async get(key = "minecraft:default") {
|
|
10
10
|
const fontKey = typeof key === "string" ? AssetKey.parse("font", key) : key;
|
|
11
11
|
return await Caching.fontCache.get(fontKey.serialize(), () => this.load(fontKey, []));
|
|
@@ -21,6 +21,7 @@ var Fonts = class {
|
|
|
21
21
|
const stack = await AssetLoader.getAll(key, AssetParser.JSON);
|
|
22
22
|
if (stack.length === 0) throw new Error(`Could not load font ${key.toNamespacedString()}`);
|
|
23
23
|
const glyphs = /* @__PURE__ */ new Map();
|
|
24
|
+
const providers = [];
|
|
24
25
|
for (const asset of stack) {
|
|
25
26
|
for (const provider of asset.providers) {
|
|
26
27
|
if (provider.filter?.uniform || provider.filter?.jp) continue;
|
|
@@ -39,17 +40,43 @@ var Fonts = class {
|
|
|
39
40
|
break;
|
|
40
41
|
case "reference":
|
|
41
42
|
case "minecraft:reference":
|
|
42
|
-
|
|
43
|
+
const reference = await this.load(this.relatedKey("font", provider.id, key), [...parents, serialized]);
|
|
44
|
+
if (reference.resolve) {
|
|
45
|
+
providers.push(async (characters) => {
|
|
46
|
+
await reference.resolve(characters);
|
|
47
|
+
return reference.glyphs;
|
|
48
|
+
});
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
51
|
+
provided = reference.glyphs;
|
|
43
52
|
break;
|
|
53
|
+
case "unihex":
|
|
54
|
+
case "minecraft:unihex":
|
|
55
|
+
providers.push(async (characters) => (await import("./_fonts/Unihex.mjs")).loadUnihex(provider, key, characters));
|
|
56
|
+
continue;
|
|
44
57
|
default:
|
|
45
58
|
continue;
|
|
46
59
|
}
|
|
47
|
-
for (const [character, glyph] of provided) {
|
|
60
|
+
if (providers.every((provider2) => provider2 instanceof Map)) for (const [character, glyph] of provided) {
|
|
48
61
|
if (character !== "\0" && !glyphs.has(character)) glyphs.set(character, glyph);
|
|
49
62
|
}
|
|
63
|
+
providers.push(provided);
|
|
50
64
|
}
|
|
51
65
|
}
|
|
52
|
-
return { glyphs
|
|
66
|
+
return { glyphs, resolve: providers.every((provider) => provider instanceof Map) ? void 0 : async (characters) => {
|
|
67
|
+
const remaining = new Set([...characters].filter((character) => character !== "\0" && character !== "\n" && character !== "\r" && !glyphs.has(character)));
|
|
68
|
+
for (const provider of providers) {
|
|
69
|
+
if (!remaining.size) break;
|
|
70
|
+
const provided = provider instanceof Map ? provider : await provider([...remaining].join(""));
|
|
71
|
+
for (const character of remaining) {
|
|
72
|
+
const glyph = provided.get(character);
|
|
73
|
+
if (glyph) {
|
|
74
|
+
glyphs.set(character, glyph);
|
|
75
|
+
remaining.delete(character);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
} };
|
|
53
80
|
}
|
|
54
81
|
static async bitmap(provider, fontKey) {
|
|
55
82
|
const rows = provider.chars.map((row) => [...row]);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/assets/Fonts.ts"],"sourcesContent":["import { AssetKey } from \"./AssetKey\";\nimport { AssetLoader } from \"./AssetLoader\";\nimport { AssetParser } from \"./source/parser/AssetParsers\";\nimport { ModelTextures } from \"./ModelTextures\";\nimport { Caching } from \"../cache/Caching\";\nimport type { CompatCanvas } from \"../canvas/CanvasCompat\";\nimport type { MinecraftAsset } from \"../MinecraftAsset\";\n\n/** A glyph's source pixels and layout metrics. Glyphs without an image contribute spacing only. */\nexport interface BitmapGlyph {\n image?: CompatCanvas;\n /** Source rectangle in the bitmap sheet, before applying scale. */\n x: number;\n y: number;\n width: number;\n height: number;\n scale: number;\n ascent: number;\n advance: number;\n}\n\n/** Character-to-glyph lookup assembled from the active resource-pack fonts. */\nexport interface BitmapFont {\n glyphs: Map<string, BitmapGlyph>;\n}\n\ninterface ProviderOptions {\n filter?: { uniform?: boolean; jp?: boolean };\n}\n\ninterface BitmapProvider extends ProviderOptions {\n type: \"bitmap\" | \"minecraft:bitmap\";\n file: string;\n height?: number;\n ascent: number;\n chars: string[];\n}\n\ninterface SpaceProvider extends ProviderOptions {\n type: \"space\" | \"minecraft:space\";\n advances: Record<string, number>;\n}\n\ninterface ReferenceProvider extends ProviderOptions {\n type: \"reference\" | \"minecraft:reference\";\n id: string;\n}\n\ninterface UnsupportedProvider extends ProviderOptions {\n type: \"unihex\" | \"minecraft:unihex\" | \"ttf\" | \"minecraft:ttf\";\n}\n\ninterface FontAsset extends MinecraftAsset {\n providers: (BitmapProvider | SpaceProvider | ReferenceProvider | UnsupportedProvider)[];\n}\n\n/** Loads Minecraft bitmap, space, and reference font providers for GUI text. */\nexport class Fonts {\n\n /** Combines font definitions in source-priority order. Unsupported Unihex and TrueType providers are skipped. */\n public static async get(key: AssetKey | string = \"minecraft:default\"): Promise<BitmapFont> {\n const fontKey = typeof key === \"string\" ? AssetKey.parse(\"font\", key) : key;\n return (await Caching.fontCache.get(fontKey.serialize(), () => this.load(fontKey, [])))!;\n }\n\n private static relatedKey(assetType: string, id: string, origin: AssetKey): AssetKey {\n const key = AssetKey.parse(assetType, id);\n key.root = origin.root;\n return key;\n }\n\n private static async load(key: AssetKey, parents: string[]): Promise<BitmapFont> {\n const serialized = key.serialize();\n if (parents.includes(serialized)) throw new Error(`Cyclic font reference: ${key.toNamespacedString()}`);\n const stack = await AssetLoader.getAll<FontAsset>(key, AssetParser.JSON);\n if (stack.length === 0) throw new Error(`Could not load font ${key.toNamespacedString()}`);\n const glyphs = new Map<string, BitmapGlyph>();\n for (const asset of stack) {\n for (const provider of asset.providers) {\n if (provider.filter?.uniform || provider.filter?.jp) continue;\n let provided: Map<string, BitmapGlyph>;\n switch (provider.type) {\n case \"bitmap\": case \"minecraft:bitmap\":\n provided = await this.bitmap(provider, key);\n break;\n case \"space\": case \"minecraft:space\":\n provided = new Map(Object.entries(provider.advances).map(([character, advance]) => [character,\n { x: 0, y: 0, width: 0, height: 0, scale: 1, ascent: 0, advance }]));\n break;\n case \"reference\": case \"minecraft:reference\":\n provided = (await this.load(this.relatedKey(\"font\", provider.id, key), [...parents, serialized])).glyphs;\n break;\n default:\n continue;\n }\n for (const [character, glyph] of provided) {\n if (character !== \"\\0\" && !glyphs.has(character)) glyphs.set(character, glyph);\n }\n }\n }\n return { glyphs };\n }\n\n private static async bitmap(provider: BitmapProvider, fontKey: AssetKey): Promise<Map<string, BitmapGlyph>> {\n const rows = provider.chars.map(row => [...row]);\n const columns = rows[0]?.length;\n if (!columns || rows.some(row => row.length !== columns)) {\n throw new Error(`Invalid character grid in font ${fontKey.toNamespacedString()}`);\n }\n const key = this.relatedKey(\"textures\", provider.file, fontKey);\n const image = await ModelTextures.get(key);\n if (!image) throw new Error(`Could not load font texture ${key.toNamespacedString()}`);\n const width = Math.floor(image.width / columns), height = Math.floor(image.height / rows.length);\n if (!width || !height) throw new Error(`Font texture ${key.toNamespacedString()} is smaller than its character grid`);\n const scale = (provider.height ?? 8) / height;\n const pixels = image.data.getImageData(0, 0, image.width, image.height).data;\n const glyphs = new Map<string, BitmapGlyph>();\n rows.forEach((row, rowIndex) => row.forEach((character, columnIndex) => {\n if (character === \"\\0\") return;\n const x = columnIndex * width, y = rowIndex * height;\n let occupiedWidth = 0;\n for (let column = width - 1; column >= 0 && !occupiedWidth; column--) {\n for (let row = 0; row < height; row++) {\n if (pixels[((y + row) * image.width + x + column) * 4 + 3] !== 0) {\n occupiedWidth = column + 1;\n break;\n }\n }\n }\n glyphs.set(character, {\n image: (image.data as CanvasRenderingContext2D).canvas, x, y, width, height, scale,\n ascent: provider.ascent, advance: Math.floor(occupiedWidth * scale + 0.5) + 1\n });\n }));\n return glyphs;\n }\n\n}\n"],"mappings":"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","names":["row"]}
|
|
1
|
+
{"version":3,"sources":["../../../../src/assets/Fonts.ts"],"sourcesContent":["import { AssetKey } from \"./AssetKey\";\nimport { AssetLoader } from \"./AssetLoader\";\nimport { AssetParser } from \"./source/parser/AssetParsers\";\nimport { ModelTextures } from \"./ModelTextures\";\nimport { Caching } from \"../cache/Caching\";\nimport type { CompatCanvas } from \"../canvas/CanvasCompat\";\nimport type { MinecraftAsset } from \"../MinecraftAsset\";\nimport type { UnihexProvider } from \"./_fonts/Unihex\";\n\n/** A glyph's source pixels and layout metrics. Glyphs without an image contribute spacing only. */\nexport interface BitmapGlyph {\n image?: CompatCanvas;\n /** Source rectangle in the bitmap sheet, before applying scale. */\n x: number;\n y: number;\n width: number;\n height: number;\n scale: number;\n ascent: number;\n advance: number;\n /** Extra advance and drawing offset for bold text, in GUI pixels. Defaults to 1. */\n boldOffset?: number;\n /** Shadow displacement in GUI pixels. Defaults to 1. */\n shadowOffset?: number;\n}\n\n/** Character-to-glyph lookup assembled from the active resource-pack fonts. */\nexport interface BitmapFont {\n glyphs: Map<string, BitmapGlyph>;\n /** Resolves characters through the font providers before measuring or drawing them. */\n resolve?(characters: string): Promise<void>;\n}\n\ninterface ProviderOptions {\n filter?: { uniform?: boolean; jp?: boolean };\n}\n\ninterface BitmapProvider extends ProviderOptions {\n type: \"bitmap\" | \"minecraft:bitmap\";\n file: string;\n height?: number;\n ascent: number;\n chars: string[];\n}\n\ninterface SpaceProvider extends ProviderOptions {\n type: \"space\" | \"minecraft:space\";\n advances: Record<string, number>;\n}\n\ninterface ReferenceProvider extends ProviderOptions {\n type: \"reference\" | \"minecraft:reference\";\n id: string;\n}\n\ninterface UnsupportedProvider extends ProviderOptions {\n type: \"ttf\" | \"minecraft:ttf\";\n}\n\ninterface FontAsset extends MinecraftAsset {\n providers: (BitmapProvider | SpaceProvider | ReferenceProvider | (UnihexProvider & ProviderOptions) | UnsupportedProvider)[];\n}\n\n/** Loads Minecraft bitmap, Unihex, space, and reference font providers for GUI text. */\nexport class Fonts {\n\n /** Combines font definitions in source-priority order. TrueType providers are skipped. */\n public static async get(key: AssetKey | string = \"minecraft:default\"): Promise<BitmapFont> {\n const fontKey = typeof key === \"string\" ? AssetKey.parse(\"font\", key) : key;\n return (await Caching.fontCache.get(fontKey.serialize(), () => this.load(fontKey, [])))!;\n }\n\n private static relatedKey(assetType: string, id: string, origin: AssetKey): AssetKey {\n const key = AssetKey.parse(assetType, id);\n key.root = origin.root;\n return key;\n }\n\n private static async load(key: AssetKey, parents: string[]): Promise<BitmapFont> {\n const serialized = key.serialize();\n if (parents.includes(serialized)) throw new Error(`Cyclic font reference: ${key.toNamespacedString()}`);\n const stack = await AssetLoader.getAll<FontAsset>(key, AssetParser.JSON);\n if (stack.length === 0) throw new Error(`Could not load font ${key.toNamespacedString()}`);\n const glyphs = new Map<string, BitmapGlyph>();\n const providers: (Map<string, BitmapGlyph> | ((characters: string) => Promise<Map<string, BitmapGlyph>>))[] = [];\n for (const asset of stack) {\n for (const provider of asset.providers) {\n if (provider.filter?.uniform || provider.filter?.jp) continue;\n let provided: Map<string, BitmapGlyph>;\n switch (provider.type) {\n case \"bitmap\": case \"minecraft:bitmap\":\n provided = await this.bitmap(provider, key);\n break;\n case \"space\": case \"minecraft:space\":\n provided = new Map(Object.entries(provider.advances).map(([character, advance]) => [character,\n { x: 0, y: 0, width: 0, height: 0, scale: 1, ascent: 0, advance }]));\n break;\n case \"reference\": case \"minecraft:reference\":\n const reference = await this.load(this.relatedKey(\"font\", provider.id, key), [...parents, serialized]);\n if (reference.resolve) {\n providers.push(async characters => { await reference.resolve!(characters); return reference.glyphs; });\n continue;\n }\n provided = reference.glyphs;\n break;\n case \"unihex\": case \"minecraft:unihex\":\n providers.push(async characters => (await import(\"./_fonts/Unihex\")).loadUnihex(provider, key, characters));\n continue;\n default:\n continue;\n }\n if (providers.every(provider => provider instanceof Map)) for (const [character, glyph] of provided) {\n if (character !== \"\\0\" && !glyphs.has(character)) glyphs.set(character, glyph);\n }\n providers.push(provided);\n }\n }\n return { glyphs, resolve: providers.every(provider => provider instanceof Map) ? undefined : async characters => {\n const remaining = new Set([...characters].filter(character => character !== \"\\0\" && character !== \"\\n\"\n && character !== \"\\r\" && !glyphs.has(character)));\n for (const provider of providers) {\n if (!remaining.size) break;\n const provided = provider instanceof Map ? provider : await provider([...remaining].join(\"\"));\n for (const character of remaining) {\n const glyph = provided.get(character);\n if (glyph) { glyphs.set(character, glyph); remaining.delete(character); }\n }\n }\n } };\n }\n\n private static async bitmap(provider: BitmapProvider, fontKey: AssetKey): Promise<Map<string, BitmapGlyph>> {\n const rows = provider.chars.map(row => [...row]);\n const columns = rows[0]?.length;\n if (!columns || rows.some(row => row.length !== columns)) {\n throw new Error(`Invalid character grid in font ${fontKey.toNamespacedString()}`);\n }\n const key = this.relatedKey(\"textures\", provider.file, fontKey);\n const image = await ModelTextures.get(key);\n if (!image) throw new Error(`Could not load font texture ${key.toNamespacedString()}`);\n const width = Math.floor(image.width / columns), height = Math.floor(image.height / rows.length);\n if (!width || !height) throw new Error(`Font texture ${key.toNamespacedString()} is smaller than its character grid`);\n const scale = (provider.height ?? 8) / height;\n const pixels = image.data.getImageData(0, 0, image.width, image.height).data;\n const glyphs = new Map<string, BitmapGlyph>();\n rows.forEach((row, rowIndex) => row.forEach((character, columnIndex) => {\n if (character === \"\\0\") return;\n const x = columnIndex * width, y = rowIndex * height;\n let occupiedWidth = 0;\n for (let column = width - 1; column >= 0 && !occupiedWidth; column--) {\n for (let row = 0; row < height; row++) {\n if (pixels[((y + row) * image.width + x + column) * 4 + 3] !== 0) {\n occupiedWidth = column + 1;\n break;\n }\n }\n }\n glyphs.set(character, {\n image: (image.data as CanvasRenderingContext2D).canvas, x, y, width, height, scale,\n ascent: provider.ascent, advance: Math.floor(occupiedWidth * scale + 0.5) + 1\n });\n }));\n return glyphs;\n }\n\n}\n"],"mappings":";AAAA,SAAS,gBAAgB;AACzB,SAAS,mBAAmB;AAC5B,SAAS,mBAAmB;AAC5B,SAAS,qBAAqB;AAC9B,SAAS,eAAe;AA4DjB,IAAM,QAAN,MAAY;AAAA;AAAA,EAGf,aAAoB,IAAI,MAAyB,qBAA0C;AACvF,UAAM,UAAU,OAAO,QAAQ,WAAW,SAAS,MAAM,QAAQ,GAAG,IAAI;AACxE,WAAQ,MAAM,QAAQ,UAAU,IAAI,QAAQ,UAAU,GAAG,MAAM,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC;AAAA,EACzF;AAAA,EAEA,OAAe,WAAW,WAAmB,IAAY,QAA4B;AACjF,UAAM,MAAM,SAAS,MAAM,WAAW,EAAE;AACxC,QAAI,OAAO,OAAO;AAClB,WAAO;AAAA,EACX;AAAA,EAEA,aAAqB,KAAK,KAAe,SAAwC;AAC7E,UAAM,aAAa,IAAI,UAAU;AACjC,QAAI,QAAQ,SAAS,UAAU,EAAG,OAAM,IAAI,MAAM,0BAA0B,IAAI,mBAAmB,CAAC,EAAE;AACtG,UAAM,QAAQ,MAAM,YAAY,OAAkB,KAAK,YAAY,IAAI;AACvE,QAAI,MAAM,WAAW,EAAG,OAAM,IAAI,MAAM,uBAAuB,IAAI,mBAAmB,CAAC,EAAE;AACzF,UAAM,SAAS,oBAAI,IAAyB;AAC5C,UAAM,YAAwG,CAAC;AAC/G,eAAW,SAAS,OAAO;AACvB,iBAAW,YAAY,MAAM,WAAW;AACpC,YAAI,SAAS,QAAQ,WAAW,SAAS,QAAQ,GAAI;AACrD,YAAI;AACJ,gBAAQ,SAAS,MAAM;AAAA,UACnB,KAAK;AAAA,UAAU,KAAK;AAChB,uBAAW,MAAM,KAAK,OAAO,UAAU,GAAG;AAC1C;AAAA,UACJ,KAAK;AAAA,UAAS,KAAK;AACf,uBAAW,IAAI,IAAI,OAAO,QAAQ,SAAS,QAAQ,EAAE,IAAI,CAAC,CAAC,WAAW,OAAO,MAAM;AAAA,cAAC;AAAA,cAChF,EAAE,GAAG,GAAG,GAAG,GAAG,OAAO,GAAG,QAAQ,GAAG,OAAO,GAAG,QAAQ,GAAG,QAAQ;AAAA,YAAC,CAAC,CAAC;AACvE;AAAA,UACJ,KAAK;AAAA,UAAa,KAAK;AACnB,kBAAM,YAAY,MAAM,KAAK,KAAK,KAAK,WAAW,QAAQ,SAAS,IAAI,GAAG,GAAG,CAAC,GAAG,SAAS,UAAU,CAAC;AACrG,gBAAI,UAAU,SAAS;AACnB,wBAAU,KAAK,OAAM,eAAc;AAAE,sBAAM,UAAU,QAAS,UAAU;AAAG,uBAAO,UAAU;AAAA,cAAQ,CAAC;AACrG;AAAA,YACJ;AACA,uBAAW,UAAU;AACrB;AAAA,UACJ,KAAK;AAAA,UAAU,KAAK;AAChB,sBAAU,KAAK,OAAM,gBAAe,MAAM,OAAO,qBAAiB,GAAG,WAAW,UAAU,KAAK,UAAU,CAAC;AAC1G;AAAA,UACJ;AACI;AAAA,QACR;AACA,YAAI,UAAU,MAAM,CAAAA,cAAYA,qBAAoB,GAAG,EAAG,YAAW,CAAC,WAAW,KAAK,KAAK,UAAU;AACjG,cAAI,cAAc,QAAQ,CAAC,OAAO,IAAI,SAAS,EAAG,QAAO,IAAI,WAAW,KAAK;AAAA,QACjF;AACA,kBAAU,KAAK,QAAQ;AAAA,MAC3B;AAAA,IACJ;AACA,WAAO,EAAE,QAAQ,SAAS,UAAU,MAAM,cAAY,oBAAoB,GAAG,IAAI,SAAY,OAAM,eAAc;AAC7G,YAAM,YAAY,IAAI,IAAI,CAAC,GAAG,UAAU,EAAE,OAAO,eAAa,cAAc,QAAQ,cAAc,QAC3F,cAAc,QAAQ,CAAC,OAAO,IAAI,SAAS,CAAC,CAAC;AACpD,iBAAW,YAAY,WAAW;AAC9B,YAAI,CAAC,UAAU,KAAM;AACrB,cAAM,WAAW,oBAAoB,MAAM,WAAW,MAAM,SAAS,CAAC,GAAG,SAAS,EAAE,KAAK,EAAE,CAAC;AAC5F,mBAAW,aAAa,WAAW;AAC/B,gBAAM,QAAQ,SAAS,IAAI,SAAS;AACpC,cAAI,OAAO;AAAE,mBAAO,IAAI,WAAW,KAAK;AAAG,sBAAU,OAAO,SAAS;AAAA,UAAG;AAAA,QAC5E;AAAA,MACJ;AAAA,IACJ,EAAE;AAAA,EACN;AAAA,EAEA,aAAqB,OAAO,UAA0B,SAAsD;AACxG,UAAM,OAAO,SAAS,MAAM,IAAI,SAAO,CAAC,GAAG,GAAG,CAAC;AAC/C,UAAM,UAAU,KAAK,CAAC,GAAG;AACzB,QAAI,CAAC,WAAW,KAAK,KAAK,SAAO,IAAI,WAAW,OAAO,GAAG;AACtD,YAAM,IAAI,MAAM,kCAAkC,QAAQ,mBAAmB,CAAC,EAAE;AAAA,IACpF;AACA,UAAM,MAAM,KAAK,WAAW,YAAY,SAAS,MAAM,OAAO;AAC9D,UAAM,QAAQ,MAAM,cAAc,IAAI,GAAG;AACzC,QAAI,CAAC,MAAO,OAAM,IAAI,MAAM,+BAA+B,IAAI,mBAAmB,CAAC,EAAE;AACrF,UAAM,QAAQ,KAAK,MAAM,MAAM,QAAQ,OAAO,GAAG,SAAS,KAAK,MAAM,MAAM,SAAS,KAAK,MAAM;AAC/F,QAAI,CAAC,SAAS,CAAC,OAAQ,OAAM,IAAI,MAAM,gBAAgB,IAAI,mBAAmB,CAAC,qCAAqC;AACpH,UAAM,SAAS,SAAS,UAAU,KAAK;AACvC,UAAM,SAAS,MAAM,KAAK,aAAa,GAAG,GAAG,MAAM,OAAO,MAAM,MAAM,EAAE;AACxE,UAAM,SAAS,oBAAI,IAAyB;AAC5C,SAAK,QAAQ,CAAC,KAAK,aAAa,IAAI,QAAQ,CAAC,WAAW,gBAAgB;AACpE,UAAI,cAAc,KAAM;AACxB,YAAM,IAAI,cAAc,OAAO,IAAI,WAAW;AAC9C,UAAI,gBAAgB;AACpB,eAAS,SAAS,QAAQ,GAAG,UAAU,KAAK,CAAC,eAAe,UAAU;AAClE,iBAASC,OAAM,GAAGA,OAAM,QAAQA,QAAO;AACnC,cAAI,SAAS,IAAIA,QAAO,MAAM,QAAQ,IAAI,UAAU,IAAI,CAAC,MAAM,GAAG;AAC9D,4BAAgB,SAAS;AACzB;AAAA,UACJ;AAAA,QACJ;AAAA,MACJ;AACA,aAAO,IAAI,WAAW;AAAA,QAClB,OAAQ,MAAM,KAAkC;AAAA,QAAQ;AAAA,QAAG;AAAA,QAAG;AAAA,QAAO;AAAA,QAAQ;AAAA,QAC7E,QAAQ,SAAS;AAAA,QAAQ,SAAS,KAAK,MAAM,gBAAgB,QAAQ,GAAG,IAAI;AAAA,MAChF,CAAC;AAAA,IACL,CAAC,CAAC;AACF,WAAO;AAAA,EACX;AAEJ;","names":["provider","row"]}
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
// src/assets/_fonts/Unihex.ts
|
|
2
|
+
import { TextWriter, Uint8ArrayReader, ZipReader } from "@zip.js/zip.js";
|
|
3
|
+
import { AssetKey } from "../AssetKey.mjs";
|
|
4
|
+
import { AssetLoader } from "../AssetLoader.mjs";
|
|
5
|
+
import { DEFAULT_NAMESPACE } from "../Assets.mjs";
|
|
6
|
+
import { Caching } from "../../cache/Caching.mjs";
|
|
7
|
+
import { AssetParser } from "../source/parser/AssetParsers.mjs";
|
|
8
|
+
import { createCanvas } from "../../canvas/CanvasCompat.mjs";
|
|
9
|
+
var ATLAS_SIZE = 512;
|
|
10
|
+
var GLYPH_HEIGHT = 16;
|
|
11
|
+
var UnihexAtlas = class {
|
|
12
|
+
constructor() {
|
|
13
|
+
this.x = 0;
|
|
14
|
+
this.y = 0;
|
|
15
|
+
}
|
|
16
|
+
draw(glyph) {
|
|
17
|
+
const width = glyph.right - glyph.left + 1;
|
|
18
|
+
if (this.image && this.x + width > this.image.width) {
|
|
19
|
+
this.x = 0;
|
|
20
|
+
this.y += GLYPH_HEIGHT;
|
|
21
|
+
}
|
|
22
|
+
if (!this.image || this.y + GLYPH_HEIGHT > this.image.height || width > this.image.width) {
|
|
23
|
+
this.image = createCanvas(Math.max(ATLAS_SIZE, width), ATLAS_SIZE);
|
|
24
|
+
this.x = 0;
|
|
25
|
+
this.y = 0;
|
|
26
|
+
}
|
|
27
|
+
const context = this.image.getContext("2d");
|
|
28
|
+
const pixels = context.createImageData(width, GLYPH_HEIGHT);
|
|
29
|
+
for (let y = 0; y < GLYPH_HEIGHT; y++) {
|
|
30
|
+
for (let x = 0; x < width; x++) {
|
|
31
|
+
const column = glyph.left + x;
|
|
32
|
+
if (column < 0 || column >= glyph.bitWidth || !(glyph.rows[y] >>> glyph.bitWidth - column - 1 & 1)) continue;
|
|
33
|
+
pixels.data.fill(255, (y * width + x) * 4, (y * width + x + 1) * 4);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
const result = { image: this.image, x: this.x, y: this.y };
|
|
37
|
+
context.putImageData(pixels, this.x, this.y);
|
|
38
|
+
this.x += width;
|
|
39
|
+
return result;
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
function readHex(text, filename, glyphs) {
|
|
43
|
+
const lines = text.split("\n");
|
|
44
|
+
if (lines[lines.length - 1] === "") lines.pop();
|
|
45
|
+
lines.forEach((line, index) => {
|
|
46
|
+
const match = /^([0-9A-F]{4,6}):([0-9A-F]+)$/.exec(line);
|
|
47
|
+
if (!match || ![32, 64, 96, 128].includes(match[2].length)) {
|
|
48
|
+
throw new Error(`Invalid Unihex record in ${filename} at line ${index + 1}`);
|
|
49
|
+
}
|
|
50
|
+
const codepoint = parseInt(match[1], 16);
|
|
51
|
+
if (codepoint > 1114111) throw new Error(`Invalid Unihex codepoint in ${filename} at line ${index + 1}`);
|
|
52
|
+
const bitWidth = match[2].length / 4;
|
|
53
|
+
const rowLength = bitWidth / 4;
|
|
54
|
+
const rows = new Uint32Array(GLYPH_HEIGHT);
|
|
55
|
+
let mask = 0;
|
|
56
|
+
for (let y = 0; y < GLYPH_HEIGHT; y++) {
|
|
57
|
+
rows[y] = parseInt(match[2].slice(y * rowLength, (y + 1) * rowLength), 16);
|
|
58
|
+
mask |= rows[y];
|
|
59
|
+
}
|
|
60
|
+
let left = 0, right = bitWidth;
|
|
61
|
+
if (mask) {
|
|
62
|
+
while (!(mask >>> bitWidth - left - 1 & 1)) left++;
|
|
63
|
+
right = bitWidth - 1;
|
|
64
|
+
while (!(mask >>> bitWidth - right - 1 & 1)) right--;
|
|
65
|
+
}
|
|
66
|
+
glyphs.set(codepoint, { rows, bitWidth, left, right });
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
var atlases = /* @__PURE__ */ new WeakMap();
|
|
70
|
+
async function parseUnihex(key) {
|
|
71
|
+
try {
|
|
72
|
+
const asset = await AssetLoader.get(key, AssetParser.BINARY);
|
|
73
|
+
if (!asset) throw new Error(`Could not load Unihex archive ${key.toNamespacedString()}`);
|
|
74
|
+
const records = /* @__PURE__ */ new Map();
|
|
75
|
+
const reader = new ZipReader(new Uint8ArrayReader(asset.data), { useWebWorkers: false, useCompressionStream: false });
|
|
76
|
+
try {
|
|
77
|
+
for (const entry of await reader.getEntries()) {
|
|
78
|
+
if (!entry.directory && entry.filename.endsWith(".hex")) {
|
|
79
|
+
readHex(await entry.getData(new TextWriter(), { checkSignature: true }), entry.filename, records);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
} finally {
|
|
83
|
+
await reader.close();
|
|
84
|
+
}
|
|
85
|
+
const indices = new Int32Array(1114112).fill(-1);
|
|
86
|
+
const rows = new Uint32Array(records.size * GLYPH_HEIGHT), metrics = new Uint8Array(records.size * 3);
|
|
87
|
+
let index = 0;
|
|
88
|
+
for (const [codepoint, record] of records) {
|
|
89
|
+
indices[codepoint] = index;
|
|
90
|
+
rows.set(record.rows, index * GLYPH_HEIGHT);
|
|
91
|
+
metrics.set([record.bitWidth, record.left, record.right], index * 3);
|
|
92
|
+
index++;
|
|
93
|
+
}
|
|
94
|
+
return { indices, rows, metrics };
|
|
95
|
+
} catch (error) {
|
|
96
|
+
console.warn(`Could not load Unihex file ${key.toNamespacedString()}`, error);
|
|
97
|
+
return void 0;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
async function loadUnihex(provider, fontKey, characters) {
|
|
101
|
+
const origin = new AssetKey(DEFAULT_NAMESPACE, "", void 0, void 0, "assets", "", fontKey.root);
|
|
102
|
+
const key = AssetKey.parse("font", provider.hex_file, origin);
|
|
103
|
+
key.assetType = void 0;
|
|
104
|
+
const glyphs = /* @__PURE__ */ new Map();
|
|
105
|
+
let overrides;
|
|
106
|
+
try {
|
|
107
|
+
overrides = (provider.size_overrides ?? []).map((override) => {
|
|
108
|
+
const from = override.from.codePointAt(0), to = override.to.codePointAt(0);
|
|
109
|
+
if ([...override.from].length !== 1 || [...override.to].length !== 1 || from >= to || !Number.isInteger(override.left) || !Number.isInteger(override.right) || override.right < override.left) {
|
|
110
|
+
throw new Error(`Invalid Unihex size override in font ${fontKey.toNamespacedString()}`);
|
|
111
|
+
}
|
|
112
|
+
return { ...override, from, to };
|
|
113
|
+
});
|
|
114
|
+
} catch (error) {
|
|
115
|
+
console.warn(`Could not load Unihex file ${key.toNamespacedString()}`, error);
|
|
116
|
+
return glyphs;
|
|
117
|
+
}
|
|
118
|
+
const file = await Caching.unihexCache.get(key.serialize(), () => parseUnihex(key));
|
|
119
|
+
if (!file) return glyphs;
|
|
120
|
+
let atlas = atlases.get(provider);
|
|
121
|
+
if (!atlas) {
|
|
122
|
+
atlas = new UnihexAtlas();
|
|
123
|
+
atlases.set(provider, atlas);
|
|
124
|
+
}
|
|
125
|
+
for (const character of characters) {
|
|
126
|
+
const codepoint = character.codePointAt(0), index = file.indices[codepoint];
|
|
127
|
+
if (index < 0) continue;
|
|
128
|
+
const record = {
|
|
129
|
+
rows: file.rows.subarray(index * GLYPH_HEIGHT, (index + 1) * GLYPH_HEIGHT),
|
|
130
|
+
bitWidth: file.metrics[index * 3],
|
|
131
|
+
left: file.metrics[index * 3 + 1],
|
|
132
|
+
right: file.metrics[index * 3 + 2]
|
|
133
|
+
};
|
|
134
|
+
const override = overrides.find((range) => codepoint >= range.from && codepoint <= range.to);
|
|
135
|
+
if (override) {
|
|
136
|
+
record.left = override.left;
|
|
137
|
+
record.right = override.right;
|
|
138
|
+
}
|
|
139
|
+
const width = record.right - record.left + 1;
|
|
140
|
+
let rendered;
|
|
141
|
+
const render = () => rendered ?? (rendered = atlas.draw(record));
|
|
142
|
+
glyphs.set(character, {
|
|
143
|
+
get image() {
|
|
144
|
+
return render().image;
|
|
145
|
+
},
|
|
146
|
+
get x() {
|
|
147
|
+
return render().x;
|
|
148
|
+
},
|
|
149
|
+
get y() {
|
|
150
|
+
return render().y;
|
|
151
|
+
},
|
|
152
|
+
width,
|
|
153
|
+
height: GLYPH_HEIGHT,
|
|
154
|
+
scale: 0.5,
|
|
155
|
+
ascent: 7,
|
|
156
|
+
advance: Math.floor(width / 2) + 1,
|
|
157
|
+
boldOffset: 0.5,
|
|
158
|
+
shadowOffset: 0.5
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
return glyphs;
|
|
162
|
+
}
|
|
163
|
+
export {
|
|
164
|
+
loadUnihex
|
|
165
|
+
};
|
|
166
|
+
//# sourceMappingURL=Unihex.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../src/assets/_fonts/Unihex.ts"],"sourcesContent":["import { TextWriter, Uint8ArrayReader, ZipReader } from \"@zip.js/zip.js\";\nimport { AssetKey } from \"../AssetKey\";\nimport { AssetLoader } from \"../AssetLoader\";\nimport { DEFAULT_NAMESPACE } from \"../Assets\";\nimport { Caching } from \"../../cache/Caching\";\nimport { AssetParser } from \"../source/parser/AssetParsers\";\nimport { createCanvas, type CompatCanvas } from \"../../canvas/CanvasCompat\";\nimport type { BitmapGlyph } from \"../Fonts\";\nimport type { BinaryAsset } from \"../source/HostedAssetSource\";\n\nexport interface UnihexProvider {\n type: \"unihex\" | \"minecraft:unihex\";\n hex_file: string;\n size_overrides?: { from: string; to: string; left: number; right: number }[];\n}\n\ninterface HexGlyph {\n rows: Uint32Array;\n bitWidth: number;\n left: number;\n right: number;\n}\n\nexport interface UnihexFile {\n indices: Int32Array;\n rows: Uint32Array;\n metrics: Uint8Array;\n}\n\nconst ATLAS_SIZE = 512;\nconst GLYPH_HEIGHT = 16;\n\n/** Packs glyphs into shared pages only when their pixels or source rectangles are requested. */\nclass UnihexAtlas {\n private image?: CompatCanvas;\n private x = 0;\n private y = 0;\n\n public draw(glyph: HexGlyph): { image: CompatCanvas; x: number; y: number } {\n const width = glyph.right - glyph.left + 1;\n if (this.image && this.x + width > this.image.width) {\n this.x = 0;\n this.y += GLYPH_HEIGHT;\n }\n if (!this.image || this.y + GLYPH_HEIGHT > this.image.height || width > this.image.width) {\n this.image = createCanvas(Math.max(ATLAS_SIZE, width), ATLAS_SIZE);\n this.x = 0;\n this.y = 0;\n }\n const context = this.image.getContext(\"2d\") as CanvasRenderingContext2D;\n const pixels = context.createImageData(width, GLYPH_HEIGHT);\n for (let y = 0; y < GLYPH_HEIGHT; y++) {\n for (let x = 0; x < width; x++) {\n const column = glyph.left + x;\n if (column < 0 || column >= glyph.bitWidth || !(glyph.rows[y] >>> (glyph.bitWidth - column - 1) & 1)) continue;\n pixels.data.fill(255, (y * width + x) * 4, (y * width + x + 1) * 4);\n }\n }\n const result = { image: this.image, x: this.x, y: this.y };\n context.putImageData(pixels, this.x, this.y);\n this.x += width;\n return result;\n }\n}\n\nfunction readHex(text: string, filename: string, glyphs: Map<number, HexGlyph>): void {\n const lines = text.split(\"\\n\");\n if (lines[lines.length - 1] === \"\") lines.pop();\n lines.forEach((line, index) => {\n const match = /^([0-9A-F]{4,6}):([0-9A-F]+)$/.exec(line);\n if (!match || ![32, 64, 96, 128].includes(match[2].length)) {\n throw new Error(`Invalid Unihex record in ${filename} at line ${index + 1}`);\n }\n const codepoint = parseInt(match[1], 16);\n if (codepoint > 0x10ffff) throw new Error(`Invalid Unihex codepoint in ${filename} at line ${index + 1}`);\n const bitWidth = match[2].length / 4;\n const rowLength = bitWidth / 4;\n const rows = new Uint32Array(GLYPH_HEIGHT);\n let mask = 0;\n for (let y = 0; y < GLYPH_HEIGHT; y++) {\n rows[y] = parseInt(match[2].slice(y * rowLength, (y + 1) * rowLength), 16);\n mask |= rows[y];\n }\n let left = 0, right = bitWidth;\n if (mask) {\n while (!(mask >>> (bitWidth - left - 1) & 1)) left++;\n right = bitWidth - 1;\n while (!(mask >>> (bitWidth - right - 1) & 1)) right--;\n }\n glyphs.set(codepoint, { rows, bitWidth, left, right });\n });\n}\n\nconst atlases = new WeakMap<UnihexProvider, UnihexAtlas>();\n\nasync function parseUnihex(key: AssetKey): Promise<UnihexFile | undefined> {\n try {\n const asset = await AssetLoader.get<BinaryAsset>(key, AssetParser.BINARY);\n if (!asset) throw new Error(`Could not load Unihex archive ${key.toNamespacedString()}`);\n const records = new Map<number, HexGlyph>();\n const reader = new ZipReader(new Uint8ArrayReader(asset.data), { useWebWorkers: false, useCompressionStream: false });\n try {\n for (const entry of await reader.getEntries()) {\n if (!entry.directory && entry.filename.endsWith(\".hex\")) {\n readHex(await entry.getData!(new TextWriter(), { checkSignature: true }), entry.filename, records);\n }\n }\n } finally {\n await reader.close();\n }\n const indices = new Int32Array(0x110000).fill(-1);\n const rows = new Uint32Array(records.size * GLYPH_HEIGHT), metrics = new Uint8Array(records.size * 3);\n let index = 0;\n for (const [codepoint, record] of records) {\n indices[codepoint] = index;\n rows.set(record.rows, index * GLYPH_HEIGHT);\n metrics.set([record.bitWidth, record.left, record.right], index * 3);\n index++;\n }\n return { indices, rows, metrics };\n } catch (error) {\n console.warn(`Could not load Unihex file ${key.toNamespacedString()}`, error);\n return undefined;\n }\n}\n\n/** Resolves Unihex characters with vanilla metrics and lazily rasterized, half-resolution glyphs. */\nexport async function loadUnihex(provider: UnihexProvider, fontKey: AssetKey, characters: string): Promise<Map<string, BitmapGlyph>> {\n const origin = new AssetKey(DEFAULT_NAMESPACE, \"\", undefined, undefined, \"assets\", \"\", fontKey.root);\n const key = AssetKey.parse(\"font\", provider.hex_file, origin);\n // Archive references already include their directory beneath the namespace root.\n key.assetType = undefined;\n const glyphs = new Map<string, BitmapGlyph>();\n let overrides;\n try {\n overrides = (provider.size_overrides ?? []).map(override => {\n const from = override.from.codePointAt(0), to = override.to.codePointAt(0);\n if ([...override.from].length !== 1 || [...override.to].length !== 1 || from! >= to!\n || !Number.isInteger(override.left) || !Number.isInteger(override.right) || override.right < override.left) {\n throw new Error(`Invalid Unihex size override in font ${fontKey.toNamespacedString()}`);\n }\n return { ...override, from: from!, to: to! };\n });\n } catch (error) {\n console.warn(`Could not load Unihex file ${key.toNamespacedString()}`, error);\n return glyphs;\n }\n const file = await Caching.unihexCache.get(key.serialize(), () => parseUnihex(key));\n if (!file) return glyphs;\n let atlas = atlases.get(provider);\n if (!atlas) { atlas = new UnihexAtlas(); atlases.set(provider, atlas); }\n for (const character of characters) {\n const codepoint = character.codePointAt(0)!, index = file.indices[codepoint];\n if (index < 0) continue;\n const record = { rows: file.rows.subarray(index * GLYPH_HEIGHT, (index + 1) * GLYPH_HEIGHT),\n bitWidth: file.metrics[index * 3], left: file.metrics[index * 3 + 1], right: file.metrics[index * 3 + 2] };\n const override = overrides.find(range => codepoint >= range.from && codepoint <= range.to);\n if (override) { record.left = override.left; record.right = override.right; }\n const width = record.right - record.left + 1;\n let rendered: ReturnType<UnihexAtlas[\"draw\"]> | undefined;\n const render = () => rendered ??= atlas!.draw(record);\n glyphs.set(character, {\n get image() { return render().image; },\n get x() { return render().x; },\n get y() { return render().y; },\n width, height: GLYPH_HEIGHT, scale: 0.5, ascent: 7, advance: Math.floor(width / 2) + 1,\n boldOffset: 0.5, shadowOffset: 0.5\n });\n }\n return glyphs;\n}\n"],"mappings":"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","names":[]}
|
|
@@ -9,6 +9,7 @@ import { RequestError, Requests } from "../../request/index.mjs";
|
|
|
9
9
|
import { AssetLoader } from "../AssetLoader.mjs";
|
|
10
10
|
import { AssetParser } from "./parser/index.mjs";
|
|
11
11
|
import { merge } from "../../util/_internal/merge.mjs";
|
|
12
|
+
var BINARY_TIMEOUT = 6e4;
|
|
12
13
|
var p = prefix("HostedAssetSource");
|
|
13
14
|
var DEFAULT_OPTIONS = {
|
|
14
15
|
retryDefaults: true
|
|
@@ -149,6 +150,15 @@ _HostedAssetSource.JSON = {
|
|
|
149
150
|
return response.data;
|
|
150
151
|
}
|
|
151
152
|
};
|
|
153
|
+
_HostedAssetSource.BINARY = {
|
|
154
|
+
config(request) {
|
|
155
|
+
request.timeout = BINARY_TIMEOUT;
|
|
156
|
+
request.responseType = "arraybuffer";
|
|
157
|
+
},
|
|
158
|
+
parse(response) {
|
|
159
|
+
return { data: new Uint8Array(response.data) };
|
|
160
|
+
}
|
|
161
|
+
};
|
|
152
162
|
_HostedAssetSource.PARSER_MAP = /* @__PURE__ */ new Map([
|
|
153
163
|
[AssetParser.MODEL, _HostedAssetSource.MODEL],
|
|
154
164
|
[AssetParser.BLOCKSTATE, _HostedAssetSource.BLOCKSTATE],
|
|
@@ -156,7 +166,8 @@ _HostedAssetSource.PARSER_MAP = /* @__PURE__ */ new Map([
|
|
|
156
166
|
[AssetParser.NBT, _HostedAssetSource.NBT],
|
|
157
167
|
[AssetParser.IMAGE, _HostedAssetSource.IMAGE],
|
|
158
168
|
[AssetParser.LIST, _HostedAssetSource.LIST],
|
|
159
|
-
[AssetParser.JSON, _HostedAssetSource.JSON]
|
|
169
|
+
[AssetParser.JSON, _HostedAssetSource.JSON],
|
|
170
|
+
[AssetParser.BINARY, _HostedAssetSource.BINARY]
|
|
160
171
|
]);
|
|
161
172
|
var HostedAssetSource = _HostedAssetSource;
|
|
162
173
|
export {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../src/assets/source/HostedAssetSource.ts"],"sourcesContent":["import { AssetLoadError, AssetSource } from \"./AssetSource\";\nimport { BlockState, Model, TextureAsset } from \"../../model\";\nimport type { RequestConfig, RequestResponse } from \"../../request\";\nimport { Maybe, prefix } from \"../../util\";\nimport { MinecraftTextureMeta } from \"../../MinecraftTextureMeta\";\nimport { NBTAsset, NBTHelper } from \"../../nbt\";\nimport { ImageLoader } from \"../../image\";\nimport { ListAsset } from \"../../ListAsset\";\nimport { MinecraftAsset } from \"../../MinecraftAsset\";\nimport { AssetKey } from \"../AssetKey\";\nimport { DEFAULT_NAMESPACE } from \"../Assets\";\nimport { RequestError, Requests } from \"../../request\";\nimport { AssetLoader } from \"../AssetLoader\";\nimport { AssetParser } from \"./parser\";\nimport { ResponseParser } from \"./parser\";\nimport { merge } from \"../../util/_internal/merge\";\n\nconst p = prefix(\"HostedAssetSource\");\n\nconst DEFAULT_OPTIONS: HostedAssetSourceOptions = {\n retryDefaults: true\n}\n\n/** Loads assets over HTTP from a Minecraft directory tree rooted at the constructor's URL. */\nexport class HostedAssetSource extends AssetSource {\n\n static readonly MODEL: ResponseParser<Model> = {\n config(request: RequestConfig) {\n },\n parse(response: RequestResponse): Maybe<Model> {\n return response.data as Model;\n }\n }\n static readonly BLOCKSTATE: ResponseParser<BlockState> = {\n config(request: RequestConfig) {\n },\n parse(response: RequestResponse): Maybe<BlockState> {\n return response.data as BlockState;\n }\n }\n static readonly META: ResponseParser<MinecraftTextureMeta> = {\n config(request: RequestConfig) {\n // request.responseType = \"arraybuffer\";\n },\n parse(response: RequestResponse): Maybe<MinecraftTextureMeta> {\n return response.data as MinecraftTextureMeta;\n }\n }\n static readonly NBT: ResponseParser<NBTAsset> = {\n config(request: RequestConfig) {\n request.responseType = \"arraybuffer\";\n },\n parse(response: RequestResponse): Promise<Maybe<NBTAsset>> {\n return NBTHelper.fromBuffer(response.data);\n }\n }\n static readonly IMAGE: ResponseParser<TextureAsset> = {\n config(request: RequestConfig) {\n request.responseType = \"arraybuffer\";\n },\n async parse(response: RequestResponse): Promise<Maybe<TextureAsset>> {\n return await ImageLoader.processResponse(response) as TextureAsset;\n }\n }\n static readonly LIST: ResponseParser<ListAsset> = {\n config(request: RequestConfig) {\n },\n parse(response: RequestResponse): Maybe<ListAsset> {\n return response.data as ListAsset;\n }\n }\n static readonly JSON: ResponseParser<any> = {\n config(request: RequestConfig) {\n },\n parse(response: RequestResponse): Maybe<any> {\n return response.data;\n }\n }\n\n static readonly PARSER_MAP: Map<AssetParser, ResponseParser<any>> = new Map<AssetParser, ResponseParser<any>>([\n [AssetParser.MODEL, HostedAssetSource.MODEL],\n [AssetParser.BLOCKSTATE, HostedAssetSource.BLOCKSTATE],\n [AssetParser.META, HostedAssetSource.META],\n [AssetParser.NBT, HostedAssetSource.NBT],\n [AssetParser.IMAGE, HostedAssetSource.IMAGE],\n [AssetParser.LIST, HostedAssetSource.LIST],\n [AssetParser.JSON, HostedAssetSource.JSON],\n ]);\n\n /** Retries missing assets with the `minecraft` namespace and default root. Other failures reject. */\n public async loadOrRetryWithDefaults<T extends MinecraftAsset>(key: AssetKey, parser: ResponseParser<T>): Promise<Maybe<T>> {\n const direct = await this.load<T>(key, parser);\n if (typeof direct !== \"undefined\") {\n return direct;\n }\n if (key.namespace !== DEFAULT_NAMESPACE) {\n console.info(p, \"Retrying\", key, \"with default namespace\");\n // Try on the same host but with default minecraft: namespace\n const namespaceKey = new AssetKey(DEFAULT_NAMESPACE, key.path, key.assetType, key.type, key.rootType, key.extension, key.root);\n const namespaced = await this.load<T>(namespaceKey, parser);\n if (typeof namespaced !== \"undefined\") {\n return namespaced;\n }\n if ((typeof key.root !== \"undefined\" && key.root !== AssetLoader.ROOT) || (typeof this.root !== \"undefined\" && this.root !== AssetLoader.ROOT)) {\n console.info(p, \"Retrying\", key, \"with default root+namespace\");\n // Try both defaults\n const namespacedRootedKey = new AssetKey(DEFAULT_NAMESPACE, key.path, key.assetType, key.type, key.rootType, key.extension, AssetLoader.ROOT);\n const namespacedRooted = await this.load<T>(namespacedRootedKey, parser);\n if (typeof namespacedRooted !== \"undefined\") {\n return namespacedRooted;\n }\n }\n } else if ((typeof key.root !== \"undefined\" && key.root !== AssetLoader.ROOT) || (typeof this.root !== \"undefined\" && this.root !== AssetLoader.ROOT)) {\n console.info(p, \"Retrying\", key, \"with default root\");\n // Try on default root\n const rootKey = new AssetKey(key.namespace, key.path, key.assetType, key.type, key.rootType, key.extension, AssetLoader.ROOT);\n const rooted = await this.load<T>(rootKey, parser);\n if (typeof rooted !== \"undefined\") {\n return rooted;\n }\n }\n return undefined;\n }\n\n\n protected async load<T extends MinecraftAsset>(key: AssetKey, parser: ResponseParser<T>): Promise<Maybe<T>> {\n console.info(p, \"Loading\", key);\n const url = `${ this.assetBasePath(key) }${ key.type !== undefined ? key.type + '/' : '' }${ key.path }${ key.extension }`;\n console.debug(p, url);\n const request: RequestConfig = { url };\n try {\n parser.config(request);\n let response: RequestResponse;\n try {\n response = await Requests.mcAssetRequest(request);\n } catch (cause) {\n // HTTP 404 is the only request failure that permits source fallback.\n if (cause instanceof RequestError && cause.response?.status === 404) {\n return undefined;\n }\n throw cause;\n }\n if (response.data === undefined) {\n throw new Error(\"Asset response has no data\");\n }\n return await parser.parse(response);\n } catch (cause) {\n throw new AssetLoadError(this, key, request.url, cause);\n }\n }\n\n public assetBasePath(key: AssetKey) {\n return `${ key.root ?? this.root ?? AssetLoader.ROOT }/${ key.rootType !== undefined ? key.rootType + '/' : '' }${ key.namespace !== undefined ? key.namespace + '/' : '' }${ key.assetType !== undefined ? key.assetType + '/' : '' }`;\n }\n\n private readonly _root: string;\n private readonly _options: HostedAssetSourceOptions;\n\n /**\n * Creates a hosted source for {@link AssetLoader.addSource}.\n * Set `options.retryDefaults` to `false` to restrict lookups to the requested namespace and root.\n */\n public constructor(root: string, options?: Partial<HostedAssetSourceOptions>) {\n super();\n this._root = root;\n this._options = merge({}, DEFAULT_OPTIONS, options ?? {});\n }\n\n public get root(): string {\n return this._root;\n }\n\n public get cacheId(): string {\n return `hosted:${this._root}`;\n }\n\n public get options(): HostedAssetSourceOptions {\n return this._options;\n }\n\n public get<T extends MinecraftAsset>(key: AssetKey, parser: AssetParser): Promise<Maybe<T>> {\n const responseParser = HostedAssetSource.PARSER_MAP.get(parser) as ResponseParser<T>;\n if (this.options.retryDefaults && !(key.rootType === undefined && key.namespace === \"minerender-data\")) {\n return this.loadOrRetryWithDefaults(key, responseParser);\n }\n return this.load(key, responseParser);\n }\n\n}\n\ninterface HostedAssetSourceOptions {\n retryDefaults: boolean;\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../../../src/assets/source/HostedAssetSource.ts"],"sourcesContent":["import { AssetLoadError, AssetSource } from \"./AssetSource\";\nimport { BlockState, Model, TextureAsset } from \"../../model\";\nimport type { RequestConfig, RequestResponse } from \"../../request\";\nimport { Maybe, prefix } from \"../../util\";\nimport { MinecraftTextureMeta } from \"../../MinecraftTextureMeta\";\nimport { NBTAsset, NBTHelper } from \"../../nbt\";\nimport { ImageLoader } from \"../../image\";\nimport { ListAsset } from \"../../ListAsset\";\nimport { MinecraftAsset } from \"../../MinecraftAsset\";\nimport { AssetKey } from \"../AssetKey\";\nimport { DEFAULT_NAMESPACE } from \"../Assets\";\nimport { RequestError, Requests } from \"../../request\";\nimport { AssetLoader } from \"../AssetLoader\";\nimport { AssetParser } from \"./parser\";\nimport { ResponseParser } from \"./parser\";\nimport { merge } from \"../../util/_internal/merge\";\n\nconst BINARY_TIMEOUT = 60_000;\n\nconst p = prefix(\"HostedAssetSource\");\n\nconst DEFAULT_OPTIONS: HostedAssetSourceOptions = {\n retryDefaults: true\n}\n\n/** Loads assets over HTTP from a Minecraft directory tree rooted at the constructor's URL. */\nexport class HostedAssetSource extends AssetSource {\n\n static readonly MODEL: ResponseParser<Model> = {\n config(request: RequestConfig) {\n },\n parse(response: RequestResponse): Maybe<Model> {\n return response.data as Model;\n }\n }\n static readonly BLOCKSTATE: ResponseParser<BlockState> = {\n config(request: RequestConfig) {\n },\n parse(response: RequestResponse): Maybe<BlockState> {\n return response.data as BlockState;\n }\n }\n static readonly META: ResponseParser<MinecraftTextureMeta> = {\n config(request: RequestConfig) {\n // request.responseType = \"arraybuffer\";\n },\n parse(response: RequestResponse): Maybe<MinecraftTextureMeta> {\n return response.data as MinecraftTextureMeta;\n }\n }\n static readonly NBT: ResponseParser<NBTAsset> = {\n config(request: RequestConfig) {\n request.responseType = \"arraybuffer\";\n },\n parse(response: RequestResponse): Promise<Maybe<NBTAsset>> {\n return NBTHelper.fromBuffer(response.data);\n }\n }\n static readonly IMAGE: ResponseParser<TextureAsset> = {\n config(request: RequestConfig) {\n request.responseType = \"arraybuffer\";\n },\n async parse(response: RequestResponse): Promise<Maybe<TextureAsset>> {\n return await ImageLoader.processResponse(response) as TextureAsset;\n }\n }\n static readonly LIST: ResponseParser<ListAsset> = {\n config(request: RequestConfig) {\n },\n parse(response: RequestResponse): Maybe<ListAsset> {\n return response.data as ListAsset;\n }\n }\n static readonly JSON: ResponseParser<any> = {\n config(request: RequestConfig) {\n },\n parse(response: RequestResponse): Maybe<any> {\n return response.data;\n }\n }\n static readonly BINARY: ResponseParser<BinaryAsset> = {\n config(request: RequestConfig) {\n request.timeout = BINARY_TIMEOUT;\n request.responseType = \"arraybuffer\";\n },\n parse(response: RequestResponse): BinaryAsset {\n return { data: new Uint8Array(response.data as ArrayBuffer) };\n }\n }\n\n static readonly PARSER_MAP: Map<AssetParser, ResponseParser<any>> = new Map<AssetParser, ResponseParser<any>>([\n [AssetParser.MODEL, HostedAssetSource.MODEL],\n [AssetParser.BLOCKSTATE, HostedAssetSource.BLOCKSTATE],\n [AssetParser.META, HostedAssetSource.META],\n [AssetParser.NBT, HostedAssetSource.NBT],\n [AssetParser.IMAGE, HostedAssetSource.IMAGE],\n [AssetParser.LIST, HostedAssetSource.LIST],\n [AssetParser.JSON, HostedAssetSource.JSON],\n [AssetParser.BINARY, HostedAssetSource.BINARY],\n ]);\n\n /** Retries missing assets with the `minecraft` namespace and default root. Other failures reject. */\n public async loadOrRetryWithDefaults<T extends MinecraftAsset>(key: AssetKey, parser: ResponseParser<T>): Promise<Maybe<T>> {\n const direct = await this.load<T>(key, parser);\n if (typeof direct !== \"undefined\") {\n return direct;\n }\n if (key.namespace !== DEFAULT_NAMESPACE) {\n console.info(p, \"Retrying\", key, \"with default namespace\");\n // Try on the same host but with default minecraft: namespace\n const namespaceKey = new AssetKey(DEFAULT_NAMESPACE, key.path, key.assetType, key.type, key.rootType, key.extension, key.root);\n const namespaced = await this.load<T>(namespaceKey, parser);\n if (typeof namespaced !== \"undefined\") {\n return namespaced;\n }\n if ((typeof key.root !== \"undefined\" && key.root !== AssetLoader.ROOT) || (typeof this.root !== \"undefined\" && this.root !== AssetLoader.ROOT)) {\n console.info(p, \"Retrying\", key, \"with default root+namespace\");\n // Try both defaults\n const namespacedRootedKey = new AssetKey(DEFAULT_NAMESPACE, key.path, key.assetType, key.type, key.rootType, key.extension, AssetLoader.ROOT);\n const namespacedRooted = await this.load<T>(namespacedRootedKey, parser);\n if (typeof namespacedRooted !== \"undefined\") {\n return namespacedRooted;\n }\n }\n } else if ((typeof key.root !== \"undefined\" && key.root !== AssetLoader.ROOT) || (typeof this.root !== \"undefined\" && this.root !== AssetLoader.ROOT)) {\n console.info(p, \"Retrying\", key, \"with default root\");\n // Try on default root\n const rootKey = new AssetKey(key.namespace, key.path, key.assetType, key.type, key.rootType, key.extension, AssetLoader.ROOT);\n const rooted = await this.load<T>(rootKey, parser);\n if (typeof rooted !== \"undefined\") {\n return rooted;\n }\n }\n return undefined;\n }\n\n\n protected async load<T extends MinecraftAsset>(key: AssetKey, parser: ResponseParser<T>): Promise<Maybe<T>> {\n console.info(p, \"Loading\", key);\n const url = `${ this.assetBasePath(key) }${ key.type !== undefined ? key.type + '/' : '' }${ key.path }${ key.extension }`;\n console.debug(p, url);\n const request: RequestConfig = { url };\n try {\n parser.config(request);\n let response: RequestResponse;\n try {\n response = await Requests.mcAssetRequest(request);\n } catch (cause) {\n // HTTP 404 is the only request failure that permits source fallback.\n if (cause instanceof RequestError && cause.response?.status === 404) {\n return undefined;\n }\n throw cause;\n }\n if (response.data === undefined) {\n throw new Error(\"Asset response has no data\");\n }\n return await parser.parse(response);\n } catch (cause) {\n throw new AssetLoadError(this, key, request.url, cause);\n }\n }\n\n public assetBasePath(key: AssetKey) {\n return `${ key.root ?? this.root ?? AssetLoader.ROOT }/${ key.rootType !== undefined ? key.rootType + '/' : '' }${ key.namespace !== undefined ? key.namespace + '/' : '' }${ key.assetType !== undefined ? key.assetType + '/' : '' }`;\n }\n\n private readonly _root: string;\n private readonly _options: HostedAssetSourceOptions;\n\n /**\n * Creates a hosted source for {@link AssetLoader.addSource}.\n * Set `options.retryDefaults` to `false` to restrict lookups to the requested namespace and root.\n */\n public constructor(root: string, options?: Partial<HostedAssetSourceOptions>) {\n super();\n this._root = root;\n this._options = merge({}, DEFAULT_OPTIONS, options ?? {});\n }\n\n public get root(): string {\n return this._root;\n }\n\n public get cacheId(): string {\n return `hosted:${this._root}`;\n }\n\n public get options(): HostedAssetSourceOptions {\n return this._options;\n }\n\n public get<T extends MinecraftAsset>(key: AssetKey, parser: AssetParser): Promise<Maybe<T>> {\n const responseParser = HostedAssetSource.PARSER_MAP.get(parser) as ResponseParser<T>;\n if (this.options.retryDefaults && !(key.rootType === undefined && key.namespace === \"minerender-data\")) {\n return this.loadOrRetryWithDefaults(key, responseParser);\n }\n return this.load(key, responseParser);\n }\n\n}\n\ninterface HostedAssetSourceOptions {\n retryDefaults: boolean;\n}\n\n/** Encoded asset bytes loaded without JSON or image decoding. */\nexport interface BinaryAsset extends MinecraftAsset {\n data: Uint8Array;\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../../src/assets/source/parser/AssetParsers.ts"],"sourcesContent":["export enum AssetParser {\n\n MODEL = \"model\",\n BLOCKSTATE = \"blockstate\",\n META = \"meta\",\n NBT = \"nbt\",\n IMAGE = \"image\",\n LIST = \"list\",\n JSON = \"json\",\n\n}"],"mappings":";AAAO,IAAK,cAAL,kBAAKA,iBAAL;AAEH,EAAAA,aAAA,WAAQ;AACR,EAAAA,aAAA,gBAAa;AACb,EAAAA,aAAA,UAAO;AACP,EAAAA,aAAA,SAAM;AACN,EAAAA,aAAA,WAAQ;AACR,EAAAA,aAAA,UAAO;AACP,EAAAA,aAAA,UAAO;
|
|
1
|
+
{"version":3,"sources":["../../../../../../src/assets/source/parser/AssetParsers.ts"],"sourcesContent":["export enum AssetParser {\n\n MODEL = \"model\",\n BLOCKSTATE = \"blockstate\",\n META = \"meta\",\n NBT = \"nbt\",\n IMAGE = \"image\",\n LIST = \"list\",\n JSON = \"json\",\n BINARY = \"binary\",\n\n}\n"],"mappings":";AAAO,IAAK,cAAL,kBAAKA,iBAAL;AAEH,EAAAA,aAAA,WAAQ;AACR,EAAAA,aAAA,gBAAa;AACb,EAAAA,aAAA,UAAO;AACP,EAAAA,aAAA,SAAM;AACN,EAAAA,aAAA,WAAQ;AACR,EAAAA,aAAA,UAAO;AACP,EAAAA,aAAA,UAAO;AACP,EAAAA,aAAA,YAAS;AATD,SAAAA;AAAA,GAAA;","names":["AssetParser"]}
|
|
@@ -33,6 +33,7 @@ var _Caching = class _Caching {
|
|
|
33
33
|
this.entityAnimationCache,
|
|
34
34
|
this.blockEntityIndexCache,
|
|
35
35
|
this.fontCache,
|
|
36
|
+
this.unihexCache,
|
|
36
37
|
this.bannerPatternCache,
|
|
37
38
|
this.mineRenderDataCache,
|
|
38
39
|
this.usernameUuidCache,
|
|
@@ -86,6 +87,7 @@ _Caching.entityModelCache = _Caching.createAssetCache();
|
|
|
86
87
|
_Caching.entityTextureCache = _Caching.createAssetCache();
|
|
87
88
|
_Caching.entityAnimationCache = _Caching.createAssetCache();
|
|
88
89
|
_Caching.blockEntityIndexCache = _Caching.createAssetCache();
|
|
90
|
+
_Caching.unihexCache = _Caching.createAssetCache();
|
|
89
91
|
_Caching.fontCache = _Caching.createAssetCache();
|
|
90
92
|
_Caching.bannerPatternCache = _Caching.createAssetCache();
|
|
91
93
|
_Caching.mineRenderDataCache = _Caching.createAssetCache();
|