@indiegems/gem-web-sdk 7.9.0 → 8.0.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,105 @@ 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
+ ## 8.0.0
20
+
21
+ *Written from the API facts alone; no summary was generated for this release.*
22
+
23
+ Upgrading from 7.9.1. Impact: required.
24
+
25
+ ### Must change
26
+
27
+ - BucketConfig changed its signature.
28
+ - FRAME_TO_PARENT changed its signature.
29
+ - FrameMessage changed its signature.
30
+ - GemCapability changed its signature.
31
+
32
+ ### New capability
33
+
34
+ - FriendChallenge was added.
35
+ - FriendChallengesPage was added.
36
+ - FriendsApi.inbox was added.
37
+ - FriendsApi.launchedChallenge was added.
38
+ - FriendsApi.markAnswered was added.
39
+ - FriendsApiDependencies.launchedChallengeId was added.
40
+ - ListFriendChallengesOptions was added.
41
+ - Gem.vibration was added.
42
+ - GemFrame.requestVibrate was added.
43
+ - VibrationApi was added.
44
+ - GemVibrate was added.
45
+ - HostCallbacks.onVibrate was added.
46
+ - HostOptions.onVibrate was added.
47
+ - validateGemVibrate was added.
48
+
49
+ ## 7.9.1
50
+
51
+ Upgrading from 7.9.0. Impact: none.
52
+
53
+ Nothing in this release asks anything of a game.
54
+
55
+ ## 7.9.0
56
+
57
+ Upgrading from 7.8.1. Impact: required.
58
+
59
+ ### Must change
60
+
61
+ - A link your game shares can no longer carry a parameter named build. The Arcade now reads that key for itself and removes it before your game starts, so the share request refuses it with a TypeError that names the key. Rename the parameter if your game shares one by that name.
62
+
63
+ ### Rebuild
64
+
65
+ - GemCapability gained gameMenu, and the bridge's message lists and unions in both directions gained the two new menu messages. A switch that assumes it knows every GemCapability value must handle the new one. Other code that compiles today keeps compiling.
66
+
67
+ ### New capability
68
+
69
+ - gem.setMenu adds to the Arcade's menu, the one control the Arcade keeps over a game in its top right corner. Give onSettings and the menu gains a settings entry that opens your own settings screen, and give items for up to four entries of your own, each with an id, a label you have already translated and an onSelect handler. Each call is the whole answer and replaces the last, so call it again when the entries change. It returns true when the Arcade was told. After awaitBridge has settled, draw a settings button of your own only when it returns false. The Arcade pauses your game while its menu is open and resumes it before your handler runs.
70
+
71
+ ## 7.8.1
72
+
73
+ Upgrading from 7.8.0. Impact: none.
74
+
75
+ Nothing in this release asks anything of a game.
76
+
77
+ ## 7.8.0
78
+
79
+ Upgrading from 7.7.0. Impact: recommended.
80
+
81
+ ### May stop
82
+
83
+ - The SDK now stops accidental text selection, the long-press copy menu and the tap highlight across your game's document, so a game can drop its own rules for that. Your own style rules always win, and inputs, text areas and editable content stay typeable and selectable. Text a player could select and copy before no longer is, unless your own styles make it selectable. Pass selectableText as true to createGem only if your game is mostly text a player should be able to copy.
84
+
85
+ ### New capability
86
+
87
+ - A room says whether it is self-hosted in selfHosted: its dedicated server runs on the machine of the player who created it, as it does in the Gem editor. The SDK asks for such a room on your behalf where the embedder hosts locally, and there is no option for a game to set. It is false on every room a player in the Arcade is in.
88
+
89
+ ## 7.7.0
90
+
91
+ Upgrading from 7.6.0. Impact: required.
92
+
93
+ ### Must change
94
+
95
+ - In the server API types, occurred_at on a leaderboard row and on an entity leaderboard row is now optional and may be null. Code that assumes it is always a number must handle it missing. LeaderboardResponse and EntityLeaderboardResponse are now written as the shared LeaderboardPeriodFields joined with their own fields, so every field they had is still there.
96
+
97
+ ### Rebuild
98
+
99
+ - Server API unions gained values. OrderSource has earning_reset, and InventoryChange has a new earning_limits_reset change. A switch that assumes it knows every OrderSource value or every InventoryChange type must handle the new one. Other code that compiles today keeps compiling.
100
+ - The server API reads getLeaderboard and getEntityLeaderboard accept three more options, periods_back, period and player_id, and the option types GetLeaderboardOptions and EntityLeaderboardOptions now extend the new PeriodOptions. Code that compiles today keeps compiling.
101
+
102
+ ### New capability
103
+
104
+ - gem.leaderboards can read a board scoped to one period of a challenge, such as today's board or this week's. Every read takes periodsBack, where 0 is the current period and 1 is the one before, or period, the id of a period from an earlier result. Name at most one of them. A result from such a board carries period, which says which period it is, when it opens and closes, and whether it is final. A serverless function or a dedicated server passes playerId so the board answers for that player's own day. On a board that is not scoped to periods, both selectors are refused rather than ignored.
105
+
106
+ ## 7.6.0
107
+
108
+ Upgrading from 7.5.0. Impact: required.
109
+
110
+ ### Must change
111
+
112
+ - createGem now throws GemUnframedError when the page is opened on its own instead of inside a frame. Before, such a game constructed and then waited for a bridge that never came, with no player, no saves and no config. Run your game where it is framed and handed an identity: the Arcade, the Gem editor or the Gem dev host. A game that is only ever played there changes nothing. When the framing page is not one the game allows, the refusal is now final: awaitBridge, awaitIdentity, awaitPlayer and awaitCohorts answer at once instead of timing out.
113
+
114
+ ### New capability
115
+
116
+ - A serverless function written in JavaScript can use the SDK through a new function entry of the package. createGem there returns the same platform-backed calls a browser game makes, bound to the player who called the function. Nothing is retried, a conditional save is refused before it is sent, and gem.functions and gem.gameConfig throw because a function has neither. This entry is in the package only.
117
+
19
118
  ## 7.5.0
20
119
 
21
120
  Upgrading from 7.4.2. Impact: required.
package/README.md CHANGED
@@ -27,6 +27,7 @@ Read them here rather than guessing from the type declarations, which carry sign
27
27
  | a symbol on the server side — `defineServer` and what a match's server is handed | [`docs/api/api-reference-server.md`](docs/api/api-reference-server.md) |
28
28
  | saving a player's progress | [`docs/saving-player-progress.md`](docs/saving-player-progress.md) |
29
29
  | asking the player to sign in | [`docs/player-sign-in.md`](docs/player-sign-in.md) |
30
+ | vibrating the player's device, the iPhone included | [`docs/vibration.md`](docs/vibration.md) |
30
31
  | leaderboards | [`docs/leaderboards.md`](docs/leaderboards.md) |
31
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) |
32
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) |
@@ -158,6 +158,7 @@ type Boundary = {
158
158
  };
159
159
  type BucketConfig = Boundary & {
160
160
  "grant_sources"?: OrderSource[];
161
+ "max_balance"?: number | null;
161
162
  "name": string;
162
163
  "priority": number;
163
164
  "reset_amount"?: number | null;
@@ -721,6 +722,24 @@ interface ListFriendsOptions {
721
722
  readonly cursor?: string;
722
723
  readonly signal?: AbortSignal;
723
724
  }
725
+ interface FriendChallenge {
726
+ readonly id: string;
727
+ readonly from: Friend;
728
+ readonly template: string;
729
+ readonly params: Readonly<Record<string, string | number>>;
730
+ readonly createdAt: number;
731
+ readonly openedAt?: number;
732
+ readonly answeredAt?: number;
733
+ }
734
+ interface FriendChallengesPage {
735
+ readonly challenges: readonly FriendChallenge[];
736
+ readonly nextCursor?: string;
737
+ }
738
+ interface ListFriendChallengesOptions {
739
+ readonly limit?: number;
740
+ readonly cursor?: string;
741
+ readonly signal?: AbortSignal;
742
+ }
724
743
  interface FriendChallengeRequest {
725
744
  readonly playerId: string;
726
745
  readonly template: string;
@@ -744,12 +763,18 @@ declare class FriendChallengeError extends GemApiError {
744
763
  }
745
764
  interface FriendsApiDependencies {
746
765
  readonly challenge?: (request: FriendChallengeRequest) => Promise<FriendChallengeOutcome>;
766
+ readonly launchedChallengeId?: string;
747
767
  }
748
768
  declare class FriendsApi {
749
769
  #private;
750
770
  constructor(api: GameApi, dependencies?: FriendsApiDependencies);
751
771
  list(options?: ListFriendsOptions): Promise<FriendsPage>;
752
772
  challenge(request: FriendChallengeRequest): Promise<FriendChallengeOutcome>;
773
+ inbox(options?: ListFriendChallengesOptions): Promise<FriendChallengesPage>;
774
+ launchedChallenge(options?: {
775
+ readonly signal?: AbortSignal;
776
+ }): Promise<FriendChallenge | null>;
777
+ markAnswered(id: string): Promise<void>;
753
778
  }
754
779
  interface LeaderboardPeriod {
755
780
  readonly id: string;
@@ -991,4 +1016,4 @@ interface PlayerBoost {
991
1016
  readonly multipliers: readonly PlayerBoostMultiplier[];
992
1017
  readonly expiresInDays?: number;
993
1018
  }
994
- export { AnalyticsApi, type AnalyticsApiOptions, type AnalyticsFlushOptions, type AnalyticsFlushResult, type AnalyticsOptions, type AnalyticsRejection, type AnalyticsValue, AuthError, type AuthFailure, type AuthState, type Base64String, type Boundary, type BucketConfig, type BucketResetInterval, type BytesResponse, CONDITIONAL_HEADERS, type CacheParam, type Challenge, type ChallengeWindow, ChallengesApi, type Character, CharactersApi, type ClientOptions, type Clock, type ConditionalRequestHeaders, type ConfiguredPurchasePayment, type ConfiguredPurchaseRequest, type ConfiguredPurchaseResult, type CreateCharacterOptions, CurrenciesApi, type CurrencyBalance, type CurrencyBucket, type CurrencyReadOptions, type CurrencyRow, type DescribeSaveOptions, type DirectPurchaseRequest, type DirectPurchaseResult, type EarnAllowance, type EarnAllowanceEvent, type EarnAllowancePeriod, type EarnAllowanceReadOptions, type EarnAllowanceSignal, type EntityLeaderboard, type EntityLeaderboardEntry, type EntityLeaderboardOptions, EntityReadCache, type EntityRef, type EntityScope, type EntityType, type Friend, FriendChallengeError, type FriendChallengeErrorCode, type FriendChallengeOutcome, type FriendChallengeOutcomeKind, type FriendChallengeRequest, FriendsApi, type FriendsApiDependencies, type FriendsPage, type FunctionContext, type FunctionFailure, type FunctionInvokeOptions, type FunctionResult, type GameApi, type GameOrderSource, GemApiError, GemClient, type GemErrorReason, type GemFunction, GemFunctionError, type GemFunctionIdentity, GemSaveError, type GetLeaderboardOptions, type GetSaveOptions, type GetSettingOptions, type InitiateTransferOptions, InventoryApi, type InventoryItem, type InventoryOperation, type InventorySnapshot, type ItemCategory, type Leaderboard, type LeaderboardEntry, type LeaderboardPeriod, LeaderboardsApi, type ListChallengesOptions, type ListFriendsOptions, type ListSavesOptions, type ListTransfersOptions, type LootRoll, MAX_PERIODS_BACK, MutationsApi, type Order, type OrderOptions, type OrderPageOptions, type OrderResult, type OrderSource, OrdersApi, type Page, type PeriodOptions, PlatformApi, PlatformCurrenciesApi, type PlatformCurrency, type PlatformCurrencyAccess, type PlatformCurrencyPurchasePayment, type PlatformCurrencyPurchaseRequest, type PlatformCurrencyPurchaseResult, type PlatformCurrencyReadOptions, PlatformEarnAllowanceApi, type PlatformEventName, type PlatformPrice, type PlayerBadge, type PlayerBoost, type PlayerBoostMultiplier, type PlayerIdentity, type PlayerProfile, PlayerText, type ProfileCallOptions, type ProfileShowcaseEntry, ProfilesApi, type Progression, type ProgressionAchievement, ProgressionsApi, type PurchaseOptions, type PutBytesOptions, type PutSaveOptions, type PutSettingOptions, type RankedRow, type RecipeAvailability, type RecipeChange, type RecipeLock, type RecipeResult, type RecipeUsage, type RecipeUsageList, type RequestOptions, type SavePage, type SaveRecord, SavesApi, type SavesOptions, type SessionEndReason, type Setting, SettingsApi, ShowcaseApi, type ShowcaseCallOptions, type ShowcaseFriendEntry, type ShowcaseFriends, type ShowcaseValue, type SlotInfo, type SnapshotCurrency, type SnapshotItem, type SnapshotOptions, type SnapshotPageOptions, type TokenGrant, type Transfer, type TransferDirection, TransfersApi, type Transport, TransportRefusal, type TransportRequest, type TransportResponse, type VersionedGetOptions, type VersionedResponse, asPlayerText, createGem, mapIdentity, platformIconUrl, text, toBase64 };
1019
+ export { AnalyticsApi, type AnalyticsApiOptions, type AnalyticsFlushOptions, type AnalyticsFlushResult, type AnalyticsOptions, type AnalyticsRejection, type AnalyticsValue, AuthError, type AuthFailure, type AuthState, type Base64String, type Boundary, type BucketConfig, type BucketResetInterval, type BytesResponse, CONDITIONAL_HEADERS, type CacheParam, type Challenge, type ChallengeWindow, ChallengesApi, type Character, CharactersApi, type ClientOptions, type Clock, type ConditionalRequestHeaders, type ConfiguredPurchasePayment, type ConfiguredPurchaseRequest, type ConfiguredPurchaseResult, type CreateCharacterOptions, CurrenciesApi, type CurrencyBalance, type CurrencyBucket, type CurrencyReadOptions, type CurrencyRow, type DescribeSaveOptions, type DirectPurchaseRequest, type DirectPurchaseResult, type EarnAllowance, type EarnAllowanceEvent, type EarnAllowancePeriod, type EarnAllowanceReadOptions, type EarnAllowanceSignal, type EntityLeaderboard, type EntityLeaderboardEntry, type EntityLeaderboardOptions, EntityReadCache, type EntityRef, type EntityScope, type EntityType, type Friend, type FriendChallenge, FriendChallengeError, type FriendChallengeErrorCode, type FriendChallengeOutcome, type FriendChallengeOutcomeKind, type FriendChallengeRequest, type FriendChallengesPage, FriendsApi, type FriendsApiDependencies, type FriendsPage, type FunctionContext, type FunctionFailure, type FunctionInvokeOptions, type FunctionResult, type GameApi, type GameOrderSource, GemApiError, GemClient, type GemErrorReason, type GemFunction, GemFunctionError, type GemFunctionIdentity, GemSaveError, type GetLeaderboardOptions, type GetSaveOptions, type GetSettingOptions, type InitiateTransferOptions, InventoryApi, type InventoryItem, type InventoryOperation, type InventorySnapshot, type ItemCategory, type Leaderboard, type LeaderboardEntry, type LeaderboardPeriod, LeaderboardsApi, type ListChallengesOptions, type ListFriendChallengesOptions, type ListFriendsOptions, type ListSavesOptions, type ListTransfersOptions, type LootRoll, MAX_PERIODS_BACK, MutationsApi, type Order, type OrderOptions, type OrderPageOptions, type OrderResult, type OrderSource, OrdersApi, type Page, type PeriodOptions, PlatformApi, PlatformCurrenciesApi, type PlatformCurrency, type PlatformCurrencyAccess, type PlatformCurrencyPurchasePayment, type PlatformCurrencyPurchaseRequest, type PlatformCurrencyPurchaseResult, type PlatformCurrencyReadOptions, PlatformEarnAllowanceApi, type PlatformEventName, type PlatformPrice, type PlayerBadge, type PlayerBoost, type PlayerBoostMultiplier, type PlayerIdentity, type PlayerProfile, PlayerText, type ProfileCallOptions, type ProfileShowcaseEntry, ProfilesApi, type Progression, type ProgressionAchievement, ProgressionsApi, type PurchaseOptions, type PutBytesOptions, type PutSaveOptions, type PutSettingOptions, type RankedRow, type RecipeAvailability, type RecipeChange, type RecipeLock, type RecipeResult, type RecipeUsage, type RecipeUsageList, type RequestOptions, type SavePage, type SaveRecord, SavesApi, type SavesOptions, type SessionEndReason, type Setting, SettingsApi, ShowcaseApi, type ShowcaseCallOptions, type ShowcaseFriendEntry, type ShowcaseFriends, type ShowcaseValue, type SlotInfo, type SnapshotCurrency, type SnapshotItem, type SnapshotOptions, type SnapshotPageOptions, type TokenGrant, type Transfer, type TransferDirection, TransfersApi, type Transport, TransportRefusal, type TransportRequest, type TransportResponse, type VersionedGetOptions, type VersionedResponse, asPlayerText, createGem, mapIdentity, platformIconUrl, text, toBase64 };
package/dist/game.d.ts CHANGED
@@ -154,6 +154,7 @@ type Boundary = {
154
154
  type BucketColumn = "bucket_1" | "bucket_2";
155
155
  type BucketConfig = Boundary & {
156
156
  "grant_sources"?: OrderSource[];
157
+ "max_balance"?: number | null;
157
158
  "name": string;
158
159
  "priority": number;
159
160
  "reset_amount"?: number | null;
@@ -1255,6 +1256,24 @@ interface ListFriendsOptions {
1255
1256
  readonly cursor?: string;
1256
1257
  readonly signal?: AbortSignal;
1257
1258
  }
1259
+ interface FriendChallenge {
1260
+ readonly id: string;
1261
+ readonly from: Friend;
1262
+ readonly template: string;
1263
+ readonly params: Readonly<Record<string, string | number>>;
1264
+ readonly createdAt: number;
1265
+ readonly openedAt?: number;
1266
+ readonly answeredAt?: number;
1267
+ }
1268
+ interface FriendChallengesPage {
1269
+ readonly challenges: readonly FriendChallenge[];
1270
+ readonly nextCursor?: string;
1271
+ }
1272
+ interface ListFriendChallengesOptions {
1273
+ readonly limit?: number;
1274
+ readonly cursor?: string;
1275
+ readonly signal?: AbortSignal;
1276
+ }
1258
1277
  interface FriendChallengeRequest {
1259
1278
  readonly playerId: string;
1260
1279
  readonly template: string;
@@ -1278,12 +1297,18 @@ declare class FriendChallengeError extends GemApiError {
1278
1297
  }
1279
1298
  interface FriendsApiDependencies {
1280
1299
  readonly challenge?: (request: FriendChallengeRequest) => Promise<FriendChallengeOutcome>;
1300
+ readonly launchedChallengeId?: string;
1281
1301
  }
1282
1302
  declare class FriendsApi {
1283
1303
  #private;
1284
1304
  constructor(api: GameApi, dependencies?: FriendsApiDependencies);
1285
1305
  list(options?: ListFriendsOptions): Promise<FriendsPage>;
1286
1306
  challenge(request: FriendChallengeRequest): Promise<FriendChallengeOutcome>;
1307
+ inbox(options?: ListFriendChallengesOptions): Promise<FriendChallengesPage>;
1308
+ launchedChallenge(options?: {
1309
+ readonly signal?: AbortSignal;
1310
+ }): Promise<FriendChallenge | null>;
1311
+ markAnswered(id: string): Promise<void>;
1287
1312
  }
1288
1313
  type PlatformCurrencyAccess = "read" | "spend";
1289
1314
  interface PlatformCurrency {
@@ -2706,6 +2731,7 @@ declare class GemFrame {
2706
2731
  readonly key: string;
2707
2732
  readonly value: string;
2708
2733
  }>): boolean;
2734
+ requestVibrate(pattern: readonly number[]): boolean;
2709
2735
  reportFrameStats(stats: {
2710
2736
  fps: number;
2711
2737
  frameTimeP95Ms: number;
@@ -2737,6 +2763,10 @@ interface ShareApi {
2737
2763
  readonly available: boolean;
2738
2764
  request(request?: ShareRequest): void;
2739
2765
  }
2766
+ interface VibrationApi {
2767
+ readonly available: boolean;
2768
+ vibrate(pattern: number | readonly number[]): boolean;
2769
+ }
2740
2770
  type AdFormat = "interstitial" | "rewarded";
2741
2771
  interface AdRequest {
2742
2772
  placement: string;
@@ -2864,6 +2894,7 @@ interface Gem {
2864
2894
  readonly ads: AdsApi;
2865
2895
  readonly account: AccountApi;
2866
2896
  readonly share: ShareApi;
2897
+ readonly vibration: VibrationApi;
2867
2898
  readonly analytics: AnalyticsApi;
2868
2899
  readonly leaderboards: LeaderboardsApi;
2869
2900
  readonly challenges: ChallengesApi;
@@ -2906,4 +2937,4 @@ interface ExitAnalytics {
2906
2937
  }
2907
2938
  declare function leaveAndExit(rooms: ExitRooms, bridge: ExitBridge | null, reason?: string, analytics?: ExitAnalytics): Promise<void>;
2908
2939
  declare function createGem(options?: GemOptions): Gem;
2909
- 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, FriendChallengeError, type FriendChallengeErrorCode, type FriendChallengeOutcome, type FriendChallengeOutcomeKind, type FriendChallengeRequest, 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 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 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 WalletVisibleOptions, asPlayerText, createBootTimeline, createGem, leaveAndExit, mapIdentity, markOnResolve, platformIconUrl, presentJoinCredential, readTemplateTransports, readTransportAdvert, reportOnResolve, text, webTransportAvailable };
2940
+ 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 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 B(){return typeof document>"u"?void 0:document.readyState}var E=()=>Date.now();function I(t={}){let e=t.win??window,n=e,r=n[w];if(r!==void 0)return r;let o=t.readyState??B,i=t.now??E,l=[],s=[],m=c=>{let p=c.data;!p||p.type!=="gem.handshake"||(l.length>=4&&(l.shift(),s.shift(),u.dropped+=1),l.push(c),s.push(i()));};e.addEventListener("message",m);let u={events:l,times:s,dropped:0,late:o()==="complete",uninstall(){e.removeEventListener("message",m);}};return n[w]=u,u}function q(t,e,n={}){let r=t[w];if(r===void 0)return null;let o=n.ttlMs??9500,i=n.now??E,l=r.events.splice(0),s=r.times?.splice(0),m=0,u=0,c=false,p=i()-o;for(let g=l.length-1;g>=0;g--){let P=s?.[g];if(P!==void 0&&P<p){u+=1;continue}if(m+=1,e(l[g])===true){c=true;break}}return r.uninstall(),{capture:r,delivered:m,stale:u,accepted:c}}var d="gem-web-bridge",f={min:1,max:1},y=65536,L=8,v=5e3,A=1024;function R(t){return Object.freeze(Object.assign(Object.create(null),t))}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.frameStats":120,"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 z=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.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.menu":"gameMenu","gem.menuSelect":"gameMenu"}),K=Object.freeze([["gem.asyncOpponents.","asyncOpponents"],["gem.viewport.","reservedAreas"]]);function _(t){let e=z[t];if(e!==void 0)return e;for(let[n,r]of K)if(t.startsWith(n))return r}function Y(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 X(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 J(t){return /^[a-z]{2,8}(-[a-z0-9]{1,8})*$/i.test(t)}function Q(t){return /^[a-z_]+$/.test(t)}function S(t,e,n){if(e>L)return `nesting deeper than ${L}`;if(++n.nodes>v)return `more than ${v} values`;if(n.bytes>y)return `over the ${y} 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 o=t;if(n.seen.has(o))return "a repeated or cyclic object reference";if(n.seen.add(o),Array.isArray(t)){if(t.length>A)return `an array of ${t.length} entries, over the ${A} limit`;n.bytes+=2;for(let s of t){let m=S(s,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 l=t;for(let s in l){if(!Object.prototype.hasOwnProperty.call(l,s))continue;if(++n.nodes>v)return `more than ${v} values`;if(n.bytes+=s.length*3+4,n.bytes>y)return `over the ${y} byte limit`;let m=S(l[s],e+1,n);if(m)return m}return null}function Z(t){let e={nodes:0,bytes:0,seen:new Set},n=S(t,0,e);return n?`message contains ${n}`:e.bytes>y?`message is over the ${y} byte limit`:null}var ee={origin:[Y,"not a well-formed origin"],url:[X,"not a safe absolute http(s) URL"],bcp47:[J,"not a well-formed BCP 47 tag"],code:[Q,"not a code of lower-case letters and underscores"]};function M(t,e,n){for(let r of e){let o=n===""?r.n:`${n}.${r.n}`,i=t[r.n];if(i==null){if(r.o)continue;return `${o}: required`}let l=D(i,r,o);if(l)return l}return null}function D(t,e,n){switch(e.k){case "string":{if(typeof t!="string")return `${n}: expected string`;if(t.length>e.max)return `${n}: exceeds ${e.max} characters`;if(e.f){let[r,o]=ee[e.f];if(!r(t))return `${n}: ${o}`}return null}case "int":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 "boolean":return typeof t=="boolean"?null:`${n}: expected boolean`;case "enum":{let r=e.v;return r.includes(t)?null:`${n}: not one of ${r.join("|")}`}case "object":return typeof t!="object"||t===null||Array.isArray(t)?`${n}: expected object`:M(t,e.fs,n);case "json":return typeof t!="object"||t===null||Array.isArray(t)?`${n}: expected a plain object`:null;case "array":{if(!Array.isArray(t))return `${n}: expected array`;if(t.length>e.max)return `${n}: exceeds ${e.max} items`;let r=e.it,o=`${n}[]`;for(let i of t){if(i==null){if(r.o)continue;return `${o}: required`}let l=D(i,r,o);if(l)return l}return null}default:{let r=e.k;return `${n}: unknown kind ${String(r)}`}}}function a(t,e){return n=>{let r=Z(n);if(r)return r;if(typeof n!="object"||n===null||Array.isArray(n))return "message: expected object";let o=n;return o.gem!==d?"gem: wrong protocol marker":o.type!==t?`type: expected ${t}`:M(o,e,"")}}var ne=a("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}]),te=a("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}}]),re=a("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}]),oe=a("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}]),ae=a("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}]}]),se=a("gem.pause",[{n:"paused",k:"boolean"}]),ie=a("gem.prefs",[{n:"reducedMotion",k:"boolean"},{n:"muted",k:"boolean"},{n:"showFrameStats",k:"boolean",o:1},{n:"locale",k:"string",max:35,f:"bcp47"}]),le=a("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}]}}]),de=a("gem.earnAllowanceChanged",[]),me=a("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}]}}]),ge=a("gem.deviceSettings",[{n:"settings",k:"json",o:1}]),ue=a("gem.willTerminate",[{n:"reason",k:"enum",v:["grant_expiring","session_ended","navigating","kill_switch"]},{n:"graceMs",k:"int",lo:0,hi:6e4}]),ce=a("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"]}]),pe=a("gem.socketState",[{n:"connected",k:"boolean"},{n:"reason",k:"enum",o:1,v:["connecting","dropped","watchdog","terminal"]}]),ye=a("gem.seatedEvent",[{n:"roomId",k:"string",max:64}]),fe=a("gem.autoStartFailedEvent",[{n:"roomId",k:"string",max:64},{n:"code",k:"string",max:64}]),he=a("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"}]),ke=a("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}]),ve=a("gem.partyResult",[{n:"requestId",k:"string",max:64},{n:"partyId",k:"string",o:1,max:64}]),xe=a("gem.clusterTarget",[{n:"clusterTargetId",k:"string",max:64},{n:"clusterTargetIds",k:"array",o:1,max:3,it:{n:"",k:"string",max:64}}]),be=a("gem.devtools",[{n:"action",k:"enum",v:["open","close","toggle"]}]),we=a("gem.screenshot",[{n:"maxWidth",k:"int",lo:1,hi:7680},{n:"maxHeight",k:"int",lo:1,hi:4320}]),Se=a("gem.screenshot.denied",[{n:"reason",k:"enum",v:["not_wired","no_source","unsupported","unreadable","tainted","too_large","busy","declined","failed"]},{n:"retryable",k:"boolean"}]),Re=a("gem.requestContext",[]),Ge=a("gem.gameContext",[{n:"context",k:"json"}]),Oe=a("gem.signal",[{n:"signal",k:"enum",v:["join","offer","answer","ice","migrationAck","hostUnreachable"]},{n:"matchId",k:"string",max:64},{n:"data",k:"json"}]),Ce=a("gem.dedicatedOffer",[{n:"matchId",k:"string",max:64},{n:"sdp",k:"string",max:10240},{n:"intent",k:"enum",v:["initial","ice_restart","full_reconnect"]}]),Te=a("gem.partyRequest",[{n:"requestId",k:"string",max:64}]),Pe=a("gem.ready",[]),Ee=a("gem.engaged",[]),Ie=a("gem.progress",[{n:"loaded",k:"int",lo:0,hi:1099511627776},{n:"total",k:"int",lo:0,hi:1099511627776}]),qe=a("gem.requestToken",[{n:"requestId",k:"string",max:64},{n:"reason",k:"enum",v:["initial","expiring","rejected"]}]),Le=a("gem.requestLocalServer",[{n:"requestId",k:"string",max:64},{n:"gameRoomId",k:"string",max:64}]),Ae=a("gem.localServer",[{n:"requestId",k:"string",max:64},{n:"serverId",k:"string",o:1,max:128}]),je=a("gem.localServer.denied",[{n:"requestId",k:"string",max:64},{n:"retryable",k:"boolean"},{n:"reason",k:"enum",v:["refused","unavailable"]}]),_e=a("gem.exit",[{n:"reason",k:"string",o:1,max:64}]),Me=a("gem.openExternal",[{n:"url",k:"string",max:2048,f:"url"}]),De=a("gem.requestFullscreen",[{n:"enabled",k:"boolean"}]),Fe=a("gem.audioState",[{n:"muted",k:"boolean"}]),$e=a("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}]}]),He=a("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=a("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=a("gem.menuSelect",[{n:"entry",k:"enum",v:["settings","item"]},{n:"id",k:"string",o:1,max:32}]),Ne=a("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=a("gem.frameStats",[{n:"fps",k:"int",lo:0,hi:1e3},{n:"frameTimeP95Ms",k:"int",lo:0,hi:1e5}]),Be=a("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}]),ze=a("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}]),Ke=a("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}]),Ye=a("gem.deviceSettings.put",[{n:"requestId",k:"string",max:64},{n:"settings",k:"json"}]),Xe=a("gem.deviceSettings.result",[{n:"requestId",k:"string",max:64},{n:"outcome",k:"enum",v:["stored","too_large","unavailable"]}]),Je=a("gem.requestAd",[{n:"requestId",k:"string",max:64},{n:"placement",k:"string",max:32},{n:"format",k:"enum",v:["interstitial","rewarded"]}]),Qe=a("gem.adResult",[{n:"requestId",k:"string",max:64},{n:"outcome",k:"enum",v:["shown","no_ad","unavailable"]}]),Ze=a("gem.requestSignIn",[{n:"requestId",k:"string",max:64}]),en=a("gem.signInResult",[{n:"requestId",k:"string",max:64},{n:"outcome",k:"enum",v:["signed_in","declined","unavailable"]}]),nn=a("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}]),tn=a("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":te,"gem.token":re,"gem.token.denied":oe,"gem.player":ae,"gem.pause":se,"gem.prefs":ie,"gem.cohorts":le,"gem.earnAllowanceChanged":de,"gem.viewport":me,"gem.deviceSettings":ge,"gem.willTerminate":ue,"gem.roomEvent":ce,"gem.socketState":pe,"gem.seatedEvent":ye,"gem.autoStartFailedEvent":fe,"gem.signalEvent":he,"gem.dedicatedEvent":ke,"gem.partyResult":ve,"gem.clusterTarget":xe,"gem.devtools":be,"gem.screenshot":we,"gem.screenshot.denied":Se,"gem.requestContext":Re,"gem.gameContext":Ge,"gem.signal":Oe,"gem.dedicatedOffer":Ce,"gem.partyRequest":Te,"gem.ready":Pe,"gem.engaged":Ee,"gem.progress":Ie,"gem.requestToken":qe,"gem.requestLocalServer":Le,"gem.localServer":Ae,"gem.localServer.denied":je,"gem.exit":_e,"gem.openExternal":Me,"gem.requestFullscreen":De,"gem.audioState":Fe,"gem.rewardCue":$e,"gem.walletDisplay":He,"gem.menu":Ue,"gem.menuSelect":We,"gem.requestShare":Ne,"gem.frameStats":Ve,"gem.error":Be,"gem.requestPurchase":ze,"gem.purchaseResult":Ke,"gem.deviceSettings.put":Ye,"gem.deviceSettings.result":Xe,"gem.requestAd":Je,"gem.adResult":Qe,"gem.requestSignIn":Ze,"gem.signInResult":en,"gem.requestFriendChallenge":nn,"gem.friendChallengeResult":tn});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(t){return new G(t)}var C={now:()=>Date.now(),setTimeout:(t,e)=>setTimeout(t,e),clearTimeout:t=>clearTimeout(t)},h=class{constructor(e=C){this.clock=e;}clock;tokens=new Map;lastRefill=new Map;allow(e){let n=j[e];if(n===void 0)return false;let r=this.clock.now(),o=this.lastRefill.get(e)??r,i=this.tokens.get(e)??n,l=Math.max(0,r-o),s=Math.min(n,i+l*n/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(t,e){return t.toLowerCase()===e.toLowerCase()}function F(t){let e=t.toLowerCase();return e==="localhost"||e.endsWith(".localhost")||e==="[::1]"||e==="::1"?true:/^127(\.\d{1,3}){3}$/.test(e)}function $(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:F(n.hostname)&&F(r.hostname)}function H(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 U(t){return Math.min(16384,Math.max(0,Math.round(Number.isFinite(t)?t:0)))}function rn(t,e){if(t!==true)return {visible:false};let n=[],r=false;for(let o of Array.isArray(e)?e:[])o==="score"?r=true:typeof o=="string"&&o.length>0&&o.length<=64&&!n.includes(o)&&n.push(o);return !r&&n.length===0?{visible:true}:{visible:true,currencies:n.slice(0,8),score:r}}function on(t,e){let n=[];for(let r of Array.isArray(e)?e:[]){if(n.length===4)break;if(typeof r!="object"||r===null)continue;let{id:o,label:i}=r;typeof o!="string"||o.length===0||o.length>32||typeof i!="string"||i.trim().length===0||n.some(l=>l.id===o)||n.push({id:o,label:i.trim().slice(0,40)});}return n.length===0?{settings:t===true}:{settings:t===true,items:n}}function W(t,e){return Math.min(e,Math.max(0,Math.round(Number.isFinite(t)?t:0)))}function an(t){let e=t.untrusted,n=O(e.displayName),r=e.displayTag||e.displayHandle,o=r?O(r):void 0,i=t.discriminator||t.displayTag,l=i&&/^[0-9]{1,8}$/.test(i)?i:void 0,s=t.avatarIconUrl||t.avatarUrl,m={displayName:n,displayHandle:o??n,badges:(t.badges??[]).map(g=>({itemId:g.itemId,iconUrl:g.iconUrl}))};t.playerId&&(m.playerId=t.playerId),l&&(m.discriminator=l),o&&(m.displayTag=o),s&&(m.avatarIconUrl=m.avatarUrl=s);let u=t.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 sn=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))||$(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 o=e.data;if(!T(o.embedder,e.origin))return this.refuse(e,`handshake claims embedder '${o.embedder}' but arrived from '${e.origin}'`),false;let i=e.ports?.[0];if(!i)return this.refuse(e,"handshake transferred no MessagePort"),false;let l=H(f,o.versions);return l===null?(i.onmessage=null,i.postMessage({gem:d,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=l,i.onmessage=s=>this.receive(s.data,s.ports??[]),i.start?.(),this.peerCapabilities=o.capabilities??[],this.unbidden=o.unbidden===true,i.postMessage({gem:d,type:"gem.handshake.accept",v:l,...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:d,type:"gem.ready"});}settled(e=sn){return this.state!=="waiting"?Promise.resolve(this.state):new Promise(n=>{let r=i=>{this.clock.clearTimeout(o),n(i);},o=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:d,type:"gem.progress",loaded:e,total:n});}requestToken(e,n){this.send({gem:d,type:"gem.requestToken",requestId:e,reason:n});}requestLocalServer(e,n){return this.parentSupports("localHost")?(this.send({gem:d,type:"gem.requestLocalServer",requestId:e,gameRoomId:n}),true):false}exit(e){this.send(e===void 0?{gem:d,type:"gem.exit"}:{gem:d,type:"gem.exit",reason:e});}openExternal(e){this.send({gem:d,type:"gem.openExternal",url:e});}requestFullscreen(e){this.send({gem:d,type:"gem.requestFullscreen",enabled:e});}reportMuted(e){return this.state!=="connected"||!this.parentSupports("audioState")?false:(this.send({gem:d,type:"gem.audioState",muted:e}),true)}reportEngaged(){return this.engagedSent||this.state!=="connected"||!this.parentSupports("engagement")||!this.send({gem:d,type:"gem.engaged"})?false:(this.engagedSent=true,true)}cueReward(e){if(this.state!=="connected"||!this.parentSupports("rewardCue"))return false;let n={gem:d,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:U(e.origin.x),y:U(e.origin.y)}),this.send(n),true}setWalletVisible(e,n){return this.state!=="connected"||!this.parentSupports("walletDisplay")?false:this.send({gem:d,type:"gem.walletDisplay",...rn(e,n?.only)})}setMenu(e,n){return this.state!=="connected"||!this.parentSupports("gameMenu")?false:this.send({gem:d,type:"gem.menu",...on(e,n)})}requestShare(e){return this.state!=="connected"||!this.parentSupports("share")?false:this.send({gem:d,type:"gem.requestShare",params:e.map(({key:n,value:r})=>({key:n,value:r}))})}reportFrameStats(e){return this.state!=="connected"||!this.parentSupports("frameStats")?false:(this.send({gem:d,type:"gem.frameStats",fps:W(e.fps,1e3),frameTimeP95Ms:W(e.frameTimeP95Ms,1e5)}),true)}sendGameContext(e){return this.state!=="connected"?false:(this.send({gem:d,type:"gem.gameContext",context:e}),true)}signal(e,n,r){this.send({gem:d,type:"gem.signal",signal:e,matchId:n,data:r});}dedicatedOffer(e,n,r){this.send({gem:d,type:"gem.dedicatedOffer",matchId:e,sdp:n,intent:r});}requestParty(e){return this.send({gem:d,type:"gem.partyRequest",requestId:e})}requestPurchase(e,n,r,o,i,l){return this.send({gem:d,type:"gem.requestPurchase",requestId:e,purchaseKind:n,targetId:r,currencySlug:o,...i===void 0?{}:{quantity:i},...l===void 0?{}:{catalogId:l}})}putDeviceSettings(e,n){return this.send({gem:d,type:"gem.deviceSettings.put",requestId:e,settings:n})}requestAd(e,n,r){return this.send({gem:d,type:"gem.requestAd",requestId:e,placement:n,format:r})}requestSignIn(e){return this.send({gem:d,type:"gem.requestSignIn",requestId:e})}requestFriendChallenge(e,n,r,o){return this.send({gem:d,type:"gem.requestFriendChallenge",requestId:e,playerId:n,template:r,...o===void 0?{}:{params:o}})}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(x)){this.options.onDropped?.(e,n);return}this.fail(e,n);}dropUnknownType(e){this.inbound.allow(x)&&this.options.onDropped?.("unsupported",`ignored unknown message type '${e}'`);}refuse(e,n){e.ports?.[0]?.close?.(),this.inbound.allow(x)&&this.options.onRefused?.(n);}fail(e,n){this.options.onError?.(e,n),this.state==="connected"&&this.port&&this.send({gem:d,type:"gem.error",code:e,...n===void 0?{}:{message:n}});}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=b[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||N(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 o=b[r];if(!o)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 l=o(e);if(l)return this.fail("invalid_message",`${r}: ${l}`),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=n[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(n.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?.(an(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,n){this.send({gem:d,type:"gem.screenshot.denied",reason:e,retryable:n});}};function N(t){for(let e of t)try{e?.close?.();}catch{}}I();function ln(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 k({...t,expectedSource:t.expectedSource??window.parent}),n=r=>{let o=e.handleWindowMessage({data:r.data,origin:r.origin,source:r.source,ports:r.ports});return o&&window.removeEventListener("message",n),o};return window.addEventListener("message",n),q(window,n),e}var V={connect:ln,GemFrame:k,PROTOCOL:d,SUPPORTED_VERSIONS:f};window.GemWebSdkBridge=V;var bn=V;return bn;})();
1
+ var GemWebSdkBridgeBundle=(function(){'use strict';var w="GemWebSdkHandshake";function B(){return typeof document>"u"?void 0:document.readyState}var E=()=>Date.now();function I(t={}){let e=t.win??window,n=e,r=n[w];if(r!==void 0)return r;let a=t.readyState??B,i=t.now??E,l=[],s=[],m=c=>{let p=c.data;!p||p.type!=="gem.handshake"||(l.length>=4&&(l.shift(),s.shift(),u.dropped+=1),l.push(c),s.push(i()));};e.addEventListener("message",m);let u={events:l,times:s,dropped:0,late:a()==="complete",uninstall(){e.removeEventListener("message",m);}};return n[w]=u,u}function q(t,e,n={}){let r=t[w];if(r===void 0)return null;let a=n.ttlMs??9500,i=n.now??E,l=r.events.splice(0),s=r.times?.splice(0),m=0,u=0,c=false,p=i()-a;for(let g=l.length-1;g>=0;g--){let P=s?.[g];if(P!==void 0&&P<p){u+=1;continue}if(m+=1,e(l[g])===true){c=true;break}}return r.uninstall(),{capture:r,delivered:m,stale:u,accepted:c}}var d="gem-web-bridge",f={min:1,max:1},y=65536,L=8,v=5e3,A=1024;function R(t){return Object.freeze(Object.assign(Object.create(null),t))}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.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 z=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.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"}),K=Object.freeze([["gem.asyncOpponents.","asyncOpponents"],["gem.vibration.","vibration"],["gem.viewport.","reservedAreas"]]);function _(t){let e=z[t];if(e!==void 0)return e;for(let[n,r]of K)if(t.startsWith(n))return r}function Y(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 X(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 J(t){return /^[a-z]{2,8}(-[a-z0-9]{1,8})*$/i.test(t)}function Q(t){return /^[a-z_]+$/.test(t)}function S(t,e,n){if(e>L)return `nesting deeper than ${L}`;if(++n.nodes>v)return `more than ${v} values`;if(n.bytes>y)return `over the ${y} 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 a=t;if(n.seen.has(a))return "a repeated or cyclic object reference";if(n.seen.add(a),Array.isArray(t)){if(t.length>A)return `an array of ${t.length} entries, over the ${A} limit`;n.bytes+=2;for(let s of t){let m=S(s,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 l=t;for(let s in l){if(!Object.prototype.hasOwnProperty.call(l,s))continue;if(++n.nodes>v)return `more than ${v} values`;if(n.bytes+=s.length*3+4,n.bytes>y)return `over the ${y} byte limit`;let m=S(l[s],e+1,n);if(m)return m}return null}function Z(t){let e={nodes:0,bytes:0,seen:new Set},n=S(t,0,e);return n?`message contains ${n}`:e.bytes>y?`message is over the ${y} byte limit`:null}var ee={origin:[Y,"not a well-formed origin"],url:[X,"not a safe absolute http(s) URL"],bcp47:[J,"not a well-formed BCP 47 tag"],code:[Q,"not a code of lower-case letters and underscores"]};function M(t,e,n){for(let r of e){let a=n===""?r.n:`${n}.${r.n}`,i=t[r.n];if(i==null){if(r.o)continue;return `${a}: required`}let l=D(i,r,a);if(l)return l}return null}function D(t,e,n){switch(e.k){case "string":{if(typeof t!="string")return `${n}: expected string`;if(t.length>e.max)return `${n}: exceeds ${e.max} characters`;if(e.f){let[r,a]=ee[e.f];if(!r(t))return `${n}: ${a}`}return null}case "int":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 "boolean":return typeof t=="boolean"?null:`${n}: expected boolean`;case "enum":{let r=e.v;return r.includes(t)?null:`${n}: not one of ${r.join("|")}`}case "object":return typeof t!="object"||t===null||Array.isArray(t)?`${n}: expected object`:M(t,e.fs,n);case "json":return typeof t!="object"||t===null||Array.isArray(t)?`${n}: expected a plain object`:null;case "array":{if(!Array.isArray(t))return `${n}: expected array`;if(t.length>e.max)return `${n}: exceeds ${e.max} items`;let r=e.it,a=`${n}[]`;for(let i of t){if(i==null){if(r.o)continue;return `${a}: required`}let l=D(i,r,a);if(l)return l}return null}default:{let r=e.k;return `${n}: unknown kind ${String(r)}`}}}function o(t,e){return n=>{let r=Z(n);if(r)return r;if(typeof n!="object"||n===null||Array.isArray(n))return "message: expected object";let a=n;return a.gem!==d?"gem: wrong protocol marker":a.type!==t?`type: expected ${t}`: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}]),te=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}}]),re=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}]),oe=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}]),ae=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}]}]),se=o("gem.pause",[{n:"paused",k:"boolean"}]),ie=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"}]),le=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}]}}]),de=o("gem.earnAllowanceChanged",[]),me=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}]}}]),ge=o("gem.deviceSettings",[{n:"settings",k:"json",o:1}]),ue=o("gem.willTerminate",[{n:"reason",k:"enum",v:["grant_expiring","session_ended","navigating","kill_switch"]},{n:"graceMs",k:"int",lo:0,hi:6e4}]),ce=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"]}]),pe=o("gem.socketState",[{n:"connected",k:"boolean"},{n:"reason",k:"enum",o:1,v:["connecting","dropped","watchdog","terminal"]}]),ye=o("gem.seatedEvent",[{n:"roomId",k:"string",max:64}]),fe=o("gem.autoStartFailedEvent",[{n:"roomId",k:"string",max:64},{n:"code",k:"string",max:64}]),he=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"}]),ke=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}]),ve=o("gem.partyResult",[{n:"requestId",k:"string",max:64},{n:"partyId",k:"string",o:1,max:64}]),xe=o("gem.clusterTarget",[{n:"clusterTargetId",k:"string",max:64},{n:"clusterTargetIds",k:"array",o:1,max:3,it:{n:"",k:"string",max:64}}]),be=o("gem.devtools",[{n:"action",k:"enum",v:["open","close","toggle"]}]),we=o("gem.screenshot",[{n:"maxWidth",k:"int",lo:1,hi:7680},{n:"maxHeight",k:"int",lo:1,hi:4320}]),Se=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"}]),Re=o("gem.requestContext",[]),Ge=o("gem.gameContext",[{n:"context",k:"json"}]),Oe=o("gem.signal",[{n:"signal",k:"enum",v:["join","offer","answer","ice","migrationAck","hostUnreachable"]},{n:"matchId",k:"string",max:64},{n:"data",k:"json"}]),Ce=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"]}]),Te=o("gem.partyRequest",[{n:"requestId",k:"string",max:64}]),Pe=o("gem.ready",[]),Ee=o("gem.engaged",[]),Ie=o("gem.progress",[{n:"loaded",k:"int",lo:0,hi:1099511627776},{n:"total",k:"int",lo:0,hi:1099511627776}]),qe=o("gem.requestToken",[{n:"requestId",k:"string",max:64},{n:"reason",k:"enum",v:["initial","expiring","rejected"]}]),Le=o("gem.requestLocalServer",[{n:"requestId",k:"string",max:64},{n:"gameRoomId",k:"string",max:64}]),Ae=o("gem.localServer",[{n:"requestId",k:"string",max:64},{n:"serverId",k:"string",o:1,max:128}]),je=o("gem.localServer.denied",[{n:"requestId",k:"string",max:64},{n:"retryable",k:"boolean"},{n:"reason",k:"enum",v:["refused","unavailable"]}]),_e=o("gem.exit",[{n:"reason",k:"string",o:1,max:64}]),Me=o("gem.openExternal",[{n:"url",k:"string",max:2048,f:"url"}]),De=o("gem.requestFullscreen",[{n:"enabled",k:"boolean"}]),Fe=o("gem.audioState",[{n:"muted",k:"boolean"}]),$e=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}]}]),He=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}}]),Be=o("gem.frameStats",[{n:"fps",k:"int",lo:0,hi:1e3},{n:"frameTimeP95Ms",k:"int",lo:0,hi:1e5}]),ze=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}]),Ke=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}]),Ye=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}]),Xe=o("gem.deviceSettings.put",[{n:"requestId",k:"string",max:64},{n:"settings",k:"json"}]),Je=o("gem.deviceSettings.result",[{n:"requestId",k:"string",max:64},{n:"outcome",k:"enum",v:["stored","too_large","unavailable"]}]),Qe=o("gem.requestAd",[{n:"requestId",k:"string",max:64},{n:"placement",k:"string",max:32},{n:"format",k:"enum",v:["interstitial","rewarded"]}]),Ze=o("gem.adResult",[{n:"requestId",k:"string",max:64},{n:"outcome",k:"enum",v:["shown","no_ad","unavailable"]}]),en=o("gem.requestSignIn",[{n:"requestId",k:"string",max:64}]),nn=o("gem.signInResult",[{n:"requestId",k:"string",max:64},{n:"outcome",k:"enum",v:["signed_in","declined","unavailable"]}]),tn=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}]),rn=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":te,"gem.token":re,"gem.token.denied":oe,"gem.player":ae,"gem.pause":se,"gem.prefs":ie,"gem.cohorts":le,"gem.earnAllowanceChanged":de,"gem.viewport":me,"gem.deviceSettings":ge,"gem.willTerminate":ue,"gem.roomEvent":ce,"gem.socketState":pe,"gem.seatedEvent":ye,"gem.autoStartFailedEvent":fe,"gem.signalEvent":he,"gem.dedicatedEvent":ke,"gem.partyResult":ve,"gem.clusterTarget":xe,"gem.devtools":be,"gem.screenshot":we,"gem.screenshot.denied":Se,"gem.requestContext":Re,"gem.gameContext":Ge,"gem.signal":Oe,"gem.dedicatedOffer":Ce,"gem.partyRequest":Te,"gem.ready":Pe,"gem.engaged":Ee,"gem.progress":Ie,"gem.requestToken":qe,"gem.requestLocalServer":Le,"gem.localServer":Ae,"gem.localServer.denied":je,"gem.exit":_e,"gem.openExternal":Me,"gem.requestFullscreen":De,"gem.audioState":Fe,"gem.rewardCue":$e,"gem.walletDisplay":He,"gem.menu":Ue,"gem.menuSelect":We,"gem.requestShare":Ne,"gem.vibrate":Ve,"gem.frameStats":Be,"gem.error":ze,"gem.requestPurchase":Ke,"gem.purchaseResult":Ye,"gem.deviceSettings.put":Xe,"gem.deviceSettings.result":Je,"gem.requestAd":Qe,"gem.adResult":Ze,"gem.requestSignIn":en,"gem.signInResult":nn,"gem.requestFriendChallenge":tn,"gem.friendChallengeResult":rn});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(t){return new G(t)}var C={now:()=>Date.now(),setTimeout:(t,e)=>setTimeout(t,e),clearTimeout:t=>clearTimeout(t)},h=class{constructor(e=C){this.clock=e;}clock;tokens=new Map;lastRefill=new Map;allow(e){let n=j[e];if(n===void 0)return false;let r=this.clock.now(),a=this.lastRefill.get(e)??r,i=this.tokens.get(e)??n,l=Math.max(0,r-a),s=Math.min(n,i+l*n/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(t,e){return t.toLowerCase()===e.toLowerCase()}function F(t){let e=t.toLowerCase();return e==="localhost"||e.endsWith(".localhost")||e==="[::1]"||e==="::1"?true:/^127(\.\d{1,3}){3}$/.test(e)}function $(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:F(n.hostname)&&F(r.hostname)}function H(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 U(t){return Math.min(16384,Math.max(0,Math.round(Number.isFinite(t)?t:0)))}function on(t,e){if(t!==true)return {visible:false};let n=[],r=false;for(let a of Array.isArray(e)?e:[])a==="score"?r=true:typeof a=="string"&&a.length>0&&a.length<=64&&!n.includes(a)&&n.push(a);return !r&&n.length===0?{visible:true}:{visible:true,currencies:n.slice(0,8),score:r}}function an(t,e){let n=[];for(let r of Array.isArray(e)?e:[]){if(n.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||n.some(l=>l.id===a)||n.push({id:a,label:i.trim().slice(0,40)});}return n.length===0?{settings:t===true}:{settings:t===true,items:n}}function W(t,e){return Math.min(e,Math.max(0,Math.round(Number.isFinite(t)?t:0)))}function sn(t){let e=t.untrusted,n=O(e.displayName),r=e.displayTag||e.displayHandle,a=r?O(r):void 0,i=t.discriminator||t.displayTag,l=i&&/^[0-9]{1,8}$/.test(i)?i:void 0,s=t.avatarIconUrl||t.avatarUrl,m={displayName:n,displayHandle:a??n,badges:(t.badges??[]).map(g=>({itemId:g.itemId,iconUrl:g.iconUrl}))};t.playerId&&(m.playerId=t.playerId),l&&(m.discriminator=l),a&&(m.displayTag=a),s&&(m.avatarIconUrl=m.avatarUrl=s);let u=t.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 ln=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))||$(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 l=H(f,a.versions);return l===null?(i.onmessage=null,i.postMessage({gem:d,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=l,i.onmessage=s=>this.receive(s.data,s.ports??[]),i.start?.(),this.peerCapabilities=a.capabilities??[],this.unbidden=a.unbidden===true,i.postMessage({gem:d,type:"gem.handshake.accept",v:l,...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:d,type:"gem.ready"});}settled(e=ln){return this.state!=="waiting"?Promise.resolve(this.state):new Promise(n=>{let r=i=>{this.clock.clearTimeout(a),n(i);},a=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:d,type:"gem.progress",loaded:e,total:n});}requestToken(e,n){this.send({gem:d,type:"gem.requestToken",requestId:e,reason:n});}requestLocalServer(e,n){return this.parentSupports("localHost")?(this.send({gem:d,type:"gem.requestLocalServer",requestId:e,gameRoomId:n}),true):false}exit(e){this.send(e===void 0?{gem:d,type:"gem.exit"}:{gem:d,type:"gem.exit",reason:e});}openExternal(e){this.send({gem:d,type:"gem.openExternal",url:e});}requestFullscreen(e){this.send({gem:d,type:"gem.requestFullscreen",enabled:e});}reportMuted(e){return this.state!=="connected"||!this.parentSupports("audioState")?false:(this.send({gem:d,type:"gem.audioState",muted:e}),true)}reportEngaged(){return this.engagedSent||this.state!=="connected"||!this.parentSupports("engagement")||!this.send({gem:d,type:"gem.engaged"})?false:(this.engagedSent=true,true)}cueReward(e){if(this.state!=="connected"||!this.parentSupports("rewardCue"))return false;let n={gem:d,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:U(e.origin.x),y:U(e.origin.y)}),this.send(n),true}setWalletVisible(e,n){return this.state!=="connected"||!this.parentSupports("walletDisplay")?false:this.send({gem:d,type:"gem.walletDisplay",...on(e,n?.only)})}setMenu(e,n){return this.state!=="connected"||!this.parentSupports("gameMenu")?false:this.send({gem:d,type:"gem.menu",...an(e,n)})}requestShare(e){return this.state!=="connected"||!this.parentSupports("share")?false:this.send({gem:d,type:"gem.requestShare",params:e.map(({key:n,value:r})=>({key:n,value:r}))})}requestVibrate(e){return this.state!=="connected"||!this.parentSupports("vibration")?false:this.send({gem:d,type:"gem.vibrate",pattern:[...e]})}reportFrameStats(e){return this.state!=="connected"||!this.parentSupports("frameStats")?false:(this.send({gem:d,type:"gem.frameStats",fps:W(e.fps,1e3),frameTimeP95Ms:W(e.frameTimeP95Ms,1e5)}),true)}sendGameContext(e){return this.state!=="connected"?false:(this.send({gem:d,type:"gem.gameContext",context:e}),true)}signal(e,n,r){this.send({gem:d,type:"gem.signal",signal:e,matchId:n,data:r});}dedicatedOffer(e,n,r){this.send({gem:d,type:"gem.dedicatedOffer",matchId:e,sdp:n,intent:r});}requestParty(e){return this.send({gem:d,type:"gem.partyRequest",requestId:e})}requestPurchase(e,n,r,a,i,l){return this.send({gem:d,type:"gem.requestPurchase",requestId:e,purchaseKind:n,targetId:r,currencySlug:a,...i===void 0?{}:{quantity:i},...l===void 0?{}:{catalogId:l}})}putDeviceSettings(e,n){return this.send({gem:d,type:"gem.deviceSettings.put",requestId:e,settings:n})}requestAd(e,n,r){return this.send({gem:d,type:"gem.requestAd",requestId:e,placement:n,format:r})}requestSignIn(e){return this.send({gem:d,type:"gem.requestSignIn",requestId:e})}requestFriendChallenge(e,n,r,a){return this.send({gem:d,type:"gem.requestFriendChallenge",requestId:e,playerId:n,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 n of this.settleWaiters.splice(0))n(e);this.options.onStateChange?.(e);}}refuseMalformed(e,n){if(!this.inbound.allow(x)){this.options.onDropped?.(e,n);return}this.fail(e,n);}dropUnknownType(e){this.inbound.allow(x)&&this.options.onDropped?.("unsupported",`ignored unknown message type '${e}'`);}refuse(e,n){e.ports?.[0]?.close?.(),this.inbound.allow(x)&&this.options.onRefused?.(n);}fail(e,n){this.options.onError?.(e,n),this.state==="connected"&&this.port&&this.send({gem:d,type:"gem.error",code:e,...n===void 0?{}:{message:n}});}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=b[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||N(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 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 l=a(e);if(l)return this.fail("invalid_message",`${r}: ${l}`),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=n[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(n.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?.(sn(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,n){this.send({gem:d,type:"gem.screenshot.denied",reason:e,retryable:n});}};function N(t){for(let e of t)try{e?.close?.();}catch{}}I();function dn(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 k({...t,expectedSource:t.expectedSource??window.parent}),n=r=>{let a=e.handleWindowMessage({data:r.data,origin:r.origin,source:r.source,ports:r.ports});return a&&window.removeEventListener("message",n),a};return window.addEventListener("message",n),q(window,n),e}var V={connect:dn,GemFrame:k,PROTOCOL:d,SUPPORTED_VERSIONS:f};window.GemWebSdkBridge=V;var wn=V;return wn;})();