@datamoc/mw_games 0.1.2 → 0.2.1
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/README.md +42 -17
- package/dist/actors/Aura.d.ts +29 -0
- package/dist/actors/Aura.d.ts.map +1 -0
- package/dist/actors/Aura.js +69 -0
- package/dist/actors/Aura.js.map +1 -0
- package/dist/actors/ItemStatusEffect.d.ts +27 -0
- package/dist/actors/ItemStatusEffect.d.ts.map +1 -0
- package/dist/actors/ItemStatusEffect.js +35 -0
- package/dist/actors/ItemStatusEffect.js.map +1 -0
- package/dist/actors/Support.d.ts +32 -0
- package/dist/actors/Support.d.ts.map +1 -0
- package/dist/actors/Support.js +60 -0
- package/dist/actors/Support.js.map +1 -0
- package/dist/actors/Traits.d.ts +29 -0
- package/dist/actors/Traits.d.ts.map +1 -0
- package/dist/actors/Traits.js +21 -0
- package/dist/actors/Traits.js.map +1 -0
- package/dist/actors/index.d.ts +8 -0
- package/dist/actors/index.d.ts.map +1 -1
- package/dist/actors/index.js +4 -0
- package/dist/actors/index.js.map +1 -1
- package/dist/assets/Streaming.d.ts +40 -0
- package/dist/assets/Streaming.d.ts.map +1 -0
- package/dist/assets/Streaming.js +79 -0
- package/dist/assets/Streaming.js.map +1 -0
- package/dist/assets/index.d.ts +13 -0
- package/dist/assets/index.d.ts.map +1 -1
- package/dist/assets/index.js +19 -0
- package/dist/assets/index.js.map +1 -1
- package/dist/audio/Captions.d.ts +15 -0
- package/dist/audio/Captions.d.ts.map +1 -0
- package/dist/audio/Captions.js +4 -0
- package/dist/audio/Captions.js.map +1 -0
- package/dist/audio/Midi.d.ts +75 -0
- package/dist/audio/Midi.d.ts.map +1 -0
- package/dist/audio/Midi.js +186 -0
- package/dist/audio/Midi.js.map +1 -0
- package/dist/audio/Music.d.ts.map +1 -1
- package/dist/audio/Music.js +5 -2
- package/dist/audio/Music.js.map +1 -1
- package/dist/audio/Orchestrator.d.ts +40 -0
- package/dist/audio/Orchestrator.d.ts.map +1 -0
- package/dist/audio/Orchestrator.js +48 -0
- package/dist/audio/Orchestrator.js.map +1 -0
- package/dist/audio/Sound.d.ts +3 -0
- package/dist/audio/Sound.d.ts.map +1 -1
- package/dist/audio/Sound.js +8 -1
- package/dist/audio/Sound.js.map +1 -1
- package/dist/audio/Synth.d.ts +35 -0
- package/dist/audio/Synth.d.ts.map +1 -0
- package/dist/audio/Synth.js +98 -0
- package/dist/audio/Synth.js.map +1 -0
- package/dist/audio/index.d.ts +8 -0
- package/dist/audio/index.d.ts.map +1 -1
- package/dist/audio/index.js +4 -0
- package/dist/audio/index.js.map +1 -1
- package/dist/board/Army.d.ts +17 -0
- package/dist/board/Army.d.ts.map +1 -0
- package/dist/board/Army.js +48 -0
- package/dist/board/Army.js.map +1 -0
- package/dist/board/FogOfWar.d.ts +23 -0
- package/dist/board/FogOfWar.d.ts.map +1 -0
- package/dist/board/FogOfWar.js +40 -0
- package/dist/board/FogOfWar.js.map +1 -0
- package/dist/board/Tactics.d.ts +2 -0
- package/dist/board/Tactics.d.ts.map +1 -1
- package/dist/board/Tactics.js +29 -7
- package/dist/board/Tactics.js.map +1 -1
- package/dist/board/index.d.ts +5 -1
- package/dist/board/index.d.ts.map +1 -1
- package/dist/board/index.js +3 -1
- package/dist/board/index.js.map +1 -1
- package/dist/core/Feedback.d.ts +23 -0
- package/dist/core/Feedback.d.ts.map +1 -0
- package/dist/core/Feedback.js +35 -0
- package/dist/core/Feedback.js.map +1 -0
- package/dist/core/Game.d.ts +11 -0
- package/dist/core/Game.d.ts.map +1 -1
- package/dist/core/Game.js +54 -0
- package/dist/core/Game.js.map +1 -1
- package/dist/core/Input.d.ts +58 -0
- package/dist/core/Input.d.ts.map +1 -1
- package/dist/core/Input.js +135 -0
- package/dist/core/Input.js.map +1 -1
- package/dist/core/Loading.d.ts +48 -0
- package/dist/core/Loading.d.ts.map +1 -0
- package/dist/core/Loading.js +102 -0
- package/dist/core/Loading.js.map +1 -0
- package/dist/core/News.d.ts +46 -0
- package/dist/core/News.d.ts.map +1 -0
- package/dist/core/News.js +79 -0
- package/dist/core/News.js.map +1 -0
- package/dist/core/PlayerInput.d.ts +38 -0
- package/dist/core/PlayerInput.d.ts.map +1 -0
- package/dist/core/PlayerInput.js +57 -0
- package/dist/core/PlayerInput.js.map +1 -0
- package/dist/core/RunHistory.d.ts +43 -0
- package/dist/core/RunHistory.d.ts.map +1 -0
- package/dist/core/RunHistory.js +41 -0
- package/dist/core/RunHistory.js.map +1 -0
- package/dist/core/Sanitize.d.ts +56 -0
- package/dist/core/Sanitize.d.ts.map +1 -0
- package/dist/core/Sanitize.js +87 -0
- package/dist/core/Sanitize.js.map +1 -0
- package/dist/core/Save.d.ts +31 -7
- package/dist/core/Save.d.ts.map +1 -1
- package/dist/core/Save.js +56 -0
- package/dist/core/Save.js.map +1 -1
- package/dist/core/SaveSync.d.ts +26 -0
- package/dist/core/SaveSync.d.ts.map +1 -0
- package/dist/core/SaveSync.js +52 -0
- package/dist/core/SaveSync.js.map +1 -0
- package/dist/core/Scramble.d.ts +13 -0
- package/dist/core/Scramble.d.ts.map +1 -0
- package/dist/core/Scramble.js +44 -0
- package/dist/core/Scramble.js.map +1 -0
- package/dist/core/Spawner.d.ts +48 -0
- package/dist/core/Spawner.d.ts.map +1 -0
- package/dist/core/Spawner.js +65 -0
- package/dist/core/Spawner.js.map +1 -0
- package/dist/core/Tween.d.ts +25 -0
- package/dist/core/Tween.d.ts.map +1 -0
- package/dist/core/Tween.js +60 -0
- package/dist/core/Tween.js.map +1 -0
- package/dist/core/UndoHistory.d.ts +37 -0
- package/dist/core/UndoHistory.d.ts.map +1 -0
- package/dist/core/UndoHistory.js +49 -0
- package/dist/core/UndoHistory.js.map +1 -0
- package/dist/core/index.d.ts +20 -0
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +11 -0
- package/dist/core/index.js.map +1 -1
- package/dist/i18n/Fluent.d.ts +7 -0
- package/dist/i18n/Fluent.d.ts.map +1 -0
- package/dist/i18n/Fluent.js +86 -0
- package/dist/i18n/Fluent.js.map +1 -0
- package/dist/i18n/index.d.ts +15 -1
- package/dist/i18n/index.d.ts.map +1 -1
- package/dist/i18n/index.js +17 -2
- package/dist/i18n/index.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/mw_games.global.js +351 -79
- package/dist/render/Camera.d.ts +29 -2
- package/dist/render/Camera.d.ts.map +1 -1
- package/dist/render/Camera.js +44 -13
- package/dist/render/Camera.js.map +1 -1
- package/dist/render/Capabilities.d.ts +51 -0
- package/dist/render/Capabilities.d.ts.map +1 -0
- package/dist/render/Capabilities.js +56 -0
- package/dist/render/Capabilities.js.map +1 -0
- package/dist/render/ColorBlindness.d.ts +16 -0
- package/dist/render/ColorBlindness.d.ts.map +1 -0
- package/dist/render/ColorBlindness.js +41 -0
- package/dist/render/ColorBlindness.js.map +1 -0
- package/dist/render/Minimap.d.ts +52 -0
- package/dist/render/Minimap.d.ts.map +1 -0
- package/dist/render/Minimap.js +95 -0
- package/dist/render/Minimap.js.map +1 -0
- package/dist/render/Viewport.d.ts +46 -0
- package/dist/render/Viewport.d.ts.map +1 -0
- package/dist/render/Viewport.js +52 -0
- package/dist/render/Viewport.js.map +1 -0
- package/dist/render/index.d.ts +9 -1
- package/dist/render/index.d.ts.map +1 -1
- package/dist/render/index.js +5 -1
- package/dist/render/index.js.map +1 -1
- package/dist/roguelike/Stealth.d.ts +34 -0
- package/dist/roguelike/Stealth.d.ts.map +1 -0
- package/dist/roguelike/Stealth.js +35 -0
- package/dist/roguelike/Stealth.js.map +1 -0
- package/dist/roguelike/index.d.ts +2 -0
- package/dist/roguelike/index.d.ts.map +1 -1
- package/dist/roguelike/index.js +1 -0
- package/dist/roguelike/index.js.map +1 -1
- package/dist/rpg/Collision.d.ts +42 -0
- package/dist/rpg/Collision.d.ts.map +1 -0
- package/dist/rpg/Collision.js +77 -0
- package/dist/rpg/Collision.js.map +1 -0
- package/dist/rpg/FreeMover.d.ts +45 -0
- package/dist/rpg/FreeMover.d.ts.map +1 -0
- package/dist/rpg/FreeMover.js +68 -0
- package/dist/rpg/FreeMover.js.map +1 -0
- package/dist/rpg/Marshal.d.ts +65 -0
- package/dist/rpg/Marshal.d.ts.map +1 -0
- package/dist/rpg/Marshal.js +393 -0
- package/dist/rpg/Marshal.js.map +1 -0
- package/dist/rpg/Quest.d.ts +41 -0
- package/dist/rpg/Quest.d.ts.map +1 -1
- package/dist/rpg/Quest.js +39 -6
- package/dist/rpg/Quest.js.map +1 -1
- package/dist/rpg/index.d.ts +7 -1
- package/dist/rpg/index.d.ts.map +1 -1
- package/dist/rpg/index.js +3 -0
- package/dist/rpg/index.js.map +1 -1
- package/dist/stage/DialogueStage.d.ts +1 -2
- package/dist/stage/DialogueStage.d.ts.map +1 -1
- package/dist/stage/DialogueStage.js +7 -22
- package/dist/stage/DialogueStage.js.map +1 -1
- package/dist/stage/index.d.ts +1 -1
- package/dist/stage/index.d.ts.map +1 -1
- package/dist/stage/script.d.ts +29 -0
- package/dist/stage/script.d.ts.map +1 -1
- package/dist/stage/script.js +0 -0
- package/dist/stage/script.js.map +1 -1
- package/dist/three-d/Character3D.d.ts +48 -0
- package/dist/three-d/Character3D.d.ts.map +1 -0
- package/dist/three-d/Character3D.js +96 -0
- package/dist/three-d/Character3D.js.map +1 -0
- package/dist/three-d/Engine3D.d.ts +23 -0
- package/dist/three-d/Engine3D.d.ts.map +1 -0
- package/dist/three-d/Engine3D.js +45 -0
- package/dist/three-d/Engine3D.js.map +1 -0
- package/dist/three-d/Grid.d.ts +14 -0
- package/dist/three-d/Grid.d.ts.map +1 -0
- package/dist/three-d/Grid.js +13 -0
- package/dist/three-d/Grid.js.map +1 -0
- package/dist/three-d/Heightmap.d.ts +35 -0
- package/dist/three-d/Heightmap.d.ts.map +1 -0
- package/dist/three-d/Heightmap.js +29 -0
- package/dist/three-d/Heightmap.js.map +1 -0
- package/dist/three-d/Models.d.ts +12 -0
- package/dist/three-d/Models.d.ts.map +1 -0
- package/dist/three-d/Models.js +14 -0
- package/dist/three-d/Models.js.map +1 -0
- package/dist/three-d/TileGrid3D.d.ts +21 -0
- package/dist/three-d/TileGrid3D.d.ts.map +1 -0
- package/dist/three-d/TileGrid3D.js +65 -0
- package/dist/three-d/TileGrid3D.js.map +1 -0
- package/dist/three-d/Vox.d.ts +24 -0
- package/dist/three-d/Vox.d.ts.map +1 -0
- package/dist/three-d/Vox.js +93 -0
- package/dist/three-d/Vox.js.map +1 -0
- package/dist/three-d/index.d.ts +13 -0
- package/dist/three-d/index.d.ts.map +1 -0
- package/dist/three-d/index.js +7 -0
- package/dist/three-d/index.js.map +1 -0
- package/dist/ui/Bar.d.ts +49 -0
- package/dist/ui/Bar.d.ts.map +1 -0
- package/dist/ui/Bar.js +70 -0
- package/dist/ui/Bar.js.map +1 -0
- package/dist/ui/BitmapLabel.d.ts +42 -0
- package/dist/ui/BitmapLabel.d.ts.map +1 -0
- package/dist/ui/BitmapLabel.js +59 -0
- package/dist/ui/BitmapLabel.js.map +1 -0
- package/dist/ui/Button.d.ts +52 -0
- package/dist/ui/Button.d.ts.map +1 -0
- package/dist/ui/Button.js +147 -0
- package/dist/ui/Button.js.map +1 -0
- package/dist/ui/FloatingText.d.ts +28 -0
- package/dist/ui/FloatingText.d.ts.map +1 -0
- package/dist/ui/FloatingText.js +39 -0
- package/dist/ui/FloatingText.js.map +1 -0
- package/dist/ui/HelpScreen.d.ts +29 -0
- package/dist/ui/HelpScreen.d.ts.map +1 -0
- package/dist/ui/HelpScreen.js +39 -0
- package/dist/ui/HelpScreen.js.map +1 -0
- package/dist/ui/IconGrid.d.ts +8 -0
- package/dist/ui/IconGrid.d.ts.map +1 -1
- package/dist/ui/IconGrid.js +27 -1
- package/dist/ui/IconGrid.js.map +1 -1
- package/dist/ui/Label.d.ts +9 -0
- package/dist/ui/Label.d.ts.map +1 -1
- package/dist/ui/Label.js +24 -1
- package/dist/ui/Label.js.map +1 -1
- package/dist/ui/ListView.d.ts +11 -0
- package/dist/ui/ListView.d.ts.map +1 -1
- package/dist/ui/ListView.js +55 -1
- package/dist/ui/ListView.js.map +1 -1
- package/dist/ui/LoadingScreen.d.ts +31 -0
- package/dist/ui/LoadingScreen.d.ts.map +1 -0
- package/dist/ui/LoadingScreen.js +60 -0
- package/dist/ui/LoadingScreen.js.map +1 -0
- package/dist/ui/MessageBox.d.ts +26 -0
- package/dist/ui/MessageBox.d.ts.map +1 -1
- package/dist/ui/MessageBox.js +62 -13
- package/dist/ui/MessageBox.js.map +1 -1
- package/dist/ui/RebindScreen.d.ts +55 -0
- package/dist/ui/RebindScreen.d.ts.map +1 -0
- package/dist/ui/RebindScreen.js +114 -0
- package/dist/ui/RebindScreen.js.map +1 -0
- package/dist/ui/Toast.d.ts +44 -0
- package/dist/ui/Toast.d.ts.map +1 -0
- package/dist/ui/Toast.js +89 -0
- package/dist/ui/Toast.js.map +1 -0
- package/dist/ui/VerticalLabel.d.ts +5 -0
- package/dist/ui/VerticalLabel.d.ts.map +1 -1
- package/dist/ui/VerticalLabel.js +18 -7
- package/dist/ui/VerticalLabel.js.map +1 -1
- package/dist/ui/Window.d.ts +6 -0
- package/dist/ui/Window.d.ts.map +1 -1
- package/dist/ui/Window.js +16 -1
- package/dist/ui/Window.js.map +1 -1
- package/dist/ui/WindowStack.d.ts +1 -0
- package/dist/ui/WindowStack.d.ts.map +1 -1
- package/dist/ui/WindowStack.js +4 -1
- package/dist/ui/WindowStack.js.map +1 -1
- package/dist/ui/index.d.ts +17 -1
- package/dist/ui/index.d.ts.map +1 -1
- package/dist/ui/index.js +9 -1
- package/dist/ui/index.js.map +1 -1
- package/dist/ui/theme.d.ts +21 -0
- package/dist/ui/theme.d.ts.map +1 -1
- package/dist/ui/theme.js +42 -0
- package/dist/ui/theme.js.map +1 -1
- package/dist/version.d.ts +13 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +13 -0
- package/dist/version.js.map +1 -0
- package/dist/world/Environment.d.ts +35 -0
- package/dist/world/Environment.d.ts.map +1 -0
- package/dist/world/Environment.js +55 -0
- package/dist/world/Environment.js.map +1 -0
- package/dist/world/index.d.ts +2 -0
- package/dist/world/index.d.ts.map +1 -1
- package/dist/world/index.js +1 -0
- package/dist/world/index.js.map +1 -1
- package/package.json +40 -4
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { load, release } from './index.js';
|
|
2
|
+
/**
|
|
3
|
+
* Game-directed background asset staging with bounded, least-recently-used eviction.
|
|
4
|
+
*
|
|
5
|
+
* It deliberately does not guess a player's next map: the game supplies bundles it considers
|
|
6
|
+
* likely. This works with compiled data URIs as a decode/GPU warm-up and with server or
|
|
7
|
+
* desktop hosts as ordinary asynchronous streaming.
|
|
8
|
+
*/
|
|
9
|
+
export class AssetStream {
|
|
10
|
+
constructor(options = {}) {
|
|
11
|
+
this.entries = new Map();
|
|
12
|
+
this.clock = 0;
|
|
13
|
+
this.budgetBytes = options.budgetBytes ?? Number.POSITIVE_INFINITY;
|
|
14
|
+
if (!(this.budgetBytes >= 0))
|
|
15
|
+
throw new Error('asset stream budget must not be negative');
|
|
16
|
+
this.loadAssets = options.load ?? load;
|
|
17
|
+
this.releaseAssets = options.release ?? release;
|
|
18
|
+
}
|
|
19
|
+
/** loads one bundle now, then evicts older ready bundles if its budget requires it */
|
|
20
|
+
async preload(bundle) {
|
|
21
|
+
if (!bundle.id)
|
|
22
|
+
throw new Error('asset bundle needs an id');
|
|
23
|
+
if (bundle.estimatedBytes !== undefined && bundle.estimatedBytes < 0)
|
|
24
|
+
throw new Error('asset bundle size must not be negative');
|
|
25
|
+
const existing = this.entries.get(bundle.id);
|
|
26
|
+
if (existing?.ready) {
|
|
27
|
+
existing.lastUsed = ++this.clock;
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
const paths = bundle.paths.filter((path) => !this.isRetained(path));
|
|
31
|
+
if (paths.length > 0)
|
|
32
|
+
await this.loadAssets([...paths]);
|
|
33
|
+
this.entries.set(bundle.id, { ...bundle, lastUsed: ++this.clock, ready: true });
|
|
34
|
+
await this.enforceBudget(bundle.id);
|
|
35
|
+
}
|
|
36
|
+
/** preloads bundles in highest-priority-first order; callers may intentionally not await it */
|
|
37
|
+
async preloadLikely(bundles) {
|
|
38
|
+
for (const bundle of [...bundles].sort((a, b) => (b.priority ?? 0) - (a.priority ?? 0)))
|
|
39
|
+
await this.preload(bundle);
|
|
40
|
+
}
|
|
41
|
+
/** marks a ready bundle as recently used at the moment a scene adopts it */
|
|
42
|
+
use(id) {
|
|
43
|
+
const entry = this.entries.get(id);
|
|
44
|
+
if (!entry?.ready)
|
|
45
|
+
return false;
|
|
46
|
+
entry.lastUsed = ++this.clock;
|
|
47
|
+
return true;
|
|
48
|
+
}
|
|
49
|
+
isReady(id) {
|
|
50
|
+
return this.entries.get(id)?.ready ?? false;
|
|
51
|
+
}
|
|
52
|
+
/** explicitly unloads one bundle, even when the configured budget has room */
|
|
53
|
+
async unload(id) {
|
|
54
|
+
const entry = this.entries.get(id);
|
|
55
|
+
if (!entry)
|
|
56
|
+
return;
|
|
57
|
+
this.entries.delete(id);
|
|
58
|
+
const paths = entry.paths.filter((path) => !this.isRetained(path));
|
|
59
|
+
if (paths.length > 0)
|
|
60
|
+
await this.releaseAssets(paths);
|
|
61
|
+
}
|
|
62
|
+
get estimatedBytes() {
|
|
63
|
+
return [...this.entries.values()].reduce((sum, entry) => sum + (entry.estimatedBytes ?? 0), 0);
|
|
64
|
+
}
|
|
65
|
+
async enforceBudget(protectedId) {
|
|
66
|
+
while (this.estimatedBytes > this.budgetBytes) {
|
|
67
|
+
const candidate = [...this.entries.values()]
|
|
68
|
+
.filter((entry) => entry.id !== protectedId)
|
|
69
|
+
.sort((a, b) => a.lastUsed - b.lastUsed)[0];
|
|
70
|
+
if (!candidate)
|
|
71
|
+
return;
|
|
72
|
+
await this.unload(candidate.id);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
isRetained(path) {
|
|
76
|
+
return [...this.entries.values()].some((entry) => entry.ready && entry.paths.includes(path));
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=Streaming.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Streaming.js","sourceRoot":"","sources":["../../src/assets/Streaming.ts"],"names":[],"mappings":"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"}
|
package/dist/assets/index.d.ts
CHANGED
|
@@ -34,4 +34,17 @@ export declare function load(paths: string[]): Promise<void>;
|
|
|
34
34
|
export declare function texture(path: string): Texture;
|
|
35
35
|
/** a loaded asset of any other kind, such as parsed JSON */
|
|
36
36
|
export declare function get<T>(path: string): T;
|
|
37
|
+
/** true once `load` has resolved for this path and it has not since been `release`d */
|
|
38
|
+
export declare function isLoaded(path: string): boolean;
|
|
39
|
+
/**
|
|
40
|
+
* Frees assets `load` brought in, destroying any texture among them so it stops holding GPU
|
|
41
|
+
* memory. For a game with many discrete zones - each with its own tileset or sprite sheet -
|
|
42
|
+
* this is the counterpart to `world.World.unload`: that drops a map's own state, this drops
|
|
43
|
+
* the assets it pointed at, once a game decides the player has left an area for good. A path
|
|
44
|
+
* never loaded (or already released) is silently skipped rather than treated as an error,
|
|
45
|
+
* since a game unloading a zone it may or may not have visited shouldn't have to check first.
|
|
46
|
+
*/
|
|
47
|
+
export declare function release(paths: string[]): Promise<void>;
|
|
48
|
+
export { AssetStream } from './Streaming.ts';
|
|
49
|
+
export type { AssetBundle, AssetStreamOptions } from './Streaming.ts';
|
|
37
50
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/assets/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAU,OAAO,EAAE,MAAM,SAAS,CAAC;AAE1C;;;;;;;;;;GAUG;AAEH,OAAO,CAAC,MAAM,CAAC;IACd,UAAU,MAAM;QACf,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;KACxC;CACD;AAKD,mEAAmE;AACnE,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAE1C;AAMD,2EAA2E;AAC3E,wBAAgB,UAAU,IAAI,OAAO,CAEpC;AAED,wBAAgB,KAAK,IAAI,MAAM,EAAE,CAEhC;AAED,wBAAgB,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAGzC;AAED,wEAAwE;AACxE,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAW5C;AAED;;;;;GAKG;AACH,wBAAsB,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAQzD;AAED,4DAA4D;AAC5D,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAK7C;AAED,4DAA4D;AAC5D,wBAAgB,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,GAAG,CAAC,CAKtC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/assets/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAU,OAAO,EAAE,MAAM,SAAS,CAAC;AAE1C;;;;;;;;;;GAUG;AAEH,OAAO,CAAC,MAAM,CAAC;IACd,UAAU,MAAM;QACf,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;KACxC;CACD;AAKD,mEAAmE;AACnE,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAE1C;AAMD,2EAA2E;AAC3E,wBAAgB,UAAU,IAAI,OAAO,CAEpC;AAED,wBAAgB,KAAK,IAAI,MAAM,EAAE,CAEhC;AAED,wBAAgB,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAGzC;AAED,wEAAwE;AACxE,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAW5C;AAED;;;;;GAKG;AACH,wBAAsB,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAQzD;AAED,4DAA4D;AAC5D,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAK7C;AAED,4DAA4D;AAC5D,wBAAgB,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,GAAG,CAAC,CAKtC;AAED,uFAAuF;AACvF,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAE9C;AAED;;;;;;;GAOG;AACH,wBAAsB,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAI5D;AAED,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7C,YAAY,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC"}
|
package/dist/assets/index.js
CHANGED
|
@@ -59,4 +59,23 @@ export function get(path) {
|
|
|
59
59
|
}
|
|
60
60
|
return Assets.get(path);
|
|
61
61
|
}
|
|
62
|
+
/** true once `load` has resolved for this path and it has not since been `release`d */
|
|
63
|
+
export function isLoaded(path) {
|
|
64
|
+
return Assets.cache.has(path);
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Frees assets `load` brought in, destroying any texture among them so it stops holding GPU
|
|
68
|
+
* memory. For a game with many discrete zones - each with its own tileset or sprite sheet -
|
|
69
|
+
* this is the counterpart to `world.World.unload`: that drops a map's own state, this drops
|
|
70
|
+
* the assets it pointed at, once a game decides the player has left an area for good. A path
|
|
71
|
+
* never loaded (or already released) is silently skipped rather than treated as an error,
|
|
72
|
+
* since a game unloading a zone it may or may not have visited shouldn't have to check first.
|
|
73
|
+
*/
|
|
74
|
+
export async function release(paths) {
|
|
75
|
+
const loaded = paths.filter((path) => Assets.cache.has(path));
|
|
76
|
+
if (loaded.length === 0)
|
|
77
|
+
return;
|
|
78
|
+
await Assets.unload(loaded);
|
|
79
|
+
}
|
|
80
|
+
export { AssetStream } from './Streaming.js';
|
|
62
81
|
//# sourceMappingURL=index.js.map
|
package/dist/assets/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/assets/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAoB1C,kFAAkF;AAClF,IAAI,IAAI,GAAG,EAAE,CAAC;AAEd,mEAAmE;AACnE,MAAM,UAAU,OAAO,CAAC,IAAY;IACnC,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,IAAI,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,GAAG,GAAG,CAAC;AAC9D,CAAC;AAED,SAAS,QAAQ;IAChB,OAAO,OAAO,MAAM,KAAK,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,cAAc,CAAC;AAC1E,CAAC;AAED,2EAA2E;AAC3E,MAAM,UAAU,UAAU;IACzB,OAAO,QAAQ,EAAE,KAAK,SAAS,CAAC;AACjC,CAAC;AAED,MAAM,UAAU,KAAK;IACpB,OAAO,MAAM,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;AACtC,CAAC;AAED,MAAM,UAAU,GAAG,CAAC,IAAY;IAC/B,MAAM,GAAG,GAAG,QAAQ,EAAE,CAAC;IACvB,OAAO,GAAG,CAAC,CAAC,CAAC,IAAI,IAAI,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC;AACjC,CAAC;AAED,wEAAwE;AACxE,MAAM,UAAU,OAAO,CAAC,IAAY;IACnC,MAAM,GAAG,GAAG,QAAQ,EAAE,CAAC;IACvB,IAAI,CAAC,GAAG;QAAE,OAAO,IAAI,GAAG,IAAI,CAAC;IAE7B,MAAM,KAAK,GAAG,GAAG,CAAC,IAAI,CAAC,CAAC;IACxB,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACzB,MAAM,IAAI,KAAK,CACd,UAAU,IAAI,mFAAmF,CACjG,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC;AACd,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,IAAI,CAAC,KAAe;IACzC,MAAM,OAAO,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;IAChE,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO;IAEjC,KAAK,MAAM,IAAI,IAAI,OAAO,EAAE,CAAC;QAC5B,MAAM,CAAC,GAAG,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,EAAE,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACjD,CAAC;IACD,MAAM,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;AAC5B,CAAC;AAED,4DAA4D;AAC5D,MAAM,UAAU,OAAO,CAAC,IAAY;IACnC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;QAC7B,MAAM,IAAI,KAAK,CAAC,YAAY,IAAI,iDAAiD,CAAC,CAAC;IACpF,CAAC;IACD,OAAO,MAAM,CAAC,GAAG,CAAU,IAAI,CAAC,CAAC;AAClC,CAAC;AAED,4DAA4D;AAC5D,MAAM,UAAU,GAAG,CAAI,IAAY;IAClC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;QAC7B,MAAM,IAAI,KAAK,CAAC,UAAU,IAAI,iDAAiD,CAAC,CAAC;IAClF,CAAC;IACD,OAAO,MAAM,CAAC,GAAG,CAAI,IAAI,CAAC,CAAC;AAC5B,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/assets/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Signal } from '../core/Signal.ts';
|
|
2
|
+
/**
|
|
3
|
+
* A visual cue for a sound effect a deaf or hard-of-hearing player cannot hear - a footstep,
|
|
4
|
+
* a monster's growl, a door creaking. Dialogue already has its own on-screen text (`mwg/stage`'s
|
|
5
|
+
* `MessageBox` is how every line is shown at all, not an addition over voiced audio), so this
|
|
6
|
+
* exists for `Sound` alone, not `Music`: background music is not ordinarily captioned the way
|
|
7
|
+
* an important sound effect is.
|
|
8
|
+
*/
|
|
9
|
+
export interface CaptionEvent {
|
|
10
|
+
/** shown by a captioning overlay - "footsteps", "door creaks", "a growl nearby" */
|
|
11
|
+
text: string;
|
|
12
|
+
}
|
|
13
|
+
/** fires whenever a captioned `Sound` plays - a captioning overlay subscribes here, entirely decoupled from `Sound` itself, which never imports anything UI-shaped */
|
|
14
|
+
export declare const onCaption: Signal<CaptionEvent>;
|
|
15
|
+
//# sourceMappingURL=Captions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Captions.d.ts","sourceRoot":"","sources":["../../src/audio/Captions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAE3C;;;;;;GAMG;AACH,MAAM,WAAW,YAAY;IAC5B,mFAAmF;IACnF,IAAI,EAAE,MAAM,CAAC;CACb;AAED,sKAAsK;AACtK,eAAO,MAAM,SAAS,sBAA6B,CAAC"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { Signal } from '../core/Signal.js';
|
|
2
|
+
/** fires whenever a captioned `Sound` plays - a captioning overlay subscribes here, entirely decoupled from `Sound` itself, which never imports anything UI-shaped */
|
|
3
|
+
export const onCaption = new Signal();
|
|
4
|
+
//# sourceMappingURL=Captions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Captions.js","sourceRoot":"","sources":["../../src/audio/Captions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAc3C,sKAAsK;AACtK,MAAM,CAAC,MAAM,SAAS,GAAG,IAAI,MAAM,EAAgB,CAAC"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { type ToneOptions, type Waveform } from './Synth.ts';
|
|
2
|
+
import type { Playable } from './Playable.ts';
|
|
3
|
+
/**
|
|
4
|
+
* A Standard MIDI File (SMF) reader plus a player that voices each note through
|
|
5
|
+
* `audio.synthesizeTone` - `.mid` is a small, patent-free, well-documented event format
|
|
6
|
+
* (timing and note-on/note-off, not audio), so reading one is ordinary format engineering,
|
|
7
|
+
* and playback needed exactly the instrument item 120's waveform synth already supplies: a
|
|
8
|
+
* crude but real, entirely generated-not-borrowed one, closer to a chiptune cover than a
|
|
9
|
+
* sampled orchestra.
|
|
10
|
+
*/
|
|
11
|
+
export interface MidiNoteEvent {
|
|
12
|
+
tick: number;
|
|
13
|
+
type: 'noteOn' | 'noteOff';
|
|
14
|
+
note: number;
|
|
15
|
+
velocity: number;
|
|
16
|
+
channel: number;
|
|
17
|
+
}
|
|
18
|
+
export interface MidiTempoEvent {
|
|
19
|
+
tick: number;
|
|
20
|
+
type: 'tempo';
|
|
21
|
+
/** microseconds per quarter note */
|
|
22
|
+
microsecondsPerQuarter: number;
|
|
23
|
+
}
|
|
24
|
+
export type MidiEvent = MidiNoteEvent | MidiTempoEvent;
|
|
25
|
+
export interface MidiFile {
|
|
26
|
+
ticksPerQuarter: number;
|
|
27
|
+
/** every note-on/note-off and tempo-change event from every track, merged and sorted by tick */
|
|
28
|
+
events: readonly MidiEvent[];
|
|
29
|
+
}
|
|
30
|
+
/** Reads format 0/1 Standard MIDI File bytes into a flat, tick-ordered event list. */
|
|
31
|
+
export declare function parseMidi(data: ArrayBuffer | ArrayBufferView): MidiFile;
|
|
32
|
+
export interface ScheduledNote {
|
|
33
|
+
/** seconds from the start of playback */
|
|
34
|
+
time: number;
|
|
35
|
+
duration: number;
|
|
36
|
+
note: number;
|
|
37
|
+
velocity: number;
|
|
38
|
+
channel: number;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Resolves a parsed file's tick-based events into real-time seconds, honouring tempo
|
|
42
|
+
* changes and pairing each note-on with its matching note-off to find a duration. A
|
|
43
|
+
* note-on with no matching note-off (a malformed or truncated file) still sounds, for a
|
|
44
|
+
* short default duration, rather than being dropped silently.
|
|
45
|
+
*/
|
|
46
|
+
export declare function scheduleMidi(file: MidiFile): ScheduledNote[];
|
|
47
|
+
/** MIDI note 69 (A4) is 440 Hz; each semitone is a twelfth root of two step */
|
|
48
|
+
export declare function noteToFrequency(note: number): number;
|
|
49
|
+
export interface MidiPlayerOptions {
|
|
50
|
+
waveform?: Waveform;
|
|
51
|
+
/** peak volume; scaled per note by that note's own MIDI velocity */
|
|
52
|
+
volume?: number;
|
|
53
|
+
/** voices one scheduled note; defaults to `audio.playTone` */
|
|
54
|
+
play?: (options: ToneOptions) => Playable;
|
|
55
|
+
}
|
|
56
|
+
/** Plays a parsed `MidiFile` back through `mwg/audio`'s waveform synth, one tone per note, driven by `update(dt)` like every other dt-driven piece of `mwg/core`. */
|
|
57
|
+
export declare class MidiPlayer {
|
|
58
|
+
private readonly notes;
|
|
59
|
+
private readonly playFn;
|
|
60
|
+
private readonly waveform;
|
|
61
|
+
private readonly volume;
|
|
62
|
+
private elapsed;
|
|
63
|
+
private index;
|
|
64
|
+
private playing;
|
|
65
|
+
constructor(file: MidiFile, options?: MidiPlayerOptions);
|
|
66
|
+
play(): void;
|
|
67
|
+
pause(): void;
|
|
68
|
+
/** stops and rewinds to the beginning */
|
|
69
|
+
stop(): void;
|
|
70
|
+
update(dt: number): void;
|
|
71
|
+
get isPlaying(): boolean;
|
|
72
|
+
/** total playback length in seconds, from the last scheduled note's own end */
|
|
73
|
+
get duration(): number;
|
|
74
|
+
}
|
|
75
|
+
//# sourceMappingURL=Midi.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Midi.d.ts","sourceRoot":"","sources":["../../src/audio/Midi.ts"],"names":[],"mappings":"AAAA,OAAO,EAAY,KAAK,WAAW,EAAE,KAAK,QAAQ,EAAE,MAAM,YAAY,CAAC;AACvE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAE9C;;;;;;;GAOG;AAEH,MAAM,WAAW,aAAa;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,QAAQ,GAAG,SAAS,CAAC;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,cAAc;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,OAAO,CAAC;IACd,oCAAoC;IACpC,sBAAsB,EAAE,MAAM,CAAC;CAC/B;AAED,MAAM,MAAM,SAAS,GAAG,aAAa,GAAG,cAAc,CAAC;AAEvD,MAAM,WAAW,QAAQ;IACxB,eAAe,EAAE,MAAM,CAAC;IACxB,gGAAgG;IAChG,MAAM,EAAE,SAAS,SAAS,EAAE,CAAC;CAC7B;AAID,sFAAsF;AACtF,wBAAgB,SAAS,CAAC,IAAI,EAAE,WAAW,GAAG,eAAe,GAAG,QAAQ,CAqFvE;AAED,MAAM,WAAW,aAAa;IAC7B,yCAAyC;IACzC,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;CAChB;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,QAAQ,GAAG,aAAa,EAAE,CAmC5D;AAED,+EAA+E;AAC/E,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEpD;AAED,MAAM,WAAW,iBAAiB;IACjC,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,oEAAoE;IACpE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,8DAA8D;IAC9D,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,WAAW,KAAK,QAAQ,CAAC;CAC1C;AAED,qKAAqK;AACrK,qBAAa,UAAU;IACtB,OAAO,CAAC,QAAQ,CAAC,KAAK,CAA2B;IACjD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAqC;IAC5D,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAW;IACpC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAEhC,OAAO,CAAC,OAAO,CAAK;IACpB,OAAO,CAAC,KAAK,CAAK;IAClB,OAAO,CAAC,OAAO,CAAS;IAExB,YAAY,IAAI,EAAE,QAAQ,EAAE,OAAO,GAAE,iBAAsB,EAK1D;IAED,IAAI,IAAI,IAAI,CAEX;IAED,KAAK,IAAI,IAAI,CAEZ;IAED,yCAAyC;IACzC,IAAI,IAAI,IAAI,CAIX;IAED,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAgBvB;IAED,IAAI,SAAS,IAAI,OAAO,CAEvB;IAED,+EAA+E;IAC/E,IAAI,QAAQ,IAAI,MAAM,CAGrB;CACD"}
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
import { playTone } from './Synth.js';
|
|
2
|
+
const DEFAULT_TEMPO = 500000; // 120 BPM
|
|
3
|
+
/** Reads format 0/1 Standard MIDI File bytes into a flat, tick-ordered event list. */
|
|
4
|
+
export function parseMidi(data) {
|
|
5
|
+
const bytes = data instanceof ArrayBuffer
|
|
6
|
+
? new Uint8Array(data)
|
|
7
|
+
: new Uint8Array(data.buffer, data.byteOffset, data.byteLength);
|
|
8
|
+
const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
|
|
9
|
+
let offset = 0;
|
|
10
|
+
const readAscii = (length) => {
|
|
11
|
+
let text = '';
|
|
12
|
+
for (let i = 0; i < length; i++)
|
|
13
|
+
text += String.fromCharCode(bytes[offset + i]);
|
|
14
|
+
offset += length;
|
|
15
|
+
return text;
|
|
16
|
+
};
|
|
17
|
+
const readUint32 = () => { const v = view.getUint32(offset, false); offset += 4; return v; };
|
|
18
|
+
const readUint16 = () => { const v = view.getUint16(offset, false); offset += 2; return v; };
|
|
19
|
+
const readVLQ = () => {
|
|
20
|
+
let value = 0;
|
|
21
|
+
for (;;) {
|
|
22
|
+
const byte = bytes[offset++];
|
|
23
|
+
value = (value << 7) | (byte & 0x7f);
|
|
24
|
+
if (!(byte & 0x80))
|
|
25
|
+
return value;
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
if (readAscii(4) !== 'MThd' || readUint32() !== 6)
|
|
29
|
+
throw new Error('invalid MIDI header chunk');
|
|
30
|
+
const format = readUint16();
|
|
31
|
+
const trackCount = readUint16();
|
|
32
|
+
const division = readUint16();
|
|
33
|
+
if (format !== 0 && format !== 1)
|
|
34
|
+
throw new Error(`unsupported MIDI format ${format}`);
|
|
35
|
+
if (division & 0x8000)
|
|
36
|
+
throw new Error('SMPTE-based MIDI timing is not supported');
|
|
37
|
+
const ticksPerQuarter = division;
|
|
38
|
+
const events = [];
|
|
39
|
+
for (let t = 0; t < trackCount; t++) {
|
|
40
|
+
const chunkId = readAscii(4);
|
|
41
|
+
const chunkLength = readUint32();
|
|
42
|
+
if (chunkId !== 'MTrk') {
|
|
43
|
+
offset += chunkLength; //an unknown chunk type is skipped, not an error
|
|
44
|
+
continue;
|
|
45
|
+
}
|
|
46
|
+
const end = offset + chunkLength;
|
|
47
|
+
let tick = 0;
|
|
48
|
+
let runningStatus = 0;
|
|
49
|
+
while (offset < end) {
|
|
50
|
+
tick += readVLQ();
|
|
51
|
+
let statusByte = bytes[offset];
|
|
52
|
+
if (statusByte < 0x80) {
|
|
53
|
+
statusByte = runningStatus; //this byte is actually the first data byte
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
offset++;
|
|
57
|
+
if (statusByte < 0xf0)
|
|
58
|
+
runningStatus = statusByte; //meta/sysex never become running status
|
|
59
|
+
}
|
|
60
|
+
if (statusByte === 0xff) {
|
|
61
|
+
const metaType = bytes[offset++];
|
|
62
|
+
const length = readVLQ();
|
|
63
|
+
if (metaType === 0x51 && length === 3) {
|
|
64
|
+
const microsecondsPerQuarter = (bytes[offset] << 16) | (bytes[offset + 1] << 8) | bytes[offset + 2];
|
|
65
|
+
events.push({ tick, type: 'tempo', microsecondsPerQuarter });
|
|
66
|
+
}
|
|
67
|
+
offset += length;
|
|
68
|
+
}
|
|
69
|
+
else if (statusByte === 0xf0 || statusByte === 0xf7) {
|
|
70
|
+
offset += readVLQ();
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
const type = statusByte & 0xf0;
|
|
74
|
+
const channel = statusByte & 0x0f;
|
|
75
|
+
if (type === 0x80 || type === 0x90) {
|
|
76
|
+
const note = bytes[offset++];
|
|
77
|
+
const velocity = bytes[offset++];
|
|
78
|
+
const isNoteOn = type === 0x90 && velocity > 0;
|
|
79
|
+
events.push({ tick, type: isNoteOn ? 'noteOn' : 'noteOff', note, velocity, channel });
|
|
80
|
+
}
|
|
81
|
+
else if (type === 0xa0 || type === 0xb0 || type === 0xe0) {
|
|
82
|
+
offset += 2;
|
|
83
|
+
}
|
|
84
|
+
else if (type === 0xc0 || type === 0xd0) {
|
|
85
|
+
offset += 1;
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
throw new Error(`unsupported MIDI status byte 0x${statusByte.toString(16)}`);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
events.sort((a, b) => a.tick - b.tick);
|
|
94
|
+
return { ticksPerQuarter, events };
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Resolves a parsed file's tick-based events into real-time seconds, honouring tempo
|
|
98
|
+
* changes and pairing each note-on with its matching note-off to find a duration. A
|
|
99
|
+
* note-on with no matching note-off (a malformed or truncated file) still sounds, for a
|
|
100
|
+
* short default duration, rather than being dropped silently.
|
|
101
|
+
*/
|
|
102
|
+
export function scheduleMidi(file) {
|
|
103
|
+
const notes = [];
|
|
104
|
+
const active = new Map();
|
|
105
|
+
let tempo = DEFAULT_TEMPO;
|
|
106
|
+
let lastTick = 0;
|
|
107
|
+
let time = 0;
|
|
108
|
+
for (const event of file.events) {
|
|
109
|
+
time += ((event.tick - lastTick) * tempo) / file.ticksPerQuarter / 1_000_000;
|
|
110
|
+
lastTick = event.tick;
|
|
111
|
+
if (event.type === 'tempo') {
|
|
112
|
+
tempo = event.microsecondsPerQuarter;
|
|
113
|
+
continue;
|
|
114
|
+
}
|
|
115
|
+
const key = `${event.channel}:${event.note}`;
|
|
116
|
+
if (event.type === 'noteOn') {
|
|
117
|
+
active.set(key, { time, velocity: event.velocity });
|
|
118
|
+
}
|
|
119
|
+
else {
|
|
120
|
+
const start = active.get(key);
|
|
121
|
+
if (start) {
|
|
122
|
+
notes.push({ time: start.time, duration: Math.max(0.01, time - start.time), note: event.note, velocity: start.velocity, channel: event.channel });
|
|
123
|
+
active.delete(key);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
for (const [key, start] of active) {
|
|
128
|
+
const [channel, note] = key.split(':').map(Number);
|
|
129
|
+
notes.push({ time: start.time, duration: 0.3, note, velocity: start.velocity, channel });
|
|
130
|
+
}
|
|
131
|
+
return notes.sort((a, b) => a.time - b.time);
|
|
132
|
+
}
|
|
133
|
+
/** MIDI note 69 (A4) is 440 Hz; each semitone is a twelfth root of two step */
|
|
134
|
+
export function noteToFrequency(note) {
|
|
135
|
+
return 440 * 2 ** ((note - 69) / 12);
|
|
136
|
+
}
|
|
137
|
+
/** Plays a parsed `MidiFile` back through `mwg/audio`'s waveform synth, one tone per note, driven by `update(dt)` like every other dt-driven piece of `mwg/core`. */
|
|
138
|
+
export class MidiPlayer {
|
|
139
|
+
constructor(file, options = {}) {
|
|
140
|
+
this.elapsed = 0;
|
|
141
|
+
this.index = 0;
|
|
142
|
+
this.playing = false;
|
|
143
|
+
this.notes = scheduleMidi(file);
|
|
144
|
+
this.playFn = options.play ?? playTone;
|
|
145
|
+
this.waveform = options.waveform ?? 'square';
|
|
146
|
+
this.volume = options.volume ?? 0.2;
|
|
147
|
+
}
|
|
148
|
+
play() {
|
|
149
|
+
this.playing = this.index < this.notes.length;
|
|
150
|
+
}
|
|
151
|
+
pause() {
|
|
152
|
+
this.playing = false;
|
|
153
|
+
}
|
|
154
|
+
/** stops and rewinds to the beginning */
|
|
155
|
+
stop() {
|
|
156
|
+
this.playing = false;
|
|
157
|
+
this.elapsed = 0;
|
|
158
|
+
this.index = 0;
|
|
159
|
+
}
|
|
160
|
+
update(dt) {
|
|
161
|
+
if (!this.playing)
|
|
162
|
+
return;
|
|
163
|
+
this.elapsed += dt;
|
|
164
|
+
while (this.index < this.notes.length && this.notes[this.index].time <= this.elapsed) {
|
|
165
|
+
const note = this.notes[this.index];
|
|
166
|
+
this.playFn({
|
|
167
|
+
waveform: this.waveform,
|
|
168
|
+
frequency: noteToFrequency(note.note),
|
|
169
|
+
duration: note.duration,
|
|
170
|
+
volume: this.volume * (note.velocity / 127),
|
|
171
|
+
});
|
|
172
|
+
this.index++;
|
|
173
|
+
}
|
|
174
|
+
if (this.index >= this.notes.length)
|
|
175
|
+
this.playing = false;
|
|
176
|
+
}
|
|
177
|
+
get isPlaying() {
|
|
178
|
+
return this.playing;
|
|
179
|
+
}
|
|
180
|
+
/** total playback length in seconds, from the last scheduled note's own end */
|
|
181
|
+
get duration() {
|
|
182
|
+
const last = this.notes.at(-1);
|
|
183
|
+
return last ? last.time + last.duration : 0;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
//# sourceMappingURL=Midi.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Midi.js","sourceRoot":"","sources":["../../src/audio/Midi.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Music.d.ts","sourceRoot":"","sources":["../../src/audio/Music.ts"],"names":[],"mappings":"AAAA,OAAO,EAAe,KAAK,QAAQ,EAAE,MAAM,eAAe,CAAC;AAW3D,MAAM,WAAW,YAAY;IAC5B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,QAAQ,CAAC;CACpC;AAED;;;;GAIG;AACH,qBAAa,KAAK;IACjB,OAAO,CAAC,OAAO,CAAyB;IACxC,OAAO,CAAC,KAAK,CAAc;IAC3B,OAAO,CAAC,MAAM,CAA6B;IAC3C,MAAM,EAAE,MAAM,CAAC;IAEf,YAAY,OAAO,GAAE,YAAiB,EAGrC;IAED,4EAA4E;IAC5E,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,YAAY,SAAI,GAAG,IAAI,
|
|
1
|
+
{"version":3,"file":"Music.d.ts","sourceRoot":"","sources":["../../src/audio/Music.ts"],"names":[],"mappings":"AAAA,OAAO,EAAe,KAAK,QAAQ,EAAE,MAAM,eAAe,CAAC;AAW3D,MAAM,WAAW,YAAY;IAC5B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,QAAQ,CAAC;CACpC;AAED;;;;GAIG;AACH,qBAAa,KAAK;IACjB,OAAO,CAAC,OAAO,CAAyB;IACxC,OAAO,CAAC,KAAK,CAAc;IAC3B,OAAO,CAAC,MAAM,CAA6B;IAC3C,MAAM,EAAE,MAAM,CAAC;IAEf,YAAY,OAAO,GAAE,YAAiB,EAGrC;IAED,4EAA4E;IAC5E,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,YAAY,SAAI,GAAG,IAAI,CA+BzC;IAED,IAAI,CAAC,YAAY,SAAI,GAAG,IAAI,CAU3B;IAED,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAevB;CACD"}
|
package/dist/audio/Music.js
CHANGED
|
@@ -19,12 +19,15 @@ export class Music {
|
|
|
19
19
|
this.current = incoming;
|
|
20
20
|
if (fadeDuration <= 0) {
|
|
21
21
|
incoming.volume = this.volume;
|
|
22
|
-
|
|
22
|
+
// a rejection here means the switch itself (or the previous.pause() right below)
|
|
23
|
+
// interrupted this play()'s own in-flight load - expected during a track switch,
|
|
24
|
+
// so swallow it the standard way rather than let it surface as unhandled.
|
|
25
|
+
void Promise.resolve(incoming.play()).catch(() => { });
|
|
23
26
|
previous?.pause();
|
|
24
27
|
return;
|
|
25
28
|
}
|
|
26
29
|
incoming.volume = 0;
|
|
27
|
-
void incoming.play();
|
|
30
|
+
void Promise.resolve(incoming.play()).catch(() => { });
|
|
28
31
|
this.fades.push({ audio: incoming, elapsed: 0, duration: fadeDuration, from: 0, to: this.volume, stopAtEnd: false });
|
|
29
32
|
if (previous) {
|
|
30
33
|
this.fades.push({
|
package/dist/audio/Music.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Music.js","sourceRoot":"","sources":["../../src/audio/Music.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAiB,MAAM,eAAe,CAAC;AAgB3D;;;;GAIG;AACH,MAAM,OAAO,KAAK;IAMjB,YAAY,OAAO,GAAiB,EAAE;QAL9B,YAAO,GAAoB,IAAI,CAAC;QAChC,UAAK,GAAW,EAAE,CAAC;QAK1B,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,CAAC,CAAC;QAClC,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,WAAW,CAAC;IAC7C,CAAC;IAED,4EAA4E;IAC5E,IAAI,CAAC,IAAY,EAAE,YAAY,GAAG,CAAC;QAClC,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QACnC,QAAQ,CAAC,IAAI,GAAG,IAAI,CAAC;QAErB,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC;QAC9B,IAAI,CAAC,OAAO,GAAG,QAAQ,CAAC;QAExB,IAAI,YAAY,IAAI,CAAC,EAAE,CAAC;YACvB,QAAQ,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;YAC9B,KAAK,QAAQ,CAAC,IAAI,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"Music.js","sourceRoot":"","sources":["../../src/audio/Music.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { Music } from './Music.ts';
|
|
2
|
+
import type { Sound } from './Sound.ts';
|
|
3
|
+
/** what playing this state's music should look like - `fadeDuration` follows `Music.play`'s own default */
|
|
4
|
+
export interface OrchestratorState {
|
|
5
|
+
track: string;
|
|
6
|
+
fadeDuration?: number;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* The data a game writes once instead of scattering `Music.play`/`Sound.play` calls across
|
|
10
|
+
* every place a fight starts or a menu opens: name the states ("exploring", "combat",
|
|
11
|
+
* "boss", "menu") and the cues ("hit", "levelUp"), and call `enter`/`trigger` by name from
|
|
12
|
+
* then on.
|
|
13
|
+
*
|
|
14
|
+
* `enter` is idempotent by track, not by state name - two state names that happen to map to
|
|
15
|
+
* the same track will not refade into each other either, since there is nothing to refade
|
|
16
|
+
* to. Re-entering "combat" mid-fight (the same fight, the same track) must not reset the
|
|
17
|
+
* music, which is the one behaviour a direct `Music.play` call at every call site cannot
|
|
18
|
+
* give you for free: the orchestrator remembers the current track and treats entering an
|
|
19
|
+
* already-current one as a no-op.
|
|
20
|
+
*
|
|
21
|
+
* Cues are separate from states because they are fire-and-forget one-shots (`Sound`, not
|
|
22
|
+
* `Music`) - folding them into `enter` would conflate "this is where we are" with "this just
|
|
23
|
+
* happened".
|
|
24
|
+
*/
|
|
25
|
+
export declare class Orchestrator {
|
|
26
|
+
private states;
|
|
27
|
+
private cues;
|
|
28
|
+
private currentTrack;
|
|
29
|
+
private music;
|
|
30
|
+
constructor(music: Music);
|
|
31
|
+
/** defines or replaces one state's music mapping */
|
|
32
|
+
define(state: string, mapping: OrchestratorState): void;
|
|
33
|
+
/** switches to `state`'s track, crossfading; a no-op if that track is already playing */
|
|
34
|
+
enter(state: string): void;
|
|
35
|
+
/** registers the one-shot sound played by `trigger(event)` */
|
|
36
|
+
on(event: string, cue: Sound): void;
|
|
37
|
+
/** plays the sound registered for `event`, if any; silently does nothing otherwise */
|
|
38
|
+
trigger(event: string): void;
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=Orchestrator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Orchestrator.d.ts","sourceRoot":"","sources":["../../src/audio/Orchestrator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACxC,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAExC,2GAA2G;AAC3G,MAAM,WAAW,iBAAiB;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,qBAAa,YAAY;IACxB,OAAO,CAAC,MAAM,CAAwC;IACtD,OAAO,CAAC,IAAI,CAA4B;IACxC,OAAO,CAAC,YAAY,CAAuB;IAC3C,OAAO,CAAC,KAAK,CAAQ;IAErB,YAAY,KAAK,EAAE,KAAK,EAEvB;IAED,oDAAoD;IACpD,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,iBAAiB,GAAG,IAAI,CAEtD;IAED,yFAAyF;IACzF,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAQzB;IAED,8DAA8D;IAC9D,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,KAAK,GAAG,IAAI,CAElC;IAED,sFAAsF;IACtF,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAE3B;CACD"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The data a game writes once instead of scattering `Music.play`/`Sound.play` calls across
|
|
3
|
+
* every place a fight starts or a menu opens: name the states ("exploring", "combat",
|
|
4
|
+
* "boss", "menu") and the cues ("hit", "levelUp"), and call `enter`/`trigger` by name from
|
|
5
|
+
* then on.
|
|
6
|
+
*
|
|
7
|
+
* `enter` is idempotent by track, not by state name - two state names that happen to map to
|
|
8
|
+
* the same track will not refade into each other either, since there is nothing to refade
|
|
9
|
+
* to. Re-entering "combat" mid-fight (the same fight, the same track) must not reset the
|
|
10
|
+
* music, which is the one behaviour a direct `Music.play` call at every call site cannot
|
|
11
|
+
* give you for free: the orchestrator remembers the current track and treats entering an
|
|
12
|
+
* already-current one as a no-op.
|
|
13
|
+
*
|
|
14
|
+
* Cues are separate from states because they are fire-and-forget one-shots (`Sound`, not
|
|
15
|
+
* `Music`) - folding them into `enter` would conflate "this is where we are" with "this just
|
|
16
|
+
* happened".
|
|
17
|
+
*/
|
|
18
|
+
export class Orchestrator {
|
|
19
|
+
constructor(music) {
|
|
20
|
+
this.states = new Map();
|
|
21
|
+
this.cues = new Map();
|
|
22
|
+
this.currentTrack = null;
|
|
23
|
+
this.music = music;
|
|
24
|
+
}
|
|
25
|
+
/** defines or replaces one state's music mapping */
|
|
26
|
+
define(state, mapping) {
|
|
27
|
+
this.states.set(state, mapping);
|
|
28
|
+
}
|
|
29
|
+
/** switches to `state`'s track, crossfading; a no-op if that track is already playing */
|
|
30
|
+
enter(state) {
|
|
31
|
+
const mapping = this.states.get(state);
|
|
32
|
+
if (!mapping)
|
|
33
|
+
throw new Error(`Orchestrator: no state defined for "${state}"`);
|
|
34
|
+
if (mapping.track === this.currentTrack)
|
|
35
|
+
return;
|
|
36
|
+
this.music.play(mapping.track, mapping.fadeDuration);
|
|
37
|
+
this.currentTrack = mapping.track;
|
|
38
|
+
}
|
|
39
|
+
/** registers the one-shot sound played by `trigger(event)` */
|
|
40
|
+
on(event, cue) {
|
|
41
|
+
this.cues.set(event, cue);
|
|
42
|
+
}
|
|
43
|
+
/** plays the sound registered for `event`, if any; silently does nothing otherwise */
|
|
44
|
+
trigger(event) {
|
|
45
|
+
this.cues.get(event)?.play();
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=Orchestrator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Orchestrator.js","sourceRoot":"","sources":["../../src/audio/Orchestrator.ts"],"names":[],"mappings":"AASA;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,OAAO,YAAY;IAMxB,YAAY,KAAY;QALhB,WAAM,GAAG,IAAI,GAAG,EAA6B,CAAC;QAC9C,SAAI,GAAG,IAAI,GAAG,EAAiB,CAAC;QAChC,iBAAY,GAAkB,IAAI,CAAC;QAI1C,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;IACpB,CAAC;IAED,oDAAoD;IACpD,MAAM,CAAC,KAAa,EAAE,OAA0B;QAC/C,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;IACjC,CAAC;IAED,yFAAyF;IACzF,KAAK,CAAC,KAAa;QAClB,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QACvC,IAAI,CAAC,OAAO;YAAE,MAAM,IAAI,KAAK,CAAC,uCAAuC,KAAK,GAAG,CAAC,CAAC;QAE/E,IAAI,OAAO,CAAC,KAAK,KAAK,IAAI,CAAC,YAAY;YAAE,OAAO;QAEhD,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,OAAO,CAAC,YAAY,CAAC,CAAC;QACrD,IAAI,CAAC,YAAY,GAAG,OAAO,CAAC,KAAK,CAAC;IACnC,CAAC;IAED,8DAA8D;IAC9D,EAAE,CAAC,KAAa,EAAE,GAAU;QAC3B,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IAC3B,CAAC;IAED,sFAAsF;IACtF,OAAO,CAAC,KAAa;QACpB,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,CAAC;IAC9B,CAAC;CACD"}
|
package/dist/audio/Sound.d.ts
CHANGED
|
@@ -5,6 +5,8 @@ export interface SoundOptions {
|
|
|
5
5
|
volume?: number;
|
|
6
6
|
/** creates one playable instance for the resolved path; defaults to a real `Audio` element */
|
|
7
7
|
create?: (path: string) => Playable;
|
|
8
|
+
/** shown by a captioning overlay (via `Captions.onCaption`) every time this sound plays */
|
|
9
|
+
caption?: string;
|
|
8
10
|
}
|
|
9
11
|
/**
|
|
10
12
|
* A sound effect, pooled so the same clip can overlap itself. A dozen arrows landing in the
|
|
@@ -15,6 +17,7 @@ export interface SoundOptions {
|
|
|
15
17
|
export declare class Sound {
|
|
16
18
|
private pool;
|
|
17
19
|
private next;
|
|
20
|
+
private caption?;
|
|
18
21
|
volume: number;
|
|
19
22
|
constructor(path: string, options?: SoundOptions);
|
|
20
23
|
play(): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Sound.d.ts","sourceRoot":"","sources":["../../src/audio/Sound.ts"],"names":[],"mappings":"AAAA,OAAO,EAAe,KAAK,QAAQ,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"Sound.d.ts","sourceRoot":"","sources":["../../src/audio/Sound.ts"],"names":[],"mappings":"AAAA,OAAO,EAAe,KAAK,QAAQ,EAAE,MAAM,eAAe,CAAC;AAG3D,MAAM,WAAW,YAAY;IAC5B,4FAA4F;IAC5F,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB,8FAA8F;IAC9F,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,QAAQ,CAAC;IAEpC,2FAA2F;IAC3F,OAAO,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;;GAKG;AACH,qBAAa,KAAK;IACjB,OAAO,CAAC,IAAI,CAAa;IACzB,OAAO,CAAC,IAAI,CAAK;IACjB,OAAO,CAAC,OAAO,CAAC,CAAS;IACzB,MAAM,EAAE,MAAM,CAAC;IAEf,YAAY,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,YAAiB,EAMnD;IAED,IAAI,IAAI,IAAI,CAYX;IAED,OAAO,IAAI,IAAI,CAKd;CACD"}
|