* Setup default loaders for built-in asset types. * Runs during setup() phase to ensure loaders are available before scripts execute.
()
| 65 | * Runs during setup() phase to ensure loaders are available before scripts execute. |
| 66 | */ |
| 67 | static override async setup(): Promise<void> { |
| 68 | // Register default audio loader with IndexedDB persistence |
| 69 | if (!this._loaders.has('audio')) { |
| 70 | this.registerLoader('audio', { |
| 71 | loader: async (url: string, eng: VisualNovelEngine) => { |
| 72 | // Try to load from IndexedDB first (fast path - no network, no decode) |
| 73 | const cacheKey = url; // URL is used as key for persistent storage |
| 74 | const persistedBuffer = await eng.getAudioBufferPersistent(cacheKey); |
| 75 | if (persistedBuffer) { |
| 76 | return persistedBuffer; |
| 77 | } |
| 78 | |
| 79 | // Not in IndexedDB, fetch and decode from network |
| 80 | const buffer = await ArtemisPreload.audio(url, eng.audioContext); |
| 81 | |
| 82 | // Store in IndexedDB for future sessions (async, don't wait) |
| 83 | eng.storeAudioBufferPersistent(cacheKey, buffer).catch(() => { |
| 84 | // Silently ignore storage failures |
| 85 | }); |
| 86 | |
| 87 | return buffer; |
| 88 | }, |
| 89 | cache: { |
| 90 | get: (eng: VisualNovelEngine, key: string) => eng.audioBufferCache(key), |
| 91 | set: (eng: VisualNovelEngine, key: string, value: AudioBuffer) => eng.audioBufferCache(key, value), |
| 92 | delete: (eng: VisualNovelEngine, key: string) => eng.audioBufferUncache(key), |
| 93 | clear: (eng: VisualNovelEngine, prefix: string) => eng.audioBufferClearCache(prefix), |
| 94 | } |
| 95 | }); |
| 96 | } |
| 97 | |
| 98 | // Register default image loader |
| 99 | if (!this._loaders.has('image')) { |
| 100 | this.registerLoader('image', { |
| 101 | loader: async (url: string) => { |
| 102 | return ArtemisPreload.image(url); |
| 103 | }, |
| 104 | cache: { |
| 105 | get: (eng: VisualNovelEngine, key: string) => eng.imageCache(key), |
| 106 | set: (eng: VisualNovelEngine, key: string, value: HTMLImageElement) => eng.imageCache(key, value), |
| 107 | delete: (eng: VisualNovelEngine, key: string) => eng.imageUncache(key), |
| 108 | clear: (eng: VisualNovelEngine, prefix: string) => eng.imageClearCache(prefix), |
| 109 | } |
| 110 | }); |
| 111 | } |
| 112 | |
| 113 | // Register default category mappings (using plural names as assets are registered) |
| 114 | const defaultAudioCategories = ['music', 'sounds', 'voices']; |
| 115 | const defaultImageCategories = ['scenes', 'images', 'characters']; |
| 116 | |
| 117 | for (const category of defaultAudioCategories) { |
| 118 | if (!this._categoryLoaderMap.has(category)) { |
| 119 | this.registerCategory(category, 'audio'); |
| 120 | } |
| 121 | } |
| 122 | |
| 123 | for (const category of defaultImageCategories) { |
| 124 | if (!this._categoryLoaderMap.has(category)) { |
nothing calls this directly
no test coverage detected