@energy8platform/shell 0.5.0 → 0.6.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/dist/html.cjs.js +39 -5
- package/dist/html.cjs.js.map +1 -1
- package/dist/html.d.ts +28 -4
- package/dist/html.esm.js +39 -5
- package/dist/html.esm.js.map +1 -1
- package/dist/index.cjs.js +29 -1
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.d.ts +28 -4
- package/dist/index.esm.js +29 -1
- package/dist/index.esm.js.map +1 -1
- package/dist/pixi.cjs.js +54 -9
- package/dist/pixi.cjs.js.map +1 -1
- package/dist/pixi.d.ts +28 -4
- package/dist/pixi.esm.js +54 -9
- package/dist/pixi.esm.js.map +1 -1
- package/package.json +1 -1
- package/src/core/ShellController.ts +21 -0
- 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 +3 -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.0";
|
|
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,6 +543,12 @@ 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;
|
|
@@ -564,7 +588,7 @@ interface I18n {
|
|
|
564
588
|
declare function createI18n(opts: I18nOptions): I18n;
|
|
565
589
|
|
|
566
590
|
/** The @energy8platform/shell package version, stamped into the game-info footer. */
|
|
567
|
-
declare const PACKAGE_VERSION = "0.
|
|
591
|
+
declare const PACKAGE_VERSION = "0.6.0";
|
|
568
592
|
|
|
569
593
|
/** A shell: the renderer-agnostic controller plus the surface facade (safeArea/barHeight/setVisible)
|
|
570
594
|
* an embedding host reads. `createShell`, `createGameShell` and `createPixiShell` all return this. */
|
|
@@ -640,4 +664,4 @@ declare function createGameShell(config: HtmlShellConfig): ShellController;
|
|
|
640
664
|
declare function removeGameShell(): Promise<void>;
|
|
641
665
|
|
|
642
666
|
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 };
|
|
667
|
+
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.0';
|
|
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;
|
|
@@ -2827,7 +2855,10 @@ function openSettingsModal(host) {
|
|
|
2827
2855
|
return row;
|
|
2828
2856
|
})();
|
|
2829
2857
|
body.appendChild(sound);
|
|
2830
|
-
// Volume sliders — full-width column rows with a live value readout
|
|
2858
|
+
// Volume sliders — full-width column rows with a live value readout. Positions are read from the
|
|
2859
|
+
// shell's stored volumes (not hardcoded to 100%), so reopening the overlay reflects the last set
|
|
2860
|
+
// value, and `host.setVolume()` from game code updates them live via the registered refreshers.
|
|
2861
|
+
const updaters = {};
|
|
2831
2862
|
const slider = (key, label) => {
|
|
2832
2863
|
const row = document.createElement('div');
|
|
2833
2864
|
row.className = 'ge-ov-row ge-col';
|
|
@@ -2835,7 +2866,6 @@ function openSettingsModal(host) {
|
|
|
2835
2866
|
head.className = 'ge-row-head';
|
|
2836
2867
|
const val = document.createElement('span');
|
|
2837
2868
|
val.className = 'ge-val';
|
|
2838
|
-
val.textContent = '100%';
|
|
2839
2869
|
head.innerHTML = `<span>${label}</span>`;
|
|
2840
2870
|
head.appendChild(val);
|
|
2841
2871
|
const input = document.createElement('input');
|
|
@@ -2843,19 +2873,23 @@ function openSettingsModal(host) {
|
|
|
2843
2873
|
input.min = '0';
|
|
2844
2874
|
input.max = '1';
|
|
2845
2875
|
input.step = '0.05';
|
|
2846
|
-
input.value = '1';
|
|
2847
2876
|
input.className = 'ge-slider';
|
|
2848
2877
|
input.dataset.ge = `setting-${key}`;
|
|
2878
|
+
const paint = (v) => { input.value = String(v); val.textContent = `${Math.round(v * 100)}%`; };
|
|
2879
|
+
paint(host.getVolume(key));
|
|
2849
2880
|
input.addEventListener('input', () => {
|
|
2850
2881
|
val.textContent = `${Math.round(Number(input.value) * 100)}%`;
|
|
2851
|
-
host.
|
|
2882
|
+
host.setVolume(key, Number(input.value));
|
|
2852
2883
|
});
|
|
2884
|
+
updaters[key] = paint;
|
|
2853
2885
|
row.append(head, input);
|
|
2854
2886
|
return row;
|
|
2855
2887
|
};
|
|
2856
2888
|
body.appendChild(slider('master', host.t('Master volume')));
|
|
2857
2889
|
body.appendChild(slider('music', host.t('Music')));
|
|
2858
2890
|
body.appendChild(slider('sfx', host.t('SFX')));
|
|
2891
|
+
// Live-update sliders when volume changes via host.setVolume (shell clears on close).
|
|
2892
|
+
host.setVolumeRefresh((key, v) => updaters[key]?.(v));
|
|
2859
2893
|
// Game info — full-width row button that opens its own overlay
|
|
2860
2894
|
const gameInfo = document.createElement('button');
|
|
2861
2895
|
gameInfo.className = 'ge-ov-row';
|