@oasiz/sdk 1.0.1 → 1.1.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.
- package/README.md +196 -34
- package/dist/index.cjs +106 -2
- package/dist/index.d.cts +29 -217
- package/dist/index.d.ts +29 -217
- package/dist/index.js +101 -2
- package/package.json +4 -8
- package/dist/index.global.js +0 -252
package/README.md
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
# @oasiz/sdk
|
|
2
2
|
|
|
3
|
-
Typed SDK for integrating games with the Oasiz platform. Handles score submission, haptic feedback, cross-session state persistence, multiplayer room codes, and app lifecycle events.
|
|
3
|
+
Typed SDK for integrating games with the Oasiz platform. Handles score submission, haptic feedback, cross-session state persistence, multiplayer room codes, navigation hooks, and app lifecycle events for local development.
|
|
4
4
|
|
|
5
5
|
## Install
|
|
6
6
|
|
|
7
7
|
```bash
|
|
8
|
-
npm install @oasiz/sdk
|
|
8
|
+
npm install @oasiz/sdk@^0.1.0
|
|
9
9
|
```
|
|
10
10
|
|
|
11
11
|
## Quick start
|
|
@@ -13,17 +13,27 @@ npm install @oasiz/sdk
|
|
|
13
13
|
```ts
|
|
14
14
|
import { oasiz } from "@oasiz/sdk";
|
|
15
15
|
|
|
16
|
-
// 1.
|
|
16
|
+
// 1. Emit score normalization config once on init
|
|
17
|
+
oasiz.emitScoreConfig({
|
|
18
|
+
anchors: [
|
|
19
|
+
{ raw: 30, normalized: 100 },
|
|
20
|
+
{ raw: 60, normalized: 300 },
|
|
21
|
+
{ raw: 120, normalized: 600 },
|
|
22
|
+
{ raw: 300, normalized: 950 },
|
|
23
|
+
],
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
// 2. Load persisted state at the start of each session
|
|
17
27
|
const state = oasiz.loadGameState();
|
|
18
28
|
let level = typeof state.level === "number" ? state.level : 1;
|
|
19
29
|
|
|
20
|
-
//
|
|
30
|
+
// 3. Save state at checkpoints
|
|
21
31
|
oasiz.saveGameState({ level, coins: 42 });
|
|
22
32
|
|
|
23
|
-
//
|
|
33
|
+
// 4. Trigger haptics on key events
|
|
24
34
|
oasiz.triggerHaptic("medium");
|
|
25
35
|
|
|
26
|
-
//
|
|
36
|
+
// 5. Submit score when the game ends
|
|
27
37
|
oasiz.submitScore(score);
|
|
28
38
|
```
|
|
29
39
|
|
|
@@ -33,14 +43,44 @@ oasiz.submitScore(score);
|
|
|
33
43
|
|
|
34
44
|
### `oasiz.submitScore(score: number)`
|
|
35
45
|
|
|
36
|
-
Submit the player's score. The platform handles leaderboard persistence — do not track high scores locally.
|
|
46
|
+
Submit the player's final score at game over. Call this exactly once per session, when the game ends. The platform handles leaderboard persistence — do not track high scores locally.
|
|
37
47
|
|
|
38
48
|
```ts
|
|
39
|
-
|
|
49
|
+
private onGameOver(): void {
|
|
50
|
+
oasiz.submitScore(Math.floor(this.score));
|
|
51
|
+
}
|
|
40
52
|
```
|
|
41
53
|
|
|
42
54
|
- `score` must be a non-negative integer. Floats are floored automatically.
|
|
43
|
-
-
|
|
55
|
+
- Do not call on intermediate scores or level completions, only on final game over.
|
|
56
|
+
|
|
57
|
+
---
|
|
58
|
+
|
|
59
|
+
### `oasiz.emitScoreConfig(config)`
|
|
60
|
+
|
|
61
|
+
Maps raw score values to the platform's normalized 0–1000 scale. Call once during initialization, not every frame.
|
|
62
|
+
|
|
63
|
+
```ts
|
|
64
|
+
oasiz.emitScoreConfig({
|
|
65
|
+
anchors: [
|
|
66
|
+
{ raw: 10, normalized: 100 }, // beginner
|
|
67
|
+
{ raw: 30, normalized: 300 }, // good
|
|
68
|
+
{ raw: 75, normalized: 600 }, // great
|
|
69
|
+
{ raw: 200, normalized: 950 }, // godlike
|
|
70
|
+
],
|
|
71
|
+
});
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
**Anchor rules:**
|
|
75
|
+
- Exactly 4 anchors required.
|
|
76
|
+
- `raw` values must be strictly increasing.
|
|
77
|
+
- `normalized` values must end at exactly `950`.
|
|
78
|
+
- Choose thresholds based on realistic player skill bands.
|
|
79
|
+
|
|
80
|
+
**Practical guidance by game type:**
|
|
81
|
+
- Survival / time games → use seconds survived as `raw`
|
|
82
|
+
- Score accumulation games → use points as `raw`
|
|
83
|
+
- Puzzle games → use level reached or stars earned as `raw`
|
|
44
84
|
|
|
45
85
|
---
|
|
46
86
|
|
|
@@ -59,14 +99,23 @@ type HapticType = "light" | "medium" | "heavy" | "success" | "error";
|
|
|
59
99
|
| `"light"` | UI button taps, menu navigation, D-pad press |
|
|
60
100
|
| `"medium"` | Collecting items, standard collisions, scoring |
|
|
61
101
|
| `"heavy"` | Explosions, major impacts, screen shake |
|
|
62
|
-
| `"success"` | Level complete, achievement unlocked |
|
|
102
|
+
| `"success"` | Level complete, new high score, achievement unlocked |
|
|
63
103
|
| `"error"` | Damage taken, game over, invalid action |
|
|
64
104
|
|
|
65
105
|
```ts
|
|
106
|
+
// UI buttons — always light
|
|
66
107
|
button.addEventListener("click", () => {
|
|
67
108
|
oasiz.triggerHaptic("light");
|
|
68
109
|
});
|
|
69
110
|
|
|
111
|
+
// Tiered hit feedback
|
|
112
|
+
private onBallHit(zone: "center" | "edge"): void {
|
|
113
|
+
if (this.settings.haptics) {
|
|
114
|
+
oasiz.triggerHaptic(zone === "center" ? "success" : "medium");
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// Game over
|
|
70
119
|
private onGameOver(): void {
|
|
71
120
|
oasiz.submitScore(this.score);
|
|
72
121
|
if (this.settings.haptics) {
|
|
@@ -75,54 +124,75 @@ private onGameOver(): void {
|
|
|
75
124
|
}
|
|
76
125
|
```
|
|
77
126
|
|
|
127
|
+
Haptics are throttled internally (50ms cooldown) to prevent spam.
|
|
128
|
+
|
|
78
129
|
---
|
|
79
130
|
|
|
80
131
|
## Game state persistence
|
|
81
132
|
|
|
82
|
-
Persist cross-session data such as unlocked levels, inventory, or lifetime stats.
|
|
133
|
+
Persist cross-session data such as unlocked levels, inventory, or lifetime stats. State is stored per-user per-game in the Oasiz backend — available across devices and app reinstalls.
|
|
83
134
|
|
|
84
135
|
### `oasiz.loadGameState(): Record<string, unknown>`
|
|
85
136
|
|
|
86
|
-
Returns the player's saved state synchronously. Returns `{}` if no state has been saved yet.
|
|
137
|
+
Returns the player's saved state synchronously. Returns `{}` if no state has been saved yet. Call once at the start of the game.
|
|
87
138
|
|
|
88
139
|
```ts
|
|
89
|
-
|
|
90
|
-
|
|
140
|
+
private initFromSavedState(): void {
|
|
141
|
+
const state = oasiz.loadGameState();
|
|
142
|
+
this.level = typeof state.level === "number" ? state.level : 1;
|
|
143
|
+
this.lifetimeHits = typeof state.lifetimeHits === "number" ? state.lifetimeHits : 0;
|
|
144
|
+
this.unlockedSkins = Array.isArray(state.unlockedSkins) ? state.unlockedSkins : [];
|
|
145
|
+
}
|
|
91
146
|
```
|
|
92
147
|
|
|
148
|
+
Always validate the shape of loaded data — it may be `{}` on first play.
|
|
149
|
+
|
|
93
150
|
### `oasiz.saveGameState(state: Record<string, unknown>)`
|
|
94
151
|
|
|
95
|
-
Queues a debounced save.
|
|
152
|
+
Queues a debounced save. Saves are batched automatically — call freely at checkpoints without worrying about request spam.
|
|
96
153
|
|
|
97
154
|
```ts
|
|
98
|
-
|
|
155
|
+
// Save after each level completion
|
|
156
|
+
private onLevelComplete(): void {
|
|
157
|
+
this.level += 1;
|
|
158
|
+
oasiz.saveGameState({
|
|
159
|
+
level: this.level,
|
|
160
|
+
lifetimeHits: this.lifetimeHits,
|
|
161
|
+
unlockedSkins: this.unlockedSkins,
|
|
162
|
+
});
|
|
163
|
+
}
|
|
99
164
|
```
|
|
100
165
|
|
|
166
|
+
**Rules:**
|
|
101
167
|
- State must be a plain JSON object (not an array or primitive).
|
|
102
|
-
-
|
|
103
|
-
- Do not store scores here —
|
|
168
|
+
- Do not use `localStorage` for cross-session progress — use `saveGameState` so data syncs across platforms.
|
|
169
|
+
- Do not store scores here — scores are submitted via `submitScore`.
|
|
104
170
|
|
|
105
171
|
### `oasiz.flushGameState()`
|
|
106
172
|
|
|
107
|
-
Forces an immediate write, bypassing the debounce. Use at game over or before page
|
|
173
|
+
Forces an immediate write, bypassing the debounce. Use at important checkpoints like game over or before the page unloads.
|
|
108
174
|
|
|
109
175
|
```ts
|
|
110
|
-
|
|
111
|
-
oasiz.
|
|
112
|
-
oasiz.
|
|
176
|
+
private onGameOver(): void {
|
|
177
|
+
oasiz.saveGameState({ level: this.level, lifetimeHits: this.lifetimeHits });
|
|
178
|
+
oasiz.flushGameState(); // ensure it lands before the page closes
|
|
179
|
+
oasiz.submitScore(this.score);
|
|
180
|
+
}
|
|
113
181
|
```
|
|
114
182
|
|
|
115
183
|
---
|
|
116
184
|
|
|
117
185
|
## Lifecycle
|
|
118
186
|
|
|
187
|
+
The platform dispatches lifecycle events when the app goes to the background or returns to the foreground. Subscribe to pause game loops and audio accordingly.
|
|
188
|
+
|
|
119
189
|
### `oasiz.onPause(callback: () => void): Unsubscribe`
|
|
120
190
|
### `oasiz.onResume(callback: () => void): Unsubscribe`
|
|
121
191
|
|
|
122
192
|
Both return an unsubscribe function.
|
|
123
193
|
|
|
124
194
|
```ts
|
|
125
|
-
const offPause
|
|
195
|
+
const offPause = oasiz.onPause(() => {
|
|
126
196
|
this.gameLoop.stop();
|
|
127
197
|
this.bgMusic.pause();
|
|
128
198
|
});
|
|
@@ -132,39 +202,126 @@ const offResume = oasiz.onResume(() => {
|
|
|
132
202
|
this.bgMusic.play();
|
|
133
203
|
});
|
|
134
204
|
|
|
205
|
+
// Clean up when the game is destroyed
|
|
135
206
|
offPause();
|
|
136
207
|
offResume();
|
|
137
208
|
```
|
|
138
209
|
|
|
139
210
|
---
|
|
140
211
|
|
|
212
|
+
## Navigation
|
|
213
|
+
|
|
214
|
+
Use navigation hooks when your game needs to control back behavior (Android back / web Escape) or participate in host-driven close events.
|
|
215
|
+
|
|
216
|
+
### `oasiz.onBackButton(callback: () => void): Unsubscribe`
|
|
217
|
+
|
|
218
|
+
Registers a callback for platform back actions. While at least one back listener is subscribed, back actions are routed to your game instead of immediately closing it.
|
|
219
|
+
|
|
220
|
+
Use this for pause menus, in-game overlays, or custom back-stack behavior.
|
|
221
|
+
|
|
222
|
+
```ts
|
|
223
|
+
const offBack = oasiz.onBackButton(() => {
|
|
224
|
+
if (this.isPauseMenuOpen) {
|
|
225
|
+
this.closePauseMenu();
|
|
226
|
+
return;
|
|
227
|
+
}
|
|
228
|
+
this.openPauseMenu();
|
|
229
|
+
});
|
|
230
|
+
|
|
231
|
+
// Restore default host back behavior when no longer needed
|
|
232
|
+
offBack();
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
### `oasiz.leaveGame(): void`
|
|
236
|
+
|
|
237
|
+
Programmatically request the host to close the current game (for example, from a Quit button inside your game UI).
|
|
238
|
+
|
|
239
|
+
```ts
|
|
240
|
+
quitButton.addEventListener("click", () => {
|
|
241
|
+
oasiz.leaveGame();
|
|
242
|
+
});
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
### `oasiz.onLeaveGame(callback: () => void): Unsubscribe`
|
|
246
|
+
|
|
247
|
+
Registers a callback fired when the host initiates closing the game (for example, close button, gesture, or host navigation). Use this for lightweight cleanup.
|
|
248
|
+
|
|
249
|
+
```ts
|
|
250
|
+
const offLeave = oasiz.onLeaveGame(() => {
|
|
251
|
+
oasiz.flushGameState();
|
|
252
|
+
this.bgMusic.pause();
|
|
253
|
+
});
|
|
254
|
+
|
|
255
|
+
// Clean up listener when destroyed
|
|
256
|
+
offLeave();
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
---
|
|
260
|
+
|
|
141
261
|
## Multiplayer
|
|
142
262
|
|
|
143
|
-
### `oasiz.shareRoomCode(code: string | null)`
|
|
263
|
+
### `oasiz.shareRoomCode(code: string | null, options?: { inviteOverride?: boolean })`
|
|
264
|
+
|
|
265
|
+
Notify the platform of the active multiplayer room so friends can join via the invite system. Pass `null` when leaving a room.
|
|
144
266
|
|
|
145
|
-
|
|
267
|
+
Set `inviteOverride: true` when your game wants to hide the platform invite pill and render its own invite button/UI. The platform still tracks the room code, but your game owns the invite entry point.
|
|
146
268
|
|
|
147
269
|
```ts
|
|
270
|
+
import { insertCoin, getRoomCode } from "playroomkit";
|
|
271
|
+
import { oasiz } from "@oasiz/sdk";
|
|
272
|
+
|
|
273
|
+
await insertCoin({ skipLobby: true });
|
|
148
274
|
oasiz.shareRoomCode(getRoomCode());
|
|
275
|
+
|
|
276
|
+
// On disconnect
|
|
149
277
|
oasiz.shareRoomCode(null);
|
|
150
278
|
```
|
|
151
279
|
|
|
152
|
-
|
|
280
|
+
```ts
|
|
281
|
+
// Game-owned invite UI: hide the platform pill, keep room tracking
|
|
282
|
+
oasiz.shareRoomCode(getRoomCode(), { inviteOverride: true });
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
If you still want to use the platform invite sheet from your own in-game button, combine it with `openInviteModal()`:
|
|
286
|
+
|
|
287
|
+
```ts
|
|
288
|
+
import { openInviteModal, shareRoomCode } from "@oasiz/sdk";
|
|
289
|
+
|
|
290
|
+
shareRoomCode("ABCD", { inviteOverride: true });
|
|
291
|
+
|
|
292
|
+
inviteButton.addEventListener("click", () => {
|
|
293
|
+
openInviteModal();
|
|
294
|
+
});
|
|
295
|
+
```
|
|
153
296
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
297
|
+
### Read-only injected values
|
|
298
|
+
|
|
299
|
+
These are populated by the platform before the game loads. Always check for `undefined` before using.
|
|
300
|
+
|
|
301
|
+
```ts
|
|
302
|
+
// The platform's internal game ID
|
|
303
|
+
const gameId = oasiz.gameId;
|
|
304
|
+
|
|
305
|
+
// Pre-filled room code for auto-joining a friend's session
|
|
306
|
+
if (oasiz.roomCode) {
|
|
307
|
+
await connectToRoom(oasiz.roomCode);
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
// Player identity for multiplayer games
|
|
311
|
+
const name = oasiz.playerName;
|
|
312
|
+
const avatar = oasiz.playerAvatar;
|
|
313
|
+
```
|
|
160
314
|
|
|
161
315
|
---
|
|
162
316
|
|
|
163
317
|
## Named exports
|
|
164
318
|
|
|
319
|
+
All methods are also available as named exports if you prefer not to use the `oasiz` namespace object:
|
|
320
|
+
|
|
165
321
|
```ts
|
|
166
322
|
import {
|
|
167
323
|
submitScore,
|
|
324
|
+
emitScoreConfig,
|
|
168
325
|
triggerHaptic,
|
|
169
326
|
loadGameState,
|
|
170
327
|
saveGameState,
|
|
@@ -172,6 +329,9 @@ import {
|
|
|
172
329
|
shareRoomCode,
|
|
173
330
|
onPause,
|
|
174
331
|
onResume,
|
|
332
|
+
onBackButton,
|
|
333
|
+
onLeaveGame,
|
|
334
|
+
leaveGame,
|
|
175
335
|
getGameId,
|
|
176
336
|
getRoomCode,
|
|
177
337
|
getPlayerName,
|
|
@@ -184,15 +344,17 @@ import {
|
|
|
184
344
|
## TypeScript types
|
|
185
345
|
|
|
186
346
|
```ts
|
|
187
|
-
import type { HapticType, GameState } from "@oasiz/sdk";
|
|
347
|
+
import type { HapticType, ScoreConfig, ScoreAnchor, GameState } from "@oasiz/sdk";
|
|
188
348
|
```
|
|
189
349
|
|
|
190
350
|
---
|
|
191
351
|
|
|
192
352
|
## Local development
|
|
193
353
|
|
|
194
|
-
All methods safely no-op when the platform bridges are not injected. In development mode a console warning is logged:
|
|
354
|
+
All methods safely no-op when the platform bridges are not injected. In development mode a console warning is logged so you know the call was made:
|
|
195
355
|
|
|
196
356
|
```
|
|
197
357
|
[oasiz/sdk] submitScore bridge is unavailable. This is expected in local development.
|
|
198
358
|
```
|
|
359
|
+
|
|
360
|
+
No crashes, no special setup required for local dev.
|
package/dist/index.cjs
CHANGED
|
@@ -20,15 +20,20 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
20
20
|
// src/index.ts
|
|
21
21
|
var index_exports = {};
|
|
22
22
|
__export(index_exports, {
|
|
23
|
+
emitScoreConfig: () => emitScoreConfig,
|
|
23
24
|
flushGameState: () => flushGameState,
|
|
24
25
|
getGameId: () => getGameId,
|
|
25
26
|
getPlayerAvatar: () => getPlayerAvatar,
|
|
26
27
|
getPlayerName: () => getPlayerName,
|
|
27
28
|
getRoomCode: () => getRoomCode,
|
|
29
|
+
leaveGame: () => leaveGame,
|
|
28
30
|
loadGameState: () => loadGameState,
|
|
29
31
|
oasiz: () => oasiz,
|
|
32
|
+
onBackButton: () => onBackButton,
|
|
33
|
+
onLeaveGame: () => onLeaveGame,
|
|
30
34
|
onPause: () => onPause,
|
|
31
35
|
onResume: () => onResume,
|
|
36
|
+
openInviteModal: () => openInviteModal,
|
|
32
37
|
saveGameState: () => saveGameState,
|
|
33
38
|
shareRoomCode: () => shareRoomCode,
|
|
34
39
|
submitScore: () => submitScore,
|
|
@@ -71,10 +76,10 @@ function getBridgeWindow2() {
|
|
|
71
76
|
}
|
|
72
77
|
return window;
|
|
73
78
|
}
|
|
74
|
-
function shareRoomCode(roomCode) {
|
|
79
|
+
function shareRoomCode(roomCode, options) {
|
|
75
80
|
const bridge = getBridgeWindow2();
|
|
76
81
|
if (typeof bridge?.shareRoomCode === "function") {
|
|
77
|
-
bridge.shareRoomCode(roomCode);
|
|
82
|
+
bridge.shareRoomCode(roomCode, options);
|
|
78
83
|
return;
|
|
79
84
|
}
|
|
80
85
|
if (isDevelopment2()) {
|
|
@@ -83,6 +88,18 @@ function shareRoomCode(roomCode) {
|
|
|
83
88
|
);
|
|
84
89
|
}
|
|
85
90
|
}
|
|
91
|
+
function openInviteModal() {
|
|
92
|
+
const bridge = getBridgeWindow2();
|
|
93
|
+
if (typeof bridge?.openInviteModal === "function") {
|
|
94
|
+
bridge.openInviteModal();
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
if (isDevelopment2()) {
|
|
98
|
+
console.warn(
|
|
99
|
+
"[oasiz/sdk] openInviteModal bridge is unavailable. This is expected in local development."
|
|
100
|
+
);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
86
103
|
function getGameId() {
|
|
87
104
|
const bridge = getBridgeWindow2();
|
|
88
105
|
return bridge?.__GAME_ID__;
|
|
@@ -133,6 +150,14 @@ function submitScore(score) {
|
|
|
133
150
|
}
|
|
134
151
|
warnMissingBridge("submitScore");
|
|
135
152
|
}
|
|
153
|
+
function emitScoreConfig(config) {
|
|
154
|
+
const bridge = getBridgeWindow3();
|
|
155
|
+
if (typeof bridge?.emitScoreConfig === "function") {
|
|
156
|
+
bridge.emitScoreConfig(config);
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
warnMissingBridge("emitScoreConfig");
|
|
160
|
+
}
|
|
136
161
|
|
|
137
162
|
// src/state.ts
|
|
138
163
|
function isDevelopment4() {
|
|
@@ -225,16 +250,90 @@ function onResume(callback) {
|
|
|
225
250
|
return addLifecycleListener("oasiz:resume", callback);
|
|
226
251
|
}
|
|
227
252
|
|
|
253
|
+
// src/navigation.ts
|
|
254
|
+
var activeBackListeners = 0;
|
|
255
|
+
function isDevelopment6() {
|
|
256
|
+
const nodeEnv = globalThis.process?.env?.NODE_ENV;
|
|
257
|
+
return nodeEnv !== "production";
|
|
258
|
+
}
|
|
259
|
+
function getBridgeWindow5() {
|
|
260
|
+
if (typeof window === "undefined") {
|
|
261
|
+
return void 0;
|
|
262
|
+
}
|
|
263
|
+
return window;
|
|
264
|
+
}
|
|
265
|
+
function warnMissingBridge3(methodName) {
|
|
266
|
+
if (isDevelopment6()) {
|
|
267
|
+
console.warn(
|
|
268
|
+
"[oasiz/sdk] " + methodName + " bridge is unavailable. This is expected in local development."
|
|
269
|
+
);
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
function addNavigationListener(eventName, callback) {
|
|
273
|
+
if (typeof window === "undefined") {
|
|
274
|
+
if (isDevelopment6()) {
|
|
275
|
+
console.warn(
|
|
276
|
+
"[oasiz/sdk] " + eventName + " listener registered without a browser window. This is expected in local development."
|
|
277
|
+
);
|
|
278
|
+
}
|
|
279
|
+
return () => {
|
|
280
|
+
};
|
|
281
|
+
}
|
|
282
|
+
const handler = () => callback();
|
|
283
|
+
window.addEventListener(eventName, handler);
|
|
284
|
+
return () => window.removeEventListener(eventName, handler);
|
|
285
|
+
}
|
|
286
|
+
function onBackButton(callback) {
|
|
287
|
+
const off = addNavigationListener("oasiz:back", callback);
|
|
288
|
+
const bridge = getBridgeWindow5();
|
|
289
|
+
activeBackListeners += 1;
|
|
290
|
+
if (activeBackListeners === 1) {
|
|
291
|
+
if (typeof bridge?.__oasizSetBackOverride === "function") {
|
|
292
|
+
bridge.__oasizSetBackOverride(true);
|
|
293
|
+
} else {
|
|
294
|
+
warnMissingBridge3("__oasizSetBackOverride");
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
return () => {
|
|
298
|
+
off();
|
|
299
|
+
activeBackListeners = Math.max(0, activeBackListeners - 1);
|
|
300
|
+
if (activeBackListeners === 0) {
|
|
301
|
+
const currentBridge = getBridgeWindow5();
|
|
302
|
+
if (typeof currentBridge?.__oasizSetBackOverride === "function") {
|
|
303
|
+
currentBridge.__oasizSetBackOverride(false);
|
|
304
|
+
} else {
|
|
305
|
+
warnMissingBridge3("__oasizSetBackOverride");
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
};
|
|
309
|
+
}
|
|
310
|
+
function onLeaveGame(callback) {
|
|
311
|
+
return addNavigationListener("oasiz:leave", callback);
|
|
312
|
+
}
|
|
313
|
+
function leaveGame() {
|
|
314
|
+
const bridge = getBridgeWindow5();
|
|
315
|
+
if (typeof bridge?.__oasizLeaveGame === "function") {
|
|
316
|
+
bridge.__oasizLeaveGame();
|
|
317
|
+
return;
|
|
318
|
+
}
|
|
319
|
+
warnMissingBridge3("__oasizLeaveGame");
|
|
320
|
+
}
|
|
321
|
+
|
|
228
322
|
// src/index.ts
|
|
229
323
|
var oasiz = {
|
|
230
324
|
submitScore,
|
|
325
|
+
emitScoreConfig,
|
|
231
326
|
triggerHaptic,
|
|
232
327
|
loadGameState,
|
|
233
328
|
saveGameState,
|
|
234
329
|
flushGameState,
|
|
235
330
|
shareRoomCode,
|
|
331
|
+
openInviteModal,
|
|
236
332
|
onPause,
|
|
237
333
|
onResume,
|
|
334
|
+
onBackButton,
|
|
335
|
+
onLeaveGame,
|
|
336
|
+
leaveGame,
|
|
238
337
|
get gameId() {
|
|
239
338
|
return getGameId();
|
|
240
339
|
},
|
|
@@ -250,15 +349,20 @@ var oasiz = {
|
|
|
250
349
|
};
|
|
251
350
|
// Annotate the CommonJS export names for ESM import in node:
|
|
252
351
|
0 && (module.exports = {
|
|
352
|
+
emitScoreConfig,
|
|
253
353
|
flushGameState,
|
|
254
354
|
getGameId,
|
|
255
355
|
getPlayerAvatar,
|
|
256
356
|
getPlayerName,
|
|
257
357
|
getRoomCode,
|
|
358
|
+
leaveGame,
|
|
258
359
|
loadGameState,
|
|
259
360
|
oasiz,
|
|
361
|
+
onBackButton,
|
|
362
|
+
onLeaveGame,
|
|
260
363
|
onPause,
|
|
261
364
|
onResume,
|
|
365
|
+
openInviteModal,
|
|
262
366
|
saveGameState,
|
|
263
367
|
shareRoomCode,
|
|
264
368
|
submitScore,
|