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