@indiegems/gem-web-sdk 13.1.0 → 13.2.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/CHANGELOG.md CHANGED
@@ -16,6 +16,22 @@ Its entries are grouped under up to five headings:
16
16
  - **Rebuild**: a type changed. Recompile against the new version; code that compiles today keeps compiling unless the entry says otherwise.
17
17
  - **New capability**: something a game can now do. Nothing changes unless you use it.
18
18
 
19
+ ## 13.2.0
20
+
21
+ Upgrading from 13.1.0. Impact: required.
22
+
23
+ ### Rebuild
24
+
25
+ - The message-type lists and unions between game and Arcade gained the moment request and moment result messages, and the capability type gained moments. Recompiling is enough. If your code switches exhaustively over frame messages, parent messages or capabilities, add handling for the new members so it still compiles.
26
+
27
+ ### New capability
28
+
29
+ - A game can now signal a platform moment at a natural break through Gem.moments. You pass one of a fixed set of moment kinds and an optional placement, and the answer says whether a moment was shown. The call never rejects. If the SDK refuses locally, for example because the host does not support moments, the argument is invalid, ready has not been called, a request is already in flight, or the call was repeated or timed out, the answer is not shown. Check the moments capability before relying on it. Rate limits and the settle time are the same as for ad requests.
30
+ - On the frame side, GemFrame gains signalMoment for sending a moment request to the Arcade, and readyCalled so you can tell whether ready has been reported yet. Signalling before ready is refused. Frame options and callbacks gain onMomentResult to receive the answer.
31
+ - If you build a host that embeds games, for example a development host, you can now receive moment requests through onSignalMoment in the host options and callbacks, and answer them with answerMoment. The new moment request and result message types come with validators for incoming messages.
32
+ - The package now ships a JSON schema describing the log line that development hosts write for moments. Use it if your tooling reads or checks those log lines.
33
+ - Request options gain retryRateLimited, which defaults to true so existing behaviour is unchanged. Set it to false on a call if you want a rate-limit response handed straight back instead of being retried by the transport. Other failures are still retried. This applies in the browser SDK and the server package.
34
+
19
35
  ## 13.1.0
20
36
 
21
37
  Upgrading from 13.0.0. Impact: required.
package/README.md CHANGED
@@ -31,13 +31,14 @@ Read them here rather than guessing from the type declarations, which carry sign
31
31
  | leaderboards | [`docs/leaderboards.md`](docs/leaderboards.md) |
32
32
  | currencies, items, shops and loot | [`docs/inventory-and-catalogs.md`](docs/inventory-and-catalogs.md), [`docs/game-economy-tutorial.md`](docs/game-economy-tutorial.md), [`docs/trading-and-gifting.md`](docs/trading-and-gifting.md) |
33
33
  | Gems, Tickets and achievements | [`docs/arcade-economy.md`](docs/arcade-economy.md), [`docs/achievements.md`](docs/achievements.md), [`docs/brand-art.md`](docs/brand-art.md) |
34
- | daily challenges, async opponents, friends, cross-promotion | [`docs/daily-challenges.md`](docs/daily-challenges.md), [`docs/async-opponents.md`](docs/async-opponents.md), [`docs/friends.md`](docs/friends.md), [`docs/cross-promotion.md`](docs/cross-promotion.md) |
34
+ | what to signal at every break in play — level complete, game over, back to menu | [`docs/platform-moments.md`](docs/platform-moments.md) |
35
+ | daily challenges, async opponents, friends | [`docs/daily-challenges.md`](docs/daily-challenges.md), [`docs/async-opponents.md`](docs/async-opponents.md), [`docs/friends.md`](docs/friends.md) |
35
36
  | a button the player presses for a revive or an extra try — rewarded ads | [`docs/rewarded-ads.md`](docs/rewarded-ads.md) |
36
37
  | analytics | [`docs/analytics.md`](docs/analytics.md) |
37
38
  | multiplayer — rooms, matches, room shapes | [`docs/rooms-and-matches.md`](docs/rooms-and-matches.md), [`docs/room-shapes.md`](docs/room-shapes.md), [`docs/match-session.md`](docs/match-session.md) |
38
39
  | a dedicated server for a match | [`docs/server-bundles.md`](docs/server-bundles.md), [`docs/dedicated-server-flow.md`](docs/dedicated-server-flow.md) |
39
40
  | peer-to-peer matches and parties | [`docs/p2p-and-parties.md`](docs/p2p-and-parties.md) |
40
- | server-side logic without a game server | [`docs/serverless-functions.md`](docs/serverless-functions.md), and [`docs/serverless-functions-js.md`](docs/serverless-functions-js.md) to write one in JavaScript or TypeScript |
41
+ | server-side logic without a game server | [`docs/serverless-functions.md`](docs/serverless-functions.md), written in Rust; JavaScript functions are disabled for now, due to performance issues, and [`docs/serverless-functions-js.md`](docs/serverless-functions-js.md) covers one already published in JavaScript |
41
42
  | when a deprecated surface stops working | [`docs/deprecation-policy.md`](docs/deprecation-policy.md) |
42
43
  | what changed between versions, and what to do about it | [`CHANGELOG.md`](CHANGELOG.md) |
43
44
 
@@ -49,7 +50,7 @@ Every guide is one Markdown file, so a search over `docs/` finds the page that c
49
50
  |---|---|
50
51
  | `@indiegems/gem-web-sdk/sdk` | The one import a game writes, in the browser and on its server alike. |
51
52
  | `@indiegems/gem-web-sdk/game`, `@indiegems/gem-web-sdk/server` | The browser half and the server half on their own, for a build that wants only one. |
52
- | `@indiegems/gem-web-sdk/function` | What a serverless function written in JavaScript imports. A function's build bundles it, and the starter's build resolves `/sdk` and `/game` to it as well. |
53
+ | `@indiegems/gem-web-sdk/function` | What a serverless function written in JavaScript imports. JavaScript functions are disabled for now, due to performance issues: a new one cannot be uploaded, and one already published keeps running. A function's build bundles it, and the starter's build resolves `/sdk` and `/game` to it as well. |
53
54
  | `@indiegems/gem-web-sdk/schema` | The wire schema between a game and the Arcade page that hosts it. |
54
55
  | `@indiegems/gem-web-sdk/brand/*` | The platform's Gems, Tickets and trophy art — see [`docs/brand-art.md`](docs/brand-art.md). |
55
56
  | `gem-sdk-stamp <build-directory>` | Run after your bundler: records which SDK version a build carries, which a published web build has to say. |
@@ -68,6 +68,7 @@ interface RequestOptions {
68
68
  readonly keepalive?: boolean;
69
69
  readonly ifMatch?: string;
70
70
  readonly replaySafe?: boolean;
71
+ readonly retryRateLimited?: boolean;
71
72
  }
72
73
  interface VersionedGetOptions {
73
74
  readonly signal?: AbortSignal;
package/dist/game.d.ts CHANGED
@@ -77,6 +77,7 @@ interface RequestOptions {
77
77
  readonly keepalive?: boolean;
78
78
  readonly ifMatch?: string;
79
79
  readonly replaySafe?: boolean;
80
+ readonly retryRateLimited?: boolean;
80
81
  }
81
82
  interface VersionedGetOptions {
82
83
  readonly signal?: AbortSignal;
@@ -2254,6 +2255,12 @@ interface GemAdResult {
2254
2255
  readonly requestId: string;
2255
2256
  readonly outcome: "shown" | "no_ad" | "unavailable";
2256
2257
  }
2258
+ interface GemMomentResult {
2259
+ readonly gem: typeof PROTOCOL;
2260
+ readonly type: "gem.momentResult";
2261
+ readonly requestId: string;
2262
+ readonly shown: boolean;
2263
+ }
2257
2264
  interface GemSignInResult {
2258
2265
  readonly gem: typeof PROTOCOL;
2259
2266
  readonly type: "gem.signInResult";
@@ -2847,6 +2854,7 @@ interface FrameCallbacks {
2847
2854
  onDeviceSettings?(msg: GemDeviceSettings): void;
2848
2855
  onDeviceSettingsResult?(msg: GemDeviceSettingsResult): void;
2849
2856
  onAdResult?(msg: GemAdResult): void;
2857
+ onMomentResult?(msg: GemMomentResult): void;
2850
2858
  onSignInResult?(msg: GemSignInResult): void;
2851
2859
  onFriendChallengeResult?(msg: GemFriendChallengeResult): void;
2852
2860
  onError?(code: GemErrorCode, message?: string): void;
@@ -2921,6 +2929,8 @@ declare class GemFrame {
2921
2929
  requestAvatar3dPurchase(requestId: string, itemId: string, currencySlug: string): boolean;
2922
2930
  putDeviceSettings(requestId: string, settings: Readonly<Record<string, unknown>>): boolean;
2923
2931
  requestAd(requestId: string, placement: string, format: "interstitial" | "rewarded"): boolean;
2932
+ signalMoment(requestId: string, kind: string, placement?: string): boolean;
2933
+ readyCalled(): boolean;
2924
2934
  requestSignIn(requestId: string): boolean;
2925
2935
  requestFriendChallenge(requestId: string, playerId: string, template: string, params?: Readonly<Record<string, string | number>>): boolean;
2926
2936
  close(): void;
@@ -2998,6 +3008,17 @@ interface AdsApi {
2998
3008
  requestAd(req: AdRequest): Promise<AdOutcome>;
2999
3009
  rewardedStatus(placement: string): Promise<RewardedStatus>;
3000
3010
  }
3011
+ type MomentKind = "level_end" | "run_end" | "match_end" | "menu_return" | "other_break";
3012
+ interface MomentSignal {
3013
+ kind: MomentKind;
3014
+ placement?: string;
3015
+ }
3016
+ interface MomentResult {
3017
+ readonly shown: boolean;
3018
+ }
3019
+ interface MomentsApi {
3020
+ signal(moment: MomentSignal): Promise<MomentResult>;
3021
+ }
3001
3022
  type DeviceSettings = Readonly<Record<string, unknown>>;
3002
3023
  type DeviceSettingsPutOutcome = "stored" | "too_large" | "unavailable";
3003
3024
  interface DeviceSettingsApi {
@@ -3132,6 +3153,7 @@ interface Gem {
3132
3153
  readonly gameConfig: GameConfigApi;
3133
3154
  readonly purchases: PurchaseApi;
3134
3155
  readonly deviceSettings: DeviceSettingsApi;
3156
+ readonly moments: MomentsApi;
3135
3157
  readonly ads: AdsApi;
3136
3158
  readonly account: AccountApi;
3137
3159
  readonly share: ShareApi;
@@ -3187,4 +3209,4 @@ interface ExitAnalytics {
3187
3209
  }
3188
3210
  declare function leaveAndExit(rooms: ExitRooms, bridge: ExitBridge | null, reason?: string, analytics?: ExitAnalytics): Promise<void>;
3189
3211
  declare function createGem(options?: GemOptions): Gem;
3190
- export { ARCADE_EMBEDDERS, AVATAR_RIGS, type AccountApi, type AdFormat, type AdOutcome, type AdOutcomeKind, type AdRequest, type AdsApi, AnalyticsApi, type AnalyticsFlushOptions, type AnalyticsFlushResult, type AnalyticsOptions, type AnalyticsRejection, type AnalyticsValue, AuthError, type AuthFailure, type AuthState, type Avatar3dFamily, type Avatar3dOffer, type Avatar3dPrice, type Avatar3dPurchaseRequest, type AvatarRigNode, type AvatarRigs, type Avatars3dApi, type BootMark, type BootTimeline, type Challenge, type ChallengeWindow, ChallengesApi, type ConfiguredPurchasePayment, type ConfiguredPurchaseRequest, type ConfiguredPurchaseResult, type ControlsApi, DEVICE_SETTINGS_MAX_BYTES, DedicatedServerError, type DedicatedServerFailure, type DedicatedServerSession, type DevToolsOpener, type DeviceSettings, type DeviceSettingsApi, type DeviceSettingsPutOutcome, type DirectPurchaseRequest, type DirectPurchaseResult, type EarnAllowance, type EarnAllowanceEvent, type EarnAllowancePeriod, type EarnAllowanceReadOptions, type EntityLeaderboard, type EntityLeaderboardEntry, type EntityLeaderboardOptions, type EntityType, type ExitAnalytics, type ExitBridge, type ExitRooms, type FrameState, type Friend, type FriendChallenge, FriendChallengeError, type FriendChallengeErrorCode, type FriendChallengeOutcome, type FriendChallengeOutcomeKind, type FriendChallengeRequest, type FriendChallengesPage, FriendsApi, type FriendsPage, type FunctionFailure, type FunctionInvokeOptions, type FunctionResult, FunctionsApi, type GameConfig, type GameMenu, type GameMenuItem, type GameServerLink, type Gem, GemApiError, GemClient, type GemCohort, type GemCohorts, GemConfigError, type GemCorner, type GemDevTools, GemFrame, GemFunctionError, type GemGraphicsQuality, type GemIdentity, type GemInsets, type GemLook, type GemLookBase, type GemLookDelta, type GemLookOptions, type GemLookSpeed, type GemMatchApi, type GemMatchServerModule, type GemOptions, type GemPlayer, type GemPrefs, type GemRecommendedSettings, type GemReservedArea, GemSaveError, type GemServerBundle, type GemServerFactory, type GemServerHost, type GemServerHostProfile, type GemServerLifecycle, type GemTerminationNotice, GemUnframedError, type GemViewport, type GetLeaderboardOptions, type JoinWelcome, type Leaderboard, type LeaderboardEntry, type LeaderboardPeriod, LeaderboardsApi, type ListChallengesOptions, type ListFriendChallengesOptions, type ListFriendsOptions, MAX_PERIODS_BACK, type MatchConnectOptions, type MatchConnection, type MatchHosting, type MatchHostingMode, type MatchServeOptions, type MatchTransport, type MessageMeta, type MultiTransportSession, PLATFORM_EVENTS, type PeriodOptions, PlatformApi, PlatformCurrenciesApi, type PlatformCurrency, type PlatformCurrencyAccess, type PlatformCurrencyPurchasePayment, type PlatformCurrencyPurchaseRequest, type PlatformCurrencyPurchaseResult, type PlatformCurrencyReadOptions, PlatformEarnAllowanceApi, type PlatformEventName, type PlayerBadge, type PlayerBoost, type PlayerBoostMultiplier, type PlayerIdentity, type PlayerProfile, PlayerText, type ProfileCallOptions, type ProfileShowcaseEntry, ProfilesApi, type PurchaseApi, type PurchaseOptions, type PurchaseOutcome, PurchaseRefusal, type PurchaseRefusalCode, type PurchaseRequest, type PutBytesOptions, type PutSaveOptions, type RankedRow, type RecipeAvailability, type RecipeLock, type RewardCue, type RewardedStatus, type SavePage, type SaveRecord, type SendOptions$1 as SendOptions, type ServerTokenGrant, type SessionEndReason, type ShareApi, type ShareRequest, ShowcaseApi, type ShowcaseCallOptions, type ShowcaseFriendEntry, type ShowcaseFriends, type ShowcaseValue, type SignInOutcome, type SignInOutcomeKind, type SnapshotCurrency, type SnapshotItem, type TransportAdvert, type TransportKind, TransportRefusal, UNRELIABLE_CHANNEL_LABEL, type VibrationApi, type WalletVisibleOptions, type WornAvatar3d, asPlayerText, createBootTimeline, createGem, leaveAndExit, mapIdentity, markOnResolve, platformIconUrl, presentJoinCredential, readTemplateTransports, readTransportAdvert, reportOnResolve, text, webTransportAvailable };
3212
+ export { ARCADE_EMBEDDERS, AVATAR_RIGS, type AccountApi, type AdFormat, type AdOutcome, type AdOutcomeKind, type AdRequest, type AdsApi, AnalyticsApi, type AnalyticsFlushOptions, type AnalyticsFlushResult, type AnalyticsOptions, type AnalyticsRejection, type AnalyticsValue, AuthError, type AuthFailure, type AuthState, type Avatar3dFamily, type Avatar3dOffer, type Avatar3dPrice, type Avatar3dPurchaseRequest, type AvatarRigNode, type AvatarRigs, type Avatars3dApi, type BootMark, type BootTimeline, type Challenge, type ChallengeWindow, ChallengesApi, type ConfiguredPurchasePayment, type ConfiguredPurchaseRequest, type ConfiguredPurchaseResult, type ControlsApi, DEVICE_SETTINGS_MAX_BYTES, DedicatedServerError, type DedicatedServerFailure, type DedicatedServerSession, type DevToolsOpener, type DeviceSettings, type DeviceSettingsApi, type DeviceSettingsPutOutcome, type DirectPurchaseRequest, type DirectPurchaseResult, type EarnAllowance, type EarnAllowanceEvent, type EarnAllowancePeriod, type EarnAllowanceReadOptions, type EntityLeaderboard, type EntityLeaderboardEntry, type EntityLeaderboardOptions, type EntityType, type ExitAnalytics, type ExitBridge, type ExitRooms, type FrameState, type Friend, type FriendChallenge, FriendChallengeError, type FriendChallengeErrorCode, type FriendChallengeOutcome, type FriendChallengeOutcomeKind, type FriendChallengeRequest, type FriendChallengesPage, FriendsApi, type FriendsPage, type FunctionFailure, type FunctionInvokeOptions, type FunctionResult, FunctionsApi, type GameConfig, type GameMenu, type GameMenuItem, type GameServerLink, type Gem, GemApiError, GemClient, type GemCohort, type GemCohorts, GemConfigError, type GemCorner, type GemDevTools, GemFrame, GemFunctionError, type GemGraphicsQuality, type GemIdentity, type GemInsets, type GemLook, type GemLookBase, type GemLookDelta, type GemLookOptions, type GemLookSpeed, type GemMatchApi, type GemMatchServerModule, type GemOptions, type GemPlayer, type GemPrefs, type GemRecommendedSettings, type GemReservedArea, GemSaveError, type GemServerBundle, type GemServerFactory, type GemServerHost, type GemServerHostProfile, type GemServerLifecycle, type GemTerminationNotice, GemUnframedError, type GemViewport, type GetLeaderboardOptions, type JoinWelcome, type Leaderboard, type LeaderboardEntry, type LeaderboardPeriod, LeaderboardsApi, type ListChallengesOptions, type ListFriendChallengesOptions, type ListFriendsOptions, MAX_PERIODS_BACK, type MatchConnectOptions, type MatchConnection, type MatchHosting, type MatchHostingMode, type MatchServeOptions, type MatchTransport, type MessageMeta, type MomentKind, type MomentResult, type MomentSignal, type MomentsApi, type MultiTransportSession, PLATFORM_EVENTS, type PeriodOptions, PlatformApi, PlatformCurrenciesApi, type PlatformCurrency, type PlatformCurrencyAccess, type PlatformCurrencyPurchasePayment, type PlatformCurrencyPurchaseRequest, type PlatformCurrencyPurchaseResult, type PlatformCurrencyReadOptions, PlatformEarnAllowanceApi, type PlatformEventName, type PlayerBadge, type PlayerBoost, type PlayerBoostMultiplier, type PlayerIdentity, type PlayerProfile, PlayerText, type ProfileCallOptions, type ProfileShowcaseEntry, ProfilesApi, type PurchaseApi, type PurchaseOptions, type PurchaseOutcome, PurchaseRefusal, type PurchaseRefusalCode, type PurchaseRequest, type PutBytesOptions, type PutSaveOptions, type RankedRow, type RecipeAvailability, type RecipeLock, type RewardCue, type RewardedStatus, type SavePage, type SaveRecord, type SendOptions$1 as SendOptions, type ServerTokenGrant, type SessionEndReason, type ShareApi, type ShareRequest, ShowcaseApi, type ShowcaseCallOptions, type ShowcaseFriendEntry, type ShowcaseFriends, type ShowcaseValue, type SignInOutcome, type SignInOutcomeKind, type SnapshotCurrency, type SnapshotItem, type TransportAdvert, type TransportKind, TransportRefusal, UNRELIABLE_CHANNEL_LABEL, type VibrationApi, type WalletVisibleOptions, type WornAvatar3d, asPlayerText, createBootTimeline, createGem, leaveAndExit, mapIdentity, markOnResolve, platformIconUrl, presentJoinCredential, readTemplateTransports, readTransportAdvert, reportOnResolve, text, webTransportAvailable };
@@ -1 +1 @@
1
- var GemWebSdkBridgeBundle=(function(){'use strict';var P="GemWebSdkHandshake";function Z(){return typeof document>"u"?void 0:document.readyState}var L=()=>Date.now();function _(n={}){let e=n.win??window,t=e,r=t[P];if(r!==void 0)return r;let s=n.readyState??Z,i=n.now??L,d=[],o=[],m=p=>{let c=p.data;!c||c.type!=="gem.handshake"||(d.length>=4&&(d.shift(),o.shift(),g.dropped+=1),d.push(p),o.push(i()));};e.addEventListener("message",m);let g={events:d,times:o,dropped:0,late:s()==="complete",uninstall(){e.removeEventListener("message",m);}};return t[P]=g,g}function M(n,e,t={}){let r=n[P];if(r===void 0)return null;let s=t.ttlMs??9500,i=t.now??L,d=r.events.splice(0),o=r.times?.splice(0),m=0,g=0,p=false,c=i()-s;for(let y=d.length-1;y>=0;y--){let f=o?.[y];if(f!==void 0&&f<c){g+=1;continue}if(m+=1,e(d[y])===true){p=true;break}}return r.uninstall(),{capture:r,delivered:m,stale:g,accepted:p}}var l="gem-web-bridge",k={min:1,max:1},h=65536,j=8,b=5e3,D=1024;function F(n){return Object.freeze(Object.assign(Object.create(null),n))}var $=F({"gem.handshake":30,"gem.handshake.accept":5,"gem.token":30,"gem.token.denied":30,"gem.player":12,"gem.pause":120,"gem.prefs":60,"gem.cohorts":12,"gem.earnAllowanceChanged":30,"gem.viewport":60,"gem.deviceSettings":12,"gem.willTerminate":10,"gem.roomEvent":120,"gem.socketState":12,"gem.seatedEvent":60,"gem.autoStartFailedEvent":30,"gem.ticketEvent":60,"gem.signalEvent":1800,"gem.dedicatedEvent":120,"gem.partyResult":30,"gem.clusterTarget":12,"gem.devtools":30,"gem.screenshot":6,"gem.screenshot.denied":12,"gem.requestContext":12,"gem.gameContext":12,"gem.signal":1200,"gem.dedicatedOffer":60,"gem.partyRequest":12,"gem.ready":5,"gem.engaged":5,"gem.progress":600,"gem.requestToken":12,"gem.requestLocalServer":6,"gem.localServer":30,"gem.localServer.denied":30,"gem.exit":5,"gem.openExternal":6,"gem.requestFullscreen":30,"gem.audioState":120,"gem.rewardCue":60,"gem.walletDisplay":60,"gem.controlsDeclare":60,"gem.menu":60,"gem.menuSelect":60,"gem.gemCorner":12,"gem.requestShare":6,"gem.requestAvatarPicker":6,"gem.vibrate":600,"gem.frameStats":120,"gem.portraitBorders":60,"gem.error":60,"gem.requestPurchase":12,"gem.requestAvatar3dPurchase":12,"gem.purchaseResult":30,"gem.deviceSettings.put":30,"gem.deviceSettings.result":30,"gem.requestAd":6,"gem.adResult":12,"gem.requestSignIn":6,"gem.signInResult":12,"gem.requestFriendChallenge":12,"gem.friendChallengeResult":30,__malformed:60}),w="__malformed";var ee=F({"gem.requestAd":"ads","gem.adResult":"ads","gem.requestSignIn":"signIn","gem.signInResult":"signIn","gem.requestPurchase":"purchases","gem.purchaseResult":"purchases","gem.requestAvatar3dPurchase":"avatar3dPurchases","gem.requestFriendChallenge":"friendChallenges","gem.friendChallengeResult":"friendChallenges","gem.devtools":"devtools","gem.screenshot":"screenshot","gem.screenshot.denied":"screenshot","gem.requestContext":"feedbackContext","gem.gameContext":"feedbackContext","gem.roomEvent":"rooms","gem.signal":"p2p","gem.signalEvent":"p2p","gem.dedicatedOffer":"dedicated","gem.dedicatedEvent":"dedicated","gem.clusterTarget":"clusterTarget","gem.partyRequest":"parties","gem.partyResult":"parties","gem.autoStartFailedEvent":"autoStartFailure","gem.ticketEvent":"ticketEvents","gem.seatedEvent":"partySeating","gem.socketState":"socketState","gem.audioState":"audioState","gem.rewardCue":"rewardCue","gem.frameStats":"frameStats","gem.portraitBorders":"portraitBorders","gem.engaged":"engagement","gem.viewport":"viewport","gem.walletDisplay":"walletDisplay","gem.requestLocalServer":"localHost","gem.localServer":"localHost","gem.localServer.denied":"localHost","gem.cohorts":"cohorts","gem.earnAllowanceChanged":"earnAllowance","gem.deviceSettings":"deviceSettings","gem.deviceSettings.put":"deviceSettings","gem.deviceSettings.result":"deviceSettings","gem.requestShare":"share","gem.requestAvatarPicker":"avatarPicker","gem.vibrate":"vibration","gem.menu":"gameMenu","gem.menuSelect":"gameMenu","gem.controlsDeclare":"controls","gem.gemCorner":"gemCorner"}),te=Object.freeze([["gem.asyncOpponents.","asyncOpponents"],["gem.vibration.","vibration"],["gem.viewport.","reservedAreas"]]);function U(n){let e=ee[n];if(e!==void 0)return e;for(let[t,r]of te)if(n.startsWith(t))return r}function ne(n){let e=/^([a-z][a-z0-9+.-]*):\/\/([a-z0-9.-]+|\[[0-9a-f:.]+\])(:([0-9]{1,5}))?$/i.exec(n);return e===null?false:e[4]===void 0||Number(e[4])<=65535}function re(n){let e;try{e=new URL(n);}catch{return false}return e.username!==""||e.password!==""?false:e.protocol==="https:"?true:e.protocol==="http:"&&(e.hostname==="localhost"||e.hostname==="127.0.0.1")}function ae(n){return /^[a-z]{2,8}(-[a-z0-9]{1,8})*$/i.test(n)}function oe(n){return /^[a-z_]+$/.test(n)}function T(n,e,t){if(e>j)return `nesting deeper than ${j}`;if(++t.nodes>b)return `more than ${b} values`;if(t.bytes>h)return `over the ${h} byte limit`;if(n==null)return t.bytes+=4,null;let r=typeof n;if(r==="boolean")return t.bytes+=5,null;if(r==="number")return t.bytes+=8,null;if(r==="string")return t.bytes+=n.length*3+2,null;if(r!=="object")return `${r} is not plain data`;let s=n;if(t.seen.has(s))return "a repeated or cyclic object reference";if(t.seen.add(s),Array.isArray(n)){if(n.length>D)return `an array of ${n.length} entries, over the ${D} limit`;t.bytes+=2;for(let o of n){let m=T(o,e+1,t);if(m)return m}return null}let i=Object.getPrototypeOf(n);if(i!==Object.prototype&&i!==null)return "a value that is not a plain object";t.bytes+=2;let d=n;for(let o in d){if(!Object.prototype.hasOwnProperty.call(d,o))continue;if(++t.nodes>b)return `more than ${b} values`;if(t.bytes+=o.length*3+4,t.bytes>h)return `over the ${h} byte limit`;let m=T(d[o],e+1,t);if(m)return m}return null}function se(n){let e={nodes:0,bytes:0,seen:new Set},t=T(n,0,e);return t?`message contains ${t}`:e.bytes>h?`message is over the ${h} byte limit`:null}var ie={origin:[ne,"not a well-formed origin"],url:[re,"not a safe absolute http(s) URL"],bcp47:[ae,"not a well-formed BCP 47 tag"],code:[oe,"not a code of lower-case letters and underscores"]};function H(n,e,t){for(let r of e){let s=t===""?r.n:`${t}.${r.n}`,i=n[r.n];if(i==null){if(r.o)continue;return `${s}: required`}let d=B(i,r,s);if(d)return d}return null}function B(n,e,t){switch(e.k){case "s":{if(typeof n!="string")return `${t}: expected string`;if(n.length>e.max)return `${t}: exceeds ${e.max} characters`;if(e.f){let[r,s]=ie[e.f];if(!r(n))return `${t}: ${s}`}return null}case "i":return typeof n!="number"||!Number.isInteger(n)?`${t}: expected integer`:n<e.lo||n>e.hi?`${t}: out of range ${e.lo}..${e.hi}`:null;case "b":return typeof n=="boolean"?null:`${t}: expected boolean`;case "e":{let r=e.v;return r.includes(n)?null:`${t}: not one of ${r.join("|")}`}case "o":return typeof n!="object"||n===null||Array.isArray(n)?`${t}: expected object`:H(n,e.fs,t);case "j":return typeof n!="object"||n===null||Array.isArray(n)?`${t}: expected a plain object`:null;case "a":{if(!Array.isArray(n))return `${t}: expected array`;if(n.length>e.max)return `${t}: exceeds ${e.max} items`;let r=e.it,s=`${t}[]`;for(let i of n){if(i==null){if(r.o)continue;return `${s}: required`}let d=B(i,r,s);if(d)return d}return null}default:{let r=e.k;return `${t}: unknown kind ${String(r)}`}}}var W=Object.create(null);function a(n,e){return W[n]=t=>{let r=se(t);if(r)return r;if(typeof t!="object"||t===null||Array.isArray(t))return "message: expected object";let s=t;return s.gem!==l?"gem: wrong protocol marker":s.type!==n?`type: expected ${n}`:H(s,e,"")}}a("gem.handshake",[{n:"versions",k:"o",fs:[{n:"min",k:"i",lo:1,hi:1e3},{n:"max",k:"i",lo:1,hi:1e3}]},{n:"capabilities",k:"a",o:1,max:64,it:{n:"",k:"s",max:64}},{n:"embedder",k:"s",max:2048,f:"origin"},{n:"unbidden",k:"b",o:1}]);a("gem.handshake.accept",[{n:"v",k:"i",lo:1,hi:1e3},{n:"capabilities",k:"a",o:1,max:64,it:{n:"",k:"s",max:64}}]);a("gem.token",[{n:"token",k:"s",max:4096},{n:"requestId",k:"s",o:1,max:64},{n:"generation",k:"i",lo:0,hi:2147483647},{n:"apiBaseUrl",k:"s",o:1,max:512,f:"url"},{n:"playerId",k:"s",max:64},{n:"gameId",k:"s",max:64},{n:"channel",k:"e",v:["dev","test","release"]},{n:"gameVersion",k:"s",o:1,max:64},{n:"expiresAt",k:"i",lo:0,hi:4102444800},{n:"chainEndsAt",k:"i",lo:0,hi:4102444800},{n:"allowDevTools",k:"b",o:1}]);a("gem.token.denied",[{n:"requestId",k:"s",max:64},{n:"retryable",k:"b"},{n:"retryAfterMs",k:"i",o:1,lo:0,hi:36e5},{n:"reason",k:"e",v:["chain_exhausted","unavailable"]},{n:"correlationId",k:"s",max:64}]);a("gem.player",[{n:"untrusted",k:"o",fs:[{n:"displayName",k:"s",max:64},{n:"displayTag",k:"s",o:1,max:80},{n:"displayHandle",k:"s",max:80}]},{n:"playerId",k:"s",o:1,max:64},{n:"discriminator",k:"s",o:1,max:8},{n:"avatarIconUrl",k:"s",o:1,max:2048,f:"url"},{n:"avatarIconId",k:"s",o:1,max:64},{n:"avatar3dId",k:"s",o:1,max:64},{n:"avatar3dModelUrl",k:"s",o:1,max:2048,f:"url"},{n:"avatar3dIconUrl",k:"s",o:1,max:2048,f:"url"},{n:"avatars3d",k:"a",o:1,max:8,it:{n:"",k:"o",fs:[{n:"family",k:"s",max:32},{n:"id",k:"s",max:64},{n:"modelUrl",k:"s",max:256,f:"url"},{n:"iconUrl",k:"s",max:256,f:"url"}]}},{n:"badges",k:"a",o:1,max:2,it:{n:"",k:"o",fs:[{n:"itemId",k:"s",max:64},{n:"iconUrl",k:"s",max:2048,f:"url"}]}},{n:"displayTag",k:"s",max:8},{n:"avatarUrl",k:"s",o:1,max:2048,f:"url"},{n:"boost",k:"o",o:1,fs:[{n:"multipliers",k:"a",max:8,it:{n:"",k:"o",fs:[{n:"currencyId",k:"s",max:64},{n:"currencySlug",k:"s",max:32},{n:"multiplierBp",k:"i",lo:1e4,hi:1e6}]}},{n:"expiresInDays",k:"i",o:1,lo:1,hi:7}]}]);a("gem.pause",[{n:"paused",k:"b"}]);a("gem.prefs",[{n:"reducedMotion",k:"b"},{n:"muted",k:"b"},{n:"showFrameStats",k:"b",o:1},{n:"locale",k:"s",max:35,f:"bcp47"},{n:"recommended",k:"o",o:1,fs:[{n:"volume",k:"i",lo:0,hi:100},{n:"batterySaver",k:"b"},{n:"keyboardLayout",k:"e",v:["wasd","arrows"]},{n:"gamepadConfirm",k:"e",v:["south","east"]},{n:"vibration",k:"b"},{n:"lookSensitivity",k:"i",o:1,lo:20,hi:400},{n:"gamepadLookSensitivity",k:"i",o:1,lo:20,hi:400},{n:"invertLookY",k:"b",o:1},{n:"touchMovement",k:"s",o:1,max:16,f:"code"},{n:"graphicsQuality",k:"s",o:1,max:16,f:"code"},{n:"graphicsQualityAuto",k:"b",o:1}]}]);a("gem.cohorts",[{n:"cohorts",k:"a",max:8,it:{n:"",k:"o",fs:[{n:"experimentId",k:"s",max:36},{n:"variantKey",k:"s",max:32}]}}]);a("gem.earnAllowanceChanged",[]);a("gem.viewport",[{n:"insets",k:"o",fs:[{n:"top",k:"i",lo:0,hi:4096},{n:"right",k:"i",lo:0,hi:4096},{n:"bottom",k:"i",lo:0,hi:4096},{n:"left",k:"i",lo:0,hi:4096}]},{n:"reserved",k:"a",o:1,max:4,it:{n:"",k:"o",fs:[{n:"x",k:"i",lo:0,hi:16384},{n:"y",k:"i",lo:0,hi:16384},{n:"width",k:"i",lo:0,hi:16384},{n:"height",k:"i",lo:0,hi:16384}]}}]);a("gem.deviceSettings",[{n:"settings",k:"j",o:1}]);a("gem.willTerminate",[{n:"reason",k:"e",v:["grant_expiring","session_ended","navigating","kill_switch"]},{n:"graceMs",k:"i",lo:0,hi:6e4}]);a("gem.roomEvent",[{n:"event",k:"e",v:["updated","match_started","match_ready","match_failed","version_stale"]},{n:"roomId",k:"s",max:64},{n:"matchId",k:"s",o:1,max:64},{n:"version",k:"i",o:1,lo:0,hi:2147483647},{n:"reason",k:"s",o:1,max:64},{n:"platform",k:"e",o:1,v:["universal","mobile"]}]);a("gem.socketState",[{n:"connected",k:"b"},{n:"reason",k:"e",o:1,v:["connecting","dropped","watchdog","terminal"]}]);a("gem.seatedEvent",[{n:"roomId",k:"s",max:64}]);a("gem.autoStartFailedEvent",[{n:"roomId",k:"s",max:64},{n:"code",k:"s",max:64}]);a("gem.ticketEvent",[{n:"event",k:"e",v:["queued","matched","expired","cancelled","failed"]},{n:"ticketId",k:"s",max:64},{n:"partySize",k:"i",o:1,lo:1,hi:64},{n:"queuedAt",k:"i",o:1,lo:0,hi:4102444800},{n:"expiresAt",k:"i",o:1,lo:0,hi:4102444800},{n:"reason",k:"s",o:1,max:64},{n:"roomId",k:"s",o:1,max:64}]);a("gem.signalEvent",[{n:"event",k:"e",v:["hello","offer","answer","ice","peerJoined","peerLeft","migration","matchEnded","error"]},{n:"matchId",k:"s",max:64},{n:"data",k:"j"}]);a("gem.dedicatedEvent",[{n:"event",k:"e",v:["answer","error","matchEnded"]},{n:"matchId",k:"s",max:64},{n:"sdp",k:"s",o:1,max:10240},{n:"sessionId",k:"s",o:1,max:64},{n:"code",k:"s",o:1,max:64},{n:"message",k:"s",o:1,max:256},{n:"reason",k:"s",o:1,max:64}]);a("gem.partyResult",[{n:"requestId",k:"s",max:64},{n:"partyId",k:"s",o:1,max:64}]);a("gem.clusterTarget",[{n:"clusterTargetId",k:"s",max:64},{n:"clusterTargetIds",k:"a",o:1,max:3,it:{n:"",k:"s",max:64}}]);a("gem.devtools",[{n:"action",k:"e",v:["open","close","toggle"]}]);a("gem.screenshot",[{n:"maxWidth",k:"i",lo:1,hi:7680},{n:"maxHeight",k:"i",lo:1,hi:4320}]);a("gem.screenshot.denied",[{n:"reason",k:"e",v:["not_wired","no_source","unsupported","unreadable","tainted","too_large","busy","declined","failed"]},{n:"retryable",k:"b"}]);a("gem.requestContext",[]);a("gem.gameContext",[{n:"context",k:"j"}]);a("gem.signal",[{n:"signal",k:"e",v:["join","offer","answer","ice","migrationAck","hostUnreachable"]},{n:"matchId",k:"s",max:64},{n:"data",k:"j"}]);a("gem.dedicatedOffer",[{n:"matchId",k:"s",max:64},{n:"sdp",k:"s",max:10240},{n:"intent",k:"e",v:["initial","ice_restart","full_reconnect"]}]);a("gem.partyRequest",[{n:"requestId",k:"s",max:64}]);a("gem.ready",[]);a("gem.engaged",[]);a("gem.progress",[{n:"loaded",k:"i",lo:0,hi:1099511627776},{n:"total",k:"i",lo:0,hi:1099511627776}]);a("gem.requestToken",[{n:"requestId",k:"s",max:64},{n:"reason",k:"e",v:["initial","expiring","rejected"]}]);a("gem.requestLocalServer",[{n:"requestId",k:"s",max:64},{n:"gameRoomId",k:"s",max:64}]);a("gem.localServer",[{n:"requestId",k:"s",max:64},{n:"serverId",k:"s",o:1,max:128}]);a("gem.localServer.denied",[{n:"requestId",k:"s",max:64},{n:"retryable",k:"b"},{n:"reason",k:"e",v:["refused","unavailable"]}]);a("gem.exit",[{n:"reason",k:"s",o:1,max:64}]);a("gem.openExternal",[{n:"url",k:"s",max:2048,f:"url"}]);a("gem.requestFullscreen",[{n:"enabled",k:"b"}]);a("gem.audioState",[{n:"muted",k:"b"}]);a("gem.rewardCue",[{n:"currencySlug",k:"s",max:32},{n:"expected",k:"i",o:1,lo:1,hi:1e9},{n:"origin",k:"o",o:1,fs:[{n:"x",k:"i",lo:0,hi:16384},{n:"y",k:"i",lo:0,hi:16384}]}]);a("gem.walletDisplay",[{n:"visible",k:"b"},{n:"currencies",k:"a",o:1,max:8,it:{n:"",k:"s",max:64}},{n:"score",k:"b",o:1}]);a("gem.controlsDeclare",[{n:"uses",k:"o",fs:[{n:"lookSensitivity",k:"s",o:1,max:16,f:"code"},{n:"gamepadLookSensitivity",k:"s",o:1,max:16,f:"code"},{n:"invertLookY",k:"s",o:1,max:16,f:"code"},{n:"touchMovement",k:"s",o:1,max:16,f:"code"}]}]);a("gem.menu",[{n:"settings",k:"b"},{n:"items",k:"a",o:1,max:4,it:{n:"",k:"o",fs:[{n:"id",k:"s",max:32},{n:"label",k:"s",max:40}]}}]);a("gem.menuSelect",[{n:"entry",k:"e",v:["settings","item"]},{n:"id",k:"s",o:1,max:32}]);a("gem.gemCorner",[{n:"corner",k:"e",v:["top-left","top-right","bottom-left","bottom-right"]}]);a("gem.requestShare",[{n:"params",k:"a",max:16,it:{n:"",k:"o",fs:[{n:"key",k:"s",max:64},{n:"value",k:"s",max:512}]}}]);a("gem.requestAvatarPicker",[{n:"tab",k:"e",o:1,v:["2d","3d"]}]);a("gem.vibrate",[{n:"pattern",k:"a",max:99,it:{n:"",k:"i",lo:0,hi:1e4}}]);a("gem.frameStats",[{n:"fps",k:"i",lo:0,hi:1e3},{n:"frameTimeP95Ms",k:"i",lo:0,hi:1e5}]);a("gem.portraitBorders",[{n:"name",k:"s",o:1,max:40}]);a("gem.error",[{n:"code",k:"e",v:["version_mismatch","handshake_timeout","handshake_duplicate","invalid_message","rate_limited","token_unavailable","unsupported","unsupported_capability","internal"]},{n:"message",k:"s",o:1,max:256}]);a("gem.requestPurchase",[{n:"requestId",k:"s",max:64},{n:"purchaseKind",k:"e",v:["item","recipe"]},{n:"targetId",k:"s",max:64},{n:"currencySlug",k:"s",max:32},{n:"quantity",k:"i",o:1,lo:1,hi:10},{n:"catalogId",k:"s",o:1,max:64}]);a("gem.requestAvatar3dPurchase",[{n:"requestId",k:"s",max:64},{n:"itemId",k:"s",max:64},{n:"currencySlug",k:"s",max:32}]);a("gem.purchaseResult",[{n:"requestId",k:"s",max:64},{n:"outcome",k:"e",v:["ok","declined","unavailable"]},{n:"reason",k:"s",o:1,max:64,f:"code"},{n:"purchaseId",k:"s",o:1,max:64}]);a("gem.deviceSettings.put",[{n:"requestId",k:"s",max:64},{n:"settings",k:"j"}]);a("gem.deviceSettings.result",[{n:"requestId",k:"s",max:64},{n:"outcome",k:"e",v:["stored","too_large","unavailable"]}]);a("gem.requestAd",[{n:"requestId",k:"s",max:64},{n:"placement",k:"s",max:32},{n:"format",k:"e",v:["interstitial","rewarded"]}]);a("gem.adResult",[{n:"requestId",k:"s",max:64},{n:"outcome",k:"e",v:["shown","no_ad","unavailable"]}]);a("gem.requestSignIn",[{n:"requestId",k:"s",max:64}]);a("gem.signInResult",[{n:"requestId",k:"s",max:64},{n:"outcome",k:"e",v:["signed_in","declined","unavailable"]}]);a("gem.requestFriendChallenge",[{n:"requestId",k:"s",max:64},{n:"playerId",k:"s",max:64},{n:"template",k:"s",max:64},{n:"params",k:"j",o:1}]);a("gem.friendChallengeResult",[{n:"requestId",k:"s",max:64},{n:"outcome",k:"e",v:["accepted","cancelled","refused","unavailable","rate_limited","invalid"]},{n:"code",k:"s",o:1,max:64},{n:"param",k:"s",o:1,max:64},{n:"channel",k:"s",o:1,max:16},{n:"configVersion",k:"i",o:1,lo:0,hi:9007199254740991},{n:"retryAfterMs",k:"i",o:1,lo:0,hi:864e5},{n:"detail",k:"s",o:1,max:300}]);var R=Object.freeze(W);var le=/^[a-z0-9][a-z0-9_-]{0,39}$/;function de(n){return typeof n=="string"&&le.test(n)}function N(n){if(n===null||de(n))return n;let e=typeof n=="string"?JSON.stringify(n.length>48?`${n.slice(0,48)}\u2026`:n):`a value of type ${typeof n}`;console.warn(`[gem] showPortraitBorders: ${e} is not a border name, so nothing was sent. A name is 1 to 40 of a-z, 0-9, _ and -, starting with a letter or digit, exactly as your store page declares it under media.portrait_borders. Pass null for no art.`);}var E=class{#e;constructor(e){this.#e=e,Object.freeze(this);}toString(){return "[gem: use gem.text.toPlain()]"}toJSON(){return this.toString()}get[Symbol.toStringTag](){return "PlayerText"}static unwrap(e){return e.#e}};function I(n){return new E(n)}var q={now:()=>Date.now(),setTimeout:(n,e)=>setTimeout(n,e),clearTimeout:n=>clearTimeout(n)},v=class{constructor(e=q){this.clock=e;}clock;tokens=new Map;lastRefill=new Map;allow(e){let t=$[e];if(t===void 0)return false;let r=this.clock.now(),s=this.lastRefill.get(e)??r,i=this.tokens.get(e)??t,d=Math.max(0,r-s),o=Math.min(t,i+d*t/6e4);return o<1?(this.tokens.set(e,o),this.lastRefill.set(e,r),false):(this.tokens.set(e,o-1),this.lastRefill.set(e,r),true)}};function A(n,e){return n.toLowerCase()===e.toLowerCase()}function V(n){let e=n.toLowerCase();return e==="localhost"||e.endsWith(".localhost")||e==="[::1]"||e==="::1"?true:/^127(\.\d{1,3}){3}$/.test(e)}function z(n,e){if(typeof e!="string"||e==="")return false;let t,r;try{t=new URL(n),r=new URL(e);}catch{return false}return t.protocol!=="http:"&&t.protocol!=="https:"||r.protocol!=="http:"&&r.protocol!=="https:"||t.username!==""||t.password!==""||t.pathname!=="/"||t.search!==""||t.hash!==""||t.port===""?false:V(t.hostname)&&V(r.hostname)}function Y(n,e){if(n.min>n.max||e.min>e.max)return null;let t=Math.min(n.max,e.max),r=Math.max(n.min,e.min);return t>=r?t:null}function K(n){return Math.min(16384,Math.max(0,Math.round(Number.isFinite(n)?n:0)))}function me(n,e){if(n!==true)return {visible:false};let t=[],r=false;for(let s of Array.isArray(e)?e:[])s==="score"?r=true:typeof s=="string"&&s.length>0&&s.length<=64&&!t.includes(s)&&t.push(s);return !r&&t.length===0?{visible:true}:{visible:true,currencies:t.slice(0,8),score:r}}function ce(n){let e=[];for(let t of Array.isArray(n)?n:[]){if(e.length===4)break;if(typeof t!="object"||t===null)continue;let{id:r,label:s}=t;typeof r!="string"||r.length===0||r.length>32||typeof s!="string"||s.trim().length===0||e.some(i=>i.id===r)||e.push({id:r,label:s.trim().slice(0,40)});}return e.length===0?{settings:false}:{settings:false,items:e}}function J(n,e){return Math.min(e,Math.max(0,Math.round(Number.isFinite(n)?n:0)))}function ue(n){let e=n.untrusted,t=I(e.displayName),r=e.displayTag||e.displayHandle,s=r?I(r):void 0,i=n.discriminator||n.displayTag,d=i&&/^[0-9]{1,8}$/.test(i)?i:void 0,o=n.avatarIconUrl||n.avatarUrl,m=/^[\da-f]{8}(-[\da-f]{4}){3}-[\da-f]{12}$/i,g=n.avatarIconId,p=n.avatar3dId,c={displayName:t,displayHandle:s??t,badges:(n.badges??[]).map(u=>({itemId:u.itemId,iconUrl:u.iconUrl}))};n.playerId&&(c.playerId=n.playerId),d&&(c.discriminator=d),s&&(c.displayTag=s),o&&(c.avatarIconUrl=c.avatarUrl=o),g&&m.test(g)&&(c.avatarIconId=g),p&&m.test(p)&&(c.avatar3dId=p),n.avatar3dModelUrl&&(c.avatar3dModelUrl=n.avatar3dModelUrl),n.avatar3dIconUrl&&(c.avatar3dIconUrl=n.avatar3dIconUrl),n.avatars3d&&(c.avatars3d=n.avatars3d.filter(u=>m.test(u.id)&&/^[a-z][a-z0-9_]*$/.test(u.family)).filter((u,G,O)=>O.findIndex(C=>C.family==u.family)==G).map(({family:u,id:G,modelUrl:O,iconUrl:C})=>({family:u,id:G,modelUrl:O,iconUrl:C})));let y=n.boost,f=(y?.multipliers??[]).map(u=>({currencyId:u.currencyId,currencySlug:u.currencySlug,multiplier:u.multiplierBp/1e4})),S=f.some(u=>u.multiplier>1);return c.boost=S&&y?.expiresInDays?{active:S,multipliers:f,expiresInDays:y.expiresInDays}:{active:S,multipliers:f},c}var ge=1e4,x=class{constructor(e){this.options=e;if(e.expectedSource===void 0||e.expectedSource===null)throw new Error("GemFrame: expectedSource is required and must not be null \u2014 pass window.parent. The handshake transfers the MessagePort, and origin alone does not say WHICH document on that origin sent it.");this.expectedSource=e.expectedSource,this.clock=e.clock??q,this.inbound=new v(this.clock),this.outbound=new v(this.clock);}options;state="waiting";port=null;version=null;peerCapabilities=[];unbidden=false;engagedSent=false;readyPending=false;readySent=false;settleWaiters=[];clock;inbound;outbound;expectedSource;get currentState(){return this.state}get parentCapabilities(){return this.peerCapabilities}parentSupports(e){return this.peerCapabilities.includes(e)}get protocolVersion(){return this.version}get unbiddenLaunch(){return this.unbidden}handleWindowMessage(e){if(e.source!==this.expectedSource)return this.refuse(e,"handshake did not come from the expected embedder window"),false;if(!(this.options.allowedEmbedders.some(o=>A(o,e.origin))||z(e.origin,this.options.selfOrigin)))return this.refuse(e,`embedder '${e.origin}' is not in allowedEmbedders`),this.state==="waiting"&&this.transition("refused"),false;if(this.state==="connected")return this.fail("handshake_duplicate","this document already has a port"),false;if(this.state!=="waiting")return false;let r=R["gem.handshake"]?.(e.data);if(r)return this.refuse(e,`malformed handshake: ${r}`),false;let s=e.data;if(!A(s.embedder,e.origin))return this.refuse(e,`handshake claims embedder '${s.embedder}' but arrived from '${e.origin}'`),false;let i=e.ports?.[0];if(!i)return this.refuse(e,"handshake transferred no MessagePort"),false;let d=Y(k,s.versions);return d===null?(i.onmessage=null,i.postMessage({gem:l,type:"gem.error",code:"version_mismatch",message:`frame supports v${k.min}..v${k.max}`}),i.close(),this.transition("refused"),this.options.onError?.("version_mismatch"),false):(this.port=i,this.version=d,i.onmessage=o=>this.receive(o.data,o.ports??[]),i.start?.(),this.peerCapabilities=s.capabilities??[],this.unbidden=s.unbidden===true,i.postMessage({gem:l,type:"gem.handshake.accept",v:d,...this.options.capabilities===void 0?{}:{capabilities:[...this.options.capabilities]}}),this.transition("connected"),this.readyPending&&(this.readyPending=false,this.ready()),true)}ready(){if(this.state!=="connected"||!this.port){this.readyPending=true;return}if(this.readySent){this.options.onDropped?.("internal","gem.ready was already sent; duplicate suppressed");return}this.readySent=true,this.send({gem:l,type:"gem.ready"});}settled(e=ge){return this.state!=="waiting"?Promise.resolve(this.state):new Promise(t=>{let r=i=>{this.clock.clearTimeout(s),t(i);},s=this.clock.setTimeout(()=>{let i=this.settleWaiters.indexOf(r);i>=0&&this.settleWaiters.splice(i,1),t(this.state);},e);this.settleWaiters.push(r);})}progress(e,t){this.send({gem:l,type:"gem.progress",loaded:e,total:t});}requestToken(e,t){this.send({gem:l,type:"gem.requestToken",requestId:e,reason:t});}requestLocalServer(e,t){return this.parentSupports("localHost")?(this.send({gem:l,type:"gem.requestLocalServer",requestId:e,gameRoomId:t}),true):false}exit(e){this.send(e===void 0?{gem:l,type:"gem.exit"}:{gem:l,type:"gem.exit",reason:e});}openExternal(e){this.send({gem:l,type:"gem.openExternal",url:e});}requestFullscreen(e){this.send({gem:l,type:"gem.requestFullscreen",enabled:e});}reportMuted(e){return this.gated("audioState")?(this.send({gem:l,type:"gem.audioState",muted:e}),true):false}reportEngaged(){return this.engagedSent||!this.gated("engagement")||!this.send({gem:l,type:"gem.engaged"})?false:(this.engagedSent=true,true)}cueReward(e){if(!this.gated("rewardCue"))return false;let t={gem:l,type:"gem.rewardCue",currencySlug:String(e.currencySlug).slice(0,32)};return e.expected!==void 0&&Number.isFinite(e.expected)&&e.expected>=1&&(t.expected=Math.min(1e9,Math.round(e.expected))),e.origin&&(t.origin={x:K(e.origin.x),y:K(e.origin.y)}),this.send(t),true}showPortraitBorders(e){let t=N(e);return t===void 0||!this.gated("portraitBorders")?false:this.send(t===null?{gem:l,type:"gem.portraitBorders"}:{gem:l,type:"gem.portraitBorders",name:t})}setWalletVisible(e,t){return this.gated("walletDisplay")?this.send({gem:l,type:"gem.walletDisplay",...me(e,t?.only)}):false}setMenu(e){return this.gated("gameMenu")?this.send({gem:l,type:"gem.menu",...ce(e)}):false}setGemCorner(e){return this.gated("gemCorner")?this.send({gem:l,type:"gem.gemCorner",corner:e}):false}requestShare(e){return this.gated("share")?this.send({gem:l,type:"gem.requestShare",params:e.map(({key:t,value:r})=>({key:t,value:r}))}):false}requestAvatarPicker(e){return this.gated("avatarPicker")?this.send({gem:l,type:"gem.requestAvatarPicker",...e==="2d"||e==="3d"?{tab:e}:{}}):false}requestVibrate(e){return this.gated("vibration")?this.send({gem:l,type:"gem.vibrate",pattern:[...e]}):false}reportFrameStats(e){return this.gated("frameStats")?(this.send({gem:l,type:"gem.frameStats",fps:J(e.fps,1e3),frameTimeP95Ms:J(e.frameTimeP95Ms,1e5)}),true):false}sendGameContext(e){return this.state!=="connected"?false:(this.send({gem:l,type:"gem.gameContext",context:e}),true)}signal(e,t,r){this.send({gem:l,type:"gem.signal",signal:e,matchId:t,data:r});}dedicatedOffer(e,t,r){this.send({gem:l,type:"gem.dedicatedOffer",matchId:e,sdp:t,intent:r});}requestParty(e){return this.send({gem:l,type:"gem.partyRequest",requestId:e})}requestPurchase(e,t,r,s,i,d){return this.send({gem:l,type:"gem.requestPurchase",requestId:e,purchaseKind:t,targetId:r,currencySlug:s,...i===void 0?{}:{quantity:i},...d===void 0?{}:{catalogId:d}})}requestAvatar3dPurchase(e,t,r){return this.parentSupports("avatar3dPurchases")?this.send({gem:l,type:"gem.requestAvatar3dPurchase",requestId:e,itemId:t,currencySlug:r}):false}putDeviceSettings(e,t){return this.send({gem:l,type:"gem.deviceSettings.put",requestId:e,settings:t})}requestAd(e,t,r){return this.send({gem:l,type:"gem.requestAd",requestId:e,placement:t,format:r})}requestSignIn(e){return this.send({gem:l,type:"gem.requestSignIn",requestId:e})}requestFriendChallenge(e,t,r,s){return this.send({gem:l,type:"gem.requestFriendChallenge",requestId:e,playerId:t,template:r,...s===void 0?{}:{params:s}})}close(){this.port&&(this.port.onmessage=null,this.port.close(),this.port=null),this.state!=="refused"&&this.transition("closed");}transition(e){if(this.state!==e){this.state=e;for(let t of this.settleWaiters.splice(0))t(e);this.options.onStateChange?.(e);}}refuseMalformed(e,t){if(!this.inbound.allow(w)){this.options.onDropped?.(e,t);return}this.fail(e,t);}dropUnknownType(e){this.inbound.allow(w)&&this.options.onDropped?.("unsupported",`ignored unknown message type '${e}'`);}refuse(e,t){e.ports?.[0]?.close?.(),this.inbound.allow(w)&&this.options.onRefused?.(t);}fail(e,t){this.options.onError?.(e,t),this.state==="connected"&&this.port&&this.send({gem:l,type:"gem.error",code:e,...t===void 0?{}:{message:t}});}gated(e){return this.state==="connected"&&this.parentSupports(e)}send(e){if(this.state!=="connected"||!this.port)return this.options.onDropped?.("internal",`dropped ${String(e.type)} before connect`),false;let t=e.type;if(!this.outbound.allow(t))return this.options.onError?.("rate_limited",`frame exceeded its own limit for ${t}`),false;let r=R[t]?.(e);return r?(this.options.onError?.("internal",`refusing to send malformed ${t}: ${r}`),false):(this.port.postMessage(this.version===null?e:{...e,v:this.version}),true)}receive(e,t=[]){let r=false;try{r=this.dispatchInbound(e,t);}finally{r||Q(t);}}dispatchInbound(e,t){if(this.state!=="connected")return false;let r=typeof e=="object"&&e!==null?e.type:void 0;if(typeof r!="string")return this.refuseMalformed("invalid_message","message has no type"),false;let s=R[r];if(!s)return this.dropUnknownType(r),false;if(!this.inbound.allow(r))return this.fail("rate_limited",`parent exceeded the limit for ${r}`),false;let i=U(r);if(i!==void 0&&!this.options.capabilities?.includes(i))return this.fail("unsupported_capability",`${r} requires the '${i}' capability, which this frame did not advertise`),false;let d=s(e);if(d)return this.fail("invalid_message",`${r}: ${d}`),false;let o=e;if(o.v!==this.version)return this.fail("invalid_message",`${r}: expected v ${String(this.version)}`),false;switch(r){case "gem.token":this.options.onToken?.(o);break;case "gem.pause":this.options.onPause?.(o);break;case "gem.menuSelect":this.options.onMenuSelect?.(o);break;case "gem.prefs":this.options.onPrefs?.(o);break;case "gem.cohorts":this.options.onCohorts?.(o);break;case "gem.earnAllowanceChanged":this.options.onEarnAllowanceChanged?.();break;case "gem.viewport":this.options.onViewport?.(o);break;case "gem.willTerminate":this.options.onWillTerminate?.(o);break;case "gem.devtools":this.options.onDevtools?.(o.action);break;case "gem.requestContext":this.options.onRequestContext?.();break;case "gem.screenshot":{let m=t[0];if(!m){this.options.onError?.("invalid_message","gem.screenshot transferred no MessagePort");break}let g={maxWidth:o.maxWidth,maxHeight:o.maxHeight};if(!this.options.onScreenshot){m.close(),this.screenshotDenied("not_wired",false);break}return Q(t.slice(1)),this.options.onScreenshot(g,m,(p,c)=>this.screenshotDenied(p,c)),true}case "gem.token.denied":this.options.onTokenDenied?.(o);break;case "gem.localServer":this.options.onLocalServer?.(o);break;case "gem.localServer.denied":this.options.onLocalServerDenied?.(o);break;case "gem.player":{this.options.onPlayer?.(ue(o));break}case "gem.roomEvent":this.options.onRoomEvent?.(o);break;case "gem.seatedEvent":this.options.onSeatedEvent?.(o);break;case "gem.autoStartFailedEvent":this.options.onAutoStartFailedEvent?.(o);break;case "gem.ticketEvent":this.options.onTicketEvent?.(o);break;case "gem.socketState":this.options.onSocketState?.(o);break;case "gem.signalEvent":this.options.onSignalEvent?.(o);break;case "gem.dedicatedEvent":this.options.onDedicatedEvent?.(o);break;case "gem.clusterTarget":this.options.onClusterTarget?.(o);break;case "gem.partyResult":this.options.onPartyResult?.(o);break;case "gem.purchaseResult":this.options.onPurchaseResult?.(o);break;case "gem.deviceSettings":this.options.onDeviceSettings?.(o);break;case "gem.deviceSettings.result":this.options.onDeviceSettingsResult?.(o);break;case "gem.adResult":this.options.onAdResult?.(o);break;case "gem.signInResult":this.options.onSignInResult?.(o);break;case "gem.friendChallengeResult":this.options.onFriendChallengeResult?.(o);break;case "gem.error":this.options.onError?.(o.code,o.message);break;default:this.fail("unsupported",`no frame handler for '${r}'`);}return false}screenshotDenied(e,t){this.send({gem:l,type:"gem.screenshot.denied",reason:e,retryable:t});}};function Q(n){for(let e of n)try{e?.close?.();}catch{}}_();function pe(n){if((n.expectedSource??window.parent)===window)throw new Error("GemWebSdkBridge.connect: this document is not framed (window.parent === window), so there is no embedder to hand it a port. A game runs inside the Gem Arcade iframe; opening it directly will never complete a handshake.");let e=new x({...n,expectedSource:n.expectedSource??window.parent}),t=r=>{let s=e.handleWindowMessage({data:r.data,origin:r.origin,source:r.source,ports:r.ports});return s&&window.removeEventListener("message",t),s};return window.addEventListener("message",t),M(window,t),e}var X={connect:pe,GemFrame:x,PROTOCOL:l,SUPPORTED_VERSIONS:k};window.GemWebSdkBridge=X;var Dt=X;return Dt;})();
1
+ var GemWebSdkBridgeBundle=(function(){'use strict';var T="GemWebSdkHandshake";function Z(){return typeof document>"u"?void 0:document.readyState}var _=()=>Date.now();function j(t={}){let e=t.win??window,n=e,r=n[T];if(r!==void 0)return r;let s=t.readyState??Z,i=t.now??_,d=[],a=[],m=p=>{let c=p.data;!c||c.type!=="gem.handshake"||(d.length>=4&&(d.shift(),a.shift(),g.dropped+=1),d.push(p),a.push(i()));};e.addEventListener("message",m);let g={events:d,times:a,dropped:0,late:s()==="complete",uninstall(){e.removeEventListener("message",m);}};return n[T]=g,g}function D(t,e,n={}){let r=t[T];if(r===void 0)return null;let s=n.ttlMs??9500,i=n.now??_,d=r.events.splice(0),a=r.times?.splice(0),m=0,g=0,p=false,c=i()-s;for(let y=d.length-1;y>=0;y--){let f=a?.[y];if(f!==void 0&&f<c){g+=1;continue}if(m+=1,e(d[y])===true){p=true;break}}return r.uninstall(),{capture:r,delivered:m,stale:g,accepted:p}}var l="gem-web-bridge",k={min:1,max:1},h=65536,F=8,w=5e3,$=1024;var v=Object.create(null),R="__malformed";var I=Object.create(null),ee=Object.freeze([["gem.asyncOpponents.","asyncOpponents"],["gem.vibration.","vibration"],["gem.viewport.","reservedAreas"],["gem.moments.","moments"]]);function U(t){let e=I[t];if(e!==void 0)return e;for(let[n,r]of ee)if(t.startsWith(n))return r}function ne(t){let e=/^([a-z][a-z0-9+.-]*):\/\/([a-z0-9.-]+|\[[0-9a-f:.]+\])(:([0-9]{1,5}))?$/i.exec(t);return e===null?false:e[4]===void 0||Number(e[4])<=65535}function te(t){let e;try{e=new URL(t);}catch{return false}return e.username!==""||e.password!==""?false:e.protocol==="https:"?true:e.protocol==="http:"&&(e.hostname==="localhost"||e.hostname==="127.0.0.1")}function re(t){return /^[a-z]{2,8}(-[a-z0-9]{1,8})*$/i.test(t)}function oe(t){return /^[a-z_]+$/.test(t)}function E(t,e,n){if(e>F)return `nesting deeper than ${F}`;if(++n.nodes>w)return `more than ${w} values`;if(n.bytes>h)return `over the ${h} byte limit`;if(t==null)return n.bytes+=4,null;let r=typeof t;if(r==="boolean")return n.bytes+=5,null;if(r==="number")return n.bytes+=8,null;if(r==="string")return n.bytes+=t.length*3+2,null;if(r!=="object")return `${r} is not plain data`;let s=t;if(n.seen.has(s))return "a repeated or cyclic object reference";if(n.seen.add(s),Array.isArray(t)){if(t.length>$)return `an array of ${t.length} entries, over the ${$} limit`;n.bytes+=2;for(let a of t){let m=E(a,e+1,n);if(m)return m}return null}let i=Object.getPrototypeOf(t);if(i!==Object.prototype&&i!==null)return "a value that is not a plain object";n.bytes+=2;let d=t;for(let a in d){if(!Object.prototype.hasOwnProperty.call(d,a))continue;if(++n.nodes>w)return `more than ${w} values`;if(n.bytes+=a.length*3+4,n.bytes>h)return `over the ${h} byte limit`;let m=E(d[a],e+1,n);if(m)return m}return null}function ae(t){let e={nodes:0,bytes:0,seen:new Set},n=E(t,0,e);return n?`message contains ${n}`:e.bytes>h?`message is over the ${h} byte limit`:null}var se={origin:[ne,"not a well-formed origin"],url:[te,"not a safe absolute http(s) URL"],bcp47:[re,"not a well-formed BCP 47 tag"],code:[oe,"not a code of lower-case letters and underscores"]};function H(t,e,n){for(let r of e){let s=n===""?r.n:`${n}.${r.n}`,i=t[r.n];if(i==null){if(r.o)continue;return `${s}: required`}let d=W(i,r,s);if(d)return d}return null}function W(t,e,n){switch(e.k){case "s":{if(typeof t!="string")return `${n}: expected string`;if(t.length>e.max)return `${n}: exceeds ${e.max} characters`;if(e.f){let[r,s]=se[e.f];if(!r(t))return `${n}: ${s}`}return null}case "i":return typeof t!="number"||!Number.isInteger(t)?`${n}: expected integer`:t<e.lo||t>e.hi?`${n}: out of range ${e.lo}..${e.hi}`:null;case "b":return typeof t=="boolean"?null:`${n}: expected boolean`;case "e":{let r=e.v;return r.includes(t)?null:`${n}: not one of ${r.join("|")}`}case "o":return typeof t!="object"||t===null||Array.isArray(t)?`${n}: expected object`:H(t,e.fs,n);case "j":return typeof t!="object"||t===null||Array.isArray(t)?`${n}: expected a plain object`:null;case "a":{if(!Array.isArray(t))return `${n}: expected array`;if(t.length>e.max)return `${n}: exceeds ${e.max} items`;let r=e.it,s=`${n}[]`;for(let i of t){if(i==null){if(r.o)continue;return `${s}: required`}let d=W(i,r,s);if(d)return d}return null}default:{let r=e.k;return `${n}: unknown kind ${String(r)}`}}}var B=Object.create(null);function o(t,e,n,r){return v[t]=n,r&&(I[t]=r),B[t]=s=>{let i=ae(s);if(i)return i;if(typeof s!="object"||s===null||Array.isArray(s))return "message: expected object";let d=s;return d.gem!==l?"gem: wrong protocol marker":d.type!==t?`type: expected ${t}`:H(d,e,"")}}o("gem.handshake",[{n:"versions",k:"o",fs:[{n:"min",k:"i",lo:1,hi:1e3},{n:"max",k:"i",lo:1,hi:1e3}]},{n:"capabilities",k:"a",o:1,max:64,it:{n:"",k:"s",max:64}},{n:"embedder",k:"s",max:2048,f:"origin"},{n:"unbidden",k:"b",o:1}],30);o("gem.handshake.accept",[{n:"v",k:"i",lo:1,hi:1e3},{n:"capabilities",k:"a",o:1,max:64,it:{n:"",k:"s",max:64}}],5);o("gem.token",[{n:"token",k:"s",max:4096},{n:"requestId",k:"s",o:1,max:64},{n:"generation",k:"i",lo:0,hi:2147483647},{n:"apiBaseUrl",k:"s",o:1,max:512,f:"url"},{n:"playerId",k:"s",max:64},{n:"gameId",k:"s",max:64},{n:"channel",k:"e",v:["dev","test","release"]},{n:"gameVersion",k:"s",o:1,max:64},{n:"expiresAt",k:"i",lo:0,hi:4102444800},{n:"chainEndsAt",k:"i",lo:0,hi:4102444800},{n:"allowDevTools",k:"b",o:1}],30);o("gem.token.denied",[{n:"requestId",k:"s",max:64},{n:"retryable",k:"b"},{n:"retryAfterMs",k:"i",o:1,lo:0,hi:36e5},{n:"reason",k:"e",v:["chain_exhausted","unavailable"]},{n:"correlationId",k:"s",max:64}],30);o("gem.player",[{n:"untrusted",k:"o",fs:[{n:"displayName",k:"s",max:64},{n:"displayTag",k:"s",o:1,max:80},{n:"displayHandle",k:"s",max:80}]},{n:"playerId",k:"s",o:1,max:64},{n:"discriminator",k:"s",o:1,max:8},{n:"avatarIconUrl",k:"s",o:1,max:2048,f:"url"},{n:"avatarIconId",k:"s",o:1,max:64},{n:"avatar3dId",k:"s",o:1,max:64},{n:"avatar3dModelUrl",k:"s",o:1,max:2048,f:"url"},{n:"avatar3dIconUrl",k:"s",o:1,max:2048,f:"url"},{n:"avatars3d",k:"a",o:1,max:8,it:{n:"",k:"o",fs:[{n:"family",k:"s",max:32},{n:"id",k:"s",max:64},{n:"modelUrl",k:"s",max:256,f:"url"},{n:"iconUrl",k:"s",max:256,f:"url"}]}},{n:"badges",k:"a",o:1,max:2,it:{n:"",k:"o",fs:[{n:"itemId",k:"s",max:64},{n:"iconUrl",k:"s",max:2048,f:"url"}]}},{n:"displayTag",k:"s",max:8},{n:"avatarUrl",k:"s",o:1,max:2048,f:"url"},{n:"boost",k:"o",o:1,fs:[{n:"multipliers",k:"a",max:8,it:{n:"",k:"o",fs:[{n:"currencyId",k:"s",max:64},{n:"currencySlug",k:"s",max:32},{n:"multiplierBp",k:"i",lo:1e4,hi:1e6}]}},{n:"expiresInDays",k:"i",o:1,lo:1,hi:7}]}],12);o("gem.pause",[{n:"paused",k:"b"}],120);o("gem.prefs",[{n:"reducedMotion",k:"b"},{n:"muted",k:"b"},{n:"showFrameStats",k:"b",o:1},{n:"locale",k:"s",max:35,f:"bcp47"},{n:"recommended",k:"o",o:1,fs:[{n:"volume",k:"i",lo:0,hi:100},{n:"batterySaver",k:"b"},{n:"keyboardLayout",k:"e",v:["wasd","arrows"]},{n:"gamepadConfirm",k:"e",v:["south","east"]},{n:"vibration",k:"b"},{n:"lookSensitivity",k:"i",o:1,lo:20,hi:400},{n:"gamepadLookSensitivity",k:"i",o:1,lo:20,hi:400},{n:"invertLookY",k:"b",o:1},{n:"touchMovement",k:"s",o:1,max:16,f:"code"},{n:"graphicsQuality",k:"s",o:1,max:16,f:"code"},{n:"graphicsQualityAuto",k:"b",o:1}]}],60);o("gem.cohorts",[{n:"cohorts",k:"a",max:8,it:{n:"",k:"o",fs:[{n:"experimentId",k:"s",max:36},{n:"variantKey",k:"s",max:32}]}}],12,"cohorts");o("gem.earnAllowanceChanged",[],30,"earnAllowance");o("gem.viewport",[{n:"insets",k:"o",fs:[{n:"top",k:"i",lo:0,hi:4096},{n:"right",k:"i",lo:0,hi:4096},{n:"bottom",k:"i",lo:0,hi:4096},{n:"left",k:"i",lo:0,hi:4096}]},{n:"reserved",k:"a",o:1,max:4,it:{n:"",k:"o",fs:[{n:"x",k:"i",lo:0,hi:16384},{n:"y",k:"i",lo:0,hi:16384},{n:"width",k:"i",lo:0,hi:16384},{n:"height",k:"i",lo:0,hi:16384}]}}],60,"viewport");o("gem.deviceSettings",[{n:"settings",k:"j",o:1}],12,"deviceSettings");o("gem.willTerminate",[{n:"reason",k:"e",v:["grant_expiring","session_ended","navigating","kill_switch"]},{n:"graceMs",k:"i",lo:0,hi:6e4}],10);o("gem.roomEvent",[{n:"event",k:"e",v:["updated","match_started","match_ready","match_failed","version_stale"]},{n:"roomId",k:"s",max:64},{n:"matchId",k:"s",o:1,max:64},{n:"version",k:"i",o:1,lo:0,hi:2147483647},{n:"reason",k:"s",o:1,max:64},{n:"platform",k:"e",o:1,v:["universal","mobile"]}],120,"rooms");o("gem.socketState",[{n:"connected",k:"b"},{n:"reason",k:"e",o:1,v:["connecting","dropped","watchdog","terminal"]}],12,"socketState");o("gem.seatedEvent",[{n:"roomId",k:"s",max:64}],60,"partySeating");o("gem.autoStartFailedEvent",[{n:"roomId",k:"s",max:64},{n:"code",k:"s",max:64}],30,"autoStartFailure");o("gem.ticketEvent",[{n:"event",k:"e",v:["queued","matched","expired","cancelled","failed"]},{n:"ticketId",k:"s",max:64},{n:"partySize",k:"i",o:1,lo:1,hi:64},{n:"queuedAt",k:"i",o:1,lo:0,hi:4102444800},{n:"expiresAt",k:"i",o:1,lo:0,hi:4102444800},{n:"reason",k:"s",o:1,max:64},{n:"roomId",k:"s",o:1,max:64}],60,"ticketEvents");o("gem.signalEvent",[{n:"event",k:"e",v:["hello","offer","answer","ice","peerJoined","peerLeft","migration","matchEnded","error"]},{n:"matchId",k:"s",max:64},{n:"data",k:"j"}],1800,"p2p");o("gem.dedicatedEvent",[{n:"event",k:"e",v:["answer","error","matchEnded"]},{n:"matchId",k:"s",max:64},{n:"sdp",k:"s",o:1,max:10240},{n:"sessionId",k:"s",o:1,max:64},{n:"code",k:"s",o:1,max:64},{n:"message",k:"s",o:1,max:256},{n:"reason",k:"s",o:1,max:64}],120,"dedicated");o("gem.partyResult",[{n:"requestId",k:"s",max:64},{n:"partyId",k:"s",o:1,max:64}],30,"parties");o("gem.clusterTarget",[{n:"clusterTargetId",k:"s",max:64},{n:"clusterTargetIds",k:"a",o:1,max:3,it:{n:"",k:"s",max:64}}],12,"clusterTarget");o("gem.devtools",[{n:"action",k:"e",v:["open","close","toggle"]}],30,"devtools");o("gem.screenshot",[{n:"maxWidth",k:"i",lo:1,hi:7680},{n:"maxHeight",k:"i",lo:1,hi:4320}],6,"screenshot");o("gem.screenshot.denied",[{n:"reason",k:"e",v:["not_wired","no_source","unsupported","unreadable","tainted","too_large","busy","declined","failed"]},{n:"retryable",k:"b"}],12,"screenshot");o("gem.requestContext",[],12,"feedbackContext");o("gem.gameContext",[{n:"context",k:"j"}],12,"feedbackContext");o("gem.signal",[{n:"signal",k:"e",v:["join","offer","answer","ice","migrationAck","hostUnreachable"]},{n:"matchId",k:"s",max:64},{n:"data",k:"j"}],1200,"p2p");o("gem.dedicatedOffer",[{n:"matchId",k:"s",max:64},{n:"sdp",k:"s",max:10240},{n:"intent",k:"e",v:["initial","ice_restart","full_reconnect"]}],60,"dedicated");o("gem.partyRequest",[{n:"requestId",k:"s",max:64}],12,"parties");o("gem.ready",[],5);o("gem.engaged",[],5,"engagement");o("gem.progress",[{n:"loaded",k:"i",lo:0,hi:1099511627776},{n:"total",k:"i",lo:0,hi:1099511627776}],600);o("gem.requestToken",[{n:"requestId",k:"s",max:64},{n:"reason",k:"e",v:["initial","expiring","rejected"]}],12);o("gem.requestLocalServer",[{n:"requestId",k:"s",max:64},{n:"gameRoomId",k:"s",max:64}],6,"localHost");o("gem.localServer",[{n:"requestId",k:"s",max:64},{n:"serverId",k:"s",o:1,max:128}],30,"localHost");o("gem.localServer.denied",[{n:"requestId",k:"s",max:64},{n:"retryable",k:"b"},{n:"reason",k:"e",v:["refused","unavailable"]}],30,"localHost");o("gem.exit",[{n:"reason",k:"s",o:1,max:64}],5);o("gem.openExternal",[{n:"url",k:"s",max:2048,f:"url"}],6);o("gem.requestFullscreen",[{n:"enabled",k:"b"}],30);o("gem.audioState",[{n:"muted",k:"b"}],120,"audioState");o("gem.rewardCue",[{n:"currencySlug",k:"s",max:32},{n:"expected",k:"i",o:1,lo:1,hi:1e9},{n:"origin",k:"o",o:1,fs:[{n:"x",k:"i",lo:0,hi:16384},{n:"y",k:"i",lo:0,hi:16384}]}],60,"rewardCue");o("gem.walletDisplay",[{n:"visible",k:"b"},{n:"currencies",k:"a",o:1,max:8,it:{n:"",k:"s",max:64}},{n:"score",k:"b",o:1}],60,"walletDisplay");o("gem.controlsDeclare",[{n:"uses",k:"o",fs:[{n:"lookSensitivity",k:"s",o:1,max:16,f:"code"},{n:"gamepadLookSensitivity",k:"s",o:1,max:16,f:"code"},{n:"invertLookY",k:"s",o:1,max:16,f:"code"},{n:"touchMovement",k:"s",o:1,max:16,f:"code"}]}],60,"controls");o("gem.menu",[{n:"settings",k:"b"},{n:"items",k:"a",o:1,max:4,it:{n:"",k:"o",fs:[{n:"id",k:"s",max:32},{n:"label",k:"s",max:40}]}}],60,"gameMenu");o("gem.menuSelect",[{n:"entry",k:"e",v:["settings","item"]},{n:"id",k:"s",o:1,max:32}],60,"gameMenu");o("gem.gemCorner",[{n:"corner",k:"e",v:["top-left","top-right","bottom-left","bottom-right"]}],12,"gemCorner");o("gem.requestShare",[{n:"params",k:"a",max:16,it:{n:"",k:"o",fs:[{n:"key",k:"s",max:64},{n:"value",k:"s",max:512}]}}],6,"share");o("gem.requestAvatarPicker",[{n:"tab",k:"e",o:1,v:["2d","3d"]}],6,"avatarPicker");o("gem.vibrate",[{n:"pattern",k:"a",max:99,it:{n:"",k:"i",lo:0,hi:1e4}}],600,"vibration");o("gem.frameStats",[{n:"fps",k:"i",lo:0,hi:1e3},{n:"frameTimeP95Ms",k:"i",lo:0,hi:1e5}],120,"frameStats");o("gem.portraitBorders",[{n:"name",k:"s",o:1,max:40}],60,"portraitBorders");o("gem.error",[{n:"code",k:"e",v:["version_mismatch","handshake_timeout","handshake_duplicate","invalid_message","rate_limited","token_unavailable","unsupported","unsupported_capability","internal"]},{n:"message",k:"s",o:1,max:256}],60);o("gem.requestPurchase",[{n:"requestId",k:"s",max:64},{n:"purchaseKind",k:"e",v:["item","recipe"]},{n:"targetId",k:"s",max:64},{n:"currencySlug",k:"s",max:32},{n:"quantity",k:"i",o:1,lo:1,hi:10},{n:"catalogId",k:"s",o:1,max:64}],12,"purchases");o("gem.requestAvatar3dPurchase",[{n:"requestId",k:"s",max:64},{n:"itemId",k:"s",max:64},{n:"currencySlug",k:"s",max:32}],12,"avatar3dPurchases");o("gem.purchaseResult",[{n:"requestId",k:"s",max:64},{n:"outcome",k:"e",v:["ok","declined","unavailable"]},{n:"reason",k:"s",o:1,max:64,f:"code"},{n:"purchaseId",k:"s",o:1,max:64}],30,"purchases");o("gem.deviceSettings.put",[{n:"requestId",k:"s",max:64},{n:"settings",k:"j"}],30,"deviceSettings");o("gem.deviceSettings.result",[{n:"requestId",k:"s",max:64},{n:"outcome",k:"e",v:["stored","too_large","unavailable"]}],30,"deviceSettings");o("gem.requestAd",[{n:"requestId",k:"s",max:64},{n:"placement",k:"s",max:32},{n:"format",k:"e",v:["interstitial","rewarded"]}],6,"ads");o("gem.adResult",[{n:"requestId",k:"s",max:64},{n:"outcome",k:"e",v:["shown","no_ad","unavailable"]}],12,"ads");o("gem.signalMoment",[{n:"requestId",k:"s",max:64},{n:"kind",k:"e",v:["level_end","run_end","match_end","menu_return","other_break"]},{n:"placement",k:"s",o:1,max:32}],6,"moments");o("gem.momentResult",[{n:"requestId",k:"s",max:64},{n:"shown",k:"b"}],12,"moments");o("gem.requestSignIn",[{n:"requestId",k:"s",max:64}],6,"signIn");o("gem.signInResult",[{n:"requestId",k:"s",max:64},{n:"outcome",k:"e",v:["signed_in","declined","unavailable"]}],12,"signIn");o("gem.requestFriendChallenge",[{n:"requestId",k:"s",max:64},{n:"playerId",k:"s",max:64},{n:"template",k:"s",max:64},{n:"params",k:"j",o:1}],12,"friendChallenges");o("gem.friendChallengeResult",[{n:"requestId",k:"s",max:64},{n:"outcome",k:"e",v:["accepted","cancelled","refused","unavailable","rate_limited","invalid"]},{n:"code",k:"s",o:1,max:64},{n:"param",k:"s",o:1,max:64},{n:"channel",k:"s",o:1,max:16},{n:"configVersion",k:"i",o:1,lo:0,hi:9007199254740991},{n:"retryAfterMs",k:"i",o:1,lo:0,hi:864e5},{n:"detail",k:"s",o:1,max:300}],30,"friendChallenges");var S=Object.freeze(B);v.__malformed=60;Object.freeze(v);Object.freeze(I);var ie=/^[a-z0-9][a-z0-9_-]{0,39}$/;function le(t){return typeof t=="string"&&ie.test(t)}function N(t){if(t===null||le(t))return t;let e=typeof t=="string"?JSON.stringify(t.length>48?`${t.slice(0,48)}\u2026`:t):`a value of type ${typeof t}`;console.warn(`[gem] showPortraitBorders: ${e} is not a border name, so nothing was sent. A name is 1 to 40 of a-z, 0-9, _ and -, starting with a letter or digit, exactly as your store page declares it under media.portrait_borders. Pass null for no art.`);}var q=class{#e;constructor(e){this.#e=e,Object.freeze(this);}toString(){return "[gem: use gem.text.toPlain()]"}toJSON(){return this.toString()}get[Symbol.toStringTag](){return "PlayerText"}static unwrap(e){return e.#e}};function L(t){return new q(t)}var A={now:()=>Date.now(),setTimeout:(t,e)=>setTimeout(t,e),clearTimeout:t=>clearTimeout(t)},x=class{constructor(e=A){this.clock=e;}clock;tokens=new Map;lastRefill=new Map;allow(e){let n=v[e];if(n===void 0)return false;let r=this.clock.now(),s=this.lastRefill.get(e)??r,i=this.tokens.get(e)??n,d=Math.max(0,r-s),a=Math.min(n,i+d*n/6e4);return a<1?(this.tokens.set(e,a),this.lastRefill.set(e,r),false):(this.tokens.set(e,a-1),this.lastRefill.set(e,r),true)}};function M(t,e){return t.toLowerCase()===e.toLowerCase()}function V(t){let e=t.toLowerCase();return e==="localhost"||e.endsWith(".localhost")||e==="[::1]"||e==="::1"?true:/^127(\.\d{1,3}){3}$/.test(e)}function z(t,e){if(typeof e!="string"||e==="")return false;let n,r;try{n=new URL(t),r=new URL(e);}catch{return false}return n.protocol!=="http:"&&n.protocol!=="https:"||r.protocol!=="http:"&&r.protocol!=="https:"||n.username!==""||n.password!==""||n.pathname!=="/"||n.search!==""||n.hash!==""||n.port===""?false:V(n.hostname)&&V(r.hostname)}function Y(t,e){if(t.min>t.max||e.min>e.max)return null;let n=Math.min(t.max,e.max),r=Math.max(t.min,e.min);return n>=r?n:null}function K(t){return Math.min(16384,Math.max(0,Math.round(Number.isFinite(t)?t:0)))}function de(t,e){if(t!==true)return {visible:false};let n=[],r=false;for(let s of Array.isArray(e)?e:[])s==="score"?r=true:typeof s=="string"&&s.length>0&&s.length<=64&&!n.includes(s)&&n.push(s);return !r&&n.length===0?{visible:true}:{visible:true,currencies:n.slice(0,8),score:r}}function me(t){let e=[];for(let n of Array.isArray(t)?t:[]){if(e.length===4)break;if(typeof n!="object"||n===null)continue;let{id:r,label:s}=n;typeof r!="string"||r.length===0||r.length>32||typeof s!="string"||s.trim().length===0||e.some(i=>i.id===r)||e.push({id:r,label:s.trim().slice(0,40)});}return e.length===0?{settings:false}:{settings:false,items:e}}function J(t,e){return Math.min(e,Math.max(0,Math.round(Number.isFinite(t)?t:0)))}function ce(t){let e=t.untrusted,n=L(e.displayName),r=e.displayTag||e.displayHandle,s=r?L(r):void 0,i=t.discriminator||t.displayTag,d=i&&/^[0-9]{1,8}$/.test(i)?i:void 0,a=t.avatarIconUrl||t.avatarUrl,m=/^[\da-f]{8}(-[\da-f]{4}){3}-[\da-f]{12}$/i,g=t.avatarIconId,p=t.avatar3dId,c={displayName:n,displayHandle:s??n,badges:(t.badges??[]).map(u=>({itemId:u.itemId,iconUrl:u.iconUrl}))};t.playerId&&(c.playerId=t.playerId),d&&(c.discriminator=d),s&&(c.displayTag=s),a&&(c.avatarIconUrl=c.avatarUrl=a),g&&m.test(g)&&(c.avatarIconId=g),p&&m.test(p)&&(c.avatar3dId=p),t.avatar3dModelUrl&&(c.avatar3dModelUrl=t.avatar3dModelUrl),t.avatar3dIconUrl&&(c.avatar3dIconUrl=t.avatar3dIconUrl),t.avatars3d&&(c.avatars3d=t.avatars3d.filter(u=>m.test(u.id)&&/^[a-z][a-z0-9_]*$/.test(u.family)).filter((u,O,C)=>C.findIndex(P=>P.family==u.family)==O).map(({family:u,id:O,modelUrl:C,iconUrl:P})=>({family:u,id:O,modelUrl:C,iconUrl:P})));let y=t.boost,f=(y?.multipliers??[]).map(u=>({currencyId:u.currencyId,currencySlug:u.currencySlug,multiplier:u.multiplierBp/1e4})),G=f.some(u=>u.multiplier>1);return c.boost=G&&y?.expiresInDays?{active:G,multipliers:f,expiresInDays:y.expiresInDays}:{active:G,multipliers:f},c}var ue=1e4,b=class{constructor(e){this.options=e;if(e.expectedSource===void 0||e.expectedSource===null)throw new Error("GemFrame: expectedSource is required and must not be null \u2014 pass window.parent. The handshake transfers the MessagePort, and origin alone does not say WHICH document on that origin sent it.");this.expectedSource=e.expectedSource,this.clock=e.clock??A,this.inbound=new x(this.clock),this.outbound=new x(this.clock);}options;state="waiting";port=null;version=null;peerCapabilities=[];unbidden=false;engagedSent=false;readyPending=false;readySent=false;settleWaiters=[];clock;inbound;outbound;expectedSource;get currentState(){return this.state}get parentCapabilities(){return this.peerCapabilities}parentSupports(e){return this.peerCapabilities.includes(e)}get protocolVersion(){return this.version}get unbiddenLaunch(){return this.unbidden}handleWindowMessage(e){if(e.source!==this.expectedSource)return this.refuse(e,"handshake did not come from the expected embedder window"),false;if(!(this.options.allowedEmbedders.some(a=>M(a,e.origin))||z(e.origin,this.options.selfOrigin)))return this.refuse(e,`embedder '${e.origin}' is not in allowedEmbedders`),this.state==="waiting"&&this.transition("refused"),false;if(this.state==="connected")return this.fail("handshake_duplicate","this document already has a port"),false;if(this.state!=="waiting")return false;let r=S["gem.handshake"]?.(e.data);if(r)return this.refuse(e,`malformed handshake: ${r}`),false;let s=e.data;if(!M(s.embedder,e.origin))return this.refuse(e,`handshake claims embedder '${s.embedder}' but arrived from '${e.origin}'`),false;let i=e.ports?.[0];if(!i)return this.refuse(e,"handshake transferred no MessagePort"),false;let d=Y(k,s.versions);return d===null?(i.onmessage=null,i.postMessage({gem:l,type:"gem.error",code:"version_mismatch",message:`frame supports v${k.min}..v${k.max}`}),i.close(),this.transition("refused"),this.options.onError?.("version_mismatch"),false):(this.port=i,this.version=d,i.onmessage=a=>this.receive(a.data,a.ports??[]),i.start?.(),this.peerCapabilities=s.capabilities??[],this.unbidden=s.unbidden===true,i.postMessage({gem:l,type:"gem.handshake.accept",v:d,...this.options.capabilities===void 0?{}:{capabilities:[...this.options.capabilities]}}),this.transition("connected"),this.readyPending&&(this.readyPending=false,this.ready()),true)}ready(){if(this.state!=="connected"||!this.port){this.readyPending=true;return}if(this.readySent){this.options.onDropped?.("internal","gem.ready was already sent; duplicate suppressed");return}this.readySent=true,this.send({gem:l,type:"gem.ready"});}settled(e=ue){return this.state!=="waiting"?Promise.resolve(this.state):new Promise(n=>{let r=i=>{this.clock.clearTimeout(s),n(i);},s=this.clock.setTimeout(()=>{let i=this.settleWaiters.indexOf(r);i>=0&&this.settleWaiters.splice(i,1),n(this.state);},e);this.settleWaiters.push(r);})}progress(e,n){this.send({gem:l,type:"gem.progress",loaded:e,total:n});}requestToken(e,n){this.send({gem:l,type:"gem.requestToken",requestId:e,reason:n});}requestLocalServer(e,n){return this.parentSupports("localHost")?(this.send({gem:l,type:"gem.requestLocalServer",requestId:e,gameRoomId:n}),true):false}exit(e){this.send(e===void 0?{gem:l,type:"gem.exit"}:{gem:l,type:"gem.exit",reason:e});}openExternal(e){this.send({gem:l,type:"gem.openExternal",url:e});}requestFullscreen(e){this.send({gem:l,type:"gem.requestFullscreen",enabled:e});}reportMuted(e){return this.gated("audioState")?(this.send({gem:l,type:"gem.audioState",muted:e}),true):false}reportEngaged(){return this.engagedSent||!this.gated("engagement")||!this.send({gem:l,type:"gem.engaged"})?false:(this.engagedSent=true,true)}cueReward(e){if(!this.gated("rewardCue"))return false;let n={gem:l,type:"gem.rewardCue",currencySlug:String(e.currencySlug).slice(0,32)};return e.expected!==void 0&&Number.isFinite(e.expected)&&e.expected>=1&&(n.expected=Math.min(1e9,Math.round(e.expected))),e.origin&&(n.origin={x:K(e.origin.x),y:K(e.origin.y)}),this.send(n),true}showPortraitBorders(e){let n=N(e);return n===void 0||!this.gated("portraitBorders")?false:this.send(n===null?{gem:l,type:"gem.portraitBorders"}:{gem:l,type:"gem.portraitBorders",name:n})}setWalletVisible(e,n){return this.gated("walletDisplay")?this.send({gem:l,type:"gem.walletDisplay",...de(e,n?.only)}):false}setMenu(e){return this.gated("gameMenu")?this.send({gem:l,type:"gem.menu",...me(e)}):false}setGemCorner(e){return this.gated("gemCorner")?this.send({gem:l,type:"gem.gemCorner",corner:e}):false}requestShare(e){return this.gated("share")?this.send({gem:l,type:"gem.requestShare",params:e.map(({key:n,value:r})=>({key:n,value:r}))}):false}requestAvatarPicker(e){return this.gated("avatarPicker")?this.send({gem:l,type:"gem.requestAvatarPicker",...e==="2d"||e==="3d"?{tab:e}:{}}):false}requestVibrate(e){return this.gated("vibration")?this.send({gem:l,type:"gem.vibrate",pattern:[...e]}):false}reportFrameStats(e){return this.gated("frameStats")?(this.send({gem:l,type:"gem.frameStats",fps:J(e.fps,1e3),frameTimeP95Ms:J(e.frameTimeP95Ms,1e5)}),true):false}sendGameContext(e){return this.state!=="connected"?false:(this.send({gem:l,type:"gem.gameContext",context:e}),true)}signal(e,n,r){this.send({gem:l,type:"gem.signal",signal:e,matchId:n,data:r});}dedicatedOffer(e,n,r){this.send({gem:l,type:"gem.dedicatedOffer",matchId:e,sdp:n,intent:r});}requestParty(e){return this.send({gem:l,type:"gem.partyRequest",requestId:e})}requestPurchase(e,n,r,s,i,d){return this.send({gem:l,type:"gem.requestPurchase",requestId:e,purchaseKind:n,targetId:r,currencySlug:s,...i===void 0?{}:{quantity:i},...d===void 0?{}:{catalogId:d}})}requestAvatar3dPurchase(e,n,r){return this.parentSupports("avatar3dPurchases")?this.send({gem:l,type:"gem.requestAvatar3dPurchase",requestId:e,itemId:n,currencySlug:r}):false}putDeviceSettings(e,n){return this.send({gem:l,type:"gem.deviceSettings.put",requestId:e,settings:n})}requestAd(e,n,r){return this.send({gem:l,type:"gem.requestAd",requestId:e,placement:n,format:r})}signalMoment(e,n,r){return this.send({gem:l,type:"gem.signalMoment",requestId:e,kind:n,...r===void 0?{}:{placement:r}})}readyCalled(){return this.readySent||this.readyPending}requestSignIn(e){return this.send({gem:l,type:"gem.requestSignIn",requestId:e})}requestFriendChallenge(e,n,r,s){return this.send({gem:l,type:"gem.requestFriendChallenge",requestId:e,playerId:n,template:r,...s===void 0?{}:{params:s}})}close(){this.port&&(this.port.onmessage=null,this.port.close(),this.port=null),this.state!=="refused"&&this.transition("closed");}transition(e){if(this.state!==e){this.state=e;for(let n of this.settleWaiters.splice(0))n(e);this.options.onStateChange?.(e);}}refuseMalformed(e,n){if(!this.inbound.allow(R)){this.options.onDropped?.(e,n);return}this.fail(e,n);}dropUnknownType(e){this.inbound.allow(R)&&this.options.onDropped?.("unsupported",`ignored unknown message type '${e}'`);}refuse(e,n){e.ports?.[0]?.close?.(),this.inbound.allow(R)&&this.options.onRefused?.(n);}fail(e,n){this.options.onError?.(e,n),this.state==="connected"&&this.port&&this.send({gem:l,type:"gem.error",code:e,...n===void 0?{}:{message:n}});}gated(e){return this.state==="connected"&&this.parentSupports(e)}send(e){if(this.state!=="connected"||!this.port)return this.options.onDropped?.("internal",`dropped ${String(e.type)} before connect`),false;let n=e.type;if(!this.outbound.allow(n))return this.options.onError?.("rate_limited",`frame exceeded its own limit for ${n}`),false;let r=S[n]?.(e);return r?(this.options.onError?.("internal",`refusing to send malformed ${n}: ${r}`),false):(this.port.postMessage(this.version===null?e:{...e,v:this.version}),true)}receive(e,n=[]){let r=false;try{r=this.dispatchInbound(e,n);}finally{r||Q(n);}}dispatchInbound(e,n){if(this.state!=="connected")return false;let r=typeof e=="object"&&e!==null?e.type:void 0;if(typeof r!="string")return this.refuseMalformed("invalid_message","message has no type"),false;let s=S[r];if(!s)return this.dropUnknownType(r),false;if(!this.inbound.allow(r))return this.fail("rate_limited",`parent exceeded the limit for ${r}`),false;let i=U(r);if(i!==void 0&&!this.options.capabilities?.includes(i))return this.fail("unsupported_capability",`${r} requires the '${i}' capability, which this frame did not advertise`),false;let d=s(e);if(d)return this.fail("invalid_message",`${r}: ${d}`),false;let a=e;if(a.v!==this.version)return this.fail("invalid_message",`${r}: expected v ${String(this.version)}`),false;switch(r){case "gem.token":this.options.onToken?.(a);break;case "gem.pause":this.options.onPause?.(a);break;case "gem.menuSelect":this.options.onMenuSelect?.(a);break;case "gem.prefs":this.options.onPrefs?.(a);break;case "gem.cohorts":this.options.onCohorts?.(a);break;case "gem.earnAllowanceChanged":this.options.onEarnAllowanceChanged?.();break;case "gem.viewport":this.options.onViewport?.(a);break;case "gem.willTerminate":this.options.onWillTerminate?.(a);break;case "gem.devtools":this.options.onDevtools?.(a.action);break;case "gem.requestContext":this.options.onRequestContext?.();break;case "gem.screenshot":{let m=n[0];if(!m){this.options.onError?.("invalid_message","gem.screenshot transferred no MessagePort");break}let g={maxWidth:a.maxWidth,maxHeight:a.maxHeight};if(!this.options.onScreenshot){m.close(),this.screenshotDenied("not_wired",false);break}return Q(n.slice(1)),this.options.onScreenshot(g,m,(p,c)=>this.screenshotDenied(p,c)),true}case "gem.token.denied":this.options.onTokenDenied?.(a);break;case "gem.localServer":this.options.onLocalServer?.(a);break;case "gem.localServer.denied":this.options.onLocalServerDenied?.(a);break;case "gem.player":{this.options.onPlayer?.(ce(a));break}case "gem.roomEvent":this.options.onRoomEvent?.(a);break;case "gem.seatedEvent":this.options.onSeatedEvent?.(a);break;case "gem.autoStartFailedEvent":this.options.onAutoStartFailedEvent?.(a);break;case "gem.ticketEvent":this.options.onTicketEvent?.(a);break;case "gem.socketState":this.options.onSocketState?.(a);break;case "gem.signalEvent":this.options.onSignalEvent?.(a);break;case "gem.dedicatedEvent":this.options.onDedicatedEvent?.(a);break;case "gem.clusterTarget":this.options.onClusterTarget?.(a);break;case "gem.partyResult":this.options.onPartyResult?.(a);break;case "gem.purchaseResult":this.options.onPurchaseResult?.(a);break;case "gem.deviceSettings":this.options.onDeviceSettings?.(a);break;case "gem.deviceSettings.result":this.options.onDeviceSettingsResult?.(a);break;case "gem.adResult":this.options.onAdResult?.(a);break;case "gem.momentResult":this.options.onMomentResult?.(a);break;case "gem.signInResult":this.options.onSignInResult?.(a);break;case "gem.friendChallengeResult":this.options.onFriendChallengeResult?.(a);break;case "gem.error":this.options.onError?.(a.code,a.message);break;default:this.fail("unsupported",`no frame handler for '${r}'`);}return false}screenshotDenied(e,n){this.send({gem:l,type:"gem.screenshot.denied",reason:e,retryable:n});}};function Q(t){for(let e of t)try{e?.close?.();}catch{}}j();function ge(t){if((t.expectedSource??window.parent)===window)throw new Error("GemWebSdkBridge.connect: this document is not framed (window.parent === window), so there is no embedder to hand it a port. A game runs inside the Gem Arcade iframe; opening it directly will never complete a handshake.");let e=new b({...t,expectedSource:t.expectedSource??window.parent}),n=r=>{let s=e.handleWindowMessage({data:r.data,origin:r.origin,source:r.source,ports:r.ports});return s&&window.removeEventListener("message",n),s};return window.addEventListener("message",n),D(window,n),e}var X={connect:ge,GemFrame:b,PROTOCOL:l,SUPPORTED_VERSIONS:k};window.GemWebSdkBridge=X;var $n=X;return $n;})();