@energy8platform/platform-core 0.16.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.
Files changed (57) hide show
  1. package/README.md +482 -0
  2. package/bin/simulate.ts +139 -0
  3. package/dist/dev-bridge.cjs.js +237 -0
  4. package/dist/dev-bridge.cjs.js.map +1 -0
  5. package/dist/dev-bridge.d.ts +141 -0
  6. package/dist/dev-bridge.esm.js +235 -0
  7. package/dist/dev-bridge.esm.js.map +1 -0
  8. package/dist/index.cjs.js +569 -0
  9. package/dist/index.cjs.js.map +1 -0
  10. package/dist/index.d.ts +439 -0
  11. package/dist/index.esm.js +560 -0
  12. package/dist/index.esm.js.map +1 -0
  13. package/dist/loading.cjs.js +190 -0
  14. package/dist/loading.cjs.js.map +1 -0
  15. package/dist/loading.d.ts +86 -0
  16. package/dist/loading.esm.js +185 -0
  17. package/dist/loading.esm.js.map +1 -0
  18. package/dist/lua.cjs.js +1129 -0
  19. package/dist/lua.cjs.js.map +1 -0
  20. package/dist/lua.d.ts +319 -0
  21. package/dist/lua.esm.js +1119 -0
  22. package/dist/lua.esm.js.map +1 -0
  23. package/dist/simulation.cjs.js +374 -0
  24. package/dist/simulation.cjs.js.map +1 -0
  25. package/dist/simulation.d.ts +190 -0
  26. package/dist/simulation.esm.js +368 -0
  27. package/dist/simulation.esm.js.map +1 -0
  28. package/dist/vite.cjs.js +179 -0
  29. package/dist/vite.cjs.js.map +1 -0
  30. package/dist/vite.d.ts +13 -0
  31. package/dist/vite.esm.js +176 -0
  32. package/dist/vite.esm.js.map +1 -0
  33. package/package.json +100 -0
  34. package/scripts/install-simulate.mjs +101 -0
  35. package/src/EventEmitter.ts +55 -0
  36. package/src/PlatformSession.ts +156 -0
  37. package/src/dev-bridge/DevBridge.ts +305 -0
  38. package/src/dev-bridge/index.ts +2 -0
  39. package/src/index.ts +98 -0
  40. package/src/loading/CSSPreloader.ts +129 -0
  41. package/src/loading/index.ts +3 -0
  42. package/src/loading/logo.ts +95 -0
  43. package/src/lua/ActionRouter.ts +132 -0
  44. package/src/lua/LuaEngine.ts +412 -0
  45. package/src/lua/LuaEngineAPI.ts +314 -0
  46. package/src/lua/PersistentState.ts +80 -0
  47. package/src/lua/SessionManager.ts +227 -0
  48. package/src/lua/SimulationRunner.ts +192 -0
  49. package/src/lua/fengari.d.ts +10 -0
  50. package/src/lua/index.ts +28 -0
  51. package/src/lua/types.ts +149 -0
  52. package/src/simulation/NativeSimulationRunner.ts +367 -0
  53. package/src/simulation/ParallelSimulationRunner.ts +156 -0
  54. package/src/simulation/SimulationWorker.ts +44 -0
  55. package/src/simulation/index.ts +21 -0
  56. package/src/types.ts +85 -0
  57. package/src/vite/index.ts +196 -0
@@ -0,0 +1,237 @@
1
+ 'use strict';
2
+
3
+ var gameSdk = require('@energy8platform/game-sdk');
4
+
5
+ const DEFAULT_CONFIG = {
6
+ balance: 10000,
7
+ currency: 'USD',
8
+ gameConfig: {
9
+ id: 'dev-game',
10
+ type: 'slot',
11
+ version: '1.0.0',
12
+ viewport: { width: 1920, height: 1080 },
13
+ betLevels: [0.1, 0.2, 0.5, 1, 2, 5, 10, 20, 50],
14
+ },
15
+ assetsUrl: '/assets/',
16
+ session: null,
17
+ onPlay: () => ({}),
18
+ networkDelay: 200,
19
+ debug: true,
20
+ };
21
+ /**
22
+ * Mock host bridge for local development.
23
+ *
24
+ * Uses the SDK's `Bridge` class in `devMode` to communicate with
25
+ * `CasinoGameSDK` via a shared in-memory `MemoryChannel`, removing
26
+ * the need for postMessage and iframes.
27
+ *
28
+ * When `luaScript` is set, play requests are sent to the Vite dev server
29
+ * which runs LuaEngine in Node.js — no fengari in the browser.
30
+ *
31
+ * @example
32
+ * ```ts
33
+ * import { DevBridge } from '@energy8platform/platform-core/dev-bridge';
34
+ *
35
+ * const devBridge = new DevBridge({
36
+ * balance: 5000,
37
+ * currency: 'EUR',
38
+ * gameConfig: { id: 'my-slot', type: 'slot', betLevels: [0.2, 0.5, 1, 2] },
39
+ * onPlay: ({ action, bet }) => ({
40
+ * totalWin: Math.random() > 0.5 ? bet * (Math.random() * 20) : 0,
41
+ * data: { matrix: [[1,2,3],[4,5,6],[7,8,9]] },
42
+ * }),
43
+ * });
44
+ * devBridge.start();
45
+ * ```
46
+ */
47
+ class DevBridge {
48
+ _config;
49
+ _balance;
50
+ _roundCounter = 0;
51
+ _bridge = null;
52
+ _useLuaServer;
53
+ constructor(config = {}) {
54
+ this._config = { ...DEFAULT_CONFIG, ...config };
55
+ this._balance = this._config.balance;
56
+ this._useLuaServer = !!(this._config.luaScript && this._config.gameDefinition);
57
+ }
58
+ /** Current mock balance */
59
+ get balance() {
60
+ return this._balance;
61
+ }
62
+ /** Start listening for SDK messages */
63
+ start() {
64
+ if (this._bridge)
65
+ return;
66
+ console.debug('[DevBridge] Starting with config:', this._config);
67
+ this._bridge = new gameSdk.Bridge({ devMode: true, debug: this._config.debug });
68
+ this._bridge.on('GAME_READY', (_payload, id) => {
69
+ this.handleGameReady(id);
70
+ });
71
+ this._bridge.on('PLAY_REQUEST', (payload, id) => {
72
+ this.handlePlayRequest(payload, id);
73
+ });
74
+ this._bridge.on('PLAY_RESULT_ACK', (payload) => {
75
+ this.handlePlayAck(payload);
76
+ });
77
+ this._bridge.on('GET_BALANCE', (_payload, id) => {
78
+ this.handleGetBalance(id);
79
+ });
80
+ this._bridge.on('GET_STATE', (_payload, id) => {
81
+ this.handleGetState(id);
82
+ });
83
+ this._bridge.on('OPEN_DEPOSIT', () => {
84
+ this.handleOpenDeposit();
85
+ });
86
+ if (this._config.debug) {
87
+ const mode = this._useLuaServer ? 'Lua (server-side)' : 'onPlay callback';
88
+ console.log(`[DevBridge] Started — mode: ${mode}`);
89
+ }
90
+ }
91
+ /** Stop listening */
92
+ stop() {
93
+ if (this._bridge) {
94
+ this._bridge.destroy();
95
+ this._bridge = null;
96
+ }
97
+ if (this._config.debug) {
98
+ console.log('[DevBridge] Stopped');
99
+ }
100
+ }
101
+ /** Set mock balance */
102
+ setBalance(balance) {
103
+ this._balance = balance;
104
+ this._bridge?.send('BALANCE_UPDATE', { balance: this._balance });
105
+ }
106
+ /** Destroy the dev bridge */
107
+ destroy() {
108
+ this.stop();
109
+ }
110
+ // ─── Message Handling ──────────────────────────────────
111
+ handleGameReady(id) {
112
+ const initData = {
113
+ balance: this._balance,
114
+ currency: this._config.currency,
115
+ config: this._config.gameConfig,
116
+ session: this._config.session,
117
+ assetsUrl: this._config.assetsUrl,
118
+ };
119
+ this.delayedSend('INIT', initData, id);
120
+ }
121
+ handlePlayRequest(payload, id) {
122
+ const { action, bet, roundId, params } = payload;
123
+ this._roundCounter++;
124
+ if (this._useLuaServer) {
125
+ // Debit bet (server deducts before Lua execution)
126
+ // For session actions (free spins), debit is 0 — LuaEngine handles bet from session
127
+ this._balance -= bet;
128
+ this.executeLuaOnServer({ action, bet, roundId, params })
129
+ .then((result) => {
130
+ this._bridge?.send('PLAY_RESULT', result, id);
131
+ })
132
+ .catch((err) => {
133
+ console.error('[DevBridge] Lua server error:', err);
134
+ this._balance += bet;
135
+ this._bridge?.send('PLAY_RESULT', this.buildFallbackResult(action, bet, roundId), id);
136
+ });
137
+ }
138
+ else {
139
+ // Fallback to onPlay callback
140
+ const customResult = this._config.onPlay({ action, bet, roundId, params });
141
+ const totalWin = customResult.totalWin ?? (Math.random() > 0.6 ? bet * (1 + Math.random() * 10) : 0);
142
+ this._balance += totalWin;
143
+ const result = {
144
+ roundId: roundId ?? `dev-round-${this._roundCounter}`,
145
+ action,
146
+ balanceAfter: this._balance,
147
+ totalWin: Math.round(totalWin * 100) / 100,
148
+ data: customResult.data ?? {},
149
+ nextActions: customResult.nextActions ?? ['spin'],
150
+ session: customResult.session ?? null,
151
+ creditPending: false,
152
+ bonusFreeSpin: customResult.bonusFreeSpin ?? null,
153
+ currency: this._config.currency,
154
+ gameId: this._config.gameConfig?.id ?? 'dev-game',
155
+ };
156
+ this.delayedSend('PLAY_RESULT', result, id);
157
+ }
158
+ }
159
+ async executeLuaOnServer(params) {
160
+ const response = await fetch('/__lua-play', {
161
+ method: 'POST',
162
+ headers: { 'Content-Type': 'application/json' },
163
+ body: JSON.stringify(params),
164
+ });
165
+ if (!response.ok) {
166
+ const err = await response.json().catch(() => ({ error: 'Unknown error' }));
167
+ throw new Error(err.error ?? `HTTP ${response.status}`);
168
+ }
169
+ const luaResult = await response.json();
170
+ // Server credit logic:
171
+ // shouldCredit = (no session) OR (session.completed)
172
+ // creditAmount = result.totalWin
173
+ const shouldCredit = !luaResult.session || luaResult.session.completed;
174
+ if (shouldCredit && luaResult.totalWin > 0) {
175
+ this._balance += luaResult.totalWin;
176
+ }
177
+ return {
178
+ roundId: params.roundId ?? `dev-round-${this._roundCounter}`,
179
+ action: params.action,
180
+ balanceAfter: this._balance,
181
+ totalWin: Math.round(luaResult.totalWin * 100) / 100,
182
+ data: luaResult.data,
183
+ nextActions: luaResult.nextActions,
184
+ session: luaResult.session,
185
+ creditPending: !shouldCredit,
186
+ bonusFreeSpin: null,
187
+ currency: this._config.currency,
188
+ gameId: this._config.gameConfig?.id ?? 'dev-game',
189
+ };
190
+ }
191
+ buildFallbackResult(action, bet, roundId) {
192
+ return {
193
+ roundId: roundId ?? `dev-round-${this._roundCounter}`,
194
+ action,
195
+ balanceAfter: this._balance,
196
+ totalWin: 0,
197
+ data: { error: 'Lua execution failed' },
198
+ nextActions: ['spin'],
199
+ session: null,
200
+ creditPending: false,
201
+ bonusFreeSpin: null,
202
+ currency: this._config.currency,
203
+ gameId: this._config.gameConfig?.id ?? 'dev-game',
204
+ };
205
+ }
206
+ handlePlayAck(_payload) {
207
+ if (this._config.debug) {
208
+ console.log('[DevBridge] Play acknowledged');
209
+ }
210
+ }
211
+ handleGetBalance(id) {
212
+ this.delayedSend('BALANCE_UPDATE', { balance: this._balance }, id);
213
+ }
214
+ handleGetState(id) {
215
+ this.delayedSend('STATE_RESPONSE', { session: this._config.session ?? null }, id);
216
+ }
217
+ handleOpenDeposit() {
218
+ if (this._config.debug) {
219
+ console.log('[DevBridge] Open deposit requested (mock: adding 1000)');
220
+ }
221
+ this._balance += 1000;
222
+ this._bridge?.send('BALANCE_UPDATE', { balance: this._balance });
223
+ }
224
+ // ─── Communication ─────────────────────────────────────
225
+ delayedSend(type, payload, id) {
226
+ const delay = this._config.networkDelay;
227
+ if (delay > 0) {
228
+ setTimeout(() => this._bridge?.send(type, payload, id), delay);
229
+ }
230
+ else {
231
+ this._bridge?.send(type, payload, id);
232
+ }
233
+ }
234
+ }
235
+
236
+ exports.DevBridge = DevBridge;
237
+ //# sourceMappingURL=dev-bridge.cjs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dev-bridge.cjs.js","sources":["../src/dev-bridge/DevBridge.ts"],"sourcesContent":[null],"names":["Bridge"],"mappings":"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"}
@@ -0,0 +1,141 @@
1
+ import { GameConfigData, SessionData, PlayParams, PlayResultData } from '@energy8platform/game-sdk';
2
+
3
+ interface GameDefinition {
4
+ id: string;
5
+ type: 'SLOT' | 'TABLE';
6
+ actions: Record<string, ActionDefinition>;
7
+ bet_levels?: number[] | BetLevelsConfig;
8
+ max_win?: MaxWinConfig;
9
+ buy_bonus?: BuyBonusConfig;
10
+ ante_bet?: AnteBetConfig;
11
+ persistent_state?: PersistentStateConfig;
12
+ }
13
+ interface BetLevelsConfig {
14
+ levels?: number[];
15
+ min?: number;
16
+ max?: number;
17
+ }
18
+ interface MaxWinConfig {
19
+ multiplier?: number;
20
+ fixed?: number;
21
+ }
22
+ interface BuyBonusConfig {
23
+ modes: Record<string, BuyBonusMode>;
24
+ }
25
+ interface BuyBonusMode {
26
+ cost_multiplier: number;
27
+ /** Distribution of forced scatter counts. Optional — if omitted, Lua script handles bonus setup itself. */
28
+ scatter_distribution?: Record<string, number>;
29
+ /** Optional description */
30
+ description?: string;
31
+ }
32
+ interface AnteBetConfig {
33
+ cost_multiplier: number;
34
+ }
35
+ interface PersistentStateConfig {
36
+ vars: string[];
37
+ exposed_vars: string[];
38
+ }
39
+ interface ActionDefinition {
40
+ stage: string;
41
+ debit: 'bet' | 'buy_bonus_cost' | 'ante_bet_cost' | 'none';
42
+ credit?: 'win' | 'none' | 'defer';
43
+ requires_session?: boolean;
44
+ buy_bonus_mode?: string;
45
+ transitions: TransitionRule[];
46
+ input_schema?: Record<string, unknown>;
47
+ }
48
+ interface TransitionRule {
49
+ condition: string;
50
+ creates_session?: boolean;
51
+ complete_session?: boolean;
52
+ credit_override?: 'defer';
53
+ next_actions: string[];
54
+ session_config?: SessionConfig;
55
+ add_spins_var?: string;
56
+ }
57
+ interface SessionConfig {
58
+ total_spins_var: string;
59
+ persistent_vars?: string[];
60
+ }
61
+
62
+ interface DevBridgeConfig {
63
+ /** Mock initial balance */
64
+ balance?: number;
65
+ /** Mock currency */
66
+ currency?: string;
67
+ /** Game config */
68
+ gameConfig?: Partial<GameConfigData>;
69
+ /** Base URL for assets (default: '/assets/') */
70
+ assetsUrl?: string;
71
+ /** Active session to resume (null = no active session) */
72
+ session?: SessionData | null;
73
+ /** Custom play result handler — return mock result data */
74
+ onPlay?: (params: PlayParams) => Partial<PlayResultData>;
75
+ /** Simulated network delay in ms */
76
+ networkDelay?: number;
77
+ /** Enable debug logging */
78
+ debug?: boolean;
79
+ /** Lua script source code. When set, play requests are routed to the Vite dev server's LuaEngine. */
80
+ luaScript?: string;
81
+ /** Game definition for Lua engine (actions, transitions, etc.) */
82
+ gameDefinition?: GameDefinition;
83
+ /** RNG seed for deterministic Lua execution */
84
+ luaSeed?: number;
85
+ }
86
+ /**
87
+ * Mock host bridge for local development.
88
+ *
89
+ * Uses the SDK's `Bridge` class in `devMode` to communicate with
90
+ * `CasinoGameSDK` via a shared in-memory `MemoryChannel`, removing
91
+ * the need for postMessage and iframes.
92
+ *
93
+ * When `luaScript` is set, play requests are sent to the Vite dev server
94
+ * which runs LuaEngine in Node.js — no fengari in the browser.
95
+ *
96
+ * @example
97
+ * ```ts
98
+ * import { DevBridge } from '@energy8platform/platform-core/dev-bridge';
99
+ *
100
+ * const devBridge = new DevBridge({
101
+ * balance: 5000,
102
+ * currency: 'EUR',
103
+ * gameConfig: { id: 'my-slot', type: 'slot', betLevels: [0.2, 0.5, 1, 2] },
104
+ * onPlay: ({ action, bet }) => ({
105
+ * totalWin: Math.random() > 0.5 ? bet * (Math.random() * 20) : 0,
106
+ * data: { matrix: [[1,2,3],[4,5,6],[7,8,9]] },
107
+ * }),
108
+ * });
109
+ * devBridge.start();
110
+ * ```
111
+ */
112
+ declare class DevBridge {
113
+ private _config;
114
+ private _balance;
115
+ private _roundCounter;
116
+ private _bridge;
117
+ private _useLuaServer;
118
+ constructor(config?: DevBridgeConfig);
119
+ /** Current mock balance */
120
+ get balance(): number;
121
+ /** Start listening for SDK messages */
122
+ start(): void;
123
+ /** Stop listening */
124
+ stop(): void;
125
+ /** Set mock balance */
126
+ setBalance(balance: number): void;
127
+ /** Destroy the dev bridge */
128
+ destroy(): void;
129
+ private handleGameReady;
130
+ private handlePlayRequest;
131
+ private executeLuaOnServer;
132
+ private buildFallbackResult;
133
+ private handlePlayAck;
134
+ private handleGetBalance;
135
+ private handleGetState;
136
+ private handleOpenDeposit;
137
+ private delayedSend;
138
+ }
139
+
140
+ export { DevBridge };
141
+ export type { DevBridgeConfig };
@@ -0,0 +1,235 @@
1
+ import { Bridge } from '@energy8platform/game-sdk';
2
+
3
+ const DEFAULT_CONFIG = {
4
+ balance: 10000,
5
+ currency: 'USD',
6
+ gameConfig: {
7
+ id: 'dev-game',
8
+ type: 'slot',
9
+ version: '1.0.0',
10
+ viewport: { width: 1920, height: 1080 },
11
+ betLevels: [0.1, 0.2, 0.5, 1, 2, 5, 10, 20, 50],
12
+ },
13
+ assetsUrl: '/assets/',
14
+ session: null,
15
+ onPlay: () => ({}),
16
+ networkDelay: 200,
17
+ debug: true,
18
+ };
19
+ /**
20
+ * Mock host bridge for local development.
21
+ *
22
+ * Uses the SDK's `Bridge` class in `devMode` to communicate with
23
+ * `CasinoGameSDK` via a shared in-memory `MemoryChannel`, removing
24
+ * the need for postMessage and iframes.
25
+ *
26
+ * When `luaScript` is set, play requests are sent to the Vite dev server
27
+ * which runs LuaEngine in Node.js — no fengari in the browser.
28
+ *
29
+ * @example
30
+ * ```ts
31
+ * import { DevBridge } from '@energy8platform/platform-core/dev-bridge';
32
+ *
33
+ * const devBridge = new DevBridge({
34
+ * balance: 5000,
35
+ * currency: 'EUR',
36
+ * gameConfig: { id: 'my-slot', type: 'slot', betLevels: [0.2, 0.5, 1, 2] },
37
+ * onPlay: ({ action, bet }) => ({
38
+ * totalWin: Math.random() > 0.5 ? bet * (Math.random() * 20) : 0,
39
+ * data: { matrix: [[1,2,3],[4,5,6],[7,8,9]] },
40
+ * }),
41
+ * });
42
+ * devBridge.start();
43
+ * ```
44
+ */
45
+ class DevBridge {
46
+ _config;
47
+ _balance;
48
+ _roundCounter = 0;
49
+ _bridge = null;
50
+ _useLuaServer;
51
+ constructor(config = {}) {
52
+ this._config = { ...DEFAULT_CONFIG, ...config };
53
+ this._balance = this._config.balance;
54
+ this._useLuaServer = !!(this._config.luaScript && this._config.gameDefinition);
55
+ }
56
+ /** Current mock balance */
57
+ get balance() {
58
+ return this._balance;
59
+ }
60
+ /** Start listening for SDK messages */
61
+ start() {
62
+ if (this._bridge)
63
+ return;
64
+ console.debug('[DevBridge] Starting with config:', this._config);
65
+ this._bridge = new Bridge({ devMode: true, debug: this._config.debug });
66
+ this._bridge.on('GAME_READY', (_payload, id) => {
67
+ this.handleGameReady(id);
68
+ });
69
+ this._bridge.on('PLAY_REQUEST', (payload, id) => {
70
+ this.handlePlayRequest(payload, id);
71
+ });
72
+ this._bridge.on('PLAY_RESULT_ACK', (payload) => {
73
+ this.handlePlayAck(payload);
74
+ });
75
+ this._bridge.on('GET_BALANCE', (_payload, id) => {
76
+ this.handleGetBalance(id);
77
+ });
78
+ this._bridge.on('GET_STATE', (_payload, id) => {
79
+ this.handleGetState(id);
80
+ });
81
+ this._bridge.on('OPEN_DEPOSIT', () => {
82
+ this.handleOpenDeposit();
83
+ });
84
+ if (this._config.debug) {
85
+ const mode = this._useLuaServer ? 'Lua (server-side)' : 'onPlay callback';
86
+ console.log(`[DevBridge] Started — mode: ${mode}`);
87
+ }
88
+ }
89
+ /** Stop listening */
90
+ stop() {
91
+ if (this._bridge) {
92
+ this._bridge.destroy();
93
+ this._bridge = null;
94
+ }
95
+ if (this._config.debug) {
96
+ console.log('[DevBridge] Stopped');
97
+ }
98
+ }
99
+ /** Set mock balance */
100
+ setBalance(balance) {
101
+ this._balance = balance;
102
+ this._bridge?.send('BALANCE_UPDATE', { balance: this._balance });
103
+ }
104
+ /** Destroy the dev bridge */
105
+ destroy() {
106
+ this.stop();
107
+ }
108
+ // ─── Message Handling ──────────────────────────────────
109
+ handleGameReady(id) {
110
+ const initData = {
111
+ balance: this._balance,
112
+ currency: this._config.currency,
113
+ config: this._config.gameConfig,
114
+ session: this._config.session,
115
+ assetsUrl: this._config.assetsUrl,
116
+ };
117
+ this.delayedSend('INIT', initData, id);
118
+ }
119
+ handlePlayRequest(payload, id) {
120
+ const { action, bet, roundId, params } = payload;
121
+ this._roundCounter++;
122
+ if (this._useLuaServer) {
123
+ // Debit bet (server deducts before Lua execution)
124
+ // For session actions (free spins), debit is 0 — LuaEngine handles bet from session
125
+ this._balance -= bet;
126
+ this.executeLuaOnServer({ action, bet, roundId, params })
127
+ .then((result) => {
128
+ this._bridge?.send('PLAY_RESULT', result, id);
129
+ })
130
+ .catch((err) => {
131
+ console.error('[DevBridge] Lua server error:', err);
132
+ this._balance += bet;
133
+ this._bridge?.send('PLAY_RESULT', this.buildFallbackResult(action, bet, roundId), id);
134
+ });
135
+ }
136
+ else {
137
+ // Fallback to onPlay callback
138
+ const customResult = this._config.onPlay({ action, bet, roundId, params });
139
+ const totalWin = customResult.totalWin ?? (Math.random() > 0.6 ? bet * (1 + Math.random() * 10) : 0);
140
+ this._balance += totalWin;
141
+ const result = {
142
+ roundId: roundId ?? `dev-round-${this._roundCounter}`,
143
+ action,
144
+ balanceAfter: this._balance,
145
+ totalWin: Math.round(totalWin * 100) / 100,
146
+ data: customResult.data ?? {},
147
+ nextActions: customResult.nextActions ?? ['spin'],
148
+ session: customResult.session ?? null,
149
+ creditPending: false,
150
+ bonusFreeSpin: customResult.bonusFreeSpin ?? null,
151
+ currency: this._config.currency,
152
+ gameId: this._config.gameConfig?.id ?? 'dev-game',
153
+ };
154
+ this.delayedSend('PLAY_RESULT', result, id);
155
+ }
156
+ }
157
+ async executeLuaOnServer(params) {
158
+ const response = await fetch('/__lua-play', {
159
+ method: 'POST',
160
+ headers: { 'Content-Type': 'application/json' },
161
+ body: JSON.stringify(params),
162
+ });
163
+ if (!response.ok) {
164
+ const err = await response.json().catch(() => ({ error: 'Unknown error' }));
165
+ throw new Error(err.error ?? `HTTP ${response.status}`);
166
+ }
167
+ const luaResult = await response.json();
168
+ // Server credit logic:
169
+ // shouldCredit = (no session) OR (session.completed)
170
+ // creditAmount = result.totalWin
171
+ const shouldCredit = !luaResult.session || luaResult.session.completed;
172
+ if (shouldCredit && luaResult.totalWin > 0) {
173
+ this._balance += luaResult.totalWin;
174
+ }
175
+ return {
176
+ roundId: params.roundId ?? `dev-round-${this._roundCounter}`,
177
+ action: params.action,
178
+ balanceAfter: this._balance,
179
+ totalWin: Math.round(luaResult.totalWin * 100) / 100,
180
+ data: luaResult.data,
181
+ nextActions: luaResult.nextActions,
182
+ session: luaResult.session,
183
+ creditPending: !shouldCredit,
184
+ bonusFreeSpin: null,
185
+ currency: this._config.currency,
186
+ gameId: this._config.gameConfig?.id ?? 'dev-game',
187
+ };
188
+ }
189
+ buildFallbackResult(action, bet, roundId) {
190
+ return {
191
+ roundId: roundId ?? `dev-round-${this._roundCounter}`,
192
+ action,
193
+ balanceAfter: this._balance,
194
+ totalWin: 0,
195
+ data: { error: 'Lua execution failed' },
196
+ nextActions: ['spin'],
197
+ session: null,
198
+ creditPending: false,
199
+ bonusFreeSpin: null,
200
+ currency: this._config.currency,
201
+ gameId: this._config.gameConfig?.id ?? 'dev-game',
202
+ };
203
+ }
204
+ handlePlayAck(_payload) {
205
+ if (this._config.debug) {
206
+ console.log('[DevBridge] Play acknowledged');
207
+ }
208
+ }
209
+ handleGetBalance(id) {
210
+ this.delayedSend('BALANCE_UPDATE', { balance: this._balance }, id);
211
+ }
212
+ handleGetState(id) {
213
+ this.delayedSend('STATE_RESPONSE', { session: this._config.session ?? null }, id);
214
+ }
215
+ handleOpenDeposit() {
216
+ if (this._config.debug) {
217
+ console.log('[DevBridge] Open deposit requested (mock: adding 1000)');
218
+ }
219
+ this._balance += 1000;
220
+ this._bridge?.send('BALANCE_UPDATE', { balance: this._balance });
221
+ }
222
+ // ─── Communication ─────────────────────────────────────
223
+ delayedSend(type, payload, id) {
224
+ const delay = this._config.networkDelay;
225
+ if (delay > 0) {
226
+ setTimeout(() => this._bridge?.send(type, payload, id), delay);
227
+ }
228
+ else {
229
+ this._bridge?.send(type, payload, id);
230
+ }
231
+ }
232
+ }
233
+
234
+ export { DevBridge };
235
+ //# sourceMappingURL=dev-bridge.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dev-bridge.esm.js","sources":["../src/dev-bridge/DevBridge.ts"],"sourcesContent":[null],"names":[],"mappings":"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"}