@energy8platform/game-engine 0.33.7 → 0.33.9
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/host.cjs.js +60 -9
- package/dist/host.cjs.js.map +1 -1
- package/dist/host.d.ts +58 -2
- package/dist/host.esm.js +60 -10
- package/dist/host.esm.js.map +1 -1
- package/dist/slot.cjs.js +2 -0
- package/dist/slot.cjs.js.map +1 -1
- package/dist/slot.d.ts +18 -10
- package/dist/slot.esm.js +2 -0
- package/dist/slot.esm.js.map +1 -1
- package/package.json +2 -2
- package/src/host/balanceGate.ts +21 -10
- package/src/host/createSlotGame.ts +22 -6
- package/src/host/index.ts +3 -0
- package/src/host/sceneController.ts +20 -0
- package/src/host/winReporter.ts +57 -0
- package/src/slot/index.ts +1 -1
- package/src/slot/system/ReelSystem.ts +20 -3
package/dist/host.cjs.js
CHANGED
|
@@ -2455,10 +2455,11 @@ async function createSlotGame(opts) {
|
|
|
2455
2455
|
// (hidden over the intro / non-slot scenes). Applies in BOTH base and replay modes.
|
|
2456
2456
|
shell.setVisible(!!gameScene());
|
|
2457
2457
|
game.scenes.on('change', () => shell.setVisible(!!gameScene()));
|
|
2458
|
-
// The gate tracks the live wallet (for the affordability guard)
|
|
2459
|
-
//
|
|
2460
|
-
//
|
|
2461
|
-
//
|
|
2458
|
+
// The gate tracks the live wallet (for the affordability guard) and PAINTS the balance per the
|
|
2459
|
+
// HUD-timing rule: the debit paints immediately (the stake leaves the balance on spin); a win
|
|
2460
|
+
// credit landing during play→present is held to afterPresent so it doesn't post before the
|
|
2461
|
+
// animation; the async credit (/wallet/end-round, after the final ack) paints when it lands.
|
|
2462
|
+
// `balanceGate` is the single source for both the displayed balance and `ensureAffordable`.
|
|
2462
2463
|
const balanceGate = createBalanceGate((b) => shell.setBalance(b), balance);
|
|
2463
2464
|
ps?.on('balanceUpdate', (d) => {
|
|
2464
2465
|
balanceGate.onBalance(d.balance);
|
|
@@ -2501,6 +2502,11 @@ async function createSlotGame(opts) {
|
|
|
2501
2502
|
size: () => ({ width: game.app.screen.width, height: game.app.screen.height }),
|
|
2502
2503
|
});
|
|
2503
2504
|
game.on('resize', ({ width, height }) => overlayCtl.resize(width, height));
|
|
2505
|
+
// Progressive WIN readout for cascade/tumble scenes. The window is open from the moment a
|
|
2506
|
+
// segment starts (WIN cleared to 0) until the host has painted that segment's final win; outside
|
|
2507
|
+
// it the host owns the readout alone. See winReporter.ts.
|
|
2508
|
+
const { createWinReporter } = await Promise.resolve().then(function () { return winReporter; });
|
|
2509
|
+
const winReporter$1 = createWinReporter((amount, opts) => shell.setWin(amount, opts));
|
|
2504
2510
|
// Capabilities injected once per controller scene via onCreate (see `gameScene`/`ensureCreated`).
|
|
2505
2511
|
sceneApi = {
|
|
2506
2512
|
audio: createSceneAudio(game.audio),
|
|
@@ -2509,6 +2515,7 @@ async function createSlotGame(opts) {
|
|
|
2509
2515
|
get safeArea() {
|
|
2510
2516
|
return shell.safeArea;
|
|
2511
2517
|
},
|
|
2518
|
+
reportWin: winReporter$1.report,
|
|
2512
2519
|
},
|
|
2513
2520
|
formatAmount: (v) => shell.formatWin(v),
|
|
2514
2521
|
get bet() {
|
|
@@ -2729,7 +2736,8 @@ async function createSlotGame(opts) {
|
|
|
2729
2736
|
// RETURN the promise: the replay modal awaits onReplay() and only reopens once the round's
|
|
2730
2737
|
// animation has finished — returning void would reopen it instantly, over a running animation.
|
|
2731
2738
|
return runRound({
|
|
2732
|
-
//
|
|
2739
|
+
// Open the play→present window: the debit still paints immediately, but a win credit that
|
|
2740
|
+
// lands mid-animation is held until afterPresent (HUD timing).
|
|
2733
2741
|
play: (a, b, rid) => {
|
|
2734
2742
|
balanceGate.beginPlay();
|
|
2735
2743
|
return slotPlay$1.play(a, b, rid);
|
|
@@ -2747,12 +2755,15 @@ async function createSlotGame(opts) {
|
|
|
2747
2755
|
// then counts UP to this segment's delta. prevWin (the cumulative-delta tracker) is
|
|
2748
2756
|
// untouched; this only resets the DISPLAY.
|
|
2749
2757
|
shell.setWin(0, { animate: false });
|
|
2758
|
+
winReporter$1.open(); // the scene may now grow WIN per cascade step
|
|
2750
2759
|
},
|
|
2751
2760
|
onSpinStart: () => scene.onSpinStart?.(),
|
|
2752
2761
|
onSpinEnd: (last, ctx) => scene.onSpinEnd?.(last, ctx),
|
|
2753
2762
|
afterPresent: (r) => {
|
|
2754
2763
|
// WIN readout = THIS spin's win (cumulative delta); the cumulative total goes to the
|
|
2755
|
-
// bonus counter (totalWin) via settle(), not the WIN readout.
|
|
2764
|
+
// bonus counter (totalWin) via settle(), not the WIN readout. A scene that reported
|
|
2765
|
+
// per-step wins already landed on this number, so the count-up is a no-op there.
|
|
2766
|
+
winReporter$1.close();
|
|
2756
2767
|
shell.setWin(r.totalWin - prevWin);
|
|
2757
2768
|
prevWin = r.totalWin;
|
|
2758
2769
|
balanceGate.afterPresent();
|
|
@@ -2764,6 +2775,7 @@ async function createSlotGame(opts) {
|
|
|
2764
2775
|
.catch(showPlayError)
|
|
2765
2776
|
.finally(() => {
|
|
2766
2777
|
presenting = false;
|
|
2778
|
+
winReporter$1.close(); // also closes the window when a segment threw mid-flight
|
|
2767
2779
|
shell.setBusy(false);
|
|
2768
2780
|
});
|
|
2769
2781
|
};
|
|
@@ -2808,6 +2820,8 @@ async function createSlotGame(opts) {
|
|
|
2808
2820
|
shell.setMode(bonusShellMode);
|
|
2809
2821
|
}
|
|
2810
2822
|
shell.setWin(0, { animate: false }); // clear WIN before this segment animates (see playRound)
|
|
2823
|
+
if (animate)
|
|
2824
|
+
winReporter$1.open(); // a fast-forward drain doesn't present → no reports expected
|
|
2811
2825
|
if (animate)
|
|
2812
2826
|
await scene.onSpin(r, ctx);
|
|
2813
2827
|
if (inBonus) {
|
|
@@ -2815,6 +2829,7 @@ async function createSlotGame(opts) {
|
|
|
2815
2829
|
if (v)
|
|
2816
2830
|
applyBonusReadout(r, v, ctx.mode);
|
|
2817
2831
|
}
|
|
2832
|
+
winReporter$1.close();
|
|
2818
2833
|
shell.setWin(r.totalWin - prevWin); // THIS spin's win, not the cumulative bonus total
|
|
2819
2834
|
prevWin = r.totalWin;
|
|
2820
2835
|
ps.playAck(raw); // settles via /wallet/end-round on the FINAL segment
|
|
@@ -2839,6 +2854,7 @@ async function createSlotGame(opts) {
|
|
|
2839
2854
|
}
|
|
2840
2855
|
}
|
|
2841
2856
|
finally {
|
|
2857
|
+
winReporter$1.close(); // also closes the window when a drained segment threw
|
|
2842
2858
|
shell.setBusy(false);
|
|
2843
2859
|
}
|
|
2844
2860
|
};
|
|
@@ -3368,6 +3384,31 @@ var sceneStart = /*#__PURE__*/Object.freeze({
|
|
|
3368
3384
|
resolveStartScene: resolveStartScene
|
|
3369
3385
|
});
|
|
3370
3386
|
|
|
3387
|
+
function createWinReporter(paint) {
|
|
3388
|
+
let accepting = false;
|
|
3389
|
+
return {
|
|
3390
|
+
report(amountSoFar, opts) {
|
|
3391
|
+
if (!accepting || !Number.isFinite(amountSoFar))
|
|
3392
|
+
return;
|
|
3393
|
+
paint(Math.max(0, amountSoFar), opts);
|
|
3394
|
+
},
|
|
3395
|
+
open() {
|
|
3396
|
+
accepting = true;
|
|
3397
|
+
},
|
|
3398
|
+
close() {
|
|
3399
|
+
accepting = false;
|
|
3400
|
+
},
|
|
3401
|
+
get accepting() {
|
|
3402
|
+
return accepting;
|
|
3403
|
+
},
|
|
3404
|
+
};
|
|
3405
|
+
}
|
|
3406
|
+
|
|
3407
|
+
var winReporter = /*#__PURE__*/Object.freeze({
|
|
3408
|
+
__proto__: null,
|
|
3409
|
+
createWinReporter: createWinReporter
|
|
3410
|
+
});
|
|
3411
|
+
|
|
3371
3412
|
// packages/game-engine/src/host/index.ts
|
|
3372
3413
|
|
|
3373
3414
|
/**
|
|
@@ -3485,18 +3526,27 @@ var runRound$1 = /*#__PURE__*/Object.freeze({
|
|
|
3485
3526
|
|
|
3486
3527
|
function createBalanceGate(paint, initial = 0) {
|
|
3487
3528
|
let latest = initial;
|
|
3529
|
+
let painted = initial;
|
|
3488
3530
|
let suppressed = false;
|
|
3531
|
+
const show = (amount) => {
|
|
3532
|
+
painted = amount;
|
|
3533
|
+
paint(amount);
|
|
3534
|
+
};
|
|
3489
3535
|
return {
|
|
3490
3536
|
onBalance(amount) {
|
|
3491
3537
|
latest = amount;
|
|
3492
|
-
|
|
3493
|
-
|
|
3538
|
+
// During play→present, hold a CREDIT (balance rising) back so the win doesn't post before the
|
|
3539
|
+
// animation. A DEBIT (balance falling — the stake) always paints now: spin deducts instantly.
|
|
3540
|
+
if (suppressed && amount > painted)
|
|
3541
|
+
return;
|
|
3542
|
+
show(amount);
|
|
3494
3543
|
},
|
|
3495
3544
|
beginPlay() {
|
|
3496
3545
|
suppressed = true;
|
|
3497
3546
|
},
|
|
3498
3547
|
afterPresent() {
|
|
3499
|
-
|
|
3548
|
+
if (latest !== painted)
|
|
3549
|
+
show(latest); // flush a credit that landed mid-present
|
|
3500
3550
|
suppressed = false;
|
|
3501
3551
|
},
|
|
3502
3552
|
get balance() {
|
|
@@ -3784,6 +3834,7 @@ Object.defineProperty(exports, "socialize", {
|
|
|
3784
3834
|
});
|
|
3785
3835
|
exports.buildShellConfig = buildShellConfig;
|
|
3786
3836
|
exports.createSlotGame = createSlotGame;
|
|
3837
|
+
exports.createWinReporter = createWinReporter;
|
|
3787
3838
|
exports.resolveReplayBonusId = resolveReplayBonusId;
|
|
3788
3839
|
exports.resolveStartScene = resolveStartScene;
|
|
3789
3840
|
exports.stakeForAction = stakeForAction;
|