@energy8platform/platform-core 0.24.6 → 0.25.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/game-spec.cjs.js +209 -0
- package/dist/game-spec.cjs.js.map +1 -0
- package/dist/game-spec.d.ts +164 -0
- package/dist/game-spec.esm.js +198 -0
- package/dist/game-spec.esm.js.map +1 -0
- package/dist/index.cjs.js +67 -1
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.d.ts +44 -1
- package/dist/index.esm.js +67 -1
- package/dist/index.esm.js.map +1 -1
- package/dist/loading.cjs.js +10 -1
- package/dist/loading.cjs.js.map +1 -1
- package/dist/loading.esm.js +10 -1
- package/dist/loading.esm.js.map +1 -1
- package/dist/lua.cjs.js +5 -2
- package/dist/lua.cjs.js.map +1 -1
- package/dist/lua.d.ts +9 -0
- package/dist/lua.esm.js +5 -2
- package/dist/lua.esm.js.map +1 -1
- package/dist/shell.cjs.js +35 -0
- package/dist/shell.cjs.js.map +1 -1
- package/dist/shell.d.ts +16 -1
- package/dist/shell.esm.js +35 -1
- package/dist/shell.esm.js.map +1 -1
- package/dist/simulation.cjs.js +40 -22
- package/dist/simulation.cjs.js.map +1 -1
- package/dist/simulation.d.ts +35 -2
- package/dist/simulation.esm.js +39 -23
- package/dist/simulation.esm.js.map +1 -1
- package/dist/slot-result.cjs.js +17 -0
- package/dist/slot-result.cjs.js.map +1 -0
- package/dist/slot-result.d.ts +26 -0
- package/dist/slot-result.esm.js +14 -0
- package/dist/slot-result.esm.js.map +1 -0
- package/package.json +12 -1
- package/scripts/gen-version.mjs +21 -0
- package/src/PlatformSession.ts +28 -0
- package/src/game-spec/defineGame.ts +16 -0
- package/src/game-spec/derive.ts +135 -0
- package/src/game-spec/export.ts +17 -0
- package/src/game-spec/index.ts +6 -0
- package/src/game-spec/types.ts +81 -0
- package/src/game-spec/validate.ts +49 -0
- package/src/loading/CSSPreloader.ts +14 -1
- package/src/lua/LuaEngine.ts +5 -2
- package/src/lua/types.ts +8 -0
- package/src/shell/GameShell.ts +19 -1
- package/src/shell/components/GameInfo.ts +13 -0
- package/src/shell/index.ts +1 -0
- package/src/shell/shell.css.ts +2 -0
- package/src/shell/types.ts +3 -0
- package/src/shell/version.ts +3 -0
- package/src/simulation/NativeSimulationRunner.ts +62 -26
- package/src/simulation/index.ts +3 -0
- package/src/slot-result/coerce.ts +11 -0
- package/src/slot-result/index.ts +2 -0
- package/src/slot-result/types.ts +19 -0
package/dist/index.cjs.js
CHANGED
|
@@ -610,6 +610,26 @@ class PlatformSession extends EventEmitter {
|
|
|
610
610
|
}
|
|
611
611
|
return this.sdk.play(params);
|
|
612
612
|
}
|
|
613
|
+
/**
|
|
614
|
+
* Acknowledge a finished PLAY_RESULT (call AFTER the game has animated it).
|
|
615
|
+
*
|
|
616
|
+
* The host uses this to know the client is ready for the next action and, on
|
|
617
|
+
* Stake, to settle the round (`/wallet/end-round`) only once the win
|
|
618
|
+
* animation has played. No-op when constructed with `sdk: false`.
|
|
619
|
+
*/
|
|
620
|
+
playAck(result) {
|
|
621
|
+
this.sdk?.playAck(result);
|
|
622
|
+
}
|
|
623
|
+
/**
|
|
624
|
+
* Query the host for an in-flight round (e.g. after a page reload). Resolves with the last
|
|
625
|
+
* result snapshot when a round is still open, or `null`. Used to offer a "resume / finish"
|
|
626
|
+
* choice on boot. Resolves `null` when constructed with `sdk: false`.
|
|
627
|
+
*/
|
|
628
|
+
async getState() {
|
|
629
|
+
if (!this.sdk)
|
|
630
|
+
return null;
|
|
631
|
+
return this.sdk.getState();
|
|
632
|
+
}
|
|
613
633
|
/** Tear down the SDK, DevBridge, and clear listeners. */
|
|
614
634
|
destroy() {
|
|
615
635
|
this.sdk?.destroy();
|
|
@@ -649,6 +669,9 @@ async function createPlatformSession(config = {}) {
|
|
|
649
669
|
sdk.on('balanceUpdate', (data) => {
|
|
650
670
|
session.emit('balanceUpdate', data);
|
|
651
671
|
});
|
|
672
|
+
sdk.on('connectionStateChanged', (state) => {
|
|
673
|
+
session.emit('connectionStateChanged', state);
|
|
674
|
+
});
|
|
652
675
|
}
|
|
653
676
|
return session;
|
|
654
677
|
}
|
|
@@ -828,6 +851,10 @@ function createCSSPreloader(container, config) {
|
|
|
828
851
|
50% { opacity: 1; }
|
|
829
852
|
}
|
|
830
853
|
`;
|
|
854
|
+
// The absolute overlay needs a positioned ancestor. Only override a STATIC container, and
|
|
855
|
+
// remember the prior inline value so removeCSSPreloader can restore it (an inline `relative`
|
|
856
|
+
// left behind would beat the game's `#game { position: fixed; inset: 0 }` and collapse it).
|
|
857
|
+
const prevPosition = container.style.position;
|
|
831
858
|
container.style.position = container.style.position || 'relative';
|
|
832
859
|
container.appendChild(styleEl);
|
|
833
860
|
container.appendChild(overlay);
|
|
@@ -838,6 +865,7 @@ function createCSSPreloader(container, config) {
|
|
|
838
865
|
// We still record state so removeCSSPreloader works.
|
|
839
866
|
state = {
|
|
840
867
|
container,
|
|
868
|
+
prevPosition,
|
|
841
869
|
overlay,
|
|
842
870
|
styleEl,
|
|
843
871
|
rectEl: null,
|
|
@@ -856,6 +884,7 @@ function createCSSPreloader(container, config) {
|
|
|
856
884
|
}
|
|
857
885
|
state = {
|
|
858
886
|
container,
|
|
887
|
+
prevPosition,
|
|
859
888
|
overlay,
|
|
860
889
|
styleEl,
|
|
861
890
|
rectEl,
|
|
@@ -934,7 +963,7 @@ function removeCSSPreloader(_container) {
|
|
|
934
963
|
state.tapResolve = null;
|
|
935
964
|
}
|
|
936
965
|
state.removed = true;
|
|
937
|
-
const { overlay, styleEl } = state;
|
|
966
|
+
const { overlay, styleEl, container, prevPosition } = state;
|
|
938
967
|
overlay.classList.add('ge-preloader-hidden');
|
|
939
968
|
return new Promise((resolve) => {
|
|
940
969
|
let settled = false;
|
|
@@ -944,6 +973,9 @@ function removeCSSPreloader(_container) {
|
|
|
944
973
|
settled = true;
|
|
945
974
|
overlay.remove();
|
|
946
975
|
styleEl.remove();
|
|
976
|
+
// Restore the container's original inline position so the game's own layout
|
|
977
|
+
// (e.g. `#game { position: fixed; inset: 0 }`) is no longer defeated by our inline override.
|
|
978
|
+
container.style.position = prevPosition;
|
|
947
979
|
state = null;
|
|
948
980
|
resolve();
|
|
949
981
|
};
|
|
@@ -1218,6 +1250,8 @@ const SHELL_CSS = SHELL_FONT_CSS + `
|
|
|
1218
1250
|
#${SHELL_ROOT_ID} .ge-gi-sec h3 { color:var(--shell-plaque-label); font-size:11px; letter-spacing:.14em;
|
|
1219
1251
|
text-transform:uppercase; margin:0 0 12px; }
|
|
1220
1252
|
#${SHELL_ROOT_ID} .ge-gi-sec p { color:rgba(255,255,255,.88); font-size:15px; line-height:1.6; margin:0; }
|
|
1253
|
+
#${SHELL_ROOT_ID} .ge-gi-version { text-align:center; color:var(--shell-muted); font-size:11px;
|
|
1254
|
+
letter-spacing:.08em; opacity:.7; margin:4px 0 2px; }
|
|
1221
1255
|
|
|
1222
1256
|
/* controls — two blocks (gameplay / menu & info), icon/name/description per control */
|
|
1223
1257
|
#${SHELL_ROOT_ID} .ge-gi-ctl-block + .ge-gi-ctl-block { margin-top:16px; padding-top:4px; border-top:1px solid var(--shell-plaque-line); }
|
|
@@ -1927,6 +1961,10 @@ function openSettingsModal(shell) {
|
|
|
1927
1961
|
return root;
|
|
1928
1962
|
}
|
|
1929
1963
|
|
|
1964
|
+
// AUTO-GENERATED by scripts/gen-version.mjs — do not edit. Mirrors package.json "version".
|
|
1965
|
+
/** The @energy8platform/platform-core package version, stamped at build time. */
|
|
1966
|
+
const PACKAGE_VERSION = '0.25.1';
|
|
1967
|
+
|
|
1930
1968
|
const SVG_NS = 'http://www.w3.org/2000/svg';
|
|
1931
1969
|
function openGameInfoModal(shell) {
|
|
1932
1970
|
const { root, body } = createOverlay({
|
|
@@ -1943,8 +1981,19 @@ function openGameInfoModal(shell) {
|
|
|
1943
1981
|
.map((s, i) => ({ s, i, k: base(s, i) }))
|
|
1944
1982
|
.sort((a, b) => a.k - b.k || a.i - b.i)
|
|
1945
1983
|
.forEach(({ s }) => body.appendChild(renderSection(shell, s)));
|
|
1984
|
+
body.appendChild(versionFooter(shell));
|
|
1946
1985
|
return root;
|
|
1947
1986
|
}
|
|
1987
|
+
/** A muted version stamp pinned to the bottom of the game-info modal:
|
|
1988
|
+
* `${config.version ?? '1.0.0'}.${engine version without dots}` (e.g. '1.0.0.0246'). */
|
|
1989
|
+
function versionFooter(shell) {
|
|
1990
|
+
const gameVersion = shell.config.version ?? '1.0.0';
|
|
1991
|
+
const el = document.createElement('div');
|
|
1992
|
+
el.dataset.ge = 'info-version';
|
|
1993
|
+
el.className = 'ge-gi-version';
|
|
1994
|
+
el.textContent = `${gameVersion}.${PACKAGE_VERSION.replaceAll('.', '')}`;
|
|
1995
|
+
return el;
|
|
1996
|
+
}
|
|
1948
1997
|
function renderSection(shell, s) {
|
|
1949
1998
|
switch (s.type) {
|
|
1950
1999
|
case 'modes': return sectionModes(shell, s.modes, sec('info-modes', s.title, shell.t('Modes')));
|
|
@@ -2738,6 +2787,10 @@ class GameShell extends EventEmitter {
|
|
|
2738
2787
|
this.observeLayout();
|
|
2739
2788
|
if (typeof document !== 'undefined') {
|
|
2740
2789
|
document.addEventListener('keydown', this.handleKeyDown);
|
|
2790
|
+
// Stake serves the game in an iframe; on first paint focus is on the HOST page, so a `document`
|
|
2791
|
+
// keydown never fires and Space scrolls the parent. Pull window focus into the iframe on the
|
|
2792
|
+
// first pointer interaction so the spacebar shortcut works. Harmless on full-page Energy8.
|
|
2793
|
+
document.addEventListener('pointerdown', this.pullFocus, true);
|
|
2741
2794
|
this.keysBound = true;
|
|
2742
2795
|
}
|
|
2743
2796
|
this.render();
|
|
@@ -2823,6 +2876,12 @@ class GameShell extends EventEmitter {
|
|
|
2823
2876
|
* false, while a spin is running, while autoplay is active, outside base mode, when an
|
|
2824
2877
|
* overlay/modal is open, or when an editable element is focused. `repeat` (held key) is
|
|
2825
2878
|
* ignored so it can't spam. */
|
|
2879
|
+
/** Pull window focus into the iframe on first pointer interaction so `document` keydown (the
|
|
2880
|
+
* spacebar shortcut) fires. No-op / harmless when already focused or full-page. */
|
|
2881
|
+
pullFocus = () => { try {
|
|
2882
|
+
window.focus();
|
|
2883
|
+
}
|
|
2884
|
+
catch { /* cross-origin / non-browser */ } };
|
|
2826
2885
|
handleKeyDown = (e) => {
|
|
2827
2886
|
if (this.destroyed || e.code !== 'Space' || e.repeat)
|
|
2828
2887
|
return;
|
|
@@ -2896,6 +2955,9 @@ class GameShell extends EventEmitter {
|
|
|
2896
2955
|
setBusy(busy) { this.state.busy = busy; this.render(); }
|
|
2897
2956
|
setAutoplay(a) { this.state.autoplay = a; this.render(); }
|
|
2898
2957
|
setTurbo(level) { this.state.turbo = level; this.render(); }
|
|
2958
|
+
/** Currency-aware money formatter for WIN amounts (variable decimals: 0.0041 stays 0.0041, not
|
|
2959
|
+
* 0.00). The host hands this to a scene so games format money without knowing the currency. */
|
|
2960
|
+
formatWin(value) { return formatCurrency(value, this.config.currency, true); }
|
|
2899
2961
|
setBuyBonusEnabled(enabled) { this.state.buyBonusEnabled = enabled; this.render(); }
|
|
2900
2962
|
setFreeSpins(fs) { this.state.freeSpins = fs; this.render(); }
|
|
2901
2963
|
showModal(el) {
|
|
@@ -2966,6 +3028,9 @@ class GameShell extends EventEmitter {
|
|
|
2966
3028
|
/** Open a generic, externally-driven modal (title + body + optional action buttons).
|
|
2967
3029
|
* Each action runs its `on` then closes; the ✕ shows when `availableClose` is true. */
|
|
2968
3030
|
openModal(opts) { this.showModal(buildModal(opts)); }
|
|
3031
|
+
/** Programmatically dismiss whatever modal/overlay is currently shown (e.g. auto-close the
|
|
3032
|
+
* reconnect overlay once the link is restored). No-op when nothing is open. */
|
|
3033
|
+
closeModal() { this.modalHost.innerHTML = ''; }
|
|
2969
3034
|
/** Open the non-dismissable replay summary modal (START REPLAY → onReplay → reopen). */
|
|
2970
3035
|
openReplay(opts) {
|
|
2971
3036
|
if (this.destroyed)
|
|
@@ -2984,6 +3049,7 @@ class GameShell extends EventEmitter {
|
|
|
2984
3049
|
this.ro = null;
|
|
2985
3050
|
if (this.keysBound) {
|
|
2986
3051
|
document.removeEventListener('keydown', this.handleKeyDown);
|
|
3052
|
+
document.removeEventListener('pointerdown', this.pullFocus, true);
|
|
2987
3053
|
this.keysBound = false;
|
|
2988
3054
|
}
|
|
2989
3055
|
this.cancelMoneyAnims();
|