@energy8platform/game-engine 0.43.3 → 0.43.5
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 +62 -22
- package/dist/host.cjs.js.map +1 -1
- package/dist/host.esm.js +62 -22
- package/dist/host.esm.js.map +1 -1
- package/package.json +2 -2
- package/src/host/autoplay.ts +58 -17
- package/src/host/connectionRecovery.ts +21 -7
- package/src/host/createSlotGame.ts +19 -3
- package/src/host/shellConfig.ts +1 -1
package/dist/host.cjs.js
CHANGED
|
@@ -2853,6 +2853,8 @@ async function createSlotGame(opts) {
|
|
|
2853
2853
|
let playErrorOpen = false;
|
|
2854
2854
|
let stopAutoplay = () => { }; // wired to the autoplay loop once it's created (below)
|
|
2855
2855
|
let haltAutoplay = () => { }; // ditto — stops the run but KEEPS its counter
|
|
2856
|
+
let holdAutoplay = () => { }; // ditto — pauses the run, owing it a resume
|
|
2857
|
+
let releaseAutoplay = () => { }; // ditto — gives back a run that hold() paused
|
|
2856
2858
|
const reload = () => {
|
|
2857
2859
|
try {
|
|
2858
2860
|
window.location.reload();
|
|
@@ -2896,6 +2898,9 @@ async function createSlotGame(opts) {
|
|
|
2896
2898
|
const { createConnectionRecovery } = await Promise.resolve().then(function () { return connectionRecovery; });
|
|
2897
2899
|
const connection = createConnectionRecovery({
|
|
2898
2900
|
haltAutoplay: () => haltAutoplay(),
|
|
2901
|
+
// A reconnect ends the run for good (Artube): the counter the halt preserved while the link
|
|
2902
|
+
// was down is cleared here, and the disc goes back to a plain SPIN.
|
|
2903
|
+
resetAutoplay: () => stopAutoplay(),
|
|
2899
2904
|
showReconnecting: () => shell.openModal({
|
|
2900
2905
|
availableClose: false,
|
|
2901
2906
|
title: shell.t('Reconnecting…'),
|
|
@@ -2937,8 +2942,10 @@ async function createSlotGame(opts) {
|
|
|
2937
2942
|
game.scenes.root.eventMode = 'static';
|
|
2938
2943
|
game.scenes.root.on('pointertap', () => skip.tap(performance.now()));
|
|
2939
2944
|
// Full auto-pause: on tab blur, freeze the ticker (stops tweens/onUpdate/in-flight onSpin),
|
|
2940
|
-
// duck music to silence, hold autoplay, and notify the scene. On focus, reverse it all
|
|
2941
|
-
//
|
|
2945
|
+
// duck music to silence, hold autoplay, and notify the scene. On focus, reverse it all —
|
|
2946
|
+
// autoplay included: a tab switch is not the player pressing STOP.
|
|
2947
|
+
// `holdAutoplay`/`releaseAutoplay` are reassigned in the base-mode block below — the closures
|
|
2948
|
+
// read them live.
|
|
2942
2949
|
const { createPauseController } = await Promise.resolve().then(function () { return pauseController; });
|
|
2943
2950
|
createPauseController({
|
|
2944
2951
|
isHidden: () => typeof document !== 'undefined' && document.hidden,
|
|
@@ -2951,12 +2958,19 @@ async function createSlotGame(opts) {
|
|
|
2951
2958
|
onHidden: () => {
|
|
2952
2959
|
game.app.ticker.stop(); // freezes tweens, onUpdate, in-flight onSpin animation
|
|
2953
2960
|
game.audio.duckMusic(0); // silence music (ducked to 0; restored on resume)
|
|
2954
|
-
|
|
2961
|
+
// Hold, don't stop. No auto-round may start while the tab is hidden (the ticker is frozen,
|
|
2962
|
+
// so an animation would never finish, and a play fired here spends the player's money out
|
|
2963
|
+
// of sight) — but the run is owed back: the lab reads "the autoplay sequence stops when the
|
|
2964
|
+
// Stop button is pressed" as ONLY the Stop button, and stopAutoplay() here ended the run and
|
|
2965
|
+
// zeroed its counter on every alt-tab. `hold()` forgets itself if anything else ends the run
|
|
2966
|
+
// meanwhile (a lost connection, a failed round), so those don't come back on the way in.
|
|
2967
|
+
holdAutoplay();
|
|
2955
2968
|
gameScene()?.onPause?.();
|
|
2956
2969
|
},
|
|
2957
2970
|
onVisible: () => {
|
|
2958
2971
|
game.app.ticker.start();
|
|
2959
2972
|
game.audio.unduckMusic();
|
|
2973
|
+
releaseAutoplay(); // the run the blur paused picks up where it left off
|
|
2960
2974
|
gameScene()?.onResume?.();
|
|
2961
2975
|
},
|
|
2962
2976
|
});
|
|
@@ -3173,6 +3187,8 @@ async function createSlotGame(opts) {
|
|
|
3173
3187
|
});
|
|
3174
3188
|
stopAutoplay = () => autoplay$1.stop();
|
|
3175
3189
|
haltAutoplay = () => autoplay$1.halt();
|
|
3190
|
+
holdAutoplay = () => autoplay$1.hold();
|
|
3191
|
+
releaseAutoplay = () => autoplay$1.release();
|
|
3176
3192
|
shell.on('autoplayStart', (o) => autoplay$1.start(o?.remaining ?? 0));
|
|
3177
3193
|
shell.on('autoplayStop', () => autoplay$1.stop());
|
|
3178
3194
|
// Resume offer: when the game scene is (or becomes) current on a reload, ask the host whether
|
|
@@ -3398,7 +3414,7 @@ const DISCLAIMER_TITLE = 'DISCLAIMER';
|
|
|
3398
3414
|
/** The copyright/brand line ("TM and © {year} Engine.") is shown verbatim; the legal body
|
|
3399
3415
|
* lines localize. Detecting the brand keeps " Engine" out of the translation lookup entirely. */
|
|
3400
3416
|
function isBrandLine(line) {
|
|
3401
|
-
return /
|
|
3417
|
+
return /engine/i.test(line);
|
|
3402
3418
|
}
|
|
3403
3419
|
/** A disclaimer section from initData's disclaimer lines; null when none supplied. The legal body is
|
|
3404
3420
|
* run through `t` so it localizes per language, EXCEPT the brand line, which stays verbatim. The
|
|
@@ -4226,6 +4242,9 @@ function createConnectionRecovery(deps) {
|
|
|
4226
4242
|
if (!linkLost)
|
|
4227
4243
|
return; // nothing of ours is on screen; nothing of ours to recover
|
|
4228
4244
|
linkLost = false;
|
|
4245
|
+
// The run does not resume across a reconnect. Like the halt above, this runs even when a
|
|
4246
|
+
// modal owns the screen — the counter must not outlive the drop that ended the run.
|
|
4247
|
+
deps.resetAutoplay();
|
|
4229
4248
|
if (!blocked())
|
|
4230
4249
|
deps.dismiss();
|
|
4231
4250
|
await recover();
|
|
@@ -4395,7 +4414,9 @@ function createAutoplayLoop(deps) {
|
|
|
4395
4414
|
let active = false;
|
|
4396
4415
|
let remaining = 0;
|
|
4397
4416
|
let running = false; // guards against a second concurrent loop
|
|
4417
|
+
let held = false; // a hold() is outstanding — the tab is hidden and the run is owed a resume
|
|
4398
4418
|
const stop = () => {
|
|
4419
|
+
held = false;
|
|
4399
4420
|
if (!active && remaining === 0)
|
|
4400
4421
|
return;
|
|
4401
4422
|
active = false;
|
|
@@ -4403,6 +4424,7 @@ function createAutoplayLoop(deps) {
|
|
|
4403
4424
|
deps.onState({ active: false, remaining: 0 });
|
|
4404
4425
|
};
|
|
4405
4426
|
const halt = () => {
|
|
4427
|
+
held = false; // whatever is halting the run outranks a pending hold — see hold()'s doc comment
|
|
4406
4428
|
if (!active)
|
|
4407
4429
|
return; // nothing running — nothing to preserve
|
|
4408
4430
|
active = false;
|
|
@@ -4439,27 +4461,45 @@ function createAutoplayLoop(deps) {
|
|
|
4439
4461
|
running = false;
|
|
4440
4462
|
}
|
|
4441
4463
|
}
|
|
4464
|
+
const start = (count) => {
|
|
4465
|
+
if (active || count <= 0)
|
|
4466
|
+
return;
|
|
4467
|
+
held = false; // a run that is starting is no longer one that owes a resume
|
|
4468
|
+
active = true;
|
|
4469
|
+
remaining = count;
|
|
4470
|
+
deps.onState({ active: true, remaining });
|
|
4471
|
+
// `running` bars a SECOND loop, not a new run. After stop(), the round already in flight keeps
|
|
4472
|
+
// animating and the loop stays parked on `await playRound`, so `running` is still true for as
|
|
4473
|
+
// long as that takes — several seconds through a win. Bailing here made the restart a silent
|
|
4474
|
+
// no-op, and silent is what hurt: ShellController.startAutoplay has already lit the disc with
|
|
4475
|
+
// the chosen count, so the player saw autoplay running with a counter that never moved.
|
|
4476
|
+
// The parked loop re-reads `active`/`remaining` on its next turn and simply carries on with
|
|
4477
|
+
// the new budget — no second loop, nothing dropped.
|
|
4478
|
+
if (!running)
|
|
4479
|
+
void loop();
|
|
4480
|
+
};
|
|
4442
4481
|
return {
|
|
4443
|
-
start
|
|
4444
|
-
if (active || count <= 0)
|
|
4445
|
-
return;
|
|
4446
|
-
active = true;
|
|
4447
|
-
remaining = count;
|
|
4448
|
-
deps.onState({ active: true, remaining });
|
|
4449
|
-
// `running` bars a SECOND loop, not a new run. After stop(), the round already in flight keeps
|
|
4450
|
-
// animating and the loop stays parked on `await playRound`, so `running` is still true for as
|
|
4451
|
-
// long as that takes — several seconds through a win. Bailing here made the restart a silent
|
|
4452
|
-
// no-op, and silent is what hurt: ShellController.startAutoplay has already lit the disc with
|
|
4453
|
-
// the chosen count, so the player saw autoplay running with a counter that never moved.
|
|
4454
|
-
// The parked loop re-reads `active`/`remaining` on its next turn and simply carries on with
|
|
4455
|
-
// the new budget — no second loop, nothing dropped.
|
|
4456
|
-
if (!running)
|
|
4457
|
-
void loop();
|
|
4458
|
-
},
|
|
4482
|
+
start,
|
|
4459
4483
|
stop,
|
|
4460
4484
|
halt,
|
|
4461
|
-
|
|
4462
|
-
|
|
4485
|
+
hold() {
|
|
4486
|
+
if (!active)
|
|
4487
|
+
return; // nothing running — nothing to hold, and nothing to bring back
|
|
4488
|
+
halt(); // clears `held`; we set it again below, so only a hold() ever leaves it set
|
|
4489
|
+
held = true;
|
|
4490
|
+
},
|
|
4491
|
+
release() {
|
|
4492
|
+
if (!held)
|
|
4493
|
+
return;
|
|
4494
|
+
held = false;
|
|
4495
|
+
start(remaining); // no-op when the remainder is gone (something retired it while hidden)
|
|
4496
|
+
},
|
|
4497
|
+
get active() {
|
|
4498
|
+
return active;
|
|
4499
|
+
},
|
|
4500
|
+
get remaining() {
|
|
4501
|
+
return remaining;
|
|
4502
|
+
},
|
|
4463
4503
|
};
|
|
4464
4504
|
}
|
|
4465
4505
|
|