@usions/sdk 2.18.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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@usions/sdk",
3
- "version": "2.18.0",
3
+ "version": "2.19.0",
4
4
  "description": "Usion Mini App SDK for iframe games and services",
5
5
  "type": "module",
6
6
  "main": "src/modules/index.js",
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.18.0', // injected from package.json at build
72
+ version: '2.19.0', // injected from package.json at build
73
73
  config: {},
74
74
  _initialized: false,
75
75
  _initCallback: null,
@@ -2357,6 +2357,72 @@ var Usion = (function () {
2357
2357
  });
2358
2358
  };
2359
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
+
2360
2426
  /**
2361
2427
  * Disconnect from the game socket
2362
2428
  */
@@ -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
  */
package/types/index.d.ts CHANGED
@@ -256,6 +256,24 @@ export interface RematchData {
256
256
  player_id: string;
257
257
  }
258
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
+
259
277
  export interface GameModule {
260
278
  // Connection
261
279
  connect(socketUrl?: string, token?: string): Promise<void>;
@@ -292,6 +310,17 @@ export interface GameModule {
292
310
  requestRematch(): void;
293
311
  forfeit(): Promise<{ success: boolean; error?: string }>;
294
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
+
295
324
  /**
296
325
  * Checkpoint authoritative game state on the server (authority only —
297
326
  * player_ids[0]/host). (Re)joining clients receive the latest checkpoint