@indiegems/gem-web-sdk 9.1.4 → 10.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -16,6 +16,32 @@ 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
+ ## 10.1.0
20
+
21
+ Upgrading from 10.0.0. Impact: required.
22
+
23
+ ### Rebuild
24
+
25
+ - The host-side method for sending preferences now accepts an optional recommended object with the five default settings. Existing calls remain valid, so recompiling is enough. Pass the new field only if your test host should simulate the Arcade's recommended defaults.
26
+
27
+ ### New capability
28
+
29
+ - GemPrefs now carries an optional recommended field holding the player's Arcade-wide defaults as advice: volume from 0 to 100, battery saver, keyboard layout (wasd or arrows), gamepad confirm button (south or east) and vibration. It is null when the Arcade does not send it. Changes arrive through the existing preferences callback, and the latest value is always available on the current preferences. Use these values as starting points when the player has no saved choice in your game, and never overwrite a choice the player made in your own settings. Muted, reduced motion and frame stats stay where they were.
30
+ - A new GemRecommendedSettings type describes the recommended defaults object. You can use it to type your own code that reads or stores the recommended values. The object is frozen, so copy values into your own settings rather than modifying it.
31
+
32
+ ## 10.0.0
33
+
34
+ Upgrading from 9.1.4. Impact: required.
35
+
36
+ ### Rebuild
37
+
38
+ - The OrderSource type now accepts two more values, test_account_provision and developer_grant. Recompile your game. If your code handles order sources in an exhaustive switch or a lookup table typed by OrderSource, add handling for both new values, or the build may fail to compile.
39
+
40
+ ### New capability
41
+
42
+ - A game can now put a player in a matchmaking queue for a mode that needs a formed lobby. Call RoomManager.queueForMatch with the template slugs you want. It returns a MatchTicket whose outcome settles once and whose cancel method leaves the queue. When the platform finds a match it creates the room, seats everyone and starts the match, and you follow it with the same code you use for any joined room. Options are described by QueueForMatchOptions. Ticket endings are described by MatchTicketOutcome, and the waiting state by MatchTicketStatus. RoomManager.currentTicket exposes the ticket the player is waiting on. The SDK keeps the ticket alive by itself, cancels it when the tab closes, and lets a player queue from inside a room. After a match the player leaves the room they queued from when the tab closes.
43
+ - The lower-level rooms API now has createTicket, heartbeatTicket and cancelTicket calls for working with matchmaking tickets directly. Most games should use RoomManager.queueForMatch, which sends the heartbeats and cancellation for you.
44
+
19
45
  ## 9.1.4
20
46
 
21
47
  Upgrading from 9.1.3. Impact: none.
@@ -168,7 +168,7 @@ type BucketConfig = Boundary & {
168
168
  type BucketResetInterval = "never" | "daily" | "weekly" | "monthly";
169
169
  type EntityType = "player" | "character";
170
170
  type ItemCategory = "cosmetic" | "progression";
171
- type OrderSource = "real_money_purchase" | "real_money_refund" | "full_game_purchase" | "full_game_refund" | "platform_purchase" | "reward" | "admin" | "system" | "promo" | "game_consume" | "play" | "recipe" | "transfer" | "platform_funded_game_inventory_purchase" | "earning_reset";
171
+ type OrderSource = "real_money_purchase" | "real_money_refund" | "full_game_purchase" | "full_game_refund" | "platform_purchase" | "reward" | "admin" | "system" | "promo" | "game_consume" | "play" | "recipe" | "transfer" | "platform_funded_game_inventory_purchase" | "earning_reset" | "test_account_provision" | "developer_grant";
172
172
  type PlatformPrice = {
173
173
  "platform_currency_id": string;
174
174
  "price": number;
package/dist/game.d.ts CHANGED
@@ -147,6 +147,11 @@ type AffixSelection = {
147
147
  "pool": AffixPoolRef;
148
148
  "respect_groups"?: boolean;
149
149
  };
150
+ type BackfillPolicy = "fill_existing_first" | "prefer_new_match";
151
+ type BackfillSettings = {
152
+ "enabled": boolean;
153
+ "policy"?: BackfillPolicy;
154
+ };
150
155
  type Boundary = {
151
156
  "boundary"?: string;
152
157
  "reset_time"?: string;
@@ -220,11 +225,20 @@ type LevelDefinition = {
220
225
  "rewards"?: RecipeOperation[];
221
226
  "threshold": number;
222
227
  };
228
+ type MatchmakingSettings = {
229
+ "backfill"?: null | BackfillSettings;
230
+ "cluster_stagger_seconds"?: number;
231
+ "enabled": boolean;
232
+ "fill_window_seconds"?: number;
233
+ "strategy"?: MatchmakingStrategy;
234
+ "ticket_expiry_seconds"?: number | null;
235
+ };
236
+ type MatchmakingStrategy = "fifo";
223
237
  type OrderBySpec = {
224
238
  "column": RunValueColumn;
225
239
  "direction": SortDirection;
226
240
  };
227
- type OrderSource = "real_money_purchase" | "real_money_refund" | "full_game_purchase" | "full_game_refund" | "platform_purchase" | "reward" | "admin" | "system" | "promo" | "game_consume" | "play" | "recipe" | "transfer" | "platform_funded_game_inventory_purchase" | "earning_reset";
241
+ type OrderSource = "real_money_purchase" | "real_money_refund" | "full_game_purchase" | "full_game_refund" | "platform_purchase" | "reward" | "admin" | "system" | "promo" | "game_consume" | "play" | "recipe" | "transfer" | "platform_funded_game_inventory_purchase" | "earning_reset" | "test_account_provision" | "developer_grant";
228
242
  type OverflowBehavior = "fail" | "clamp" | "allow";
229
243
  type PityEffect = "guarantee_tier" | {
230
244
  "weight_boost": {
@@ -442,6 +456,7 @@ type SnapshotGameRoomTemplate = {
442
456
  "id": string;
443
457
  "idle_timeout_seconds"?: number | null;
444
458
  "match_type": string;
459
+ "matchmaking"?: null | MatchmakingSettings;
445
460
  "max_match_duration_seconds"?: number | null;
446
461
  "max_players": number;
447
462
  "min_players": number;
@@ -513,6 +528,7 @@ type SnapshotProgression = {
513
528
  "display_name"?: string | null;
514
529
  "icon_url"?: string | null;
515
530
  "id": string;
531
+ "localized"?: Record<string, unknown>;
516
532
  "progression_type": string;
517
533
  "slug"?: string | null;
518
534
  "sort_order": number;
@@ -550,6 +566,7 @@ type SnapshotRewardedPlacement = {
550
566
  "grants": SnapshotRewardGrant[];
551
567
  "max_held"?: number | null;
552
568
  "max_per_day"?: number | null;
569
+ "min_watch_secs"?: number | null;
553
570
  "placement": string;
554
571
  "reward_class": string;
555
572
  "without_ads": string;
@@ -1514,26 +1531,6 @@ interface ClusterTarget {
1514
1531
  readonly id: string;
1515
1532
  readonly pressure: string;
1516
1533
  }
1517
- type RoomArgScalar = string | number | boolean;
1518
- type RoomArgValue$1 = RoomArgScalar | readonly RoomArgScalar[];
1519
- type RoomArgs = Readonly<Record<string, RoomArgValue$1>>;
1520
- type RoomArgType = "string" | "int" | "float" | "bool" | (string & {});
1521
- interface RoomArgEntry {
1522
- readonly name: string;
1523
- readonly type: RoomArgType;
1524
- readonly list: boolean;
1525
- readonly required: boolean;
1526
- readonly mutable: boolean;
1527
- readonly fixed?: RoomArgValue$1;
1528
- readonly default?: RoomArgValue$1;
1529
- readonly description?: string;
1530
- readonly allowed?: readonly RoomArgScalar[];
1531
- readonly min?: number;
1532
- readonly max?: number;
1533
- readonly minItems?: number;
1534
- readonly maxItems?: number;
1535
- readonly maxLength?: number;
1536
- }
1537
1534
  type DedicatedServerFailure = "timeout" | "aborted" | "allocation_failed" | "no_server_ready" | "start_rate_limited" | "p2p_unavailable" | "unsupported_protocol" | "credential_expired" | "credential_reused" | "join_rate_limited" | "signaling_unavailable" | "signaling_failed" | "offer_refused" | "invalid_sdp" | "media_refused" | "connection_failed" | "join_refused" | "match_ended" | "misconfigured";
1538
1535
  declare class DedicatedServerError extends Error {
1539
1536
  readonly reason: DedicatedServerFailure;
@@ -1642,6 +1639,26 @@ interface TransportAdvert {
1642
1639
  declare function readTemplateTransports(value: unknown): readonly TransportKind[] | null;
1643
1640
  declare function readTransportAdvert(settings: unknown, forMatch?: string): TransportAdvert | null;
1644
1641
  declare function webTransportAvailable(): boolean;
1642
+ type RoomArgScalar = string | number | boolean;
1643
+ type RoomArgValue$1 = RoomArgScalar | readonly RoomArgScalar[];
1644
+ type RoomArgs = Readonly<Record<string, RoomArgValue$1>>;
1645
+ type RoomArgType = "string" | "int" | "float" | "bool" | (string & {});
1646
+ interface RoomArgEntry {
1647
+ readonly name: string;
1648
+ readonly type: RoomArgType;
1649
+ readonly list: boolean;
1650
+ readonly required: boolean;
1651
+ readonly mutable: boolean;
1652
+ readonly fixed?: RoomArgValue$1;
1653
+ readonly default?: RoomArgValue$1;
1654
+ readonly description?: string;
1655
+ readonly allowed?: readonly RoomArgScalar[];
1656
+ readonly min?: number;
1657
+ readonly max?: number;
1658
+ readonly minItems?: number;
1659
+ readonly maxItems?: number;
1660
+ readonly maxLength?: number;
1661
+ }
1645
1662
  type RoomStatus = "open" | "in_game" | "closed" | (string & {});
1646
1663
  type MatchConnectionState = "disconnected" | "connecting" | "connected" | "suspended";
1647
1664
  type MatchSessionPhase = "none" | "starting" | "ready" | "connected" | "suspended" | "ended" | (string & {});
@@ -1739,6 +1756,38 @@ interface RoomOperationError {
1739
1756
  readonly message: string;
1740
1757
  readonly retryable: boolean;
1741
1758
  }
1759
+ interface QueueForMatchOptions {
1760
+ readonly templateSlugs: readonly string[];
1761
+ readonly partyId?: string;
1762
+ readonly signal?: AbortSignal;
1763
+ }
1764
+ type MatchTicketStatus = "queued" | "matched" | "expired" | "cancelled" | "failed" | "lost" | "unavailable";
1765
+ type MatchTicketOutcome = {
1766
+ readonly status: "matched";
1767
+ readonly room: Room;
1768
+ } | {
1769
+ readonly status: "expired";
1770
+ readonly reason: string;
1771
+ } | {
1772
+ readonly status: "cancelled";
1773
+ readonly reason: string;
1774
+ } | {
1775
+ readonly status: "failed";
1776
+ readonly reason: string;
1777
+ } | {
1778
+ readonly status: "lost";
1779
+ } | {
1780
+ readonly status: "unavailable";
1781
+ };
1782
+ interface MatchTicket {
1783
+ readonly id: string;
1784
+ readonly status: MatchTicketStatus;
1785
+ readonly partySize: number;
1786
+ readonly queuedAt: number;
1787
+ readonly expiresAt: number;
1788
+ readonly outcome: Promise<MatchTicketOutcome>;
1789
+ cancel(): Promise<MatchTicketOutcome>;
1790
+ }
1742
1791
  interface CreateRoomOptions {
1743
1792
  readonly name: string;
1744
1793
  readonly maxPlayers?: number;
@@ -1881,6 +1930,7 @@ interface RoomManager {
1881
1930
  join(roomId: string, options?: JoinRoomOptions): Promise<Room>;
1882
1931
  joinByCode(code: string, options?: JoinRoomOptions): Promise<Room>;
1883
1932
  quickJoin(options: QuickJoinOptions): Promise<Room>;
1933
+ queueForMatch(options: QueueForMatchOptions): Promise<MatchTicket>;
1884
1934
  list(options?: ListRoomsOptions): Promise<RoomPage>;
1885
1935
  myRooms(signal?: AbortSignal): Promise<readonly RoomSummary[]>;
1886
1936
  leave(options?: {
@@ -1906,6 +1956,7 @@ interface RoomManager {
1906
1956
  }): Promise<void>;
1907
1957
  readonly gameId: string | null;
1908
1958
  readonly currentRoom: Room | null;
1959
+ readonly currentTicket: MatchTicket | null;
1909
1960
  readonly currentMatch: ReadyMatch | null;
1910
1961
  readonly matchConnectionState: MatchConnectionState;
1911
1962
  readonly matchSession: MatchSession;
@@ -1963,6 +2014,13 @@ interface GemPrefs$1 {
1963
2014
  readonly muted: boolean;
1964
2015
  readonly showFrameStats?: boolean;
1965
2016
  readonly locale: string;
2017
+ readonly recommended?: {
2018
+ volume: number;
2019
+ batterySaver: boolean;
2020
+ keyboardLayout: "wasd" | "arrows";
2021
+ gamepadConfirm: "south" | "east";
2022
+ vibration: boolean;
2023
+ };
1966
2024
  }
1967
2025
  interface GemCohorts$1 {
1968
2026
  readonly gem: typeof PROTOCOL;
@@ -2847,6 +2905,14 @@ interface GemPrefs {
2847
2905
  readonly muted: boolean;
2848
2906
  readonly showFrameStats: boolean;
2849
2907
  readonly locale: string;
2908
+ readonly recommended: GemRecommendedSettings | null;
2909
+ }
2910
+ interface GemRecommendedSettings {
2911
+ readonly volume: number;
2912
+ readonly batterySaver: boolean;
2913
+ readonly keyboardLayout: "wasd" | "arrows";
2914
+ readonly gamepadConfirm: "south" | "east";
2915
+ readonly vibration: boolean;
2850
2916
  }
2851
2917
  interface GemCohort {
2852
2918
  readonly experimentId: string;
@@ -2949,4 +3015,4 @@ interface ExitAnalytics {
2949
3015
  }
2950
3016
  declare function leaveAndExit(rooms: ExitRooms, bridge: ExitBridge | null, reason?: string, analytics?: ExitAnalytics): Promise<void>;
2951
3017
  declare function createGem(options?: GemOptions): Gem;
2952
- export { ARCADE_EMBEDDERS, 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 BootMark, type BootTimeline, type Challenge, type ChallengeWindow, ChallengesApi, type ConfiguredPurchasePayment, type ConfiguredPurchaseRequest, type ConfiguredPurchaseResult, 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 GemDevTools, GemFrame, GemFunctionError, type GemIdentity, type GemInsets, type GemMatchApi, type GemMatchServerModule, type GemOptions, type GemPlayer, type GemPrefs, 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, asPlayerText, createBootTimeline, createGem, leaveAndExit, mapIdentity, markOnResolve, platformIconUrl, presentJoinCredential, readTemplateTransports, readTransportAdvert, reportOnResolve, text, webTransportAvailable };
3018
+ export { ARCADE_EMBEDDERS, 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 BootMark, type BootTimeline, type Challenge, type ChallengeWindow, ChallengesApi, type ConfiguredPurchasePayment, type ConfiguredPurchaseRequest, type ConfiguredPurchaseResult, 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 GemDevTools, GemFrame, GemFunctionError, type GemIdentity, type GemInsets, 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, asPlayerText, createBootTimeline, createGem, leaveAndExit, mapIdentity, markOnResolve, platformIconUrl, presentJoinCredential, readTemplateTransports, readTransportAdvert, reportOnResolve, text, webTransportAvailable };
@@ -1 +1 @@
1
- var GemWebSdkBridgeBundle=(function(){'use strict';var w="GemWebSdkHandshake";function z(){return typeof document>"u"?void 0:document.readyState}var E=()=>Date.now();function I(n={}){let e=n.win??window,t=e,r=t[w];if(r!==void 0)return r;let a=n.readyState??z,i=n.now??E,d=[],s=[],m=c=>{let p=c.data;!p||p.type!=="gem.handshake"||(d.length>=4&&(d.shift(),s.shift(),u.dropped+=1),d.push(c),s.push(i()));};e.addEventListener("message",m);let u={events:d,times:s,dropped:0,late:a()==="complete",uninstall(){e.removeEventListener("message",m);}};return t[w]=u,u}function q(n,e,t={}){let r=n[w];if(r===void 0)return null;let a=t.ttlMs??9500,i=t.now??E,d=r.events.splice(0),s=r.times?.splice(0),m=0,u=0,c=false,p=i()-a;for(let g=d.length-1;g>=0;g--){let P=s?.[g];if(P!==void 0&&P<p){u+=1;continue}if(m+=1,e(d[g])===true){c=true;break}}return r.uninstall(),{capture:r,delivered:m,stale:u,accepted:c}}var l="gem-web-bridge",f={min:1,max:1},y=65536,L=8,v=5e3,A=1024;function R(n){return Object.freeze(Object.assign(Object.create(null),n))}var j=R({"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.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.menu":60,"gem.menuSelect":60,"gem.requestShare":6,"gem.vibrate":600,"gem.frameStats":120,"gem.portraitBorders":60,"gem.error":60,"gem.requestPurchase":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}),x="__malformed";var K=R({"gem.requestAd":"ads","gem.adResult":"ads","gem.requestSignIn":"signIn","gem.signInResult":"signIn","gem.requestPurchase":"purchases","gem.purchaseResult":"purchases","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.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.vibrate":"vibration","gem.menu":"gameMenu","gem.menuSelect":"gameMenu"}),Y=Object.freeze([["gem.asyncOpponents.","asyncOpponents"],["gem.vibration.","vibration"],["gem.viewport.","reservedAreas"]]);function _(n){let e=K[n];if(e!==void 0)return e;for(let[t,r]of Y)if(n.startsWith(t))return r}function J(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 X(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 Q(n){return /^[a-z]{2,8}(-[a-z0-9]{1,8})*$/i.test(n)}function Z(n){return /^[a-z_]+$/.test(n)}function S(n,e,t){if(e>L)return `nesting deeper than ${L}`;if(++t.nodes>v)return `more than ${v} values`;if(t.bytes>y)return `over the ${y} 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 a=n;if(t.seen.has(a))return "a repeated or cyclic object reference";if(t.seen.add(a),Array.isArray(n)){if(n.length>A)return `an array of ${n.length} entries, over the ${A} limit`;t.bytes+=2;for(let s of n){let m=S(s,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 s in d){if(!Object.prototype.hasOwnProperty.call(d,s))continue;if(++t.nodes>v)return `more than ${v} values`;if(t.bytes+=s.length*3+4,t.bytes>y)return `over the ${y} byte limit`;let m=S(d[s],e+1,t);if(m)return m}return null}function ee(n){let e={nodes:0,bytes:0,seen:new Set},t=S(n,0,e);return t?`message contains ${t}`:e.bytes>y?`message is over the ${y} byte limit`:null}var te={origin:[J,"not a well-formed origin"],url:[X,"not a safe absolute http(s) URL"],bcp47:[Q,"not a well-formed BCP 47 tag"],code:[Z,"not a code of lower-case letters and underscores"]};function M(n,e,t){for(let r of e){let a=t===""?r.n:`${t}.${r.n}`,i=n[r.n];if(i==null){if(r.o)continue;return `${a}: required`}let d=D(i,r,a);if(d)return d}return null}function D(n,e,t){switch(e.k){case "string":{if(typeof n!="string")return `${t}: expected string`;if(n.length>e.max)return `${t}: exceeds ${e.max} characters`;if(e.f){let[r,a]=te[e.f];if(!r(n))return `${t}: ${a}`}return null}case "int":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 "boolean":return typeof n=="boolean"?null:`${t}: expected boolean`;case "enum":{let r=e.v;return r.includes(n)?null:`${t}: not one of ${r.join("|")}`}case "object":return typeof n!="object"||n===null||Array.isArray(n)?`${t}: expected object`:M(n,e.fs,t);case "json":return typeof n!="object"||n===null||Array.isArray(n)?`${t}: expected a plain object`:null;case "array":{if(!Array.isArray(n))return `${t}: expected array`;if(n.length>e.max)return `${t}: exceeds ${e.max} items`;let r=e.it,a=`${t}[]`;for(let i of n){if(i==null){if(r.o)continue;return `${a}: required`}let d=D(i,r,a);if(d)return d}return null}default:{let r=e.k;return `${t}: unknown kind ${String(r)}`}}}function o(n,e){return t=>{let r=ee(t);if(r)return r;if(typeof t!="object"||t===null||Array.isArray(t))return "message: expected object";let a=t;return a.gem!==l?"gem: wrong protocol marker":a.type!==n?`type: expected ${n}`:M(a,e,"")}}var ne=o("gem.handshake",[{n:"versions",k:"object",fs:[{n:"min",k:"int",lo:1,hi:1e3},{n:"max",k:"int",lo:1,hi:1e3}]},{n:"capabilities",k:"array",o:1,max:64,it:{n:"",k:"string",max:64}},{n:"embedder",k:"string",max:2048,f:"origin"},{n:"unbidden",k:"boolean",o:1}]),re=o("gem.handshake.accept",[{n:"v",k:"int",lo:1,hi:1e3},{n:"capabilities",k:"array",o:1,max:64,it:{n:"",k:"string",max:64}}]),oe=o("gem.token",[{n:"token",k:"string",max:4096},{n:"requestId",k:"string",o:1,max:64},{n:"generation",k:"int",lo:0,hi:2147483647},{n:"apiBaseUrl",k:"string",o:1,max:512,f:"url"},{n:"playerId",k:"string",max:64},{n:"gameId",k:"string",max:64},{n:"channel",k:"enum",v:["dev","test","release"]},{n:"gameVersion",k:"string",o:1,max:64},{n:"expiresAt",k:"int",lo:0,hi:4102444800},{n:"chainEndsAt",k:"int",lo:0,hi:4102444800},{n:"allowDevTools",k:"boolean",o:1}]),ae=o("gem.token.denied",[{n:"requestId",k:"string",max:64},{n:"retryable",k:"boolean"},{n:"retryAfterMs",k:"int",o:1,lo:0,hi:36e5},{n:"reason",k:"enum",v:["chain_exhausted","unavailable"]},{n:"correlationId",k:"string",max:64}]),se=o("gem.player",[{n:"untrusted",k:"object",fs:[{n:"displayName",k:"string",max:64},{n:"displayTag",k:"string",o:1,max:80},{n:"displayHandle",k:"string",max:80}]},{n:"playerId",k:"string",o:1,max:64},{n:"discriminator",k:"string",o:1,max:8},{n:"avatarIconUrl",k:"string",o:1,max:2048,f:"url"},{n:"badges",k:"array",o:1,max:2,it:{n:"",k:"object",fs:[{n:"itemId",k:"string",max:64},{n:"iconUrl",k:"string",max:2048,f:"url"}]}},{n:"displayTag",k:"string",max:8},{n:"avatarUrl",k:"string",o:1,max:2048,f:"url"},{n:"boost",k:"object",o:1,fs:[{n:"multipliers",k:"array",max:8,it:{n:"",k:"object",fs:[{n:"currencyId",k:"string",max:64},{n:"currencySlug",k:"string",max:32},{n:"multiplierBp",k:"int",lo:1e4,hi:1e6}]}},{n:"expiresInDays",k:"int",o:1,lo:1,hi:7}]}]),ie=o("gem.pause",[{n:"paused",k:"boolean"}]),le=o("gem.prefs",[{n:"reducedMotion",k:"boolean"},{n:"muted",k:"boolean"},{n:"showFrameStats",k:"boolean",o:1},{n:"locale",k:"string",max:35,f:"bcp47"}]),de=o("gem.cohorts",[{n:"cohorts",k:"array",max:8,it:{n:"",k:"object",fs:[{n:"experimentId",k:"string",max:36},{n:"variantKey",k:"string",max:32}]}}]),me=o("gem.earnAllowanceChanged",[]),ge=o("gem.viewport",[{n:"insets",k:"object",fs:[{n:"top",k:"int",lo:0,hi:4096},{n:"right",k:"int",lo:0,hi:4096},{n:"bottom",k:"int",lo:0,hi:4096},{n:"left",k:"int",lo:0,hi:4096}]},{n:"reserved",k:"array",o:1,max:4,it:{n:"",k:"object",fs:[{n:"x",k:"int",lo:0,hi:16384},{n:"y",k:"int",lo:0,hi:16384},{n:"width",k:"int",lo:0,hi:16384},{n:"height",k:"int",lo:0,hi:16384}]}}]),ue=o("gem.deviceSettings",[{n:"settings",k:"json",o:1}]),ce=o("gem.willTerminate",[{n:"reason",k:"enum",v:["grant_expiring","session_ended","navigating","kill_switch"]},{n:"graceMs",k:"int",lo:0,hi:6e4}]),pe=o("gem.roomEvent",[{n:"event",k:"enum",v:["updated","match_started","match_ready","match_failed","version_stale"]},{n:"roomId",k:"string",max:64},{n:"matchId",k:"string",o:1,max:64},{n:"version",k:"int",o:1,lo:0,hi:2147483647},{n:"reason",k:"string",o:1,max:64},{n:"platform",k:"enum",o:1,v:["universal","mobile"]}]),ye=o("gem.socketState",[{n:"connected",k:"boolean"},{n:"reason",k:"enum",o:1,v:["connecting","dropped","watchdog","terminal"]}]),fe=o("gem.seatedEvent",[{n:"roomId",k:"string",max:64}]),he=o("gem.autoStartFailedEvent",[{n:"roomId",k:"string",max:64},{n:"code",k:"string",max:64}]),ke=o("gem.signalEvent",[{n:"event",k:"enum",v:["hello","offer","answer","ice","peerJoined","peerLeft","migration","matchEnded","error"]},{n:"matchId",k:"string",max:64},{n:"data",k:"json"}]),ve=o("gem.dedicatedEvent",[{n:"event",k:"enum",v:["answer","error","matchEnded"]},{n:"matchId",k:"string",max:64},{n:"sdp",k:"string",o:1,max:10240},{n:"sessionId",k:"string",o:1,max:64},{n:"code",k:"string",o:1,max:64},{n:"message",k:"string",o:1,max:256},{n:"reason",k:"string",o:1,max:64}]),xe=o("gem.partyResult",[{n:"requestId",k:"string",max:64},{n:"partyId",k:"string",o:1,max:64}]),be=o("gem.clusterTarget",[{n:"clusterTargetId",k:"string",max:64},{n:"clusterTargetIds",k:"array",o:1,max:3,it:{n:"",k:"string",max:64}}]),we=o("gem.devtools",[{n:"action",k:"enum",v:["open","close","toggle"]}]),Se=o("gem.screenshot",[{n:"maxWidth",k:"int",lo:1,hi:7680},{n:"maxHeight",k:"int",lo:1,hi:4320}]),Re=o("gem.screenshot.denied",[{n:"reason",k:"enum",v:["not_wired","no_source","unsupported","unreadable","tainted","too_large","busy","declined","failed"]},{n:"retryable",k:"boolean"}]),Ge=o("gem.requestContext",[]),Oe=o("gem.gameContext",[{n:"context",k:"json"}]),Ce=o("gem.signal",[{n:"signal",k:"enum",v:["join","offer","answer","ice","migrationAck","hostUnreachable"]},{n:"matchId",k:"string",max:64},{n:"data",k:"json"}]),Te=o("gem.dedicatedOffer",[{n:"matchId",k:"string",max:64},{n:"sdp",k:"string",max:10240},{n:"intent",k:"enum",v:["initial","ice_restart","full_reconnect"]}]),Pe=o("gem.partyRequest",[{n:"requestId",k:"string",max:64}]),Ee=o("gem.ready",[]),Ie=o("gem.engaged",[]),qe=o("gem.progress",[{n:"loaded",k:"int",lo:0,hi:1099511627776},{n:"total",k:"int",lo:0,hi:1099511627776}]),Le=o("gem.requestToken",[{n:"requestId",k:"string",max:64},{n:"reason",k:"enum",v:["initial","expiring","rejected"]}]),Ae=o("gem.requestLocalServer",[{n:"requestId",k:"string",max:64},{n:"gameRoomId",k:"string",max:64}]),je=o("gem.localServer",[{n:"requestId",k:"string",max:64},{n:"serverId",k:"string",o:1,max:128}]),_e=o("gem.localServer.denied",[{n:"requestId",k:"string",max:64},{n:"retryable",k:"boolean"},{n:"reason",k:"enum",v:["refused","unavailable"]}]),Me=o("gem.exit",[{n:"reason",k:"string",o:1,max:64}]),De=o("gem.openExternal",[{n:"url",k:"string",max:2048,f:"url"}]),Fe=o("gem.requestFullscreen",[{n:"enabled",k:"boolean"}]),$e=o("gem.audioState",[{n:"muted",k:"boolean"}]),He=o("gem.rewardCue",[{n:"currencySlug",k:"string",max:32},{n:"expected",k:"int",o:1,lo:1,hi:1e9},{n:"origin",k:"object",o:1,fs:[{n:"x",k:"int",lo:0,hi:16384},{n:"y",k:"int",lo:0,hi:16384}]}]),Be=o("gem.walletDisplay",[{n:"visible",k:"boolean"},{n:"currencies",k:"array",o:1,max:8,it:{n:"",k:"string",max:64}},{n:"score",k:"boolean",o:1}]),Ue=o("gem.menu",[{n:"settings",k:"boolean"},{n:"items",k:"array",o:1,max:4,it:{n:"",k:"object",fs:[{n:"id",k:"string",max:32},{n:"label",k:"string",max:40}]}}]),We=o("gem.menuSelect",[{n:"entry",k:"enum",v:["settings","item"]},{n:"id",k:"string",o:1,max:32}]),Ne=o("gem.requestShare",[{n:"params",k:"array",max:16,it:{n:"",k:"object",fs:[{n:"key",k:"string",max:64},{n:"value",k:"string",max:512}]}}]),Ve=o("gem.vibrate",[{n:"pattern",k:"array",max:99,it:{n:"",k:"int",lo:0,hi:1e4}}]),ze=o("gem.frameStats",[{n:"fps",k:"int",lo:0,hi:1e3},{n:"frameTimeP95Ms",k:"int",lo:0,hi:1e5}]),Ke=o("gem.portraitBorders",[{n:"name",k:"string",o:1,max:40}]),Ye=o("gem.error",[{n:"code",k:"enum",v:["version_mismatch","handshake_timeout","handshake_duplicate","invalid_message","rate_limited","token_unavailable","unsupported","unsupported_capability","internal"]},{n:"message",k:"string",o:1,max:256}]),Je=o("gem.requestPurchase",[{n:"requestId",k:"string",max:64},{n:"purchaseKind",k:"enum",v:["item","recipe"]},{n:"targetId",k:"string",max:64},{n:"currencySlug",k:"string",max:32},{n:"quantity",k:"int",o:1,lo:1,hi:10},{n:"catalogId",k:"string",o:1,max:64}]),Xe=o("gem.purchaseResult",[{n:"requestId",k:"string",max:64},{n:"outcome",k:"enum",v:["ok","declined","unavailable"]},{n:"reason",k:"string",o:1,max:64,f:"code"},{n:"purchaseId",k:"string",o:1,max:64}]),Qe=o("gem.deviceSettings.put",[{n:"requestId",k:"string",max:64},{n:"settings",k:"json"}]),Ze=o("gem.deviceSettings.result",[{n:"requestId",k:"string",max:64},{n:"outcome",k:"enum",v:["stored","too_large","unavailable"]}]),et=o("gem.requestAd",[{n:"requestId",k:"string",max:64},{n:"placement",k:"string",max:32},{n:"format",k:"enum",v:["interstitial","rewarded"]}]),tt=o("gem.adResult",[{n:"requestId",k:"string",max:64},{n:"outcome",k:"enum",v:["shown","no_ad","unavailable"]}]),nt=o("gem.requestSignIn",[{n:"requestId",k:"string",max:64}]),rt=o("gem.signInResult",[{n:"requestId",k:"string",max:64},{n:"outcome",k:"enum",v:["signed_in","declined","unavailable"]}]),ot=o("gem.requestFriendChallenge",[{n:"requestId",k:"string",max:64},{n:"playerId",k:"string",max:64},{n:"template",k:"string",max:64},{n:"params",k:"json",o:1}]),at=o("gem.friendChallengeResult",[{n:"requestId",k:"string",max:64},{n:"outcome",k:"enum",v:["accepted","cancelled","refused","unavailable","rate_limited","invalid"]},{n:"code",k:"string",o:1,max:64},{n:"param",k:"string",o:1,max:64},{n:"channel",k:"string",o:1,max:16},{n:"configVersion",k:"int",o:1,lo:0,hi:9007199254740991},{n:"retryAfterMs",k:"int",o:1,lo:0,hi:864e5},{n:"detail",k:"string",o:1,max:300}]),b=R({"gem.handshake":ne,"gem.handshake.accept":re,"gem.token":oe,"gem.token.denied":ae,"gem.player":se,"gem.pause":ie,"gem.prefs":le,"gem.cohorts":de,"gem.earnAllowanceChanged":me,"gem.viewport":ge,"gem.deviceSettings":ue,"gem.willTerminate":ce,"gem.roomEvent":pe,"gem.socketState":ye,"gem.seatedEvent":fe,"gem.autoStartFailedEvent":he,"gem.signalEvent":ke,"gem.dedicatedEvent":ve,"gem.partyResult":xe,"gem.clusterTarget":be,"gem.devtools":we,"gem.screenshot":Se,"gem.screenshot.denied":Re,"gem.requestContext":Ge,"gem.gameContext":Oe,"gem.signal":Ce,"gem.dedicatedOffer":Te,"gem.partyRequest":Pe,"gem.ready":Ee,"gem.engaged":Ie,"gem.progress":qe,"gem.requestToken":Le,"gem.requestLocalServer":Ae,"gem.localServer":je,"gem.localServer.denied":_e,"gem.exit":Me,"gem.openExternal":De,"gem.requestFullscreen":Fe,"gem.audioState":$e,"gem.rewardCue":He,"gem.walletDisplay":Be,"gem.menu":Ue,"gem.menuSelect":We,"gem.requestShare":Ne,"gem.vibrate":Ve,"gem.frameStats":ze,"gem.portraitBorders":Ke,"gem.error":Ye,"gem.requestPurchase":Je,"gem.purchaseResult":Xe,"gem.deviceSettings.put":Qe,"gem.deviceSettings.result":Ze,"gem.requestAd":et,"gem.adResult":tt,"gem.requestSignIn":nt,"gem.signInResult":rt,"gem.requestFriendChallenge":ot,"gem.friendChallengeResult":at});var st=/^[a-z0-9][a-z0-9_-]{0,39}$/;function it(n){return typeof n=="string"&&st.test(n)}function F(n){if(n===null||it(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 G=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 O(n){return new G(n)}var C={now:()=>Date.now(),setTimeout:(n,e)=>setTimeout(n,e),clearTimeout:n=>clearTimeout(n)},h=class{constructor(e=C){this.clock=e;}clock;tokens=new Map;lastRefill=new Map;allow(e){let t=j[e];if(t===void 0)return false;let r=this.clock.now(),a=this.lastRefill.get(e)??r,i=this.tokens.get(e)??t,d=Math.max(0,r-a),s=Math.min(t,i+d*t/6e4);return s<1?(this.tokens.set(e,s),this.lastRefill.set(e,r),false):(this.tokens.set(e,s-1),this.lastRefill.set(e,r),true)}};function T(n,e){return n.toLowerCase()===e.toLowerCase()}function $(n){let e=n.toLowerCase();return e==="localhost"||e.endsWith(".localhost")||e==="[::1]"||e==="::1"?true:/^127(\.\d{1,3}){3}$/.test(e)}function H(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:$(t.hostname)&&$(r.hostname)}function B(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 U(n){return Math.min(16384,Math.max(0,Math.round(Number.isFinite(n)?n:0)))}function lt(n,e){if(n!==true)return {visible:false};let t=[],r=false;for(let a of Array.isArray(e)?e:[])a==="score"?r=true:typeof a=="string"&&a.length>0&&a.length<=64&&!t.includes(a)&&t.push(a);return !r&&t.length===0?{visible:true}:{visible:true,currencies:t.slice(0,8),score:r}}function dt(n,e){let t=[];for(let r of Array.isArray(e)?e:[]){if(t.length===4)break;if(typeof r!="object"||r===null)continue;let{id:a,label:i}=r;typeof a!="string"||a.length===0||a.length>32||typeof i!="string"||i.trim().length===0||t.some(d=>d.id===a)||t.push({id:a,label:i.trim().slice(0,40)});}return t.length===0?{settings:n===true}:{settings:n===true,items:t}}function W(n,e){return Math.min(e,Math.max(0,Math.round(Number.isFinite(n)?n:0)))}function mt(n){let e=n.untrusted,t=O(e.displayName),r=e.displayTag||e.displayHandle,a=r?O(r):void 0,i=n.discriminator||n.displayTag,d=i&&/^[0-9]{1,8}$/.test(i)?i:void 0,s=n.avatarIconUrl||n.avatarUrl,m={displayName:t,displayHandle:a??t,badges:(n.badges??[]).map(g=>({itemId:g.itemId,iconUrl:g.iconUrl}))};n.playerId&&(m.playerId=n.playerId),d&&(m.discriminator=d),a&&(m.displayTag=a),s&&(m.avatarIconUrl=m.avatarUrl=s);let u=n.boost,c=(u?.multipliers??[]).map(g=>({currencyId:g.currencyId,currencySlug:g.currencySlug,multiplier:g.multiplierBp/1e4})),p=c.some(g=>g.multiplier>1);return m.boost=p&&u?.expiresInDays?{active:p,multipliers:c,expiresInDays:u.expiresInDays}:{active:p,multipliers:c},m}var gt=1e4,k=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??C,this.inbound=new h(this.clock),this.outbound=new h(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(s=>T(s,e.origin))||H(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=b["gem.handshake"]?.(e.data);if(r)return this.refuse(e,`malformed handshake: ${r}`),false;let a=e.data;if(!T(a.embedder,e.origin))return this.refuse(e,`handshake claims embedder '${a.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=B(f,a.versions);return d===null?(i.onmessage=null,i.postMessage({gem:l,type:"gem.error",code:"version_mismatch",message:`frame supports v${f.min}..v${f.max}`}),i.close(),this.transition("refused"),this.options.onError?.("version_mismatch"),false):(this.port=i,this.version=d,i.onmessage=s=>this.receive(s.data,s.ports??[]),i.start?.(),this.peerCapabilities=a.capabilities??[],this.unbidden=a.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=gt){return this.state!=="waiting"?Promise.resolve(this.state):new Promise(t=>{let r=i=>{this.clock.clearTimeout(a),t(i);},a=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.state!=="connected"||!this.parentSupports("audioState")?false:(this.send({gem:l,type:"gem.audioState",muted:e}),true)}reportEngaged(){return this.engagedSent||this.state!=="connected"||!this.parentSupports("engagement")||!this.send({gem:l,type:"gem.engaged"})?false:(this.engagedSent=true,true)}cueReward(e){if(this.state!=="connected"||!this.parentSupports("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:U(e.origin.x),y:U(e.origin.y)}),this.send(t),true}showPortraitBorders(e){let t=F(e);return t===void 0||this.state!=="connected"||!this.parentSupports("portraitBorders")?false:this.send(t===null?{gem:l,type:"gem.portraitBorders"}:{gem:l,type:"gem.portraitBorders",name:t})}setWalletVisible(e,t){return this.state!=="connected"||!this.parentSupports("walletDisplay")?false:this.send({gem:l,type:"gem.walletDisplay",...lt(e,t?.only)})}setMenu(e,t){return this.state!=="connected"||!this.parentSupports("gameMenu")?false:this.send({gem:l,type:"gem.menu",...dt(e,t)})}requestShare(e){return this.state!=="connected"||!this.parentSupports("share")?false:this.send({gem:l,type:"gem.requestShare",params:e.map(({key:t,value:r})=>({key:t,value:r}))})}requestVibrate(e){return this.state!=="connected"||!this.parentSupports("vibration")?false:this.send({gem:l,type:"gem.vibrate",pattern:[...e]})}reportFrameStats(e){return this.state!=="connected"||!this.parentSupports("frameStats")?false:(this.send({gem:l,type:"gem.frameStats",fps:W(e.fps,1e3),frameTimeP95Ms:W(e.frameTimeP95Ms,1e5)}),true)}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,a,i,d){return this.send({gem:l,type:"gem.requestPurchase",requestId:e,purchaseKind:t,targetId:r,currencySlug:a,...i===void 0?{}:{quantity:i},...d===void 0?{}:{catalogId:d}})}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,a){return this.send({gem:l,type:"gem.requestFriendChallenge",requestId:e,playerId:t,template:r,...a===void 0?{}:{params:a}})}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(x)){this.options.onDropped?.(e,t);return}this.fail(e,t);}dropUnknownType(e){this.inbound.allow(x)&&this.options.onDropped?.("unsupported",`ignored unknown message type '${e}'`);}refuse(e,t){e.ports?.[0]?.close?.(),this.inbound.allow(x)&&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}});}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=b[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||N(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 a=b[r];if(!a)return this.dropUnknownType(r),false;if(!this.inbound.allow(r))return this.fail("rate_limited",`parent exceeded the limit for ${r}`),false;let i=_(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=a(e);if(d)return this.fail("invalid_message",`${r}: ${d}`),false;let s=e;if(s.v!==this.version)return this.fail("invalid_message",`${r}: expected v ${String(this.version)}`),false;switch(r){case "gem.token":this.options.onToken?.(s);break;case "gem.pause":this.options.onPause?.(s);break;case "gem.menuSelect":this.options.onMenuSelect?.(s);break;case "gem.prefs":this.options.onPrefs?.(s);break;case "gem.cohorts":this.options.onCohorts?.(s);break;case "gem.earnAllowanceChanged":this.options.onEarnAllowanceChanged?.();break;case "gem.viewport":this.options.onViewport?.(s);break;case "gem.willTerminate":this.options.onWillTerminate?.(s);break;case "gem.devtools":this.options.onDevtools?.(s.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 u={maxWidth:s.maxWidth,maxHeight:s.maxHeight};if(!this.options.onScreenshot){m.close(),this.screenshotDenied("not_wired",false);break}return N(t.slice(1)),this.options.onScreenshot(u,m,(c,p)=>this.screenshotDenied(c,p)),true}case "gem.token.denied":this.options.onTokenDenied?.(s);break;case "gem.localServer":this.options.onLocalServer?.(s);break;case "gem.localServer.denied":this.options.onLocalServerDenied?.(s);break;case "gem.player":{this.options.onPlayer?.(mt(s));break}case "gem.roomEvent":this.options.onRoomEvent?.(s);break;case "gem.seatedEvent":this.options.onSeatedEvent?.(s);break;case "gem.autoStartFailedEvent":this.options.onAutoStartFailedEvent?.(s);break;case "gem.socketState":this.options.onSocketState?.(s);break;case "gem.signalEvent":this.options.onSignalEvent?.(s);break;case "gem.dedicatedEvent":this.options.onDedicatedEvent?.(s);break;case "gem.clusterTarget":this.options.onClusterTarget?.(s);break;case "gem.partyResult":this.options.onPartyResult?.(s);break;case "gem.purchaseResult":this.options.onPurchaseResult?.(s);break;case "gem.deviceSettings":this.options.onDeviceSettings?.(s);break;case "gem.deviceSettings.result":this.options.onDeviceSettingsResult?.(s);break;case "gem.adResult":this.options.onAdResult?.(s);break;case "gem.signInResult":this.options.onSignInResult?.(s);break;case "gem.friendChallengeResult":this.options.onFriendChallengeResult?.(s);break;case "gem.error":this.options.onError?.(s.code,s.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 N(n){for(let e of n)try{e?.close?.();}catch{}}I();function ut(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 k({...n,expectedSource:n.expectedSource??window.parent}),t=r=>{let a=e.handleWindowMessage({data:r.data,origin:r.origin,source:r.source,ports:r.ports});return a&&window.removeEventListener("message",t),a};return window.addEventListener("message",t),q(window,t),e}var V={connect:ut,GemFrame:k,PROTOCOL:l,SUPPORTED_VERSIONS:f};window.GemWebSdkBridge=V;var Ct=V;return Ct;})();
1
+ var GemWebSdkBridgeBundle=(function(){'use strict';var w="GemWebSdkHandshake";function z(){return typeof document>"u"?void 0:document.readyState}var E=()=>Date.now();function I(n={}){let e=n.win??window,t=e,r=t[w];if(r!==void 0)return r;let a=n.readyState??z,i=n.now??E,d=[],s=[],m=g=>{let p=g.data;!p||p.type!=="gem.handshake"||(d.length>=4&&(d.shift(),s.shift(),c.dropped+=1),d.push(g),s.push(i()));};e.addEventListener("message",m);let c={events:d,times:s,dropped:0,late:a()==="complete",uninstall(){e.removeEventListener("message",m);}};return t[w]=c,c}function q(n,e,t={}){let r=n[w];if(r===void 0)return null;let a=t.ttlMs??9500,i=t.now??E,d=r.events.splice(0),s=r.times?.splice(0),m=0,c=0,g=false,p=i()-a;for(let u=d.length-1;u>=0;u--){let P=s?.[u];if(P!==void 0&&P<p){c+=1;continue}if(m+=1,e(d[u])===true){g=true;break}}return r.uninstall(),{capture:r,delivered:m,stale:c,accepted:g}}var l="gem-web-bridge",f={min:1,max:1},y=65536,L=8,v=5e3,A=1024;function R(n){return Object.freeze(Object.assign(Object.create(null),n))}var _=R({"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.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.menu":60,"gem.menuSelect":60,"gem.requestShare":6,"gem.vibrate":600,"gem.frameStats":120,"gem.portraitBorders":60,"gem.error":60,"gem.requestPurchase":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}),x="__malformed";var K=R({"gem.requestAd":"ads","gem.adResult":"ads","gem.requestSignIn":"signIn","gem.signInResult":"signIn","gem.requestPurchase":"purchases","gem.purchaseResult":"purchases","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.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.vibrate":"vibration","gem.menu":"gameMenu","gem.menuSelect":"gameMenu"}),Y=Object.freeze([["gem.asyncOpponents.","asyncOpponents"],["gem.vibration.","vibration"],["gem.viewport.","reservedAreas"]]);function j(n){let e=K[n];if(e!==void 0)return e;for(let[t,r]of Y)if(n.startsWith(t))return r}function J(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 X(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 Q(n){return /^[a-z]{2,8}(-[a-z0-9]{1,8})*$/i.test(n)}function Z(n){return /^[a-z_]+$/.test(n)}function S(n,e,t){if(e>L)return `nesting deeper than ${L}`;if(++t.nodes>v)return `more than ${v} values`;if(t.bytes>y)return `over the ${y} 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 a=n;if(t.seen.has(a))return "a repeated or cyclic object reference";if(t.seen.add(a),Array.isArray(n)){if(n.length>A)return `an array of ${n.length} entries, over the ${A} limit`;t.bytes+=2;for(let s of n){let m=S(s,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 s in d){if(!Object.prototype.hasOwnProperty.call(d,s))continue;if(++t.nodes>v)return `more than ${v} values`;if(t.bytes+=s.length*3+4,t.bytes>y)return `over the ${y} byte limit`;let m=S(d[s],e+1,t);if(m)return m}return null}function ee(n){let e={nodes:0,bytes:0,seen:new Set},t=S(n,0,e);return t?`message contains ${t}`:e.bytes>y?`message is over the ${y} byte limit`:null}var te={origin:[J,"not a well-formed origin"],url:[X,"not a safe absolute http(s) URL"],bcp47:[Q,"not a well-formed BCP 47 tag"],code:[Z,"not a code of lower-case letters and underscores"]};function M(n,e,t){for(let r of e){let a=t===""?r.n:`${t}.${r.n}`,i=n[r.n];if(i==null){if(r.o)continue;return `${a}: required`}let d=D(i,r,a);if(d)return d}return null}function D(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,a]=te[e.f];if(!r(n))return `${t}: ${a}`}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`:M(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,a=`${t}[]`;for(let i of n){if(i==null){if(r.o)continue;return `${a}: required`}let d=D(i,r,a);if(d)return d}return null}default:{let r=e.k;return `${t}: unknown kind ${String(r)}`}}}function o(n,e){return t=>{let r=ee(t);if(r)return r;if(typeof t!="object"||t===null||Array.isArray(t))return "message: expected object";let a=t;return a.gem!==l?"gem: wrong protocol marker":a.type!==n?`type: expected ${n}`:M(a,e,"")}}var ne=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}]),re=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}}]),oe=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}]),ae=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}]),se=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:"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}]}]),ie=o("gem.pause",[{n:"paused",k:"b"}]),le=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"}]}]),de=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}]}}]),me=o("gem.earnAllowanceChanged",[]),ue=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}]}}]),ce=o("gem.deviceSettings",[{n:"settings",k:"j",o:1}]),ge=o("gem.willTerminate",[{n:"reason",k:"e",v:["grant_expiring","session_ended","navigating","kill_switch"]},{n:"graceMs",k:"i",lo:0,hi:6e4}]),pe=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"]}]),ye=o("gem.socketState",[{n:"connected",k:"b"},{n:"reason",k:"e",o:1,v:["connecting","dropped","watchdog","terminal"]}]),fe=o("gem.seatedEvent",[{n:"roomId",k:"s",max:64}]),he=o("gem.autoStartFailedEvent",[{n:"roomId",k:"s",max:64},{n:"code",k:"s",max:64}]),ke=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"}]),ve=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}]),xe=o("gem.partyResult",[{n:"requestId",k:"s",max:64},{n:"partyId",k:"s",o:1,max:64}]),be=o("gem.clusterTarget",[{n:"clusterTargetId",k:"s",max:64},{n:"clusterTargetIds",k:"a",o:1,max:3,it:{n:"",k:"s",max:64}}]),we=o("gem.devtools",[{n:"action",k:"e",v:["open","close","toggle"]}]),Se=o("gem.screenshot",[{n:"maxWidth",k:"i",lo:1,hi:7680},{n:"maxHeight",k:"i",lo:1,hi:4320}]),Re=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"}]),Ge=o("gem.requestContext",[]),Oe=o("gem.gameContext",[{n:"context",k:"j"}]),Ce=o("gem.signal",[{n:"signal",k:"e",v:["join","offer","answer","ice","migrationAck","hostUnreachable"]},{n:"matchId",k:"s",max:64},{n:"data",k:"j"}]),Te=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"]}]),Pe=o("gem.partyRequest",[{n:"requestId",k:"s",max:64}]),Ee=o("gem.ready",[]),Ie=o("gem.engaged",[]),qe=o("gem.progress",[{n:"loaded",k:"i",lo:0,hi:1099511627776},{n:"total",k:"i",lo:0,hi:1099511627776}]),Le=o("gem.requestToken",[{n:"requestId",k:"s",max:64},{n:"reason",k:"e",v:["initial","expiring","rejected"]}]),Ae=o("gem.requestLocalServer",[{n:"requestId",k:"s",max:64},{n:"gameRoomId",k:"s",max:64}]),_e=o("gem.localServer",[{n:"requestId",k:"s",max:64},{n:"serverId",k:"s",o:1,max:128}]),je=o("gem.localServer.denied",[{n:"requestId",k:"s",max:64},{n:"retryable",k:"b"},{n:"reason",k:"e",v:["refused","unavailable"]}]),Me=o("gem.exit",[{n:"reason",k:"s",o:1,max:64}]),De=o("gem.openExternal",[{n:"url",k:"s",max:2048,f:"url"}]),Fe=o("gem.requestFullscreen",[{n:"enabled",k:"b"}]),$e=o("gem.audioState",[{n:"muted",k:"b"}]),He=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}]}]),Be=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}]),Ue=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}]}}]),We=o("gem.menuSelect",[{n:"entry",k:"e",v:["settings","item"]},{n:"id",k:"s",o:1,max:32}]),Ne=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}]}}]),Ve=o("gem.vibrate",[{n:"pattern",k:"a",max:99,it:{n:"",k:"i",lo:0,hi:1e4}}]),ze=o("gem.frameStats",[{n:"fps",k:"i",lo:0,hi:1e3},{n:"frameTimeP95Ms",k:"i",lo:0,hi:1e5}]),Ke=o("gem.portraitBorders",[{n:"name",k:"s",o:1,max:40}]),Ye=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}]),Je=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}]),Xe=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}]),Qe=o("gem.deviceSettings.put",[{n:"requestId",k:"s",max:64},{n:"settings",k:"j"}]),Ze=o("gem.deviceSettings.result",[{n:"requestId",k:"s",max:64},{n:"outcome",k:"e",v:["stored","too_large","unavailable"]}]),et=o("gem.requestAd",[{n:"requestId",k:"s",max:64},{n:"placement",k:"s",max:32},{n:"format",k:"e",v:["interstitial","rewarded"]}]),tt=o("gem.adResult",[{n:"requestId",k:"s",max:64},{n:"outcome",k:"e",v:["shown","no_ad","unavailable"]}]),nt=o("gem.requestSignIn",[{n:"requestId",k:"s",max:64}]),rt=o("gem.signInResult",[{n:"requestId",k:"s",max:64},{n:"outcome",k:"e",v:["signed_in","declined","unavailable"]}]),ot=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}]),at=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}]),b=R({"gem.handshake":ne,"gem.handshake.accept":re,"gem.token":oe,"gem.token.denied":ae,"gem.player":se,"gem.pause":ie,"gem.prefs":le,"gem.cohorts":de,"gem.earnAllowanceChanged":me,"gem.viewport":ue,"gem.deviceSettings":ce,"gem.willTerminate":ge,"gem.roomEvent":pe,"gem.socketState":ye,"gem.seatedEvent":fe,"gem.autoStartFailedEvent":he,"gem.signalEvent":ke,"gem.dedicatedEvent":ve,"gem.partyResult":xe,"gem.clusterTarget":be,"gem.devtools":we,"gem.screenshot":Se,"gem.screenshot.denied":Re,"gem.requestContext":Ge,"gem.gameContext":Oe,"gem.signal":Ce,"gem.dedicatedOffer":Te,"gem.partyRequest":Pe,"gem.ready":Ee,"gem.engaged":Ie,"gem.progress":qe,"gem.requestToken":Le,"gem.requestLocalServer":Ae,"gem.localServer":_e,"gem.localServer.denied":je,"gem.exit":Me,"gem.openExternal":De,"gem.requestFullscreen":Fe,"gem.audioState":$e,"gem.rewardCue":He,"gem.walletDisplay":Be,"gem.menu":Ue,"gem.menuSelect":We,"gem.requestShare":Ne,"gem.vibrate":Ve,"gem.frameStats":ze,"gem.portraitBorders":Ke,"gem.error":Ye,"gem.requestPurchase":Je,"gem.purchaseResult":Xe,"gem.deviceSettings.put":Qe,"gem.deviceSettings.result":Ze,"gem.requestAd":et,"gem.adResult":tt,"gem.requestSignIn":nt,"gem.signInResult":rt,"gem.requestFriendChallenge":ot,"gem.friendChallengeResult":at});var st=/^[a-z0-9][a-z0-9_-]{0,39}$/;function it(n){return typeof n=="string"&&st.test(n)}function F(n){if(n===null||it(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 G=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 O(n){return new G(n)}var C={now:()=>Date.now(),setTimeout:(n,e)=>setTimeout(n,e),clearTimeout:n=>clearTimeout(n)},h=class{constructor(e=C){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(),a=this.lastRefill.get(e)??r,i=this.tokens.get(e)??t,d=Math.max(0,r-a),s=Math.min(t,i+d*t/6e4);return s<1?(this.tokens.set(e,s),this.lastRefill.set(e,r),false):(this.tokens.set(e,s-1),this.lastRefill.set(e,r),true)}};function T(n,e){return n.toLowerCase()===e.toLowerCase()}function $(n){let e=n.toLowerCase();return e==="localhost"||e.endsWith(".localhost")||e==="[::1]"||e==="::1"?true:/^127(\.\d{1,3}){3}$/.test(e)}function H(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:$(t.hostname)&&$(r.hostname)}function B(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 U(n){return Math.min(16384,Math.max(0,Math.round(Number.isFinite(n)?n:0)))}function lt(n,e){if(n!==true)return {visible:false};let t=[],r=false;for(let a of Array.isArray(e)?e:[])a==="score"?r=true:typeof a=="string"&&a.length>0&&a.length<=64&&!t.includes(a)&&t.push(a);return !r&&t.length===0?{visible:true}:{visible:true,currencies:t.slice(0,8),score:r}}function dt(n,e){let t=[];for(let r of Array.isArray(e)?e:[]){if(t.length===4)break;if(typeof r!="object"||r===null)continue;let{id:a,label:i}=r;typeof a!="string"||a.length===0||a.length>32||typeof i!="string"||i.trim().length===0||t.some(d=>d.id===a)||t.push({id:a,label:i.trim().slice(0,40)});}return t.length===0?{settings:n===true}:{settings:n===true,items:t}}function W(n,e){return Math.min(e,Math.max(0,Math.round(Number.isFinite(n)?n:0)))}function mt(n){let e=n.untrusted,t=O(e.displayName),r=e.displayTag||e.displayHandle,a=r?O(r):void 0,i=n.discriminator||n.displayTag,d=i&&/^[0-9]{1,8}$/.test(i)?i:void 0,s=n.avatarIconUrl||n.avatarUrl,m={displayName:t,displayHandle:a??t,badges:(n.badges??[]).map(u=>({itemId:u.itemId,iconUrl:u.iconUrl}))};n.playerId&&(m.playerId=n.playerId),d&&(m.discriminator=d),a&&(m.displayTag=a),s&&(m.avatarIconUrl=m.avatarUrl=s);let c=n.boost,g=(c?.multipliers??[]).map(u=>({currencyId:u.currencyId,currencySlug:u.currencySlug,multiplier:u.multiplierBp/1e4})),p=g.some(u=>u.multiplier>1);return m.boost=p&&c?.expiresInDays?{active:p,multipliers:g,expiresInDays:c.expiresInDays}:{active:p,multipliers:g},m}var ut=1e4,k=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??C,this.inbound=new h(this.clock),this.outbound=new h(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(s=>T(s,e.origin))||H(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=b["gem.handshake"]?.(e.data);if(r)return this.refuse(e,`malformed handshake: ${r}`),false;let a=e.data;if(!T(a.embedder,e.origin))return this.refuse(e,`handshake claims embedder '${a.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=B(f,a.versions);return d===null?(i.onmessage=null,i.postMessage({gem:l,type:"gem.error",code:"version_mismatch",message:`frame supports v${f.min}..v${f.max}`}),i.close(),this.transition("refused"),this.options.onError?.("version_mismatch"),false):(this.port=i,this.version=d,i.onmessage=s=>this.receive(s.data,s.ports??[]),i.start?.(),this.peerCapabilities=a.capabilities??[],this.unbidden=a.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=ut){return this.state!=="waiting"?Promise.resolve(this.state):new Promise(t=>{let r=i=>{this.clock.clearTimeout(a),t(i);},a=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.state!=="connected"||!this.parentSupports("audioState")?false:(this.send({gem:l,type:"gem.audioState",muted:e}),true)}reportEngaged(){return this.engagedSent||this.state!=="connected"||!this.parentSupports("engagement")||!this.send({gem:l,type:"gem.engaged"})?false:(this.engagedSent=true,true)}cueReward(e){if(this.state!=="connected"||!this.parentSupports("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:U(e.origin.x),y:U(e.origin.y)}),this.send(t),true}showPortraitBorders(e){let t=F(e);return t===void 0||this.state!=="connected"||!this.parentSupports("portraitBorders")?false:this.send(t===null?{gem:l,type:"gem.portraitBorders"}:{gem:l,type:"gem.portraitBorders",name:t})}setWalletVisible(e,t){return this.state!=="connected"||!this.parentSupports("walletDisplay")?false:this.send({gem:l,type:"gem.walletDisplay",...lt(e,t?.only)})}setMenu(e,t){return this.state!=="connected"||!this.parentSupports("gameMenu")?false:this.send({gem:l,type:"gem.menu",...dt(e,t)})}requestShare(e){return this.state!=="connected"||!this.parentSupports("share")?false:this.send({gem:l,type:"gem.requestShare",params:e.map(({key:t,value:r})=>({key:t,value:r}))})}requestVibrate(e){return this.state!=="connected"||!this.parentSupports("vibration")?false:this.send({gem:l,type:"gem.vibrate",pattern:[...e]})}reportFrameStats(e){return this.state!=="connected"||!this.parentSupports("frameStats")?false:(this.send({gem:l,type:"gem.frameStats",fps:W(e.fps,1e3),frameTimeP95Ms:W(e.frameTimeP95Ms,1e5)}),true)}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,a,i,d){return this.send({gem:l,type:"gem.requestPurchase",requestId:e,purchaseKind:t,targetId:r,currencySlug:a,...i===void 0?{}:{quantity:i},...d===void 0?{}:{catalogId:d}})}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,a){return this.send({gem:l,type:"gem.requestFriendChallenge",requestId:e,playerId:t,template:r,...a===void 0?{}:{params:a}})}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(x)){this.options.onDropped?.(e,t);return}this.fail(e,t);}dropUnknownType(e){this.inbound.allow(x)&&this.options.onDropped?.("unsupported",`ignored unknown message type '${e}'`);}refuse(e,t){e.ports?.[0]?.close?.(),this.inbound.allow(x)&&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}});}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=b[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||N(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 a=b[r];if(!a)return this.dropUnknownType(r),false;if(!this.inbound.allow(r))return this.fail("rate_limited",`parent exceeded the limit for ${r}`),false;let i=j(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=a(e);if(d)return this.fail("invalid_message",`${r}: ${d}`),false;let s=e;if(s.v!==this.version)return this.fail("invalid_message",`${r}: expected v ${String(this.version)}`),false;switch(r){case "gem.token":this.options.onToken?.(s);break;case "gem.pause":this.options.onPause?.(s);break;case "gem.menuSelect":this.options.onMenuSelect?.(s);break;case "gem.prefs":this.options.onPrefs?.(s);break;case "gem.cohorts":this.options.onCohorts?.(s);break;case "gem.earnAllowanceChanged":this.options.onEarnAllowanceChanged?.();break;case "gem.viewport":this.options.onViewport?.(s);break;case "gem.willTerminate":this.options.onWillTerminate?.(s);break;case "gem.devtools":this.options.onDevtools?.(s.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 c={maxWidth:s.maxWidth,maxHeight:s.maxHeight};if(!this.options.onScreenshot){m.close(),this.screenshotDenied("not_wired",false);break}return N(t.slice(1)),this.options.onScreenshot(c,m,(g,p)=>this.screenshotDenied(g,p)),true}case "gem.token.denied":this.options.onTokenDenied?.(s);break;case "gem.localServer":this.options.onLocalServer?.(s);break;case "gem.localServer.denied":this.options.onLocalServerDenied?.(s);break;case "gem.player":{this.options.onPlayer?.(mt(s));break}case "gem.roomEvent":this.options.onRoomEvent?.(s);break;case "gem.seatedEvent":this.options.onSeatedEvent?.(s);break;case "gem.autoStartFailedEvent":this.options.onAutoStartFailedEvent?.(s);break;case "gem.socketState":this.options.onSocketState?.(s);break;case "gem.signalEvent":this.options.onSignalEvent?.(s);break;case "gem.dedicatedEvent":this.options.onDedicatedEvent?.(s);break;case "gem.clusterTarget":this.options.onClusterTarget?.(s);break;case "gem.partyResult":this.options.onPartyResult?.(s);break;case "gem.purchaseResult":this.options.onPurchaseResult?.(s);break;case "gem.deviceSettings":this.options.onDeviceSettings?.(s);break;case "gem.deviceSettings.result":this.options.onDeviceSettingsResult?.(s);break;case "gem.adResult":this.options.onAdResult?.(s);break;case "gem.signInResult":this.options.onSignInResult?.(s);break;case "gem.friendChallengeResult":this.options.onFriendChallengeResult?.(s);break;case "gem.error":this.options.onError?.(s.code,s.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 N(n){for(let e of n)try{e?.close?.();}catch{}}I();function ct(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 k({...n,expectedSource:n.expectedSource??window.parent}),t=r=>{let a=e.handleWindowMessage({data:r.data,origin:r.origin,source:r.source,ports:r.ports});return a&&window.removeEventListener("message",t),a};return window.addEventListener("message",t),q(window,t),e}var V={connect:ct,GemFrame:k,PROTOCOL:l,SUPPORTED_VERSIONS:f};window.GemWebSdkBridge=V;var Ct=V;return Ct;})();