pixi-rainman-game-engine 0.3.42 → 0.3.43-c
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/ComponentRegistry/ComponentRegistry.js +3 -2
- package/dist/ComponentRegistry/types.d.ts +2 -1
- package/dist/ComponentRegistry/types.js +1 -1
- package/dist/application/SoundManager/SoundManager.d.ts +20 -7
- package/dist/application/SoundManager/SoundManager.js +117 -63
- package/dist/components/AbstractMainContainer/AbstractMainContainer.d.ts +3 -1
- package/dist/components/AbstractMainContainer/AbstractMainContainer.js +15 -4
- package/dist/components/buttons/buttonGroups/MiddleButtons.d.ts +3 -2
- package/dist/components/buttons/buttonGroups/MiddleButtons.js +19 -5
- package/dist/components/buttons/buttonGroups/RightButtonsMobile.d.ts +3 -3
- package/dist/components/buttons/buttonGroups/RightButtonsMobile.js +10 -7
- package/dist/components/buttons/default/SpeedControlButtonMobile.d.ts +22 -0
- package/dist/components/buttons/default/SpeedControlButtonMobile.js +51 -0
- package/dist/components/buttons/default/index.d.ts +1 -0
- package/dist/components/buttons/default/index.js +1 -0
- package/dist/connectivity/ConnectionWrapper.d.ts +1 -0
- package/dist/connectivity/ConnectionWrapper.js +13 -1
- package/dist/controllers/AbstractController.js +21 -12
- package/dist/controllers/UiController.d.ts +0 -1
- package/dist/controllers/UiController.js +7 -4
- package/dist/utils/common/sound.js +4 -4
- package/package.json +1 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { isIncentiveComponentInterface, isSpeedAdapterInterface, SpeedLevelHandler, TimedIncentiveController } from "../application";
|
|
2
|
-
import { AbstractSymbolsColumn, SpeedControlButton } from "../components";
|
|
2
|
+
import { AbstractSymbolsColumn, SpeedControlButton, SpeedControlButtonMobile } from "../components";
|
|
3
3
|
import { RainMan } from "../Rainman";
|
|
4
4
|
import { openFullscreen } from "../utils";
|
|
5
5
|
/**
|
|
@@ -60,7 +60,8 @@ export class ComponentRegistry {
|
|
|
60
60
|
this.speedLevelHandler.nextSpeed();
|
|
61
61
|
RainMan.settingsStore.setSpeedLevel(this.speedLevelHandler.currentSpeed);
|
|
62
62
|
this.updateAllSpeedAdaptable(RainMan.settingsStore.currentSpeed);
|
|
63
|
-
this.
|
|
63
|
+
this.getIfExists(SpeedControlButton.registryName)?.forceTextureUpdate();
|
|
64
|
+
this.getIfExists(SpeedControlButtonMobile.registryName)?.forceTextureUpdate();
|
|
64
65
|
}
|
|
65
66
|
/**
|
|
66
67
|
* Getter for current speed level
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AbstractColumnsContainer, AbstractFrame, AbstractInnerFrame, AutoplayButton, Background, BUTTONS, COMPONENTS, FreeSpinButton, GambleButton, InfoButton, MessageBox, MoreButton, NegButton, PlusButton, RefreshButton, SpeedControlButton, StylefulUpdatableText, TakeButton, UpdatableTextComponent, UpdatableValueComponent, VolumeButton } from "../components";
|
|
1
|
+
import { AbstractColumnsContainer, AbstractFrame, AbstractInnerFrame, AutoplayButton, Background, BUTTONS, COMPONENTS, FreeSpinButton, GambleButton, InfoButton, MessageBox, MoreButton, NegButton, PlusButton, RefreshButton, SpeedControlButton, SpeedControlButtonMobile, StylefulUpdatableText, TakeButton, UpdatableTextComponent, UpdatableValueComponent, VolumeButton } from "../components";
|
|
2
2
|
/**
|
|
3
3
|
* RegistryMap is a map of all components that are registered in the ComponentRegistry.
|
|
4
4
|
* It is used to type-check the components that are registered in the ComponentRegistry.
|
|
@@ -11,6 +11,7 @@ export interface RegistryMap {
|
|
|
11
11
|
[MessageBox.gamePaysTextRegistryName]: UpdatableTextComponent;
|
|
12
12
|
[MessageBox.registryName]: MessageBox;
|
|
13
13
|
[SpeedControlButton.registryName]: SpeedControlButton;
|
|
14
|
+
[SpeedControlButtonMobile.registryName]: SpeedControlButtonMobile;
|
|
14
15
|
[Background.registryName]: Background;
|
|
15
16
|
[VolumeButton.registryName]: VolumeButton;
|
|
16
17
|
[AutoplayButton.registryName]: AutoplayButton;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import { AbstractColumnsContainer, AbstractFrame, AbstractInnerFrame, AutoplayButton, Background, BUTTONS, COMPONENTS, FreeSpinButton, InfoButton, MessageBox, MoreButton, NegButton, PlusButton, RefreshButton, SpeedControlButton, VolumeButton } from "../components";
|
|
1
|
+
import { AbstractColumnsContainer, AbstractFrame, AbstractInnerFrame, AutoplayButton, Background, BUTTONS, COMPONENTS, FreeSpinButton, InfoButton, MessageBox, MoreButton, NegButton, PlusButton, RefreshButton, SpeedControlButton, SpeedControlButtonMobile, VolumeButton } from "../components";
|
|
@@ -16,8 +16,10 @@ export declare class SoundManagerInstance implements SpeedAdapterInterface<Sound
|
|
|
16
16
|
readonly speedLevelMapper: SpeedLevelDirectory<SoundOverrides>;
|
|
17
17
|
private musicCatalogue;
|
|
18
18
|
private currentAmbientTrack;
|
|
19
|
-
private
|
|
19
|
+
private loadedSoundAssets;
|
|
20
|
+
private audioContextRecoveryPromise;
|
|
20
21
|
constructor();
|
|
22
|
+
private loadSound;
|
|
21
23
|
/**
|
|
22
24
|
* Function for loading sounds into pixi
|
|
23
25
|
* @public
|
|
@@ -38,7 +40,7 @@ export declare class SoundManagerInstance implements SpeedAdapterInterface<Sound
|
|
|
38
40
|
* @returns {void}
|
|
39
41
|
*/
|
|
40
42
|
stopPlayingFxSounds(): void;
|
|
41
|
-
|
|
43
|
+
stopSoundsForPageHide(): void;
|
|
42
44
|
/**
|
|
43
45
|
* Function for resuming and pausing sound in game
|
|
44
46
|
* @public
|
|
@@ -62,7 +64,11 @@ export declare class SoundManagerInstance implements SpeedAdapterInterface<Sound
|
|
|
62
64
|
getVolumeLevel(soundName: SoundTrack): number;
|
|
63
65
|
private isAmbientTrack;
|
|
64
66
|
private getOppositeAmbientTrack;
|
|
67
|
+
private getCurrentAmbientTrack;
|
|
65
68
|
private getSound;
|
|
69
|
+
private isIOSWebAudioRuntime;
|
|
70
|
+
private recreatePixiSoundContext;
|
|
71
|
+
private recreatePixiSoundContextOnce;
|
|
66
72
|
stopAmbientMusic(): void;
|
|
67
73
|
/**
|
|
68
74
|
* Function for resuming all sounds in game
|
|
@@ -78,11 +84,18 @@ export declare class SoundManagerInstance implements SpeedAdapterInterface<Sound
|
|
|
78
84
|
*/
|
|
79
85
|
restoreAmbientPlayback(): void;
|
|
80
86
|
/**
|
|
81
|
-
*
|
|
82
|
-
*
|
|
87
|
+
* Recreates the active ambient WebAudio source after iOS app interruptions.
|
|
88
|
+
* Existing Pixi instances can report isPlaying=true even when the native audio pipeline is silent.
|
|
89
|
+
* @private
|
|
83
90
|
* @returns {void}
|
|
84
91
|
*/
|
|
85
|
-
|
|
92
|
+
private restartAmbientPlaybackAfterInterruption;
|
|
93
|
+
/**
|
|
94
|
+
* Restores ambient playback after page visibility change or iOS app interruption.
|
|
95
|
+
* @public
|
|
96
|
+
* @returns {boolean} True when audio context is ready after recovery.
|
|
97
|
+
*/
|
|
98
|
+
restorePlaybackAfterPageHide(): Promise<boolean>;
|
|
86
99
|
/**
|
|
87
100
|
* Function for pausing all sounds in game
|
|
88
101
|
* If sound is not playing, it will be skipped
|
|
@@ -128,13 +141,13 @@ export declare class SoundManagerInstance implements SpeedAdapterInterface<Sound
|
|
|
128
141
|
/**
|
|
129
142
|
* Function that resumes sounds and music when game is back in focus.
|
|
130
143
|
* @public
|
|
131
|
-
* @returns {
|
|
144
|
+
* @returns {Promise<boolean>} True when audio context is running.
|
|
132
145
|
*/
|
|
133
146
|
resumeAudioContext(): Promise<boolean>;
|
|
134
147
|
/**
|
|
135
148
|
* Function that resumes sounds and music when game is back in focus.
|
|
136
149
|
* @public
|
|
137
|
-
* @returns {
|
|
150
|
+
* @returns {Promise<boolean>} True when audio context and ambient recovery are ready.
|
|
138
151
|
*/
|
|
139
152
|
resumeOnFocus(): Promise<boolean>;
|
|
140
153
|
/**
|
|
@@ -31,10 +31,24 @@ export class SoundManagerInstance {
|
|
|
31
31
|
};
|
|
32
32
|
musicCatalogue = new Map();
|
|
33
33
|
currentAmbientTrack = null;
|
|
34
|
-
|
|
34
|
+
loadedSoundAssets = {};
|
|
35
|
+
audioContextRecoveryPromise = null;
|
|
35
36
|
constructor() {
|
|
36
37
|
this.overrides = this.speedLevelMapper.slow;
|
|
37
38
|
}
|
|
39
|
+
loadSound(soundName, url) {
|
|
40
|
+
return new Promise((resolve) => {
|
|
41
|
+
const sound = Sound.from({
|
|
42
|
+
url,
|
|
43
|
+
autoPlay: false,
|
|
44
|
+
preload: true,
|
|
45
|
+
volume: this.getVolumeLevel(soundName),
|
|
46
|
+
loaded: () => resolve()
|
|
47
|
+
});
|
|
48
|
+
sound.name = soundName;
|
|
49
|
+
this.musicCatalogue.set(soundName, sound);
|
|
50
|
+
});
|
|
51
|
+
}
|
|
38
52
|
/**
|
|
39
53
|
* Function for loading sounds into pixi
|
|
40
54
|
* @public
|
|
@@ -42,22 +56,13 @@ export class SoundManagerInstance {
|
|
|
42
56
|
* @returns {Promise<void>} - promise that resolves when all sounds are loaded
|
|
43
57
|
*/
|
|
44
58
|
async loadSounds(assets) {
|
|
59
|
+
this.loadedSoundAssets = { ...assets };
|
|
45
60
|
const loadingSoundsPromises = [];
|
|
46
61
|
for (const [soundName, url] of Object.entries(assets)) {
|
|
47
62
|
if (!url) {
|
|
48
63
|
continue;
|
|
49
64
|
}
|
|
50
|
-
loadingSoundsPromises.push(
|
|
51
|
-
const sound = Sound.from({
|
|
52
|
-
url,
|
|
53
|
-
autoPlay: false,
|
|
54
|
-
preload: true,
|
|
55
|
-
volume: this.getVolumeLevel(soundName),
|
|
56
|
-
loaded: () => resolve()
|
|
57
|
-
});
|
|
58
|
-
sound.name = soundName;
|
|
59
|
-
this.musicCatalogue.set(soundName, sound);
|
|
60
|
-
}));
|
|
65
|
+
loadingSoundsPromises.push(this.loadSound(soundName, url));
|
|
61
66
|
}
|
|
62
67
|
await Promise.allSettled(loadingSoundsPromises);
|
|
63
68
|
}
|
|
@@ -95,18 +100,19 @@ export class SoundManagerInstance {
|
|
|
95
100
|
sound.stop();
|
|
96
101
|
}
|
|
97
102
|
}
|
|
98
|
-
|
|
99
|
-
this.
|
|
100
|
-
this.
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
this.
|
|
108
|
-
|
|
109
|
-
|
|
103
|
+
stopSoundsForPageHide() {
|
|
104
|
+
const music = this.getSound(SoundTracks.music);
|
|
105
|
+
const freeSpinsMusic = this.getSound(SoundTracks.freeSpinsMusic);
|
|
106
|
+
const isMusicPlaying = Boolean(music?.isPlaying && !music.paused);
|
|
107
|
+
const isFreeSpinsMusicPlaying = Boolean(freeSpinsMusic?.isPlaying && !freeSpinsMusic.paused);
|
|
108
|
+
if (isFreeSpinsMusicPlaying) {
|
|
109
|
+
this.currentAmbientTrack = SoundTracks.freeSpinsMusic;
|
|
110
|
+
}
|
|
111
|
+
else if (isMusicPlaying) {
|
|
112
|
+
this.currentAmbientTrack = SoundTracks.music;
|
|
113
|
+
}
|
|
114
|
+
this.stopAmbientMusic();
|
|
115
|
+
this.stopPlayingFxSounds();
|
|
110
116
|
}
|
|
111
117
|
/**
|
|
112
118
|
* Function for resuming and pausing sound in game
|
|
@@ -178,10 +184,51 @@ export class SoundManagerInstance {
|
|
|
178
184
|
getOppositeAmbientTrack(soundName) {
|
|
179
185
|
return soundName === SoundTracks.freeSpinsMusic ? SoundTracks.music : SoundTracks.freeSpinsMusic;
|
|
180
186
|
}
|
|
187
|
+
getCurrentAmbientTrack() {
|
|
188
|
+
return (this.currentAmbientTrack ??
|
|
189
|
+
(RainMan.settingsStore.isFreeSpinsStarted ? SoundTracks.freeSpinsMusic : SoundTracks.music));
|
|
190
|
+
}
|
|
181
191
|
getSound(soundName) {
|
|
182
192
|
const overrideSoundName = this.overrides[soundName];
|
|
183
193
|
return this.musicCatalogue.get(overrideSoundName ?? soundName);
|
|
184
194
|
}
|
|
195
|
+
isIOSWebAudioRuntime() {
|
|
196
|
+
const userAgent = navigator.userAgent;
|
|
197
|
+
const platform = navigator.platform;
|
|
198
|
+
return /iPad|iPhone|iPod/.test(userAgent) || (platform === "MacIntel" && navigator.maxTouchPoints > 1);
|
|
199
|
+
}
|
|
200
|
+
async recreatePixiSoundContext() {
|
|
201
|
+
if (this.audioContextRecoveryPromise) {
|
|
202
|
+
return this.audioContextRecoveryPromise;
|
|
203
|
+
}
|
|
204
|
+
this.audioContextRecoveryPromise = this.recreatePixiSoundContextOnce().finally(() => {
|
|
205
|
+
this.audioContextRecoveryPromise = null;
|
|
206
|
+
});
|
|
207
|
+
return this.audioContextRecoveryPromise;
|
|
208
|
+
}
|
|
209
|
+
async recreatePixiSoundContextOnce() {
|
|
210
|
+
if (!Object.keys(this.loadedSoundAssets).length) {
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
this.musicCatalogue.forEach((sound) => sound.destroy());
|
|
214
|
+
this.musicCatalogue.clear();
|
|
215
|
+
try {
|
|
216
|
+
sound.context.destroy();
|
|
217
|
+
}
|
|
218
|
+
catch (error) {
|
|
219
|
+
console.error("Could not destroy Pixi sound context", error);
|
|
220
|
+
}
|
|
221
|
+
sound.init();
|
|
222
|
+
sound.disableAutoPause = false;
|
|
223
|
+
const loadingSoundsPromises = [];
|
|
224
|
+
for (const [soundName, url] of Object.entries(this.loadedSoundAssets)) {
|
|
225
|
+
if (!url) {
|
|
226
|
+
continue;
|
|
227
|
+
}
|
|
228
|
+
loadingSoundsPromises.push(this.loadSound(soundName, url));
|
|
229
|
+
}
|
|
230
|
+
await Promise.allSettled(loadingSoundsPromises);
|
|
231
|
+
}
|
|
185
232
|
stopAmbientMusic() {
|
|
186
233
|
this.stop(SoundTracks.music);
|
|
187
234
|
this.stop(SoundTracks.freeSpinsMusic);
|
|
@@ -196,23 +243,8 @@ export class SoundManagerInstance {
|
|
|
196
243
|
if (!RainMan.settingsStore.isSoundStarted) {
|
|
197
244
|
return;
|
|
198
245
|
}
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
sound.resume();
|
|
202
|
-
}
|
|
203
|
-
if (RainMan.settingsStore.shouldPlayAmbientMusic &&
|
|
204
|
-
!RainMan.settingsStore.isFreeSpinsPlayEnabled &&
|
|
205
|
-
soundName === SoundTracks.music &&
|
|
206
|
-
sound.paused) {
|
|
207
|
-
sound.resume();
|
|
208
|
-
}
|
|
209
|
-
if (RainMan.settingsStore.shouldPlayAmbientMusic &&
|
|
210
|
-
RainMan.settingsStore.isFreeSpinsPlayEnabled &&
|
|
211
|
-
soundName === SoundTracks.freeSpinsMusic &&
|
|
212
|
-
sound.paused) {
|
|
213
|
-
sound.resume();
|
|
214
|
-
}
|
|
215
|
-
});
|
|
246
|
+
sound.resumeAll();
|
|
247
|
+
this.restoreAmbientPlayback();
|
|
216
248
|
}
|
|
217
249
|
/**
|
|
218
250
|
* Restores currently active ambient loop if browser dropped it while page was inactive.
|
|
@@ -227,36 +259,58 @@ export class SoundManagerInstance {
|
|
|
227
259
|
this.stopAmbientMusic();
|
|
228
260
|
return;
|
|
229
261
|
}
|
|
230
|
-
const ambientTrack = this.
|
|
231
|
-
(RainMan.settingsStore.isFreeSpinsStarted ? SoundTracks.freeSpinsMusic : SoundTracks.music);
|
|
262
|
+
const ambientTrack = this.getCurrentAmbientTrack();
|
|
232
263
|
this.play(ambientTrack);
|
|
233
264
|
}
|
|
234
265
|
/**
|
|
235
|
-
*
|
|
236
|
-
*
|
|
266
|
+
* Recreates the active ambient WebAudio source after iOS app interruptions.
|
|
267
|
+
* Existing Pixi instances can report isPlaying=true even when the native audio pipeline is silent.
|
|
268
|
+
* @private
|
|
237
269
|
* @returns {void}
|
|
238
270
|
*/
|
|
239
|
-
|
|
271
|
+
restartAmbientPlaybackAfterInterruption() {
|
|
240
272
|
if (!RainMan.settingsStore.isSoundStarted) {
|
|
241
|
-
this.pausedSoundsForPageHide.clear();
|
|
242
273
|
return;
|
|
243
274
|
}
|
|
244
|
-
if (!
|
|
245
|
-
this.
|
|
275
|
+
if (!RainMan.settingsStore.shouldPlayAmbientMusic) {
|
|
276
|
+
this.stopAmbientMusic();
|
|
246
277
|
return;
|
|
247
278
|
}
|
|
248
|
-
const
|
|
249
|
-
this.
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
279
|
+
const ambientTrack = this.getCurrentAmbientTrack();
|
|
280
|
+
const ambientSound = this.getSound(ambientTrack);
|
|
281
|
+
if (!ambientSound) {
|
|
282
|
+
return;
|
|
283
|
+
}
|
|
284
|
+
this.stop(this.getOppositeAmbientTrack(ambientTrack));
|
|
285
|
+
ambientSound.stop();
|
|
286
|
+
this.currentAmbientTrack = ambientTrack;
|
|
287
|
+
ambientSound.play({
|
|
288
|
+
singleInstance: true,
|
|
289
|
+
loop: soundsToLoop.includes(ambientTrack),
|
|
290
|
+
volume: this.getVolumeLevel(ambientTrack),
|
|
291
|
+
speed: 1
|
|
258
292
|
});
|
|
259
293
|
}
|
|
294
|
+
/**
|
|
295
|
+
* Restores ambient playback after page visibility change or iOS app interruption.
|
|
296
|
+
* @public
|
|
297
|
+
* @returns {boolean} True when audio context is ready after recovery.
|
|
298
|
+
*/
|
|
299
|
+
async restorePlaybackAfterPageHide() {
|
|
300
|
+
if (!RainMan.settingsStore.isSoundStarted) {
|
|
301
|
+
return false;
|
|
302
|
+
}
|
|
303
|
+
sound.resumeAll();
|
|
304
|
+
if (this.isIOSWebAudioRuntime()) {
|
|
305
|
+
await this.recreatePixiSoundContext();
|
|
306
|
+
}
|
|
307
|
+
const isAudioContextRunning = await this.resumeAudioContext();
|
|
308
|
+
if (!isAudioContextRunning) {
|
|
309
|
+
return false;
|
|
310
|
+
}
|
|
311
|
+
this.restartAmbientPlaybackAfterInterruption();
|
|
312
|
+
return true;
|
|
313
|
+
}
|
|
260
314
|
/**
|
|
261
315
|
* Function for pausing all sounds in game
|
|
262
316
|
* If sound is not playing, it will be skipped
|
|
@@ -264,7 +318,7 @@ export class SoundManagerInstance {
|
|
|
264
318
|
* @returns {void}
|
|
265
319
|
*/
|
|
266
320
|
pauseAll() {
|
|
267
|
-
|
|
321
|
+
sound.pauseAll();
|
|
268
322
|
}
|
|
269
323
|
/**
|
|
270
324
|
* Function for stopping all sounds in game
|
|
@@ -314,7 +368,7 @@ export class SoundManagerInstance {
|
|
|
314
368
|
/**
|
|
315
369
|
* Function that resumes sounds and music when game is back in focus.
|
|
316
370
|
* @public
|
|
317
|
-
* @returns {
|
|
371
|
+
* @returns {Promise<boolean>} True when audio context is running.
|
|
318
372
|
*/
|
|
319
373
|
async resumeAudioContext() {
|
|
320
374
|
const pixiSoundContext = sound.context;
|
|
@@ -333,7 +387,7 @@ export class SoundManagerInstance {
|
|
|
333
387
|
/**
|
|
334
388
|
* Function that resumes sounds and music when game is back in focus.
|
|
335
389
|
* @public
|
|
336
|
-
* @returns {
|
|
390
|
+
* @returns {Promise<boolean>} True when audio context and ambient recovery are ready.
|
|
337
391
|
*/
|
|
338
392
|
async resumeOnFocus() {
|
|
339
393
|
if (!RainMan.settingsStore.isSoundStarted) {
|
|
@@ -343,7 +397,7 @@ export class SoundManagerInstance {
|
|
|
343
397
|
if (!isAudioContextRunning) {
|
|
344
398
|
return false;
|
|
345
399
|
}
|
|
346
|
-
this.
|
|
400
|
+
this.restoreAmbientPlayback();
|
|
347
401
|
return true;
|
|
348
402
|
}
|
|
349
403
|
/**
|
|
@@ -6,7 +6,7 @@ import { RainMan } from "../../Rainman";
|
|
|
6
6
|
import { Nullable, PromiseResolverType } from "../../utils";
|
|
7
7
|
import { BigWinContainer, MysteryWinContainer, UpdatableSpineContainer } from "../../winComponents";
|
|
8
8
|
import { AbstractFreeSpinContainer } from "../AbstractFreeSpinContainer";
|
|
9
|
-
import { LeftButtons, LeftButtonsLandscape, LeftButtonsMobile, MiddleButtons, RightButtons, RightButtonsLandscape, RightButtonsMobile } from "../buttons";
|
|
9
|
+
import { LeftButtons, LeftButtonsLandscape, LeftButtonsMobile, MiddleButtons, RightButtons, RightButtonsLandscape, RightButtonsMobile, SpeedControlButtonMobile } from "../buttons";
|
|
10
10
|
import { FreeSpinButton, Logo, ResponsiveContainer } from "../common";
|
|
11
11
|
import { IResizableContainer } from "../common/IResizableContainer";
|
|
12
12
|
import { AbstractFrame } from "../frame";
|
|
@@ -34,6 +34,7 @@ export declare abstract class AbstractMainContainer extends Container {
|
|
|
34
34
|
static readonly registryName = "mainContainer";
|
|
35
35
|
messageBox: MessageBox;
|
|
36
36
|
protected bigWinContainer: Nullable<UpdatableSpineContainer> | BigWinContainer;
|
|
37
|
+
protected readonly mobileSpeedButton: SpeedControlButtonMobile;
|
|
37
38
|
protected mysteryWinContainer: Nullable<UpdatableSpineContainer> | MysteryWinContainer;
|
|
38
39
|
protected bonusWinContainer: Nullable<UpdatableSpineContainer>;
|
|
39
40
|
protected superBonusWinContainer: Nullable<UpdatableSpineContainer>;
|
|
@@ -75,6 +76,7 @@ export declare abstract class AbstractMainContainer extends Container {
|
|
|
75
76
|
* @returns {Promise<void>} - A promise that resolves when the animation is complete.
|
|
76
77
|
*/
|
|
77
78
|
invokeMysteryWinPlate(_animationName: string, _popupAnimation: string, _winType: WinTypeId, _amount: number, _isAdditionalFreeSpins: boolean): Promise<void>;
|
|
79
|
+
protected attachMobileSpeedButton(parent: Container): void;
|
|
78
80
|
/**
|
|
79
81
|
* This function initializes the spines that should be paused when the battery saver is on
|
|
80
82
|
* @protected
|
|
@@ -3,7 +3,7 @@ import { ButtonsEventManager, SoundManager, SoundTracks } from "../../applicatio
|
|
|
3
3
|
import { AnimationLayer, BackgroundLayer, FrameLayer, UXLayer } from "../../layers";
|
|
4
4
|
import { RainMan } from "../../Rainman";
|
|
5
5
|
import { getDeviceOrientation, globalMinRatio } from "../../utils";
|
|
6
|
-
import { BUTTONS, LeftButtons, LeftButtonsLandscape, LeftButtonsMobile, MiddleButtons, RefreshButton, RightButtons, RightButtonsLandscape, RightButtonsMobile } from "../buttons";
|
|
6
|
+
import { BUTTONS, LeftButtons, LeftButtonsLandscape, LeftButtonsMobile, MiddleButtons, RefreshButton, RightButtons, RightButtonsLandscape, RightButtonsMobile, SpeedControlButtonMobile } from "../buttons";
|
|
7
7
|
import { GambleGame } from "../GambleGame";
|
|
8
8
|
import { MessageBox } from "../messageBox";
|
|
9
9
|
/**
|
|
@@ -29,6 +29,7 @@ export class AbstractMainContainer extends Container {
|
|
|
29
29
|
static registryName = "mainContainer";
|
|
30
30
|
messageBox;
|
|
31
31
|
bigWinContainer = null;
|
|
32
|
+
mobileSpeedButton = new SpeedControlButtonMobile();
|
|
32
33
|
mysteryWinContainer = null;
|
|
33
34
|
bonusWinContainer = null;
|
|
34
35
|
superBonusWinContainer = null;
|
|
@@ -59,6 +60,9 @@ export class AbstractMainContainer extends Container {
|
|
|
59
60
|
this.name = AbstractMainContainer.registryName;
|
|
60
61
|
this.buttonsEventManager = new ButtonsEventManager();
|
|
61
62
|
this.messageBox = new MessageBox();
|
|
63
|
+
if (!RainMan.componentRegistry.has(SpeedControlButtonMobile.registryName)) {
|
|
64
|
+
RainMan.componentRegistry.add(this.mobileSpeedButton);
|
|
65
|
+
}
|
|
62
66
|
SoundManager.setPlayStatus(SoundTracks.music, RainMan.settingsStore.shouldPlayAmbientMusic);
|
|
63
67
|
RainMan.settingsStore.setHandleInvokeFreeSpinPlate(this.invokeFreeSpinPlate.bind(this));
|
|
64
68
|
RainMan.settingsStore.setHandleBuyFreeSpinPopupActivatio(this.invokeBuyFreeSpinPlate.bind(this));
|
|
@@ -75,6 +79,13 @@ export class AbstractMainContainer extends Container {
|
|
|
75
79
|
* @returns {Promise<void>} - A promise that resolves when the animation is complete.
|
|
76
80
|
*/
|
|
77
81
|
async invokeMysteryWinPlate(_animationName, _popupAnimation, _winType, _amount, _isAdditionalFreeSpins) { }
|
|
82
|
+
attachMobileSpeedButton(parent) {
|
|
83
|
+
if (this.mobileSpeedButton.parent) {
|
|
84
|
+
this.mobileSpeedButton.parent.removeChild(this.mobileSpeedButton);
|
|
85
|
+
}
|
|
86
|
+
parent.addChild(this.mobileSpeedButton);
|
|
87
|
+
this.mobileSpeedButton.adaptToSpeed(RainMan.componentRegistry.getSpeedLevel());
|
|
88
|
+
}
|
|
78
89
|
/**
|
|
79
90
|
* This function initializes the spines that should be paused when the battery saver is on
|
|
80
91
|
* @protected
|
|
@@ -771,7 +782,7 @@ export class AbstractMainContainer extends Container {
|
|
|
771
782
|
* @returns {RightButtonsMobile} - Returns a new instance of RightButtonsMobile for mobile portrait orientation.
|
|
772
783
|
*/
|
|
773
784
|
createRightButtonsMobile() {
|
|
774
|
-
return new RightButtonsMobile();
|
|
785
|
+
return new RightButtonsMobile(this.mobileSpeedButton);
|
|
775
786
|
}
|
|
776
787
|
/**
|
|
777
788
|
* Function for creating the left buttons for landscape orientation
|
|
@@ -795,7 +806,7 @@ export class AbstractMainContainer extends Container {
|
|
|
795
806
|
* @returns {MiddleButtons} - Returns a new instance of MiddleButtons for portrait orientation.
|
|
796
807
|
*/
|
|
797
808
|
createPortraitPlayButtons() {
|
|
798
|
-
return new MiddleButtons();
|
|
809
|
+
return new MiddleButtons(false);
|
|
799
810
|
}
|
|
800
811
|
/**
|
|
801
812
|
* Function for creating the landscape play buttons
|
|
@@ -803,7 +814,7 @@ export class AbstractMainContainer extends Container {
|
|
|
803
814
|
* @returns {MiddleButtons} - Returns a new instance of MiddleButtons for landscape orientation.
|
|
804
815
|
*/
|
|
805
816
|
createLandscapePlayButtons() {
|
|
806
|
-
return new MiddleButtons(true);
|
|
817
|
+
return new MiddleButtons(true, this.mobileSpeedButton);
|
|
807
818
|
}
|
|
808
819
|
/**
|
|
809
820
|
* This method initializes the components for the current screen ratio.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Graphics } from "pixi.js";
|
|
2
2
|
import { ResponsiveContainer } from "../../common";
|
|
3
|
-
import { AutoplayButton, GambleButton, PlusButton, RefreshButton, TakeButton } from "../default";
|
|
3
|
+
import { AutoplayButton, GambleButton, PlusButton, RefreshButton, SpeedControlButtonMobile, TakeButton } from "../default";
|
|
4
4
|
/**
|
|
5
5
|
* Class for managing middle buttons in game (MOBILE ONLY).
|
|
6
6
|
* The class uses {@link AutoplayButton}, {@link PlusButton}, {@link RefreshButton}.
|
|
@@ -8,13 +8,14 @@ import { AutoplayButton, GambleButton, PlusButton, RefreshButton, TakeButton } f
|
|
|
8
8
|
*/
|
|
9
9
|
export declare class MiddleButtons extends ResponsiveContainer {
|
|
10
10
|
private landscape;
|
|
11
|
+
private readonly speedButtonMobile?;
|
|
11
12
|
protected readonly autoplayButton: AutoplayButton;
|
|
12
13
|
protected readonly betButton: PlusButton;
|
|
13
14
|
protected readonly refreshButton: RefreshButton;
|
|
14
15
|
protected readonly positioningFrame: Graphics;
|
|
15
16
|
protected readonly gambleButton: GambleButton;
|
|
16
17
|
protected readonly takeButton: TakeButton;
|
|
17
|
-
constructor(landscape?: boolean);
|
|
18
|
+
constructor(landscape?: boolean, speedButtonMobile?: SpeedControlButtonMobile | undefined);
|
|
18
19
|
/**
|
|
19
20
|
* Function for removing children from the registry
|
|
20
21
|
* @public
|
|
@@ -11,26 +11,37 @@ import { REGISTRY } from "../registrynames";
|
|
|
11
11
|
*/
|
|
12
12
|
export class MiddleButtons extends ResponsiveContainer {
|
|
13
13
|
landscape;
|
|
14
|
+
speedButtonMobile;
|
|
14
15
|
autoplayButton = new AutoplayButton(true);
|
|
15
16
|
betButton = new PlusButton(true);
|
|
16
17
|
refreshButton = new RefreshButton(true);
|
|
17
18
|
positioningFrame = new Graphics();
|
|
18
19
|
gambleButton = new GambleButton(true);
|
|
19
20
|
takeButton = new TakeButton(true);
|
|
20
|
-
constructor(landscape = false) {
|
|
21
|
+
constructor(landscape = false, speedButtonMobile) {
|
|
21
22
|
super();
|
|
22
23
|
this.landscape = landscape;
|
|
24
|
+
this.speedButtonMobile = speedButtonMobile;
|
|
23
25
|
this.name = REGISTRY.middleButtons;
|
|
24
26
|
this.parentLayer = UXLayer;
|
|
25
27
|
const buttons = [this.autoplayButton, this.betButton, this.refreshButton];
|
|
26
28
|
this.addChild(...buttons);
|
|
27
29
|
RainMan.componentRegistry.addMany(buttons);
|
|
30
|
+
if (this.speedButtonMobile) {
|
|
31
|
+
this.speedButtonMobile.visible = true;
|
|
32
|
+
this.speedButtonMobile.scale.set(1);
|
|
33
|
+
this.speedButtonMobile.adaptToSpeed(RainMan.componentRegistry.getSpeedLevel());
|
|
34
|
+
this.addChild(this.speedButtonMobile);
|
|
35
|
+
}
|
|
28
36
|
this.addGambleAndTakeButtons();
|
|
29
37
|
this.positioningFrame.beginFill(0x000000, 0);
|
|
30
38
|
this.positioningFrame.drawRect(0, 0, 800, 250);
|
|
31
39
|
this.addChild(this.positioningFrame);
|
|
32
40
|
this.refreshButton.scale.set(0.75);
|
|
33
41
|
this.autoplayButton.scale.set(0.75);
|
|
42
|
+
if (this.speedButtonMobile) {
|
|
43
|
+
this.speedButtonMobile.scale.set(1);
|
|
44
|
+
}
|
|
34
45
|
this.betButton.scale.set(0.75);
|
|
35
46
|
this.takeButton.scale.set(0.75);
|
|
36
47
|
this.gambleButton.scale.set(0.75);
|
|
@@ -63,7 +74,6 @@ export class MiddleButtons extends ResponsiveContainer {
|
|
|
63
74
|
this.refreshButton,
|
|
64
75
|
this.autoplayButton,
|
|
65
76
|
this.betButton,
|
|
66
|
-
this.positioningFrame,
|
|
67
77
|
...(this.gambleButton && RainMan.config.gambleGameEnabled ? [this.gambleButton] : []),
|
|
68
78
|
...(this.takeButton ? [this.takeButton] : [])
|
|
69
79
|
]);
|
|
@@ -92,15 +102,19 @@ export class MiddleButtons extends ResponsiveContainer {
|
|
|
92
102
|
const { width, height } = this.positioningFrame;
|
|
93
103
|
this.refreshButton.x = width / 2;
|
|
94
104
|
this.refreshButton.y = height / 2;
|
|
105
|
+
if (this.speedButtonMobile) {
|
|
106
|
+
this.speedButtonMobile.x = width / 2;
|
|
107
|
+
this.speedButtonMobile.y = 150;
|
|
108
|
+
}
|
|
95
109
|
if (this.landscape) {
|
|
96
110
|
this.betButton.x = width / 2;
|
|
97
|
-
this.betButton.y =
|
|
111
|
+
this.betButton.y = -20;
|
|
98
112
|
this.autoplayButton.x = width / 2;
|
|
99
|
-
this.autoplayButton.y = height;
|
|
113
|
+
this.autoplayButton.y = height + 30;
|
|
100
114
|
}
|
|
101
115
|
else {
|
|
102
116
|
this.autoplayButton.x = -width;
|
|
103
|
-
this.autoplayButton.y =
|
|
117
|
+
this.autoplayButton.y = 50;
|
|
104
118
|
this.betButton.x = width;
|
|
105
119
|
this.betButton.y = height;
|
|
106
120
|
}
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import { ITextStyle } from "pixi.js";
|
|
2
2
|
import { ResponsiveContainer } from "../../common";
|
|
3
3
|
import { UpdatableTextComponent } from "../../updatable";
|
|
4
|
-
import { InfoButton, NegButton,
|
|
4
|
+
import { InfoButton, NegButton, SpeedControlButtonMobile } from "../default";
|
|
5
5
|
/**
|
|
6
6
|
* Buttons for mobile version. It has a current bet and game information button.
|
|
7
7
|
* @augments {ResponsiveContainer}
|
|
8
8
|
*/
|
|
9
9
|
export declare class RightButtonsMobile extends ResponsiveContainer {
|
|
10
|
+
private readonly speedButtonMobile;
|
|
10
11
|
protected readonly infoButton: InfoButton;
|
|
11
12
|
protected readonly negButton: NegButton;
|
|
12
|
-
protected readonly speedControlButton: SpeedControlButton;
|
|
13
13
|
protected bet: UpdatableTextComponent;
|
|
14
|
-
constructor();
|
|
14
|
+
constructor(speedButtonMobile: SpeedControlButtonMobile);
|
|
15
15
|
/**
|
|
16
16
|
* Function for removing children from the registry.
|
|
17
17
|
* @public
|
|
@@ -3,7 +3,7 @@ import { UXLayer } from "../../../layers";
|
|
|
3
3
|
import { RainMan } from "../../../Rainman";
|
|
4
4
|
import { ResponsiveContainer } from "../../common";
|
|
5
5
|
import { UPDATABLE_MODES, UpdatableTextComponent } from "../../updatable";
|
|
6
|
-
import { InfoButton, NegButton
|
|
6
|
+
import { InfoButton, NegButton } from "../default";
|
|
7
7
|
import { COMPONENTS, REGISTRY } from "../registrynames";
|
|
8
8
|
import { MOBILE_BUTTONS_GAP, MOBILE_PANEL_BUTTON_SCALE, MOBILE_X_OFFSET, MOBILE_Y_BOTTOM_OFFSET } from "./constants";
|
|
9
9
|
/**
|
|
@@ -11,22 +11,25 @@ import { MOBILE_BUTTONS_GAP, MOBILE_PANEL_BUTTON_SCALE, MOBILE_X_OFFSET, MOBILE_
|
|
|
11
11
|
* @augments {ResponsiveContainer}
|
|
12
12
|
*/
|
|
13
13
|
export class RightButtonsMobile extends ResponsiveContainer {
|
|
14
|
+
speedButtonMobile;
|
|
14
15
|
infoButton = new InfoButton(true);
|
|
15
16
|
negButton = new NegButton();
|
|
16
|
-
speedControlButton = new SpeedControlButton();
|
|
17
17
|
bet = new UpdatableTextComponent(COMPONENTS.betText, i18next.t("bet"), UPDATABLE_MODES.money, RainMan.config.mobileFontSize);
|
|
18
|
-
constructor() {
|
|
18
|
+
constructor(speedButtonMobile) {
|
|
19
19
|
super(-1);
|
|
20
|
+
this.speedButtonMobile = speedButtonMobile;
|
|
20
21
|
this.name = REGISTRY.rightButtons;
|
|
21
22
|
this.parentLayer = UXLayer;
|
|
22
23
|
this.negButton.visible = false;
|
|
23
|
-
this.speedControlButton.visible = false;
|
|
24
24
|
this.infoButton.anchor.set(1, 0.5);
|
|
25
25
|
this.infoButton.scale.set(-MOBILE_PANEL_BUTTON_SCALE);
|
|
26
26
|
this.bet.pivot.set(this.bet.width, this.bet.height / 2);
|
|
27
27
|
this.bet.scale.set(-1);
|
|
28
|
-
this.
|
|
29
|
-
|
|
28
|
+
this.speedButtonMobile.scale.set(-1);
|
|
29
|
+
this.speedButtonMobile.x = 100;
|
|
30
|
+
this.speedButtonMobile.y = 200;
|
|
31
|
+
this.addChild(this.infoButton, this.bet, this.speedButtonMobile);
|
|
32
|
+
RainMan.componentRegistry.addMany([this.infoButton, this.bet, this.negButton]);
|
|
30
33
|
this.resize();
|
|
31
34
|
}
|
|
32
35
|
/**
|
|
@@ -35,7 +38,7 @@ export class RightButtonsMobile extends ResponsiveContainer {
|
|
|
35
38
|
* @returns {void}
|
|
36
39
|
*/
|
|
37
40
|
removeChildrenFromRegistry() {
|
|
38
|
-
RainMan.componentRegistry.removeMany([this.infoButton, this.bet, this.negButton
|
|
41
|
+
RainMan.componentRegistry.removeMany([this.infoButton, this.bet, this.negButton]);
|
|
39
42
|
}
|
|
40
43
|
/**
|
|
41
44
|
* Function for repositioning components on mobile screens.
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { SpeedAdapterInterface, SpeedLevel, SpeedLevelDirectory } from "../../../application";
|
|
2
|
+
import { BaseButton, TextureMap } from "../BaseButton";
|
|
3
|
+
/**
|
|
4
|
+
* Button for speed control {@link SpeedLevel}
|
|
5
|
+
* It needs following textures:
|
|
6
|
+
* - turtle - `speed-turtle.png`
|
|
7
|
+
* - rabbit - `speed-rabbit.png`
|
|
8
|
+
* - cheetah - `speed-cheetah.png`
|
|
9
|
+
* @class
|
|
10
|
+
*/
|
|
11
|
+
export declare class SpeedControlButtonMobile extends BaseButton implements SpeedAdapterInterface<TextureMap> {
|
|
12
|
+
static readonly registryName = "speedControlButtonMobile";
|
|
13
|
+
readonly speedLevelMapper: SpeedLevelDirectory<TextureMap>;
|
|
14
|
+
constructor();
|
|
15
|
+
/**
|
|
16
|
+
* Change button's texture according to speed level
|
|
17
|
+
* @public
|
|
18
|
+
* @param {SpeedLevel} speedLevel - new speed level
|
|
19
|
+
* @returns {void}
|
|
20
|
+
*/
|
|
21
|
+
adaptToSpeed(speedLevel: SpeedLevel): void;
|
|
22
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { RainMan } from "../../../Rainman";
|
|
2
|
+
import { getTexture } from "../../../utils";
|
|
3
|
+
import { BaseButton, ButtonStates } from "../BaseButton";
|
|
4
|
+
const createTextureMap = (speedLevel) => {
|
|
5
|
+
return {
|
|
6
|
+
[ButtonStates.NORMAL]: getTexture(`${speedLevel}.png`),
|
|
7
|
+
[ButtonStates.CLICKED]: getTexture(`${speedLevel}-c.png`)
|
|
8
|
+
};
|
|
9
|
+
};
|
|
10
|
+
const createTextureMapForSpeed = (speedLevel) => {
|
|
11
|
+
const speedLevelMapper = {
|
|
12
|
+
slow: createTextureMap("turtle"),
|
|
13
|
+
normal: createTextureMap("rabbit"),
|
|
14
|
+
fast: createTextureMap("cheetah")
|
|
15
|
+
};
|
|
16
|
+
return speedLevelMapper[speedLevel];
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* Button for speed control {@link SpeedLevel}
|
|
20
|
+
* It needs following textures:
|
|
21
|
+
* - turtle - `speed-turtle.png`
|
|
22
|
+
* - rabbit - `speed-rabbit.png`
|
|
23
|
+
* - cheetah - `speed-cheetah.png`
|
|
24
|
+
* @class
|
|
25
|
+
*/
|
|
26
|
+
export class SpeedControlButtonMobile extends BaseButton {
|
|
27
|
+
static registryName = "speedControlButtonMobile";
|
|
28
|
+
speedLevelMapper;
|
|
29
|
+
constructor() {
|
|
30
|
+
super(SpeedControlButtonMobile.registryName, createTextureMapForSpeed(RainMan.settingsStore.currentSpeed));
|
|
31
|
+
this.speedLevelMapper = {
|
|
32
|
+
slow: createTextureMap("turtle"),
|
|
33
|
+
normal: createTextureMap("rabbit"),
|
|
34
|
+
fast: createTextureMap("cheetah")
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Change button's texture according to speed level
|
|
39
|
+
* @public
|
|
40
|
+
* @param {SpeedLevel} speedLevel - new speed level
|
|
41
|
+
* @returns {void}
|
|
42
|
+
*/
|
|
43
|
+
adaptToSpeed(speedLevel) {
|
|
44
|
+
if (RainMan.settingsStore.isTemporarySpeed) {
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
const textureMap = this.speedLevelMapper[speedLevel];
|
|
48
|
+
this.setTextureMap(textureMap);
|
|
49
|
+
this.texture = textureMap[ButtonStates.NORMAL];
|
|
50
|
+
}
|
|
51
|
+
}
|
|
@@ -9,6 +9,7 @@ export * from "./PlusButton";
|
|
|
9
9
|
export * from "./RedButton";
|
|
10
10
|
export * from "./RefreshButton";
|
|
11
11
|
export * from "./SpeedControlButton";
|
|
12
|
+
export * from "./SpeedControlButtonMobile";
|
|
12
13
|
export * from "./SpinConfirmationButton";
|
|
13
14
|
export * from "./TakeButton";
|
|
14
15
|
export * from "./VolumeButton";
|
|
@@ -9,6 +9,7 @@ export * from "./PlusButton";
|
|
|
9
9
|
export * from "./RedButton";
|
|
10
10
|
export * from "./RefreshButton";
|
|
11
11
|
export * from "./SpeedControlButton";
|
|
12
|
+
export * from "./SpeedControlButtonMobile";
|
|
12
13
|
export * from "./SpinConfirmationButton";
|
|
13
14
|
export * from "./TakeButton";
|
|
14
15
|
export * from "./VolumeButton";
|
|
@@ -11,6 +11,7 @@ export declare class ConnectionWrapper implements SubscribableConnectionWrapper
|
|
|
11
11
|
private fetchInProgress;
|
|
12
12
|
private lastFetchResponse;
|
|
13
13
|
private lastGambleResponse;
|
|
14
|
+
private pendingSpinEndPromise;
|
|
14
15
|
private subscribers;
|
|
15
16
|
/**
|
|
16
17
|
* Mapper function for data that comes from the server
|
|
@@ -17,6 +17,7 @@ export class ConnectionWrapper {
|
|
|
17
17
|
fetchInProgress = false;
|
|
18
18
|
lastFetchResponse = new Map();
|
|
19
19
|
lastGambleResponse = null;
|
|
20
|
+
pendingSpinEndPromise = null;
|
|
20
21
|
subscribers = [];
|
|
21
22
|
/**
|
|
22
23
|
* Mapper function for data that comes from the server
|
|
@@ -83,6 +84,7 @@ export class ConnectionWrapper {
|
|
|
83
84
|
* @memberof ConnectionWrapper
|
|
84
85
|
*/
|
|
85
86
|
async fetchInitData() {
|
|
87
|
+
this.pendingSpinEndPromise = null;
|
|
86
88
|
this._initData = (await this.fetch({
|
|
87
89
|
action: "init",
|
|
88
90
|
reference: RainMan.config.gameInitReference,
|
|
@@ -177,6 +179,9 @@ export class ConnectionWrapper {
|
|
|
177
179
|
if (typeof this.config?.token === "undefined") {
|
|
178
180
|
throw new Error("Token was not defined");
|
|
179
181
|
}
|
|
182
|
+
if (this.pendingSpinEndPromise !== null) {
|
|
183
|
+
await this.pendingSpinEndPromise;
|
|
184
|
+
}
|
|
180
185
|
const data = await this.fetch({
|
|
181
186
|
action: "spin",
|
|
182
187
|
reference: RainMan.config.gameInitReference,
|
|
@@ -186,7 +191,14 @@ export class ConnectionWrapper {
|
|
|
186
191
|
extra_data
|
|
187
192
|
});
|
|
188
193
|
this._messageHistory.push(data);
|
|
189
|
-
this.sendEndOfRoundData(data.round_number);
|
|
194
|
+
const endPromise = this.sendEndOfRoundData(data.round_number);
|
|
195
|
+
let trackedEndPromise = null;
|
|
196
|
+
trackedEndPromise = endPromise.finally(() => {
|
|
197
|
+
if (this.pendingSpinEndPromise === trackedEndPromise) {
|
|
198
|
+
this.pendingSpinEndPromise = null;
|
|
199
|
+
}
|
|
200
|
+
});
|
|
201
|
+
this.pendingSpinEndPromise = trackedEndPromise;
|
|
190
202
|
return new SpinData(this.config, data);
|
|
191
203
|
}
|
|
192
204
|
/**
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import i18next from "i18next";
|
|
2
2
|
import { sample } from "lodash";
|
|
3
3
|
import { ApiConfig, SoundManager, SoundTracks, SPEED_LEVELS } from "../application";
|
|
4
|
-
import { AbstractFrame, AutoplayButton, BUTTONS, COMPONENTS, FreeSpinButton, MessageBox, RefreshButton, SpeedControlButton } from "../components";
|
|
4
|
+
import { AbstractFrame, AutoplayButton, BUTTONS, COMPONENTS, FreeSpinButton, MessageBox, RefreshButton, SpeedControlButton, SpeedControlButtonMobile } from "../components";
|
|
5
5
|
import { SpinData } from "../connectivity";
|
|
6
6
|
import { gamePhases, PossibleWins } from "../constants";
|
|
7
7
|
import { RainMan } from "../Rainman";
|
|
@@ -256,7 +256,10 @@ export class AbstractController {
|
|
|
256
256
|
* @returns {void}
|
|
257
257
|
*/
|
|
258
258
|
disableSpeedButton(shouldBeDisabled) {
|
|
259
|
-
RainMan.componentRegistry.
|
|
259
|
+
RainMan.componentRegistry.getIfExists(SpeedControlButton.registryName)?.flipDisabledFlag(shouldBeDisabled);
|
|
260
|
+
RainMan.componentRegistry
|
|
261
|
+
.getIfExists(SpeedControlButtonMobile.registryName)
|
|
262
|
+
?.flipDisabledFlag(shouldBeDisabled);
|
|
260
263
|
}
|
|
261
264
|
/**
|
|
262
265
|
* Function for disabling information buttons
|
|
@@ -289,14 +292,11 @@ export class AbstractController {
|
|
|
289
292
|
*/
|
|
290
293
|
handleDisablingButtons(disabled) {
|
|
291
294
|
this.disableBetButtons(disabled ?? this.shouldBetButtonsBeDisabled);
|
|
292
|
-
|
|
293
|
-
RainMan.globals.isSuperBonusGameEnabled
|
|
294
|
-
RainMan.settingsStore.isAutoplayEnabled
|
|
295
|
-
this.
|
|
296
|
-
|
|
297
|
-
else {
|
|
298
|
-
this.disableSpeedButton(disabled ?? this.shouldButtonsBeDisabled);
|
|
299
|
-
}
|
|
295
|
+
const shouldSpeedBeDisabled = !RainMan.settingsStore.isFreeSpinsPlayEnabled &&
|
|
296
|
+
!RainMan.globals.isSuperBonusGameEnabled &&
|
|
297
|
+
!RainMan.settingsStore.isAutoplayEnabled &&
|
|
298
|
+
this.shouldButtonsBeDisabled;
|
|
299
|
+
this.disableSpeedButton(shouldSpeedBeDisabled);
|
|
300
300
|
}
|
|
301
301
|
/**
|
|
302
302
|
* Function for initializing buttons
|
|
@@ -339,10 +339,12 @@ export class AbstractController {
|
|
|
339
339
|
this.gamePhase === gamePhases.SPINNING ||
|
|
340
340
|
this.gamePhase === gamePhases.GAME_SUMMARY);
|
|
341
341
|
}
|
|
342
|
-
RainMan.componentRegistry.
|
|
342
|
+
RainMan.componentRegistry.getIfExists(SpeedControlButton.registryName)?.setOnClick(() => {
|
|
343
343
|
RainMan.settingsStore.closeCurrentlyOpenModal?.();
|
|
344
344
|
RainMan.componentRegistry.nextSpeedLevel();
|
|
345
|
-
|
|
345
|
+
const speedLevel = RainMan.componentRegistry.getSpeedLevel();
|
|
346
|
+
this.uiController.updateShownSpeedLevel(speedLevel);
|
|
347
|
+
this.uiController.messageBox.updateIncentiveText(sample(i18next.t("idleMessages", { returnObjects: true })[speedLevel]));
|
|
346
348
|
});
|
|
347
349
|
}
|
|
348
350
|
/**
|
|
@@ -365,6 +367,13 @@ export class AbstractController {
|
|
|
365
367
|
}
|
|
366
368
|
RainMan.settingsStore.handleModalInvocation?.(UI_ITEMS.bet);
|
|
367
369
|
});
|
|
370
|
+
if (RainMan.componentRegistry.has(SpeedControlButtonMobile.registryName)) {
|
|
371
|
+
RainMan.componentRegistry.get(SpeedControlButtonMobile.registryName).setOnClick(() => {
|
|
372
|
+
RainMan.settingsStore.closeCurrentlyOpenModal?.();
|
|
373
|
+
RainMan.componentRegistry.nextSpeedLevel();
|
|
374
|
+
this.uiController.messageBox.updateIncentiveText(sample(i18next.t("idleMessages", { returnObjects: true })[RainMan.componentRegistry.getSpeedLevel()]));
|
|
375
|
+
});
|
|
376
|
+
}
|
|
368
377
|
return;
|
|
369
378
|
}
|
|
370
379
|
RainMan.componentRegistry.get(BUTTONS.plus).setOnClick(() => {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { round } from "lodash";
|
|
2
|
-
import { COMPONENTS, MessageBox, SpeedControlButton } from "../components";
|
|
2
|
+
import { COMPONENTS, MessageBox, SpeedControlButton, SpeedControlButtonMobile } from "../components";
|
|
3
3
|
import { RainMan } from "../Rainman";
|
|
4
4
|
import { ceilToDecimal } from "../utils";
|
|
5
5
|
/**
|
|
@@ -181,8 +181,12 @@ export class UiController {
|
|
|
181
181
|
* @returns {void}
|
|
182
182
|
*/
|
|
183
183
|
updateShownSpeedLevel(currentSpeed) {
|
|
184
|
-
RainMan.componentRegistry.
|
|
185
|
-
RainMan.componentRegistry.
|
|
184
|
+
const speedButton = RainMan.componentRegistry.getIfExists(SpeedControlButton.registryName);
|
|
185
|
+
const mobileSpeedButton = RainMan.componentRegistry.getIfExists(SpeedControlButtonMobile.registryName);
|
|
186
|
+
speedButton?.adaptToSpeed(currentSpeed);
|
|
187
|
+
speedButton?.forceTextureUpdate();
|
|
188
|
+
mobileSpeedButton?.adaptToSpeed(currentSpeed);
|
|
189
|
+
mobileSpeedButton?.forceTextureUpdate();
|
|
186
190
|
}
|
|
187
191
|
/**
|
|
188
192
|
* Function for updating shown balance
|
|
@@ -216,7 +220,6 @@ export class UiController {
|
|
|
216
220
|
}
|
|
217
221
|
/**
|
|
218
222
|
* Shows game pays in a bottom panel, if exists
|
|
219
|
-
* @param amount
|
|
220
223
|
* @public
|
|
221
224
|
* @returns {void}
|
|
222
225
|
*/
|
|
@@ -24,7 +24,7 @@ const pauseAudio = () => {
|
|
|
24
24
|
shouldResumeAudioOnInterruption = false;
|
|
25
25
|
removeInterruptedAudioResumeListeners();
|
|
26
26
|
if (RainMan.settingsStore.isSoundEnabled()) {
|
|
27
|
-
SoundManager.
|
|
27
|
+
SoundManager.stopSoundsForPageHide();
|
|
28
28
|
}
|
|
29
29
|
};
|
|
30
30
|
/**
|
|
@@ -81,9 +81,9 @@ const handleVisibilityChange = () => {
|
|
|
81
81
|
* @returns {void}
|
|
82
82
|
*/
|
|
83
83
|
export const loadSoundsOnTabChange = () => {
|
|
84
|
-
sound.disableAutoPause =
|
|
84
|
+
sound.disableAutoPause = false;
|
|
85
85
|
document.addEventListener("visibilitychange", handleVisibilityChange);
|
|
86
86
|
window.addEventListener("pagehide", () => pauseAudio());
|
|
87
|
-
window.addEventListener("pageshow", () =>
|
|
88
|
-
window.addEventListener("focus", () =>
|
|
87
|
+
window.addEventListener("pageshow", () => interruptedAudioResume());
|
|
88
|
+
window.addEventListener("focus", () => interruptedAudioResume());
|
|
89
89
|
};
|
package/package.json
CHANGED