@indiegems/gem-web-sdk 12.0.0 → 13.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,43 @@ Its entries are grouped under up to five headings:
16
16
  - **Rebuild**: a type changed. Recompile against the new version; code that compiles today keeps compiling unless the entry says otherwise.
17
17
  - **New capability**: something a game can now do. Nothing changes unless you use it.
18
18
 
19
+ ## 13.1.0
20
+
21
+ Upgrading from 13.0.0. Impact: required.
22
+
23
+ ### Rebuild
24
+
25
+ - Avatar3dFamily now also accepts adult_human alongside small_human. Recompile your game. If any code switches over the family and assumes small_human is the only named value, add handling for adult_human or a sensible default.
26
+ - The list of messages a frame sends to its parent, the FrameMessage type, and the GemCapability type each gained a member for the Gem button corner (the gem.gemCorner message and the gemCorner capability). Recompile your game. If your code matches these unions exhaustively, add a case for the new member.
27
+
28
+ ### New capability
29
+
30
+ - Your game can now ask the Arcade to move its Gem button to another corner by calling setGemCorner, using the GemCorner type for the value. Check that the gemCorner capability is available before relying on it, since the Arcade decides whether to honour the request.
31
+ - The adult_human avatar rig family is now available, and AVATAR_RIGS exposes the node and parent trees of both the small_human and adult_human rigs, described by the AvatarRigNode and AvatarRigs types. The package also ships a reference rig for adult_human, reachable through a new rigs export. Use these to attach items or animations to the right nodes of either family.
32
+
33
+ ## 13.0.0
34
+
35
+ Upgrading from 12.0.0. Impact: required.
36
+
37
+ ### Must change
38
+
39
+ - The controls declaration is gone. Remove every call that declares controls, along with any code that builds a controls declaration or a control choice, because these no longer exist and the game will not compile against them. Follow the updated settings guidance for how the game now exposes settings and controls.
40
+ - If you embed the game in your own host, remove the controls-declare callback from the host options and callbacks, because the host no longer receives that message and the property is no longer accepted.
41
+ - setMenu no longer takes a settings flag as its first argument. Pass only the optional list of menu items. Also remove any onSettings handler from the game menu, since that handler is gone.
42
+
43
+ ### Rebuild
44
+
45
+ - The purchase refusal code gains a new value, already_owned, for purchases of something the player already has. Recompile; if the game switches over refusal codes exhaustively, add a branch for it.
46
+ - The list of messages a game frame sends to its parent, the frame message type, and the capability names each gain an entry for 3D avatar purchases, including the new avatar3dPurchases capability. Recompiling is enough unless the game or host switches over these values exhaustively.
47
+
48
+ ### New capability
49
+
50
+ - A game can now work with 3D avatars. The new avatars3d API lists the avatar rig families the game supports, reports the avatar a player wears per family, lists avatar offers and their prices, starts a purchase, and notifies the game when the worn avatar changes. Purchases are also available through the frame, gated by the avatar3dPurchases capability, and are answered like other purchases. Outside the Arcade, avatar purchases are unavailable immediately.
51
+ - The worn 3D avatar, one per rig family, is now available on the current player and on other players' data, including friends, leaderboard entries, profiles, showcase friends, player identities and room members. Use it to render other players with the avatar they wear.
52
+ - The game configuration can now declare the 3D avatar families the game supports through avatar_3d_families.
53
+ - If you embed games in your own host, you can now supply worn 3D avatars when sending player information, handle 3D avatar purchase requests with the new request callback, and validate those requests with the new validator and message type.
54
+ - Server-side code can now read the worn 3D avatars in avatars_3d on player and subject identity data, using the new worn avatar type.
55
+
19
56
  ## 12.0.0
20
57
 
21
58
  Upgrading from 11.1.2. Impact: required.
@@ -699,6 +699,13 @@ interface PlayerBadge {
699
699
  readonly itemId: string;
700
700
  readonly iconUrl: string;
701
701
  }
702
+ type Avatar3dFamily = "small_human" | "adult_human" | (string & {});
703
+ interface WornAvatar3d {
704
+ readonly family: Avatar3dFamily;
705
+ readonly id: string;
706
+ readonly modelUrl: string;
707
+ readonly iconUrl: string;
708
+ }
702
709
  interface PlayerIdentity {
703
710
  readonly playerId?: string;
704
711
  readonly displayName?: PlayerText;
@@ -709,6 +716,7 @@ interface PlayerIdentity {
709
716
  readonly avatar3dId?: string;
710
717
  readonly avatar3dModelUrl?: string;
711
718
  readonly avatar3dIconUrl?: string;
719
+ readonly avatars3d?: readonly WornAvatar3d[];
712
720
  readonly badges: readonly PlayerBadge[];
713
721
  }
714
722
  declare function mapIdentity(row: unknown): PlayerIdentity;
@@ -1019,4 +1027,4 @@ interface PlayerBoost {
1019
1027
  readonly multipliers: readonly PlayerBoostMultiplier[];
1020
1028
  readonly expiresInDays?: number;
1021
1029
  }
1022
- 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 };
1030
+ export { AnalyticsApi, type AnalyticsApiOptions, type AnalyticsFlushOptions, type AnalyticsFlushResult, type AnalyticsOptions, type AnalyticsRejection, type AnalyticsValue, AuthError, type AuthFailure, type AuthState, type Avatar3dFamily, 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, type WornAvatar3d, asPlayerText, createGem, mapIdentity, platformIconUrl, text, toBase64 };
package/dist/game.d.ts CHANGED
@@ -202,6 +202,7 @@ type GameConfigSnapshot = {
202
202
  "analytics_events"?: SnapshotAnalyticsEvent[];
203
203
  "analytics_funnels"?: SnapshotAnalyticsFunnel[];
204
204
  "async_opponent_types"?: SnapshotAsyncOpponentType[];
205
+ "avatar_3d_families"?: string[];
205
206
  "catalogs": SnapshotCatalog[];
206
207
  "currencies": SnapshotCurrency[];
207
208
  "friend_challenge_templates"?: SnapshotFriendChallengeTemplate[];
@@ -1166,6 +1167,13 @@ interface PlayerBadge {
1166
1167
  readonly itemId: string;
1167
1168
  readonly iconUrl: string;
1168
1169
  }
1170
+ type Avatar3dFamily = "small_human" | "adult_human" | (string & {});
1171
+ interface WornAvatar3d {
1172
+ readonly family: Avatar3dFamily;
1173
+ readonly id: string;
1174
+ readonly modelUrl: string;
1175
+ readonly iconUrl: string;
1176
+ }
1169
1177
  interface PlayerIdentity {
1170
1178
  readonly playerId?: string;
1171
1179
  readonly displayName?: PlayerText;
@@ -1176,6 +1184,7 @@ interface PlayerIdentity {
1176
1184
  readonly avatar3dId?: string;
1177
1185
  readonly avatar3dModelUrl?: string;
1178
1186
  readonly avatar3dIconUrl?: string;
1187
+ readonly avatars3d?: readonly WornAvatar3d[];
1179
1188
  readonly badges: readonly PlayerBadge[];
1180
1189
  }
1181
1190
  declare function mapIdentity(row: unknown): PlayerIdentity;
@@ -2725,7 +2734,7 @@ interface GemMatchApi {
2725
2734
  serve(server: GemMatchServerModule, options?: MatchServeOptions): Promise<MatchHosting>;
2726
2735
  connect(options?: MatchConnectOptions): Promise<MatchConnection>;
2727
2736
  }
2728
- type PurchaseRefusalCode = "unknown_currency" | "currency_not_in_game_payable" | "not_purchasable" | "no_price_in_currency" | "busy" | "cancelled" | "insufficient_funds" | "price_mismatch" | "config_version_stale" | "platform_currency_unavailable" | "not_available" | "recipe_locked" | "recipe_on_cooldown" | "recipe_max_uses_exceeded" | "item_max_stack_exceeded" | "recipe_costs_unmet" | "quantity_invalid" | "error";
2737
+ type PurchaseRefusalCode = "unknown_currency" | "currency_not_in_game_payable" | "not_purchasable" | "no_price_in_currency" | "busy" | "cancelled" | "insufficient_funds" | "price_mismatch" | "config_version_stale" | "platform_currency_unavailable" | "not_available" | "recipe_locked" | "already_owned" | "recipe_on_cooldown" | "recipe_max_uses_exceeded" | "item_max_stack_exceeded" | "recipe_costs_unmet" | "quantity_invalid" | "error";
2729
2738
  declare class PurchaseRefusal extends RangeError {
2730
2739
  readonly code: Extract<PurchaseRefusalCode, "unknown_currency" | "not_purchasable" | "no_price_in_currency" | "quantity_invalid">;
2731
2740
  readonly retryable: false;
@@ -2748,6 +2757,31 @@ type PurchaseOutcome = {
2748
2757
  interface PurchaseApi {
2749
2758
  request(req: PurchaseRequest): Promise<PurchaseOutcome>;
2750
2759
  }
2760
+ interface Avatar3dPurchaseRequest {
2761
+ itemId: string;
2762
+ currencySlug: string;
2763
+ }
2764
+ interface Avatar3dPrice {
2765
+ readonly currencySlug: string;
2766
+ readonly price: number;
2767
+ }
2768
+ interface Avatar3dOffer {
2769
+ readonly itemId: string;
2770
+ readonly slug: string;
2771
+ readonly family: Avatar3dFamily;
2772
+ readonly displayName: string;
2773
+ readonly description?: string;
2774
+ readonly iconUrl: string;
2775
+ readonly modelUrl: string;
2776
+ readonly prices: readonly Avatar3dPrice[];
2777
+ }
2778
+ interface Avatars3dApi {
2779
+ families(): Promise<readonly Avatar3dFamily[]>;
2780
+ worn(family?: Avatar3dFamily): WornAvatar3d | undefined;
2781
+ offers(): Promise<readonly Avatar3dOffer[]>;
2782
+ purchase(request: Avatar3dPurchaseRequest): Promise<PurchaseOutcome>;
2783
+ onChange(listener: (worn: readonly WornAvatar3d[]) => void): () => void;
2784
+ }
2751
2785
  type SignInOutcomeKind = "signed_in" | "declined" | "unavailable";
2752
2786
  interface SignInOutcome {
2753
2787
  readonly outcome: SignInOutcomeKind;
@@ -2765,13 +2799,6 @@ interface PlayerBoost {
2765
2799
  readonly multipliers: readonly PlayerBoostMultiplier[];
2766
2800
  readonly expiresInDays?: number;
2767
2801
  }
2768
- type GemControlChoice = "player" | "game";
2769
- interface GemControlsDeclaration {
2770
- readonly lookSensitivity?: GemControlChoice;
2771
- readonly gamepadLookSensitivity?: GemControlChoice;
2772
- readonly invertLookY?: GemControlChoice;
2773
- readonly touchMovement?: GemControlChoice;
2774
- }
2775
2802
  interface RewardCue {
2776
2803
  currencySlug: string;
2777
2804
  expected?: number;
@@ -2780,6 +2807,7 @@ interface RewardCue {
2780
2807
  y: number;
2781
2808
  };
2782
2809
  }
2810
+ type GemCorner = "top-left" | "top-right" | "bottom-left" | "bottom-right";
2783
2811
  type FrameState = "waiting" | "connected" | "refused" | "closed";
2784
2812
  interface FramePlayer extends PlayerIdentity {
2785
2813
  readonly displayName: PlayerText;
@@ -2870,11 +2898,11 @@ declare class GemFrame {
2870
2898
  setWalletVisible(visible: boolean, options?: {
2871
2899
  only?: readonly string[];
2872
2900
  }): boolean;
2873
- declareControls(uses: GemControlsDeclaration): boolean;
2874
- setMenu(settings: boolean, items?: ReadonlyArray<{
2901
+ setMenu(items?: ReadonlyArray<{
2875
2902
  readonly id: string;
2876
2903
  readonly label: string;
2877
2904
  }>): boolean;
2905
+ setGemCorner(corner: GemCorner): boolean;
2878
2906
  requestShare(params: ReadonlyArray<{
2879
2907
  readonly key: string;
2880
2908
  readonly value: string;
@@ -2890,6 +2918,7 @@ declare class GemFrame {
2890
2918
  dedicatedOffer(matchId: string, sdp: string, intent: GemDedicatedOffer["intent"]): void;
2891
2919
  requestParty(requestId: string): boolean;
2892
2920
  requestPurchase(requestId: string, purchaseKind: "item" | "recipe", targetId: string, currencySlug: string, quantity?: number, catalogId?: string): boolean;
2921
+ requestAvatar3dPurchase(requestId: string, itemId: string, currencySlug: string): boolean;
2893
2922
  putDeviceSettings(requestId: string, settings: Readonly<Record<string, unknown>>): boolean;
2894
2923
  requestAd(requestId: string, placement: string, format: "interstitial" | "rewarded"): boolean;
2895
2924
  requestSignIn(requestId: string): boolean;
@@ -2900,6 +2929,7 @@ declare class GemFrame {
2900
2929
  private dropUnknownType;
2901
2930
  private refuse;
2902
2931
  private fail;
2932
+ private gated;
2903
2933
  private send;
2904
2934
  private receive;
2905
2935
  private dispatchInbound;
@@ -2943,7 +2973,6 @@ interface GemLook {
2943
2973
  set(options: GemLookOptions): void;
2944
2974
  }
2945
2975
  interface ControlsApi {
2946
- declare(uses: GemControlsDeclaration): boolean;
2947
2976
  look(options?: GemLookOptions): GemLook;
2948
2977
  readonly LOOK_BASE: GemLookBase;
2949
2978
  }
@@ -2979,6 +3008,15 @@ interface DeviceSettingsApi {
2979
3008
  declare class GemUnframedError extends Error {
2980
3009
  constructor();
2981
3010
  }
3011
+ interface AvatarRigNode {
3012
+ readonly node: string;
3013
+ readonly parent: string | null;
3014
+ }
3015
+ interface AvatarRigs {
3016
+ readonly small_human: readonly AvatarRigNode[];
3017
+ readonly adult_human: readonly AvatarRigNode[];
3018
+ }
3019
+ declare const AVATAR_RIGS: AvatarRigs;
2982
3020
  declare const DEVICE_SETTINGS_MAX_BYTES = 16384;
2983
3021
  declare const ARCADE_EMBEDDERS: readonly string[];
2984
3022
  interface GemOptions {
@@ -3071,7 +3109,6 @@ interface GameMenuItem {
3071
3109
  readonly onSelect: () => void;
3072
3110
  }
3073
3111
  interface GameMenu {
3074
- readonly onSettings?: () => void;
3075
3112
  readonly items?: readonly GameMenuItem[];
3076
3113
  }
3077
3114
  interface GemTerminationNotice {
@@ -3102,6 +3139,7 @@ interface Gem {
3102
3139
  openAvatarPicker(options?: {
3103
3140
  readonly tab?: "2d" | "3d";
3104
3141
  }): boolean;
3142
+ readonly avatars3d: Avatars3dApi;
3105
3143
  readonly vibration: VibrationApi;
3106
3144
  readonly controls: ControlsApi;
3107
3145
  readonly analytics: AnalyticsApi;
@@ -3123,6 +3161,7 @@ interface Gem {
3123
3161
  cueReward(cue: RewardCue): boolean;
3124
3162
  setWalletVisible(visible: boolean, options?: WalletVisibleOptions): boolean;
3125
3163
  setMenu(menu: GameMenu): boolean;
3164
+ setGemCorner(corner: GemCorner): boolean;
3126
3165
  exit(reason?: string): Promise<void>;
3127
3166
  readonly boot: BootTimeline;
3128
3167
  readonly frame: GemFrame;
@@ -3148,4 +3187,4 @@ interface ExitAnalytics {
3148
3187
  }
3149
3188
  declare function leaveAndExit(rooms: ExitRooms, bridge: ExitBridge | null, reason?: string, analytics?: ExitAnalytics): Promise<void>;
3150
3189
  declare function createGem(options?: GemOptions): Gem;
3151
- 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, type ControlsApi, DEVICE_SETTINGS_MAX_BYTES, DedicatedServerError, type DedicatedServerFailure, type DedicatedServerSession, type DevToolsOpener, type DeviceSettings, type DeviceSettingsApi, type DeviceSettingsPutOutcome, type DirectPurchaseRequest, type DirectPurchaseResult, type EarnAllowance, type EarnAllowanceEvent, type EarnAllowancePeriod, type EarnAllowanceReadOptions, type EntityLeaderboard, type EntityLeaderboardEntry, type EntityLeaderboardOptions, type EntityType, type ExitAnalytics, type ExitBridge, type ExitRooms, type FrameState, type Friend, type FriendChallenge, FriendChallengeError, type FriendChallengeErrorCode, type FriendChallengeOutcome, type FriendChallengeOutcomeKind, type FriendChallengeRequest, type FriendChallengesPage, FriendsApi, type FriendsPage, type FunctionFailure, type FunctionInvokeOptions, type FunctionResult, FunctionsApi, type GameConfig, type GameMenu, type GameMenuItem, type GameServerLink, type Gem, GemApiError, GemClient, type GemCohort, type GemCohorts, GemConfigError, type GemControlChoice, type GemControlsDeclaration, type GemDevTools, GemFrame, GemFunctionError, type GemGraphicsQuality, type GemIdentity, type GemInsets, type GemLook, type GemLookBase, type GemLookDelta, type GemLookOptions, type GemLookSpeed, type GemMatchApi, type GemMatchServerModule, type GemOptions, type GemPlayer, type GemPrefs, type GemRecommendedSettings, type GemReservedArea, GemSaveError, type GemServerBundle, type GemServerFactory, type GemServerHost, type GemServerHostProfile, type GemServerLifecycle, type GemTerminationNotice, GemUnframedError, type GemViewport, type GetLeaderboardOptions, type JoinWelcome, type Leaderboard, type LeaderboardEntry, type LeaderboardPeriod, LeaderboardsApi, type ListChallengesOptions, type ListFriendChallengesOptions, type ListFriendsOptions, MAX_PERIODS_BACK, type MatchConnectOptions, type MatchConnection, type MatchHosting, type MatchHostingMode, type MatchServeOptions, type MatchTransport, type MessageMeta, type MultiTransportSession, PLATFORM_EVENTS, type PeriodOptions, PlatformApi, PlatformCurrenciesApi, type PlatformCurrency, type PlatformCurrencyAccess, type PlatformCurrencyPurchasePayment, type PlatformCurrencyPurchaseRequest, type PlatformCurrencyPurchaseResult, type PlatformCurrencyReadOptions, PlatformEarnAllowanceApi, type PlatformEventName, type PlayerBadge, type PlayerBoost, type PlayerBoostMultiplier, type PlayerIdentity, type PlayerProfile, PlayerText, type ProfileCallOptions, type ProfileShowcaseEntry, ProfilesApi, type PurchaseApi, type PurchaseOptions, type PurchaseOutcome, PurchaseRefusal, type PurchaseRefusalCode, type PurchaseRequest, type PutBytesOptions, type PutSaveOptions, type RankedRow, type RecipeAvailability, type RecipeLock, type RewardCue, type RewardedStatus, type SavePage, type SaveRecord, type SendOptions$1 as SendOptions, type ServerTokenGrant, type SessionEndReason, type ShareApi, type ShareRequest, ShowcaseApi, type ShowcaseCallOptions, type ShowcaseFriendEntry, type ShowcaseFriends, type ShowcaseValue, type SignInOutcome, type SignInOutcomeKind, type SnapshotCurrency, type SnapshotItem, type TransportAdvert, type TransportKind, TransportRefusal, UNRELIABLE_CHANNEL_LABEL, type VibrationApi, type WalletVisibleOptions, asPlayerText, createBootTimeline, createGem, leaveAndExit, mapIdentity, markOnResolve, platformIconUrl, presentJoinCredential, readTemplateTransports, readTransportAdvert, reportOnResolve, text, webTransportAvailable };
3190
+ export { ARCADE_EMBEDDERS, AVATAR_RIGS, type AccountApi, type AdFormat, type AdOutcome, type AdOutcomeKind, type AdRequest, type AdsApi, AnalyticsApi, type AnalyticsFlushOptions, type AnalyticsFlushResult, type AnalyticsOptions, type AnalyticsRejection, type AnalyticsValue, AuthError, type AuthFailure, type AuthState, type Avatar3dFamily, type Avatar3dOffer, type Avatar3dPrice, type Avatar3dPurchaseRequest, type AvatarRigNode, type AvatarRigs, type Avatars3dApi, type BootMark, type BootTimeline, type Challenge, type ChallengeWindow, ChallengesApi, type ConfiguredPurchasePayment, type ConfiguredPurchaseRequest, type ConfiguredPurchaseResult, type ControlsApi, DEVICE_SETTINGS_MAX_BYTES, DedicatedServerError, type DedicatedServerFailure, type DedicatedServerSession, type DevToolsOpener, type DeviceSettings, type DeviceSettingsApi, type DeviceSettingsPutOutcome, type DirectPurchaseRequest, type DirectPurchaseResult, type EarnAllowance, type EarnAllowanceEvent, type EarnAllowancePeriod, type EarnAllowanceReadOptions, type EntityLeaderboard, type EntityLeaderboardEntry, type EntityLeaderboardOptions, type EntityType, type ExitAnalytics, type ExitBridge, type ExitRooms, type FrameState, type Friend, type FriendChallenge, FriendChallengeError, type FriendChallengeErrorCode, type FriendChallengeOutcome, type FriendChallengeOutcomeKind, type FriendChallengeRequest, type FriendChallengesPage, FriendsApi, type FriendsPage, type FunctionFailure, type FunctionInvokeOptions, type FunctionResult, FunctionsApi, type GameConfig, type GameMenu, type GameMenuItem, type GameServerLink, type Gem, GemApiError, GemClient, type GemCohort, type GemCohorts, GemConfigError, type GemCorner, type GemDevTools, GemFrame, GemFunctionError, type GemGraphicsQuality, type GemIdentity, type GemInsets, type GemLook, type GemLookBase, type GemLookDelta, type GemLookOptions, type GemLookSpeed, type GemMatchApi, type GemMatchServerModule, type GemOptions, type GemPlayer, type GemPrefs, type GemRecommendedSettings, type GemReservedArea, GemSaveError, type GemServerBundle, type GemServerFactory, type GemServerHost, type GemServerHostProfile, type GemServerLifecycle, type GemTerminationNotice, GemUnframedError, type GemViewport, type GetLeaderboardOptions, type JoinWelcome, type Leaderboard, type LeaderboardEntry, type LeaderboardPeriod, LeaderboardsApi, type ListChallengesOptions, type ListFriendChallengesOptions, type ListFriendsOptions, MAX_PERIODS_BACK, type MatchConnectOptions, type MatchConnection, type MatchHosting, type MatchHostingMode, type MatchServeOptions, type MatchTransport, type MessageMeta, type MultiTransportSession, PLATFORM_EVENTS, type PeriodOptions, PlatformApi, PlatformCurrenciesApi, type PlatformCurrency, type PlatformCurrencyAccess, type PlatformCurrencyPurchasePayment, type PlatformCurrencyPurchaseRequest, type PlatformCurrencyPurchaseResult, type PlatformCurrencyReadOptions, PlatformEarnAllowanceApi, type PlatformEventName, type PlayerBadge, type PlayerBoost, type PlayerBoostMultiplier, type PlayerIdentity, type PlayerProfile, PlayerText, type ProfileCallOptions, type ProfileShowcaseEntry, ProfilesApi, type PurchaseApi, type PurchaseOptions, type PurchaseOutcome, PurchaseRefusal, type PurchaseRefusalCode, type PurchaseRequest, type PutBytesOptions, type PutSaveOptions, type RankedRow, type RecipeAvailability, type RecipeLock, type RewardCue, type RewardedStatus, type SavePage, type SaveRecord, type SendOptions$1 as SendOptions, type ServerTokenGrant, type SessionEndReason, type ShareApi, type ShareRequest, ShowcaseApi, type ShowcaseCallOptions, type ShowcaseFriendEntry, type ShowcaseFriends, type ShowcaseValue, type SignInOutcome, type SignInOutcomeKind, type SnapshotCurrency, type SnapshotItem, type TransportAdvert, type TransportKind, TransportRefusal, UNRELIABLE_CHANNEL_LABEL, type VibrationApi, type WalletVisibleOptions, type WornAvatar3d, asPlayerText, createBootTimeline, createGem, leaveAndExit, mapIdentity, markOnResolve, platformIconUrl, presentJoinCredential, readTemplateTransports, readTransportAdvert, reportOnResolve, text, webTransportAvailable };
@@ -1 +1 @@
1
- var GemWebSdkBridgeBundle=(function(){'use strict';var G="GemWebSdkHandshake";function Q(){return typeof document>"u"?void 0:document.readyState}var I=()=>Date.now();function q(n={}){let e=n.win??window,t=e,r=t[G];if(r!==void 0)return r;let a=n.readyState??Q,i=n.now??I,d=[],s=[],m=g=>{let c=g.data;!c||c.type!=="gem.handshake"||(d.length>=4&&(d.shift(),s.shift(),u.dropped+=1),d.push(g),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[G]=u,u}function L(n,e,t={}){let r=n[G];if(r===void 0)return null;let a=t.ttlMs??9500,i=t.now??I,d=r.events.splice(0),s=r.times?.splice(0),m=0,u=0,g=false,c=i()-a;for(let p=d.length-1;p>=0;p--){let f=s?.[p];if(f!==void 0&&f<c){u+=1;continue}if(m+=1,e(d[p])===true){g=true;break}}return r.uninstall(),{capture:r,delivered:m,stale:u,accepted:g}}var l="gem-web-bridge",k={min:1,max:1},h=65536,A=8,b=5e3,_=1024;function M(n){return Object.freeze(Object.assign(Object.create(null),n))}var D=M({"gem.handshake":30,"gem.handshake.accept":5,"gem.token":30,"gem.token.denied":30,"gem.player":12,"gem.pause":120,"gem.prefs":60,"gem.cohorts":12,"gem.earnAllowanceChanged":30,"gem.viewport":60,"gem.deviceSettings":12,"gem.willTerminate":10,"gem.roomEvent":120,"gem.socketState":12,"gem.seatedEvent":60,"gem.autoStartFailedEvent":30,"gem.ticketEvent":60,"gem.signalEvent":1800,"gem.dedicatedEvent":120,"gem.partyResult":30,"gem.clusterTarget":12,"gem.devtools":30,"gem.screenshot":6,"gem.screenshot.denied":12,"gem.requestContext":12,"gem.gameContext":12,"gem.signal":1200,"gem.dedicatedOffer":60,"gem.partyRequest":12,"gem.ready":5,"gem.engaged":5,"gem.progress":600,"gem.requestToken":12,"gem.requestLocalServer":6,"gem.localServer":30,"gem.localServer.denied":30,"gem.exit":5,"gem.openExternal":6,"gem.requestFullscreen":30,"gem.audioState":120,"gem.rewardCue":60,"gem.walletDisplay":60,"gem.controlsDeclare":60,"gem.menu":60,"gem.menuSelect":60,"gem.requestShare":6,"gem.requestAvatarPicker":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}),w="__malformed";var X=M({"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.ticketEvent":"ticketEvents","gem.seatedEvent":"partySeating","gem.socketState":"socketState","gem.audioState":"audioState","gem.rewardCue":"rewardCue","gem.frameStats":"frameStats","gem.portraitBorders":"portraitBorders","gem.engaged":"engagement","gem.viewport":"viewport","gem.walletDisplay":"walletDisplay","gem.requestLocalServer":"localHost","gem.localServer":"localHost","gem.localServer.denied":"localHost","gem.cohorts":"cohorts","gem.earnAllowanceChanged":"earnAllowance","gem.deviceSettings":"deviceSettings","gem.deviceSettings.put":"deviceSettings","gem.deviceSettings.result":"deviceSettings","gem.requestShare":"share","gem.requestAvatarPicker":"avatarPicker","gem.vibrate":"vibration","gem.menu":"gameMenu","gem.menuSelect":"gameMenu","gem.controlsDeclare":"controls"}),Z=Object.freeze([["gem.asyncOpponents.","asyncOpponents"],["gem.vibration.","vibration"],["gem.viewport.","reservedAreas"]]);function j(n){let e=X[n];if(e!==void 0)return e;for(let[t,r]of Z)if(n.startsWith(t))return r}function ee(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 te(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 ne(n){return /^[a-z]{2,8}(-[a-z0-9]{1,8})*$/i.test(n)}function re(n){return /^[a-z_]+$/.test(n)}function O(n,e,t){if(e>A)return `nesting deeper than ${A}`;if(++t.nodes>b)return `more than ${b} values`;if(t.bytes>h)return `over the ${h} byte limit`;if(n==null)return t.bytes+=4,null;let r=typeof n;if(r==="boolean")return t.bytes+=5,null;if(r==="number")return t.bytes+=8,null;if(r==="string")return t.bytes+=n.length*3+2,null;if(r!=="object")return `${r} is not plain data`;let 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>_)return `an array of ${n.length} entries, over the ${_} limit`;t.bytes+=2;for(let s of n){let m=O(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>b)return `more than ${b} values`;if(t.bytes+=s.length*3+4,t.bytes>h)return `over the ${h} byte limit`;let m=O(d[s],e+1,t);if(m)return m}return null}function oe(n){let e={nodes:0,bytes:0,seen:new Set},t=O(n,0,e);return t?`message contains ${t}`:e.bytes>h?`message is over the ${h} byte limit`:null}var ae={origin:[ee,"not a well-formed origin"],url:[te,"not a safe absolute http(s) URL"],bcp47:[ne,"not a well-formed BCP 47 tag"],code:[re,"not a code of lower-case letters and underscores"]};function F(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=$(i,r,a);if(d)return d}return null}function $(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]=ae[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`:F(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=$(i,r,a);if(d)return d}return null}default:{let r=e.k;return `${t}: unknown kind ${String(r)}`}}}var U=Object.create(null);function o(n,e){return U[n]=t=>{let r=oe(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}`:F(a,e,"")}}o("gem.handshake",[{n:"versions",k:"o",fs:[{n:"min",k:"i",lo:1,hi:1e3},{n:"max",k:"i",lo:1,hi:1e3}]},{n:"capabilities",k:"a",o:1,max:64,it:{n:"",k:"s",max:64}},{n:"embedder",k:"s",max:2048,f:"origin"},{n:"unbidden",k:"b",o:1}]);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}}]);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}]);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}]);o("gem.player",[{n:"untrusted",k:"o",fs:[{n:"displayName",k:"s",max:64},{n:"displayTag",k:"s",o:1,max:80},{n:"displayHandle",k:"s",max:80}]},{n:"playerId",k:"s",o:1,max:64},{n:"discriminator",k:"s",o:1,max:8},{n:"avatarIconUrl",k:"s",o:1,max:2048,f:"url"},{n:"avatarIconId",k:"s",o:1,max:64},{n:"avatar3dId",k:"s",o:1,max:64},{n:"avatar3dModelUrl",k:"s",o:1,max:2048,f:"url"},{n:"avatar3dIconUrl",k:"s",o:1,max:2048,f:"url"},{n:"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}]}]);o("gem.pause",[{n:"paused",k:"b"}]);o("gem.prefs",[{n:"reducedMotion",k:"b"},{n:"muted",k:"b"},{n:"showFrameStats",k:"b",o:1},{n:"locale",k:"s",max:35,f:"bcp47"},{n:"recommended",k:"o",o:1,fs:[{n:"volume",k:"i",lo:0,hi:100},{n:"batterySaver",k:"b"},{n:"keyboardLayout",k:"e",v:["wasd","arrows"]},{n:"gamepadConfirm",k:"e",v:["south","east"]},{n:"vibration",k:"b"},{n:"lookSensitivity",k:"i",o:1,lo:20,hi:400},{n:"gamepadLookSensitivity",k:"i",o:1,lo:20,hi:400},{n:"invertLookY",k:"b",o:1},{n:"touchMovement",k:"s",o:1,max:16,f:"code"},{n:"graphicsQuality",k:"s",o:1,max:16,f:"code"},{n:"graphicsQualityAuto",k:"b",o:1}]}]);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}]}}]);o("gem.earnAllowanceChanged",[]);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}]}}]);o("gem.deviceSettings",[{n:"settings",k:"j",o:1}]);o("gem.willTerminate",[{n:"reason",k:"e",v:["grant_expiring","session_ended","navigating","kill_switch"]},{n:"graceMs",k:"i",lo:0,hi:6e4}]);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"]}]);o("gem.socketState",[{n:"connected",k:"b"},{n:"reason",k:"e",o:1,v:["connecting","dropped","watchdog","terminal"]}]);o("gem.seatedEvent",[{n:"roomId",k:"s",max:64}]);o("gem.autoStartFailedEvent",[{n:"roomId",k:"s",max:64},{n:"code",k:"s",max:64}]);o("gem.ticketEvent",[{n:"event",k:"e",v:["queued","matched","expired","cancelled","failed"]},{n:"ticketId",k:"s",max:64},{n:"partySize",k:"i",o:1,lo:1,hi:64},{n:"queuedAt",k:"i",o:1,lo:0,hi:4102444800},{n:"expiresAt",k:"i",o:1,lo:0,hi:4102444800},{n:"reason",k:"s",o:1,max:64},{n:"roomId",k:"s",o:1,max:64}]);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"}]);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}]);o("gem.partyResult",[{n:"requestId",k:"s",max:64},{n:"partyId",k:"s",o:1,max:64}]);o("gem.clusterTarget",[{n:"clusterTargetId",k:"s",max:64},{n:"clusterTargetIds",k:"a",o:1,max:3,it:{n:"",k:"s",max:64}}]);o("gem.devtools",[{n:"action",k:"e",v:["open","close","toggle"]}]);o("gem.screenshot",[{n:"maxWidth",k:"i",lo:1,hi:7680},{n:"maxHeight",k:"i",lo:1,hi:4320}]);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"}]);o("gem.requestContext",[]);o("gem.gameContext",[{n:"context",k:"j"}]);o("gem.signal",[{n:"signal",k:"e",v:["join","offer","answer","ice","migrationAck","hostUnreachable"]},{n:"matchId",k:"s",max:64},{n:"data",k:"j"}]);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"]}]);o("gem.partyRequest",[{n:"requestId",k:"s",max:64}]);o("gem.ready",[]);o("gem.engaged",[]);o("gem.progress",[{n:"loaded",k:"i",lo:0,hi:1099511627776},{n:"total",k:"i",lo:0,hi:1099511627776}]);o("gem.requestToken",[{n:"requestId",k:"s",max:64},{n:"reason",k:"e",v:["initial","expiring","rejected"]}]);o("gem.requestLocalServer",[{n:"requestId",k:"s",max:64},{n:"gameRoomId",k:"s",max:64}]);o("gem.localServer",[{n:"requestId",k:"s",max:64},{n:"serverId",k:"s",o:1,max:128}]);o("gem.localServer.denied",[{n:"requestId",k:"s",max:64},{n:"retryable",k:"b"},{n:"reason",k:"e",v:["refused","unavailable"]}]);o("gem.exit",[{n:"reason",k:"s",o:1,max:64}]);o("gem.openExternal",[{n:"url",k:"s",max:2048,f:"url"}]);o("gem.requestFullscreen",[{n:"enabled",k:"b"}]);o("gem.audioState",[{n:"muted",k:"b"}]);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}]}]);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}]);o("gem.controlsDeclare",[{n:"uses",k:"o",fs:[{n:"lookSensitivity",k:"s",o:1,max:16,f:"code"},{n:"gamepadLookSensitivity",k:"s",o:1,max:16,f:"code"},{n:"invertLookY",k:"s",o:1,max:16,f:"code"},{n:"touchMovement",k:"s",o:1,max:16,f:"code"}]}]);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}]}}]);o("gem.menuSelect",[{n:"entry",k:"e",v:["settings","item"]},{n:"id",k:"s",o:1,max:32}]);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}]}}]);o("gem.requestAvatarPicker",[{n:"tab",k:"e",o:1,v:["2d","3d"]}]);o("gem.vibrate",[{n:"pattern",k:"a",max:99,it:{n:"",k:"i",lo:0,hi:1e4}}]);o("gem.frameStats",[{n:"fps",k:"i",lo:0,hi:1e3},{n:"frameTimeP95Ms",k:"i",lo:0,hi:1e5}]);o("gem.portraitBorders",[{n:"name",k:"s",o:1,max:40}]);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}]);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}]);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}]);o("gem.deviceSettings.put",[{n:"requestId",k:"s",max:64},{n:"settings",k:"j"}]);o("gem.deviceSettings.result",[{n:"requestId",k:"s",max:64},{n:"outcome",k:"e",v:["stored","too_large","unavailable"]}]);o("gem.requestAd",[{n:"requestId",k:"s",max:64},{n:"placement",k:"s",max:32},{n:"format",k:"e",v:["interstitial","rewarded"]}]);o("gem.adResult",[{n:"requestId",k:"s",max:64},{n:"outcome",k:"e",v:["shown","no_ad","unavailable"]}]);o("gem.requestSignIn",[{n:"requestId",k:"s",max:64}]);o("gem.signInResult",[{n:"requestId",k:"s",max:64},{n:"outcome",k:"e",v:["signed_in","declined","unavailable"]}]);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}]);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}]);var S=Object.freeze(U);var se=["lookSensitivity","gamepadLookSensitivity","invertLookY","touchMovement"];function H(n){let e={};if(typeof n=="object"&&n!==null)for(let t of se){let r=n[t];(r==="player"||r==="game")&&(e[t]=r);}return e}var ie=/^[a-z0-9][a-z0-9_-]{0,39}$/;function le(n){return typeof n=="string"&&ie.test(n)}function B(n){if(n===null||le(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 C=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 P(n){return new C(n)}var T={now:()=>Date.now(),setTimeout:(n,e)=>setTimeout(n,e),clearTimeout:n=>clearTimeout(n)},v=class{constructor(e=T){this.clock=e;}clock;tokens=new Map;lastRefill=new Map;allow(e){let t=D[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 E(n,e){return n.toLowerCase()===e.toLowerCase()}function W(n){let e=n.toLowerCase();return e==="localhost"||e.endsWith(".localhost")||e==="[::1]"||e==="::1"?true:/^127(\.\d{1,3}){3}$/.test(e)}function N(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:W(t.hostname)&&W(r.hostname)}function V(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 z(n){return Math.min(16384,Math.max(0,Math.round(Number.isFinite(n)?n:0)))}function de(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 me(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 Y(n,e){return Math.min(e,Math.max(0,Math.round(Number.isFinite(n)?n:0)))}function ce(n){let e=n.untrusted,t=P(e.displayName),r=e.displayTag||e.displayHandle,a=r?P(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=/^[\da-f]{8}(-[\da-f]{4}){3}-[\da-f]{12}$/i,u=n.avatarIconId,g=n.avatar3dId,c={displayName:t,displayHandle:a??t,badges:(n.badges??[]).map(y=>({itemId:y.itemId,iconUrl:y.iconUrl}))};n.playerId&&(c.playerId=n.playerId),d&&(c.discriminator=d),a&&(c.displayTag=a),s&&(c.avatarIconUrl=c.avatarUrl=s),u&&m.test(u)&&(c.avatarIconId=u),g&&m.test(g)&&(c.avatar3dId=g),n.avatar3dModelUrl&&(c.avatar3dModelUrl=n.avatar3dModelUrl),n.avatar3dIconUrl&&(c.avatar3dIconUrl=n.avatar3dIconUrl);let p=n.boost,f=(p?.multipliers??[]).map(y=>({currencyId:y.currencyId,currencySlug:y.currencySlug,multiplier:y.multiplierBp/1e4})),R=f.some(y=>y.multiplier>1);return c.boost=R&&p?.expiresInDays?{active:R,multipliers:f,expiresInDays:p.expiresInDays}:{active:R,multipliers:f},c}var ue=1e4,x=class{constructor(e){this.options=e;if(e.expectedSource===void 0||e.expectedSource===null)throw new Error("GemFrame: expectedSource is required and must not be null \u2014 pass window.parent. The handshake transfers the MessagePort, and origin alone does not say WHICH document on that origin sent it.");this.expectedSource=e.expectedSource,this.clock=e.clock??T,this.inbound=new v(this.clock),this.outbound=new v(this.clock);}options;state="waiting";port=null;version=null;peerCapabilities=[];unbidden=false;engagedSent=false;readyPending=false;readySent=false;settleWaiters=[];clock;inbound;outbound;expectedSource;get currentState(){return this.state}get parentCapabilities(){return this.peerCapabilities}parentSupports(e){return this.peerCapabilities.includes(e)}get protocolVersion(){return this.version}get unbiddenLaunch(){return this.unbidden}handleWindowMessage(e){if(e.source!==this.expectedSource)return this.refuse(e,"handshake did not come from the expected embedder window"),false;if(!(this.options.allowedEmbedders.some(s=>E(s,e.origin))||N(e.origin,this.options.selfOrigin)))return this.refuse(e,`embedder '${e.origin}' is not in allowedEmbedders`),this.state==="waiting"&&this.transition("refused"),false;if(this.state==="connected")return this.fail("handshake_duplicate","this document already has a port"),false;if(this.state!=="waiting")return false;let r=S["gem.handshake"]?.(e.data);if(r)return this.refuse(e,`malformed handshake: ${r}`),false;let a=e.data;if(!E(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=V(k,a.versions);return d===null?(i.onmessage=null,i.postMessage({gem:l,type:"gem.error",code:"version_mismatch",message:`frame supports v${k.min}..v${k.max}`}),i.close(),this.transition("refused"),this.options.onError?.("version_mismatch"),false):(this.port=i,this.version=d,i.onmessage=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=ue){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:z(e.origin.x),y:z(e.origin.y)}),this.send(t),true}showPortraitBorders(e){let t=B(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",...de(e,t?.only)})}declareControls(e){return this.state!=="connected"||!this.parentSupports("controls")?false:this.send({gem:l,type:"gem.controlsDeclare",uses:H(e)})}setMenu(e,t){return this.state!=="connected"||!this.parentSupports("gameMenu")?false:this.send({gem:l,type:"gem.menu",...me(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}))})}requestAvatarPicker(e){return this.state!=="connected"||!this.parentSupports("avatarPicker")?false:this.send({gem:l,type:"gem.requestAvatarPicker",...e==="2d"||e==="3d"?{tab:e}:{}})}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:Y(e.fps,1e3),frameTimeP95Ms:Y(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(w)){this.options.onDropped?.(e,t);return}this.fail(e,t);}dropUnknownType(e){this.inbound.allow(w)&&this.options.onDropped?.("unsupported",`ignored unknown message type '${e}'`);}refuse(e,t){e.ports?.[0]?.close?.(),this.inbound.allow(w)&&this.options.onRefused?.(t);}fail(e,t){this.options.onError?.(e,t),this.state==="connected"&&this.port&&this.send({gem:l,type:"gem.error",code:e,...t===void 0?{}:{message:t}});}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=S[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||K(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=S[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 u={maxWidth:s.maxWidth,maxHeight:s.maxHeight};if(!this.options.onScreenshot){m.close(),this.screenshotDenied("not_wired",false);break}return K(t.slice(1)),this.options.onScreenshot(u,m,(g,c)=>this.screenshotDenied(g,c)),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?.(ce(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.ticketEvent":this.options.onTicketEvent?.(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 K(n){for(let e of n)try{e?.close?.();}catch{}}q();function ge(n){if((n.expectedSource??window.parent)===window)throw new Error("GemWebSdkBridge.connect: this document is not framed (window.parent === window), so there is no embedder to hand it a port. A game runs inside the Gem Arcade iframe; opening it directly will never complete a handshake.");let e=new x({...n,expectedSource:n.expectedSource??window.parent}),t=r=>{let 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),L(window,t),e}var J={connect:ge,GemFrame:x,PROTOCOL:l,SUPPORTED_VERSIONS:k};window.GemWebSdkBridge=J;var Dt=J;return Dt;})();
1
+ var GemWebSdkBridgeBundle=(function(){'use strict';var P="GemWebSdkHandshake";function Z(){return typeof document>"u"?void 0:document.readyState}var L=()=>Date.now();function _(n={}){let e=n.win??window,t=e,r=t[P];if(r!==void 0)return r;let s=n.readyState??Z,i=n.now??L,d=[],o=[],m=p=>{let c=p.data;!c||c.type!=="gem.handshake"||(d.length>=4&&(d.shift(),o.shift(),g.dropped+=1),d.push(p),o.push(i()));};e.addEventListener("message",m);let g={events:d,times:o,dropped:0,late:s()==="complete",uninstall(){e.removeEventListener("message",m);}};return t[P]=g,g}function M(n,e,t={}){let r=n[P];if(r===void 0)return null;let s=t.ttlMs??9500,i=t.now??L,d=r.events.splice(0),o=r.times?.splice(0),m=0,g=0,p=false,c=i()-s;for(let y=d.length-1;y>=0;y--){let f=o?.[y];if(f!==void 0&&f<c){g+=1;continue}if(m+=1,e(d[y])===true){p=true;break}}return r.uninstall(),{capture:r,delivered:m,stale:g,accepted:p}}var l="gem-web-bridge",k={min:1,max:1},h=65536,j=8,b=5e3,D=1024;function F(n){return Object.freeze(Object.assign(Object.create(null),n))}var $=F({"gem.handshake":30,"gem.handshake.accept":5,"gem.token":30,"gem.token.denied":30,"gem.player":12,"gem.pause":120,"gem.prefs":60,"gem.cohorts":12,"gem.earnAllowanceChanged":30,"gem.viewport":60,"gem.deviceSettings":12,"gem.willTerminate":10,"gem.roomEvent":120,"gem.socketState":12,"gem.seatedEvent":60,"gem.autoStartFailedEvent":30,"gem.ticketEvent":60,"gem.signalEvent":1800,"gem.dedicatedEvent":120,"gem.partyResult":30,"gem.clusterTarget":12,"gem.devtools":30,"gem.screenshot":6,"gem.screenshot.denied":12,"gem.requestContext":12,"gem.gameContext":12,"gem.signal":1200,"gem.dedicatedOffer":60,"gem.partyRequest":12,"gem.ready":5,"gem.engaged":5,"gem.progress":600,"gem.requestToken":12,"gem.requestLocalServer":6,"gem.localServer":30,"gem.localServer.denied":30,"gem.exit":5,"gem.openExternal":6,"gem.requestFullscreen":30,"gem.audioState":120,"gem.rewardCue":60,"gem.walletDisplay":60,"gem.controlsDeclare":60,"gem.menu":60,"gem.menuSelect":60,"gem.gemCorner":12,"gem.requestShare":6,"gem.requestAvatarPicker":6,"gem.vibrate":600,"gem.frameStats":120,"gem.portraitBorders":60,"gem.error":60,"gem.requestPurchase":12,"gem.requestAvatar3dPurchase":12,"gem.purchaseResult":30,"gem.deviceSettings.put":30,"gem.deviceSettings.result":30,"gem.requestAd":6,"gem.adResult":12,"gem.requestSignIn":6,"gem.signInResult":12,"gem.requestFriendChallenge":12,"gem.friendChallengeResult":30,__malformed:60}),w="__malformed";var ee=F({"gem.requestAd":"ads","gem.adResult":"ads","gem.requestSignIn":"signIn","gem.signInResult":"signIn","gem.requestPurchase":"purchases","gem.purchaseResult":"purchases","gem.requestAvatar3dPurchase":"avatar3dPurchases","gem.requestFriendChallenge":"friendChallenges","gem.friendChallengeResult":"friendChallenges","gem.devtools":"devtools","gem.screenshot":"screenshot","gem.screenshot.denied":"screenshot","gem.requestContext":"feedbackContext","gem.gameContext":"feedbackContext","gem.roomEvent":"rooms","gem.signal":"p2p","gem.signalEvent":"p2p","gem.dedicatedOffer":"dedicated","gem.dedicatedEvent":"dedicated","gem.clusterTarget":"clusterTarget","gem.partyRequest":"parties","gem.partyResult":"parties","gem.autoStartFailedEvent":"autoStartFailure","gem.ticketEvent":"ticketEvents","gem.seatedEvent":"partySeating","gem.socketState":"socketState","gem.audioState":"audioState","gem.rewardCue":"rewardCue","gem.frameStats":"frameStats","gem.portraitBorders":"portraitBorders","gem.engaged":"engagement","gem.viewport":"viewport","gem.walletDisplay":"walletDisplay","gem.requestLocalServer":"localHost","gem.localServer":"localHost","gem.localServer.denied":"localHost","gem.cohorts":"cohorts","gem.earnAllowanceChanged":"earnAllowance","gem.deviceSettings":"deviceSettings","gem.deviceSettings.put":"deviceSettings","gem.deviceSettings.result":"deviceSettings","gem.requestShare":"share","gem.requestAvatarPicker":"avatarPicker","gem.vibrate":"vibration","gem.menu":"gameMenu","gem.menuSelect":"gameMenu","gem.controlsDeclare":"controls","gem.gemCorner":"gemCorner"}),te=Object.freeze([["gem.asyncOpponents.","asyncOpponents"],["gem.vibration.","vibration"],["gem.viewport.","reservedAreas"]]);function U(n){let e=ee[n];if(e!==void 0)return e;for(let[t,r]of te)if(n.startsWith(t))return r}function ne(n){let e=/^([a-z][a-z0-9+.-]*):\/\/([a-z0-9.-]+|\[[0-9a-f:.]+\])(:([0-9]{1,5}))?$/i.exec(n);return e===null?false:e[4]===void 0||Number(e[4])<=65535}function re(n){let e;try{e=new URL(n);}catch{return false}return e.username!==""||e.password!==""?false:e.protocol==="https:"?true:e.protocol==="http:"&&(e.hostname==="localhost"||e.hostname==="127.0.0.1")}function ae(n){return /^[a-z]{2,8}(-[a-z0-9]{1,8})*$/i.test(n)}function oe(n){return /^[a-z_]+$/.test(n)}function T(n,e,t){if(e>j)return `nesting deeper than ${j}`;if(++t.nodes>b)return `more than ${b} values`;if(t.bytes>h)return `over the ${h} byte limit`;if(n==null)return t.bytes+=4,null;let r=typeof n;if(r==="boolean")return t.bytes+=5,null;if(r==="number")return t.bytes+=8,null;if(r==="string")return t.bytes+=n.length*3+2,null;if(r!=="object")return `${r} is not plain data`;let s=n;if(t.seen.has(s))return "a repeated or cyclic object reference";if(t.seen.add(s),Array.isArray(n)){if(n.length>D)return `an array of ${n.length} entries, over the ${D} limit`;t.bytes+=2;for(let o of n){let m=T(o,e+1,t);if(m)return m}return null}let i=Object.getPrototypeOf(n);if(i!==Object.prototype&&i!==null)return "a value that is not a plain object";t.bytes+=2;let d=n;for(let o in d){if(!Object.prototype.hasOwnProperty.call(d,o))continue;if(++t.nodes>b)return `more than ${b} values`;if(t.bytes+=o.length*3+4,t.bytes>h)return `over the ${h} byte limit`;let m=T(d[o],e+1,t);if(m)return m}return null}function se(n){let e={nodes:0,bytes:0,seen:new Set},t=T(n,0,e);return t?`message contains ${t}`:e.bytes>h?`message is over the ${h} byte limit`:null}var ie={origin:[ne,"not a well-formed origin"],url:[re,"not a safe absolute http(s) URL"],bcp47:[ae,"not a well-formed BCP 47 tag"],code:[oe,"not a code of lower-case letters and underscores"]};function H(n,e,t){for(let r of e){let s=t===""?r.n:`${t}.${r.n}`,i=n[r.n];if(i==null){if(r.o)continue;return `${s}: required`}let d=B(i,r,s);if(d)return d}return null}function B(n,e,t){switch(e.k){case "s":{if(typeof n!="string")return `${t}: expected string`;if(n.length>e.max)return `${t}: exceeds ${e.max} characters`;if(e.f){let[r,s]=ie[e.f];if(!r(n))return `${t}: ${s}`}return null}case "i":return typeof n!="number"||!Number.isInteger(n)?`${t}: expected integer`:n<e.lo||n>e.hi?`${t}: out of range ${e.lo}..${e.hi}`:null;case "b":return typeof n=="boolean"?null:`${t}: expected boolean`;case "e":{let r=e.v;return r.includes(n)?null:`${t}: not one of ${r.join("|")}`}case "o":return typeof n!="object"||n===null||Array.isArray(n)?`${t}: expected object`:H(n,e.fs,t);case "j":return typeof n!="object"||n===null||Array.isArray(n)?`${t}: expected a plain object`:null;case "a":{if(!Array.isArray(n))return `${t}: expected array`;if(n.length>e.max)return `${t}: exceeds ${e.max} items`;let r=e.it,s=`${t}[]`;for(let i of n){if(i==null){if(r.o)continue;return `${s}: required`}let d=B(i,r,s);if(d)return d}return null}default:{let r=e.k;return `${t}: unknown kind ${String(r)}`}}}var W=Object.create(null);function a(n,e){return W[n]=t=>{let r=se(t);if(r)return r;if(typeof t!="object"||t===null||Array.isArray(t))return "message: expected object";let s=t;return s.gem!==l?"gem: wrong protocol marker":s.type!==n?`type: expected ${n}`:H(s,e,"")}}a("gem.handshake",[{n:"versions",k:"o",fs:[{n:"min",k:"i",lo:1,hi:1e3},{n:"max",k:"i",lo:1,hi:1e3}]},{n:"capabilities",k:"a",o:1,max:64,it:{n:"",k:"s",max:64}},{n:"embedder",k:"s",max:2048,f:"origin"},{n:"unbidden",k:"b",o:1}]);a("gem.handshake.accept",[{n:"v",k:"i",lo:1,hi:1e3},{n:"capabilities",k:"a",o:1,max:64,it:{n:"",k:"s",max:64}}]);a("gem.token",[{n:"token",k:"s",max:4096},{n:"requestId",k:"s",o:1,max:64},{n:"generation",k:"i",lo:0,hi:2147483647},{n:"apiBaseUrl",k:"s",o:1,max:512,f:"url"},{n:"playerId",k:"s",max:64},{n:"gameId",k:"s",max:64},{n:"channel",k:"e",v:["dev","test","release"]},{n:"gameVersion",k:"s",o:1,max:64},{n:"expiresAt",k:"i",lo:0,hi:4102444800},{n:"chainEndsAt",k:"i",lo:0,hi:4102444800},{n:"allowDevTools",k:"b",o:1}]);a("gem.token.denied",[{n:"requestId",k:"s",max:64},{n:"retryable",k:"b"},{n:"retryAfterMs",k:"i",o:1,lo:0,hi:36e5},{n:"reason",k:"e",v:["chain_exhausted","unavailable"]},{n:"correlationId",k:"s",max:64}]);a("gem.player",[{n:"untrusted",k:"o",fs:[{n:"displayName",k:"s",max:64},{n:"displayTag",k:"s",o:1,max:80},{n:"displayHandle",k:"s",max:80}]},{n:"playerId",k:"s",o:1,max:64},{n:"discriminator",k:"s",o:1,max:8},{n:"avatarIconUrl",k:"s",o:1,max:2048,f:"url"},{n:"avatarIconId",k:"s",o:1,max:64},{n:"avatar3dId",k:"s",o:1,max:64},{n:"avatar3dModelUrl",k:"s",o:1,max:2048,f:"url"},{n:"avatar3dIconUrl",k:"s",o:1,max:2048,f:"url"},{n:"avatars3d",k:"a",o:1,max:8,it:{n:"",k:"o",fs:[{n:"family",k:"s",max:32},{n:"id",k:"s",max:64},{n:"modelUrl",k:"s",max:256,f:"url"},{n:"iconUrl",k:"s",max:256,f:"url"}]}},{n:"badges",k:"a",o:1,max:2,it:{n:"",k:"o",fs:[{n:"itemId",k:"s",max:64},{n:"iconUrl",k:"s",max:2048,f:"url"}]}},{n:"displayTag",k:"s",max:8},{n:"avatarUrl",k:"s",o:1,max:2048,f:"url"},{n:"boost",k:"o",o:1,fs:[{n:"multipliers",k:"a",max:8,it:{n:"",k:"o",fs:[{n:"currencyId",k:"s",max:64},{n:"currencySlug",k:"s",max:32},{n:"multiplierBp",k:"i",lo:1e4,hi:1e6}]}},{n:"expiresInDays",k:"i",o:1,lo:1,hi:7}]}]);a("gem.pause",[{n:"paused",k:"b"}]);a("gem.prefs",[{n:"reducedMotion",k:"b"},{n:"muted",k:"b"},{n:"showFrameStats",k:"b",o:1},{n:"locale",k:"s",max:35,f:"bcp47"},{n:"recommended",k:"o",o:1,fs:[{n:"volume",k:"i",lo:0,hi:100},{n:"batterySaver",k:"b"},{n:"keyboardLayout",k:"e",v:["wasd","arrows"]},{n:"gamepadConfirm",k:"e",v:["south","east"]},{n:"vibration",k:"b"},{n:"lookSensitivity",k:"i",o:1,lo:20,hi:400},{n:"gamepadLookSensitivity",k:"i",o:1,lo:20,hi:400},{n:"invertLookY",k:"b",o:1},{n:"touchMovement",k:"s",o:1,max:16,f:"code"},{n:"graphicsQuality",k:"s",o:1,max:16,f:"code"},{n:"graphicsQualityAuto",k:"b",o:1}]}]);a("gem.cohorts",[{n:"cohorts",k:"a",max:8,it:{n:"",k:"o",fs:[{n:"experimentId",k:"s",max:36},{n:"variantKey",k:"s",max:32}]}}]);a("gem.earnAllowanceChanged",[]);a("gem.viewport",[{n:"insets",k:"o",fs:[{n:"top",k:"i",lo:0,hi:4096},{n:"right",k:"i",lo:0,hi:4096},{n:"bottom",k:"i",lo:0,hi:4096},{n:"left",k:"i",lo:0,hi:4096}]},{n:"reserved",k:"a",o:1,max:4,it:{n:"",k:"o",fs:[{n:"x",k:"i",lo:0,hi:16384},{n:"y",k:"i",lo:0,hi:16384},{n:"width",k:"i",lo:0,hi:16384},{n:"height",k:"i",lo:0,hi:16384}]}}]);a("gem.deviceSettings",[{n:"settings",k:"j",o:1}]);a("gem.willTerminate",[{n:"reason",k:"e",v:["grant_expiring","session_ended","navigating","kill_switch"]},{n:"graceMs",k:"i",lo:0,hi:6e4}]);a("gem.roomEvent",[{n:"event",k:"e",v:["updated","match_started","match_ready","match_failed","version_stale"]},{n:"roomId",k:"s",max:64},{n:"matchId",k:"s",o:1,max:64},{n:"version",k:"i",o:1,lo:0,hi:2147483647},{n:"reason",k:"s",o:1,max:64},{n:"platform",k:"e",o:1,v:["universal","mobile"]}]);a("gem.socketState",[{n:"connected",k:"b"},{n:"reason",k:"e",o:1,v:["connecting","dropped","watchdog","terminal"]}]);a("gem.seatedEvent",[{n:"roomId",k:"s",max:64}]);a("gem.autoStartFailedEvent",[{n:"roomId",k:"s",max:64},{n:"code",k:"s",max:64}]);a("gem.ticketEvent",[{n:"event",k:"e",v:["queued","matched","expired","cancelled","failed"]},{n:"ticketId",k:"s",max:64},{n:"partySize",k:"i",o:1,lo:1,hi:64},{n:"queuedAt",k:"i",o:1,lo:0,hi:4102444800},{n:"expiresAt",k:"i",o:1,lo:0,hi:4102444800},{n:"reason",k:"s",o:1,max:64},{n:"roomId",k:"s",o:1,max:64}]);a("gem.signalEvent",[{n:"event",k:"e",v:["hello","offer","answer","ice","peerJoined","peerLeft","migration","matchEnded","error"]},{n:"matchId",k:"s",max:64},{n:"data",k:"j"}]);a("gem.dedicatedEvent",[{n:"event",k:"e",v:["answer","error","matchEnded"]},{n:"matchId",k:"s",max:64},{n:"sdp",k:"s",o:1,max:10240},{n:"sessionId",k:"s",o:1,max:64},{n:"code",k:"s",o:1,max:64},{n:"message",k:"s",o:1,max:256},{n:"reason",k:"s",o:1,max:64}]);a("gem.partyResult",[{n:"requestId",k:"s",max:64},{n:"partyId",k:"s",o:1,max:64}]);a("gem.clusterTarget",[{n:"clusterTargetId",k:"s",max:64},{n:"clusterTargetIds",k:"a",o:1,max:3,it:{n:"",k:"s",max:64}}]);a("gem.devtools",[{n:"action",k:"e",v:["open","close","toggle"]}]);a("gem.screenshot",[{n:"maxWidth",k:"i",lo:1,hi:7680},{n:"maxHeight",k:"i",lo:1,hi:4320}]);a("gem.screenshot.denied",[{n:"reason",k:"e",v:["not_wired","no_source","unsupported","unreadable","tainted","too_large","busy","declined","failed"]},{n:"retryable",k:"b"}]);a("gem.requestContext",[]);a("gem.gameContext",[{n:"context",k:"j"}]);a("gem.signal",[{n:"signal",k:"e",v:["join","offer","answer","ice","migrationAck","hostUnreachable"]},{n:"matchId",k:"s",max:64},{n:"data",k:"j"}]);a("gem.dedicatedOffer",[{n:"matchId",k:"s",max:64},{n:"sdp",k:"s",max:10240},{n:"intent",k:"e",v:["initial","ice_restart","full_reconnect"]}]);a("gem.partyRequest",[{n:"requestId",k:"s",max:64}]);a("gem.ready",[]);a("gem.engaged",[]);a("gem.progress",[{n:"loaded",k:"i",lo:0,hi:1099511627776},{n:"total",k:"i",lo:0,hi:1099511627776}]);a("gem.requestToken",[{n:"requestId",k:"s",max:64},{n:"reason",k:"e",v:["initial","expiring","rejected"]}]);a("gem.requestLocalServer",[{n:"requestId",k:"s",max:64},{n:"gameRoomId",k:"s",max:64}]);a("gem.localServer",[{n:"requestId",k:"s",max:64},{n:"serverId",k:"s",o:1,max:128}]);a("gem.localServer.denied",[{n:"requestId",k:"s",max:64},{n:"retryable",k:"b"},{n:"reason",k:"e",v:["refused","unavailable"]}]);a("gem.exit",[{n:"reason",k:"s",o:1,max:64}]);a("gem.openExternal",[{n:"url",k:"s",max:2048,f:"url"}]);a("gem.requestFullscreen",[{n:"enabled",k:"b"}]);a("gem.audioState",[{n:"muted",k:"b"}]);a("gem.rewardCue",[{n:"currencySlug",k:"s",max:32},{n:"expected",k:"i",o:1,lo:1,hi:1e9},{n:"origin",k:"o",o:1,fs:[{n:"x",k:"i",lo:0,hi:16384},{n:"y",k:"i",lo:0,hi:16384}]}]);a("gem.walletDisplay",[{n:"visible",k:"b"},{n:"currencies",k:"a",o:1,max:8,it:{n:"",k:"s",max:64}},{n:"score",k:"b",o:1}]);a("gem.controlsDeclare",[{n:"uses",k:"o",fs:[{n:"lookSensitivity",k:"s",o:1,max:16,f:"code"},{n:"gamepadLookSensitivity",k:"s",o:1,max:16,f:"code"},{n:"invertLookY",k:"s",o:1,max:16,f:"code"},{n:"touchMovement",k:"s",o:1,max:16,f:"code"}]}]);a("gem.menu",[{n:"settings",k:"b"},{n:"items",k:"a",o:1,max:4,it:{n:"",k:"o",fs:[{n:"id",k:"s",max:32},{n:"label",k:"s",max:40}]}}]);a("gem.menuSelect",[{n:"entry",k:"e",v:["settings","item"]},{n:"id",k:"s",o:1,max:32}]);a("gem.gemCorner",[{n:"corner",k:"e",v:["top-left","top-right","bottom-left","bottom-right"]}]);a("gem.requestShare",[{n:"params",k:"a",max:16,it:{n:"",k:"o",fs:[{n:"key",k:"s",max:64},{n:"value",k:"s",max:512}]}}]);a("gem.requestAvatarPicker",[{n:"tab",k:"e",o:1,v:["2d","3d"]}]);a("gem.vibrate",[{n:"pattern",k:"a",max:99,it:{n:"",k:"i",lo:0,hi:1e4}}]);a("gem.frameStats",[{n:"fps",k:"i",lo:0,hi:1e3},{n:"frameTimeP95Ms",k:"i",lo:0,hi:1e5}]);a("gem.portraitBorders",[{n:"name",k:"s",o:1,max:40}]);a("gem.error",[{n:"code",k:"e",v:["version_mismatch","handshake_timeout","handshake_duplicate","invalid_message","rate_limited","token_unavailable","unsupported","unsupported_capability","internal"]},{n:"message",k:"s",o:1,max:256}]);a("gem.requestPurchase",[{n:"requestId",k:"s",max:64},{n:"purchaseKind",k:"e",v:["item","recipe"]},{n:"targetId",k:"s",max:64},{n:"currencySlug",k:"s",max:32},{n:"quantity",k:"i",o:1,lo:1,hi:10},{n:"catalogId",k:"s",o:1,max:64}]);a("gem.requestAvatar3dPurchase",[{n:"requestId",k:"s",max:64},{n:"itemId",k:"s",max:64},{n:"currencySlug",k:"s",max:32}]);a("gem.purchaseResult",[{n:"requestId",k:"s",max:64},{n:"outcome",k:"e",v:["ok","declined","unavailable"]},{n:"reason",k:"s",o:1,max:64,f:"code"},{n:"purchaseId",k:"s",o:1,max:64}]);a("gem.deviceSettings.put",[{n:"requestId",k:"s",max:64},{n:"settings",k:"j"}]);a("gem.deviceSettings.result",[{n:"requestId",k:"s",max:64},{n:"outcome",k:"e",v:["stored","too_large","unavailable"]}]);a("gem.requestAd",[{n:"requestId",k:"s",max:64},{n:"placement",k:"s",max:32},{n:"format",k:"e",v:["interstitial","rewarded"]}]);a("gem.adResult",[{n:"requestId",k:"s",max:64},{n:"outcome",k:"e",v:["shown","no_ad","unavailable"]}]);a("gem.requestSignIn",[{n:"requestId",k:"s",max:64}]);a("gem.signInResult",[{n:"requestId",k:"s",max:64},{n:"outcome",k:"e",v:["signed_in","declined","unavailable"]}]);a("gem.requestFriendChallenge",[{n:"requestId",k:"s",max:64},{n:"playerId",k:"s",max:64},{n:"template",k:"s",max:64},{n:"params",k:"j",o:1}]);a("gem.friendChallengeResult",[{n:"requestId",k:"s",max:64},{n:"outcome",k:"e",v:["accepted","cancelled","refused","unavailable","rate_limited","invalid"]},{n:"code",k:"s",o:1,max:64},{n:"param",k:"s",o:1,max:64},{n:"channel",k:"s",o:1,max:16},{n:"configVersion",k:"i",o:1,lo:0,hi:9007199254740991},{n:"retryAfterMs",k:"i",o:1,lo:0,hi:864e5},{n:"detail",k:"s",o:1,max:300}]);var R=Object.freeze(W);var le=/^[a-z0-9][a-z0-9_-]{0,39}$/;function de(n){return typeof n=="string"&&le.test(n)}function N(n){if(n===null||de(n))return n;let e=typeof n=="string"?JSON.stringify(n.length>48?`${n.slice(0,48)}\u2026`:n):`a value of type ${typeof n}`;console.warn(`[gem] showPortraitBorders: ${e} is not a border name, so nothing was sent. A name is 1 to 40 of a-z, 0-9, _ and -, starting with a letter or digit, exactly as your store page declares it under media.portrait_borders. Pass null for no art.`);}var E=class{#e;constructor(e){this.#e=e,Object.freeze(this);}toString(){return "[gem: use gem.text.toPlain()]"}toJSON(){return this.toString()}get[Symbol.toStringTag](){return "PlayerText"}static unwrap(e){return e.#e}};function I(n){return new E(n)}var q={now:()=>Date.now(),setTimeout:(n,e)=>setTimeout(n,e),clearTimeout:n=>clearTimeout(n)},v=class{constructor(e=q){this.clock=e;}clock;tokens=new Map;lastRefill=new Map;allow(e){let t=$[e];if(t===void 0)return false;let r=this.clock.now(),s=this.lastRefill.get(e)??r,i=this.tokens.get(e)??t,d=Math.max(0,r-s),o=Math.min(t,i+d*t/6e4);return o<1?(this.tokens.set(e,o),this.lastRefill.set(e,r),false):(this.tokens.set(e,o-1),this.lastRefill.set(e,r),true)}};function A(n,e){return n.toLowerCase()===e.toLowerCase()}function V(n){let e=n.toLowerCase();return e==="localhost"||e.endsWith(".localhost")||e==="[::1]"||e==="::1"?true:/^127(\.\d{1,3}){3}$/.test(e)}function z(n,e){if(typeof e!="string"||e==="")return false;let t,r;try{t=new URL(n),r=new URL(e);}catch{return false}return t.protocol!=="http:"&&t.protocol!=="https:"||r.protocol!=="http:"&&r.protocol!=="https:"||t.username!==""||t.password!==""||t.pathname!=="/"||t.search!==""||t.hash!==""||t.port===""?false:V(t.hostname)&&V(r.hostname)}function Y(n,e){if(n.min>n.max||e.min>e.max)return null;let t=Math.min(n.max,e.max),r=Math.max(n.min,e.min);return t>=r?t:null}function K(n){return Math.min(16384,Math.max(0,Math.round(Number.isFinite(n)?n:0)))}function me(n,e){if(n!==true)return {visible:false};let t=[],r=false;for(let s of Array.isArray(e)?e:[])s==="score"?r=true:typeof s=="string"&&s.length>0&&s.length<=64&&!t.includes(s)&&t.push(s);return !r&&t.length===0?{visible:true}:{visible:true,currencies:t.slice(0,8),score:r}}function ce(n){let e=[];for(let t of Array.isArray(n)?n:[]){if(e.length===4)break;if(typeof t!="object"||t===null)continue;let{id:r,label:s}=t;typeof r!="string"||r.length===0||r.length>32||typeof s!="string"||s.trim().length===0||e.some(i=>i.id===r)||e.push({id:r,label:s.trim().slice(0,40)});}return e.length===0?{settings:false}:{settings:false,items:e}}function J(n,e){return Math.min(e,Math.max(0,Math.round(Number.isFinite(n)?n:0)))}function ue(n){let e=n.untrusted,t=I(e.displayName),r=e.displayTag||e.displayHandle,s=r?I(r):void 0,i=n.discriminator||n.displayTag,d=i&&/^[0-9]{1,8}$/.test(i)?i:void 0,o=n.avatarIconUrl||n.avatarUrl,m=/^[\da-f]{8}(-[\da-f]{4}){3}-[\da-f]{12}$/i,g=n.avatarIconId,p=n.avatar3dId,c={displayName:t,displayHandle:s??t,badges:(n.badges??[]).map(u=>({itemId:u.itemId,iconUrl:u.iconUrl}))};n.playerId&&(c.playerId=n.playerId),d&&(c.discriminator=d),s&&(c.displayTag=s),o&&(c.avatarIconUrl=c.avatarUrl=o),g&&m.test(g)&&(c.avatarIconId=g),p&&m.test(p)&&(c.avatar3dId=p),n.avatar3dModelUrl&&(c.avatar3dModelUrl=n.avatar3dModelUrl),n.avatar3dIconUrl&&(c.avatar3dIconUrl=n.avatar3dIconUrl),n.avatars3d&&(c.avatars3d=n.avatars3d.filter(u=>m.test(u.id)&&/^[a-z][a-z0-9_]*$/.test(u.family)).filter((u,G,O)=>O.findIndex(C=>C.family==u.family)==G).map(({family:u,id:G,modelUrl:O,iconUrl:C})=>({family:u,id:G,modelUrl:O,iconUrl:C})));let y=n.boost,f=(y?.multipliers??[]).map(u=>({currencyId:u.currencyId,currencySlug:u.currencySlug,multiplier:u.multiplierBp/1e4})),S=f.some(u=>u.multiplier>1);return c.boost=S&&y?.expiresInDays?{active:S,multipliers:f,expiresInDays:y.expiresInDays}:{active:S,multipliers:f},c}var ge=1e4,x=class{constructor(e){this.options=e;if(e.expectedSource===void 0||e.expectedSource===null)throw new Error("GemFrame: expectedSource is required and must not be null \u2014 pass window.parent. The handshake transfers the MessagePort, and origin alone does not say WHICH document on that origin sent it.");this.expectedSource=e.expectedSource,this.clock=e.clock??q,this.inbound=new v(this.clock),this.outbound=new v(this.clock);}options;state="waiting";port=null;version=null;peerCapabilities=[];unbidden=false;engagedSent=false;readyPending=false;readySent=false;settleWaiters=[];clock;inbound;outbound;expectedSource;get currentState(){return this.state}get parentCapabilities(){return this.peerCapabilities}parentSupports(e){return this.peerCapabilities.includes(e)}get protocolVersion(){return this.version}get unbiddenLaunch(){return this.unbidden}handleWindowMessage(e){if(e.source!==this.expectedSource)return this.refuse(e,"handshake did not come from the expected embedder window"),false;if(!(this.options.allowedEmbedders.some(o=>A(o,e.origin))||z(e.origin,this.options.selfOrigin)))return this.refuse(e,`embedder '${e.origin}' is not in allowedEmbedders`),this.state==="waiting"&&this.transition("refused"),false;if(this.state==="connected")return this.fail("handshake_duplicate","this document already has a port"),false;if(this.state!=="waiting")return false;let r=R["gem.handshake"]?.(e.data);if(r)return this.refuse(e,`malformed handshake: ${r}`),false;let s=e.data;if(!A(s.embedder,e.origin))return this.refuse(e,`handshake claims embedder '${s.embedder}' but arrived from '${e.origin}'`),false;let i=e.ports?.[0];if(!i)return this.refuse(e,"handshake transferred no MessagePort"),false;let d=Y(k,s.versions);return d===null?(i.onmessage=null,i.postMessage({gem:l,type:"gem.error",code:"version_mismatch",message:`frame supports v${k.min}..v${k.max}`}),i.close(),this.transition("refused"),this.options.onError?.("version_mismatch"),false):(this.port=i,this.version=d,i.onmessage=o=>this.receive(o.data,o.ports??[]),i.start?.(),this.peerCapabilities=s.capabilities??[],this.unbidden=s.unbidden===true,i.postMessage({gem:l,type:"gem.handshake.accept",v:d,...this.options.capabilities===void 0?{}:{capabilities:[...this.options.capabilities]}}),this.transition("connected"),this.readyPending&&(this.readyPending=false,this.ready()),true)}ready(){if(this.state!=="connected"||!this.port){this.readyPending=true;return}if(this.readySent){this.options.onDropped?.("internal","gem.ready was already sent; duplicate suppressed");return}this.readySent=true,this.send({gem:l,type:"gem.ready"});}settled(e=ge){return this.state!=="waiting"?Promise.resolve(this.state):new Promise(t=>{let r=i=>{this.clock.clearTimeout(s),t(i);},s=this.clock.setTimeout(()=>{let i=this.settleWaiters.indexOf(r);i>=0&&this.settleWaiters.splice(i,1),t(this.state);},e);this.settleWaiters.push(r);})}progress(e,t){this.send({gem:l,type:"gem.progress",loaded:e,total:t});}requestToken(e,t){this.send({gem:l,type:"gem.requestToken",requestId:e,reason:t});}requestLocalServer(e,t){return this.parentSupports("localHost")?(this.send({gem:l,type:"gem.requestLocalServer",requestId:e,gameRoomId:t}),true):false}exit(e){this.send(e===void 0?{gem:l,type:"gem.exit"}:{gem:l,type:"gem.exit",reason:e});}openExternal(e){this.send({gem:l,type:"gem.openExternal",url:e});}requestFullscreen(e){this.send({gem:l,type:"gem.requestFullscreen",enabled:e});}reportMuted(e){return this.gated("audioState")?(this.send({gem:l,type:"gem.audioState",muted:e}),true):false}reportEngaged(){return this.engagedSent||!this.gated("engagement")||!this.send({gem:l,type:"gem.engaged"})?false:(this.engagedSent=true,true)}cueReward(e){if(!this.gated("rewardCue"))return false;let t={gem:l,type:"gem.rewardCue",currencySlug:String(e.currencySlug).slice(0,32)};return e.expected!==void 0&&Number.isFinite(e.expected)&&e.expected>=1&&(t.expected=Math.min(1e9,Math.round(e.expected))),e.origin&&(t.origin={x:K(e.origin.x),y:K(e.origin.y)}),this.send(t),true}showPortraitBorders(e){let t=N(e);return t===void 0||!this.gated("portraitBorders")?false:this.send(t===null?{gem:l,type:"gem.portraitBorders"}:{gem:l,type:"gem.portraitBorders",name:t})}setWalletVisible(e,t){return this.gated("walletDisplay")?this.send({gem:l,type:"gem.walletDisplay",...me(e,t?.only)}):false}setMenu(e){return this.gated("gameMenu")?this.send({gem:l,type:"gem.menu",...ce(e)}):false}setGemCorner(e){return this.gated("gemCorner")?this.send({gem:l,type:"gem.gemCorner",corner:e}):false}requestShare(e){return this.gated("share")?this.send({gem:l,type:"gem.requestShare",params:e.map(({key:t,value:r})=>({key:t,value:r}))}):false}requestAvatarPicker(e){return this.gated("avatarPicker")?this.send({gem:l,type:"gem.requestAvatarPicker",...e==="2d"||e==="3d"?{tab:e}:{}}):false}requestVibrate(e){return this.gated("vibration")?this.send({gem:l,type:"gem.vibrate",pattern:[...e]}):false}reportFrameStats(e){return this.gated("frameStats")?(this.send({gem:l,type:"gem.frameStats",fps:J(e.fps,1e3),frameTimeP95Ms:J(e.frameTimeP95Ms,1e5)}),true):false}sendGameContext(e){return this.state!=="connected"?false:(this.send({gem:l,type:"gem.gameContext",context:e}),true)}signal(e,t,r){this.send({gem:l,type:"gem.signal",signal:e,matchId:t,data:r});}dedicatedOffer(e,t,r){this.send({gem:l,type:"gem.dedicatedOffer",matchId:e,sdp:t,intent:r});}requestParty(e){return this.send({gem:l,type:"gem.partyRequest",requestId:e})}requestPurchase(e,t,r,s,i,d){return this.send({gem:l,type:"gem.requestPurchase",requestId:e,purchaseKind:t,targetId:r,currencySlug:s,...i===void 0?{}:{quantity:i},...d===void 0?{}:{catalogId:d}})}requestAvatar3dPurchase(e,t,r){return this.parentSupports("avatar3dPurchases")?this.send({gem:l,type:"gem.requestAvatar3dPurchase",requestId:e,itemId:t,currencySlug:r}):false}putDeviceSettings(e,t){return this.send({gem:l,type:"gem.deviceSettings.put",requestId:e,settings:t})}requestAd(e,t,r){return this.send({gem:l,type:"gem.requestAd",requestId:e,placement:t,format:r})}requestSignIn(e){return this.send({gem:l,type:"gem.requestSignIn",requestId:e})}requestFriendChallenge(e,t,r,s){return this.send({gem:l,type:"gem.requestFriendChallenge",requestId:e,playerId:t,template:r,...s===void 0?{}:{params:s}})}close(){this.port&&(this.port.onmessage=null,this.port.close(),this.port=null),this.state!=="refused"&&this.transition("closed");}transition(e){if(this.state!==e){this.state=e;for(let t of this.settleWaiters.splice(0))t(e);this.options.onStateChange?.(e);}}refuseMalformed(e,t){if(!this.inbound.allow(w)){this.options.onDropped?.(e,t);return}this.fail(e,t);}dropUnknownType(e){this.inbound.allow(w)&&this.options.onDropped?.("unsupported",`ignored unknown message type '${e}'`);}refuse(e,t){e.ports?.[0]?.close?.(),this.inbound.allow(w)&&this.options.onRefused?.(t);}fail(e,t){this.options.onError?.(e,t),this.state==="connected"&&this.port&&this.send({gem:l,type:"gem.error",code:e,...t===void 0?{}:{message:t}});}gated(e){return this.state==="connected"&&this.parentSupports(e)}send(e){if(this.state!=="connected"||!this.port)return this.options.onDropped?.("internal",`dropped ${String(e.type)} before connect`),false;let t=e.type;if(!this.outbound.allow(t))return this.options.onError?.("rate_limited",`frame exceeded its own limit for ${t}`),false;let r=R[t]?.(e);return r?(this.options.onError?.("internal",`refusing to send malformed ${t}: ${r}`),false):(this.port.postMessage(this.version===null?e:{...e,v:this.version}),true)}receive(e,t=[]){let r=false;try{r=this.dispatchInbound(e,t);}finally{r||Q(t);}}dispatchInbound(e,t){if(this.state!=="connected")return false;let r=typeof e=="object"&&e!==null?e.type:void 0;if(typeof r!="string")return this.refuseMalformed("invalid_message","message has no type"),false;let s=R[r];if(!s)return this.dropUnknownType(r),false;if(!this.inbound.allow(r))return this.fail("rate_limited",`parent exceeded the limit for ${r}`),false;let i=U(r);if(i!==void 0&&!this.options.capabilities?.includes(i))return this.fail("unsupported_capability",`${r} requires the '${i}' capability, which this frame did not advertise`),false;let d=s(e);if(d)return this.fail("invalid_message",`${r}: ${d}`),false;let o=e;if(o.v!==this.version)return this.fail("invalid_message",`${r}: expected v ${String(this.version)}`),false;switch(r){case "gem.token":this.options.onToken?.(o);break;case "gem.pause":this.options.onPause?.(o);break;case "gem.menuSelect":this.options.onMenuSelect?.(o);break;case "gem.prefs":this.options.onPrefs?.(o);break;case "gem.cohorts":this.options.onCohorts?.(o);break;case "gem.earnAllowanceChanged":this.options.onEarnAllowanceChanged?.();break;case "gem.viewport":this.options.onViewport?.(o);break;case "gem.willTerminate":this.options.onWillTerminate?.(o);break;case "gem.devtools":this.options.onDevtools?.(o.action);break;case "gem.requestContext":this.options.onRequestContext?.();break;case "gem.screenshot":{let m=t[0];if(!m){this.options.onError?.("invalid_message","gem.screenshot transferred no MessagePort");break}let g={maxWidth:o.maxWidth,maxHeight:o.maxHeight};if(!this.options.onScreenshot){m.close(),this.screenshotDenied("not_wired",false);break}return Q(t.slice(1)),this.options.onScreenshot(g,m,(p,c)=>this.screenshotDenied(p,c)),true}case "gem.token.denied":this.options.onTokenDenied?.(o);break;case "gem.localServer":this.options.onLocalServer?.(o);break;case "gem.localServer.denied":this.options.onLocalServerDenied?.(o);break;case "gem.player":{this.options.onPlayer?.(ue(o));break}case "gem.roomEvent":this.options.onRoomEvent?.(o);break;case "gem.seatedEvent":this.options.onSeatedEvent?.(o);break;case "gem.autoStartFailedEvent":this.options.onAutoStartFailedEvent?.(o);break;case "gem.ticketEvent":this.options.onTicketEvent?.(o);break;case "gem.socketState":this.options.onSocketState?.(o);break;case "gem.signalEvent":this.options.onSignalEvent?.(o);break;case "gem.dedicatedEvent":this.options.onDedicatedEvent?.(o);break;case "gem.clusterTarget":this.options.onClusterTarget?.(o);break;case "gem.partyResult":this.options.onPartyResult?.(o);break;case "gem.purchaseResult":this.options.onPurchaseResult?.(o);break;case "gem.deviceSettings":this.options.onDeviceSettings?.(o);break;case "gem.deviceSettings.result":this.options.onDeviceSettingsResult?.(o);break;case "gem.adResult":this.options.onAdResult?.(o);break;case "gem.signInResult":this.options.onSignInResult?.(o);break;case "gem.friendChallengeResult":this.options.onFriendChallengeResult?.(o);break;case "gem.error":this.options.onError?.(o.code,o.message);break;default:this.fail("unsupported",`no frame handler for '${r}'`);}return false}screenshotDenied(e,t){this.send({gem:l,type:"gem.screenshot.denied",reason:e,retryable:t});}};function Q(n){for(let e of n)try{e?.close?.();}catch{}}_();function pe(n){if((n.expectedSource??window.parent)===window)throw new Error("GemWebSdkBridge.connect: this document is not framed (window.parent === window), so there is no embedder to hand it a port. A game runs inside the Gem Arcade iframe; opening it directly will never complete a handshake.");let e=new x({...n,expectedSource:n.expectedSource??window.parent}),t=r=>{let s=e.handleWindowMessage({data:r.data,origin:r.origin,source:r.source,ports:r.ports});return s&&window.removeEventListener("message",t),s};return window.addEventListener("message",t),M(window,t),e}var X={connect:pe,GemFrame:x,PROTOCOL:l,SUPPORTED_VERSIONS:k};window.GemWebSdkBridge=X;var Dt=X;return Dt;})();