@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
package/dist/core/Game.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Game.d.ts","sourceRoot":"","sources":["../../src/core/Game.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAiB,MAAM,SAAS,CAAC;AACrD,OAAO,KAAK,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAEpD,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"Game.d.ts","sourceRoot":"","sources":["../../src/core/Game.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAiB,MAAM,SAAS,CAAC;AACrD,OAAO,KAAK,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAEpD,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAkDrC,MAAM,WAAW,WAAW;IAC3B,sEAAsE;IACtE,MAAM,CAAC,EAAE,iBAAiB,CAAC;IAE3B,uDAAuD;IACvD,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB;;;;;;OAMG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IAEnB;;;;;;OAMG;IACH,QAAQ,CAAC,EAAE,WAAW,GAAG,MAAM,CAAC;IAEhC;;;;;;;;;;;;;OAaG;IACH,UAAU,CAAC,EAAE,SAAS,CAAC,MAAM,IAAI,CAAC,EAAE,CAAC;CACrC;AAED;;;;GAIG;AACH,qBAAa,IAAI;IAChB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAqB;IAE5C,QAAQ,CAAC,GAAG,0CAAqB;IAEjC,mEAAmE;IACnE,OAAO,SAAK;IAEZ,wDAAwD;IACxD,SAAS,SAAK;IAEd,+EAA+E;IAC/E,SAAS,SAAK;IAEd,6EAA6E;IAC7E,QAAQ,CAAC,OAAO,iBAAwB;IAExC,OAAO,CAAC,gBAAgB,CAAK;IAC7B,OAAO,CAAC,YAAY,CAAK;IAEzB,OAAO,CAAC,KAAK,CAAoB;IACjC,OAAO,CAAC,OAAO,CAAsB;IACrC,OAAO,CAAC,OAAO,CAAwB;IACvC,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,eAAe,CAA6B;IAEpD,YAAY,OAAO,GAAE,WAAgB,EAwBpC;IAED,6EAA6E;IAC7E,IAAI,KAAK,IAAI,MAAM,CAElB;IAED,IAAI,MAAM,IAAI,MAAM,CAEnB;IAED,wEAAwE;IACxE,MAAM,KAAK,OAAO,IAAI,IAAI,CAGzB;IAEK,KAAK,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CA2D5C;IAED;;;;;OAKG;IACH,WAAW,CAAC,IAAI,EAAE,UAAU,GAAG,IAAI,CAElC;IAED;;;;;;OAMG;IACH,SAAS,CAAC,IAAI,EAAE,UAAU,GAAG,IAAI,CAEhC;IAED;;;;OAIG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,GAAG,IAAI,CAE/B;IAED,yDAAyD;IACzD,IAAI,YAAY,IAAI,KAAK,GAAG,IAAI,CAE/B;IAED;;;;;;OAMG;IACH,OAAO,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,SAAI,GAAG,IAAI,CAGzC;IAED;;;;;;;;OAQG;IACH,IAAI,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAGrB;IAED;;;;;;;;;;OAUG;IACH,OAAO,CAAC,MAAM;IAMd,OAAO,CAAC,KAAK;IA8Bb,OAAO,CAAC,SAAS;IAIjB,0EAA0E;IAC1E,OAAO,CAAC,WAAW;IAanB,+EAA+E;IAC/E,OAAO,CAAC,SAAS;IAYjB,kEAAkE;IAClE,OAAO,CAAC,QAAQ;IAMhB,OAAO,IAAI,IAAI,CAOd;CACD"}
|
package/dist/core/Game.js
CHANGED
|
@@ -17,6 +17,27 @@ function ensurePixelArtStylesheet() {
|
|
|
17
17
|
style.textContent = `.${PIXEL_ART_CLASS} { image-rendering: pixelated; }`;
|
|
18
18
|
document.head.appendChild(style);
|
|
19
19
|
}
|
|
20
|
+
/**
|
|
21
|
+
* Calls back whenever `devicePixelRatio` changes - a browser zoom, or dragging the window
|
|
22
|
+
* to a display with a different scale factor. There is no direct DOM event for this: a
|
|
23
|
+
* `matchMedia` query only fires once, for the specific ratio it was created against, so
|
|
24
|
+
* catching the *next* change means building a fresh query after every firing.
|
|
25
|
+
*
|
|
26
|
+
* @returns a function that stops watching
|
|
27
|
+
*/
|
|
28
|
+
function watchDevicePixelRatio(onChange) {
|
|
29
|
+
let query = null;
|
|
30
|
+
const rearm = () => {
|
|
31
|
+
query = matchMedia(`(resolution: ${window.devicePixelRatio}dppx)`);
|
|
32
|
+
query.addEventListener('change', fire, { once: true });
|
|
33
|
+
};
|
|
34
|
+
const fire = () => {
|
|
35
|
+
onChange();
|
|
36
|
+
rearm();
|
|
37
|
+
};
|
|
38
|
+
rearm();
|
|
39
|
+
return () => query?.removeEventListener('change', fire);
|
|
40
|
+
}
|
|
20
41
|
/**
|
|
21
42
|
* The application: owns the renderer, the loop, and the current scene.
|
|
22
43
|
*
|
|
@@ -34,9 +55,12 @@ export class Game {
|
|
|
34
55
|
this.timeScale = 1;
|
|
35
56
|
/** fires after every frame's update, for systems that are not scene-owned */
|
|
36
57
|
this.onFrame = new Signal();
|
|
58
|
+
this.hitStopRemaining = 0;
|
|
59
|
+
this.hitStopScale = 0;
|
|
37
60
|
this.stack = new SceneStack();
|
|
38
61
|
this.pending = [];
|
|
39
62
|
this.started = false;
|
|
63
|
+
this.stopWatchingDpr = null;
|
|
40
64
|
this.options = {
|
|
41
65
|
canvas: options.canvas ?? document.createElement('canvas'),
|
|
42
66
|
background: options.background ?? 0x000000,
|
|
@@ -111,6 +135,16 @@ export class Game {
|
|
|
111
135
|
this.app.renderer.on('resize', () => {
|
|
112
136
|
this.stack.resize(this.width, this.height);
|
|
113
137
|
});
|
|
138
|
+
//the resolution passed to app.init() above is a one-time snapshot of
|
|
139
|
+
//devicePixelRatio; a later browser zoom (or dragging the window to a display with a
|
|
140
|
+
//different scale factor) changes that ratio without Pixi noticing on its own. Left
|
|
141
|
+
//stale, the backing buffer and the browser's own CSS scaling of the canvas element
|
|
142
|
+
//fall out of a whole-pixel relationship, and nearest-neighbour upscaling of a
|
|
143
|
+
//non-integer ratio duplicates pixel columns inconsistently - the seams a pixel-art
|
|
144
|
+
//tilemap shows between tiles that were perfectly adjacent in the buffer itself.
|
|
145
|
+
this.stopWatchingDpr = watchDevicePixelRatio(() => {
|
|
146
|
+
this.app.renderer.resize(this.width, this.height, window.devicePixelRatio || 1);
|
|
147
|
+
});
|
|
114
148
|
this.expose();
|
|
115
149
|
this.switchNow(first);
|
|
116
150
|
//pixi's ticker drives the loop, so its own systems stay in step with the game
|
|
@@ -147,6 +181,17 @@ export class Game {
|
|
|
147
181
|
get currentScene() {
|
|
148
182
|
return this.stack.current;
|
|
149
183
|
}
|
|
184
|
+
/**
|
|
185
|
+
* Briefly dips `timeScale` toward `scale` for `duration` real seconds, then restores it
|
|
186
|
+
* to 1 - a heavy hit's momentary freeze-frame, distinct from `render.Camera.shake` (which
|
|
187
|
+
* moves the view, not the clock) and from `ui.FloatingText` (a damage number, not a time
|
|
188
|
+
* effect). A second call while one is still running simply replaces it, the same way
|
|
189
|
+
* `Camera.shake` restarts rather than stacking.
|
|
190
|
+
*/
|
|
191
|
+
hitStop(duration, scale = 0) {
|
|
192
|
+
this.hitStopRemaining = duration;
|
|
193
|
+
this.hitStopScale = scale;
|
|
194
|
+
}
|
|
150
195
|
/**
|
|
151
196
|
* Advances the game by one frame and draws it, without waiting for the browser.
|
|
152
197
|
*
|
|
@@ -188,8 +233,16 @@ export class Game {
|
|
|
188
233
|
this.applyPop(request.result);
|
|
189
234
|
}
|
|
190
235
|
this.pending.length = 0;
|
|
236
|
+
if (this.hitStopRemaining > 0) {
|
|
237
|
+
//counts down in real time, not scaled time, or a hit-stop would extend itself
|
|
238
|
+
this.hitStopRemaining -= deltaSeconds;
|
|
239
|
+
this.timeScale = this.hitStopRemaining > 0 ? this.hitStopScale : 1;
|
|
240
|
+
}
|
|
191
241
|
this.elapsed = Math.min(deltaSeconds, this.options.maxDelta) * this.timeScale;
|
|
192
242
|
this.timeTotal += this.elapsed;
|
|
243
|
+
//no native "gamepad button pressed" event exists to attach a listener to, so this
|
|
244
|
+
//has to run once a frame instead, before the scene reads isDown/justPressed
|
|
245
|
+
Input.pollGamepads();
|
|
193
246
|
this.stack.update(this.elapsed);
|
|
194
247
|
this.onFrame.dispatch(this.elapsed);
|
|
195
248
|
//after everything has had a chance to poll it, so nothing misses a press
|
|
@@ -228,6 +281,7 @@ export class Game {
|
|
|
228
281
|
}
|
|
229
282
|
destroy() {
|
|
230
283
|
Input.detach();
|
|
284
|
+
this.stopWatchingDpr?.();
|
|
231
285
|
this.stack.destroy();
|
|
232
286
|
this.onFrame.removeAll();
|
|
233
287
|
this.app.destroy(true, { children: true });
|
package/dist/core/Game.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Game.js","sourceRoot":"","sources":["../../src/core/Game.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAErD,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,KAAK,KAAK,MAAM,YAAY,CAAC;AAEpC,MAAM,eAAe,GAAG,eAAe,CAAC;AAQxC;;;;;GAKG;AACH,SAAS,wBAAwB;IAChC,IAAI,QAAQ,CAAC,cAAc,CAAC,eAAe,CAAC;QAAE,OAAO;IAErD,MAAM,KAAK,GAAG,QAAQ,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;IAC9C,KAAK,CAAC,EAAE,GAAG,eAAe,CAAC;IAC3B,KAAK,CAAC,WAAW,GAAG,IAAI,eAAe,kCAAkC,CAAC;IAC1E,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;AAClC,CAAC;AAoDD;;;;GAIG;AACH,MAAM,OAAO,IAAI;aACD,aAAQ,GAAgB,IAAI,AAApB,CAAqB;
|
|
1
|
+
{"version":3,"file":"Game.js","sourceRoot":"","sources":["../../src/core/Game.ts"],"names":[],"mappings":"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"}
|
package/dist/core/Input.d.ts
CHANGED
|
@@ -15,9 +15,41 @@ export type Action = string;
|
|
|
15
15
|
export declare const onAction: Signal<string>;
|
|
16
16
|
/** fires for every keydown, for the rare case that needs the raw key */
|
|
17
17
|
export declare const onKey: Signal<KeyboardEvent>;
|
|
18
|
+
/**
|
|
19
|
+
* What one wheel notch means, decided by whichever modifier key was held - the same
|
|
20
|
+
* physical wheel serves three different intents depending on it. `'zoom'` is for a game's
|
|
21
|
+
* own in-scene zoom (`render.Camera.zoom`, typically), never the browser's own page/pinch
|
|
22
|
+
* zoom, which `dispatchWheel` already calls `preventDefault()` to stop from firing at the
|
|
23
|
+
* same time.
|
|
24
|
+
*/
|
|
25
|
+
export type WheelAction = 'scroll' | 'scrollHorizontal' | 'zoom';
|
|
26
|
+
export interface WheelInput {
|
|
27
|
+
action: WheelAction;
|
|
28
|
+
/** the raw wheel delta for whichever axis `action` reads; positive is down/right/out */
|
|
29
|
+
delta: number;
|
|
30
|
+
}
|
|
31
|
+
/** fires once per wheel notch, resolved to a `WheelAction` by the held modifier; a listener returning true stops it reaching anything else */
|
|
32
|
+
export declare const onWheel: Signal<WheelInput>;
|
|
33
|
+
/**
|
|
34
|
+
* The documented default modifier convention: plain wheel scrolls vertically, Shift scrolls
|
|
35
|
+
* horizontally (for a game with wide content - `ListView`'s own plain-wheel handling is a
|
|
36
|
+
* single column and does not need this), Ctrl/Cmd zooms. Exported so a game can override the
|
|
37
|
+
* convention itself rather than only being able to work around a baked-in one - unlike the
|
|
38
|
+
* browser's own inconsistent-across-platforms Ctrl+wheel-means-zoom behaviour, which this
|
|
39
|
+
* does not rely on: the modifier check happens here, not left to the browser to interpret.
|
|
40
|
+
*/
|
|
41
|
+
export declare function wheelActionFor(event: Pick<globalThis.WheelEvent, 'ctrlKey' | 'metaKey' | 'shiftKey'>): WheelAction;
|
|
18
42
|
/** the bindings a game starts with; every one can be replaced */
|
|
19
43
|
export declare const DEFAULT_BINDINGS: Readonly<Record<Action, readonly string[]>>;
|
|
20
44
|
export declare function bind(action: Action, keys: readonly string[]): void;
|
|
45
|
+
/**
|
|
46
|
+
* Every action currently bound to `key`, if any - the query a rebind flow needs before
|
|
47
|
+
* committing a captured key, so it can warn (or auto-unbind the loser) instead of two
|
|
48
|
+
* actions silently firing together the moment a key ends up shared between them. `bind`
|
|
49
|
+
* itself does not call this or refuse a collision; nothing about existing behaviour changes
|
|
50
|
+
* for a game that never rebinds.
|
|
51
|
+
*/
|
|
52
|
+
export declare function actionsForKey(key: string): Action[];
|
|
21
53
|
export declare function unbind(action: Action): void;
|
|
22
54
|
export declare function keysFor(action: Action): string[];
|
|
23
55
|
/** every binding, in a shape that can be written to a settings file and read back */
|
|
@@ -36,6 +68,32 @@ export declare function justReleased(action: Action): boolean;
|
|
|
36
68
|
* a `justPressed` would be missed by whatever polls it later in the same frame.
|
|
37
69
|
*/
|
|
38
70
|
export declare function endFrame(): void;
|
|
71
|
+
/** the pseudo key code for button `button` on pad `padIndex` - bind it the same way a `KeyboardEvent.code` is bound */
|
|
72
|
+
export declare function gamepadButtonCode(padIndex: number, button: number): string;
|
|
73
|
+
/** the pseudo key code for axis `axis` pushed past its deadzone in `direction` on pad `padIndex` */
|
|
74
|
+
export declare function gamepadAxisCode(padIndex: number, axis: number, direction: 1 | -1): string;
|
|
75
|
+
export declare function bindButton(action: Action, padIndex: number, buttons: readonly number[]): void;
|
|
76
|
+
export declare function bindAxis(action: Action, padIndex: number, axis: number, direction: 1 | -1): void;
|
|
77
|
+
/**
|
|
78
|
+
* Folds every connected gamepad's buttons and axes into the same held-code state a keydown
|
|
79
|
+
* would produce. There is no native "gamepad button pressed" event to attach a listener to
|
|
80
|
+
* - the Gamepad API only ever hands back a live snapshot - so this has to be polled once a
|
|
81
|
+
* frame instead, which is why `Game` calls it right before updating the scene, before
|
|
82
|
+
* `endFrame` clears the one-frame flags.
|
|
83
|
+
*/
|
|
84
|
+
export declare function pollGamepads(pads?: readonly (Gamepad | null)[]): void;
|
|
85
|
+
export interface RumbleOptions {
|
|
86
|
+
/** milliseconds */
|
|
87
|
+
duration: number;
|
|
88
|
+
weakMagnitude?: number;
|
|
89
|
+
strongMagnitude?: number;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Vibrates one connected gamepad, if it and the browser expose a dual-rumble actuator - a
|
|
93
|
+
* no-op otherwise, rather than throwing, since support is inconsistent across browsers and a
|
|
94
|
+
* game reaching for "juice" should not have to feature-test this itself.
|
|
95
|
+
*/
|
|
96
|
+
export declare function rumble(padIndex: number, options: RumbleOptions, pads?: readonly (Gamepad | null)[]): void;
|
|
39
97
|
export declare function attach(target?: EventTarget): void;
|
|
40
98
|
export declare function detach(target?: EventTarget): void;
|
|
41
99
|
//# sourceMappingURL=Input.d.ts.map
|
package/dist/core/Input.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Input.d.ts","sourceRoot":"","sources":["../../src/core/Input.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC;;;;;;;;;;GAUG;AAEH,MAAM,MAAM,MAAM,GAAG,MAAM,CAAC;AAO5B,6FAA6F;AAC7F,eAAO,MAAM,QAAQ,gBAA2B,CAAC;AAEjD,wEAAwE;AACxE,eAAO,MAAM,KAAK,uBAAkC,CAAC;
|
|
1
|
+
{"version":3,"file":"Input.d.ts","sourceRoot":"","sources":["../../src/core/Input.ts"],"names":[],"mappings":"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"}
|
package/dist/core/Input.js
CHANGED
|
@@ -7,6 +7,33 @@ const releasedThisFrame = new Set();
|
|
|
7
7
|
export const onAction = new Signal(true);
|
|
8
8
|
/** fires for every keydown, for the rare case that needs the raw key */
|
|
9
9
|
export const onKey = new Signal(true);
|
|
10
|
+
/** fires once per wheel notch, resolved to a `WheelAction` by the held modifier; a listener returning true stops it reaching anything else */
|
|
11
|
+
export const onWheel = new Signal(true);
|
|
12
|
+
/**
|
|
13
|
+
* The documented default modifier convention: plain wheel scrolls vertically, Shift scrolls
|
|
14
|
+
* horizontally (for a game with wide content - `ListView`'s own plain-wheel handling is a
|
|
15
|
+
* single column and does not need this), Ctrl/Cmd zooms. Exported so a game can override the
|
|
16
|
+
* convention itself rather than only being able to work around a baked-in one - unlike the
|
|
17
|
+
* browser's own inconsistent-across-platforms Ctrl+wheel-means-zoom behaviour, which this
|
|
18
|
+
* does not rely on: the modifier check happens here, not left to the browser to interpret.
|
|
19
|
+
*/
|
|
20
|
+
export function wheelActionFor(event) {
|
|
21
|
+
if (event.ctrlKey || event.metaKey)
|
|
22
|
+
return 'zoom';
|
|
23
|
+
if (event.shiftKey)
|
|
24
|
+
return 'scrollHorizontal';
|
|
25
|
+
return 'scroll';
|
|
26
|
+
}
|
|
27
|
+
function handleWheel(event) {
|
|
28
|
+
const action = wheelActionFor(event);
|
|
29
|
+
//stops the browser's own page-zoom/pinch-zoom from firing alongside an in-game zoom;
|
|
30
|
+
//plain and shift-scroll are left alone, since preventing those would also block a page
|
|
31
|
+
//that embeds the game from scrolling normally around it
|
|
32
|
+
if (action === 'zoom')
|
|
33
|
+
event.preventDefault();
|
|
34
|
+
const delta = action === 'scrollHorizontal' && event.deltaX !== 0 ? event.deltaX : event.deltaY;
|
|
35
|
+
onWheel.dispatch({ action, delta });
|
|
36
|
+
}
|
|
10
37
|
let attached = false;
|
|
11
38
|
/** the bindings a game starts with; every one can be replaced */
|
|
12
39
|
export const DEFAULT_BINDINGS = {
|
|
@@ -26,6 +53,23 @@ export const DEFAULT_BINDINGS = {
|
|
|
26
53
|
export function bind(action, keys) {
|
|
27
54
|
bindings.set(action, new Set(keys));
|
|
28
55
|
}
|
|
56
|
+
/** adds keys to an action's existing bindings, rather than replacing them like `bind` does */
|
|
57
|
+
function addBindings(action, keys) {
|
|
58
|
+
const set = bindings.get(action) ?? new Set();
|
|
59
|
+
for (const key of keys)
|
|
60
|
+
set.add(key);
|
|
61
|
+
bindings.set(action, set);
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Every action currently bound to `key`, if any - the query a rebind flow needs before
|
|
65
|
+
* committing a captured key, so it can warn (or auto-unbind the loser) instead of two
|
|
66
|
+
* actions silently firing together the moment a key ends up shared between them. `bind`
|
|
67
|
+
* itself does not call this or refuse a collision; nothing about existing behaviour changes
|
|
68
|
+
* for a game that never rebinds.
|
|
69
|
+
*/
|
|
70
|
+
export function actionsForKey(key) {
|
|
71
|
+
return actionsFor(key);
|
|
72
|
+
}
|
|
29
73
|
export function unbind(action) {
|
|
30
74
|
bindings.delete(action);
|
|
31
75
|
}
|
|
@@ -112,6 +156,93 @@ function handleBlur() {
|
|
|
112
156
|
pressedThisFrame.clear();
|
|
113
157
|
releasedThisFrame.clear();
|
|
114
158
|
}
|
|
159
|
+
//---- gamepad and controller input ----
|
|
160
|
+
//
|
|
161
|
+
//a button or axis binds to the same named action a key does, by folding it into the very
|
|
162
|
+
//same `held`/`bindings` state under a synthetic code (`gamepadButtonCode`/`gamepadAxisCode`)
|
|
163
|
+
//that will never collide with a real `KeyboardEvent.code` - `isDown`/`justPressed`/
|
|
164
|
+
//`justReleased`/`actionsForKey` all keep working unmodified, whether an action came from a
|
|
165
|
+
//key or a stick, since none of them know or care where a held code came from.
|
|
166
|
+
const AXIS_DEADZONE = 0.5;
|
|
167
|
+
/** scratch space for `pollGamepads`, reused every call rather than allocated fresh */
|
|
168
|
+
const gamepadDown = new Set();
|
|
169
|
+
/** the pseudo key code for button `button` on pad `padIndex` - bind it the same way a `KeyboardEvent.code` is bound */
|
|
170
|
+
export function gamepadButtonCode(padIndex, button) {
|
|
171
|
+
return `Gamepad${padIndex}Button${button}`;
|
|
172
|
+
}
|
|
173
|
+
/** the pseudo key code for axis `axis` pushed past its deadzone in `direction` on pad `padIndex` */
|
|
174
|
+
export function gamepadAxisCode(padIndex, axis, direction) {
|
|
175
|
+
return `Gamepad${padIndex}Axis${axis}${direction > 0 ? '+' : '-'}`;
|
|
176
|
+
}
|
|
177
|
+
export function bindButton(action, padIndex, buttons) {
|
|
178
|
+
addBindings(action, buttons.map((button) => gamepadButtonCode(padIndex, button)));
|
|
179
|
+
}
|
|
180
|
+
export function bindAxis(action, padIndex, axis, direction) {
|
|
181
|
+
addBindings(action, [gamepadAxisCode(padIndex, axis, direction)]);
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Folds every connected gamepad's buttons and axes into the same held-code state a keydown
|
|
185
|
+
* would produce. There is no native "gamepad button pressed" event to attach a listener to
|
|
186
|
+
* - the Gamepad API only ever hands back a live snapshot - so this has to be polled once a
|
|
187
|
+
* frame instead, which is why `Game` calls it right before updating the scene, before
|
|
188
|
+
* `endFrame` clears the one-frame flags.
|
|
189
|
+
*/
|
|
190
|
+
export function pollGamepads(
|
|
191
|
+
//Node has exposed a global `navigator` since v21, with no `getGamepads` on it - guarding
|
|
192
|
+
//on the method itself, not just the object, is what actually detects a browser
|
|
193
|
+
pads = typeof navigator?.getGamepads === 'function' ? navigator.getGamepads() : []) {
|
|
194
|
+
//reused rather than allocated fresh every call - this runs once a frame, on every frame
|
|
195
|
+
gamepadDown.clear();
|
|
196
|
+
for (const pad of pads) {
|
|
197
|
+
if (!pad)
|
|
198
|
+
continue;
|
|
199
|
+
for (let i = 0; i < pad.buttons.length; i++) {
|
|
200
|
+
if (pad.buttons[i].pressed)
|
|
201
|
+
gamepadDown.add(gamepadButtonCode(pad.index, i));
|
|
202
|
+
}
|
|
203
|
+
for (let i = 0; i < pad.axes.length; i++) {
|
|
204
|
+
const value = pad.axes[i];
|
|
205
|
+
if (value >= AXIS_DEADZONE)
|
|
206
|
+
gamepadDown.add(gamepadAxisCode(pad.index, i, 1));
|
|
207
|
+
else if (value <= -AXIS_DEADZONE)
|
|
208
|
+
gamepadDown.add(gamepadAxisCode(pad.index, i, -1));
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
for (const code of gamepadDown) {
|
|
212
|
+
if (held.has(code))
|
|
213
|
+
continue;
|
|
214
|
+
held.add(code);
|
|
215
|
+
for (const action of actionsFor(code)) {
|
|
216
|
+
pressedThisFrame.add(action);
|
|
217
|
+
onAction.dispatch(action);
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
//a real KeyboardEvent.code never starts with "Gamepad", so this only ever releases codes
|
|
221
|
+
//pollGamepads itself could have added, never a key still held from handleKeyDown; safe to
|
|
222
|
+
//delete the current entry mid-iteration, since Set iteration order is insertion order and
|
|
223
|
+
//a deletion never revisits or skips an entry not yet reached
|
|
224
|
+
for (const code of held) {
|
|
225
|
+
if (gamepadDown.has(code) || !code.startsWith('Gamepad'))
|
|
226
|
+
continue;
|
|
227
|
+
held.delete(code);
|
|
228
|
+
for (const action of actionsFor(code))
|
|
229
|
+
releasedThisFrame.add(action);
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* Vibrates one connected gamepad, if it and the browser expose a dual-rumble actuator - a
|
|
234
|
+
* no-op otherwise, rather than throwing, since support is inconsistent across browsers and a
|
|
235
|
+
* game reaching for "juice" should not have to feature-test this itself.
|
|
236
|
+
*/
|
|
237
|
+
export function rumble(padIndex, options, pads = typeof navigator?.getGamepads === 'function' ? navigator.getGamepads() : []) {
|
|
238
|
+
const pad = pads[padIndex];
|
|
239
|
+
const actuator = pad?.vibrationActuator;
|
|
240
|
+
actuator?.playEffect('dual-rumble', {
|
|
241
|
+
duration: options.duration,
|
|
242
|
+
weakMagnitude: options.weakMagnitude ?? 1,
|
|
243
|
+
strongMagnitude: options.strongMagnitude ?? 1,
|
|
244
|
+
});
|
|
245
|
+
}
|
|
115
246
|
export function attach(target = window) {
|
|
116
247
|
if (attached)
|
|
117
248
|
return;
|
|
@@ -119,6 +250,9 @@ export function attach(target = window) {
|
|
|
119
250
|
target.addEventListener('keydown', handleKeyDown);
|
|
120
251
|
target.addEventListener('keyup', handleKeyUp);
|
|
121
252
|
window.addEventListener('blur', handleBlur);
|
|
253
|
+
//not passive: a zoom notch calls preventDefault() to stop the browser's own page/pinch
|
|
254
|
+
//zoom, which a passive listener is not allowed to do
|
|
255
|
+
target.addEventListener('wheel', handleWheel, { passive: false });
|
|
122
256
|
}
|
|
123
257
|
export function detach(target = window) {
|
|
124
258
|
if (!attached)
|
|
@@ -126,6 +260,7 @@ export function detach(target = window) {
|
|
|
126
260
|
attached = false;
|
|
127
261
|
target.removeEventListener('keydown', handleKeyDown);
|
|
128
262
|
target.removeEventListener('keyup', handleKeyUp);
|
|
263
|
+
target.removeEventListener('wheel', handleWheel);
|
|
129
264
|
window.removeEventListener('blur', handleBlur);
|
|
130
265
|
handleBlur();
|
|
131
266
|
}
|
package/dist/core/Input.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Input.js","sourceRoot":"","sources":["../../src/core/Input.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAgBrC,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAuB,CAAC;AAChD,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;AAC/B,MAAM,gBAAgB,GAAG,IAAI,GAAG,EAAU,CAAC;AAC3C,MAAM,iBAAiB,GAAG,IAAI,GAAG,EAAU,CAAC;AAE5C,6FAA6F;AAC7F,MAAM,CAAC,MAAM,QAAQ,GAAG,IAAI,MAAM,CAAS,IAAI,CAAC,CAAC;AAEjD,wEAAwE;AACxE,MAAM,CAAC,MAAM,KAAK,GAAG,IAAI,MAAM,CAAgB,IAAI,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"Input.js","sourceRoot":"","sources":["../../src/core/Input.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { Signal } from './Signal.ts';
|
|
2
|
+
export type LoadStatus = 'idle' | 'loading' | 'ready' | 'failed' | 'cancelled';
|
|
3
|
+
export interface LoadTaskContext {
|
|
4
|
+
/** reports a task-local fraction, from 0 to 1 */
|
|
5
|
+
report(fraction: number): void;
|
|
6
|
+
/** becomes true after `cancel()`; a task should stop at its next safe boundary */
|
|
7
|
+
readonly cancelled: boolean;
|
|
8
|
+
}
|
|
9
|
+
export interface LoadTask {
|
|
10
|
+
id: string;
|
|
11
|
+
weight?: number;
|
|
12
|
+
run(context: LoadTaskContext): Promise<void> | void;
|
|
13
|
+
}
|
|
14
|
+
export interface LoadSnapshot {
|
|
15
|
+
status: LoadStatus;
|
|
16
|
+
completed: number;
|
|
17
|
+
total: number;
|
|
18
|
+
current: string | null;
|
|
19
|
+
error: unknown | null;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Runs named, weighted asynchronous work while exposing truthful loading progress.
|
|
23
|
+
*
|
|
24
|
+
* Tasks run in order, which makes dependency ordering explicit and leaves a game free to
|
|
25
|
+
* start independent work concurrently inside one task. A task that cannot measure itself
|
|
26
|
+
* simply never calls `report`, so consumers can display an indeterminate current stage
|
|
27
|
+
* instead of inventing a percentage.
|
|
28
|
+
*/
|
|
29
|
+
export declare class LoadQueue {
|
|
30
|
+
readonly changed: Signal<LoadSnapshot>;
|
|
31
|
+
private readonly tasks;
|
|
32
|
+
private readonly progress;
|
|
33
|
+
private status_;
|
|
34
|
+
private current_;
|
|
35
|
+
private error_;
|
|
36
|
+
private cancelled;
|
|
37
|
+
add(task: LoadTask): this;
|
|
38
|
+
get snapshot(): LoadSnapshot;
|
|
39
|
+
/** starts queued work and resolves only after every task succeeds */
|
|
40
|
+
start(): Promise<void>;
|
|
41
|
+
/** asks the current task to stop; cancellation is cooperative */
|
|
42
|
+
cancel(): void;
|
|
43
|
+
/** clears failure/cancellation state and task progress for a new attempt */
|
|
44
|
+
retry(): void;
|
|
45
|
+
private report;
|
|
46
|
+
private emit;
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=Loading.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Loading.d.ts","sourceRoot":"","sources":["../../src/core/Loading.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,SAAS,GAAG,OAAO,GAAG,QAAQ,GAAG,WAAW,CAAC;AAE/E,MAAM,WAAW,eAAe;IAC/B,iDAAiD;IACjD,MAAM,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,kFAAkF;IAClF,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;CAC5B;AAED,MAAM,WAAW,QAAQ;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;CACpD;AAED,MAAM,WAAW,YAAY;IAC5B,MAAM,EAAE,UAAU,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,KAAK,EAAE,OAAO,GAAG,IAAI,CAAC;CACtB;AAED;;;;;;;GAOG;AACH,qBAAa,SAAS;IACrB,QAAQ,CAAC,OAAO,uBAA8B;IAE9C,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAkB;IACxC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA6B;IACtD,OAAO,CAAC,OAAO,CAAsB;IACrC,OAAO,CAAC,QAAQ,CAAuB;IACvC,OAAO,CAAC,MAAM,CAAwB;IACtC,OAAO,CAAC,SAAS,CAAS;IAE1B,GAAG,CAAC,IAAI,EAAE,QAAQ,GAAG,IAAI,CASxB;IAED,IAAI,QAAQ,IAAI,YAAY,CAI3B;IAED,qEAAqE;IAC/D,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CA8B3B;IAED,iEAAiE;IACjE,MAAM,IAAI,IAAI,CAEb;IAED,4EAA4E;IAC5E,KAAK,IAAI,IAAI,CAQZ;IAED,OAAO,CAAC,MAAM;IAMd,OAAO,CAAC,IAAI;CAGZ"}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { Signal } from './Signal.js';
|
|
2
|
+
/**
|
|
3
|
+
* Runs named, weighted asynchronous work while exposing truthful loading progress.
|
|
4
|
+
*
|
|
5
|
+
* Tasks run in order, which makes dependency ordering explicit and leaves a game free to
|
|
6
|
+
* start independent work concurrently inside one task. A task that cannot measure itself
|
|
7
|
+
* simply never calls `report`, so consumers can display an indeterminate current stage
|
|
8
|
+
* instead of inventing a percentage.
|
|
9
|
+
*/
|
|
10
|
+
export class LoadQueue {
|
|
11
|
+
constructor() {
|
|
12
|
+
this.changed = new Signal();
|
|
13
|
+
this.tasks = [];
|
|
14
|
+
this.progress = new Map();
|
|
15
|
+
this.status_ = 'idle';
|
|
16
|
+
this.current_ = null;
|
|
17
|
+
this.error_ = null;
|
|
18
|
+
this.cancelled = false;
|
|
19
|
+
}
|
|
20
|
+
add(task) {
|
|
21
|
+
if (!task.id)
|
|
22
|
+
throw new Error('load task needs an id');
|
|
23
|
+
if (this.tasks.some((candidate) => candidate.id === task.id))
|
|
24
|
+
throw new Error(`duplicate load task "${task.id}"`);
|
|
25
|
+
if (task.weight !== undefined && !(task.weight > 0))
|
|
26
|
+
throw new Error('load task weight must be positive');
|
|
27
|
+
if (this.status_ === 'loading')
|
|
28
|
+
throw new Error('cannot add a task while loading');
|
|
29
|
+
this.tasks.push(task);
|
|
30
|
+
this.progress.set(task.id, 0);
|
|
31
|
+
this.emit();
|
|
32
|
+
return this;
|
|
33
|
+
}
|
|
34
|
+
get snapshot() {
|
|
35
|
+
const total = this.tasks.reduce((sum, task) => sum + (task.weight ?? 1), 0);
|
|
36
|
+
const complete = this.tasks.reduce((sum, task) => sum + (task.weight ?? 1) * (this.progress.get(task.id) ?? 0), 0);
|
|
37
|
+
return { status: this.status_, completed: complete, total, current: this.current_, error: this.error_ };
|
|
38
|
+
}
|
|
39
|
+
/** starts queued work and resolves only after every task succeeds */
|
|
40
|
+
async start() {
|
|
41
|
+
if (this.status_ === 'loading')
|
|
42
|
+
throw new Error('load queue is already running');
|
|
43
|
+
this.status_ = 'loading';
|
|
44
|
+
this.cancelled = false;
|
|
45
|
+
this.error_ = null;
|
|
46
|
+
this.emit();
|
|
47
|
+
try {
|
|
48
|
+
for (const task of this.tasks) {
|
|
49
|
+
if (this.cancelled)
|
|
50
|
+
break;
|
|
51
|
+
this.current_ = task.id;
|
|
52
|
+
this.emit();
|
|
53
|
+
const queue = this;
|
|
54
|
+
await task.run({
|
|
55
|
+
get cancelled() {
|
|
56
|
+
return queue.cancelled;
|
|
57
|
+
},
|
|
58
|
+
report: (fraction) => this.report(task.id, fraction),
|
|
59
|
+
});
|
|
60
|
+
if (!this.cancelled)
|
|
61
|
+
this.report(task.id, 1);
|
|
62
|
+
}
|
|
63
|
+
this.current_ = null;
|
|
64
|
+
this.status_ = this.cancelled ? 'cancelled' : 'ready';
|
|
65
|
+
this.emit();
|
|
66
|
+
}
|
|
67
|
+
catch (error) {
|
|
68
|
+
this.current_ = null;
|
|
69
|
+
this.error_ = error;
|
|
70
|
+
this.status_ = 'failed';
|
|
71
|
+
this.emit();
|
|
72
|
+
throw error;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
/** asks the current task to stop; cancellation is cooperative */
|
|
76
|
+
cancel() {
|
|
77
|
+
if (this.status_ === 'loading')
|
|
78
|
+
this.cancelled = true;
|
|
79
|
+
}
|
|
80
|
+
/** clears failure/cancellation state and task progress for a new attempt */
|
|
81
|
+
retry() {
|
|
82
|
+
if (this.status_ === 'loading')
|
|
83
|
+
throw new Error('cannot retry while loading');
|
|
84
|
+
this.status_ = 'idle';
|
|
85
|
+
this.current_ = null;
|
|
86
|
+
this.error_ = null;
|
|
87
|
+
this.cancelled = false;
|
|
88
|
+
for (const task of this.tasks)
|
|
89
|
+
this.progress.set(task.id, 0);
|
|
90
|
+
this.emit();
|
|
91
|
+
}
|
|
92
|
+
report(id, fraction) {
|
|
93
|
+
if (!Number.isFinite(fraction))
|
|
94
|
+
throw new Error('load progress must be finite');
|
|
95
|
+
this.progress.set(id, Math.max(0, Math.min(1, fraction)));
|
|
96
|
+
this.emit();
|
|
97
|
+
}
|
|
98
|
+
emit() {
|
|
99
|
+
this.changed.dispatch(this.snapshot);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
//# sourceMappingURL=Loading.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Loading.js","sourceRoot":"","sources":["../../src/core/Loading.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { type SaveStorage } from './Save.ts';
|
|
2
|
+
/**
|
|
3
|
+
* Fetches a game's own news/announcements feed - the inbound counterpart to
|
|
4
|
+
* `FeedbackClient`, following the same injectable-transport shape (a game's own HTTPS
|
|
5
|
+
* endpoint, no backend shipped or assumed) rather than a second pattern.
|
|
6
|
+
*/
|
|
7
|
+
export interface NewsItem {
|
|
8
|
+
id: string;
|
|
9
|
+
title: string;
|
|
10
|
+
body: string;
|
|
11
|
+
publishedAt?: number;
|
|
12
|
+
}
|
|
13
|
+
export interface NewsOptions {
|
|
14
|
+
endpoint: string;
|
|
15
|
+
timeoutMs?: number;
|
|
16
|
+
fetch?: typeof globalThis.fetch;
|
|
17
|
+
}
|
|
18
|
+
export declare class NewsClient {
|
|
19
|
+
private readonly endpoint;
|
|
20
|
+
private readonly timeoutMs;
|
|
21
|
+
private readonly fetchFn;
|
|
22
|
+
constructor(options: NewsOptions);
|
|
23
|
+
/**
|
|
24
|
+
* Fetches and validates the feed; a malformed item throws rather than reaching a game as
|
|
25
|
+
* trusted data. The response is read as text and run through `sanitizeInboundText`
|
|
26
|
+
* (a size cap, no embedded control characters) before `JSON.parse` ever sees it, ahead of
|
|
27
|
+
* `normalizeItem`'s own per-field shape check below.
|
|
28
|
+
*/
|
|
29
|
+
fetchItems(): Promise<NewsItem[]>;
|
|
30
|
+
}
|
|
31
|
+
export interface NewsSeenOptions {
|
|
32
|
+
namespace: string;
|
|
33
|
+
storage?: SaveStorage;
|
|
34
|
+
}
|
|
35
|
+
/** which news items a player has already dismissed, so a returning player is not shown the same announcement forever */
|
|
36
|
+
export declare class NewsSeenTracker {
|
|
37
|
+
private readonly storage;
|
|
38
|
+
private readonly key;
|
|
39
|
+
constructor(options: NewsSeenOptions);
|
|
40
|
+
private readSeen;
|
|
41
|
+
isSeen(id: string): boolean;
|
|
42
|
+
markSeen(id: string): void;
|
|
43
|
+
/** `items` filtered down to whichever have not been marked seen yet */
|
|
44
|
+
unseen(items: readonly NewsItem[]): NewsItem[];
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=News.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"News.d.ts","sourceRoot":"","sources":["../../src/core/News.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkB,KAAK,WAAW,EAAE,MAAM,WAAW,CAAC;AAG7D;;;;GAIG;AACH,MAAM,WAAW,QAAQ;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,WAAW;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,OAAO,UAAU,CAAC,KAAK,CAAC;CAChC;AAED,qBAAa,UAAU;IACtB,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA0B;IAElD,YAAY,OAAO,EAAE,WAAW,EAO/B;IAED;;;;;OAKG;IACG,UAAU,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC,CAYtC;CACD;AAgBD,MAAM,WAAW,eAAe;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,WAAW,CAAC;CACtB;AAED,wHAAwH;AACxH,qBAAa,eAAe;IAC3B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAc;IACtC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAS;IAE7B,YAAY,OAAO,EAAE,eAAe,EAGnC;IAED,OAAO,CAAC,QAAQ;IAKhB,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAE1B;IAED,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAIzB;IAED,uEAAuE;IACvE,MAAM,CAAC,KAAK,EAAE,SAAS,QAAQ,EAAE,GAAG,QAAQ,EAAE,CAG7C;CACD"}
|