@indiegems/gem-web-sdk 10.1.1 → 10.3.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 +32 -0
- package/dist/game.d.ts +52 -1
- package/dist/gem-web-sdk.bridge.js +1 -1
- package/dist/gem-web-sdk.esm.js +2 -2
- package/dist/gem-web-sdk.function.js +2 -2
- package/dist/gem-web-sdk.game.js +2 -2
- package/dist/gem-web-sdk.min.js +2 -2
- package/dist/gem-web-sdk.sdk.js +2 -2
- package/dist/gem-web-sdk.server-api.js +1 -1
- package/dist/gem-web-sdk.server.js +2 -2
- package/dist/index.d.ts +42 -3
- package/dist/sdk.d.ts +162 -11
- package/dist/server-api.d.ts +70 -2
- package/dist/server.d.ts +103 -3
- package/docs/api/api-reference-game.md +616 -10
- package/docs/api/api-reference-server.md +244 -4
- package/docs/api/reference.json +993 -12
- package/docs/changelog.md +32 -0
- package/docs/getting-started.md +1 -1
- package/docs/manifest.json +10 -10
- package/docs/rooms-and-matches.md +7 -0
- package/docs/server-bundles.md +46 -2
- package/docs/what-a-game-must-do.md +140 -1
- package/package.json +1 -1
- package/schema/bridge.v1.json +220 -7
- package/schema/capabilities.public.json +12 -0
package/CHANGELOG.md
CHANGED
|
@@ -16,6 +16,38 @@ Its entries are grouped under up to five headings:
|
|
|
16
16
|
- **Rebuild**: a type changed. Recompile against the new version; code that compiles today keeps compiling unless the entry says otherwise.
|
|
17
17
|
- **New capability**: something a game can now do. Nothing changes unless you use it.
|
|
18
18
|
|
|
19
|
+
## 10.3.0
|
|
20
|
+
|
|
21
|
+
Upgrading from 10.2.0. Impact: required.
|
|
22
|
+
|
|
23
|
+
### Rebuild
|
|
24
|
+
|
|
25
|
+
- The set of messages a frame sends to the Arcade has grown by one controls declaration message, so the message list and the FrameMessage union changed. Recompiling is enough. If your code switches exhaustively over frame message types, add a case for the new one.
|
|
26
|
+
- GemCapability gained a controls value. Recompiling is enough. If you map every capability to something exhaustively, add an entry for it.
|
|
27
|
+
- The recommended settings inside the preferences gained four optional fields for look sensitivity, gamepad look sensitivity, look inversion and touch movement. Recompiling is enough. The touch movement value appears as a plain string in the received preferences, while the host-side sendPrefs accepts only floating or fixed, so treat unknown values as the default.
|
|
28
|
+
|
|
29
|
+
### New capability
|
|
30
|
+
|
|
31
|
+
- Your game can now declare which control choices it offers by using Gem.controls, which is a ControlsApi, or GemFrame.declareControls. You describe the choices with GemControlChoice entries inside a GemControlsDeclaration. Declaring them lets the Arcade show the matching camera and controls settings for your game. Check that the new controls capability is available before declaring.
|
|
32
|
+
- The SDK now provides camera look input. GemLook delivers GemLookDelta values, configured with GemLookOptions and scaled by a GemLookSpeed. GemLookBase gives the base look speed. Use these instead of your own look scaling so that the player's sensitivity choices apply to your game.
|
|
33
|
+
- The player's recommended settings now carry four optional fields: lookSensitivity, gamepadLookSensitivity, invertLookY and touchMovement. Read them to start with the player's preferred look sensitivity, look inversion and touch movement style. They may be absent, so keep your own defaults for when they are not provided.
|
|
34
|
+
|
|
35
|
+
## 10.2.0
|
|
36
|
+
|
|
37
|
+
Upgrading from 10.1.1. Impact: required.
|
|
38
|
+
|
|
39
|
+
### Rebuild
|
|
40
|
+
|
|
41
|
+
- The match object on the server types now has two more methods, setBackfill and reportPlayers, besides end. Recompile your server. If you wrote your own implementation or test double of the server or match server types, add the two new methods or it will no longer type-check.
|
|
42
|
+
- The list of frame-to-parent message names, the frame message type and the capability type each gained a new member for the avatar picker. Recompile. If your code switches exhaustively over any of them, or checks that every member is handled, add a case for the new avatar picker member.
|
|
43
|
+
- The order source type gained two new values, one for test account provisioning and one for developer grants, and each progression state entry in a paginated response may now carry an optional completion threshold. Recompile. If you switch exhaustively over order sources, handle the new values.
|
|
44
|
+
|
|
45
|
+
### New capability
|
|
46
|
+
|
|
47
|
+
- Games running inside the Arcade can now read the player's current Arcade avatar from GemPlayer.avatarIconId. It is only set when the value is a valid identifier, and the Arcade sends the player again whenever the worn avatar changes, so listen for player updates rather than reading it once. Games can also ask the Arcade to open its avatar picker. Check Gem.avatarPickerAvailable first, then call Gem.openAvatarPicker. It returns false outside the Arcade, before the connection is ready, when the Arcade does not offer the picker, or when you call it too often, and it never throws or waits. Nothing answers the request directly; the outcome is an updated player.
|
|
48
|
+
- If your code hosts a game frame, you can now pass the avatar identifier when sending player information and handle the avatar picker request through the new host callback and option. Incoming picker requests have a new message type with its own validator. Without a handler, the request is refused.
|
|
49
|
+
- Dedicated game servers can now control matchmaking backfill. Call setBackfill to stop or restart the platform topping up a running match from the matchmaking queue, optionally with a seat count, and it returns the resulting backfill state. Call reportPlayers to tell the platform whether each player has connected, never showed up, or left. The last two remove the player from the room. The server SDK also reports each joining player as connected on its own, which gives a seat filled from the queue a time limit. If the platform does not offer these routes, it stops trying for that match after one refused call. The matching low-level server API operations and request and response types are available too.
|
|
50
|
+
|
|
19
51
|
## 10.1.1
|
|
20
52
|
|
|
21
53
|
Upgrading from 10.1.0. Impact: none.
|
package/dist/game.d.ts
CHANGED
|
@@ -2020,6 +2020,10 @@ interface GemPrefs$1 {
|
|
|
2020
2020
|
keyboardLayout: "wasd" | "arrows";
|
|
2021
2021
|
gamepadConfirm: "south" | "east";
|
|
2022
2022
|
vibration: boolean;
|
|
2023
|
+
lookSensitivity?: number;
|
|
2024
|
+
gamepadLookSensitivity?: number;
|
|
2025
|
+
invertLookY?: boolean;
|
|
2026
|
+
touchMovement?: string;
|
|
2023
2027
|
};
|
|
2024
2028
|
}
|
|
2025
2029
|
interface GemCohorts$1 {
|
|
@@ -2686,6 +2690,13 @@ interface PlayerBoost {
|
|
|
2686
2690
|
readonly multipliers: readonly PlayerBoostMultiplier[];
|
|
2687
2691
|
readonly expiresInDays?: number;
|
|
2688
2692
|
}
|
|
2693
|
+
type GemControlChoice = "player" | "game";
|
|
2694
|
+
interface GemControlsDeclaration {
|
|
2695
|
+
readonly lookSensitivity?: GemControlChoice;
|
|
2696
|
+
readonly gamepadLookSensitivity?: GemControlChoice;
|
|
2697
|
+
readonly invertLookY?: GemControlChoice;
|
|
2698
|
+
readonly touchMovement?: GemControlChoice;
|
|
2699
|
+
}
|
|
2689
2700
|
interface RewardCue {
|
|
2690
2701
|
currencySlug: string;
|
|
2691
2702
|
expected?: number;
|
|
@@ -2783,6 +2794,7 @@ declare class GemFrame {
|
|
|
2783
2794
|
setWalletVisible(visible: boolean, options?: {
|
|
2784
2795
|
only?: readonly string[];
|
|
2785
2796
|
}): boolean;
|
|
2797
|
+
declareControls(uses: GemControlsDeclaration): boolean;
|
|
2786
2798
|
setMenu(settings: boolean, items?: ReadonlyArray<{
|
|
2787
2799
|
readonly id: string;
|
|
2788
2800
|
readonly label: string;
|
|
@@ -2791,6 +2803,7 @@ declare class GemFrame {
|
|
|
2791
2803
|
readonly key: string;
|
|
2792
2804
|
readonly value: string;
|
|
2793
2805
|
}>): boolean;
|
|
2806
|
+
requestAvatarPicker(): boolean;
|
|
2794
2807
|
requestVibrate(pattern: readonly number[]): boolean;
|
|
2795
2808
|
reportFrameStats(stats: {
|
|
2796
2809
|
fps: number;
|
|
@@ -2827,6 +2840,37 @@ interface VibrationApi {
|
|
|
2827
2840
|
readonly available: boolean;
|
|
2828
2841
|
vibrate(pattern: number | readonly number[]): boolean;
|
|
2829
2842
|
}
|
|
2843
|
+
interface GemLookSpeed {
|
|
2844
|
+
readonly yaw: number;
|
|
2845
|
+
readonly pitch: number;
|
|
2846
|
+
}
|
|
2847
|
+
interface GemLookBase {
|
|
2848
|
+
readonly touch: GemLookSpeed;
|
|
2849
|
+
readonly mouse: GemLookSpeed;
|
|
2850
|
+
readonly stick: GemLookSpeed;
|
|
2851
|
+
readonly stickDeadzone: number;
|
|
2852
|
+
readonly stickCurve: number;
|
|
2853
|
+
readonly touchPitchMin: number;
|
|
2854
|
+
}
|
|
2855
|
+
interface GemLookOptions {
|
|
2856
|
+
readonly sensitivity?: number;
|
|
2857
|
+
readonly gamepadSensitivity?: number;
|
|
2858
|
+
readonly invertY?: boolean;
|
|
2859
|
+
}
|
|
2860
|
+
interface GemLookDelta {
|
|
2861
|
+
readonly yaw: number;
|
|
2862
|
+
readonly pitch: number;
|
|
2863
|
+
}
|
|
2864
|
+
interface GemLook {
|
|
2865
|
+
fromPointer(dx: number, dy: number, pointerType: string, pitch?: number): GemLookDelta;
|
|
2866
|
+
fromStick(x: number, y: number, dt: number): GemLookDelta;
|
|
2867
|
+
set(options: GemLookOptions): void;
|
|
2868
|
+
}
|
|
2869
|
+
interface ControlsApi {
|
|
2870
|
+
declare(uses: GemControlsDeclaration): boolean;
|
|
2871
|
+
look(options?: GemLookOptions): GemLook;
|
|
2872
|
+
readonly LOOK_BASE: GemLookBase;
|
|
2873
|
+
}
|
|
2830
2874
|
interface RewardedStatus {
|
|
2831
2875
|
readonly declared: boolean;
|
|
2832
2876
|
readonly grantable: boolean;
|
|
@@ -2913,6 +2957,10 @@ interface GemRecommendedSettings {
|
|
|
2913
2957
|
readonly keyboardLayout: "wasd" | "arrows";
|
|
2914
2958
|
readonly gamepadConfirm: "south" | "east";
|
|
2915
2959
|
readonly vibration: boolean;
|
|
2960
|
+
readonly lookSensitivity: number;
|
|
2961
|
+
readonly gamepadLookSensitivity: number;
|
|
2962
|
+
readonly invertLookY: boolean;
|
|
2963
|
+
readonly touchMovement: "floating" | "fixed";
|
|
2916
2964
|
}
|
|
2917
2965
|
interface GemCohort {
|
|
2918
2966
|
readonly experimentId: string;
|
|
@@ -2971,7 +3019,10 @@ interface Gem {
|
|
|
2971
3019
|
readonly ads: AdsApi;
|
|
2972
3020
|
readonly account: AccountApi;
|
|
2973
3021
|
readonly share: ShareApi;
|
|
3022
|
+
readonly avatarPickerAvailable: boolean;
|
|
3023
|
+
openAvatarPicker(): boolean;
|
|
2974
3024
|
readonly vibration: VibrationApi;
|
|
3025
|
+
readonly controls: ControlsApi;
|
|
2975
3026
|
readonly analytics: AnalyticsApi;
|
|
2976
3027
|
readonly leaderboards: LeaderboardsApi;
|
|
2977
3028
|
readonly challenges: ChallengesApi;
|
|
@@ -3015,4 +3066,4 @@ interface ExitAnalytics {
|
|
|
3015
3066
|
}
|
|
3016
3067
|
declare function leaveAndExit(rooms: ExitRooms, bridge: ExitBridge | null, reason?: string, analytics?: ExitAnalytics): Promise<void>;
|
|
3017
3068
|
declare function createGem(options?: GemOptions): Gem;
|
|
3018
|
-
export { ARCADE_EMBEDDERS, type AccountApi, type AdFormat, type AdOutcome, type AdOutcomeKind, type AdRequest, type AdsApi, AnalyticsApi, type AnalyticsFlushOptions, type AnalyticsFlushResult, type AnalyticsOptions, type AnalyticsRejection, type AnalyticsValue, AuthError, type AuthFailure, type AuthState, type BootMark, type BootTimeline, type Challenge, type ChallengeWindow, ChallengesApi, type ConfiguredPurchasePayment, type ConfiguredPurchaseRequest, type ConfiguredPurchaseResult, DEVICE_SETTINGS_MAX_BYTES, DedicatedServerError, type DedicatedServerFailure, type DedicatedServerSession, type DevToolsOpener, type DeviceSettings, type DeviceSettingsApi, type DeviceSettingsPutOutcome, type DirectPurchaseRequest, type DirectPurchaseResult, type EarnAllowance, type EarnAllowanceEvent, type EarnAllowancePeriod, type EarnAllowanceReadOptions, type EntityLeaderboard, type EntityLeaderboardEntry, type EntityLeaderboardOptions, type EntityType, type ExitAnalytics, type ExitBridge, type ExitRooms, type FrameState, type Friend, type FriendChallenge, FriendChallengeError, type FriendChallengeErrorCode, type FriendChallengeOutcome, type FriendChallengeOutcomeKind, type FriendChallengeRequest, type FriendChallengesPage, FriendsApi, type FriendsPage, type FunctionFailure, type FunctionInvokeOptions, type FunctionResult, FunctionsApi, type GameConfig, type GameMenu, type GameMenuItem, type GameServerLink, type Gem, GemApiError, GemClient, type GemCohort, type GemCohorts, GemConfigError, type GemDevTools, GemFrame, GemFunctionError, type GemIdentity, type GemInsets, type GemMatchApi, type GemMatchServerModule, type GemOptions, type GemPlayer, type GemPrefs, type GemRecommendedSettings, type GemReservedArea, GemSaveError, type GemServerBundle, type GemServerFactory, type GemServerHost, type GemServerHostProfile, type GemServerLifecycle, type GemTerminationNotice, GemUnframedError, type GemViewport, type GetLeaderboardOptions, type JoinWelcome, type Leaderboard, type LeaderboardEntry, type LeaderboardPeriod, LeaderboardsApi, type ListChallengesOptions, type ListFriendChallengesOptions, type ListFriendsOptions, MAX_PERIODS_BACK, type MatchConnectOptions, type MatchConnection, type MatchHosting, type MatchHostingMode, type MatchServeOptions, type MatchTransport, type MessageMeta, type MultiTransportSession, PLATFORM_EVENTS, type PeriodOptions, PlatformApi, PlatformCurrenciesApi, type PlatformCurrency, type PlatformCurrencyAccess, type PlatformCurrencyPurchasePayment, type PlatformCurrencyPurchaseRequest, type PlatformCurrencyPurchaseResult, type PlatformCurrencyReadOptions, PlatformEarnAllowanceApi, type PlatformEventName, type PlayerBadge, type PlayerBoost, type PlayerBoostMultiplier, type PlayerIdentity, type PlayerProfile, PlayerText, type ProfileCallOptions, type ProfileShowcaseEntry, ProfilesApi, type PurchaseApi, type PurchaseOptions, type PurchaseOutcome, PurchaseRefusal, type PurchaseRefusalCode, type PurchaseRequest, type PutBytesOptions, type PutSaveOptions, type RankedRow, type RecipeAvailability, type RecipeLock, type RewardCue, type RewardedStatus, type SavePage, type SaveRecord, type SendOptions$1 as SendOptions, type ServerTokenGrant, type SessionEndReason, type ShareApi, type ShareRequest, ShowcaseApi, type ShowcaseCallOptions, type ShowcaseFriendEntry, type ShowcaseFriends, type ShowcaseValue, type SignInOutcome, type SignInOutcomeKind, type SnapshotCurrency, type SnapshotItem, type TransportAdvert, type TransportKind, TransportRefusal, UNRELIABLE_CHANNEL_LABEL, type VibrationApi, type WalletVisibleOptions, asPlayerText, createBootTimeline, createGem, leaveAndExit, mapIdentity, markOnResolve, platformIconUrl, presentJoinCredential, readTemplateTransports, readTransportAdvert, reportOnResolve, text, webTransportAvailable };
|
|
3069
|
+
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 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 };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var GemWebSdkBridgeBundle=(function(){'use strict';var w="GemWebSdkHandshake";function z(){return typeof document>"u"?void 0:document.readyState}var E=()=>Date.now();function I(n={}){let e=n.win??window,t=e,r=t[w];if(r!==void 0)return r;let a=n.readyState??z,i=n.now??E,d=[],s=[],m=g=>{let p=g.data;!p||p.type!=="gem.handshake"||(d.length>=4&&(d.shift(),s.shift(),c.dropped+=1),d.push(g),s.push(i()));};e.addEventListener("message",m);let c={events:d,times:s,dropped:0,late:a()==="complete",uninstall(){e.removeEventListener("message",m);}};return t[w]=c,c}function q(n,e,t={}){let r=n[w];if(r===void 0)return null;let a=t.ttlMs??9500,i=t.now??E,d=r.events.splice(0),s=r.times?.splice(0),m=0,c=0,g=false,p=i()-a;for(let u=d.length-1;u>=0;u--){let P=s?.[u];if(P!==void 0&&P<p){c+=1;continue}if(m+=1,e(d[u])===true){g=true;break}}return r.uninstall(),{capture:r,delivered:m,stale:c,accepted:g}}var l="gem-web-bridge",f={min:1,max:1},y=65536,L=8,v=5e3,A=1024;function R(n){return Object.freeze(Object.assign(Object.create(null),n))}var _=R({"gem.handshake":30,"gem.handshake.accept":5,"gem.token":30,"gem.token.denied":30,"gem.player":12,"gem.pause":120,"gem.prefs":60,"gem.cohorts":12,"gem.earnAllowanceChanged":30,"gem.viewport":60,"gem.deviceSettings":12,"gem.willTerminate":10,"gem.roomEvent":120,"gem.socketState":12,"gem.seatedEvent":60,"gem.autoStartFailedEvent":30,"gem.signalEvent":1800,"gem.dedicatedEvent":120,"gem.partyResult":30,"gem.clusterTarget":12,"gem.devtools":30,"gem.screenshot":6,"gem.screenshot.denied":12,"gem.requestContext":12,"gem.gameContext":12,"gem.signal":1200,"gem.dedicatedOffer":60,"gem.partyRequest":12,"gem.ready":5,"gem.engaged":5,"gem.progress":600,"gem.requestToken":12,"gem.requestLocalServer":6,"gem.localServer":30,"gem.localServer.denied":30,"gem.exit":5,"gem.openExternal":6,"gem.requestFullscreen":30,"gem.audioState":120,"gem.rewardCue":60,"gem.walletDisplay":60,"gem.menu":60,"gem.menuSelect":60,"gem.requestShare":6,"gem.vibrate":600,"gem.frameStats":120,"gem.portraitBorders":60,"gem.error":60,"gem.requestPurchase":12,"gem.purchaseResult":30,"gem.deviceSettings.put":30,"gem.deviceSettings.result":30,"gem.requestAd":6,"gem.adResult":12,"gem.requestSignIn":6,"gem.signInResult":12,"gem.requestFriendChallenge":12,"gem.friendChallengeResult":30,__malformed:60}),x="__malformed";var K=R({"gem.requestAd":"ads","gem.adResult":"ads","gem.requestSignIn":"signIn","gem.signInResult":"signIn","gem.requestPurchase":"purchases","gem.purchaseResult":"purchases","gem.requestFriendChallenge":"friendChallenges","gem.friendChallengeResult":"friendChallenges","gem.devtools":"devtools","gem.screenshot":"screenshot","gem.screenshot.denied":"screenshot","gem.requestContext":"feedbackContext","gem.gameContext":"feedbackContext","gem.roomEvent":"rooms","gem.signal":"p2p","gem.signalEvent":"p2p","gem.dedicatedOffer":"dedicated","gem.dedicatedEvent":"dedicated","gem.clusterTarget":"clusterTarget","gem.partyRequest":"parties","gem.partyResult":"parties","gem.autoStartFailedEvent":"autoStartFailure","gem.seatedEvent":"partySeating","gem.socketState":"socketState","gem.audioState":"audioState","gem.rewardCue":"rewardCue","gem.frameStats":"frameStats","gem.portraitBorders":"portraitBorders","gem.engaged":"engagement","gem.viewport":"viewport","gem.walletDisplay":"walletDisplay","gem.requestLocalServer":"localHost","gem.localServer":"localHost","gem.localServer.denied":"localHost","gem.cohorts":"cohorts","gem.earnAllowanceChanged":"earnAllowance","gem.deviceSettings":"deviceSettings","gem.deviceSettings.put":"deviceSettings","gem.deviceSettings.result":"deviceSettings","gem.requestShare":"share","gem.vibrate":"vibration","gem.menu":"gameMenu","gem.menuSelect":"gameMenu"}),Y=Object.freeze([["gem.asyncOpponents.","asyncOpponents"],["gem.vibration.","vibration"],["gem.viewport.","reservedAreas"]]);function j(n){let e=K[n];if(e!==void 0)return e;for(let[t,r]of Y)if(n.startsWith(t))return r}function J(n){let e=/^([a-z][a-z0-9+.-]*):\/\/([a-z0-9.-]+|\[[0-9a-f:.]+\])(:([0-9]{1,5}))?$/i.exec(n);return e===null?false:e[4]===void 0||Number(e[4])<=65535}function X(n){let e;try{e=new URL(n);}catch{return false}return e.username!==""||e.password!==""?false:e.protocol==="https:"?true:e.protocol==="http:"&&(e.hostname==="localhost"||e.hostname==="127.0.0.1")}function Q(n){return /^[a-z]{2,8}(-[a-z0-9]{1,8})*$/i.test(n)}function Z(n){return /^[a-z_]+$/.test(n)}function S(n,e,t){if(e>L)return `nesting deeper than ${L}`;if(++t.nodes>v)return `more than ${v} values`;if(t.bytes>y)return `over the ${y} byte limit`;if(n==null)return t.bytes+=4,null;let r=typeof n;if(r==="boolean")return t.bytes+=5,null;if(r==="number")return t.bytes+=8,null;if(r==="string")return t.bytes+=n.length*3+2,null;if(r!=="object")return `${r} is not plain data`;let a=n;if(t.seen.has(a))return "a repeated or cyclic object reference";if(t.seen.add(a),Array.isArray(n)){if(n.length>A)return `an array of ${n.length} entries, over the ${A} limit`;t.bytes+=2;for(let s of n){let m=S(s,e+1,t);if(m)return m}return null}let i=Object.getPrototypeOf(n);if(i!==Object.prototype&&i!==null)return "a value that is not a plain object";t.bytes+=2;let d=n;for(let s in d){if(!Object.prototype.hasOwnProperty.call(d,s))continue;if(++t.nodes>v)return `more than ${v} values`;if(t.bytes+=s.length*3+4,t.bytes>y)return `over the ${y} byte limit`;let m=S(d[s],e+1,t);if(m)return m}return null}function ee(n){let e={nodes:0,bytes:0,seen:new Set},t=S(n,0,e);return t?`message contains ${t}`:e.bytes>y?`message is over the ${y} byte limit`:null}var te={origin:[J,"not a well-formed origin"],url:[X,"not a safe absolute http(s) URL"],bcp47:[Q,"not a well-formed BCP 47 tag"],code:[Z,"not a code of lower-case letters and underscores"]};function M(n,e,t){for(let r of e){let a=t===""?r.n:`${t}.${r.n}`,i=n[r.n];if(i==null){if(r.o)continue;return `${a}: required`}let d=D(i,r,a);if(d)return d}return null}function D(n,e,t){switch(e.k){case "s":{if(typeof n!="string")return `${t}: expected string`;if(n.length>e.max)return `${t}: exceeds ${e.max} characters`;if(e.f){let[r,a]=te[e.f];if(!r(n))return `${t}: ${a}`}return null}case "i":return typeof n!="number"||!Number.isInteger(n)?`${t}: expected integer`:n<e.lo||n>e.hi?`${t}: out of range ${e.lo}..${e.hi}`:null;case "b":return typeof n=="boolean"?null:`${t}: expected boolean`;case "e":{let r=e.v;return r.includes(n)?null:`${t}: not one of ${r.join("|")}`}case "o":return typeof n!="object"||n===null||Array.isArray(n)?`${t}: expected object`:M(n,e.fs,t);case "j":return typeof n!="object"||n===null||Array.isArray(n)?`${t}: expected a plain object`:null;case "a":{if(!Array.isArray(n))return `${t}: expected array`;if(n.length>e.max)return `${t}: exceeds ${e.max} items`;let r=e.it,a=`${t}[]`;for(let i of n){if(i==null){if(r.o)continue;return `${a}: required`}let d=D(i,r,a);if(d)return d}return null}default:{let r=e.k;return `${t}: unknown kind ${String(r)}`}}}function o(n,e){return t=>{let r=ee(t);if(r)return r;if(typeof t!="object"||t===null||Array.isArray(t))return "message: expected object";let a=t;return a.gem!==l?"gem: wrong protocol marker":a.type!==n?`type: expected ${n}`:M(a,e,"")}}var ne=o("gem.handshake",[{n:"versions",k:"o",fs:[{n:"min",k:"i",lo:1,hi:1e3},{n:"max",k:"i",lo:1,hi:1e3}]},{n:"capabilities",k:"a",o:1,max:64,it:{n:"",k:"s",max:64}},{n:"embedder",k:"s",max:2048,f:"origin"},{n:"unbidden",k:"b",o:1}]),re=o("gem.handshake.accept",[{n:"v",k:"i",lo:1,hi:1e3},{n:"capabilities",k:"a",o:1,max:64,it:{n:"",k:"s",max:64}}]),oe=o("gem.token",[{n:"token",k:"s",max:4096},{n:"requestId",k:"s",o:1,max:64},{n:"generation",k:"i",lo:0,hi:2147483647},{n:"apiBaseUrl",k:"s",o:1,max:512,f:"url"},{n:"playerId",k:"s",max:64},{n:"gameId",k:"s",max:64},{n:"channel",k:"e",v:["dev","test","release"]},{n:"gameVersion",k:"s",o:1,max:64},{n:"expiresAt",k:"i",lo:0,hi:4102444800},{n:"chainEndsAt",k:"i",lo:0,hi:4102444800},{n:"allowDevTools",k:"b",o:1}]),ae=o("gem.token.denied",[{n:"requestId",k:"s",max:64},{n:"retryable",k:"b"},{n:"retryAfterMs",k:"i",o:1,lo:0,hi:36e5},{n:"reason",k:"e",v:["chain_exhausted","unavailable"]},{n:"correlationId",k:"s",max:64}]),se=o("gem.player",[{n:"untrusted",k:"o",fs:[{n:"displayName",k:"s",max:64},{n:"displayTag",k:"s",o:1,max:80},{n:"displayHandle",k:"s",max:80}]},{n:"playerId",k:"s",o:1,max:64},{n:"discriminator",k:"s",o:1,max:8},{n:"avatarIconUrl",k:"s",o:1,max:2048,f:"url"},{n:"badges",k:"a",o:1,max:2,it:{n:"",k:"o",fs:[{n:"itemId",k:"s",max:64},{n:"iconUrl",k:"s",max:2048,f:"url"}]}},{n:"displayTag",k:"s",max:8},{n:"avatarUrl",k:"s",o:1,max:2048,f:"url"},{n:"boost",k:"o",o:1,fs:[{n:"multipliers",k:"a",max:8,it:{n:"",k:"o",fs:[{n:"currencyId",k:"s",max:64},{n:"currencySlug",k:"s",max:32},{n:"multiplierBp",k:"i",lo:1e4,hi:1e6}]}},{n:"expiresInDays",k:"i",o:1,lo:1,hi:7}]}]),ie=o("gem.pause",[{n:"paused",k:"b"}]),le=o("gem.prefs",[{n:"reducedMotion",k:"b"},{n:"muted",k:"b"},{n:"showFrameStats",k:"b",o:1},{n:"locale",k:"s",max:35,f:"bcp47"},{n:"recommended",k:"o",o:1,fs:[{n:"volume",k:"i",lo:0,hi:100},{n:"batterySaver",k:"b"},{n:"keyboardLayout",k:"e",v:["wasd","arrows"]},{n:"gamepadConfirm",k:"e",v:["south","east"]},{n:"vibration",k:"b"}]}]),de=o("gem.cohorts",[{n:"cohorts",k:"a",max:8,it:{n:"",k:"o",fs:[{n:"experimentId",k:"s",max:36},{n:"variantKey",k:"s",max:32}]}}]),me=o("gem.earnAllowanceChanged",[]),ue=o("gem.viewport",[{n:"insets",k:"o",fs:[{n:"top",k:"i",lo:0,hi:4096},{n:"right",k:"i",lo:0,hi:4096},{n:"bottom",k:"i",lo:0,hi:4096},{n:"left",k:"i",lo:0,hi:4096}]},{n:"reserved",k:"a",o:1,max:4,it:{n:"",k:"o",fs:[{n:"x",k:"i",lo:0,hi:16384},{n:"y",k:"i",lo:0,hi:16384},{n:"width",k:"i",lo:0,hi:16384},{n:"height",k:"i",lo:0,hi:16384}]}}]),ce=o("gem.deviceSettings",[{n:"settings",k:"j",o:1}]),ge=o("gem.willTerminate",[{n:"reason",k:"e",v:["grant_expiring","session_ended","navigating","kill_switch"]},{n:"graceMs",k:"i",lo:0,hi:6e4}]),pe=o("gem.roomEvent",[{n:"event",k:"e",v:["updated","match_started","match_ready","match_failed","version_stale"]},{n:"roomId",k:"s",max:64},{n:"matchId",k:"s",o:1,max:64},{n:"version",k:"i",o:1,lo:0,hi:2147483647},{n:"reason",k:"s",o:1,max:64},{n:"platform",k:"e",o:1,v:["universal","mobile"]}]),ye=o("gem.socketState",[{n:"connected",k:"b"},{n:"reason",k:"e",o:1,v:["connecting","dropped","watchdog","terminal"]}]),fe=o("gem.seatedEvent",[{n:"roomId",k:"s",max:64}]),he=o("gem.autoStartFailedEvent",[{n:"roomId",k:"s",max:64},{n:"code",k:"s",max:64}]),ke=o("gem.signalEvent",[{n:"event",k:"e",v:["hello","offer","answer","ice","peerJoined","peerLeft","migration","matchEnded","error"]},{n:"matchId",k:"s",max:64},{n:"data",k:"j"}]),ve=o("gem.dedicatedEvent",[{n:"event",k:"e",v:["answer","error","matchEnded"]},{n:"matchId",k:"s",max:64},{n:"sdp",k:"s",o:1,max:10240},{n:"sessionId",k:"s",o:1,max:64},{n:"code",k:"s",o:1,max:64},{n:"message",k:"s",o:1,max:256},{n:"reason",k:"s",o:1,max:64}]),xe=o("gem.partyResult",[{n:"requestId",k:"s",max:64},{n:"partyId",k:"s",o:1,max:64}]),be=o("gem.clusterTarget",[{n:"clusterTargetId",k:"s",max:64},{n:"clusterTargetIds",k:"a",o:1,max:3,it:{n:"",k:"s",max:64}}]),we=o("gem.devtools",[{n:"action",k:"e",v:["open","close","toggle"]}]),Se=o("gem.screenshot",[{n:"maxWidth",k:"i",lo:1,hi:7680},{n:"maxHeight",k:"i",lo:1,hi:4320}]),Re=o("gem.screenshot.denied",[{n:"reason",k:"e",v:["not_wired","no_source","unsupported","unreadable","tainted","too_large","busy","declined","failed"]},{n:"retryable",k:"b"}]),Ge=o("gem.requestContext",[]),Oe=o("gem.gameContext",[{n:"context",k:"j"}]),Ce=o("gem.signal",[{n:"signal",k:"e",v:["join","offer","answer","ice","migrationAck","hostUnreachable"]},{n:"matchId",k:"s",max:64},{n:"data",k:"j"}]),Te=o("gem.dedicatedOffer",[{n:"matchId",k:"s",max:64},{n:"sdp",k:"s",max:10240},{n:"intent",k:"e",v:["initial","ice_restart","full_reconnect"]}]),Pe=o("gem.partyRequest",[{n:"requestId",k:"s",max:64}]),Ee=o("gem.ready",[]),Ie=o("gem.engaged",[]),qe=o("gem.progress",[{n:"loaded",k:"i",lo:0,hi:1099511627776},{n:"total",k:"i",lo:0,hi:1099511627776}]),Le=o("gem.requestToken",[{n:"requestId",k:"s",max:64},{n:"reason",k:"e",v:["initial","expiring","rejected"]}]),Ae=o("gem.requestLocalServer",[{n:"requestId",k:"s",max:64},{n:"gameRoomId",k:"s",max:64}]),_e=o("gem.localServer",[{n:"requestId",k:"s",max:64},{n:"serverId",k:"s",o:1,max:128}]),je=o("gem.localServer.denied",[{n:"requestId",k:"s",max:64},{n:"retryable",k:"b"},{n:"reason",k:"e",v:["refused","unavailable"]}]),Me=o("gem.exit",[{n:"reason",k:"s",o:1,max:64}]),De=o("gem.openExternal",[{n:"url",k:"s",max:2048,f:"url"}]),Fe=o("gem.requestFullscreen",[{n:"enabled",k:"b"}]),$e=o("gem.audioState",[{n:"muted",k:"b"}]),He=o("gem.rewardCue",[{n:"currencySlug",k:"s",max:32},{n:"expected",k:"i",o:1,lo:1,hi:1e9},{n:"origin",k:"o",o:1,fs:[{n:"x",k:"i",lo:0,hi:16384},{n:"y",k:"i",lo:0,hi:16384}]}]),Be=o("gem.walletDisplay",[{n:"visible",k:"b"},{n:"currencies",k:"a",o:1,max:8,it:{n:"",k:"s",max:64}},{n:"score",k:"b",o:1}]),Ue=o("gem.menu",[{n:"settings",k:"b"},{n:"items",k:"a",o:1,max:4,it:{n:"",k:"o",fs:[{n:"id",k:"s",max:32},{n:"label",k:"s",max:40}]}}]),We=o("gem.menuSelect",[{n:"entry",k:"e",v:["settings","item"]},{n:"id",k:"s",o:1,max:32}]),Ne=o("gem.requestShare",[{n:"params",k:"a",max:16,it:{n:"",k:"o",fs:[{n:"key",k:"s",max:64},{n:"value",k:"s",max:512}]}}]),Ve=o("gem.vibrate",[{n:"pattern",k:"a",max:99,it:{n:"",k:"i",lo:0,hi:1e4}}]),ze=o("gem.frameStats",[{n:"fps",k:"i",lo:0,hi:1e3},{n:"frameTimeP95Ms",k:"i",lo:0,hi:1e5}]),Ke=o("gem.portraitBorders",[{n:"name",k:"s",o:1,max:40}]),Ye=o("gem.error",[{n:"code",k:"e",v:["version_mismatch","handshake_timeout","handshake_duplicate","invalid_message","rate_limited","token_unavailable","unsupported","unsupported_capability","internal"]},{n:"message",k:"s",o:1,max:256}]),Je=o("gem.requestPurchase",[{n:"requestId",k:"s",max:64},{n:"purchaseKind",k:"e",v:["item","recipe"]},{n:"targetId",k:"s",max:64},{n:"currencySlug",k:"s",max:32},{n:"quantity",k:"i",o:1,lo:1,hi:10},{n:"catalogId",k:"s",o:1,max:64}]),Xe=o("gem.purchaseResult",[{n:"requestId",k:"s",max:64},{n:"outcome",k:"e",v:["ok","declined","unavailable"]},{n:"reason",k:"s",o:1,max:64,f:"code"},{n:"purchaseId",k:"s",o:1,max:64}]),Qe=o("gem.deviceSettings.put",[{n:"requestId",k:"s",max:64},{n:"settings",k:"j"}]),Ze=o("gem.deviceSettings.result",[{n:"requestId",k:"s",max:64},{n:"outcome",k:"e",v:["stored","too_large","unavailable"]}]),et=o("gem.requestAd",[{n:"requestId",k:"s",max:64},{n:"placement",k:"s",max:32},{n:"format",k:"e",v:["interstitial","rewarded"]}]),tt=o("gem.adResult",[{n:"requestId",k:"s",max:64},{n:"outcome",k:"e",v:["shown","no_ad","unavailable"]}]),nt=o("gem.requestSignIn",[{n:"requestId",k:"s",max:64}]),rt=o("gem.signInResult",[{n:"requestId",k:"s",max:64},{n:"outcome",k:"e",v:["signed_in","declined","unavailable"]}]),ot=o("gem.requestFriendChallenge",[{n:"requestId",k:"s",max:64},{n:"playerId",k:"s",max:64},{n:"template",k:"s",max:64},{n:"params",k:"j",o:1}]),at=o("gem.friendChallengeResult",[{n:"requestId",k:"s",max:64},{n:"outcome",k:"e",v:["accepted","cancelled","refused","unavailable","rate_limited","invalid"]},{n:"code",k:"s",o:1,max:64},{n:"param",k:"s",o:1,max:64},{n:"channel",k:"s",o:1,max:16},{n:"configVersion",k:"i",o:1,lo:0,hi:9007199254740991},{n:"retryAfterMs",k:"i",o:1,lo:0,hi:864e5},{n:"detail",k:"s",o:1,max:300}]),b=R({"gem.handshake":ne,"gem.handshake.accept":re,"gem.token":oe,"gem.token.denied":ae,"gem.player":se,"gem.pause":ie,"gem.prefs":le,"gem.cohorts":de,"gem.earnAllowanceChanged":me,"gem.viewport":ue,"gem.deviceSettings":ce,"gem.willTerminate":ge,"gem.roomEvent":pe,"gem.socketState":ye,"gem.seatedEvent":fe,"gem.autoStartFailedEvent":he,"gem.signalEvent":ke,"gem.dedicatedEvent":ve,"gem.partyResult":xe,"gem.clusterTarget":be,"gem.devtools":we,"gem.screenshot":Se,"gem.screenshot.denied":Re,"gem.requestContext":Ge,"gem.gameContext":Oe,"gem.signal":Ce,"gem.dedicatedOffer":Te,"gem.partyRequest":Pe,"gem.ready":Ee,"gem.engaged":Ie,"gem.progress":qe,"gem.requestToken":Le,"gem.requestLocalServer":Ae,"gem.localServer":_e,"gem.localServer.denied":je,"gem.exit":Me,"gem.openExternal":De,"gem.requestFullscreen":Fe,"gem.audioState":$e,"gem.rewardCue":He,"gem.walletDisplay":Be,"gem.menu":Ue,"gem.menuSelect":We,"gem.requestShare":Ne,"gem.vibrate":Ve,"gem.frameStats":ze,"gem.portraitBorders":Ke,"gem.error":Ye,"gem.requestPurchase":Je,"gem.purchaseResult":Xe,"gem.deviceSettings.put":Qe,"gem.deviceSettings.result":Ze,"gem.requestAd":et,"gem.adResult":tt,"gem.requestSignIn":nt,"gem.signInResult":rt,"gem.requestFriendChallenge":ot,"gem.friendChallengeResult":at});var st=/^[a-z0-9][a-z0-9_-]{0,39}$/;function it(n){return typeof n=="string"&&st.test(n)}function F(n){if(n===null||it(n))return n;let e=typeof n=="string"?JSON.stringify(n.length>48?`${n.slice(0,48)}\u2026`:n):`a value of type ${typeof n}`;console.warn(`[gem] showPortraitBorders: ${e} is not a border name, so nothing was sent. A name is 1 to 40 of a-z, 0-9, _ and -, starting with a letter or digit, exactly as your store page declares it under media.portrait_borders. Pass null for no art.`);}var G=class{#e;constructor(e){this.#e=e,Object.freeze(this);}toString(){return "[gem: use gem.text.toPlain()]"}toJSON(){return this.toString()}get[Symbol.toStringTag](){return "PlayerText"}static unwrap(e){return e.#e}};function O(n){return new G(n)}var C={now:()=>Date.now(),setTimeout:(n,e)=>setTimeout(n,e),clearTimeout:n=>clearTimeout(n)},h=class{constructor(e=C){this.clock=e;}clock;tokens=new Map;lastRefill=new Map;allow(e){let t=_[e];if(t===void 0)return false;let r=this.clock.now(),a=this.lastRefill.get(e)??r,i=this.tokens.get(e)??t,d=Math.max(0,r-a),s=Math.min(t,i+d*t/6e4);return s<1?(this.tokens.set(e,s),this.lastRefill.set(e,r),false):(this.tokens.set(e,s-1),this.lastRefill.set(e,r),true)}};function T(n,e){return n.toLowerCase()===e.toLowerCase()}function $(n){let e=n.toLowerCase();return e==="localhost"||e.endsWith(".localhost")||e==="[::1]"||e==="::1"?true:/^127(\.\d{1,3}){3}$/.test(e)}function H(n,e){if(typeof e!="string"||e==="")return false;let t,r;try{t=new URL(n),r=new URL(e);}catch{return false}return t.protocol!=="http:"&&t.protocol!=="https:"||r.protocol!=="http:"&&r.protocol!=="https:"||t.username!==""||t.password!==""||t.pathname!=="/"||t.search!==""||t.hash!==""||t.port===""?false:$(t.hostname)&&$(r.hostname)}function B(n,e){if(n.min>n.max||e.min>e.max)return null;let t=Math.min(n.max,e.max),r=Math.max(n.min,e.min);return t>=r?t:null}function U(n){return Math.min(16384,Math.max(0,Math.round(Number.isFinite(n)?n:0)))}function lt(n,e){if(n!==true)return {visible:false};let t=[],r=false;for(let a of Array.isArray(e)?e:[])a==="score"?r=true:typeof a=="string"&&a.length>0&&a.length<=64&&!t.includes(a)&&t.push(a);return !r&&t.length===0?{visible:true}:{visible:true,currencies:t.slice(0,8),score:r}}function dt(n,e){let t=[];for(let r of Array.isArray(e)?e:[]){if(t.length===4)break;if(typeof r!="object"||r===null)continue;let{id:a,label:i}=r;typeof a!="string"||a.length===0||a.length>32||typeof i!="string"||i.trim().length===0||t.some(d=>d.id===a)||t.push({id:a,label:i.trim().slice(0,40)});}return t.length===0?{settings:n===true}:{settings:n===true,items:t}}function W(n,e){return Math.min(e,Math.max(0,Math.round(Number.isFinite(n)?n:0)))}function mt(n){let e=n.untrusted,t=O(e.displayName),r=e.displayTag||e.displayHandle,a=r?O(r):void 0,i=n.discriminator||n.displayTag,d=i&&/^[0-9]{1,8}$/.test(i)?i:void 0,s=n.avatarIconUrl||n.avatarUrl,m={displayName:t,displayHandle:a??t,badges:(n.badges??[]).map(u=>({itemId:u.itemId,iconUrl:u.iconUrl}))};n.playerId&&(m.playerId=n.playerId),d&&(m.discriminator=d),a&&(m.displayTag=a),s&&(m.avatarIconUrl=m.avatarUrl=s);let c=n.boost,g=(c?.multipliers??[]).map(u=>({currencyId:u.currencyId,currencySlug:u.currencySlug,multiplier:u.multiplierBp/1e4})),p=g.some(u=>u.multiplier>1);return m.boost=p&&c?.expiresInDays?{active:p,multipliers:g,expiresInDays:c.expiresInDays}:{active:p,multipliers:g},m}var ut=1e4,k=class{constructor(e){this.options=e;if(e.expectedSource===void 0||e.expectedSource===null)throw new Error("GemFrame: expectedSource is required and must not be null \u2014 pass window.parent. The handshake transfers the MessagePort, and origin alone does not say WHICH document on that origin sent it.");this.expectedSource=e.expectedSource,this.clock=e.clock??C,this.inbound=new h(this.clock),this.outbound=new h(this.clock);}options;state="waiting";port=null;version=null;peerCapabilities=[];unbidden=false;engagedSent=false;readyPending=false;readySent=false;settleWaiters=[];clock;inbound;outbound;expectedSource;get currentState(){return this.state}get parentCapabilities(){return this.peerCapabilities}parentSupports(e){return this.peerCapabilities.includes(e)}get protocolVersion(){return this.version}get unbiddenLaunch(){return this.unbidden}handleWindowMessage(e){if(e.source!==this.expectedSource)return this.refuse(e,"handshake did not come from the expected embedder window"),false;if(!(this.options.allowedEmbedders.some(s=>T(s,e.origin))||H(e.origin,this.options.selfOrigin)))return this.refuse(e,`embedder '${e.origin}' is not in allowedEmbedders`),this.state==="waiting"&&this.transition("refused"),false;if(this.state==="connected")return this.fail("handshake_duplicate","this document already has a port"),false;if(this.state!=="waiting")return false;let r=b["gem.handshake"]?.(e.data);if(r)return this.refuse(e,`malformed handshake: ${r}`),false;let a=e.data;if(!T(a.embedder,e.origin))return this.refuse(e,`handshake claims embedder '${a.embedder}' but arrived from '${e.origin}'`),false;let i=e.ports?.[0];if(!i)return this.refuse(e,"handshake transferred no MessagePort"),false;let d=B(f,a.versions);return d===null?(i.onmessage=null,i.postMessage({gem:l,type:"gem.error",code:"version_mismatch",message:`frame supports v${f.min}..v${f.max}`}),i.close(),this.transition("refused"),this.options.onError?.("version_mismatch"),false):(this.port=i,this.version=d,i.onmessage=s=>this.receive(s.data,s.ports??[]),i.start?.(),this.peerCapabilities=a.capabilities??[],this.unbidden=a.unbidden===true,i.postMessage({gem:l,type:"gem.handshake.accept",v:d,...this.options.capabilities===void 0?{}:{capabilities:[...this.options.capabilities]}}),this.transition("connected"),this.readyPending&&(this.readyPending=false,this.ready()),true)}ready(){if(this.state!=="connected"||!this.port){this.readyPending=true;return}if(this.readySent){this.options.onDropped?.("internal","gem.ready was already sent; duplicate suppressed");return}this.readySent=true,this.send({gem:l,type:"gem.ready"});}settled(e=ut){return this.state!=="waiting"?Promise.resolve(this.state):new Promise(t=>{let r=i=>{this.clock.clearTimeout(a),t(i);},a=this.clock.setTimeout(()=>{let i=this.settleWaiters.indexOf(r);i>=0&&this.settleWaiters.splice(i,1),t(this.state);},e);this.settleWaiters.push(r);})}progress(e,t){this.send({gem:l,type:"gem.progress",loaded:e,total:t});}requestToken(e,t){this.send({gem:l,type:"gem.requestToken",requestId:e,reason:t});}requestLocalServer(e,t){return this.parentSupports("localHost")?(this.send({gem:l,type:"gem.requestLocalServer",requestId:e,gameRoomId:t}),true):false}exit(e){this.send(e===void 0?{gem:l,type:"gem.exit"}:{gem:l,type:"gem.exit",reason:e});}openExternal(e){this.send({gem:l,type:"gem.openExternal",url:e});}requestFullscreen(e){this.send({gem:l,type:"gem.requestFullscreen",enabled:e});}reportMuted(e){return this.state!=="connected"||!this.parentSupports("audioState")?false:(this.send({gem:l,type:"gem.audioState",muted:e}),true)}reportEngaged(){return this.engagedSent||this.state!=="connected"||!this.parentSupports("engagement")||!this.send({gem:l,type:"gem.engaged"})?false:(this.engagedSent=true,true)}cueReward(e){if(this.state!=="connected"||!this.parentSupports("rewardCue"))return false;let t={gem:l,type:"gem.rewardCue",currencySlug:String(e.currencySlug).slice(0,32)};return e.expected!==void 0&&Number.isFinite(e.expected)&&e.expected>=1&&(t.expected=Math.min(1e9,Math.round(e.expected))),e.origin&&(t.origin={x:U(e.origin.x),y:U(e.origin.y)}),this.send(t),true}showPortraitBorders(e){let t=F(e);return t===void 0||this.state!=="connected"||!this.parentSupports("portraitBorders")?false:this.send(t===null?{gem:l,type:"gem.portraitBorders"}:{gem:l,type:"gem.portraitBorders",name:t})}setWalletVisible(e,t){return this.state!=="connected"||!this.parentSupports("walletDisplay")?false:this.send({gem:l,type:"gem.walletDisplay",...lt(e,t?.only)})}setMenu(e,t){return this.state!=="connected"||!this.parentSupports("gameMenu")?false:this.send({gem:l,type:"gem.menu",...dt(e,t)})}requestShare(e){return this.state!=="connected"||!this.parentSupports("share")?false:this.send({gem:l,type:"gem.requestShare",params:e.map(({key:t,value:r})=>({key:t,value:r}))})}requestVibrate(e){return this.state!=="connected"||!this.parentSupports("vibration")?false:this.send({gem:l,type:"gem.vibrate",pattern:[...e]})}reportFrameStats(e){return this.state!=="connected"||!this.parentSupports("frameStats")?false:(this.send({gem:l,type:"gem.frameStats",fps:W(e.fps,1e3),frameTimeP95Ms:W(e.frameTimeP95Ms,1e5)}),true)}sendGameContext(e){return this.state!=="connected"?false:(this.send({gem:l,type:"gem.gameContext",context:e}),true)}signal(e,t,r){this.send({gem:l,type:"gem.signal",signal:e,matchId:t,data:r});}dedicatedOffer(e,t,r){this.send({gem:l,type:"gem.dedicatedOffer",matchId:e,sdp:t,intent:r});}requestParty(e){return this.send({gem:l,type:"gem.partyRequest",requestId:e})}requestPurchase(e,t,r,a,i,d){return this.send({gem:l,type:"gem.requestPurchase",requestId:e,purchaseKind:t,targetId:r,currencySlug:a,...i===void 0?{}:{quantity:i},...d===void 0?{}:{catalogId:d}})}putDeviceSettings(e,t){return this.send({gem:l,type:"gem.deviceSettings.put",requestId:e,settings:t})}requestAd(e,t,r){return this.send({gem:l,type:"gem.requestAd",requestId:e,placement:t,format:r})}requestSignIn(e){return this.send({gem:l,type:"gem.requestSignIn",requestId:e})}requestFriendChallenge(e,t,r,a){return this.send({gem:l,type:"gem.requestFriendChallenge",requestId:e,playerId:t,template:r,...a===void 0?{}:{params:a}})}close(){this.port&&(this.port.onmessage=null,this.port.close(),this.port=null),this.state!=="refused"&&this.transition("closed");}transition(e){if(this.state!==e){this.state=e;for(let t of this.settleWaiters.splice(0))t(e);this.options.onStateChange?.(e);}}refuseMalformed(e,t){if(!this.inbound.allow(x)){this.options.onDropped?.(e,t);return}this.fail(e,t);}dropUnknownType(e){this.inbound.allow(x)&&this.options.onDropped?.("unsupported",`ignored unknown message type '${e}'`);}refuse(e,t){e.ports?.[0]?.close?.(),this.inbound.allow(x)&&this.options.onRefused?.(t);}fail(e,t){this.options.onError?.(e,t),this.state==="connected"&&this.port&&this.send({gem:l,type:"gem.error",code:e,...t===void 0?{}:{message:t}});}send(e){if(this.state!=="connected"||!this.port)return this.options.onDropped?.("internal",`dropped ${String(e.type)} before connect`),false;let t=e.type;if(!this.outbound.allow(t))return this.options.onError?.("rate_limited",`frame exceeded its own limit for ${t}`),false;let r=b[t]?.(e);return r?(this.options.onError?.("internal",`refusing to send malformed ${t}: ${r}`),false):(this.port.postMessage(this.version===null?e:{...e,v:this.version}),true)}receive(e,t=[]){let r=false;try{r=this.dispatchInbound(e,t);}finally{r||N(t);}}dispatchInbound(e,t){if(this.state!=="connected")return false;let r=typeof e=="object"&&e!==null?e.type:void 0;if(typeof r!="string")return this.refuseMalformed("invalid_message","message has no type"),false;let a=b[r];if(!a)return this.dropUnknownType(r),false;if(!this.inbound.allow(r))return this.fail("rate_limited",`parent exceeded the limit for ${r}`),false;let i=j(r);if(i!==void 0&&!this.options.capabilities?.includes(i))return this.fail("unsupported_capability",`${r} requires the '${i}' capability, which this frame did not advertise`),false;let d=a(e);if(d)return this.fail("invalid_message",`${r}: ${d}`),false;let s=e;if(s.v!==this.version)return this.fail("invalid_message",`${r}: expected v ${String(this.version)}`),false;switch(r){case "gem.token":this.options.onToken?.(s);break;case "gem.pause":this.options.onPause?.(s);break;case "gem.menuSelect":this.options.onMenuSelect?.(s);break;case "gem.prefs":this.options.onPrefs?.(s);break;case "gem.cohorts":this.options.onCohorts?.(s);break;case "gem.earnAllowanceChanged":this.options.onEarnAllowanceChanged?.();break;case "gem.viewport":this.options.onViewport?.(s);break;case "gem.willTerminate":this.options.onWillTerminate?.(s);break;case "gem.devtools":this.options.onDevtools?.(s.action);break;case "gem.requestContext":this.options.onRequestContext?.();break;case "gem.screenshot":{let m=t[0];if(!m){this.options.onError?.("invalid_message","gem.screenshot transferred no MessagePort");break}let c={maxWidth:s.maxWidth,maxHeight:s.maxHeight};if(!this.options.onScreenshot){m.close(),this.screenshotDenied("not_wired",false);break}return N(t.slice(1)),this.options.onScreenshot(c,m,(g,p)=>this.screenshotDenied(g,p)),true}case "gem.token.denied":this.options.onTokenDenied?.(s);break;case "gem.localServer":this.options.onLocalServer?.(s);break;case "gem.localServer.denied":this.options.onLocalServerDenied?.(s);break;case "gem.player":{this.options.onPlayer?.(mt(s));break}case "gem.roomEvent":this.options.onRoomEvent?.(s);break;case "gem.seatedEvent":this.options.onSeatedEvent?.(s);break;case "gem.autoStartFailedEvent":this.options.onAutoStartFailedEvent?.(s);break;case "gem.socketState":this.options.onSocketState?.(s);break;case "gem.signalEvent":this.options.onSignalEvent?.(s);break;case "gem.dedicatedEvent":this.options.onDedicatedEvent?.(s);break;case "gem.clusterTarget":this.options.onClusterTarget?.(s);break;case "gem.partyResult":this.options.onPartyResult?.(s);break;case "gem.purchaseResult":this.options.onPurchaseResult?.(s);break;case "gem.deviceSettings":this.options.onDeviceSettings?.(s);break;case "gem.deviceSettings.result":this.options.onDeviceSettingsResult?.(s);break;case "gem.adResult":this.options.onAdResult?.(s);break;case "gem.signInResult":this.options.onSignInResult?.(s);break;case "gem.friendChallengeResult":this.options.onFriendChallengeResult?.(s);break;case "gem.error":this.options.onError?.(s.code,s.message);break;default:this.fail("unsupported",`no frame handler for '${r}'`);}return false}screenshotDenied(e,t){this.send({gem:l,type:"gem.screenshot.denied",reason:e,retryable:t});}};function N(n){for(let e of n)try{e?.close?.();}catch{}}I();function ct(n){if((n.expectedSource??window.parent)===window)throw new Error("GemWebSdkBridge.connect: this document is not framed (window.parent === window), so there is no embedder to hand it a port. A game runs inside the Gem Arcade iframe; opening it directly will never complete a handshake.");let e=new k({...n,expectedSource:n.expectedSource??window.parent}),t=r=>{let a=e.handleWindowMessage({data:r.data,origin:r.origin,source:r.source,ports:r.ports});return a&&window.removeEventListener("message",t),a};return window.addEventListener("message",t),q(window,t),e}var V={connect:ct,GemFrame:k,PROTOCOL:l,SUPPORTED_VERSIONS:f};window.GemWebSdkBridge=V;var Ct=V;return Ct;})();
|
|
1
|
+
var GemWebSdkBridgeBundle=(function(){'use strict';var S="GemWebSdkHandshake";function K(){return typeof document>"u"?void 0:document.readyState}var T=()=>Date.now();function E(n={}){let e=n.win??window,t=e,r=t[S];if(r!==void 0)return r;let a=n.readyState??K,i=n.now??T,d=[],s=[],m=u=>{let p=u.data;!p||p.type!=="gem.handshake"||(d.length>=4&&(d.shift(),s.shift(),c.dropped+=1),d.push(u),s.push(i()));};e.addEventListener("message",m);let c={events:d,times:s,dropped:0,late:a()==="complete",uninstall(){e.removeEventListener("message",m);}};return t[S]=c,c}function I(n,e,t={}){let r=n[S];if(r===void 0)return null;let a=t.ttlMs??9500,i=t.now??T,d=r.events.splice(0),s=r.times?.splice(0),m=0,c=0,u=false,p=i()-a;for(let y=d.length-1;y>=0;y--){let g=s?.[y];if(g!==void 0&&g<p){c+=1;continue}if(m+=1,e(d[y])===true){u=true;break}}return r.uninstall(),{capture:r,delivered:m,stale:c,accepted:u}}var l="gem-web-bridge",h={min:1,max:1},f=65536,q=8,x=5e3,L=1024;function A(n){return Object.freeze(Object.assign(Object.create(null),n))}var _=A({"gem.handshake":30,"gem.handshake.accept":5,"gem.token":30,"gem.token.denied":30,"gem.player":12,"gem.pause":120,"gem.prefs":60,"gem.cohorts":12,"gem.earnAllowanceChanged":30,"gem.viewport":60,"gem.deviceSettings":12,"gem.willTerminate":10,"gem.roomEvent":120,"gem.socketState":12,"gem.seatedEvent":60,"gem.autoStartFailedEvent":30,"gem.signalEvent":1800,"gem.dedicatedEvent":120,"gem.partyResult":30,"gem.clusterTarget":12,"gem.devtools":30,"gem.screenshot":6,"gem.screenshot.denied":12,"gem.requestContext":12,"gem.gameContext":12,"gem.signal":1200,"gem.dedicatedOffer":60,"gem.partyRequest":12,"gem.ready":5,"gem.engaged":5,"gem.progress":600,"gem.requestToken":12,"gem.requestLocalServer":6,"gem.localServer":30,"gem.localServer.denied":30,"gem.exit":5,"gem.openExternal":6,"gem.requestFullscreen":30,"gem.audioState":120,"gem.rewardCue":60,"gem.walletDisplay":60,"gem.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}),b="__malformed";var J=A({"gem.requestAd":"ads","gem.adResult":"ads","gem.requestSignIn":"signIn","gem.signInResult":"signIn","gem.requestPurchase":"purchases","gem.purchaseResult":"purchases","gem.requestFriendChallenge":"friendChallenges","gem.friendChallengeResult":"friendChallenges","gem.devtools":"devtools","gem.screenshot":"screenshot","gem.screenshot.denied":"screenshot","gem.requestContext":"feedbackContext","gem.gameContext":"feedbackContext","gem.roomEvent":"rooms","gem.signal":"p2p","gem.signalEvent":"p2p","gem.dedicatedOffer":"dedicated","gem.dedicatedEvent":"dedicated","gem.clusterTarget":"clusterTarget","gem.partyRequest":"parties","gem.partyResult":"parties","gem.autoStartFailedEvent":"autoStartFailure","gem.seatedEvent":"partySeating","gem.socketState":"socketState","gem.audioState":"audioState","gem.rewardCue":"rewardCue","gem.frameStats":"frameStats","gem.portraitBorders":"portraitBorders","gem.engaged":"engagement","gem.viewport":"viewport","gem.walletDisplay":"walletDisplay","gem.requestLocalServer":"localHost","gem.localServer":"localHost","gem.localServer.denied":"localHost","gem.cohorts":"cohorts","gem.earnAllowanceChanged":"earnAllowance","gem.deviceSettings":"deviceSettings","gem.deviceSettings.put":"deviceSettings","gem.deviceSettings.result":"deviceSettings","gem.requestShare":"share","gem.requestAvatarPicker":"avatarPicker","gem.vibrate":"vibration","gem.menu":"gameMenu","gem.menuSelect":"gameMenu","gem.controlsDeclare":"controls"}),X=Object.freeze([["gem.asyncOpponents.","asyncOpponents"],["gem.vibration.","vibration"],["gem.viewport.","reservedAreas"]]);function D(n){let e=J[n];if(e!==void 0)return e;for(let[t,r]of X)if(n.startsWith(t))return r}function Q(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 Z(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 ee(n){return /^[a-z]{2,8}(-[a-z0-9]{1,8})*$/i.test(n)}function te(n){return /^[a-z_]+$/.test(n)}function R(n,e,t){if(e>q)return `nesting deeper than ${q}`;if(++t.nodes>x)return `more than ${x} values`;if(t.bytes>f)return `over the ${f} 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>L)return `an array of ${n.length} entries, over the ${L} limit`;t.bytes+=2;for(let s of n){let m=R(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>x)return `more than ${x} values`;if(t.bytes+=s.length*3+4,t.bytes>f)return `over the ${f} byte limit`;let m=R(d[s],e+1,t);if(m)return m}return null}function ne(n){let e={nodes:0,bytes:0,seen:new Set},t=R(n,0,e);return t?`message contains ${t}`:e.bytes>f?`message is over the ${f} byte limit`:null}var re={origin:[Q,"not a well-formed origin"],url:[Z,"not a safe absolute http(s) URL"],bcp47:[ee,"not a well-formed BCP 47 tag"],code:[te,"not a code of lower-case letters and underscores"]};function j(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=M(i,r,a);if(d)return d}return null}function M(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]=re[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`:j(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=M(i,r,a);if(d)return d}return null}default:{let r=e.k;return `${t}: unknown kind ${String(r)}`}}}var F=Object.create(null);function o(n,e){return F[n]=t=>{let r=ne(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}`:j(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:"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"}]}]);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.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",[]);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 w=Object.freeze(F);var oe=["lookSensitivity","gamepadLookSensitivity","invertLookY","touchMovement"];function $(n){let e={};if(typeof n=="object"&&n!==null)for(let t of oe){let r=n[t];(r==="player"||r==="game")&&(e[t]=r);}return e}var ae=/^[a-z0-9][a-z0-9_-]{0,39}$/;function se(n){return typeof n=="string"&&ae.test(n)}function H(n){if(n===null||se(n))return n;let e=typeof n=="string"?JSON.stringify(n.length>48?`${n.slice(0,48)}\u2026`:n):`a value of type ${typeof n}`;console.warn(`[gem] showPortraitBorders: ${e} is not a border name, so nothing was sent. A name is 1 to 40 of a-z, 0-9, _ and -, starting with a letter or digit, exactly as your store page declares it under media.portrait_borders. Pass null for no art.`);}var G=class{#e;constructor(e){this.#e=e,Object.freeze(this);}toString(){return "[gem: use gem.text.toPlain()]"}toJSON(){return this.toString()}get[Symbol.toStringTag](){return "PlayerText"}static unwrap(e){return e.#e}};function O(n){return new G(n)}var C={now:()=>Date.now(),setTimeout:(n,e)=>setTimeout(n,e),clearTimeout:n=>clearTimeout(n)},k=class{constructor(e=C){this.clock=e;}clock;tokens=new Map;lastRefill=new Map;allow(e){let t=_[e];if(t===void 0)return false;let r=this.clock.now(),a=this.lastRefill.get(e)??r,i=this.tokens.get(e)??t,d=Math.max(0,r-a),s=Math.min(t,i+d*t/6e4);return s<1?(this.tokens.set(e,s),this.lastRefill.set(e,r),false):(this.tokens.set(e,s-1),this.lastRefill.set(e,r),true)}};function P(n,e){return n.toLowerCase()===e.toLowerCase()}function U(n){let e=n.toLowerCase();return e==="localhost"||e.endsWith(".localhost")||e==="[::1]"||e==="::1"?true:/^127(\.\d{1,3}){3}$/.test(e)}function B(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:U(t.hostname)&&U(r.hostname)}function W(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 N(n){return Math.min(16384,Math.max(0,Math.round(Number.isFinite(n)?n:0)))}function ie(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 le(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 V(n,e){return Math.min(e,Math.max(0,Math.round(Number.isFinite(n)?n:0)))}function de(n){let e=n.untrusted,t=O(e.displayName),r=e.displayTag||e.displayHandle,a=r?O(r):void 0,i=n.discriminator||n.displayTag,d=i&&/^[0-9]{1,8}$/.test(i)?i:void 0,s=n.avatarIconUrl||n.avatarUrl,m=n.avatarIconId,c={displayName:t,displayHandle:a??t,badges:(n.badges??[]).map(g=>({itemId:g.itemId,iconUrl:g.iconUrl}))};n.playerId&&(c.playerId=n.playerId),d&&(c.discriminator=d),a&&(c.displayTag=a),s&&(c.avatarIconUrl=c.avatarUrl=s),m&&/^[\da-f]{8}(-[\da-f]{4}){3}-[\da-f]{12}$/i.test(m)&&(c.avatarIconId=m);let u=n.boost,p=(u?.multipliers??[]).map(g=>({currencyId:g.currencyId,currencySlug:g.currencySlug,multiplier:g.multiplierBp/1e4})),y=p.some(g=>g.multiplier>1);return c.boost=y&&u?.expiresInDays?{active:y,multipliers:p,expiresInDays:u.expiresInDays}:{active:y,multipliers:p},c}var me=1e4,v=class{constructor(e){this.options=e;if(e.expectedSource===void 0||e.expectedSource===null)throw new Error("GemFrame: expectedSource is required and must not be null \u2014 pass window.parent. The handshake transfers the MessagePort, and origin alone does not say WHICH document on that origin sent it.");this.expectedSource=e.expectedSource,this.clock=e.clock??C,this.inbound=new k(this.clock),this.outbound=new k(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=>P(s,e.origin))||B(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=w["gem.handshake"]?.(e.data);if(r)return this.refuse(e,`malformed handshake: ${r}`),false;let a=e.data;if(!P(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=W(h,a.versions);return d===null?(i.onmessage=null,i.postMessage({gem:l,type:"gem.error",code:"version_mismatch",message:`frame supports v${h.min}..v${h.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=me){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:N(e.origin.x),y:N(e.origin.y)}),this.send(t),true}showPortraitBorders(e){let t=H(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",...ie(e,t?.only)})}declareControls(e){return this.state!=="connected"||!this.parentSupports("controls")?false:this.send({gem:l,type:"gem.controlsDeclare",uses:$(e)})}setMenu(e,t){return this.state!=="connected"||!this.parentSupports("gameMenu")?false:this.send({gem:l,type:"gem.menu",...le(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(){return this.state!=="connected"||!this.parentSupports("avatarPicker")?false:this.send({gem:l,type:"gem.requestAvatarPicker"})}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:V(e.fps,1e3),frameTimeP95Ms:V(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(b)){this.options.onDropped?.(e,t);return}this.fail(e,t);}dropUnknownType(e){this.inbound.allow(b)&&this.options.onDropped?.("unsupported",`ignored unknown message type '${e}'`);}refuse(e,t){e.ports?.[0]?.close?.(),this.inbound.allow(b)&&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=w[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||z(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=w[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=D(r);if(i!==void 0&&!this.options.capabilities?.includes(i))return this.fail("unsupported_capability",`${r} requires the '${i}' capability, which this frame did not advertise`),false;let d=a(e);if(d)return this.fail("invalid_message",`${r}: ${d}`),false;let s=e;if(s.v!==this.version)return this.fail("invalid_message",`${r}: expected v ${String(this.version)}`),false;switch(r){case "gem.token":this.options.onToken?.(s);break;case "gem.pause":this.options.onPause?.(s);break;case "gem.menuSelect":this.options.onMenuSelect?.(s);break;case "gem.prefs":this.options.onPrefs?.(s);break;case "gem.cohorts":this.options.onCohorts?.(s);break;case "gem.earnAllowanceChanged":this.options.onEarnAllowanceChanged?.();break;case "gem.viewport":this.options.onViewport?.(s);break;case "gem.willTerminate":this.options.onWillTerminate?.(s);break;case "gem.devtools":this.options.onDevtools?.(s.action);break;case "gem.requestContext":this.options.onRequestContext?.();break;case "gem.screenshot":{let m=t[0];if(!m){this.options.onError?.("invalid_message","gem.screenshot transferred no MessagePort");break}let c={maxWidth:s.maxWidth,maxHeight:s.maxHeight};if(!this.options.onScreenshot){m.close(),this.screenshotDenied("not_wired",false);break}return z(t.slice(1)),this.options.onScreenshot(c,m,(u,p)=>this.screenshotDenied(u,p)),true}case "gem.token.denied":this.options.onTokenDenied?.(s);break;case "gem.localServer":this.options.onLocalServer?.(s);break;case "gem.localServer.denied":this.options.onLocalServerDenied?.(s);break;case "gem.player":{this.options.onPlayer?.(de(s));break}case "gem.roomEvent":this.options.onRoomEvent?.(s);break;case "gem.seatedEvent":this.options.onSeatedEvent?.(s);break;case "gem.autoStartFailedEvent":this.options.onAutoStartFailedEvent?.(s);break;case "gem.socketState":this.options.onSocketState?.(s);break;case "gem.signalEvent":this.options.onSignalEvent?.(s);break;case "gem.dedicatedEvent":this.options.onDedicatedEvent?.(s);break;case "gem.clusterTarget":this.options.onClusterTarget?.(s);break;case "gem.partyResult":this.options.onPartyResult?.(s);break;case "gem.purchaseResult":this.options.onPurchaseResult?.(s);break;case "gem.deviceSettings":this.options.onDeviceSettings?.(s);break;case "gem.deviceSettings.result":this.options.onDeviceSettingsResult?.(s);break;case "gem.adResult":this.options.onAdResult?.(s);break;case "gem.signInResult":this.options.onSignInResult?.(s);break;case "gem.friendChallengeResult":this.options.onFriendChallengeResult?.(s);break;case "gem.error":this.options.onError?.(s.code,s.message);break;default:this.fail("unsupported",`no frame handler for '${r}'`);}return false}screenshotDenied(e,t){this.send({gem:l,type:"gem.screenshot.denied",reason:e,retryable:t});}};function z(n){for(let e of n)try{e?.close?.();}catch{}}E();function ce(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 v({...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),I(window,t),e}var Y={connect:ce,GemFrame:v,PROTOCOL:l,SUPPORTED_VERSIONS:h};window.GemWebSdkBridge=Y;var At=Y;return At;})();
|