pixi-rainman-game-engine 0.2.28 → 0.3.0

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.
@@ -3,7 +3,7 @@ import { Application } from "pixi.js";
3
3
  import { SymbolIds, WinTypeIds } from "../application";
4
4
  import { ComponentRegistry } from "../ComponentRegistry";
5
5
  import { SettingsStore } from "../stores";
6
- import { AppConfig, Globals, OptionalAppConfig, RequiredAppConfig } from "./types";
6
+ import { AppConfigWithoutToken, Globals, OptionalAppConfig, RequiredAppConfig } from "./types";
7
7
  /**
8
8
  * This class represents Pixi application. Before initializing game, user has to configure following:
9
9
  * - {@link Application}
@@ -20,5 +20,10 @@ export declare class RainMan {
20
20
  static settingsStore: SettingsStore;
21
21
  static componentRegistry: ComponentRegistry;
22
22
  static globals: Globals;
23
- constructor(app: Application, config: AppConfig, symbolIds: SymbolIds, winTypeIds: WinTypeIds);
23
+ constructor(app: Application, config: AppConfigWithoutToken, symbolIds: SymbolIds, winTypeIds: WinTypeIds);
24
+ /**
25
+ * Method for genereting a token or getting existing token for the game session.
26
+ * @returns {string} - token for the game session
27
+ */
28
+ private getToken;
24
29
  }
@@ -1,6 +1,7 @@
1
1
  import "../components/dictionary/i18n";
2
2
  import { merge } from "lodash";
3
3
  import { Currencies } from "ts-money";
4
+ import uuid4 from "uuid4";
4
5
  import { ComponentRegistry } from "../ComponentRegistry";
5
6
  import { settingStore } from "../SettingsUI/hooks";
6
7
  import { defaultAppConfig } from "./appConfig";
@@ -22,7 +23,9 @@ export class RainMan {
22
23
  static globals;
23
24
  constructor(app, config, symbolIds, winTypeIds) {
24
25
  RainMan.app = app;
25
- RainMan.config = merge(defaultAppConfig, config);
26
+ RainMan.config = merge({}, defaultAppConfig, config, {
27
+ gameInitToken: this.getToken()
28
+ });
26
29
  RainMan.symbolIds = symbolIds;
27
30
  RainMan.winTypeIds = winTypeIds;
28
31
  RainMan.settingsStore = settingStore;
@@ -32,4 +35,21 @@ export class RainMan {
32
35
  shouldShowModals: false
33
36
  };
34
37
  }
38
+ /**
39
+ * Method for genereting a token or getting existing token for the game session.
40
+ * @returns {string} - token for the game session
41
+ */
42
+ getToken() {
43
+ const url = new URL(window.location.href);
44
+ let token = url.searchParams.get("token");
45
+ if (token) {
46
+ return token;
47
+ }
48
+ else {
49
+ token = uuid4();
50
+ url.searchParams.set("token", token);
51
+ window.history.replaceState({}, "", url.toString());
52
+ return token;
53
+ }
54
+ }
35
55
  }
@@ -62,6 +62,7 @@ export type OptionalAppConfig = {
62
62
  };
63
63
  };
64
64
  export type AppConfig = RequiredAppConfig & DeepPartial<OptionalAppConfig>;
65
+ export type AppConfigWithoutToken = Omit<RequiredAppConfig, "gameInitToken"> & DeepPartial<OptionalAppConfig>;
65
66
  /**
66
67
  * This interface represents global variables in pixi application. Can be extended in `engine.d.ts` in each project to provide project-wide variables.
67
68
  */
@@ -131,5 +131,15 @@ export declare class ButtonsEventManager {
131
131
  * @param {string} layerName - name of layer
132
132
  */
133
133
  private handleModalInvocation;
134
+ /**
135
+ * Function for closing all other modals except the one with given name
136
+ * @param {string} activeLayerName - name of the layer that should remain open
137
+ */
138
+ private closeOtherModals;
139
+ /**
140
+ * Function for checking if any layer is present except the one with given name
141
+ * @param {string} layerName - name of layer to check
142
+ * @returns {boolean} - true if any other layer is present, false otherwise
143
+ */
134
144
  private checkAnyLayerIsPresent;
135
145
  }
@@ -327,6 +327,9 @@ export class ButtonsEventManager {
327
327
  handleModalInvocation(layerName) {
328
328
  if (this.checkAnyLayerIsPresent(layerName) && RainMan.globals.shouldShowModals)
329
329
  return;
330
+ if (this.checkAnyLayerIsPresent(layerName)) {
331
+ this.closeOtherModals(layerName);
332
+ }
330
333
  const layer = window.document.getElementById(layerName);
331
334
  if (layer !== null) {
332
335
  if (layer.style.display !== "flex") {
@@ -339,6 +342,26 @@ export class ButtonsEventManager {
339
342
  }
340
343
  }
341
344
  }
345
+ /**
346
+ * Function for closing all other modals except the one with given name
347
+ * @param {string} activeLayerName - name of the layer that should remain open
348
+ */
349
+ closeOtherModals(activeLayerName) {
350
+ for (const itemId of allUiItems) {
351
+ if (itemId === activeLayerName) {
352
+ continue;
353
+ }
354
+ const layer = window.document.getElementById(itemId);
355
+ if (layer !== null && layer.style.display === "flex") {
356
+ layer.style.display = "none";
357
+ }
358
+ }
359
+ }
360
+ /**
361
+ * Function for checking if any layer is present except the one with given name
362
+ * @param {string} layerName - name of layer to check
363
+ * @returns {boolean} - true if any other layer is present, false otherwise
364
+ */
342
365
  checkAnyLayerIsPresent(layerName) {
343
366
  return Object.values(UI_ITEMS).some((item) => {
344
367
  if (item === layerName)
@@ -1,6 +1,7 @@
1
1
  import { Sprite } from "pixi.js";
2
2
  import { SoundManager, SoundTracks } from "../../../application";
3
3
  import { TINT_DISABLED, TINT_ENABLED } from "../../../constants";
4
+ import { hidePaytable } from "../../../utils";
4
5
  /**
5
6
  * Class for basic button with states and textures
6
7
  * @class BaseButton
@@ -23,6 +24,7 @@ export class BaseButton extends Sprite {
23
24
  }
24
25
  this._customClickHandler();
25
26
  this._manageStateOver();
27
+ hidePaytable();
26
28
  };
27
29
  _customClickHandler = () => { };
28
30
  constructor(name, textureMap, stateful = false, clickSound = SoundTracks.button) {
@@ -32,19 +32,81 @@ export declare class MessageBox extends Container {
32
32
  private incentiveMessageShown;
33
33
  private winLineIndicatorShown;
34
34
  constructor();
35
+ /**
36
+ * Updates the incentive text displayed in the message box.
37
+ * @param {string} newText - The new text to display.
38
+ */
35
39
  updateIncentiveText(newText: string): void;
40
+ /**
41
+ * Function for hiding current win text
42
+ */
36
43
  hideCurrentWinText(): void;
44
+ /**
45
+ * Function fro hiding possible win text
46
+ */
37
47
  hidePossibleWinText(): void;
48
+ /**
49
+ * Function for hiding free spin text
50
+ */
38
51
  hideFreeSpinText(): void;
52
+ /**
53
+ * Function for hiding auto spin text
54
+ */
39
55
  hideAutoSpinText(): void;
56
+ /**
57
+ * Function for hiding incentive text
58
+ */
40
59
  hideIncentiveText(): void;
60
+ /**
61
+ * Function for hiding win line indicator
62
+ */
41
63
  hideWinLineIndicator(): void;
64
+ /**
65
+ * Function for resizing message box
66
+ * It sets the scale of the message box to the global minimum ratio.
67
+ * If the device orientation is mobile and the win line indicator is shown, it repositions
68
+ * the win line indicator to ensure it is displayed correctly.
69
+ * @memberof MessageBox
70
+ */
42
71
  resize(): void;
72
+ /**
73
+ * Getter for the height of the win line animation.
74
+ * If the win line indicator is not defined, it returns 0.
75
+ * @returns {number} The height of the win line animation.
76
+ */
77
+ get winLineAnimationHeight(): number;
78
+ /**
79
+ * Displays the current win text in the message box.
80
+ * @returns {void}
81
+ */
43
82
  showCurrentWinText(): void;
44
83
  showPossibleWinText(): void;
84
+ /**
85
+ * Displays the auto spin text in the message box.
86
+ * It checks if auto spins are enabled and if the text is already shown.
87
+ * @returns {void}
88
+ */
45
89
  showAutoSpinText(): void;
90
+ /**
91
+ * Displays the free spin text in the message box.
92
+ * It checks if free spins are enabled and if the text is already shown.
93
+ * If free spin text is disabled in the configuration, it does nothing.
94
+ * @returns {void}
95
+ */
46
96
  showFreeSpinText(): void;
47
97
  showIncentiveText(): void;
98
+ /**
99
+ * Function to center a text component on the X-axis of the message box.
100
+ * @param {Container | undefined} component container component to center
101
+ * @returns {void}
102
+ */
48
103
  private centerTextOnX;
104
+ /**
105
+ * Displays the win line indicator in the message box.
106
+ * @param {string} message The message to display.
107
+ * @param {(symbolId: SymbolId, suffix?: string) => string} getImageForSymbolId Function to get the image for a symbol ID.
108
+ * @param {SymbolId[]} symbolIds The symbol IDs to display.
109
+ * @param {Partial<ITextStyle>} winLineTextStyleOverrides Overrides for the text style.
110
+ */
49
111
  showWinLineIndicator(message: string, getImageForSymbolId: (symbolId: SymbolId, suffix?: string) => string, symbolIds?: SymbolId[], winLineTextStyleOverrides?: Partial<ITextStyle>): void;
50
112
  }
@@ -4,7 +4,7 @@ import { Color, Container, Graphics, Text } from "pixi.js";
4
4
  import { UPDATABLE_MODES, UpdatableTextComponent, WinLineIndicator } from "../../components";
5
5
  import { UXLayer } from "../../layers";
6
6
  import { RainMan } from "../../Rainman";
7
- import { getDeviceOrientation, globalMinRatio } from "../../utils";
7
+ import { getDeviceOrientation } from "../../utils";
8
8
  /**
9
9
  * Class represents messages information in box
10
10
  * Like:
@@ -44,7 +44,7 @@ export class MessageBox extends Container {
44
44
  : RainMan.config.fontSize;
45
45
  this.positioningFrame = new Graphics();
46
46
  this.positioningFrame.beginFill(0xff0000, 0.0);
47
- this.positioningFrame.drawRect(0, 0, 800, 100);
47
+ this.positioningFrame.drawRect(0, 0, 800, 150);
48
48
  this.addChild(this.positioningFrame);
49
49
  this.parentLayer = UXLayer;
50
50
  this.freeSpinText = new UpdatableTextComponent(MessageBox.freeSpinTextRegistryName, i18n.t("currentFreeSpins"), UPDATABLE_MODES.int, fontSize, new Color(0xffffff).toHex(), () => this.centerTextOnX(this.freeSpinText));
@@ -70,40 +70,62 @@ export class MessageBox extends Container {
70
70
  this.possibleWinText
71
71
  ]);
72
72
  }
73
+ /**
74
+ * Updates the incentive text displayed in the message box.
75
+ * @param {string} newText - The new text to display.
76
+ */
73
77
  updateIncentiveText(newText) {
74
78
  this.incentiveText.text = newText;
75
79
  this.centerTextOnX(this.incentiveText);
76
80
  }
81
+ /**
82
+ * Function for hiding current win text
83
+ */
77
84
  hideCurrentWinText() {
78
85
  if (this.currentWinShown) {
79
86
  this.currentWinShown = false;
80
87
  this.removeChild(this.currentWinText);
81
88
  }
82
89
  }
90
+ /**
91
+ * Function fro hiding possible win text
92
+ */
83
93
  hidePossibleWinText() {
84
94
  if (this.possibleWinShown) {
85
95
  this.possibleWinShown = false;
86
96
  this.removeChild(this.possibleWinText);
87
97
  }
88
98
  }
99
+ /**
100
+ * Function for hiding free spin text
101
+ */
89
102
  hideFreeSpinText() {
90
103
  if (this.freeSpinShown) {
91
104
  this.freeSpinShown = false;
92
105
  this.removeChild(this.freeSpinText);
93
106
  }
94
107
  }
108
+ /**
109
+ * Function for hiding auto spin text
110
+ */
95
111
  hideAutoSpinText() {
96
112
  if (this.autoSpinShown) {
97
113
  this.autoSpinShown = false;
98
114
  this.removeChild(this.autoSpinText);
99
115
  }
100
116
  }
117
+ /**
118
+ * Function for hiding incentive text
119
+ */
101
120
  hideIncentiveText() {
102
121
  if (this.incentiveMessageShown) {
103
122
  this.incentiveMessageShown = false;
104
123
  this.removeChild(this.incentiveText);
105
124
  }
106
125
  }
126
+ /**
127
+ * Function for hiding win line indicator
128
+ */
107
129
  hideWinLineIndicator() {
108
130
  if (this.winLineIndicatorShown && this.winLineIndicator) {
109
131
  this.winLineIndicatorShown = false;
@@ -112,50 +134,84 @@ export class MessageBox extends Container {
112
134
  this.winLineIndicator = undefined;
113
135
  }
114
136
  }
137
+ /**
138
+ * Function for resizing message box
139
+ * It sets the scale of the message box to the global minimum ratio.
140
+ * If the device orientation is mobile and the win line indicator is shown, it repositions
141
+ * the win line indicator to ensure it is displayed correctly.
142
+ * @memberof MessageBox
143
+ */
115
144
  resize() {
116
- this.scale.set(globalMinRatio());
117
145
  if (getDeviceOrientation().includes("mobile") && this.winLineIndicatorShown && this.winLineIndicator) {
118
146
  this.removeChild(this.winLineIndicator);
119
147
  this.addChild(this.winLineIndicator);
120
148
  }
121
149
  }
150
+ /**
151
+ * Getter for the height of the win line animation.
152
+ * If the win line indicator is not defined, it returns 0.
153
+ * @returns {number} The height of the win line animation.
154
+ */
155
+ get winLineAnimationHeight() {
156
+ return this.winLineIndicator?.height ?? 0;
157
+ }
158
+ /**
159
+ * Displays the current win text in the message box.
160
+ * @returns {void}
161
+ */
122
162
  showCurrentWinText() {
123
- if (RainMan.settingsStore.isFreeSpinsPlayEnabled && RainMan.config.disableFreeSpinText)
163
+ if (RainMan.settingsStore.isFreeSpinsPlayEnabled && RainMan.config.disableFreeSpinText) {
124
164
  return;
165
+ }
125
166
  this.hideIncentiveText();
126
167
  this.hidePossibleWinText();
127
- if (this.currentWinShown)
168
+ if (this.currentWinShown) {
128
169
  return;
170
+ }
129
171
  this.currentWinShown = true;
130
172
  this.centerTextOnX(this.currentWinText);
131
173
  this.addChild(this.currentWinText);
132
174
  }
133
175
  showPossibleWinText() {
134
176
  this.hideIncentiveText();
135
- if (this.possibleWinShown)
177
+ if (this.possibleWinShown) {
136
178
  return;
179
+ }
137
180
  this.possibleWinShown = true;
138
181
  this.centerTextOnX(this.possibleWinText);
139
182
  this.addChild(this.possibleWinText);
140
183
  }
184
+ /**
185
+ * Displays the auto spin text in the message box.
186
+ * It checks if auto spins are enabled and if the text is already shown.
187
+ * @returns {void}
188
+ */
141
189
  showAutoSpinText() {
142
190
  this.hideIncentiveText();
143
191
  this.hideWinLineIndicator();
144
- if (this.autoSpinShown || this.freeSpinShown)
192
+ if (this.autoSpinShown || this.freeSpinShown) {
145
193
  return;
194
+ }
146
195
  this.autoSpinShown = true;
147
- this.autoSpinText.set(RainMan.settingsStore.howManyAutoSpinsLeft + 1);
196
+ this.autoSpinText.set(RainMan.settingsStore.howManyAutoSpinsLeft);
148
197
  this.centerTextOnX(this.autoSpinText);
149
198
  this.addChild(this.autoSpinText);
150
199
  }
200
+ /**
201
+ * Displays the free spin text in the message box.
202
+ * It checks if free spins are enabled and if the text is already shown.
203
+ * If free spin text is disabled in the configuration, it does nothing.
204
+ * @returns {void}
205
+ */
151
206
  showFreeSpinText() {
152
- if (RainMan.config.disableFreeSpinText)
207
+ if (RainMan.config.disableFreeSpinText) {
153
208
  return;
209
+ }
154
210
  this.hideIncentiveText();
155
- this.hideAutoSpinText();
156
211
  this.hideWinLineIndicator();
157
- if (this.freeSpinShown)
212
+ if (this.freeSpinShown) {
158
213
  return;
214
+ }
159
215
  this.freeSpinShown = true;
160
216
  this.centerTextOnX(this.freeSpinText);
161
217
  this.addChild(this.freeSpinText);
@@ -166,17 +222,31 @@ export class MessageBox extends Container {
166
222
  this.hideFreeSpinText();
167
223
  this.hideAutoSpinText();
168
224
  this.hideWinLineIndicator();
169
- if (this.incentiveMessageShown)
225
+ if (this.incentiveMessageShown) {
170
226
  return;
227
+ }
171
228
  this.incentiveMessageShown = true;
172
229
  this.centerTextOnX(this.incentiveText);
173
230
  this.addChild(this.incentiveText);
174
231
  }
232
+ /**
233
+ * Function to center a text component on the X-axis of the message box.
234
+ * @param {Container | undefined} component container component to center
235
+ * @returns {void}
236
+ */
175
237
  centerTextOnX(component) {
176
- if (!component)
238
+ if (!component) {
177
239
  return;
240
+ }
178
241
  component.x = this.positioningFrame.width / 2 - component.width / 2;
179
242
  }
243
+ /**
244
+ * Displays the win line indicator in the message box.
245
+ * @param {string} message The message to display.
246
+ * @param {(symbolId: SymbolId, suffix?: string) => string} getImageForSymbolId Function to get the image for a symbol ID.
247
+ * @param {SymbolId[]} symbolIds The symbol IDs to display.
248
+ * @param {Partial<ITextStyle>} winLineTextStyleOverrides Overrides for the text style.
249
+ */
180
250
  showWinLineIndicator(message, getImageForSymbolId, symbolIds = [], winLineTextStyleOverrides = {}) {
181
251
  this.hideWinLineIndicator();
182
252
  this.hideIncentiveText();
@@ -195,7 +265,7 @@ export class MessageBox extends Container {
195
265
  ...winLineTextStyleOverrides
196
266
  };
197
267
  this.winLineIndicator = new WinLineIndicator(winLineTextStyle, getImageForSymbolId, message, symbolIds);
198
- this.winLineIndicator.y = -this.currentWinText.y + this.winLineIndicator.height / 2;
268
+ this.winLineIndicator.y = 50;
199
269
  this.winLineIndicatorShown = true;
200
270
  this.centerTextOnX(this.winLineIndicator);
201
271
  this.addChild(this.winLineIndicator);
@@ -3,7 +3,7 @@ import { Spine } from "pixi-spine";
3
3
  import { animationsSpeedLevels, defaultSpeedConfig, SoundManager, SoundTracks } from "../../application";
4
4
  import { AnimationLayer } from "../../layers";
5
5
  import { RainMan } from "../../Rainman";
6
- import { getSpineData, getTexture, togglePaytable } from "../../utils";
6
+ import { getSpineData, getTexture, logError, togglePaytable } from "../../utils";
7
7
  /**
8
8
  * Class represents symbol which is displayed in columns
9
9
  * @abstract
@@ -117,11 +117,17 @@ export class AbstractSymbolBase extends Container {
117
117
  if (multiplier <= 1 || this.multiplierSpineName === null)
118
118
  return;
119
119
  const symbolMultiplier = new Spine(getSpineData(this.multiplierSpineName));
120
+ if (symbolMultiplier.state.hasAnimation(`x${multiplier}`)) {
121
+ symbolMultiplier.state.setAnimation(0, `x${multiplier}`, false);
122
+ }
123
+ else {
124
+ logError(`$ Multiplier animation 'x${multiplier}' does not exist for symbol ID: ${this._id}`);
125
+ return;
126
+ }
120
127
  this.addChild(symbolMultiplier);
121
128
  await new Promise((resolve) => {
122
129
  symbolMultiplier.state.timeScale = this.animationSpeedMultiplier;
123
130
  symbolMultiplier.parentLayer = AnimationLayer;
124
- symbolMultiplier.state.setAnimation(0, `x${multiplier}`, false);
125
131
  this.endOfMultiplierAnimationPromise = resolve;
126
132
  symbolMultiplier.state.addListener({
127
133
  complete: () => resolve()
@@ -1,4 +1,4 @@
1
- import { ExtraDataRequest, GambleCardColor, GambleDataInterface, InitDataInterface, ServerMessage, SpinData, SubscribableConnectionWrapper } from "../connectivity";
1
+ import { ExtraDataRequest, GambleCardColor, GambleDataInterface, InitDataInterface, MiniGameInterface, ServerMessage, SpinData, SubscribableConnectionWrapper } from "../connectivity";
2
2
  /**
3
3
  * Class for managing connection to the server via websockets
4
4
  * This class handles communication with the server, including fetching initial data, spin data, free spin data, and gamble data.
@@ -88,6 +88,14 @@ export declare class ConnectionWrapper implements SubscribableConnectionWrapper
88
88
  * @returns {WebSocket} fresh websocket instance
89
89
  */
90
90
  private getFreshWsInstance;
91
+ /**
92
+ * Method for fetching mini game data from the server
93
+ * @param {number} roundNumber - the round number to fetch data for
94
+ * @param {string} operation - the operation to perform
95
+ * @param {number} position - the position to use
96
+ * @returns {Promise<MiniGameInterface>} - the mini game data
97
+ */
98
+ fetchMiniGameData(roundNumber: number, operation: string, position: number): Promise<MiniGameInterface>;
91
99
  /**
92
100
  * Method for fetching data from the server
93
101
  * @param {ServerRequest} request request for the server
@@ -220,6 +220,30 @@ export class ConnectionWrapper {
220
220
  getFreshWsInstance() {
221
221
  return new WebSocket(RainMan.config.websocketUrl);
222
222
  }
223
+ /**
224
+ * Method for fetching mini game data from the server
225
+ * @param {number} roundNumber - the round number to fetch data for
226
+ * @param {string} operation - the operation to perform
227
+ * @param {number} position - the position to use
228
+ * @returns {Promise<MiniGameInterface>} - the mini game data
229
+ */
230
+ async fetchMiniGameData(roundNumber, operation, position) {
231
+ if (typeof this.config?.token === "undefined") {
232
+ throw new Error("Token was not defined");
233
+ }
234
+ const data = await this.fetch({
235
+ action: "mini-game",
236
+ operation,
237
+ round_number: roundNumber,
238
+ token: this.config.token,
239
+ reference: RainMan.config.gameInitReference,
240
+ extra_data: {
241
+ position: position
242
+ }
243
+ });
244
+ this.sendEndOfRoundData(roundNumber);
245
+ return data;
246
+ }
223
247
  /**
224
248
  * Method for fetching data from the server
225
249
  * @param {ServerRequest} request request for the server
@@ -1,5 +1,5 @@
1
1
  import { ServerMessage, SubscribableConnectionWrapper } from "./serverConnection";
2
- import { InitDataInterface } from "./serverData";
2
+ import { InitDataInterface, MiniGameInterface } from "./serverData";
3
3
  import { SpinData } from "./spinData";
4
4
  /**
5
5
  * Class for mocking connection to the server
@@ -19,6 +19,7 @@ export declare class LocalConnectionWrapper implements SubscribableConnectionWra
19
19
  fetchSpinData(): Promise<SpinData>;
20
20
  subscribeForConfigChanges(subscriberFn: () => void): void;
21
21
  sendEndOfRoundData(roundNumber: number): Promise<ServerMessage>;
22
+ fetchMiniGameData(_roundNumber: number, _operation: string, _position: number): Promise<MiniGameInterface>;
22
23
  sendTakeAction(roundNumber: number): Promise<ServerMessage>;
23
24
  fetchFreeSpinData(roundNumber: number, quantity: number): Promise<SpinData>;
24
25
  getMessageHistory(): ServerMessage[];
@@ -51,6 +51,14 @@ export class LocalConnectionWrapper {
51
51
  this.subscribers.forEach((subscriber) => subscriber());
52
52
  return Promise.resolve(data);
53
53
  }
54
+ fetchMiniGameData(_roundNumber, _operation, _position) {
55
+ return new Promise((res) => {
56
+ setTimeout(() => {
57
+ const data = apiQueue(this.localResponse);
58
+ res(data);
59
+ }, 200);
60
+ });
61
+ }
54
62
  sendTakeAction(roundNumber) {
55
63
  const data = {
56
64
  action: "take",
@@ -1,10 +1,11 @@
1
- import { EndDataInterface, GambleCardColor, GambleDataInterface, InitDataInterface, SpinDataInterface, TakeDataInterface } from "./serverData";
1
+ import { EndDataInterface, GambleCardColor, GambleDataInterface, InitDataInterface, MiniGameInterface, SpinDataInterface, TakeDataInterface } from "./serverData";
2
2
  import { SpinData } from "./spinData";
3
3
  export interface ServerCommunication {
4
4
  initCommunication(): Promise<void>;
5
5
  fetchInitData(): Promise<void>;
6
6
  initData(): InitDataInterface;
7
7
  fetchSpinData(roundNumber: number, bet: number, extraData?: ExtraDataRequest): Promise<SpinData>;
8
+ fetchMiniGameData(roundNumber: number, operation: string, position: number): Promise<MiniGameInterface>;
8
9
  fetchFreeSpinData(roundNumber: number, amount: number, price: number): Promise<SpinData>;
9
10
  sendEndOfRoundData(roundNumber: number): Promise<ServerMessage>;
10
11
  sendTakeAction(roundNumber: number): Promise<ServerMessage>;
@@ -35,6 +36,11 @@ export type SpinServerRequest = BaseServerRequest & {
35
36
  bet: number;
36
37
  extra_data: ExtraDataRequest;
37
38
  };
39
+ export type MiniGameRequest = {
40
+ action: "mini-game";
41
+ operation: string;
42
+ extra_data: ExtraDataRequest;
43
+ } & BaseServerRequest;
38
44
  export type BuyFreeSpinServerRequest = BaseServerRequest & {
39
45
  action: "buy";
40
46
  operation: "buy-free-spins";
@@ -57,6 +63,6 @@ export type TakeServerRequest = BaseServerRequest & {
57
63
  };
58
64
  export interface ExtraDataRequest {
59
65
  }
60
- export type ServerRequest = InitServerRequest | SpinServerRequest | BuyFreeSpinServerRequest | GambleServerRequest | EndServerRequest | TakeServerRequest;
61
- export type ServerMessage = InitDataInterface | SpinDataInterface | GambleDataInterface | EndDataInterface | TakeDataInterface;
66
+ export type ServerRequest = InitServerRequest | MiniGameRequest | SpinServerRequest | BuyFreeSpinServerRequest | GambleServerRequest | EndServerRequest | TakeServerRequest;
67
+ export type ServerMessage = InitDataInterface | SpinDataInterface | GambleDataInterface | EndDataInterface | MiniGameInterface | TakeDataInterface;
62
68
  export {};
@@ -40,6 +40,23 @@ export interface TakeDataInterface {
40
40
  };
41
41
  win_amount_total: number;
42
42
  }
43
+ export interface MiniGameInterface {
44
+ action: "mini-game";
45
+ balance: number;
46
+ round_number: number;
47
+ status: {
48
+ code: number;
49
+ message: string;
50
+ };
51
+ extra_data: ExtraData;
52
+ win_amount: number;
53
+ wins: Record<string, RawWin>;
54
+ matrix: {
55
+ height: number;
56
+ width: number;
57
+ symbols: Record<string, number>;
58
+ };
59
+ }
43
60
  export type JackpotType = "jackpot-mini" | "jackpot-minor" | "jackpot-major" | "jackpot-grand";
44
61
  export type JackpotWins = {
45
62
  "jackpot-grand": {
@@ -529,8 +529,8 @@ export class AbstractController {
529
529
  if (this.gamePhase === gamePhases.DATA_FETCH ||
530
530
  this.gamePhase === gamePhases.SPINNING ||
531
531
  this.gamePhase === gamePhases.CONFIGURING_SPIN) {
532
- this.isSpinThrottled = true;
533
532
  this.columnsContainer.enableQuickReelsStop();
533
+ this.isSpinThrottled = true;
534
534
  this.quickStopController.handleResetCounter(this.spinThrottlerTimeout !== null);
535
535
  this.quickStopController.handleInvokingSpeedPopup();
536
536
  return;
@@ -557,10 +557,10 @@ export class AbstractController {
557
557
  this.columnsContainer.clearQuickReelsStop();
558
558
  return;
559
559
  }
560
- if (this.mobileSpinTimeout !== null) {
561
- this.columnsContainer.clearQuickReelsStop();
562
- return;
563
- }
560
+ // if (this.mobileSpinTimeout !== null) {
561
+ // this.columnsContainer.clearQuickReelsStop();
562
+ // return;
563
+ // }
564
564
  if (this.gamePhase === gamePhases.IDLE || this.gamePhase === gamePhases.HANDLING_ACTIONS) {
565
565
  this.spin();
566
566
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pixi-rainman-game-engine",
3
- "version": "0.2.28",
3
+ "version": "0.3.0",
4
4
  "description": "This repository contains all of the mechanics that used in rainman games.",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.js",
@@ -38,6 +38,7 @@
38
38
  "react-dom": "^18.2.0",
39
39
  "stats.js": "^0.17.0",
40
40
  "ts-money": "^0.4.8",
41
+ "uuid4": "^2.0.3",
41
42
  "zod": "^3.22.4"
42
43
  },
43
44
  "devDependencies": {
@@ -47,6 +48,7 @@
47
48
  "@types/react-custom-scroll": "^5.0.3",
48
49
  "@types/react-dom": "^18.2.22",
49
50
  "@types/stats.js": "^0.17.3",
51
+ "@types/uuid4": "^2.0.3",
50
52
  "@types/web": "^0.0.199",
51
53
  "@typescript-eslint/eslint-plugin": "^7.0.2",
52
54
  "@typescript-eslint/parser": "^7.0.2",