minerender 2.1.0-alpha.131 → 2.1.0-alpha.133

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.
@@ -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. Unsupported Unihex and TrueType providers are skipped. */
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
- provided = (await this.load(this.relatedKey("font", provider.id, key), [...parents, serialized])).glyphs;
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":"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","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":";AAAA,SAAS,YAAY,kBAAkB,iBAAiB;AACxD,SAAS,gBAAgB;AACzB,SAAS,mBAAmB;AAC5B,SAAS,yBAAyB;AAClC,SAAS,eAAe;AACxB,SAAS,mBAAmB;AAC5B,SAAS,oBAAuC;AAuBhD,IAAM,aAAa;AACnB,IAAM,eAAe;AAGrB,IAAM,cAAN,MAAkB;AAAA,EAAlB;AAEI,SAAQ,IAAI;AACZ,SAAQ,IAAI;AAAA;AAAA,EAEL,KAAK,OAAgE;AACxE,UAAM,QAAQ,MAAM,QAAQ,MAAM,OAAO;AACzC,QAAI,KAAK,SAAS,KAAK,IAAI,QAAQ,KAAK,MAAM,OAAO;AACjD,WAAK,IAAI;AACT,WAAK,KAAK;AAAA,IACd;AACA,QAAI,CAAC,KAAK,SAAS,KAAK,IAAI,eAAe,KAAK,MAAM,UAAU,QAAQ,KAAK,MAAM,OAAO;AACtF,WAAK,QAAQ,aAAa,KAAK,IAAI,YAAY,KAAK,GAAG,UAAU;AACjE,WAAK,IAAI;AACT,WAAK,IAAI;AAAA,IACb;AACA,UAAM,UAAU,KAAK,MAAM,WAAW,IAAI;AAC1C,UAAM,SAAS,QAAQ,gBAAgB,OAAO,YAAY;AAC1D,aAAS,IAAI,GAAG,IAAI,cAAc,KAAK;AACnC,eAAS,IAAI,GAAG,IAAI,OAAO,KAAK;AAC5B,cAAM,SAAS,MAAM,OAAO;AAC5B,YAAI,SAAS,KAAK,UAAU,MAAM,YAAY,EAAE,MAAM,KAAK,CAAC,MAAO,MAAM,WAAW,SAAS,IAAK,GAAI;AACtG,eAAO,KAAK,KAAK,MAAM,IAAI,QAAQ,KAAK,IAAI,IAAI,QAAQ,IAAI,KAAK,CAAC;AAAA,MACtE;AAAA,IACJ;AACA,UAAM,SAAS,EAAE,OAAO,KAAK,OAAO,GAAG,KAAK,GAAG,GAAG,KAAK,EAAE;AACzD,YAAQ,aAAa,QAAQ,KAAK,GAAG,KAAK,CAAC;AAC3C,SAAK,KAAK;AACV,WAAO;AAAA,EACX;AACJ;AAEA,SAAS,QAAQ,MAAc,UAAkB,QAAqC;AAClF,QAAM,QAAQ,KAAK,MAAM,IAAI;AAC7B,MAAI,MAAM,MAAM,SAAS,CAAC,MAAM,GAAI,OAAM,IAAI;AAC9C,QAAM,QAAQ,CAAC,MAAM,UAAU;AAC3B,UAAM,QAAQ,gCAAgC,KAAK,IAAI;AACvD,QAAI,CAAC,SAAS,CAAC,CAAC,IAAI,IAAI,IAAI,GAAG,EAAE,SAAS,MAAM,CAAC,EAAE,MAAM,GAAG;AACxD,YAAM,IAAI,MAAM,4BAA4B,QAAQ,YAAY,QAAQ,CAAC,EAAE;AAAA,IAC/E;AACA,UAAM,YAAY,SAAS,MAAM,CAAC,GAAG,EAAE;AACvC,QAAI,YAAY,QAAU,OAAM,IAAI,MAAM,+BAA+B,QAAQ,YAAY,QAAQ,CAAC,EAAE;AACxG,UAAM,WAAW,MAAM,CAAC,EAAE,SAAS;AACnC,UAAM,YAAY,WAAW;AAC7B,UAAM,OAAO,IAAI,YAAY,YAAY;AACzC,QAAI,OAAO;AACX,aAAS,IAAI,GAAG,IAAI,cAAc,KAAK;AACnC,WAAK,CAAC,IAAI,SAAS,MAAM,CAAC,EAAE,MAAM,IAAI,YAAY,IAAI,KAAK,SAAS,GAAG,EAAE;AACzE,cAAQ,KAAK,CAAC;AAAA,IAClB;AACA,QAAI,OAAO,GAAG,QAAQ;AACtB,QAAI,MAAM;AACN,aAAO,EAAE,SAAU,WAAW,OAAO,IAAK,GAAI;AAC9C,cAAQ,WAAW;AACnB,aAAO,EAAE,SAAU,WAAW,QAAQ,IAAK,GAAI;AAAA,IACnD;AACA,WAAO,IAAI,WAAW,EAAE,MAAM,UAAU,MAAM,MAAM,CAAC;AAAA,EACzD,CAAC;AACL;AAEA,IAAM,UAAU,oBAAI,QAAqC;AAEzD,eAAe,YAAY,KAAgD;AACvE,MAAI;AACA,UAAM,QAAQ,MAAM,YAAY,IAAiB,KAAK,YAAY,MAAM;AACxE,QAAI,CAAC,MAAO,OAAM,IAAI,MAAM,iCAAiC,IAAI,mBAAmB,CAAC,EAAE;AACvF,UAAM,UAAU,oBAAI,IAAsB;AAC1C,UAAM,SAAS,IAAI,UAAU,IAAI,iBAAiB,MAAM,IAAI,GAAG,EAAE,eAAe,OAAO,sBAAsB,MAAM,CAAC;AACpH,QAAI;AACA,iBAAW,SAAS,MAAM,OAAO,WAAW,GAAG;AAC3C,YAAI,CAAC,MAAM,aAAa,MAAM,SAAS,SAAS,MAAM,GAAG;AACrD,kBAAQ,MAAM,MAAM,QAAS,IAAI,WAAW,GAAG,EAAE,gBAAgB,KAAK,CAAC,GAAG,MAAM,UAAU,OAAO;AAAA,QACrG;AAAA,MACJ;AAAA,IACJ,UAAE;AACE,YAAM,OAAO,MAAM;AAAA,IACvB;AACA,UAAM,UAAU,IAAI,WAAW,OAAQ,EAAE,KAAK,EAAE;AAChD,UAAM,OAAO,IAAI,YAAY,QAAQ,OAAO,YAAY,GAAG,UAAU,IAAI,WAAW,QAAQ,OAAO,CAAC;AACpG,QAAI,QAAQ;AACZ,eAAW,CAAC,WAAW,MAAM,KAAK,SAAS;AACvC,cAAQ,SAAS,IAAI;AACrB,WAAK,IAAI,OAAO,MAAM,QAAQ,YAAY;AAC1C,cAAQ,IAAI,CAAC,OAAO,UAAU,OAAO,MAAM,OAAO,KAAK,GAAG,QAAQ,CAAC;AACnE;AAAA,IACJ;AACA,WAAO,EAAE,SAAS,MAAM,QAAQ;AAAA,EACpC,SAAS,OAAO;AACZ,YAAQ,KAAK,8BAA8B,IAAI,mBAAmB,CAAC,IAAI,KAAK;AAC5E,WAAO;AAAA,EACX;AACJ;AAGA,eAAsB,WAAW,UAA0B,SAAmB,YAAuD;AACjI,QAAM,SAAS,IAAI,SAAS,mBAAmB,IAAI,QAAW,QAAW,UAAU,IAAI,QAAQ,IAAI;AACnG,QAAM,MAAM,SAAS,MAAM,QAAQ,SAAS,UAAU,MAAM;AAE5D,MAAI,YAAY;AAChB,QAAM,SAAS,oBAAI,IAAyB;AAC5C,MAAI;AACJ,MAAI;AACA,iBAAa,SAAS,kBAAkB,CAAC,GAAG,IAAI,cAAY;AACxD,YAAM,OAAO,SAAS,KAAK,YAAY,CAAC,GAAG,KAAK,SAAS,GAAG,YAAY,CAAC;AACzE,UAAI,CAAC,GAAG,SAAS,IAAI,EAAE,WAAW,KAAK,CAAC,GAAG,SAAS,EAAE,EAAE,WAAW,KAAK,QAAS,MAC1E,CAAC,OAAO,UAAU,SAAS,IAAI,KAAK,CAAC,OAAO,UAAU,SAAS,KAAK,KAAK,SAAS,QAAQ,SAAS,MAAM;AAC5G,cAAM,IAAI,MAAM,wCAAwC,QAAQ,mBAAmB,CAAC,EAAE;AAAA,MAC1F;AACA,aAAO,EAAE,GAAG,UAAU,MAAa,GAAQ;AAAA,IAC/C,CAAC;AAAA,EACL,SAAS,OAAO;AACZ,YAAQ,KAAK,8BAA8B,IAAI,mBAAmB,CAAC,IAAI,KAAK;AAC5E,WAAO;AAAA,EACX;AACA,QAAM,OAAO,MAAM,QAAQ,YAAY,IAAI,IAAI,UAAU,GAAG,MAAM,YAAY,GAAG,CAAC;AAClF,MAAI,CAAC,KAAM,QAAO;AAClB,MAAI,QAAQ,QAAQ,IAAI,QAAQ;AAChC,MAAI,CAAC,OAAO;AAAE,YAAQ,IAAI,YAAY;AAAG,YAAQ,IAAI,UAAU,KAAK;AAAA,EAAG;AACvE,aAAW,aAAa,YAAY;AAChC,UAAM,YAAY,UAAU,YAAY,CAAC,GAAI,QAAQ,KAAK,QAAQ,SAAS;AAC3E,QAAI,QAAQ,EAAG;AACf,UAAM,SAAS;AAAA,MAAE,MAAM,KAAK,KAAK,SAAS,QAAQ,eAAe,QAAQ,KAAK,YAAY;AAAA,MACtF,UAAU,KAAK,QAAQ,QAAQ,CAAC;AAAA,MAAG,MAAM,KAAK,QAAQ,QAAQ,IAAI,CAAC;AAAA,MAAG,OAAO,KAAK,QAAQ,QAAQ,IAAI,CAAC;AAAA,IAAE;AAC7G,UAAM,WAAW,UAAU,KAAK,WAAS,aAAa,MAAM,QAAQ,aAAa,MAAM,EAAE;AACzF,QAAI,UAAU;AAAE,aAAO,OAAO,SAAS;AAAM,aAAO,QAAQ,SAAS;AAAA,IAAO;AAC5E,UAAM,QAAQ,OAAO,QAAQ,OAAO,OAAO;AAC3C,QAAI;AACJ,UAAM,SAAS,MAAM,wBAAa,MAAO,KAAK,MAAM;AACpD,WAAO,IAAI,WAAW;AAAA,MAClB,IAAI,QAAQ;AAAE,eAAO,OAAO,EAAE;AAAA,MAAO;AAAA,MACrC,IAAI,IAAI;AAAE,eAAO,OAAO,EAAE;AAAA,MAAG;AAAA,MAC7B,IAAI,IAAI;AAAE,eAAO,OAAO,EAAE;AAAA,MAAG;AAAA,MAC7B;AAAA,MAAO,QAAQ;AAAA,MAAc,OAAO;AAAA,MAAK,QAAQ;AAAA,MAAG,SAAS,KAAK,MAAM,QAAQ,CAAC,IAAI;AAAA,MACrF,YAAY;AAAA,MAAK,cAAc;AAAA,IACnC,CAAC;AAAA,EACL;AACA,SAAO;AACX;","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":";AAAA,SAAS,gBAAgB,mBAAmB;AAG5C,SAAgB,cAAc;AAE9B,SAAmB,iBAAiB;AACpC,SAAS,mBAAmB;AAG5B,SAAS,gBAAgB;AACzB,SAAS,yBAAyB;AAClC,SAAS,cAAc,gBAAgB;AACvC,SAAS,mBAAmB;AAC5B,SAAS,mBAAmB;AAE5B,SAAS,aAAa;AAEtB,IAAM,IAAI,OAAO,mBAAmB;AAEpC,IAAM,kBAA4C;AAAA,EAC9C,eAAe;AACnB;AAGO,IAAM,qBAAN,MAAM,2BAA0B,YAAY;AAAA;AAAA,EAkE/C,MAAa,wBAAkD,KAAe,QAA8C;AACxH,UAAM,SAAS,MAAM,KAAK,KAAQ,KAAK,MAAM;AAC7C,QAAI,OAAO,WAAW,aAAa;AAC/B,aAAO;AAAA,IACX;AACA,QAAI,IAAI,cAAc,mBAAmB;AACrC,cAAQ,KAAK,GAAG,YAAY,KAAK,wBAAwB;AAEzD,YAAM,eAAe,IAAI,SAAS,mBAAmB,IAAI,MAAM,IAAI,WAAW,IAAI,MAAM,IAAI,UAAU,IAAI,WAAW,IAAI,IAAI;AAC7H,YAAM,aAAa,MAAM,KAAK,KAAQ,cAAc,MAAM;AAC1D,UAAI,OAAO,eAAe,aAAa;AACnC,eAAO;AAAA,MACX;AACA,UAAK,OAAO,IAAI,SAAS,eAAe,IAAI,SAAS,YAAY,QAAU,OAAO,KAAK,SAAS,eAAe,KAAK,SAAS,YAAY,MAAO;AAC5I,gBAAQ,KAAK,GAAG,YAAY,KAAK,6BAA6B;AAE9D,cAAM,sBAAsB,IAAI,SAAS,mBAAmB,IAAI,MAAM,IAAI,WAAW,IAAI,MAAM,IAAI,UAAU,IAAI,WAAW,YAAY,IAAI;AAC5I,cAAM,mBAAmB,MAAM,KAAK,KAAQ,qBAAqB,MAAM;AACvE,YAAI,OAAO,qBAAqB,aAAa;AACzC,iBAAO;AAAA,QACX;AAAA,MACJ;AAAA,IACJ,WAAY,OAAO,IAAI,SAAS,eAAe,IAAI,SAAS,YAAY,QAAU,OAAO,KAAK,SAAS,eAAe,KAAK,SAAS,YAAY,MAAO;AACnJ,cAAQ,KAAK,GAAG,YAAY,KAAK,mBAAmB;AAEpD,YAAM,UAAU,IAAI,SAAS,IAAI,WAAW,IAAI,MAAM,IAAI,WAAW,IAAI,MAAM,IAAI,UAAU,IAAI,WAAW,YAAY,IAAI;AAC5H,YAAM,SAAS,MAAM,KAAK,KAAQ,SAAS,MAAM;AACjD,UAAI,OAAO,WAAW,aAAa;AAC/B,eAAO;AAAA,MACX;AAAA,IACJ;AACA,WAAO;AAAA,EACX;AAAA,EAGA,MAAgB,KAA+B,KAAe,QAA8C;AACxG,YAAQ,KAAK,GAAG,WAAW,GAAG;AAC9B,UAAM,MAAM,GAAI,KAAK,cAAc,GAAG,CAAE,GAAI,IAAI,SAAS,SAAY,IAAI,OAAO,MAAM,EAAG,GAAI,IAAI,IAAK,GAAI,IAAI,SAAU;AACxH,YAAQ,MAAM,GAAG,GAAG;AACpB,UAAM,UAAyB,EAAE,IAAI;AACrC,QAAI;AACA,aAAO,OAAO,OAAO;AACrB,UAAI;AACJ,UAAI;AACA,mBAAW,MAAM,SAAS,eAAe,OAAO;AAAA,MACpD,SAAS,OAAO;AAEZ,YAAI,iBAAiB,gBAAgB,MAAM,UAAU,WAAW,KAAK;AACjE,iBAAO;AAAA,QACX;AACA,cAAM;AAAA,MACV;AACA,UAAI,SAAS,SAAS,QAAW;AAC7B,cAAM,IAAI,MAAM,4BAA4B;AAAA,MAChD;AACA,aAAO,MAAM,OAAO,MAAM,QAAQ;AAAA,IACtC,SAAS,OAAO;AACZ,YAAM,IAAI,eAAe,MAAM,KAAK,QAAQ,KAAK,KAAK;AAAA,IAC1D;AAAA,EACJ;AAAA,EAEO,cAAc,KAAe;AAChC,WAAO,GAAI,IAAI,QAAQ,KAAK,QAAQ,YAAY,IAAK,IAAK,IAAI,aAAa,SAAY,IAAI,WAAW,MAAM,EAAG,GAAI,IAAI,cAAc,SAAY,IAAI,YAAY,MAAM,EAAG,GAAI,IAAI,cAAc,SAAY,IAAI,YAAY,MAAM,EAAG;AAAA,EACzO;AAAA;AAAA;AAAA;AAAA;AAAA,EASO,YAAY,MAAc,SAA6C;AAC1E,UAAM;AACN,SAAK,QAAQ;AACb,SAAK,WAAW,MAAM,CAAC,GAAG,iBAAiB,WAAW,CAAC,CAAC;AAAA,EAC5D;AAAA,EAEA,IAAW,OAAe;AACtB,WAAO,KAAK;AAAA,EAChB;AAAA,EAEA,IAAW,UAAkB;AACzB,WAAO,UAAU,KAAK,KAAK;AAAA,EAC/B;AAAA,EAEA,IAAW,UAAoC;AAC3C,WAAO,KAAK;AAAA,EAChB;AAAA,EAEO,IAA8B,KAAe,QAAwC;AACxF,UAAM,iBAAiB,mBAAkB,WAAW,IAAI,MAAM;AAC9D,QAAI,KAAK,QAAQ,iBAAiB,EAAE,IAAI,aAAa,UAAa,IAAI,cAAc,oBAAoB;AACpG,aAAO,KAAK,wBAAwB,KAAK,cAAc;AAAA,IAC3D;AACA,WAAO,KAAK,KAAK,KAAK,cAAc;AAAA,EACxC;AAEJ;AApKa,mBAEO,QAA+B;AAAA,EAC3C,OAAO,SAAwB;AAAA,EAC/B;AAAA,EACA,MAAM,UAAyC;AAC3C,WAAO,SAAS;AAAA,EACpB;AACJ;AARS,mBASO,aAAyC;AAAA,EACrD,OAAO,SAAwB;AAAA,EAC/B;AAAA,EACA,MAAM,UAA8C;AAChD,WAAO,SAAS;AAAA,EACpB;AACJ;AAfS,mBAgBO,OAA6C;AAAA,EACzD,OAAO,SAAwB;AAAA,EAE/B;AAAA,EACA,MAAM,UAAwD;AAC1D,WAAO,SAAS;AAAA,EACpB;AACJ;AAvBS,mBAwBO,MAAgC;AAAA,EAC5C,OAAO,SAAwB;AAC3B,YAAQ,eAAe;AAAA,EAC3B;AAAA,EACA,MAAM,UAAqD;AACvD,WAAO,UAAU,WAAW,SAAS,IAAI;AAAA,EAC7C;AACJ;AA/BS,mBAgCO,QAAsC;AAAA,EAClD,OAAO,SAAwB;AAC3B,YAAQ,eAAe;AAAA,EAC3B;AAAA,EACA,MAAM,MAAM,UAAyD;AACjE,WAAO,MAAM,YAAY,gBAAgB,QAAQ;AAAA,EACrD;AACJ;AAvCS,mBAwCO,OAAkC;AAAA,EAC9C,OAAO,SAAwB;AAAA,EAC/B;AAAA,EACA,MAAM,UAA6C;AAC/C,WAAO,SAAS;AAAA,EACpB;AACJ;AA9CS,mBA+CO,OAA4B;AAAA,EACxC,OAAO,SAAwB;AAAA,EAC/B;AAAA,EACA,MAAM,UAAuC;AACzC,WAAO,SAAS;AAAA,EACpB;AACJ;AArDS,mBAuDO,aAAoD,oBAAI,IAAsC;AAAA,EAC1G,CAAC,YAAY,OAAO,mBAAkB,KAAK;AAAA,EAC3C,CAAC,YAAY,YAAY,mBAAkB,UAAU;AAAA,EACrD,CAAC,YAAY,MAAM,mBAAkB,IAAI;AAAA,EACzC,CAAC,YAAY,KAAK,mBAAkB,GAAG;AAAA,EACvC,CAAC,YAAY,OAAO,mBAAkB,KAAK;AAAA,EAC3C,CAAC,YAAY,MAAM,mBAAkB,IAAI;AAAA,EACzC,CAAC,YAAY,MAAM,mBAAkB,IAAI;AAC7C,CAAC;AA/DE,IAAM,oBAAN;","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":[]}
@@ -7,6 +7,7 @@ var AssetParser = /* @__PURE__ */ ((AssetParser2) => {
7
7
  AssetParser2["IMAGE"] = "image";
8
8
  AssetParser2["LIST"] = "list";
9
9
  AssetParser2["JSON"] = "json";
10
+ AssetParser2["BINARY"] = "binary";
10
11
  return AssetParser2;
11
12
  })(AssetParser || {});
12
13
  export {
@@ -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;AARC,SAAAA;AAAA,GAAA;","names":["AssetParser"]}
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();
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/cache/Caching.ts"],"sourcesContent":["import { AsyncLoadingCache, Caches, Loader, LoadingCache, SimpleCache } from \"@inventivetalent/loading-cache\";\nimport { BoxGeometryKey, CacheKey, serializeBoxGeometryKey, serializeImageKey, TextureKey } from \"./CacheKey\";\nimport { Time } from \"@inventivetalent/time\";\nimport { ImageInfo, ImageLoader } from \"../image/ImageLoader\";\nimport { BoxGeometry, Material, Mesh, PixelFormat, RGBAFormat, Texture } from \"three\";\nimport { Materials } from \"../Materials\";\nimport { CompatImage } from \"../canvas/CanvasCompat\";\nimport { Model, TextureAsset } from \"../model/Model\";\nimport { WrappedImage } from \"../WrappedImage\";\nimport { TextureAtlas } from \"../texture/TextureAtlas\";\nimport { ExtractableImageData } from \"../ExtractableImageData\";\nimport { MinecraftTextureMeta } from \"../MinecraftTextureMeta\";\nimport type { EntityModelFile } from \"../entity/EntityModel\";\nimport type { EntityAnimationFile } from \"../entity/EntityAnimation\";\nimport type { BlockEntityIndex } from \"../assets/BlockEntities\";\nimport type { ListAsset } from \"../ListAsset\";\nimport { BlockState } from \"../model/block/BlockState\";\nimport type { AssetKey } from \"../assets/AssetKey\";\nimport type { BitmapFont } from \"../assets/Fonts\";\nimport type { BannerPattern } from \"../assets/BannerPatterns\";\nimport type { Biome } from \"../assets/Biomes\";\n\n/** Shared in-memory caches for loaded assets and render resources. Persistent stores are managed separately. */\nexport class Caching {\n\n private static _generation = 0;\n\n /** Changes when shared assets are cleared, so derived caches can discard their old values. */\n public static get generation(): number { return this._generation; }\n\n static readonly rawImageCache: AsyncLoadingCache<CacheKey, ImageInfo> = Caches.builder()\n .expireAfterWrite(Time.minutes(10))\n .expireAfterAccess(Time.minutes(5))\n .expirationInterval(Time.seconds(5))\n .buildAsync<CacheKey, ImageInfo>();\n static readonly imageDataCache: AsyncLoadingCache<CacheKey, ImageData> = Caches.builder()\n .expireAfterWrite(Time.minutes(10))\n .expireAfterAccess(Time.minutes(5))\n .expirationInterval(Time.seconds(10))\n .buildAsync<CacheKey, ImageData>();\n static readonly canvasImageDataCache: AsyncLoadingCache<CacheKey, ExtractableImageData> = Caches.builder()\n .expireAfterWrite(Time.minutes(10))\n .expireAfterAccess(Time.minutes(5))\n .expirationInterval(Time.seconds(10))\n .buildAsync<CacheKey, ExtractableImageData>();\n static readonly wrappedImageCache: AsyncLoadingCache<CacheKey, WrappedImage> = Caches.builder()\n .expireAfterWrite(Time.minutes(10))\n .expireAfterAccess(Time.minutes(5))\n .expirationInterval(Time.seconds(10))\n .buildAsync<CacheKey, WrappedImage>();\n\n static readonly boxGeometryCache: SimpleCache<CacheKey, BoxGeometry> = Caches.builder()\n .expireAfterWrite(Time.minutes(10))\n .expireAfterAccess(Time.minutes(5))\n .expirationInterval(Time.seconds(20))\n .build<CacheKey, BoxGeometry>();\n\n static readonly textureCache: SimpleCache<CacheKey, Texture> = Caches.builder()\n .expireAfterWrite(Time.minutes(10))\n .expireAfterAccess(Time.minutes(5))\n .expirationInterval(Time.seconds(30))\n .build<CacheKey, Texture>();\n\n static readonly materialCache: SimpleCache<CacheKey, Material> = Caches.builder()\n .expireAfterWrite(Time.minutes(10))\n .expireAfterAccess(Time.minutes(5))\n .expirationInterval(Time.seconds(30))\n .build<CacheKey, Material>();\n\n static readonly boxMeshCache: SimpleCache<CacheKey, Mesh> = Caches.builder()\n .expireAfterWrite(Time.minutes(10))\n .expireAfterAccess(Time.minutes(5))\n .expirationInterval(Time.seconds(30))\n .build<CacheKey, Mesh>();\n\n static readonly textureAssetCache: AsyncLoadingCache<CacheKey, TextureAsset> = Caches.builder()\n .expireAfterWrite(Time.minutes(10))\n .expireAfterAccess(Time.minutes(5))\n .expirationInterval(Time.seconds(30))\n .buildAsync<CacheKey, TextureAsset>();\n static readonly textureMetaCache: AsyncLoadingCache<CacheKey, MinecraftTextureMeta> = Caches.builder()\n .expireAfterWrite(Time.minutes(10))\n .expireAfterAccess(Time.minutes(5))\n .expirationInterval(Time.seconds(30))\n .buildAsync<CacheKey, MinecraftTextureMeta>();\n\n static readonly rawModelCache: AsyncLoadingCache<CacheKey, Model> = Caches.builder()\n .expireAfterWrite(Time.minutes(10))\n .expireAfterAccess(Time.minutes(5))\n .expirationInterval(Time.seconds(30))\n .buildAsync<CacheKey, Model>();\n static readonly mergedModelCache: AsyncLoadingCache<CacheKey, Model> = Caches.builder()\n .expireAfterWrite(Time.minutes(10))\n .expireAfterAccess(Time.minutes(5))\n .expirationInterval(Time.seconds(30))\n .buildAsync<CacheKey, Model>();\n static readonly modelTextureAtlasCache: AsyncLoadingCache<CacheKey, TextureAtlas> = Caches.builder()\n .expireAfterWrite(Time.minutes(10))\n .expireAfterAccess(Time.minutes(5))\n .expirationInterval(Time.seconds(30))\n .buildAsync<CacheKey, TextureAtlas>();\n\n static readonly blockStateCache: AsyncLoadingCache<CacheKey, BlockState> = Caches.builder()\n .expireAfterWrite(Time.minutes(10))\n .expireAfterAccess(Time.minutes(5))\n .expirationInterval(Time.seconds(30))\n .buildAsync<CacheKey, BlockState>();\n\n static readonly listAssetCache: AsyncLoadingCache<CacheKey, ListAsset> = Caching.createAssetCache<ListAsset>();\n\n static readonly blockTintCache: AsyncLoadingCache<CacheKey, number> = Caching.createAssetCache<number>();\n\n static readonly entityModelCache: AsyncLoadingCache<CacheKey, EntityModelFile> = Caching.createAssetCache<EntityModelFile>();\n\n static readonly entityTextureCache: AsyncLoadingCache<CacheKey, AssetKey> = Caching.createAssetCache<AssetKey>();\n\n static readonly entityAnimationCache: AsyncLoadingCache<CacheKey, EntityAnimationFile> = Caching.createAssetCache<EntityAnimationFile>();\n static readonly blockEntityIndexCache: AsyncLoadingCache<CacheKey, BlockEntityIndex> = Caching.createAssetCache<BlockEntityIndex>();\n static readonly fontCache: AsyncLoadingCache<CacheKey, BitmapFont> = Caching.createAssetCache<BitmapFont>();\n static readonly bannerPatternCache: AsyncLoadingCache<CacheKey, BannerPattern> = Caching.createAssetCache<BannerPattern>();\n static readonly mineRenderDataCache: AsyncLoadingCache<CacheKey, unknown> = Caching.createAssetCache<unknown>();\n static readonly usernameUuidCache: AsyncLoadingCache<CacheKey, string> = Caches.builder()\n .expireAfterWrite(Time.minutes(5))\n .expirationInterval(Time.seconds(30))\n .buildAsync<CacheKey, string>();\n static readonly biomeCache: AsyncLoadingCache<CacheKey, Biome> = Caching.createAssetCache<Biome>();\n\n private static createAssetCache<T>(): AsyncLoadingCache<CacheKey, T> {\n return Caches.builder()\n .expireAfterWrite(Time.minutes(10))\n .expireAfterAccess(Time.minutes(5))\n .expirationInterval(Time.seconds(30))\n .buildAsync<CacheKey, T>();\n }\n\n\n /** Every cache above, so clear()/end() can never fall out of sync with the field list again. */\n private static get all(): { invalidateAll(): void; end(): void }[] {\n return [\n this.rawImageCache,\n this.imageDataCache,\n this.canvasImageDataCache,\n this.wrappedImageCache,\n this.boxGeometryCache,\n this.textureCache,\n this.materialCache,\n this.boxMeshCache,\n this.textureAssetCache,\n this.textureMetaCache,\n this.rawModelCache,\n this.mergedModelCache,\n this.modelTextureAtlasCache,\n this.blockStateCache,\n this.listAssetCache,\n this.blockTintCache,\n this.entityModelCache,\n this.entityTextureCache,\n this.entityAnimationCache,\n this.blockEntityIndexCache,\n this.fontCache,\n this.bannerPatternCache,\n this.mineRenderDataCache,\n this.usernameUuidCache,\n this.biomeCache\n ];\n }\n\n /** Invalidates in-memory entries so later lookups reload them. Persisted entries are retained. */\n public static clear() {\n this._generation++;\n for (const cache of this.all) {\n cache.invalidateAll();\n }\n }\n\n /**\n * Clears every cache and stops its expiry timer.\n *\n * Expiry timers are unref'd in Node, so idle processes can exit without this cleanup.\n * Use {@link shutdown} to also stop requests and the shared Ticker.\n */\n public static end() {\n this._generation++;\n for (const cache of this.all) {\n cache.invalidateAll();\n cache.end();\n }\n }\n\n public static get cacheSizes() {\n return {\n //TODO\n }\n }\n\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../../src/cache/Caching.ts"],"sourcesContent":["import { AsyncLoadingCache, Caches, Loader, LoadingCache, SimpleCache } from \"@inventivetalent/loading-cache\";\nimport { BoxGeometryKey, CacheKey, serializeBoxGeometryKey, serializeImageKey, TextureKey } from \"./CacheKey\";\nimport { Time } from \"@inventivetalent/time\";\nimport { ImageInfo, ImageLoader } from \"../image/ImageLoader\";\nimport { BoxGeometry, Material, Mesh, PixelFormat, RGBAFormat, Texture } from \"three\";\nimport { Materials } from \"../Materials\";\nimport { CompatImage } from \"../canvas/CanvasCompat\";\nimport { Model, TextureAsset } from \"../model/Model\";\nimport { WrappedImage } from \"../WrappedImage\";\nimport { TextureAtlas } from \"../texture/TextureAtlas\";\nimport { ExtractableImageData } from \"../ExtractableImageData\";\nimport { MinecraftTextureMeta } from \"../MinecraftTextureMeta\";\nimport type { EntityModelFile } from \"../entity/EntityModel\";\nimport type { EntityAnimationFile } from \"../entity/EntityAnimation\";\nimport type { BlockEntityIndex } from \"../assets/BlockEntities\";\nimport type { ListAsset } from \"../ListAsset\";\nimport { BlockState } from \"../model/block/BlockState\";\nimport type { AssetKey } from \"../assets/AssetKey\";\nimport type { UnihexFile } from \"../assets/_fonts/Unihex\";\nimport type { BitmapFont } from \"../assets/Fonts\";\nimport type { BannerPattern } from \"../assets/BannerPatterns\";\nimport type { Biome } from \"../assets/Biomes\";\n\n/** Shared in-memory caches for loaded assets and render resources. Persistent stores are managed separately. */\nexport class Caching {\n\n private static _generation = 0;\n\n /** Changes when shared assets are cleared, so derived caches can discard their old values. */\n public static get generation(): number { return this._generation; }\n\n static readonly rawImageCache: AsyncLoadingCache<CacheKey, ImageInfo> = Caches.builder()\n .expireAfterWrite(Time.minutes(10))\n .expireAfterAccess(Time.minutes(5))\n .expirationInterval(Time.seconds(5))\n .buildAsync<CacheKey, ImageInfo>();\n static readonly imageDataCache: AsyncLoadingCache<CacheKey, ImageData> = Caches.builder()\n .expireAfterWrite(Time.minutes(10))\n .expireAfterAccess(Time.minutes(5))\n .expirationInterval(Time.seconds(10))\n .buildAsync<CacheKey, ImageData>();\n static readonly canvasImageDataCache: AsyncLoadingCache<CacheKey, ExtractableImageData> = Caches.builder()\n .expireAfterWrite(Time.minutes(10))\n .expireAfterAccess(Time.minutes(5))\n .expirationInterval(Time.seconds(10))\n .buildAsync<CacheKey, ExtractableImageData>();\n static readonly wrappedImageCache: AsyncLoadingCache<CacheKey, WrappedImage> = Caches.builder()\n .expireAfterWrite(Time.minutes(10))\n .expireAfterAccess(Time.minutes(5))\n .expirationInterval(Time.seconds(10))\n .buildAsync<CacheKey, WrappedImage>();\n\n static readonly boxGeometryCache: SimpleCache<CacheKey, BoxGeometry> = Caches.builder()\n .expireAfterWrite(Time.minutes(10))\n .expireAfterAccess(Time.minutes(5))\n .expirationInterval(Time.seconds(20))\n .build<CacheKey, BoxGeometry>();\n\n static readonly textureCache: SimpleCache<CacheKey, Texture> = Caches.builder()\n .expireAfterWrite(Time.minutes(10))\n .expireAfterAccess(Time.minutes(5))\n .expirationInterval(Time.seconds(30))\n .build<CacheKey, Texture>();\n\n static readonly materialCache: SimpleCache<CacheKey, Material> = Caches.builder()\n .expireAfterWrite(Time.minutes(10))\n .expireAfterAccess(Time.minutes(5))\n .expirationInterval(Time.seconds(30))\n .build<CacheKey, Material>();\n\n static readonly boxMeshCache: SimpleCache<CacheKey, Mesh> = Caches.builder()\n .expireAfterWrite(Time.minutes(10))\n .expireAfterAccess(Time.minutes(5))\n .expirationInterval(Time.seconds(30))\n .build<CacheKey, Mesh>();\n\n static readonly textureAssetCache: AsyncLoadingCache<CacheKey, TextureAsset> = Caches.builder()\n .expireAfterWrite(Time.minutes(10))\n .expireAfterAccess(Time.minutes(5))\n .expirationInterval(Time.seconds(30))\n .buildAsync<CacheKey, TextureAsset>();\n static readonly textureMetaCache: AsyncLoadingCache<CacheKey, MinecraftTextureMeta> = Caches.builder()\n .expireAfterWrite(Time.minutes(10))\n .expireAfterAccess(Time.minutes(5))\n .expirationInterval(Time.seconds(30))\n .buildAsync<CacheKey, MinecraftTextureMeta>();\n\n static readonly rawModelCache: AsyncLoadingCache<CacheKey, Model> = Caches.builder()\n .expireAfterWrite(Time.minutes(10))\n .expireAfterAccess(Time.minutes(5))\n .expirationInterval(Time.seconds(30))\n .buildAsync<CacheKey, Model>();\n static readonly mergedModelCache: AsyncLoadingCache<CacheKey, Model> = Caches.builder()\n .expireAfterWrite(Time.minutes(10))\n .expireAfterAccess(Time.minutes(5))\n .expirationInterval(Time.seconds(30))\n .buildAsync<CacheKey, Model>();\n static readonly modelTextureAtlasCache: AsyncLoadingCache<CacheKey, TextureAtlas> = Caches.builder()\n .expireAfterWrite(Time.minutes(10))\n .expireAfterAccess(Time.minutes(5))\n .expirationInterval(Time.seconds(30))\n .buildAsync<CacheKey, TextureAtlas>();\n\n static readonly blockStateCache: AsyncLoadingCache<CacheKey, BlockState> = Caches.builder()\n .expireAfterWrite(Time.minutes(10))\n .expireAfterAccess(Time.minutes(5))\n .expirationInterval(Time.seconds(30))\n .buildAsync<CacheKey, BlockState>();\n\n static readonly listAssetCache: AsyncLoadingCache<CacheKey, ListAsset> = Caching.createAssetCache<ListAsset>();\n\n static readonly blockTintCache: AsyncLoadingCache<CacheKey, number> = Caching.createAssetCache<number>();\n\n static readonly entityModelCache: AsyncLoadingCache<CacheKey, EntityModelFile> = Caching.createAssetCache<EntityModelFile>();\n\n static readonly entityTextureCache: AsyncLoadingCache<CacheKey, AssetKey> = Caching.createAssetCache<AssetKey>();\n\n static readonly entityAnimationCache: AsyncLoadingCache<CacheKey, EntityAnimationFile> = Caching.createAssetCache<EntityAnimationFile>();\n static readonly blockEntityIndexCache: AsyncLoadingCache<CacheKey, BlockEntityIndex> = Caching.createAssetCache<BlockEntityIndex>();\n static readonly unihexCache: AsyncLoadingCache<CacheKey, UnihexFile> = Caching.createAssetCache<UnihexFile>();\n static readonly fontCache: AsyncLoadingCache<CacheKey, BitmapFont> = Caching.createAssetCache<BitmapFont>();\n static readonly bannerPatternCache: AsyncLoadingCache<CacheKey, BannerPattern> = Caching.createAssetCache<BannerPattern>();\n static readonly mineRenderDataCache: AsyncLoadingCache<CacheKey, unknown> = Caching.createAssetCache<unknown>();\n static readonly usernameUuidCache: AsyncLoadingCache<CacheKey, string> = Caches.builder()\n .expireAfterWrite(Time.minutes(5))\n .expirationInterval(Time.seconds(30))\n .buildAsync<CacheKey, string>();\n static readonly biomeCache: AsyncLoadingCache<CacheKey, Biome> = Caching.createAssetCache<Biome>();\n\n private static createAssetCache<T>(): AsyncLoadingCache<CacheKey, T> {\n return Caches.builder()\n .expireAfterWrite(Time.minutes(10))\n .expireAfterAccess(Time.minutes(5))\n .expirationInterval(Time.seconds(30))\n .buildAsync<CacheKey, T>();\n }\n\n\n /** Every cache above, so clear()/end() can never fall out of sync with the field list again. */\n private static get all(): { invalidateAll(): void; end(): void }[] {\n return [\n this.rawImageCache,\n this.imageDataCache,\n this.canvasImageDataCache,\n this.wrappedImageCache,\n this.boxGeometryCache,\n this.textureCache,\n this.materialCache,\n this.boxMeshCache,\n this.textureAssetCache,\n this.textureMetaCache,\n this.rawModelCache,\n this.mergedModelCache,\n this.modelTextureAtlasCache,\n this.blockStateCache,\n this.listAssetCache,\n this.blockTintCache,\n this.entityModelCache,\n this.entityTextureCache,\n this.entityAnimationCache,\n this.blockEntityIndexCache,\n this.fontCache,\n this.unihexCache,\n this.bannerPatternCache,\n this.mineRenderDataCache,\n this.usernameUuidCache,\n this.biomeCache\n ];\n }\n\n /** Invalidates in-memory entries so later lookups reload them. Persisted entries are retained. */\n public static clear() {\n this._generation++;\n for (const cache of this.all) {\n cache.invalidateAll();\n }\n }\n\n /**\n * Clears every cache and stops its expiry timer.\n *\n * Expiry timers are unref'd in Node, so idle processes can exit without this cleanup.\n * Use {@link shutdown} to also stop requests and the shared Ticker.\n */\n public static end() {\n this._generation++;\n for (const cache of this.all) {\n cache.invalidateAll();\n cache.end();\n }\n }\n\n public static get cacheSizes() {\n return {\n //TODO\n }\n }\n\n}\n"],"mappings":"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","names":[]}