@usions/sdk 2.17.0 → 2.19.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/package.json +1 -1
- package/src/browser.js +90 -2
- package/src/modules/core.js +12 -1
- package/src/modules/game-methods.js +77 -0
- package/types/index.d.ts +45 -2
package/package.json
CHANGED
package/src/browser.js
CHANGED
|
@@ -69,7 +69,7 @@ var Usion = (function () {
|
|
|
69
69
|
* Core Usion object with init, _post, _request
|
|
70
70
|
*/
|
|
71
71
|
const core = {
|
|
72
|
-
version: '2.
|
|
72
|
+
version: '2.19.0', // injected from package.json at build
|
|
73
73
|
config: {},
|
|
74
74
|
_initialized: false,
|
|
75
75
|
_initCallback: null,
|
|
@@ -263,14 +263,25 @@ var Usion = (function () {
|
|
|
263
263
|
* to a specific screen — e.g. when the user taps a notification sent via
|
|
264
264
|
* `Usion.notify.send({ path })`, the app reopens and `getLaunchParams().path`
|
|
265
265
|
* returns that same path so the app can route to it.
|
|
266
|
-
*
|
|
266
|
+
*
|
|
267
|
+
* `mode` is how the app was launched: `'single'` (opened from Explore / the
|
|
268
|
+
* Game hub, played solo) or `'multiplayer'` (opened from a game invite in a
|
|
269
|
+
* chat, played with another person). The host declares it authoritatively;
|
|
270
|
+
* branch on it to skip lobby/matchmaking UI in single-player or wire up
|
|
271
|
+
* netcode in multiplayer. When the host doesn't declare a mode (legacy hosts
|
|
272
|
+
* or a standalone URL), it falls back to "a room means multiplayer".
|
|
273
|
+
* @returns {{ path: string|null, ref: string|null, roomId: string|null, mode: 'single'|'multiplayer' }}
|
|
267
274
|
*/
|
|
268
275
|
getLaunchParams: function() {
|
|
269
276
|
var c = this.config || {};
|
|
277
|
+
var mode = (c.mode === 'single' || c.mode === 'multiplayer')
|
|
278
|
+
? c.mode
|
|
279
|
+
: (c.roomId ? 'multiplayer' : 'single');
|
|
270
280
|
return {
|
|
271
281
|
path: c.launchPath || null,
|
|
272
282
|
ref: c.ref || c.launchRef || null,
|
|
273
283
|
roomId: c.roomId || null,
|
|
284
|
+
mode: mode,
|
|
274
285
|
};
|
|
275
286
|
},
|
|
276
287
|
|
|
@@ -2346,6 +2357,72 @@ var Usion = (function () {
|
|
|
2346
2357
|
});
|
|
2347
2358
|
};
|
|
2348
2359
|
|
|
2360
|
+
/**
|
|
2361
|
+
* Invite friends to play in your room — like asking for money, but for players.
|
|
2362
|
+
*
|
|
2363
|
+
* Opens the host's friend/group picker (recent chats + search any user by
|
|
2364
|
+
* username + your groups, multi-select). Everyone you pick gets a game-invite
|
|
2365
|
+
* card in their chat; anyone who taps it joins THIS room and your game
|
|
2366
|
+
* receives `onPlayerJoined`.
|
|
2367
|
+
*
|
|
2368
|
+
* Works for any multiplayer-capable game. If the game was opened solo (from
|
|
2369
|
+
* Explore / the Game hub) with no room yet, the host creates one with you as
|
|
2370
|
+
* host and this method joins you to it — so register `onPlayerJoined` before
|
|
2371
|
+
* or right after calling invite(). Capacity is bounded by the game's
|
|
2372
|
+
* `max_players`; the picker caps selection at the remaining seats.
|
|
2373
|
+
*
|
|
2374
|
+
* Embedded feature (the host renders the picker). Standalone resolves
|
|
2375
|
+
* `{ success: false }`. Never rejects.
|
|
2376
|
+
*
|
|
2377
|
+
* @param {{ maxPlayers?: number, timeout?: number }} [opts]
|
|
2378
|
+
* @returns {Promise<{ success: boolean, roomId: string|null, invited: string[] }>}
|
|
2379
|
+
*/
|
|
2380
|
+
game.invite = function(opts) {
|
|
2381
|
+
const self = this;
|
|
2382
|
+
opts = opts || {};
|
|
2383
|
+
|
|
2384
|
+
const embedded = typeof window !== 'undefined' &&
|
|
2385
|
+
(!!window.ReactNativeWebView ||
|
|
2386
|
+
(!!window.parent && window.parent !== window));
|
|
2387
|
+
|
|
2388
|
+
const currentRoom = self.roomId || (Usion.config && Usion.config.roomId) || null;
|
|
2389
|
+
|
|
2390
|
+
if (!embedded) {
|
|
2391
|
+
try { console.warn('[Usion] game.invite needs the Usion app; resolving as not sent.'); } catch (e) { /* noop */ }
|
|
2392
|
+
return Promise.resolve({ success: false, roomId: currentRoom, invited: [] });
|
|
2393
|
+
}
|
|
2394
|
+
|
|
2395
|
+
const reqData = { roomId: currentRoom };
|
|
2396
|
+
if (typeof opts.maxPlayers === 'number' && opts.maxPlayers > 0) {
|
|
2397
|
+
reqData.maxPlayers = opts.maxPlayers;
|
|
2398
|
+
}
|
|
2399
|
+
|
|
2400
|
+
// Long timeout — the user may sit in the picker. Never reject: a dropped
|
|
2401
|
+
// result must not throw inside the game (mirrors permissions.request).
|
|
2402
|
+
return Usion._request('GAME_INVITE_REQUEST', reqData, opts.timeout || 120000)
|
|
2403
|
+
.then(function(res) {
|
|
2404
|
+
res = res || {};
|
|
2405
|
+
const roomId = res.roomId || currentRoom || null;
|
|
2406
|
+
const result = {
|
|
2407
|
+
success: !!res.success,
|
|
2408
|
+
roomId: roomId,
|
|
2409
|
+
invited: Array.isArray(res.invited) ? res.invited : [],
|
|
2410
|
+
};
|
|
2411
|
+
if (!result.success || !roomId) return result;
|
|
2412
|
+
// Ensure the inviter is connected + joined to the room (as host) so
|
|
2413
|
+
// they get onPlayerJoined as invitees arrive. Idempotent when the game
|
|
2414
|
+
// is already in this room; invites were sent by the host regardless.
|
|
2415
|
+
return Promise.resolve()
|
|
2416
|
+
.then(function() { return self.connect(); })
|
|
2417
|
+
.then(function() { return self.join(roomId); })
|
|
2418
|
+
.then(function() { return result; })
|
|
2419
|
+
.catch(function() { return result; });
|
|
2420
|
+
})
|
|
2421
|
+
.catch(function() {
|
|
2422
|
+
return { success: false, roomId: currentRoom, invited: [] };
|
|
2423
|
+
});
|
|
2424
|
+
};
|
|
2425
|
+
|
|
2349
2426
|
/**
|
|
2350
2427
|
* Disconnect from the game socket
|
|
2351
2428
|
*/
|
|
@@ -2507,6 +2584,17 @@ var Usion = (function () {
|
|
|
2507
2584
|
} catch (e) { /* non-fatal */ }
|
|
2508
2585
|
};
|
|
2509
2586
|
|
|
2587
|
+
/**
|
|
2588
|
+
* Whether this app was launched in multiplayer mode (opened from a game
|
|
2589
|
+
* invite in a chat) rather than single-player (opened from Explore / the
|
|
2590
|
+
* Game hub). Convenience wrapper over Usion.getLaunchParams().mode — use it
|
|
2591
|
+
* to branch setup, e.g. skip matchmaking and run solo when false.
|
|
2592
|
+
* @returns {boolean}
|
|
2593
|
+
*/
|
|
2594
|
+
game.isMultiplayer = function() {
|
|
2595
|
+
return Usion.getLaunchParams().mode === 'multiplayer';
|
|
2596
|
+
};
|
|
2597
|
+
|
|
2510
2598
|
/**
|
|
2511
2599
|
* Get connection status
|
|
2512
2600
|
* @returns {boolean}
|
package/src/modules/core.js
CHANGED
|
@@ -260,14 +260,25 @@ export const core = {
|
|
|
260
260
|
* to a specific screen — e.g. when the user taps a notification sent via
|
|
261
261
|
* `Usion.notify.send({ path })`, the app reopens and `getLaunchParams().path`
|
|
262
262
|
* returns that same path so the app can route to it.
|
|
263
|
-
*
|
|
263
|
+
*
|
|
264
|
+
* `mode` is how the app was launched: `'single'` (opened from Explore / the
|
|
265
|
+
* Game hub, played solo) or `'multiplayer'` (opened from a game invite in a
|
|
266
|
+
* chat, played with another person). The host declares it authoritatively;
|
|
267
|
+
* branch on it to skip lobby/matchmaking UI in single-player or wire up
|
|
268
|
+
* netcode in multiplayer. When the host doesn't declare a mode (legacy hosts
|
|
269
|
+
* or a standalone URL), it falls back to "a room means multiplayer".
|
|
270
|
+
* @returns {{ path: string|null, ref: string|null, roomId: string|null, mode: 'single'|'multiplayer' }}
|
|
264
271
|
*/
|
|
265
272
|
getLaunchParams: function() {
|
|
266
273
|
var c = this.config || {};
|
|
274
|
+
var mode = (c.mode === 'single' || c.mode === 'multiplayer')
|
|
275
|
+
? c.mode
|
|
276
|
+
: (c.roomId ? 'multiplayer' : 'single');
|
|
267
277
|
return {
|
|
268
278
|
path: c.launchPath || null,
|
|
269
279
|
ref: c.ref || c.launchRef || null,
|
|
270
280
|
roomId: c.roomId || null,
|
|
281
|
+
mode: mode,
|
|
271
282
|
};
|
|
272
283
|
},
|
|
273
284
|
|
|
@@ -406,6 +406,72 @@ export function applyGameMethods(game, Usion) {
|
|
|
406
406
|
});
|
|
407
407
|
};
|
|
408
408
|
|
|
409
|
+
/**
|
|
410
|
+
* Invite friends to play in your room — like asking for money, but for players.
|
|
411
|
+
*
|
|
412
|
+
* Opens the host's friend/group picker (recent chats + search any user by
|
|
413
|
+
* username + your groups, multi-select). Everyone you pick gets a game-invite
|
|
414
|
+
* card in their chat; anyone who taps it joins THIS room and your game
|
|
415
|
+
* receives `onPlayerJoined`.
|
|
416
|
+
*
|
|
417
|
+
* Works for any multiplayer-capable game. If the game was opened solo (from
|
|
418
|
+
* Explore / the Game hub) with no room yet, the host creates one with you as
|
|
419
|
+
* host and this method joins you to it — so register `onPlayerJoined` before
|
|
420
|
+
* or right after calling invite(). Capacity is bounded by the game's
|
|
421
|
+
* `max_players`; the picker caps selection at the remaining seats.
|
|
422
|
+
*
|
|
423
|
+
* Embedded feature (the host renders the picker). Standalone resolves
|
|
424
|
+
* `{ success: false }`. Never rejects.
|
|
425
|
+
*
|
|
426
|
+
* @param {{ maxPlayers?: number, timeout?: number }} [opts]
|
|
427
|
+
* @returns {Promise<{ success: boolean, roomId: string|null, invited: string[] }>}
|
|
428
|
+
*/
|
|
429
|
+
game.invite = function(opts) {
|
|
430
|
+
const self = this;
|
|
431
|
+
opts = opts || {};
|
|
432
|
+
|
|
433
|
+
const embedded = typeof window !== 'undefined' &&
|
|
434
|
+
(!!window.ReactNativeWebView ||
|
|
435
|
+
(!!window.parent && window.parent !== window));
|
|
436
|
+
|
|
437
|
+
const currentRoom = self.roomId || (Usion.config && Usion.config.roomId) || null;
|
|
438
|
+
|
|
439
|
+
if (!embedded) {
|
|
440
|
+
try { console.warn('[Usion] game.invite needs the Usion app; resolving as not sent.'); } catch (e) { /* noop */ }
|
|
441
|
+
return Promise.resolve({ success: false, roomId: currentRoom, invited: [] });
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
const reqData = { roomId: currentRoom };
|
|
445
|
+
if (typeof opts.maxPlayers === 'number' && opts.maxPlayers > 0) {
|
|
446
|
+
reqData.maxPlayers = opts.maxPlayers;
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
// Long timeout — the user may sit in the picker. Never reject: a dropped
|
|
450
|
+
// result must not throw inside the game (mirrors permissions.request).
|
|
451
|
+
return Usion._request('GAME_INVITE_REQUEST', reqData, opts.timeout || 120000)
|
|
452
|
+
.then(function(res) {
|
|
453
|
+
res = res || {};
|
|
454
|
+
const roomId = res.roomId || currentRoom || null;
|
|
455
|
+
const result = {
|
|
456
|
+
success: !!res.success,
|
|
457
|
+
roomId: roomId,
|
|
458
|
+
invited: Array.isArray(res.invited) ? res.invited : [],
|
|
459
|
+
};
|
|
460
|
+
if (!result.success || !roomId) return result;
|
|
461
|
+
// Ensure the inviter is connected + joined to the room (as host) so
|
|
462
|
+
// they get onPlayerJoined as invitees arrive. Idempotent when the game
|
|
463
|
+
// is already in this room; invites were sent by the host regardless.
|
|
464
|
+
return Promise.resolve()
|
|
465
|
+
.then(function() { return self.connect(); })
|
|
466
|
+
.then(function() { return self.join(roomId); })
|
|
467
|
+
.then(function() { return result; })
|
|
468
|
+
.catch(function() { return result; });
|
|
469
|
+
})
|
|
470
|
+
.catch(function() {
|
|
471
|
+
return { success: false, roomId: currentRoom, invited: [] };
|
|
472
|
+
});
|
|
473
|
+
};
|
|
474
|
+
|
|
409
475
|
/**
|
|
410
476
|
* Disconnect from the game socket
|
|
411
477
|
*/
|
|
@@ -567,6 +633,17 @@ export function applyGameMethods(game, Usion) {
|
|
|
567
633
|
} catch (e) { /* non-fatal */ }
|
|
568
634
|
};
|
|
569
635
|
|
|
636
|
+
/**
|
|
637
|
+
* Whether this app was launched in multiplayer mode (opened from a game
|
|
638
|
+
* invite in a chat) rather than single-player (opened from Explore / the
|
|
639
|
+
* Game hub). Convenience wrapper over Usion.getLaunchParams().mode — use it
|
|
640
|
+
* to branch setup, e.g. skip matchmaking and run solo when false.
|
|
641
|
+
* @returns {boolean}
|
|
642
|
+
*/
|
|
643
|
+
game.isMultiplayer = function() {
|
|
644
|
+
return Usion.getLaunchParams().mode === 'multiplayer';
|
|
645
|
+
};
|
|
646
|
+
|
|
570
647
|
/**
|
|
571
648
|
* Get connection status
|
|
572
649
|
* @returns {boolean}
|
package/types/index.d.ts
CHANGED
|
@@ -31,6 +31,12 @@ export interface UsionConfig {
|
|
|
31
31
|
launchPath?: string;
|
|
32
32
|
/** Referral code the app was opened with, if any. */
|
|
33
33
|
ref?: string;
|
|
34
|
+
/**
|
|
35
|
+
* How the app was launched: `'single'` (from Explore / the Game hub, solo)
|
|
36
|
+
* or `'multiplayer'` (from a game invite in a chat). Read via
|
|
37
|
+
* `Usion.getLaunchParams().mode`. (SDK ≥ 2.18)
|
|
38
|
+
*/
|
|
39
|
+
mode?: 'single' | 'multiplayer';
|
|
34
40
|
}
|
|
35
41
|
|
|
36
42
|
// ─── Payment ─────────────────────────────────────────────────────
|
|
@@ -250,12 +256,36 @@ export interface RematchData {
|
|
|
250
256
|
player_id: string;
|
|
251
257
|
}
|
|
252
258
|
|
|
259
|
+
/** Options for game.invite(). */
|
|
260
|
+
export interface GameInviteOptions {
|
|
261
|
+
/** Cap the room at this many players (otherwise the game's max_players). */
|
|
262
|
+
maxPlayers?: number;
|
|
263
|
+
/** Max ms to wait for the user to finish in the picker (default 120000). */
|
|
264
|
+
timeout?: number;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/** Result of game.invite(). */
|
|
268
|
+
export interface GameInviteResult {
|
|
269
|
+
/** True if the user sent at least one invite. */
|
|
270
|
+
success: boolean;
|
|
271
|
+
/** The room invitees will join (you are host); null if nothing was sent. */
|
|
272
|
+
roomId: string | null;
|
|
273
|
+
/** User/group ids the invite was sent to. */
|
|
274
|
+
invited: string[];
|
|
275
|
+
}
|
|
276
|
+
|
|
253
277
|
export interface GameModule {
|
|
254
278
|
// Connection
|
|
255
279
|
connect(socketUrl?: string, token?: string): Promise<void>;
|
|
256
280
|
connectDirect(config?: DirectConnectionConfig): Promise<void>;
|
|
257
281
|
disconnect(): void;
|
|
258
282
|
isConnected(): boolean;
|
|
283
|
+
/**
|
|
284
|
+
* Whether the app was launched multiplayer (from a chat game invite) vs
|
|
285
|
+
* single-player (from Explore / the Game hub). Wrapper over
|
|
286
|
+
* `Usion.getLaunchParams().mode === 'multiplayer'`. (SDK ≥ 2.18)
|
|
287
|
+
*/
|
|
288
|
+
isMultiplayer(): boolean;
|
|
259
289
|
|
|
260
290
|
// Room & actions
|
|
261
291
|
//
|
|
@@ -280,6 +310,17 @@ export interface GameModule {
|
|
|
280
310
|
requestRematch(): void;
|
|
281
311
|
forfeit(): Promise<{ success: boolean; error?: string }>;
|
|
282
312
|
|
|
313
|
+
/**
|
|
314
|
+
* Invite friends to play in your room. Opens the host's friend/group picker
|
|
315
|
+
* (recent chats + username search + your groups, multi-select); each pick gets
|
|
316
|
+
* a game-invite card in their chat, and anyone who taps it joins THIS room
|
|
317
|
+
* (your game gets `onPlayerJoined`). Works for any multiplayer-capable game —
|
|
318
|
+
* if launched solo with no room, the host creates one with you as host and
|
|
319
|
+
* this joins you to it. Embedded only; standalone resolves `{success:false}`.
|
|
320
|
+
* Never rejects. (SDK ≥ 2.19)
|
|
321
|
+
*/
|
|
322
|
+
invite(opts?: GameInviteOptions): Promise<GameInviteResult>;
|
|
323
|
+
|
|
283
324
|
/**
|
|
284
325
|
* Checkpoint authoritative game state on the server (authority only —
|
|
285
326
|
* player_ids[0]/host). (Re)joining clients receive the latest checkpoint
|
|
@@ -774,9 +815,11 @@ export interface UsionSDK {
|
|
|
774
815
|
/**
|
|
775
816
|
* Launch parameters the host opened this app with. `path` is the deep-link
|
|
776
817
|
* target (e.g. from a tapped `Usion.notify` notification); route to it after
|
|
777
|
-
* init so the user lands on the right screen.
|
|
818
|
+
* init so the user lands on the right screen. `mode` is `'single'` (opened
|
|
819
|
+
* from Explore / the Game hub, solo) or `'multiplayer'` (opened from a game
|
|
820
|
+
* invite in a chat) — branch game setup on it. (mode: SDK ≥ 2.18)
|
|
778
821
|
*/
|
|
779
|
-
getLaunchParams(): { path: string | null; ref: string | null; roomId: string | null };
|
|
822
|
+
getLaunchParams(): { path: string | null; ref: string | null; roomId: string | null; mode: 'single' | 'multiplayer' };
|
|
780
823
|
|
|
781
824
|
// Payments
|
|
782
825
|
requestPayment(amount: number, reason: string, data?: PaymentOptions): Promise<PaymentResponse>;
|