@datamoc/mw_games 0.1.2 → 0.2.0
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/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 +4 -0
- 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 +96 -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 +40 -11
- 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,52 @@
|
|
|
1
|
+
export class SaveSyncClient {
|
|
2
|
+
constructor(options) {
|
|
3
|
+
if (!options.endpoint)
|
|
4
|
+
throw new Error('save sync endpoint is required');
|
|
5
|
+
this.endpoint = options.endpoint;
|
|
6
|
+
this.timeoutMs = options.timeoutMs ?? 10000;
|
|
7
|
+
if (!(this.timeoutMs > 0))
|
|
8
|
+
throw new Error('save sync timeout must be positive');
|
|
9
|
+
this.fetchFn = options.fetch ?? globalThis.fetch;
|
|
10
|
+
if (!this.fetchFn)
|
|
11
|
+
throw new Error('fetch is unavailable; provide SaveSyncOptions.fetch');
|
|
12
|
+
}
|
|
13
|
+
/** sends an `exportSlot` payload to the endpoint, replacing whatever it held before */
|
|
14
|
+
async upload(payload) {
|
|
15
|
+
if (!payload)
|
|
16
|
+
throw new Error('save sync payload cannot be empty');
|
|
17
|
+
const controller = new AbortController();
|
|
18
|
+
const timer = setTimeout(() => controller.abort(), this.timeoutMs);
|
|
19
|
+
try {
|
|
20
|
+
const response = await this.fetchFn(this.endpoint, {
|
|
21
|
+
method: 'POST',
|
|
22
|
+
headers: { 'content-type': 'application/json' },
|
|
23
|
+
body: JSON.stringify({ payload }),
|
|
24
|
+
signal: controller.signal,
|
|
25
|
+
});
|
|
26
|
+
if (!response.ok)
|
|
27
|
+
throw new Error(`save upload failed with HTTP ${response.status}`);
|
|
28
|
+
return { ok: true, status: response.status };
|
|
29
|
+
}
|
|
30
|
+
finally {
|
|
31
|
+
clearTimeout(timer);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
/** fetches whatever payload the endpoint currently holds, ready for `SaveSystem.importSlot` */
|
|
35
|
+
async download() {
|
|
36
|
+
const controller = new AbortController();
|
|
37
|
+
const timer = setTimeout(() => controller.abort(), this.timeoutMs);
|
|
38
|
+
try {
|
|
39
|
+
const response = await this.fetchFn(this.endpoint, { signal: controller.signal });
|
|
40
|
+
if (!response.ok)
|
|
41
|
+
throw new Error(`save download failed with HTTP ${response.status}`);
|
|
42
|
+
const data = (await response.json());
|
|
43
|
+
if (typeof data.payload !== 'string')
|
|
44
|
+
throw new Error('save download response missing a string payload');
|
|
45
|
+
return data.payload;
|
|
46
|
+
}
|
|
47
|
+
finally {
|
|
48
|
+
clearTimeout(timer);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=SaveSync.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SaveSync.js","sourceRoot":"","sources":["../../src/core/SaveSync.ts"],"names":[],"mappings":"AAiBA,MAAM,OAAO,cAAc;IAK1B,YAAY,OAAwB;QACnC,IAAI,CAAC,OAAO,CAAC,QAAQ;YAAE,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAC;QACzE,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC;QACjC,IAAI,CAAC,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,KAAK,CAAC;QAC5C,IAAI,CAAC,CAAC,IAAI,CAAC,SAAS,GAAG,CAAC,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC;QACjF,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,KAAK,IAAI,UAAU,CAAC,KAAK,CAAC;QACjD,IAAI,CAAC,IAAI,CAAC,OAAO;YAAE,MAAM,IAAI,KAAK,CAAC,qDAAqD,CAAC,CAAC;IAC3F,CAAC;IAED,uFAAuF;IACvF,KAAK,CAAC,MAAM,CAAC,OAAe;QAC3B,IAAI,CAAC,OAAO;YAAE,MAAM,IAAI,KAAK,CAAC,mCAAmC,CAAC,CAAC;QACnE,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;QACzC,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;QACnE,IAAI,CAAC;YACJ,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,EAAE;gBAClD,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;gBAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,CAAC;gBACjC,MAAM,EAAE,UAAU,CAAC,MAAM;aACzB,CAAC,CAAC;YACH,IAAI,CAAC,QAAQ,CAAC,EAAE;gBAAE,MAAM,IAAI,KAAK,CAAC,gCAAgC,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;YACrF,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,EAAE,CAAC;QAC9C,CAAC;gBAAS,CAAC;YACV,YAAY,CAAC,KAAK,CAAC,CAAC;QACrB,CAAC;IACF,CAAC;IAED,+FAA+F;IAC/F,KAAK,CAAC,QAAQ;QACb,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;QACzC,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;QACnE,IAAI,CAAC;YACJ,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,EAAE,EAAE,MAAM,EAAE,UAAU,CAAC,MAAM,EAAE,CAAC,CAAC;YAClF,IAAI,CAAC,QAAQ,CAAC,EAAE;gBAAE,MAAM,IAAI,KAAK,CAAC,kCAAkC,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;YACvF,MAAM,IAAI,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAA0B,CAAC;YAC9D,IAAI,OAAO,IAAI,CAAC,OAAO,KAAK,QAAQ;gBAAE,MAAM,IAAI,KAAK,CAAC,iDAAiD,CAAC,CAAC;YACzG,OAAO,IAAI,CAAC,OAAO,CAAC;QACrB,CAAC;gBAAS,CAAC;YACV,YAAY,CAAC,KAAK,CAAC,CAAC;QACrB,CAAC;IACF,CAAC;CACD"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* XOR-with-a-key text scrambling. This is explicitly **not encryption** and must never be
|
|
3
|
+
* presented to a player or a game's own documentation as one: it stops a save being
|
|
4
|
+
* hand-edited by someone opening it in a text editor, and deliberately nothing stronger -
|
|
5
|
+
* the key is recoverable from the scrambled text plus any known plaintext fragment, the
|
|
6
|
+
* classic XOR weakness, accepted on purpose rather than overlooked. Reach for this only
|
|
7
|
+
* where "not trivially editable" is the actual requirement, per `SaveSystem.exportSlot`'s
|
|
8
|
+
* own use of it.
|
|
9
|
+
*/
|
|
10
|
+
export declare function scramble(text: string, key: string): string;
|
|
11
|
+
/** reverses `scramble`; throws if `key` does not match the one it was scrambled with (garbled UTF-8 rather than a silent wrong answer) */
|
|
12
|
+
export declare function unscramble(payload: string, key: string): string;
|
|
13
|
+
//# sourceMappingURL=Scramble.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Scramble.d.ts","sourceRoot":"","sources":["../../src/core/Scramble.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAO1D;AAED,0IAA0I;AAC1I,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAO/D"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* XOR-with-a-key text scrambling. This is explicitly **not encryption** and must never be
|
|
3
|
+
* presented to a player or a game's own documentation as one: it stops a save being
|
|
4
|
+
* hand-edited by someone opening it in a text editor, and deliberately nothing stronger -
|
|
5
|
+
* the key is recoverable from the scrambled text plus any known plaintext fragment, the
|
|
6
|
+
* classic XOR weakness, accepted on purpose rather than overlooked. Reach for this only
|
|
7
|
+
* where "not trivially editable" is the actual requirement, per `SaveSystem.exportSlot`'s
|
|
8
|
+
* own use of it.
|
|
9
|
+
*/
|
|
10
|
+
export function scramble(text, key) {
|
|
11
|
+
if (!key)
|
|
12
|
+
throw new Error('scramble needs a non-empty key');
|
|
13
|
+
const bytes = new TextEncoder().encode(text);
|
|
14
|
+
const keyBytes = new TextEncoder().encode(key);
|
|
15
|
+
const out = new Uint8Array(bytes.length);
|
|
16
|
+
for (let i = 0; i < bytes.length; i++)
|
|
17
|
+
out[i] = bytes[i] ^ keyBytes[i % keyBytes.length];
|
|
18
|
+
return toBase64(out);
|
|
19
|
+
}
|
|
20
|
+
/** reverses `scramble`; throws if `key` does not match the one it was scrambled with (garbled UTF-8 rather than a silent wrong answer) */
|
|
21
|
+
export function unscramble(payload, key) {
|
|
22
|
+
if (!key)
|
|
23
|
+
throw new Error('scramble needs a non-empty key');
|
|
24
|
+
const bytes = fromBase64(payload);
|
|
25
|
+
const keyBytes = new TextEncoder().encode(key);
|
|
26
|
+
const out = new Uint8Array(bytes.length);
|
|
27
|
+
for (let i = 0; i < bytes.length; i++)
|
|
28
|
+
out[i] = bytes[i] ^ keyBytes[i % keyBytes.length];
|
|
29
|
+
return new TextDecoder('utf-8', { fatal: true }).decode(out);
|
|
30
|
+
}
|
|
31
|
+
function toBase64(bytes) {
|
|
32
|
+
let binary = '';
|
|
33
|
+
for (const byte of bytes)
|
|
34
|
+
binary += String.fromCharCode(byte);
|
|
35
|
+
return btoa(binary);
|
|
36
|
+
}
|
|
37
|
+
function fromBase64(text) {
|
|
38
|
+
const binary = atob(text);
|
|
39
|
+
const bytes = new Uint8Array(binary.length);
|
|
40
|
+
for (let i = 0; i < binary.length; i++)
|
|
41
|
+
bytes[i] = binary.charCodeAt(i);
|
|
42
|
+
return bytes;
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=Scramble.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Scramble.js","sourceRoot":"","sources":["../../src/core/Scramble.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,MAAM,UAAU,QAAQ,CAAC,IAAY,EAAE,GAAW;IACjD,IAAI,CAAC,GAAG;QAAE,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAC;IAC5D,MAAM,KAAK,GAAG,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IAC7C,MAAM,QAAQ,GAAG,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IAC/C,MAAM,GAAG,GAAG,IAAI,UAAU,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IACzC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE;QAAE,GAAG,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAC,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC;IACzF,OAAO,QAAQ,CAAC,GAAG,CAAC,CAAC;AACtB,CAAC;AAED,0IAA0I;AAC1I,MAAM,UAAU,UAAU,CAAC,OAAe,EAAE,GAAW;IACtD,IAAI,CAAC,GAAG;QAAE,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAC;IAC5D,MAAM,KAAK,GAAG,UAAU,CAAC,OAAO,CAAC,CAAC;IAClC,MAAM,QAAQ,GAAG,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IAC/C,MAAM,GAAG,GAAG,IAAI,UAAU,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IACzC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE;QAAE,GAAG,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAC,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC;IACzF,OAAO,IAAI,WAAW,CAAC,OAAO,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;AAC9D,CAAC;AAED,SAAS,QAAQ,CAAC,KAAiB;IAClC,IAAI,MAAM,GAAG,EAAE,CAAC;IAChB,KAAK,MAAM,IAAI,IAAI,KAAK;QAAE,MAAM,IAAI,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;IAC9D,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC;AACrB,CAAC;AAED,SAAS,UAAU,CAAC,IAAY;IAC/B,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1B,MAAM,KAAK,GAAG,IAAI,UAAU,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAC5C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE;QAAE,KAAK,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;IACxE,OAAO,KAAK,CAAC;AACd,CAAC"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One wave: `entries` spawn spread evenly across `duration` seconds, starting `delay`
|
|
3
|
+
* seconds after the spawner itself starts (not after the previous wave ends - waves may
|
|
4
|
+
* overlap, which is exactly what a game escalating toward a boss often wants).
|
|
5
|
+
*/
|
|
6
|
+
export interface Wave<T> {
|
|
7
|
+
delay: number;
|
|
8
|
+
entries: readonly {
|
|
9
|
+
kind: T;
|
|
10
|
+
count: number;
|
|
11
|
+
}[];
|
|
12
|
+
/** spread `entries` across this many seconds; 0 (the default) spawns them all at once */
|
|
13
|
+
duration?: number;
|
|
14
|
+
}
|
|
15
|
+
export interface SpawnerOptions<T> {
|
|
16
|
+
waves: readonly Wave<T>[];
|
|
17
|
+
onSpawn: (kind: T) => void;
|
|
18
|
+
/** fires once, the moment the first entry of a wave actually spawns */
|
|
19
|
+
onWaveStart?: (waveIndex: number) => void;
|
|
20
|
+
/** fires once every scheduled spawn across every wave has happened */
|
|
21
|
+
onComplete?: () => void;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* A `dt`-driven timer for escalating, timed spawning - "wave 3 starts at t+45s, spawns 8 of
|
|
25
|
+
* kind A and 2 of kind B over the next 10s" - distinct in shape from `roguelike.Scheduler`,
|
|
26
|
+
* which orders whose turn it is by energy cost and has no concept of real time at all. Not
|
|
27
|
+
* specific to tower defense: any game with escalating timed spawns (a horde mode, a survival
|
|
28
|
+
* minigame) wants the same primitive.
|
|
29
|
+
*
|
|
30
|
+
* The whole schedule is flattened and sorted once, at construction, rather than tracked wave
|
|
31
|
+
* by wave - simpler to get right, and cheap enough that a spawner is not something a game
|
|
32
|
+
* expects to have thousands of.
|
|
33
|
+
*/
|
|
34
|
+
export declare class Spawner<T> {
|
|
35
|
+
private schedule;
|
|
36
|
+
private cursor;
|
|
37
|
+
private elapsed;
|
|
38
|
+
private startedWaves;
|
|
39
|
+
private completed;
|
|
40
|
+
private onSpawn;
|
|
41
|
+
private onWaveStart?;
|
|
42
|
+
private onComplete?;
|
|
43
|
+
constructor(options: SpawnerOptions<T>);
|
|
44
|
+
update(dt: number): void;
|
|
45
|
+
/** true once every scheduled spawn has happened */
|
|
46
|
+
get isComplete(): boolean;
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=Spawner.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Spawner.d.ts","sourceRoot":"","sources":["../../src/core/Spawner.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,WAAW,IAAI,CAAC,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,SAAS;QAAE,IAAI,EAAE,CAAC,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAE/C,yFAAyF;IACzF,QAAQ,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,cAAc,CAAC,CAAC;IAChC,KAAK,EAAE,SAAS,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;IAC1B,OAAO,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,IAAI,CAAC;IAE3B,uEAAuE;IACvE,WAAW,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAE1C,sEAAsE;IACtE,UAAU,CAAC,EAAE,MAAM,IAAI,CAAC;CACxB;AAQD;;;;;;;;;;GAUG;AACH,qBAAa,OAAO,CAAC,CAAC;IACrB,OAAO,CAAC,QAAQ,CAA2B;IAC3C,OAAO,CAAC,MAAM,CAAK;IACnB,OAAO,CAAC,OAAO,CAAK;IAIpB,OAAO,CAAC,YAAY,CAAqB;IACzC,OAAO,CAAC,SAAS,CAAS;IAE1B,OAAO,CAAC,OAAO,CAAoB;IACnC,OAAO,CAAC,WAAW,CAAC,CAA8B;IAClD,OAAO,CAAC,UAAU,CAAC,CAAa;IAEhC,YAAY,OAAO,EAAE,cAAc,CAAC,CAAC,CAAC,EAuBrC;IAED,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAkBvB;IAED,mDAAmD;IACnD,IAAI,UAAU,IAAI,OAAO,CAExB;CACD"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A `dt`-driven timer for escalating, timed spawning - "wave 3 starts at t+45s, spawns 8 of
|
|
3
|
+
* kind A and 2 of kind B over the next 10s" - distinct in shape from `roguelike.Scheduler`,
|
|
4
|
+
* which orders whose turn it is by energy cost and has no concept of real time at all. Not
|
|
5
|
+
* specific to tower defense: any game with escalating timed spawns (a horde mode, a survival
|
|
6
|
+
* minigame) wants the same primitive.
|
|
7
|
+
*
|
|
8
|
+
* The whole schedule is flattened and sorted once, at construction, rather than tracked wave
|
|
9
|
+
* by wave - simpler to get right, and cheap enough that a spawner is not something a game
|
|
10
|
+
* expects to have thousands of.
|
|
11
|
+
*/
|
|
12
|
+
export class Spawner {
|
|
13
|
+
constructor(options) {
|
|
14
|
+
this.schedule = [];
|
|
15
|
+
this.cursor = 0;
|
|
16
|
+
this.elapsed = 0;
|
|
17
|
+
//a Set, not a single "last" index - overlapping waves (see the Wave doc) interleave in
|
|
18
|
+
//the time-sorted schedule, so a wave already started can recur after a different one's
|
|
19
|
+
//entry sorts between two of its own
|
|
20
|
+
this.startedWaves = new Set();
|
|
21
|
+
this.completed = false;
|
|
22
|
+
this.onSpawn = options.onSpawn;
|
|
23
|
+
this.onWaveStart = options.onWaveStart;
|
|
24
|
+
this.onComplete = options.onComplete;
|
|
25
|
+
options.waves.forEach((wave, waveIndex) => {
|
|
26
|
+
const total = wave.entries.reduce((sum, entry) => sum + entry.count, 0);
|
|
27
|
+
const duration = wave.duration ?? 0;
|
|
28
|
+
let i = 0;
|
|
29
|
+
for (const entry of wave.entries) {
|
|
30
|
+
for (let n = 0; n < entry.count; n++, i++) {
|
|
31
|
+
const spread = total > 1 && duration > 0 ? (i / (total - 1)) * duration : 0;
|
|
32
|
+
this.schedule.push({ time: wave.delay + spread, kind: entry.kind, waveIndex });
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
this.schedule.sort((a, b) => a.time - b.time);
|
|
37
|
+
if (this.schedule.length === 0) {
|
|
38
|
+
this.completed = true;
|
|
39
|
+
this.onComplete?.();
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
update(dt) {
|
|
43
|
+
if (this.completed)
|
|
44
|
+
return;
|
|
45
|
+
this.elapsed += dt;
|
|
46
|
+
while (this.cursor < this.schedule.length && this.schedule[this.cursor].time <= this.elapsed) {
|
|
47
|
+
const spawn = this.schedule[this.cursor];
|
|
48
|
+
if (!this.startedWaves.has(spawn.waveIndex)) {
|
|
49
|
+
this.startedWaves.add(spawn.waveIndex);
|
|
50
|
+
this.onWaveStart?.(spawn.waveIndex);
|
|
51
|
+
}
|
|
52
|
+
this.onSpawn(spawn.kind);
|
|
53
|
+
this.cursor++;
|
|
54
|
+
}
|
|
55
|
+
if (this.cursor >= this.schedule.length) {
|
|
56
|
+
this.completed = true;
|
|
57
|
+
this.onComplete?.();
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
/** true once every scheduled spawn has happened */
|
|
61
|
+
get isComplete() {
|
|
62
|
+
return this.completed;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=Spawner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Spawner.js","sourceRoot":"","sources":["../../src/core/Spawner.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The one interpolation primitive every dt-driven feature wants: given a duration and a
|
|
3
|
+
* function of progress, run it from 0 to 1 and resolve. `DialogueStage`'s fades and
|
|
4
|
+
* `render.Camera`'s shake decay each used to hand-roll this same shape under a different
|
|
5
|
+
* name; this is that shape, pulled out once.
|
|
6
|
+
*/
|
|
7
|
+
export type Easing = (t: number) => number;
|
|
8
|
+
/** a small standard set, named the way CSS and most engines already do */
|
|
9
|
+
export declare const Easing: Record<'linear' | 'easeInQuad' | 'easeOutQuad' | 'easeInOutQuad' | 'easeInCubic' | 'easeOutCubic' | 'easeInOutCubic', Easing>;
|
|
10
|
+
/** Runs any number of concurrent tweens; a game or a widget drives it from its own `update(dt)`. */
|
|
11
|
+
export declare class Tweener {
|
|
12
|
+
private tweens;
|
|
13
|
+
/**
|
|
14
|
+
* Runs `apply` with progress eased from 0 to 1 over `duration` seconds, resolving once it
|
|
15
|
+
* reaches 1. A non-positive duration applies the end state at once rather than waiting a
|
|
16
|
+
* frame for it.
|
|
17
|
+
*/
|
|
18
|
+
tween(duration: number, apply: (t: number) => void, ease?: Easing): Promise<void>;
|
|
19
|
+
update(dt: number): void;
|
|
20
|
+
/** true while any tween is still running */
|
|
21
|
+
get isBusy(): boolean;
|
|
22
|
+
/** drops every running tween without applying its end state or resolving it - a teardown, not a completion */
|
|
23
|
+
clear(): void;
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=Tween.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Tween.d.ts","sourceRoot":"","sources":["../../src/core/Tween.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,MAAM,MAAM,GAAG,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,CAAC;AAE3C,0EAA0E;AAC1E,eAAO,MAAM,MAAM,EAAE,MAAM,CAC1B,QAAQ,GAAG,YAAY,GAAG,aAAa,GAAG,eAAe,GAAG,aAAa,GAAG,cAAc,GAAG,gBAAgB,EAC7G,MAAM,CASN,CAAC;AAUF,oGAAoG;AACpG,qBAAa,OAAO;IACnB,OAAO,CAAC,MAAM,CAAqB;IAEnC;;;;OAIG;IACH,KAAK,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,IAAI,EAAE,IAAI,GAAE,MAAsB,GAAG,OAAO,CAAC,IAAI,CAAC,CAQ/F;IAED,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAevB;IAED,4CAA4C;IAC5C,IAAI,MAAM,IAAI,OAAO,CAEpB;IAED,8GAA8G;IAC9G,KAAK,IAAI,IAAI,CAEZ;CACD"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The one interpolation primitive every dt-driven feature wants: given a duration and a
|
|
3
|
+
* function of progress, run it from 0 to 1 and resolve. `DialogueStage`'s fades and
|
|
4
|
+
* `render.Camera`'s shake decay each used to hand-roll this same shape under a different
|
|
5
|
+
* name; this is that shape, pulled out once.
|
|
6
|
+
*/
|
|
7
|
+
/** a small standard set, named the way CSS and most engines already do */
|
|
8
|
+
export const Easing = {
|
|
9
|
+
linear: (t) => t,
|
|
10
|
+
easeInQuad: (t) => t * t,
|
|
11
|
+
easeOutQuad: (t) => t * (2 - t),
|
|
12
|
+
easeInOutQuad: (t) => (t < 0.5 ? 2 * t * t : 1 - ((-2 * t + 2) ** 2) / 2),
|
|
13
|
+
easeInCubic: (t) => t * t * t,
|
|
14
|
+
easeOutCubic: (t) => 1 - (1 - t) ** 3,
|
|
15
|
+
easeInOutCubic: (t) => (t < 0.5 ? 4 * t * t * t : 1 - ((-2 * t + 2) ** 3) / 2),
|
|
16
|
+
};
|
|
17
|
+
/** Runs any number of concurrent tweens; a game or a widget drives it from its own `update(dt)`. */
|
|
18
|
+
export class Tweener {
|
|
19
|
+
constructor() {
|
|
20
|
+
this.tweens = [];
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Runs `apply` with progress eased from 0 to 1 over `duration` seconds, resolving once it
|
|
24
|
+
* reaches 1. A non-positive duration applies the end state at once rather than waiting a
|
|
25
|
+
* frame for it.
|
|
26
|
+
*/
|
|
27
|
+
tween(duration, apply, ease = Easing.linear) {
|
|
28
|
+
if (!(duration > 0)) {
|
|
29
|
+
apply(1);
|
|
30
|
+
return Promise.resolve();
|
|
31
|
+
}
|
|
32
|
+
return new Promise((resolve) => {
|
|
33
|
+
this.tweens.push({ elapsed: 0, duration, apply, ease, resolve });
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
update(dt) {
|
|
37
|
+
if (this.tweens.length === 0)
|
|
38
|
+
return;
|
|
39
|
+
//iterate a copy: a tween's resolve may start another, which must not be advanced
|
|
40
|
+
//again within this same update
|
|
41
|
+
for (const tween of [...this.tweens]) {
|
|
42
|
+
tween.elapsed += dt;
|
|
43
|
+
const t = Math.min(1, tween.elapsed / tween.duration);
|
|
44
|
+
tween.apply(tween.ease(t));
|
|
45
|
+
if (t >= 1) {
|
|
46
|
+
this.tweens.splice(this.tweens.indexOf(tween), 1);
|
|
47
|
+
tween.resolve();
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
/** true while any tween is still running */
|
|
52
|
+
get isBusy() {
|
|
53
|
+
return this.tweens.length > 0;
|
|
54
|
+
}
|
|
55
|
+
/** drops every running tween without applying its end state or resolving it - a teardown, not a completion */
|
|
56
|
+
clear() {
|
|
57
|
+
this.tweens = [];
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=Tween.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Tween.js","sourceRoot":"","sources":["../../src/core/Tween.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,0EAA0E;AAC1E,MAAM,CAAC,MAAM,MAAM,GAGf;IACH,MAAM,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAChB,UAAU,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC;IACxB,WAAW,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC;IAC/B,aAAa,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;IACzE,WAAW,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC;IAC7B,YAAY,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;IACrC,cAAc,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;CAC9E,CAAC;AAUF,oGAAoG;AACpG,MAAM,OAAO,OAAO;IAApB;QACS,WAAM,GAAkB,EAAE,CAAC;IA2CpC,CAAC;IAzCA;;;;OAIG;IACH,KAAK,CAAC,QAAgB,EAAE,KAA0B,EAAE,IAAI,GAAW,MAAM,CAAC,MAAM;QAC/E,IAAI,CAAC,CAAC,QAAQ,GAAG,CAAC,CAAC,EAAE,CAAC;YACrB,KAAK,CAAC,CAAC,CAAC,CAAC;YACT,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;QAC1B,CAAC;QACD,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;YAC9B,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;QAClE,CAAC,CAAC,CAAC;IACJ,CAAC;IAED,MAAM,CAAC,EAAU;QAChB,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO;QAErC,iFAAiF;QACjF,+BAA+B;QAC/B,KAAK,MAAM,KAAK,IAAI,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;YACtC,KAAK,CAAC,OAAO,IAAI,EAAE,CAAC;YACpB,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,OAAO,GAAG,KAAK,CAAC,QAAQ,CAAC,CAAC;YACtD,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;YAE3B,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;gBACZ,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC;gBAClD,KAAK,CAAC,OAAO,EAAE,CAAC;YACjB,CAAC;QACF,CAAC;IACF,CAAC;IAED,4CAA4C;IAC5C,IAAI,MAAM;QACT,OAAO,IAAI,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC;IAC/B,CAAC;IAED,8GAA8G;IAC9G,KAAK;QACJ,IAAI,CAAC,MAAM,GAAG,EAAE,CAAC;IAClB,CAAC;CACD"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A bounded, generic back/forward step through recent turns - a mode a game opts into
|
|
3
|
+
* (useless in a permadeath roguelike, useful elsewhere), agnostic about what "a turn's
|
|
4
|
+
* state" actually contains the same way `SaveSystem` is agnostic about what "the save"
|
|
5
|
+
* contains: a game serializes its own turn-scoped state (a `Level`, a `BoardGrid`, whatever
|
|
6
|
+
* it has) and this only ever stores and replays snapshots of it, never interprets them.
|
|
7
|
+
*
|
|
8
|
+
* Distinct from `Recorder`/`Player` (item 42), which replay a whole `Input.onAction` log
|
|
9
|
+
* deterministically for testing, not a bounded, player-facing "undo my last move".
|
|
10
|
+
*/
|
|
11
|
+
export interface UndoHistoryOptions {
|
|
12
|
+
/** states retained before the oldest is dropped; defaults to 50 */
|
|
13
|
+
limit?: number;
|
|
14
|
+
}
|
|
15
|
+
export declare class UndoHistory<T> {
|
|
16
|
+
private history;
|
|
17
|
+
private cursor;
|
|
18
|
+
private readonly limit;
|
|
19
|
+
constructor(options?: UndoHistoryOptions);
|
|
20
|
+
/**
|
|
21
|
+
* Records `state` as the new current point - the normal "a turn was taken" case. Any
|
|
22
|
+
* redo history beyond the current point is discarded, the same rule undo/redo everywhere
|
|
23
|
+
* follows: taking a new turn after undoing invalidates whatever future it undid away from.
|
|
24
|
+
*/
|
|
25
|
+
push(state: T): void;
|
|
26
|
+
get canUndo(): boolean;
|
|
27
|
+
get canRedo(): boolean;
|
|
28
|
+
/** steps back one state and returns it; null when already at the oldest retained state */
|
|
29
|
+
undo(): T | null;
|
|
30
|
+
/** steps forward one state and returns it; null when already at the newest state */
|
|
31
|
+
redo(): T | null;
|
|
32
|
+
/** the state at the current point, or null before anything has ever been pushed */
|
|
33
|
+
get current(): T | null;
|
|
34
|
+
/** drops everything - a new game, a floor transition, anywhere undoing across the boundary makes no sense */
|
|
35
|
+
clear(): void;
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=UndoHistory.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"UndoHistory.d.ts","sourceRoot":"","sources":["../../src/core/UndoHistory.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,MAAM,WAAW,kBAAkB;IAClC,mEAAmE;IACnE,KAAK,CAAC,EAAE,MAAM,CAAC;CACf;AAED,qBAAa,WAAW,CAAC,CAAC;IACzB,OAAO,CAAC,OAAO,CAAW;IAC1B,OAAO,CAAC,MAAM,CAAM;IACpB,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAS;IAE/B,YAAY,OAAO,GAAE,kBAAuB,EAE3C;IAED;;;;OAIG;IACH,IAAI,CAAC,KAAK,EAAE,CAAC,GAAG,IAAI,CAKnB;IAED,IAAI,OAAO,IAAI,OAAO,CAErB;IAED,IAAI,OAAO,IAAI,OAAO,CAErB;IAED,0FAA0F;IAC1F,IAAI,IAAI,CAAC,GAAG,IAAI,CAIf;IAED,oFAAoF;IACpF,IAAI,IAAI,CAAC,GAAG,IAAI,CAIf;IAED,mFAAmF;IACnF,IAAI,OAAO,IAAI,CAAC,GAAG,IAAI,CAEtB;IAED,6GAA6G;IAC7G,KAAK,IAAI,IAAI,CAGZ;CACD"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
export class UndoHistory {
|
|
2
|
+
constructor(options = {}) {
|
|
3
|
+
this.history = [];
|
|
4
|
+
this.cursor = -1;
|
|
5
|
+
this.limit = Math.max(1, options.limit ?? 50);
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Records `state` as the new current point - the normal "a turn was taken" case. Any
|
|
9
|
+
* redo history beyond the current point is discarded, the same rule undo/redo everywhere
|
|
10
|
+
* follows: taking a new turn after undoing invalidates whatever future it undid away from.
|
|
11
|
+
*/
|
|
12
|
+
push(state) {
|
|
13
|
+
this.history.length = this.cursor + 1;
|
|
14
|
+
this.history.push(state);
|
|
15
|
+
if (this.history.length > this.limit)
|
|
16
|
+
this.history.shift();
|
|
17
|
+
this.cursor = this.history.length - 1;
|
|
18
|
+
}
|
|
19
|
+
get canUndo() {
|
|
20
|
+
return this.cursor > 0;
|
|
21
|
+
}
|
|
22
|
+
get canRedo() {
|
|
23
|
+
return this.cursor < this.history.length - 1;
|
|
24
|
+
}
|
|
25
|
+
/** steps back one state and returns it; null when already at the oldest retained state */
|
|
26
|
+
undo() {
|
|
27
|
+
if (!this.canUndo)
|
|
28
|
+
return null;
|
|
29
|
+
this.cursor--;
|
|
30
|
+
return this.history[this.cursor];
|
|
31
|
+
}
|
|
32
|
+
/** steps forward one state and returns it; null when already at the newest state */
|
|
33
|
+
redo() {
|
|
34
|
+
if (!this.canRedo)
|
|
35
|
+
return null;
|
|
36
|
+
this.cursor++;
|
|
37
|
+
return this.history[this.cursor];
|
|
38
|
+
}
|
|
39
|
+
/** the state at the current point, or null before anything has ever been pushed */
|
|
40
|
+
get current() {
|
|
41
|
+
return this.cursor >= 0 ? this.history[this.cursor] : null;
|
|
42
|
+
}
|
|
43
|
+
/** drops everything - a new game, a floor transition, anywhere undoing across the boundary makes no sense */
|
|
44
|
+
clear() {
|
|
45
|
+
this.history = [];
|
|
46
|
+
this.cursor = -1;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=UndoHistory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"UndoHistory.js","sourceRoot":"","sources":["../../src/core/UndoHistory.ts"],"names":[],"mappings":"AAeA,MAAM,OAAO,WAAW;IAKvB,YAAY,OAAO,GAAuB,EAAE;QAJpC,YAAO,GAAQ,EAAE,CAAC;QAClB,WAAM,GAAG,CAAC,CAAC,CAAC;QAInB,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC;IAC/C,CAAC;IAED;;;;OAIG;IACH,IAAI,CAAC,KAAQ;QACZ,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC;QACtC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACzB,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,KAAK;YAAE,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;QAC3D,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC;IACvC,CAAC;IAED,IAAI,OAAO;QACV,OAAO,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC;IACxB,CAAC;IAED,IAAI,OAAO;QACV,OAAO,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC;IAC9C,CAAC;IAED,0FAA0F;IAC1F,IAAI;QACH,IAAI,CAAC,IAAI,CAAC,OAAO;YAAE,OAAO,IAAI,CAAC;QAC/B,IAAI,CAAC,MAAM,EAAE,CAAC;QACd,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAClC,CAAC;IAED,oFAAoF;IACpF,IAAI;QACH,IAAI,CAAC,IAAI,CAAC,OAAO;YAAE,OAAO,IAAI,CAAC;QAC/B,IAAI,CAAC,MAAM,EAAE,CAAC;QACd,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAClC,CAAC;IAED,mFAAmF;IACnF,IAAI,OAAO;QACV,OAAO,IAAI,CAAC,MAAM,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAC5D,CAAC;IAED,6GAA6G;IAC7G,KAAK;QACJ,IAAI,CAAC,OAAO,GAAG,EAAE,CAAC;QAClB,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IAClB,CAAC;CACD"}
|
package/dist/core/index.d.ts
CHANGED
|
@@ -9,9 +9,20 @@ export { Signal } from './Signal.ts';
|
|
|
9
9
|
export type { SignalListener } from './Signal.ts';
|
|
10
10
|
export * as Random from './Random.ts';
|
|
11
11
|
export * as Input from './Input.ts';
|
|
12
|
+
export { PlayerInput } from './PlayerInput.ts';
|
|
13
|
+
export type { PlayerInputOptions } from './PlayerInput.ts';
|
|
12
14
|
export { Generator } from './Random.ts';
|
|
13
15
|
export { SaveSystem } from './Save.ts';
|
|
14
16
|
export type { SaveMeta, SaveData, SaveStorage, SaveSystemOptions } from './Save.ts';
|
|
17
|
+
export { scramble, unscramble } from './Scramble.ts';
|
|
18
|
+
export { SaveSyncClient } from './SaveSync.ts';
|
|
19
|
+
export type { SaveSyncOptions, SaveSyncResponse } from './SaveSync.ts';
|
|
20
|
+
export { RunHistory } from './RunHistory.ts';
|
|
21
|
+
export type { RunHistoryEntry, RunHistoryOptions } from './RunHistory.ts';
|
|
22
|
+
export { NewsClient, NewsSeenTracker } from './News.ts';
|
|
23
|
+
export type { NewsItem, NewsOptions, NewsSeenOptions } from './News.ts';
|
|
24
|
+
export { checkSize, checkNoControlCharacters, sanitizeInboundText, validateSchema } from './Sanitize.ts';
|
|
25
|
+
export type { SizeLimitOptions, Schema } from './Sanitize.ts';
|
|
15
26
|
export { Collection } from './Collection.ts';
|
|
16
27
|
export type { DbRecord, CollectionOptions } from './Collection.ts';
|
|
17
28
|
export { Recorder, Player, serializeReplay, deserializeReplay } from './Replay.ts';
|
|
@@ -20,6 +31,15 @@ export { Achievements } from './Achievements.ts';
|
|
|
20
31
|
export type { AchievementDef } from './Achievements.ts';
|
|
21
32
|
export { Session } from './Session.ts';
|
|
22
33
|
export type { SessionOptions } from './Session.ts';
|
|
34
|
+
export { FeedbackClient } from './Feedback.ts';
|
|
35
|
+
export type { FeedbackOptions, FeedbackRequest, FeedbackResponse } from './Feedback.ts';
|
|
36
|
+
export { Spawner } from './Spawner.ts';
|
|
37
|
+
export type { Wave, SpawnerOptions } from './Spawner.ts';
|
|
23
38
|
export { hexNeighbors, hexDistance, hexLine, hexRange, hexToPixel, pixelToHex } from './Hex.ts';
|
|
24
39
|
export type { HexCoord } from './Hex.ts';
|
|
40
|
+
export { Tweener, Easing } from './Tween.ts';
|
|
41
|
+
export { UndoHistory } from './UndoHistory.ts';
|
|
42
|
+
export type { UndoHistoryOptions } from './UndoHistory.ts';
|
|
43
|
+
export { LoadQueue } from './Loading.ts';
|
|
44
|
+
export type { LoadStatus, LoadTask, LoadTaskContext, LoadSnapshot } from './Loading.ts';
|
|
25
45
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/core/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,YAAY,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,YAAY,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,YAAY,EAAE,QAAQ,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAClE,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,YAAY,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,KAAK,MAAM,MAAM,aAAa,CAAC;AACtC,OAAO,KAAK,KAAK,MAAM,YAAY,CAAC;AACpC,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AACvC,YAAY,EAAE,QAAQ,EAAE,QAAQ,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AACpF,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,YAAY,EAAE,QAAQ,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACnE,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AACnF,YAAY,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,YAAY,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,YAAY,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAChG,YAAY,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"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"}
|
package/dist/core/index.js
CHANGED
|
@@ -5,11 +5,22 @@ export { Logger } from './Log.js';
|
|
|
5
5
|
export { Signal } from './Signal.js';
|
|
6
6
|
export * as Random from './Random.js';
|
|
7
7
|
export * as Input from './Input.js';
|
|
8
|
+
export { PlayerInput } from './PlayerInput.js';
|
|
8
9
|
export { Generator } from './Random.js';
|
|
9
10
|
export { SaveSystem } from './Save.js';
|
|
11
|
+
export { scramble, unscramble } from './Scramble.js';
|
|
12
|
+
export { SaveSyncClient } from './SaveSync.js';
|
|
13
|
+
export { RunHistory } from './RunHistory.js';
|
|
14
|
+
export { NewsClient, NewsSeenTracker } from './News.js';
|
|
15
|
+
export { checkSize, checkNoControlCharacters, sanitizeInboundText, validateSchema } from './Sanitize.js';
|
|
10
16
|
export { Collection } from './Collection.js';
|
|
11
17
|
export { Recorder, Player, serializeReplay, deserializeReplay } from './Replay.js';
|
|
12
18
|
export { Achievements } from './Achievements.js';
|
|
13
19
|
export { Session } from './Session.js';
|
|
20
|
+
export { FeedbackClient } from './Feedback.js';
|
|
21
|
+
export { Spawner } from './Spawner.js';
|
|
14
22
|
export { hexNeighbors, hexDistance, hexLine, hexRange, hexToPixel, pixelToHex } from './Hex.js';
|
|
23
|
+
export { Tweener, Easing } from './Tween.js';
|
|
24
|
+
export { UndoHistory } from './UndoHistory.js';
|
|
25
|
+
export { LoadQueue } from './Loading.js';
|
|
15
26
|
//# sourceMappingURL=index.js.map
|
package/dist/core/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAEnC,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAElC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC,OAAO,KAAK,MAAM,MAAM,aAAa,CAAC;AACtC,OAAO,KAAK,KAAK,MAAM,YAAY,CAAC;AACpC,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAEvC,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAE7C,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAEnF,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEjD,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAEvC,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAEnC,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAElC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC,OAAO,KAAK,MAAM,MAAM,aAAa,CAAC;AACtC,OAAO,KAAK,KAAK,MAAM,YAAY,CAAC;AACpC,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAE/C,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAEvC,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AACrD,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAE/C,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAE7C,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAExD,OAAO,EAAE,SAAS,EAAE,wBAAwB,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAEzG,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAE7C,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAEnF,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEjD,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAEvC,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAE/C,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAEvC,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAEhG,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAE/C,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { Catalog, Direction } from './index.ts';
|
|
2
|
+
export interface FluentOptions {
|
|
3
|
+
direction?: Direction;
|
|
4
|
+
}
|
|
5
|
+
/** Parses the useful, dependency-free subset of FTL used by game message catalogs. */
|
|
6
|
+
export declare function parseFTL(locale: string, source: string, options?: FluentOptions): Catalog;
|
|
7
|
+
//# sourceMappingURL=Fluent.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Fluent.d.ts","sourceRoot":"","sources":["../../src/i18n/Fluent.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,SAAS,EAAiB,MAAM,YAAY,CAAC;AAEpE,MAAM,WAAW,aAAa;IAC7B,SAAS,CAAC,EAAE,SAAS,CAAC;CACtB;AAID,sFAAsF;AACtF,wBAAgB,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,GAAE,aAAkB,GAAG,OAAO,CAuD7F"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/** Parses the useful, dependency-free subset of FTL used by game message catalogs. */
|
|
2
|
+
export function parseFTL(locale, source, options = {}) {
|
|
3
|
+
const messages = {};
|
|
4
|
+
const lines = source.replace(/\r/g, '').split('\n');
|
|
5
|
+
let id = null;
|
|
6
|
+
let value = '';
|
|
7
|
+
let variants = [];
|
|
8
|
+
let selectClosed = false;
|
|
9
|
+
const finish = () => {
|
|
10
|
+
if (!id)
|
|
11
|
+
return;
|
|
12
|
+
if (messages[id] !== undefined)
|
|
13
|
+
throw new Error(`Duplicate FTL message: ${id}`);
|
|
14
|
+
if (variants.length) {
|
|
15
|
+
if (!selectClosed)
|
|
16
|
+
throw new Error(`FTL select expression is not closed: ${id}`);
|
|
17
|
+
const selector = value.trim().match(/^\{\s*\$([\w-]+)\s*->\s*$/)?.[1];
|
|
18
|
+
if (!selector)
|
|
19
|
+
throw new Error(`Invalid FTL selector: ${value}`);
|
|
20
|
+
messages[id] = selectMessage(locale, selector, variants);
|
|
21
|
+
}
|
|
22
|
+
else {
|
|
23
|
+
messages[id] = normalize(value);
|
|
24
|
+
}
|
|
25
|
+
id = null;
|
|
26
|
+
value = '';
|
|
27
|
+
variants = [];
|
|
28
|
+
selectClosed = false;
|
|
29
|
+
};
|
|
30
|
+
for (const line of lines) {
|
|
31
|
+
if (!line.trim() || line.trimStart().startsWith('#'))
|
|
32
|
+
continue;
|
|
33
|
+
const message = line.match(/^([\w-]+)\s*=\s*(.*)$/);
|
|
34
|
+
if (message) {
|
|
35
|
+
finish();
|
|
36
|
+
id = message[1];
|
|
37
|
+
value = message[2];
|
|
38
|
+
continue;
|
|
39
|
+
}
|
|
40
|
+
if (!id)
|
|
41
|
+
throw new Error(`FTL continuation has no message: ${line}`);
|
|
42
|
+
if (line.trim() === '}') {
|
|
43
|
+
if (!variants.length || selectClosed)
|
|
44
|
+
throw new Error(`Unexpected FTL select terminator: ${line}`);
|
|
45
|
+
selectClosed = true;
|
|
46
|
+
continue;
|
|
47
|
+
}
|
|
48
|
+
if (selectClosed)
|
|
49
|
+
throw new Error(`FTL content follows a closed select expression: ${line}`);
|
|
50
|
+
const variant = line.match(/^\s*(\*)?\[([^\]]+)\]\s*(.*)$/);
|
|
51
|
+
if (variant) {
|
|
52
|
+
variants.push({ key: variant[2], value: variant[3], default: Boolean(variant[1]) });
|
|
53
|
+
continue;
|
|
54
|
+
}
|
|
55
|
+
if (/^\s+/.test(line)) {
|
|
56
|
+
if (variants.length)
|
|
57
|
+
variants[variants.length - 1].value += ` ${line.trim()}`;
|
|
58
|
+
else
|
|
59
|
+
value += ` ${line.trim()}`;
|
|
60
|
+
continue;
|
|
61
|
+
}
|
|
62
|
+
throw new Error(`Invalid FTL line: ${line}`);
|
|
63
|
+
}
|
|
64
|
+
finish();
|
|
65
|
+
return { locale, direction: options.direction ?? (/^(ar|he|fa|ur)(?:-|$)/i.test(locale) ? 'rtl' : 'ltr'), messages };
|
|
66
|
+
}
|
|
67
|
+
function normalize(text) {
|
|
68
|
+
return text.replace(/\{\s*\$([\w-]+)\s*\}/g, '{$1}').trim();
|
|
69
|
+
}
|
|
70
|
+
function selectMessage(locale, selectorName, variants) {
|
|
71
|
+
const defaults = variants.filter((variant) => variant.default);
|
|
72
|
+
if (defaults.length !== 1)
|
|
73
|
+
throw new Error('FTL select expressions need exactly one default variant');
|
|
74
|
+
const defaultVariant = defaults[0];
|
|
75
|
+
const rules = new Intl.PluralRules(locale);
|
|
76
|
+
return {
|
|
77
|
+
format(params = {}) {
|
|
78
|
+
const selector = params[selectorName];
|
|
79
|
+
const exact = variants.find((variant) => variant.key === String(selector));
|
|
80
|
+
const category = typeof selector === 'number' ? rules.select(selector) : '';
|
|
81
|
+
const chosen = exact ?? variants.find((variant) => variant.key === category) ?? defaultVariant;
|
|
82
|
+
return normalize(chosen.value);
|
|
83
|
+
},
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=Fluent.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Fluent.js","sourceRoot":"","sources":["../../src/i18n/Fluent.ts"],"names":[],"mappings":"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"}
|