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