@energy8platform/shell 0.5.0 → 0.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/html.cjs.js +47 -6
- package/dist/html.cjs.js.map +1 -1
- package/dist/html.d.ts +34 -5
- package/dist/html.esm.js +47 -6
- package/dist/html.esm.js.map +1 -1
- package/dist/index.cjs.js +37 -2
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.d.ts +34 -5
- package/dist/index.esm.js +37 -2
- package/dist/index.esm.js.map +1 -1
- package/dist/pixi.cjs.js +69 -10
- package/dist/pixi.cjs.js.map +1 -1
- package/dist/pixi.d.ts +34 -5
- package/dist/pixi.esm.js +69 -10
- package/dist/pixi.esm.js.map +1 -1
- package/package.json +1 -1
- package/src/core/ShellController.ts +29 -1
- package/src/core/renderer.ts +8 -1
- package/src/core/state.ts +10 -0
- package/src/core/types.ts +12 -1
- package/src/core/version.ts +1 -1
- package/src/ui/html/components/Settings.ts +14 -5
- package/src/ui/pixi/PixiRenderer.ts +9 -0
- package/src/ui/pixi/components/Settings.ts +23 -8
- package/src/ui/pixi/primitives/controls.ts +7 -0
package/dist/html.d.ts
CHANGED
|
@@ -21,6 +21,9 @@ declare class EventEmitter<TEvents extends {}> {
|
|
|
21
21
|
* `bonus` pairs with `setBonus()` to show a game-supplied label + value (adventure, hold-and-spin,
|
|
22
22
|
* respins — anything that isn't a plain free-spins counter). */
|
|
23
23
|
type ShellMode = 'base' | 'bonus' | 'freeSpins' | 'replay';
|
|
24
|
+
/** The three independent volume sliders shown in the Settings overlay. */
|
|
25
|
+
type VolumeKey = 'master' | 'music' | 'sfx';
|
|
26
|
+
type VolumeLevels = Record<VolumeKey, number>;
|
|
24
27
|
interface CurrencyConfig {
|
|
25
28
|
symbol: string;
|
|
26
29
|
position: 'left' | 'right';
|
|
@@ -282,9 +285,13 @@ interface ShellConfig {
|
|
|
282
285
|
* opening the built-in buy-bonus overlay (e.g. the game shows its own bonus UI). The button
|
|
283
286
|
* is shown whenever this OR `features.buyBonus` is set. */
|
|
284
287
|
onBonusBuy?: () => void;
|
|
288
|
+
/** Initial Settings-overlay volume slider positions (each 0..1, defaults to 1 = 100%). The shell
|
|
289
|
+
* keeps them stateful across opens; read/update at runtime via `shell.getVolume()` /
|
|
290
|
+
* `shell.setVolume()`, and listen to `settingChange` ({ key: 'master'|'music'|'sfx' }) to apply. */
|
|
291
|
+
volumes?: Partial<VolumeLevels>;
|
|
285
292
|
}
|
|
286
293
|
/** ShellConfig after the controller applies defaults (version, isSocial, replay, theme). No mount. */
|
|
287
|
-
type ResolvedShellConfig = Required<Pick<ShellConfig, 'language' | 'currency' | 'availableBets' | 'defaultBet' | 'balance' | 'win' | 'mode' | 'features' | 'gameInfo' | 'version' | 'isSocial' | 'replay'>> & Pick<ShellConfig, 'currentBet' | 'theme' | 'onBonusBuy'>;
|
|
294
|
+
type ResolvedShellConfig = Required<Pick<ShellConfig, 'language' | 'currency' | 'availableBets' | 'defaultBet' | 'balance' | 'win' | 'mode' | 'features' | 'gameInfo' | 'version' | 'isSocial' | 'replay'>> & Pick<ShellConfig, 'currentBet' | 'theme' | 'onBonusBuy' | 'volumes'>;
|
|
288
295
|
interface ShellState {
|
|
289
296
|
mode: ShellMode;
|
|
290
297
|
/** Sticky replay marker — true for a historical-round replay, regardless of the current
|
|
@@ -309,6 +316,9 @@ interface ShellState {
|
|
|
309
316
|
/** The currently activated `feature` option (e.g. Ante), or null. Drives the
|
|
310
317
|
* effective-bet readout tint and the BUY BONUS → DISABLE toggle on the bar. */
|
|
311
318
|
activeFeature: BonusOption | null;
|
|
319
|
+
/** Volume slider positions (0..1) surfaced in the Settings overlay. Stateful across opens so a
|
|
320
|
+
* reopened overlay reflects the last-set positions instead of resetting to 100%. */
|
|
321
|
+
volumes: VolumeLevels;
|
|
312
322
|
}
|
|
313
323
|
interface ShellEvents {
|
|
314
324
|
spin: void;
|
|
@@ -431,6 +441,13 @@ interface ShellHost {
|
|
|
431
441
|
setSound(on: boolean): void;
|
|
432
442
|
/** An open Settings overlay registers an icon updater here (null clears it on close). */
|
|
433
443
|
setSoundRefresh(fn: ((on: boolean) => void) | null): void;
|
|
444
|
+
/** Current volume slider position (0..1) for master/music/sfx. */
|
|
445
|
+
getVolume(key: VolumeKey): number;
|
|
446
|
+
/** Set a volume slider (0..1): clamps, stores, emits `settingChange`, and live-updates an open
|
|
447
|
+
* Settings overlay. Called by the slider control on drag AND by game code as the public API. */
|
|
448
|
+
setVolume(key: VolumeKey, value: number): void;
|
|
449
|
+
/** An open Settings overlay registers a slider updater here (null clears it on close). */
|
|
450
|
+
setVolumeRefresh(fn: ((key: VolumeKey, value: number) => void) | null): void;
|
|
434
451
|
/** Logic-bearing actions invoked by renderer controls. */
|
|
435
452
|
readonly actions: ShellActions;
|
|
436
453
|
}
|
|
@@ -494,13 +511,14 @@ declare class ShellController extends EventEmitter<ShellEvents> implements Shell
|
|
|
494
511
|
tokens: ShellTokens;
|
|
495
512
|
layout: ShellLayoutMode;
|
|
496
513
|
soundOn: boolean;
|
|
497
|
-
readonly engineVersion = "0.
|
|
514
|
+
readonly engineVersion = "0.6.1";
|
|
498
515
|
readonly actions: ShellActions;
|
|
499
516
|
private renderer;
|
|
500
517
|
private i18n;
|
|
501
518
|
private kbd?;
|
|
502
519
|
private overlay;
|
|
503
520
|
private soundRefresh;
|
|
521
|
+
private volumeRefresh;
|
|
504
522
|
private prevBalance;
|
|
505
523
|
private prevWin;
|
|
506
524
|
private destroyed;
|
|
@@ -525,11 +543,22 @@ declare class ShellController extends EventEmitter<ShellEvents> implements Shell
|
|
|
525
543
|
closeModal(): void;
|
|
526
544
|
setSound(on: boolean): void;
|
|
527
545
|
setSoundRefresh(fn: ((on: boolean) => void) | null): void;
|
|
546
|
+
getVolume(key: VolumeKey): number;
|
|
547
|
+
/** Set a volume slider (0..1). Shared by the slider control (drag) and game code (public API):
|
|
548
|
+
* clamps, stores so a reopened Settings overlay reflects it, emits `settingChange`, and
|
|
549
|
+
* live-updates the slider if the overlay is currently open. */
|
|
550
|
+
setVolume(key: VolumeKey, value: number): void;
|
|
551
|
+
setVolumeRefresh(fn: ((key: VolumeKey, value: number) => void) | null): void;
|
|
528
552
|
activateFeature(bonus: BonusOption): void;
|
|
529
553
|
deactivateFeature(): void;
|
|
530
554
|
private money;
|
|
531
555
|
setBalance(n: number): void;
|
|
532
|
-
|
|
556
|
+
/** Set the WIN readout. Counts up/down from the previous value by default. Pass
|
|
557
|
+
* `{ animate: false }` to SNAP instantly (renderBar cancels any in-flight count-up) — used by the
|
|
558
|
+
* host to clear WIN to 0 at spin start, where an animated count-DOWN would look wrong. */
|
|
559
|
+
setWin(n: number, opts?: {
|
|
560
|
+
animate?: boolean;
|
|
561
|
+
}): void;
|
|
533
562
|
setBet(n: number): void;
|
|
534
563
|
setMode(mode: ShellMode): void;
|
|
535
564
|
setBusy(busy: boolean): void;
|
|
@@ -564,7 +593,7 @@ interface I18n {
|
|
|
564
593
|
declare function createI18n(opts: I18nOptions): I18n;
|
|
565
594
|
|
|
566
595
|
/** The @energy8platform/shell package version, stamped into the game-info footer. */
|
|
567
|
-
declare const PACKAGE_VERSION = "0.
|
|
596
|
+
declare const PACKAGE_VERSION = "0.6.1";
|
|
568
597
|
|
|
569
598
|
/** A shell: the renderer-agnostic controller plus the surface facade (safeArea/barHeight/setVisible)
|
|
570
599
|
* an embedding host reads. `createShell`, `createGameShell` and `createPixiShell` all return this. */
|
|
@@ -640,4 +669,4 @@ declare function createGameShell(config: HtmlShellConfig): ShellController;
|
|
|
640
669
|
declare function removeGameShell(): Promise<void>;
|
|
641
670
|
|
|
642
671
|
export { DEFAULT_ACCENT, ShellController as GameShell, HtmlRenderer, PACKAGE_VERSION, SCHEMES, ShellController, createGameShell, createI18n, createShell, normalizeLang, removeGameShell, resolveConfig, resolveTheme, socialize };
|
|
643
|
-
export type { AutoplayConfig, AutoplayOptions, BonusCardContext, BonusOption, BonusReadout, CellRef, CreateShellOptions, CurrencyConfig, FreeSpinsState, GameInfoContent, GameInfoSection, GameMode, HtmlShellConfig, I18n, I18nOptions, Lang, ModalAction, ModalOptions, OverlayHandle, OverlayRequest, PaylineDef, PaytableRow, ReplayModalOptions, ResolvedShellConfig, SafeArea, ShapeDef, Shell, ShellActions, HtmlShellConfig as ShellConfig, ShellEvents, ShellFeatures, ShellHost, ShellLayoutMode, ShellMode, ShellRenderer, ShellState, ShellSurface, ShellTokens, ThemeConfig, WinSection };
|
|
672
|
+
export type { AutoplayConfig, AutoplayOptions, BonusCardContext, BonusOption, BonusReadout, CellRef, CreateShellOptions, CurrencyConfig, FreeSpinsState, GameInfoContent, GameInfoSection, GameMode, HtmlShellConfig, I18n, I18nOptions, Lang, ModalAction, ModalOptions, OverlayHandle, OverlayRequest, PaylineDef, PaytableRow, ReplayModalOptions, ResolvedShellConfig, SafeArea, ShapeDef, Shell, ShellActions, HtmlShellConfig as ShellConfig, ShellEvents, ShellFeatures, ShellHost, ShellLayoutMode, ShellMode, ShellRenderer, ShellState, ShellSurface, ShellTokens, ThemeConfig, VolumeKey, VolumeLevels, WinSection };
|
package/dist/html.esm.js
CHANGED
|
@@ -65,8 +65,17 @@ function createInitialState(config) {
|
|
|
65
65
|
freeSpins: { current: 0, total: 0, totalWin: 0 },
|
|
66
66
|
bonus: null,
|
|
67
67
|
activeFeature: null,
|
|
68
|
+
volumes: {
|
|
69
|
+
master: clampVolume(config.volumes?.master),
|
|
70
|
+
music: clampVolume(config.volumes?.music),
|
|
71
|
+
sfx: clampVolume(config.volumes?.sfx),
|
|
72
|
+
},
|
|
68
73
|
};
|
|
69
74
|
}
|
|
75
|
+
/** Clamp a configured volume to 0..1, defaulting to full (1) when unset/invalid. */
|
|
76
|
+
function clampVolume(v) {
|
|
77
|
+
return typeof v === 'number' && Number.isFinite(v) ? Math.max(0, Math.min(1, v)) : 1;
|
|
78
|
+
}
|
|
70
79
|
/** Step bet up/down within availableBets, clamped at the ends. */
|
|
71
80
|
function stepBet(state, direction) {
|
|
72
81
|
const idx = state.availableBets.indexOf(state.bet);
|
|
@@ -1437,7 +1446,7 @@ class KeyboardController {
|
|
|
1437
1446
|
|
|
1438
1447
|
// AUTO-GENERATED by scripts/gen-version.mjs — do not edit. Mirrors package.json "version".
|
|
1439
1448
|
/** The @energy8platform/shell package version, stamped into the game-info footer. */
|
|
1440
|
-
const PACKAGE_VERSION = '0.
|
|
1449
|
+
const PACKAGE_VERSION = '0.6.1';
|
|
1441
1450
|
|
|
1442
1451
|
/** Apply defaults to the raw config (the mount target lives on the renderer, not here). */
|
|
1443
1452
|
function resolveConfig(config) {
|
|
@@ -1454,6 +1463,7 @@ function resolveConfig(config) {
|
|
|
1454
1463
|
features: config.features,
|
|
1455
1464
|
theme: config.theme,
|
|
1456
1465
|
onBonusBuy: config.onBonusBuy,
|
|
1466
|
+
volumes: config.volumes,
|
|
1457
1467
|
version: config.version ?? '1.0.0',
|
|
1458
1468
|
isSocial: config.isSocial ?? false,
|
|
1459
1469
|
replay: config.replay ?? config.mode === 'replay',
|
|
@@ -1475,6 +1485,7 @@ class ShellController extends EventEmitter {
|
|
|
1475
1485
|
kbd;
|
|
1476
1486
|
overlay = null;
|
|
1477
1487
|
soundRefresh = null;
|
|
1488
|
+
volumeRefresh = null;
|
|
1478
1489
|
prevBalance;
|
|
1479
1490
|
prevWin;
|
|
1480
1491
|
destroyed = false;
|
|
@@ -1658,6 +1669,7 @@ class ShellController extends EventEmitter {
|
|
|
1658
1669
|
return;
|
|
1659
1670
|
this.overlay = null;
|
|
1660
1671
|
this.soundRefresh = null;
|
|
1672
|
+
this.volumeRefresh = null;
|
|
1661
1673
|
this.renderer.closeOverlay();
|
|
1662
1674
|
}
|
|
1663
1675
|
// ── sound ──────────────────────────────────────────────────────────────────
|
|
@@ -1670,6 +1682,22 @@ class ShellController extends EventEmitter {
|
|
|
1670
1682
|
setSoundRefresh(fn) {
|
|
1671
1683
|
this.soundRefresh = fn;
|
|
1672
1684
|
}
|
|
1685
|
+
// ── volume ─────────────────────────────────────────────────────────────────
|
|
1686
|
+
getVolume(key) {
|
|
1687
|
+
return this.state.volumes[key];
|
|
1688
|
+
}
|
|
1689
|
+
/** Set a volume slider (0..1). Shared by the slider control (drag) and game code (public API):
|
|
1690
|
+
* clamps, stores so a reopened Settings overlay reflects it, emits `settingChange`, and
|
|
1691
|
+
* live-updates the slider if the overlay is currently open. */
|
|
1692
|
+
setVolume(key, value) {
|
|
1693
|
+
const v = Math.max(0, Math.min(1, value));
|
|
1694
|
+
this.state.volumes[key] = v;
|
|
1695
|
+
this.emit('settingChange', { key, value: v });
|
|
1696
|
+
this.volumeRefresh?.(key, v);
|
|
1697
|
+
}
|
|
1698
|
+
setVolumeRefresh(fn) {
|
|
1699
|
+
this.volumeRefresh = fn;
|
|
1700
|
+
}
|
|
1673
1701
|
// ── features ─────────────────────────────────────────────────────────────────
|
|
1674
1702
|
activateFeature(bonus) {
|
|
1675
1703
|
this.state.activeFeature = bonus;
|
|
@@ -1696,10 +1724,17 @@ class ShellController extends EventEmitter {
|
|
|
1696
1724
|
this.prevBalance = n;
|
|
1697
1725
|
this.money('balance', from, n);
|
|
1698
1726
|
}
|
|
1699
|
-
|
|
1727
|
+
/** Set the WIN readout. Counts up/down from the previous value by default. Pass
|
|
1728
|
+
* `{ animate: false }` to SNAP instantly (renderBar cancels any in-flight count-up) — used by the
|
|
1729
|
+
* host to clear WIN to 0 at spin start, where an animated count-DOWN would look wrong. */
|
|
1730
|
+
setWin(n, opts) {
|
|
1700
1731
|
const from = this.prevWin;
|
|
1701
1732
|
this.state.win = n;
|
|
1702
1733
|
this.prevWin = n;
|
|
1734
|
+
if (opts?.animate === false) {
|
|
1735
|
+
this.renderer.renderBar(); // instant repaint from state; cancels running money anims
|
|
1736
|
+
return;
|
|
1737
|
+
}
|
|
1703
1738
|
this.money('win', from, n);
|
|
1704
1739
|
}
|
|
1705
1740
|
setBet(n) {
|
|
@@ -2827,7 +2862,10 @@ function openSettingsModal(host) {
|
|
|
2827
2862
|
return row;
|
|
2828
2863
|
})();
|
|
2829
2864
|
body.appendChild(sound);
|
|
2830
|
-
// Volume sliders — full-width column rows with a live value readout
|
|
2865
|
+
// Volume sliders — full-width column rows with a live value readout. Positions are read from the
|
|
2866
|
+
// shell's stored volumes (not hardcoded to 100%), so reopening the overlay reflects the last set
|
|
2867
|
+
// value, and `host.setVolume()` from game code updates them live via the registered refreshers.
|
|
2868
|
+
const updaters = {};
|
|
2831
2869
|
const slider = (key, label) => {
|
|
2832
2870
|
const row = document.createElement('div');
|
|
2833
2871
|
row.className = 'ge-ov-row ge-col';
|
|
@@ -2835,7 +2873,6 @@ function openSettingsModal(host) {
|
|
|
2835
2873
|
head.className = 'ge-row-head';
|
|
2836
2874
|
const val = document.createElement('span');
|
|
2837
2875
|
val.className = 'ge-val';
|
|
2838
|
-
val.textContent = '100%';
|
|
2839
2876
|
head.innerHTML = `<span>${label}</span>`;
|
|
2840
2877
|
head.appendChild(val);
|
|
2841
2878
|
const input = document.createElement('input');
|
|
@@ -2843,19 +2880,23 @@ function openSettingsModal(host) {
|
|
|
2843
2880
|
input.min = '0';
|
|
2844
2881
|
input.max = '1';
|
|
2845
2882
|
input.step = '0.05';
|
|
2846
|
-
input.value = '1';
|
|
2847
2883
|
input.className = 'ge-slider';
|
|
2848
2884
|
input.dataset.ge = `setting-${key}`;
|
|
2885
|
+
const paint = (v) => { input.value = String(v); val.textContent = `${Math.round(v * 100)}%`; };
|
|
2886
|
+
paint(host.getVolume(key));
|
|
2849
2887
|
input.addEventListener('input', () => {
|
|
2850
2888
|
val.textContent = `${Math.round(Number(input.value) * 100)}%`;
|
|
2851
|
-
host.
|
|
2889
|
+
host.setVolume(key, Number(input.value));
|
|
2852
2890
|
});
|
|
2891
|
+
updaters[key] = paint;
|
|
2853
2892
|
row.append(head, input);
|
|
2854
2893
|
return row;
|
|
2855
2894
|
};
|
|
2856
2895
|
body.appendChild(slider('master', host.t('Master volume')));
|
|
2857
2896
|
body.appendChild(slider('music', host.t('Music')));
|
|
2858
2897
|
body.appendChild(slider('sfx', host.t('SFX')));
|
|
2898
|
+
// Live-update sliders when volume changes via host.setVolume (shell clears on close).
|
|
2899
|
+
host.setVolumeRefresh((key, v) => updaters[key]?.(v));
|
|
2859
2900
|
// Game info — full-width row button that opens its own overlay
|
|
2860
2901
|
const gameInfo = document.createElement('button');
|
|
2861
2902
|
gameInfo.className = 'ge-ov-row';
|