@oasiz/sdk 1.3.0 → 1.5.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 +165 -94
- package/dist/index.cjs +90 -21
- package/dist/index.d.cts +7 -10
- package/dist/index.d.ts +7 -10
- package/dist/index.js +88 -20
- package/package.json +14 -4
package/README.md
CHANGED
|
@@ -1,53 +1,63 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Oasiz game SDKs
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Games on Oasiz can integrate using either of these official SDKs:
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
| Platform | Package | Use for |
|
|
6
|
+
| --- | --- | --- |
|
|
7
|
+
| **HTML5 / TypeScript** | [`@oasiz/sdk`](#html5--typescript-oasizsdk) (npm) | Canvas, Phaser, custom JS/TS, any browser game |
|
|
8
|
+
| **Unity WebGL** | [Unity runtime](#unity-webgl-sdk) in this repo (`packages/OasizSDK/`) | Unity projects targeting WebGL |
|
|
9
|
+
|
|
10
|
+
Both talk to the same host bridges (`window.submitScore`, `__oasizLeaveGame`, layout APIs, custom DOM events such as `oasiz:pause`, etc.). Unsupported hosts no-op safely; local dev usually logs warnings instead of crashing.
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## HTML5 / TypeScript (`@oasiz/sdk`)
|
|
15
|
+
|
|
16
|
+
Typed SDK for integrating browser games with the Oasiz platform: score, haptics, cross-session state, multiplayer hooks, layout (safe area, leaderboard visibility), navigation (back / leave), and lifecycle events.
|
|
17
|
+
|
|
18
|
+
### Install
|
|
6
19
|
|
|
7
20
|
```bash
|
|
8
|
-
npm install @oasiz/sdk
|
|
21
|
+
npm install @oasiz/sdk
|
|
9
22
|
```
|
|
10
23
|
|
|
11
|
-
|
|
24
|
+
### Quick start
|
|
12
25
|
|
|
13
26
|
```ts
|
|
14
27
|
import { oasiz } from "@oasiz/sdk";
|
|
15
28
|
|
|
16
|
-
// 1.
|
|
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
|
|
29
|
+
// 1. Load persisted state at the start of each session
|
|
27
30
|
const state = oasiz.loadGameState();
|
|
28
31
|
let level = typeof state.level === "number" ? state.level : 1;
|
|
29
32
|
|
|
30
|
-
//
|
|
33
|
+
// 2. Save state at checkpoints
|
|
31
34
|
oasiz.saveGameState({ level, coins: 42 });
|
|
32
35
|
|
|
33
|
-
//
|
|
36
|
+
// 3. Trigger haptics on key events
|
|
34
37
|
oasiz.triggerHaptic("medium");
|
|
35
38
|
|
|
39
|
+
// 4. Respect the host's top safe area
|
|
40
|
+
document.documentElement.style.setProperty(
|
|
41
|
+
"--safe-top",
|
|
42
|
+
`${oasiz.safeAreaTop}px`,
|
|
43
|
+
);
|
|
44
|
+
|
|
36
45
|
// 5. Submit score when the game ends
|
|
37
46
|
oasiz.submitScore(score);
|
|
38
47
|
|
|
39
|
-
// 6. Optionally
|
|
48
|
+
// 6. Optionally hide the leaderboard while a custom overlay is open
|
|
49
|
+
oasiz.setLeaderboardVisible(false);
|
|
50
|
+
|
|
51
|
+
// 7. Optionally surface console logs in-game while debugging
|
|
40
52
|
oasiz.enableLogOverlay({
|
|
41
53
|
enabled: new URLSearchParams(window.location.search).has("oasizLogs"),
|
|
42
54
|
collapsed: true,
|
|
43
55
|
});
|
|
44
56
|
```
|
|
45
57
|
|
|
46
|
-
|
|
58
|
+
### Score
|
|
47
59
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
### `oasiz.submitScore(score: number)`
|
|
60
|
+
#### `oasiz.submitScore(score: number)`
|
|
51
61
|
|
|
52
62
|
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.
|
|
53
63
|
|
|
@@ -60,39 +70,9 @@ private onGameOver(): void {
|
|
|
60
70
|
- `score` must be a non-negative integer. Floats are floored automatically.
|
|
61
71
|
- Do not call on intermediate scores or level completions, only on final game over.
|
|
62
72
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
### `oasiz.emitScoreConfig(config)`
|
|
66
|
-
|
|
67
|
-
Maps raw score values to the platform's normalized 0–1000 scale. Call once during initialization, not every frame.
|
|
68
|
-
|
|
69
|
-
```ts
|
|
70
|
-
oasiz.emitScoreConfig({
|
|
71
|
-
anchors: [
|
|
72
|
-
{ raw: 10, normalized: 100 }, // beginner
|
|
73
|
-
{ raw: 30, normalized: 300 }, // good
|
|
74
|
-
{ raw: 75, normalized: 600 }, // great
|
|
75
|
-
{ raw: 200, normalized: 950 }, // godlike
|
|
76
|
-
],
|
|
77
|
-
});
|
|
78
|
-
```
|
|
73
|
+
### Haptics
|
|
79
74
|
|
|
80
|
-
|
|
81
|
-
- Exactly 4 anchors required.
|
|
82
|
-
- `raw` values must be strictly increasing.
|
|
83
|
-
- `normalized` values must end at exactly `950`.
|
|
84
|
-
- Choose thresholds based on realistic player skill bands.
|
|
85
|
-
|
|
86
|
-
**Practical guidance by game type:**
|
|
87
|
-
- Survival / time games → use seconds survived as `raw`
|
|
88
|
-
- Score accumulation games → use points as `raw`
|
|
89
|
-
- Puzzle games → use level reached or stars earned as `raw`
|
|
90
|
-
|
|
91
|
-
---
|
|
92
|
-
|
|
93
|
-
## Haptics
|
|
94
|
-
|
|
95
|
-
### `oasiz.triggerHaptic(type: HapticType)`
|
|
75
|
+
#### `oasiz.triggerHaptic(type: HapticType)`
|
|
96
76
|
|
|
97
77
|
Trigger native haptic feedback. Always guard with the user's haptics setting.
|
|
98
78
|
|
|
@@ -101,7 +81,7 @@ type HapticType = "light" | "medium" | "heavy" | "success" | "error";
|
|
|
101
81
|
```
|
|
102
82
|
|
|
103
83
|
| Type | When to use |
|
|
104
|
-
|
|
84
|
+
| --- | --- |
|
|
105
85
|
| `"light"` | UI button taps, menu navigation, D-pad press |
|
|
106
86
|
| `"medium"` | Collecting items, standard collisions, scoring |
|
|
107
87
|
| `"heavy"` | Explosions, major impacts, screen shake |
|
|
@@ -132,11 +112,9 @@ private onGameOver(): void {
|
|
|
132
112
|
|
|
133
113
|
Haptics are throttled internally (50ms cooldown) to prevent spam.
|
|
134
114
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
## Debugging
|
|
115
|
+
### Debugging
|
|
138
116
|
|
|
139
|
-
|
|
117
|
+
#### `oasiz.enableLogOverlay(options?: LogOverlayOptions)`
|
|
140
118
|
|
|
141
119
|
Mount an opt-in in-game console viewer for local debugging, QA sessions, or creator support. It mirrors `console.log`, `console.info`, `console.warn`, `console.error`, and `console.debug` into a floating overlay inside the game iframe. The overlay can be collapsed, repositioned by dragging the top bar, and resized from the bottom-right corner while the action buttons remain clickable.
|
|
142
120
|
|
|
@@ -153,6 +131,7 @@ logOverlay.destroy();
|
|
|
153
131
|
```
|
|
154
132
|
|
|
155
133
|
Options:
|
|
134
|
+
|
|
156
135
|
- `enabled`: defaults to `true`. Pass your own flag or query-param check here.
|
|
157
136
|
- `collapsed`: start with only the toggle pill visible.
|
|
158
137
|
- `maxEntries`: cap retained log lines. Defaults to `200`.
|
|
@@ -160,20 +139,18 @@ Options:
|
|
|
160
139
|
|
|
161
140
|
The returned handle supports `show()`, `hide()`, `clear()`, `isVisible()`, and `destroy()`.
|
|
162
141
|
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
## Game state persistence
|
|
142
|
+
### Game state persistence
|
|
166
143
|
|
|
167
144
|
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.
|
|
168
145
|
|
|
169
|
-
|
|
146
|
+
#### `oasiz.loadGameState(): Record<string, unknown>`
|
|
170
147
|
|
|
171
148
|
Returns the player's saved state synchronously. Returns `{}` if no state has been saved yet. Call once at the start of the game.
|
|
172
149
|
|
|
173
150
|
```ts
|
|
174
151
|
private initFromSavedState(): void {
|
|
175
152
|
const state = oasiz.loadGameState();
|
|
176
|
-
this.level
|
|
153
|
+
this.level = typeof state.level === "number" ? state.level : 1;
|
|
177
154
|
this.lifetimeHits = typeof state.lifetimeHits === "number" ? state.lifetimeHits : 0;
|
|
178
155
|
this.unlockedSkins = Array.isArray(state.unlockedSkins) ? state.unlockedSkins : [];
|
|
179
156
|
}
|
|
@@ -181,7 +158,7 @@ private initFromSavedState(): void {
|
|
|
181
158
|
|
|
182
159
|
Always validate the shape of loaded data — it may be `{}` on first play.
|
|
183
160
|
|
|
184
|
-
|
|
161
|
+
#### `oasiz.saveGameState(state: Record<string, unknown>)`
|
|
185
162
|
|
|
186
163
|
Queues a debounced save. Saves are batched automatically — call freely at checkpoints without worrying about request spam.
|
|
187
164
|
|
|
@@ -198,11 +175,12 @@ private onLevelComplete(): void {
|
|
|
198
175
|
```
|
|
199
176
|
|
|
200
177
|
**Rules:**
|
|
178
|
+
|
|
201
179
|
- State must be a plain JSON object (not an array or primitive).
|
|
202
180
|
- Do not use `localStorage` for cross-session progress — use `saveGameState` so data syncs across platforms.
|
|
203
181
|
- Do not store scores here — scores are submitted via `submitScore`.
|
|
204
182
|
|
|
205
|
-
|
|
183
|
+
#### `oasiz.flushGameState()`
|
|
206
184
|
|
|
207
185
|
Forces an immediate write, bypassing the debounce. Use at important checkpoints like game over or before the page unloads.
|
|
208
186
|
|
|
@@ -214,19 +192,63 @@ private onGameOver(): void {
|
|
|
214
192
|
}
|
|
215
193
|
```
|
|
216
194
|
|
|
217
|
-
|
|
195
|
+
### Layout
|
|
196
|
+
|
|
197
|
+
Use the runtime safe-area value instead of hardcoded top offsets. The host reports the current top inset in **CSS pixels** for persistent chrome such as the back button and top controls.
|
|
198
|
+
|
|
199
|
+
#### `oasiz.getSafeAreaTop(): number`
|
|
200
|
+
|
|
201
|
+
Returns the current top inset. The host may expose `window.getSafeAreaTop()` or `window.__OASIZ_SAFE_AREA_TOP__`. Unsupported hosts return `0`.
|
|
202
|
+
|
|
203
|
+
```ts
|
|
204
|
+
const safeTop = oasiz.getSafeAreaTop();
|
|
205
|
+
document.documentElement.style.setProperty("--safe-top", `${safeTop}px`);
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
#### `oasiz.safeAreaTop`
|
|
209
|
+
|
|
210
|
+
Getter alias for `getSafeAreaTop()`.
|
|
211
|
+
|
|
212
|
+
Recommended CSS pattern:
|
|
213
|
+
|
|
214
|
+
```css
|
|
215
|
+
:root {
|
|
216
|
+
--safe-top: 0px;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
#top-bar {
|
|
220
|
+
padding-top: var(--safe-top);
|
|
221
|
+
}
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
#### `oasiz.setLeaderboardVisible(visible: boolean): void`
|
|
225
|
+
|
|
226
|
+
Show or hide the host leaderboard UI from inside the game. This only affects the leaderboard; back and social controls remain visible. Calls `window.__oasizSetLeaderboardVisible` when present.
|
|
218
227
|
|
|
219
|
-
|
|
228
|
+
```ts
|
|
229
|
+
function openCustomOverlay(): void {
|
|
230
|
+
oasiz.setLeaderboardVisible(false);
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
function closeCustomOverlay(): void {
|
|
234
|
+
oasiz.setLeaderboardVisible(true);
|
|
235
|
+
}
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
Unsupported hosts safely no-op.
|
|
239
|
+
|
|
240
|
+
### Lifecycle
|
|
220
241
|
|
|
221
242
|
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.
|
|
222
243
|
|
|
223
|
-
|
|
224
|
-
|
|
244
|
+
#### `oasiz.onPause(callback: () => void): Unsubscribe`
|
|
245
|
+
|
|
246
|
+
#### `oasiz.onResume(callback: () => void): Unsubscribe`
|
|
225
247
|
|
|
226
248
|
Both return an unsubscribe function.
|
|
227
249
|
|
|
228
250
|
```ts
|
|
229
|
-
const offPause
|
|
251
|
+
const offPause = oasiz.onPause(() => {
|
|
230
252
|
this.gameLoop.stop();
|
|
231
253
|
this.bgMusic.pause();
|
|
232
254
|
});
|
|
@@ -241,18 +263,18 @@ offPause();
|
|
|
241
263
|
offResume();
|
|
242
264
|
```
|
|
243
265
|
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
## Navigation
|
|
266
|
+
### Navigation
|
|
247
267
|
|
|
248
268
|
Use navigation hooks when your game needs to control back behavior (Android back / web Escape) or participate in host-driven close events.
|
|
249
269
|
|
|
250
|
-
|
|
270
|
+
#### `oasiz.onBackButton(callback: () => void): Unsubscribe`
|
|
251
271
|
|
|
252
272
|
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.
|
|
253
273
|
|
|
254
274
|
Use this for pause menus, in-game overlays, or custom back-stack behavior.
|
|
255
275
|
|
|
276
|
+
**If your callback throws**, the SDK calls `leaveGame()` (host close) and **rethrows** the error so you still see it in devtools or error reporting. Non-`Error` throws are normalized to an `Error` (strings become the message; otherwise `"Back button callback failed."`).
|
|
277
|
+
|
|
256
278
|
```ts
|
|
257
279
|
const offBack = oasiz.onBackButton(() => {
|
|
258
280
|
if (this.isPauseMenuOpen) {
|
|
@@ -266,7 +288,7 @@ const offBack = oasiz.onBackButton(() => {
|
|
|
266
288
|
offBack();
|
|
267
289
|
```
|
|
268
290
|
|
|
269
|
-
|
|
291
|
+
#### `oasiz.leaveGame(): void`
|
|
270
292
|
|
|
271
293
|
Programmatically request the host to close the current game (for example, from a Quit button inside your game UI).
|
|
272
294
|
|
|
@@ -276,7 +298,7 @@ quitButton.addEventListener("click", () => {
|
|
|
276
298
|
});
|
|
277
299
|
```
|
|
278
300
|
|
|
279
|
-
|
|
301
|
+
#### `oasiz.onLeaveGame(callback: () => void): Unsubscribe`
|
|
280
302
|
|
|
281
303
|
Registers a callback fired when the host initiates closing the game (for example, close button, gesture, or host navigation). Use this for lightweight cleanup.
|
|
282
304
|
|
|
@@ -290,11 +312,9 @@ const offLeave = oasiz.onLeaveGame(() => {
|
|
|
290
312
|
offLeave();
|
|
291
313
|
```
|
|
292
314
|
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
## Multiplayer
|
|
315
|
+
### Multiplayer
|
|
296
316
|
|
|
297
|
-
|
|
317
|
+
#### `oasiz.shareRoomCode(code: string | null, options?: { inviteOverride?: boolean })`
|
|
298
318
|
|
|
299
319
|
Notify the platform of the active multiplayer room so friends can join via the invite system. Pass `null` when leaving a room.
|
|
300
320
|
|
|
@@ -316,7 +336,9 @@ oasiz.shareRoomCode(null);
|
|
|
316
336
|
oasiz.shareRoomCode(getRoomCode(), { inviteOverride: true });
|
|
317
337
|
```
|
|
318
338
|
|
|
319
|
-
|
|
339
|
+
#### `oasiz.openInviteModal(): void`
|
|
340
|
+
|
|
341
|
+
Opens the platform invite-friends UI when the bridge is available. Typically used together with `shareRoomCode` (for example, your own invite button calls this).
|
|
320
342
|
|
|
321
343
|
```ts
|
|
322
344
|
import { openInviteModal, shareRoomCode } from "@oasiz/sdk";
|
|
@@ -328,7 +350,7 @@ inviteButton.addEventListener("click", () => {
|
|
|
328
350
|
});
|
|
329
351
|
```
|
|
330
352
|
|
|
331
|
-
|
|
353
|
+
#### Read-only injected values
|
|
332
354
|
|
|
333
355
|
These are populated by the platform before the game loads. Always check for `undefined` before using.
|
|
334
356
|
|
|
@@ -342,26 +364,26 @@ if (oasiz.roomCode) {
|
|
|
342
364
|
}
|
|
343
365
|
|
|
344
366
|
// Player identity for multiplayer games
|
|
345
|
-
const name
|
|
367
|
+
const name = oasiz.playerName;
|
|
346
368
|
const avatar = oasiz.playerAvatar;
|
|
347
369
|
```
|
|
348
370
|
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
## Named exports
|
|
371
|
+
### Named exports
|
|
352
372
|
|
|
353
373
|
All methods are also available as named exports if you prefer not to use the `oasiz` namespace object:
|
|
354
374
|
|
|
355
375
|
```ts
|
|
356
376
|
import {
|
|
357
377
|
submitScore,
|
|
358
|
-
emitScoreConfig,
|
|
359
378
|
triggerHaptic,
|
|
360
379
|
loadGameState,
|
|
361
380
|
saveGameState,
|
|
362
381
|
flushGameState,
|
|
363
382
|
shareRoomCode,
|
|
383
|
+
openInviteModal,
|
|
364
384
|
enableLogOverlay,
|
|
385
|
+
getSafeAreaTop,
|
|
386
|
+
setLeaderboardVisible,
|
|
365
387
|
onPause,
|
|
366
388
|
onResume,
|
|
367
389
|
onBackButton,
|
|
@@ -374,9 +396,7 @@ import {
|
|
|
374
396
|
} from "@oasiz/sdk";
|
|
375
397
|
```
|
|
376
398
|
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
## TypeScript types
|
|
399
|
+
### TypeScript types
|
|
380
400
|
|
|
381
401
|
```ts
|
|
382
402
|
import type {
|
|
@@ -384,15 +404,62 @@ import type {
|
|
|
384
404
|
HapticType,
|
|
385
405
|
LogOverlayHandle,
|
|
386
406
|
LogOverlayOptions,
|
|
387
|
-
|
|
388
|
-
|
|
407
|
+
ShareRoomCodeOptions,
|
|
408
|
+
Unsubscribe,
|
|
389
409
|
} from "@oasiz/sdk";
|
|
390
410
|
```
|
|
391
411
|
|
|
392
412
|
---
|
|
393
413
|
|
|
414
|
+
## Unity WebGL SDK
|
|
415
|
+
|
|
416
|
+
C# API and **WebGL-only** `OasizBridge.jslib` live in this repository at **`packages/OasizSDK/`**. Copy the **`OasizSDK`** folder into your Unity project under **`Assets/`** (for example `Assets/OasizSDK`).
|
|
417
|
+
|
|
418
|
+
### Setup
|
|
419
|
+
|
|
420
|
+
1. Copy `packages/OasizSDK` from this repo into `Assets/OasizSDK`.
|
|
421
|
+
2. Ensure the **WebGL** platform is selected for release builds; the `.jslib` under `Runtime/Plugins/WebGL/` is included automatically for WebGL.
|
|
422
|
+
3. Add an **`OasizSDK`** component to a persistent GameObject early (for example a bootstrap scene), **or** rely on `OasizSDK.Instance` which creates a `DontDestroyOnLoad` object. The component registers listeners for `oasiz:pause`, `oasiz:resume`, `oasiz:back`, and `oasiz:leave` via `SendMessage`.
|
|
423
|
+
|
|
424
|
+
### API parity (TypeScript → C#)
|
|
425
|
+
|
|
426
|
+
| HTML5 (`@oasiz/sdk`) | Unity (`Oasiz` namespace) |
|
|
427
|
+
| --- | --- |
|
|
428
|
+
| `oasiz.submitScore(n)` | `OasizSDK.SubmitScore(int)` |
|
|
429
|
+
| `oasiz.triggerHaptic(type)` | `OasizSDK.TriggerHaptic(HapticType)` |
|
|
430
|
+
| `oasiz.loadGameState()` | `OasizSDK.LoadGameState()` → `Dictionary<string, object>` |
|
|
431
|
+
| `oasiz.saveGameState(obj)` | `OasizSDK.SaveGameState(Dictionary<string, object>)` |
|
|
432
|
+
| `oasiz.flushGameState()` | `OasizSDK.FlushGameState()` |
|
|
433
|
+
| `oasiz.getSafeAreaTop()` / `safeAreaTop` | `OasizSDK.GetSafeAreaTop()` / `OasizSDK.SafeAreaTop` (`float`, CSS px) |
|
|
434
|
+
| `oasiz.setLeaderboardVisible(v)` | `OasizSDK.SetLeaderboardVisible(bool)` |
|
|
435
|
+
| `oasiz.onPause` / `onResume` | `OasizSDK.OnPause` / `OnResume` static events |
|
|
436
|
+
| `oasiz.onBackButton` | `OasizSDK.OnBackButton` or `SubscribeBackButton(Action)` (reference-counts `__oasizSetBackOverride`) |
|
|
437
|
+
| `oasiz.onLeaveGame` | `OasizSDK.OnLeaveGame` |
|
|
438
|
+
| `oasiz.leaveGame()` | `OasizSDK.LeaveGame()` |
|
|
439
|
+
| `oasiz.shareRoomCode` | `OasizSDK.ShareRoomCode(string, ShareRoomCodeOptions)` |
|
|
440
|
+
| `oasiz.openInviteModal()` | `OasizSDK.OpenInviteModal()` |
|
|
441
|
+
| `oasiz.gameId` / `roomCode` / … | `OasizSDK.GameId` / `RoomCode` / `PlayerName` / `PlayerAvatar` |
|
|
442
|
+
| — | `OasizSDK.EmitScoreConfig(ScoreConfig)` → `window.emitScoreConfig` (Unity-only helper for normalized score UI) |
|
|
443
|
+
| `oasiz.enableLogOverlay` | `OasizSDK.EnableLogOverlay(LogOverlayOptions)` (see note below) |
|
|
444
|
+
|
|
445
|
+
### Back button and errors
|
|
446
|
+
|
|
447
|
+
Matching the HTML5 SDK: if any **`OnBackButton`** handler throws, **`OasizSDK.LeaveGame()`** is invoked and the **original exception is rethrown** (`throw;` preserves the stack trace). Use **`SubscribeBackButton`** when you want an unsubscribe delegate; you can also use `OnBackButton +=` / `-=` directly.
|
|
448
|
+
|
|
449
|
+
### Editor vs WebGL builds
|
|
450
|
+
|
|
451
|
+
In the **Unity Editor**, bridge calls are mostly **logged** and return safe defaults (for example safe area `0`, `null` platform IDs). Real host integration applies to **WebGL player** builds running inside Oasiz.
|
|
452
|
+
|
|
453
|
+
### Log overlay (Unity)
|
|
454
|
+
|
|
455
|
+
The C# API for the log overlay exists for API compatibility, but the **default `OasizBridge.jslib` in this repo does not inject DOM UI** — `EnableLogOverlay` / `AppendLogOverlay` are no-ops at the JavaScript layer. Use Unity’s console and device logs for debugging unless you replace or extend the `.jslib` on your side.
|
|
456
|
+
|
|
457
|
+
---
|
|
458
|
+
|
|
394
459
|
## Local development
|
|
395
460
|
|
|
461
|
+
### HTML5 / TypeScript
|
|
462
|
+
|
|
396
463
|
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:
|
|
397
464
|
|
|
398
465
|
```
|
|
@@ -400,3 +467,7 @@ All methods safely no-op when the platform bridges are not injected. In developm
|
|
|
400
467
|
```
|
|
401
468
|
|
|
402
469
|
No crashes, no special setup required for local dev.
|
|
470
|
+
|
|
471
|
+
### Unity WebGL
|
|
472
|
+
|
|
473
|
+
The `.jslib` logs warnings when `window.*` bridges are missing (for example `submitScore`, `__oasizLeaveGame`). The Editor path avoids calling native plugins and prints `Debug.Log` for most operations instead.
|
package/dist/index.cjs
CHANGED
|
@@ -20,13 +20,13 @@ 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,
|
|
24
23
|
enableLogOverlay: () => enableLogOverlay,
|
|
25
24
|
flushGameState: () => flushGameState,
|
|
26
25
|
getGameId: () => getGameId,
|
|
27
26
|
getPlayerAvatar: () => getPlayerAvatar,
|
|
28
27
|
getPlayerName: () => getPlayerName,
|
|
29
28
|
getRoomCode: () => getRoomCode,
|
|
29
|
+
getSafeAreaTop: () => getSafeAreaTop,
|
|
30
30
|
leaveGame: () => leaveGame,
|
|
31
31
|
loadGameState: () => loadGameState,
|
|
32
32
|
oasiz: () => oasiz,
|
|
@@ -36,6 +36,7 @@ __export(index_exports, {
|
|
|
36
36
|
onResume: () => onResume,
|
|
37
37
|
openInviteModal: () => openInviteModal,
|
|
38
38
|
saveGameState: () => saveGameState,
|
|
39
|
+
setLeaderboardVisible: () => setLeaderboardVisible,
|
|
39
40
|
shareRoomCode: () => shareRoomCode,
|
|
40
41
|
submitScore: () => submitScore,
|
|
41
42
|
triggerHaptic: () => triggerHaptic
|
|
@@ -1042,14 +1043,6 @@ function submitScore(score) {
|
|
|
1042
1043
|
}
|
|
1043
1044
|
warnMissingBridge("submitScore");
|
|
1044
1045
|
}
|
|
1045
|
-
function emitScoreConfig(config) {
|
|
1046
|
-
const bridge = getBridgeWindow3();
|
|
1047
|
-
if (typeof bridge?.emitScoreConfig === "function") {
|
|
1048
|
-
bridge.emitScoreConfig(config);
|
|
1049
|
-
return;
|
|
1050
|
-
}
|
|
1051
|
-
warnMissingBridge("emitScoreConfig");
|
|
1052
|
-
}
|
|
1053
1046
|
|
|
1054
1047
|
// src/state.ts
|
|
1055
1048
|
function isDevelopment4() {
|
|
@@ -1142,8 +1135,7 @@ function onResume(callback) {
|
|
|
1142
1135
|
return addLifecycleListener("oasiz:resume", callback);
|
|
1143
1136
|
}
|
|
1144
1137
|
|
|
1145
|
-
// src/
|
|
1146
|
-
var activeBackListeners = 0;
|
|
1138
|
+
// src/layout.ts
|
|
1147
1139
|
function isDevelopment6() {
|
|
1148
1140
|
const nodeEnv = globalThis.process?.env?.NODE_ENV;
|
|
1149
1141
|
return nodeEnv !== "production";
|
|
@@ -1161,9 +1153,74 @@ function warnMissingBridge3(methodName) {
|
|
|
1161
1153
|
);
|
|
1162
1154
|
}
|
|
1163
1155
|
}
|
|
1156
|
+
function normalizeSafeAreaTop(value) {
|
|
1157
|
+
if (typeof value !== "number" || !Number.isFinite(value)) {
|
|
1158
|
+
return 0;
|
|
1159
|
+
}
|
|
1160
|
+
return Math.max(0, value);
|
|
1161
|
+
}
|
|
1162
|
+
function getSafeAreaTop() {
|
|
1163
|
+
const bridge = getBridgeWindow5();
|
|
1164
|
+
if (!bridge) {
|
|
1165
|
+
return 0;
|
|
1166
|
+
}
|
|
1167
|
+
if (typeof bridge.getSafeAreaTop === "function") {
|
|
1168
|
+
return normalizeSafeAreaTop(bridge.getSafeAreaTop());
|
|
1169
|
+
}
|
|
1170
|
+
if (typeof bridge.__OASIZ_SAFE_AREA_TOP__ !== "undefined") {
|
|
1171
|
+
return normalizeSafeAreaTop(bridge.__OASIZ_SAFE_AREA_TOP__);
|
|
1172
|
+
}
|
|
1173
|
+
warnMissingBridge3("getSafeAreaTop");
|
|
1174
|
+
return 0;
|
|
1175
|
+
}
|
|
1176
|
+
function setLeaderboardVisible(visible) {
|
|
1177
|
+
if (typeof visible !== "boolean") {
|
|
1178
|
+
if (isDevelopment6()) {
|
|
1179
|
+
console.warn(
|
|
1180
|
+
"[oasiz/sdk] setLeaderboardVisible expected a boolean:",
|
|
1181
|
+
visible
|
|
1182
|
+
);
|
|
1183
|
+
}
|
|
1184
|
+
return;
|
|
1185
|
+
}
|
|
1186
|
+
const bridge = getBridgeWindow5();
|
|
1187
|
+
if (typeof bridge?.__oasizSetLeaderboardVisible === "function") {
|
|
1188
|
+
bridge.__oasizSetLeaderboardVisible(visible);
|
|
1189
|
+
return;
|
|
1190
|
+
}
|
|
1191
|
+
warnMissingBridge3("__oasizSetLeaderboardVisible");
|
|
1192
|
+
}
|
|
1193
|
+
|
|
1194
|
+
// src/navigation.ts
|
|
1195
|
+
var activeBackListeners = 0;
|
|
1196
|
+
function isDevelopment7() {
|
|
1197
|
+
const nodeEnv = globalThis.process?.env?.NODE_ENV;
|
|
1198
|
+
return nodeEnv !== "production";
|
|
1199
|
+
}
|
|
1200
|
+
function getBridgeWindow6() {
|
|
1201
|
+
if (typeof window === "undefined") {
|
|
1202
|
+
return void 0;
|
|
1203
|
+
}
|
|
1204
|
+
return window;
|
|
1205
|
+
}
|
|
1206
|
+
function warnMissingBridge4(methodName) {
|
|
1207
|
+
if (isDevelopment7()) {
|
|
1208
|
+
console.warn(
|
|
1209
|
+
"[oasiz/sdk] " + methodName + " bridge is unavailable. This is expected in local development."
|
|
1210
|
+
);
|
|
1211
|
+
}
|
|
1212
|
+
}
|
|
1213
|
+
function normalizeNavigationError(error) {
|
|
1214
|
+
if (error instanceof Error) {
|
|
1215
|
+
return error;
|
|
1216
|
+
}
|
|
1217
|
+
return new Error(
|
|
1218
|
+
typeof error === "string" ? error : "Back button callback failed."
|
|
1219
|
+
);
|
|
1220
|
+
}
|
|
1164
1221
|
function addNavigationListener(eventName, callback) {
|
|
1165
1222
|
if (typeof window === "undefined") {
|
|
1166
|
-
if (
|
|
1223
|
+
if (isDevelopment7()) {
|
|
1167
1224
|
console.warn(
|
|
1168
1225
|
"[oasiz/sdk] " + eventName + " listener registered without a browser window. This is expected in local development."
|
|
1169
1226
|
);
|
|
@@ -1176,25 +1233,32 @@ function addNavigationListener(eventName, callback) {
|
|
|
1176
1233
|
return () => window.removeEventListener(eventName, handler);
|
|
1177
1234
|
}
|
|
1178
1235
|
function onBackButton(callback) {
|
|
1179
|
-
const off = addNavigationListener("oasiz:back",
|
|
1180
|
-
|
|
1236
|
+
const off = addNavigationListener("oasiz:back", () => {
|
|
1237
|
+
try {
|
|
1238
|
+
callback();
|
|
1239
|
+
} catch (error) {
|
|
1240
|
+
leaveGame();
|
|
1241
|
+
throw normalizeNavigationError(error);
|
|
1242
|
+
}
|
|
1243
|
+
});
|
|
1244
|
+
const bridge = getBridgeWindow6();
|
|
1181
1245
|
activeBackListeners += 1;
|
|
1182
1246
|
if (activeBackListeners === 1) {
|
|
1183
1247
|
if (typeof bridge?.__oasizSetBackOverride === "function") {
|
|
1184
1248
|
bridge.__oasizSetBackOverride(true);
|
|
1185
1249
|
} else {
|
|
1186
|
-
|
|
1250
|
+
warnMissingBridge4("__oasizSetBackOverride");
|
|
1187
1251
|
}
|
|
1188
1252
|
}
|
|
1189
1253
|
return () => {
|
|
1190
1254
|
off();
|
|
1191
1255
|
activeBackListeners = Math.max(0, activeBackListeners - 1);
|
|
1192
1256
|
if (activeBackListeners === 0) {
|
|
1193
|
-
const currentBridge =
|
|
1257
|
+
const currentBridge = getBridgeWindow6();
|
|
1194
1258
|
if (typeof currentBridge?.__oasizSetBackOverride === "function") {
|
|
1195
1259
|
currentBridge.__oasizSetBackOverride(false);
|
|
1196
1260
|
} else {
|
|
1197
|
-
|
|
1261
|
+
warnMissingBridge4("__oasizSetBackOverride");
|
|
1198
1262
|
}
|
|
1199
1263
|
}
|
|
1200
1264
|
};
|
|
@@ -1203,18 +1267,17 @@ function onLeaveGame(callback) {
|
|
|
1203
1267
|
return addNavigationListener("oasiz:leave", callback);
|
|
1204
1268
|
}
|
|
1205
1269
|
function leaveGame() {
|
|
1206
|
-
const bridge =
|
|
1270
|
+
const bridge = getBridgeWindow6();
|
|
1207
1271
|
if (typeof bridge?.__oasizLeaveGame === "function") {
|
|
1208
1272
|
bridge.__oasizLeaveGame();
|
|
1209
1273
|
return;
|
|
1210
1274
|
}
|
|
1211
|
-
|
|
1275
|
+
warnMissingBridge4("__oasizLeaveGame");
|
|
1212
1276
|
}
|
|
1213
1277
|
|
|
1214
1278
|
// src/index.ts
|
|
1215
1279
|
var oasiz = {
|
|
1216
1280
|
submitScore,
|
|
1217
|
-
emitScoreConfig,
|
|
1218
1281
|
triggerHaptic,
|
|
1219
1282
|
enableLogOverlay,
|
|
1220
1283
|
loadGameState,
|
|
@@ -1224,6 +1287,8 @@ var oasiz = {
|
|
|
1224
1287
|
openInviteModal,
|
|
1225
1288
|
onPause,
|
|
1226
1289
|
onResume,
|
|
1290
|
+
getSafeAreaTop,
|
|
1291
|
+
setLeaderboardVisible,
|
|
1227
1292
|
onBackButton,
|
|
1228
1293
|
onLeaveGame,
|
|
1229
1294
|
leaveGame,
|
|
@@ -1238,17 +1303,20 @@ var oasiz = {
|
|
|
1238
1303
|
},
|
|
1239
1304
|
get playerAvatar() {
|
|
1240
1305
|
return getPlayerAvatar();
|
|
1306
|
+
},
|
|
1307
|
+
get safeAreaTop() {
|
|
1308
|
+
return getSafeAreaTop();
|
|
1241
1309
|
}
|
|
1242
1310
|
};
|
|
1243
1311
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1244
1312
|
0 && (module.exports = {
|
|
1245
|
-
emitScoreConfig,
|
|
1246
1313
|
enableLogOverlay,
|
|
1247
1314
|
flushGameState,
|
|
1248
1315
|
getGameId,
|
|
1249
1316
|
getPlayerAvatar,
|
|
1250
1317
|
getPlayerName,
|
|
1251
1318
|
getRoomCode,
|
|
1319
|
+
getSafeAreaTop,
|
|
1252
1320
|
leaveGame,
|
|
1253
1321
|
loadGameState,
|
|
1254
1322
|
oasiz,
|
|
@@ -1258,6 +1326,7 @@ var oasiz = {
|
|
|
1258
1326
|
onResume,
|
|
1259
1327
|
openInviteModal,
|
|
1260
1328
|
saveGameState,
|
|
1329
|
+
setLeaderboardVisible,
|
|
1261
1330
|
shareRoomCode,
|
|
1262
1331
|
submitScore,
|
|
1263
1332
|
triggerHaptic
|
package/dist/index.d.cts
CHANGED
|
@@ -19,13 +19,6 @@ interface LogOverlayHandle {
|
|
|
19
19
|
isVisible: () => boolean;
|
|
20
20
|
show: () => void;
|
|
21
21
|
}
|
|
22
|
-
interface ScoreAnchor {
|
|
23
|
-
raw: number;
|
|
24
|
-
normalized: 100 | 300 | 600 | 950;
|
|
25
|
-
}
|
|
26
|
-
interface ScoreConfig {
|
|
27
|
-
anchors: [ScoreAnchor, ScoreAnchor, ScoreAnchor, ScoreAnchor];
|
|
28
|
-
}
|
|
29
22
|
type GameState = Record<string, unknown>;
|
|
30
23
|
|
|
31
24
|
declare function triggerHaptic(type: HapticType): void;
|
|
@@ -53,7 +46,6 @@ declare function getPlayerName(): string | undefined;
|
|
|
53
46
|
declare function getPlayerAvatar(): string | undefined;
|
|
54
47
|
|
|
55
48
|
declare function submitScore(score: number): void;
|
|
56
|
-
declare function emitScoreConfig(config: ScoreConfig): void;
|
|
57
49
|
|
|
58
50
|
declare function loadGameState(): GameState;
|
|
59
51
|
declare function saveGameState(state: GameState): void;
|
|
@@ -63,13 +55,15 @@ type Unsubscribe = () => void;
|
|
|
63
55
|
declare function onPause(callback: () => void): Unsubscribe;
|
|
64
56
|
declare function onResume(callback: () => void): Unsubscribe;
|
|
65
57
|
|
|
58
|
+
declare function getSafeAreaTop(): number;
|
|
59
|
+
declare function setLeaderboardVisible(visible: boolean): void;
|
|
60
|
+
|
|
66
61
|
declare function onBackButton(callback: () => void): Unsubscribe;
|
|
67
62
|
declare function onLeaveGame(callback: () => void): Unsubscribe;
|
|
68
63
|
declare function leaveGame(): void;
|
|
69
64
|
|
|
70
65
|
declare const oasiz: {
|
|
71
66
|
submitScore: typeof submitScore;
|
|
72
|
-
emitScoreConfig: typeof emitScoreConfig;
|
|
73
67
|
triggerHaptic: typeof triggerHaptic;
|
|
74
68
|
enableLogOverlay: typeof enableLogOverlay;
|
|
75
69
|
loadGameState: typeof loadGameState;
|
|
@@ -79,6 +73,8 @@ declare const oasiz: {
|
|
|
79
73
|
openInviteModal: typeof openInviteModal;
|
|
80
74
|
onPause: typeof onPause;
|
|
81
75
|
onResume: typeof onResume;
|
|
76
|
+
getSafeAreaTop: typeof getSafeAreaTop;
|
|
77
|
+
setLeaderboardVisible: typeof setLeaderboardVisible;
|
|
82
78
|
onBackButton: typeof onBackButton;
|
|
83
79
|
onLeaveGame: typeof onLeaveGame;
|
|
84
80
|
leaveGame: typeof leaveGame;
|
|
@@ -86,6 +82,7 @@ declare const oasiz: {
|
|
|
86
82
|
readonly roomCode: string | undefined;
|
|
87
83
|
readonly playerName: string | undefined;
|
|
88
84
|
readonly playerAvatar: string | undefined;
|
|
85
|
+
readonly safeAreaTop: number;
|
|
89
86
|
};
|
|
90
87
|
|
|
91
|
-
export { type GameState, type HapticType, type LogOverlayEntry, type LogOverlayHandle, type LogOverlayLevel, type LogOverlayOptions, type
|
|
88
|
+
export { type GameState, type HapticType, type LogOverlayEntry, type LogOverlayHandle, type LogOverlayLevel, type LogOverlayOptions, type ShareRoomCodeOptions, type Unsubscribe, enableLogOverlay, flushGameState, getGameId, getPlayerAvatar, getPlayerName, getRoomCode, getSafeAreaTop, leaveGame, loadGameState, oasiz, onBackButton, onLeaveGame, onPause, onResume, openInviteModal, saveGameState, setLeaderboardVisible, shareRoomCode, submitScore, triggerHaptic };
|
package/dist/index.d.ts
CHANGED
|
@@ -19,13 +19,6 @@ interface LogOverlayHandle {
|
|
|
19
19
|
isVisible: () => boolean;
|
|
20
20
|
show: () => void;
|
|
21
21
|
}
|
|
22
|
-
interface ScoreAnchor {
|
|
23
|
-
raw: number;
|
|
24
|
-
normalized: 100 | 300 | 600 | 950;
|
|
25
|
-
}
|
|
26
|
-
interface ScoreConfig {
|
|
27
|
-
anchors: [ScoreAnchor, ScoreAnchor, ScoreAnchor, ScoreAnchor];
|
|
28
|
-
}
|
|
29
22
|
type GameState = Record<string, unknown>;
|
|
30
23
|
|
|
31
24
|
declare function triggerHaptic(type: HapticType): void;
|
|
@@ -53,7 +46,6 @@ declare function getPlayerName(): string | undefined;
|
|
|
53
46
|
declare function getPlayerAvatar(): string | undefined;
|
|
54
47
|
|
|
55
48
|
declare function submitScore(score: number): void;
|
|
56
|
-
declare function emitScoreConfig(config: ScoreConfig): void;
|
|
57
49
|
|
|
58
50
|
declare function loadGameState(): GameState;
|
|
59
51
|
declare function saveGameState(state: GameState): void;
|
|
@@ -63,13 +55,15 @@ type Unsubscribe = () => void;
|
|
|
63
55
|
declare function onPause(callback: () => void): Unsubscribe;
|
|
64
56
|
declare function onResume(callback: () => void): Unsubscribe;
|
|
65
57
|
|
|
58
|
+
declare function getSafeAreaTop(): number;
|
|
59
|
+
declare function setLeaderboardVisible(visible: boolean): void;
|
|
60
|
+
|
|
66
61
|
declare function onBackButton(callback: () => void): Unsubscribe;
|
|
67
62
|
declare function onLeaveGame(callback: () => void): Unsubscribe;
|
|
68
63
|
declare function leaveGame(): void;
|
|
69
64
|
|
|
70
65
|
declare const oasiz: {
|
|
71
66
|
submitScore: typeof submitScore;
|
|
72
|
-
emitScoreConfig: typeof emitScoreConfig;
|
|
73
67
|
triggerHaptic: typeof triggerHaptic;
|
|
74
68
|
enableLogOverlay: typeof enableLogOverlay;
|
|
75
69
|
loadGameState: typeof loadGameState;
|
|
@@ -79,6 +73,8 @@ declare const oasiz: {
|
|
|
79
73
|
openInviteModal: typeof openInviteModal;
|
|
80
74
|
onPause: typeof onPause;
|
|
81
75
|
onResume: typeof onResume;
|
|
76
|
+
getSafeAreaTop: typeof getSafeAreaTop;
|
|
77
|
+
setLeaderboardVisible: typeof setLeaderboardVisible;
|
|
82
78
|
onBackButton: typeof onBackButton;
|
|
83
79
|
onLeaveGame: typeof onLeaveGame;
|
|
84
80
|
leaveGame: typeof leaveGame;
|
|
@@ -86,6 +82,7 @@ declare const oasiz: {
|
|
|
86
82
|
readonly roomCode: string | undefined;
|
|
87
83
|
readonly playerName: string | undefined;
|
|
88
84
|
readonly playerAvatar: string | undefined;
|
|
85
|
+
readonly safeAreaTop: number;
|
|
89
86
|
};
|
|
90
87
|
|
|
91
|
-
export { type GameState, type HapticType, type LogOverlayEntry, type LogOverlayHandle, type LogOverlayLevel, type LogOverlayOptions, type
|
|
88
|
+
export { type GameState, type HapticType, type LogOverlayEntry, type LogOverlayHandle, type LogOverlayLevel, type LogOverlayOptions, type ShareRoomCodeOptions, type Unsubscribe, enableLogOverlay, flushGameState, getGameId, getPlayerAvatar, getPlayerName, getRoomCode, getSafeAreaTop, leaveGame, loadGameState, oasiz, onBackButton, onLeaveGame, onPause, onResume, openInviteModal, saveGameState, setLeaderboardVisible, shareRoomCode, submitScore, triggerHaptic };
|
package/dist/index.js
CHANGED
|
@@ -998,14 +998,6 @@ function submitScore(score) {
|
|
|
998
998
|
}
|
|
999
999
|
warnMissingBridge("submitScore");
|
|
1000
1000
|
}
|
|
1001
|
-
function emitScoreConfig(config) {
|
|
1002
|
-
const bridge = getBridgeWindow3();
|
|
1003
|
-
if (typeof bridge?.emitScoreConfig === "function") {
|
|
1004
|
-
bridge.emitScoreConfig(config);
|
|
1005
|
-
return;
|
|
1006
|
-
}
|
|
1007
|
-
warnMissingBridge("emitScoreConfig");
|
|
1008
|
-
}
|
|
1009
1001
|
|
|
1010
1002
|
// src/state.ts
|
|
1011
1003
|
function isDevelopment4() {
|
|
@@ -1098,8 +1090,7 @@ function onResume(callback) {
|
|
|
1098
1090
|
return addLifecycleListener("oasiz:resume", callback);
|
|
1099
1091
|
}
|
|
1100
1092
|
|
|
1101
|
-
// src/
|
|
1102
|
-
var activeBackListeners = 0;
|
|
1093
|
+
// src/layout.ts
|
|
1103
1094
|
function isDevelopment6() {
|
|
1104
1095
|
const nodeEnv = globalThis.process?.env?.NODE_ENV;
|
|
1105
1096
|
return nodeEnv !== "production";
|
|
@@ -1117,9 +1108,74 @@ function warnMissingBridge3(methodName) {
|
|
|
1117
1108
|
);
|
|
1118
1109
|
}
|
|
1119
1110
|
}
|
|
1111
|
+
function normalizeSafeAreaTop(value) {
|
|
1112
|
+
if (typeof value !== "number" || !Number.isFinite(value)) {
|
|
1113
|
+
return 0;
|
|
1114
|
+
}
|
|
1115
|
+
return Math.max(0, value);
|
|
1116
|
+
}
|
|
1117
|
+
function getSafeAreaTop() {
|
|
1118
|
+
const bridge = getBridgeWindow5();
|
|
1119
|
+
if (!bridge) {
|
|
1120
|
+
return 0;
|
|
1121
|
+
}
|
|
1122
|
+
if (typeof bridge.getSafeAreaTop === "function") {
|
|
1123
|
+
return normalizeSafeAreaTop(bridge.getSafeAreaTop());
|
|
1124
|
+
}
|
|
1125
|
+
if (typeof bridge.__OASIZ_SAFE_AREA_TOP__ !== "undefined") {
|
|
1126
|
+
return normalizeSafeAreaTop(bridge.__OASIZ_SAFE_AREA_TOP__);
|
|
1127
|
+
}
|
|
1128
|
+
warnMissingBridge3("getSafeAreaTop");
|
|
1129
|
+
return 0;
|
|
1130
|
+
}
|
|
1131
|
+
function setLeaderboardVisible(visible) {
|
|
1132
|
+
if (typeof visible !== "boolean") {
|
|
1133
|
+
if (isDevelopment6()) {
|
|
1134
|
+
console.warn(
|
|
1135
|
+
"[oasiz/sdk] setLeaderboardVisible expected a boolean:",
|
|
1136
|
+
visible
|
|
1137
|
+
);
|
|
1138
|
+
}
|
|
1139
|
+
return;
|
|
1140
|
+
}
|
|
1141
|
+
const bridge = getBridgeWindow5();
|
|
1142
|
+
if (typeof bridge?.__oasizSetLeaderboardVisible === "function") {
|
|
1143
|
+
bridge.__oasizSetLeaderboardVisible(visible);
|
|
1144
|
+
return;
|
|
1145
|
+
}
|
|
1146
|
+
warnMissingBridge3("__oasizSetLeaderboardVisible");
|
|
1147
|
+
}
|
|
1148
|
+
|
|
1149
|
+
// src/navigation.ts
|
|
1150
|
+
var activeBackListeners = 0;
|
|
1151
|
+
function isDevelopment7() {
|
|
1152
|
+
const nodeEnv = globalThis.process?.env?.NODE_ENV;
|
|
1153
|
+
return nodeEnv !== "production";
|
|
1154
|
+
}
|
|
1155
|
+
function getBridgeWindow6() {
|
|
1156
|
+
if (typeof window === "undefined") {
|
|
1157
|
+
return void 0;
|
|
1158
|
+
}
|
|
1159
|
+
return window;
|
|
1160
|
+
}
|
|
1161
|
+
function warnMissingBridge4(methodName) {
|
|
1162
|
+
if (isDevelopment7()) {
|
|
1163
|
+
console.warn(
|
|
1164
|
+
"[oasiz/sdk] " + methodName + " bridge is unavailable. This is expected in local development."
|
|
1165
|
+
);
|
|
1166
|
+
}
|
|
1167
|
+
}
|
|
1168
|
+
function normalizeNavigationError(error) {
|
|
1169
|
+
if (error instanceof Error) {
|
|
1170
|
+
return error;
|
|
1171
|
+
}
|
|
1172
|
+
return new Error(
|
|
1173
|
+
typeof error === "string" ? error : "Back button callback failed."
|
|
1174
|
+
);
|
|
1175
|
+
}
|
|
1120
1176
|
function addNavigationListener(eventName, callback) {
|
|
1121
1177
|
if (typeof window === "undefined") {
|
|
1122
|
-
if (
|
|
1178
|
+
if (isDevelopment7()) {
|
|
1123
1179
|
console.warn(
|
|
1124
1180
|
"[oasiz/sdk] " + eventName + " listener registered without a browser window. This is expected in local development."
|
|
1125
1181
|
);
|
|
@@ -1132,25 +1188,32 @@ function addNavigationListener(eventName, callback) {
|
|
|
1132
1188
|
return () => window.removeEventListener(eventName, handler);
|
|
1133
1189
|
}
|
|
1134
1190
|
function onBackButton(callback) {
|
|
1135
|
-
const off = addNavigationListener("oasiz:back",
|
|
1136
|
-
|
|
1191
|
+
const off = addNavigationListener("oasiz:back", () => {
|
|
1192
|
+
try {
|
|
1193
|
+
callback();
|
|
1194
|
+
} catch (error) {
|
|
1195
|
+
leaveGame();
|
|
1196
|
+
throw normalizeNavigationError(error);
|
|
1197
|
+
}
|
|
1198
|
+
});
|
|
1199
|
+
const bridge = getBridgeWindow6();
|
|
1137
1200
|
activeBackListeners += 1;
|
|
1138
1201
|
if (activeBackListeners === 1) {
|
|
1139
1202
|
if (typeof bridge?.__oasizSetBackOverride === "function") {
|
|
1140
1203
|
bridge.__oasizSetBackOverride(true);
|
|
1141
1204
|
} else {
|
|
1142
|
-
|
|
1205
|
+
warnMissingBridge4("__oasizSetBackOverride");
|
|
1143
1206
|
}
|
|
1144
1207
|
}
|
|
1145
1208
|
return () => {
|
|
1146
1209
|
off();
|
|
1147
1210
|
activeBackListeners = Math.max(0, activeBackListeners - 1);
|
|
1148
1211
|
if (activeBackListeners === 0) {
|
|
1149
|
-
const currentBridge =
|
|
1212
|
+
const currentBridge = getBridgeWindow6();
|
|
1150
1213
|
if (typeof currentBridge?.__oasizSetBackOverride === "function") {
|
|
1151
1214
|
currentBridge.__oasizSetBackOverride(false);
|
|
1152
1215
|
} else {
|
|
1153
|
-
|
|
1216
|
+
warnMissingBridge4("__oasizSetBackOverride");
|
|
1154
1217
|
}
|
|
1155
1218
|
}
|
|
1156
1219
|
};
|
|
@@ -1159,18 +1222,17 @@ function onLeaveGame(callback) {
|
|
|
1159
1222
|
return addNavigationListener("oasiz:leave", callback);
|
|
1160
1223
|
}
|
|
1161
1224
|
function leaveGame() {
|
|
1162
|
-
const bridge =
|
|
1225
|
+
const bridge = getBridgeWindow6();
|
|
1163
1226
|
if (typeof bridge?.__oasizLeaveGame === "function") {
|
|
1164
1227
|
bridge.__oasizLeaveGame();
|
|
1165
1228
|
return;
|
|
1166
1229
|
}
|
|
1167
|
-
|
|
1230
|
+
warnMissingBridge4("__oasizLeaveGame");
|
|
1168
1231
|
}
|
|
1169
1232
|
|
|
1170
1233
|
// src/index.ts
|
|
1171
1234
|
var oasiz = {
|
|
1172
1235
|
submitScore,
|
|
1173
|
-
emitScoreConfig,
|
|
1174
1236
|
triggerHaptic,
|
|
1175
1237
|
enableLogOverlay,
|
|
1176
1238
|
loadGameState,
|
|
@@ -1180,6 +1242,8 @@ var oasiz = {
|
|
|
1180
1242
|
openInviteModal,
|
|
1181
1243
|
onPause,
|
|
1182
1244
|
onResume,
|
|
1245
|
+
getSafeAreaTop,
|
|
1246
|
+
setLeaderboardVisible,
|
|
1183
1247
|
onBackButton,
|
|
1184
1248
|
onLeaveGame,
|
|
1185
1249
|
leaveGame,
|
|
@@ -1194,16 +1258,19 @@ var oasiz = {
|
|
|
1194
1258
|
},
|
|
1195
1259
|
get playerAvatar() {
|
|
1196
1260
|
return getPlayerAvatar();
|
|
1261
|
+
},
|
|
1262
|
+
get safeAreaTop() {
|
|
1263
|
+
return getSafeAreaTop();
|
|
1197
1264
|
}
|
|
1198
1265
|
};
|
|
1199
1266
|
export {
|
|
1200
|
-
emitScoreConfig,
|
|
1201
1267
|
enableLogOverlay,
|
|
1202
1268
|
flushGameState,
|
|
1203
1269
|
getGameId,
|
|
1204
1270
|
getPlayerAvatar,
|
|
1205
1271
|
getPlayerName,
|
|
1206
1272
|
getRoomCode,
|
|
1273
|
+
getSafeAreaTop,
|
|
1207
1274
|
leaveGame,
|
|
1208
1275
|
loadGameState,
|
|
1209
1276
|
oasiz,
|
|
@@ -1213,6 +1280,7 @@ export {
|
|
|
1213
1280
|
onResume,
|
|
1214
1281
|
openInviteModal,
|
|
1215
1282
|
saveGameState,
|
|
1283
|
+
setLeaderboardVisible,
|
|
1216
1284
|
shareRoomCode,
|
|
1217
1285
|
submitScore,
|
|
1218
1286
|
triggerHaptic
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@oasiz/sdk",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.5.0",
|
|
4
4
|
"description": "Typed SDK for Oasiz game platform bridge APIs.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -19,19 +19,25 @@
|
|
|
19
19
|
"sideEffects": false,
|
|
20
20
|
"scripts": {
|
|
21
21
|
"build": "tsup src/index.ts --format esm,cjs --dts",
|
|
22
|
-
"prepack": "
|
|
22
|
+
"prepack": "npm run build",
|
|
23
23
|
"test": "node --experimental-strip-types --test ./tests/**/*.test.ts"
|
|
24
24
|
},
|
|
25
25
|
"publishConfig": {
|
|
26
26
|
"access": "public"
|
|
27
27
|
},
|
|
28
|
+
"tagFormat": "sdk-v${version}",
|
|
28
29
|
"release": {
|
|
29
30
|
"branches": [
|
|
30
31
|
"main"
|
|
31
32
|
],
|
|
32
33
|
"plugins": [
|
|
33
|
-
|
|
34
|
-
|
|
34
|
+
[
|
|
35
|
+
"../../scripts/semantic-release/workspace-release.mjs",
|
|
36
|
+
{
|
|
37
|
+
"packageName": "@oasiz/sdk",
|
|
38
|
+
"packagePath": "packages/sdk"
|
|
39
|
+
}
|
|
40
|
+
],
|
|
35
41
|
"@semantic-release/github",
|
|
36
42
|
[
|
|
37
43
|
"@semantic-release/exec",
|
|
@@ -48,5 +54,9 @@
|
|
|
48
54
|
"semantic-release": "^25.0.3",
|
|
49
55
|
"tsup": "^8.5.1",
|
|
50
56
|
"typescript": "^5.9.3"
|
|
57
|
+
},
|
|
58
|
+
"repository": {
|
|
59
|
+
"type": "git",
|
|
60
|
+
"url": "https://github.com/oasiz-ai/oasiz-tooling.git"
|
|
51
61
|
}
|
|
52
62
|
}
|