@indiegems/gem-web-sdk 7.9.1 → 8.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 +45 -0
- package/README.md +1 -0
- package/dist/function.d.ts +26 -1
- package/dist/game.d.ts +44 -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.js +2 -2
- package/dist/index.d.ts +21 -3
- package/dist/sdk.d.ts +44 -1
- package/docs/achievements.md +72 -5
- package/docs/api/api-reference-game.md +719 -24
- package/docs/api/api-reference-server.md +1 -1
- package/docs/api/reference.json +671 -15
- package/docs/changelog.md +45 -0
- package/docs/cross-promotion.md +38 -2
- package/docs/friends.md +86 -11
- package/docs/getting-started.md +12 -7
- package/docs/manifest.json +25 -20
- package/docs/saving-player-progress.md +41 -0
- package/docs/server-bundles.md +2 -2
- package/docs/serverless-functions-js.md +3 -2
- package/docs/serverless-functions.md +53 -7
- package/docs/vibration.md +141 -0
- package/docs/what-a-game-must-do.md +136 -3
- package/package.json +1 -1
- package/schema/bridge.v1.json +102 -1
- package/schema/capabilities.public.json +15 -0
package/CHANGELOG.md
CHANGED
|
@@ -16,6 +16,51 @@ Its entries are grouped under up to five headings:
|
|
|
16
16
|
- **Rebuild**: a type changed. Recompile against the new version; code that compiles today keeps compiling unless the entry says otherwise.
|
|
17
17
|
- **New capability**: something a game can now do. Nothing changes unless you use it.
|
|
18
18
|
|
|
19
|
+
## 8.1.0
|
|
20
|
+
|
|
21
|
+
Upgrading from 8.0.0. Impact: required.
|
|
22
|
+
|
|
23
|
+
### Rebuild
|
|
24
|
+
|
|
25
|
+
- The list of messages a frame sends to its parent, the FrameMessage type and the GemCapability type each gained a portrait borders member. Recompiling is enough for most games. If your code handles every FrameMessage or GemCapability member exhaustively, add a case for the new one so it keeps compiling.
|
|
26
|
+
|
|
27
|
+
### New capability
|
|
28
|
+
|
|
29
|
+
- A game can now ask whether a rewarded placement could pay right now, before it draws its reward button, by calling AdsApi.rewardedStatus with the placement. The answer is a RewardedStatus saying whether the placement is declared, whether it is grantable now, how many grants remain today, when it is next eligible, whether the held limit is reached, and when the allowance resets. Times are in epoch milliseconds. The call never rejects. A failed read, a missing play token or a bad placement resolves as not declared and not grantable, and the read gives up after ten seconds. A placement only counts as grantable when the Arcade you run in supports ads. Failures are reported once per kind through your error handler.
|
|
30
|
+
- A game can now choose which border image from its store page the Arcade paints beside it in portrait by calling Gem.showPortraitBorders with the image's name. The name is a plain string of at most 40 characters, and one that fails the store page's naming rule is refused whole with a console warning. The choice is held until the bridge connects, sent at most once a second with the latest choice winning, and not resent if it matches what was last posted. If the Arcade does not advertise the portraitBorders capability, nothing is sent and nothing is raised.
|
|
31
|
+
- If you embed a game in your own frame, GemFrame.showPortraitBorders lets you send the same border choice, or clear it. It sends only while connected and only to a parent that advertised the portraitBorders capability, and it applies the same name rule as the game side.
|
|
32
|
+
- If you host games, you can now pass onPortraitBorders in your host options to receive the border name a game chose. The new GemPortraitBorders message carries it, and validateGemPortraitBorders checks a message you receive. The host re-checks the name on receipt and drops one that no store page could declare before your callback sees it.
|
|
33
|
+
|
|
34
|
+
## 8.0.0
|
|
35
|
+
|
|
36
|
+
*Written from the API facts alone; no summary was generated for this release.*
|
|
37
|
+
|
|
38
|
+
Upgrading from 7.9.1. Impact: required.
|
|
39
|
+
|
|
40
|
+
### Must change
|
|
41
|
+
|
|
42
|
+
- BucketConfig changed its signature.
|
|
43
|
+
- FRAME_TO_PARENT changed its signature.
|
|
44
|
+
- FrameMessage changed its signature.
|
|
45
|
+
- GemCapability changed its signature.
|
|
46
|
+
|
|
47
|
+
### New capability
|
|
48
|
+
|
|
49
|
+
- FriendChallenge was added.
|
|
50
|
+
- FriendChallengesPage was added.
|
|
51
|
+
- FriendsApi.inbox was added.
|
|
52
|
+
- FriendsApi.launchedChallenge was added.
|
|
53
|
+
- FriendsApi.markAnswered was added.
|
|
54
|
+
- FriendsApiDependencies.launchedChallengeId was added.
|
|
55
|
+
- ListFriendChallengesOptions was added.
|
|
56
|
+
- Gem.vibration was added.
|
|
57
|
+
- GemFrame.requestVibrate was added.
|
|
58
|
+
- VibrationApi was added.
|
|
59
|
+
- GemVibrate was added.
|
|
60
|
+
- HostCallbacks.onVibrate was added.
|
|
61
|
+
- HostOptions.onVibrate was added.
|
|
62
|
+
- validateGemVibrate was added.
|
|
63
|
+
|
|
19
64
|
## 7.9.1
|
|
20
65
|
|
|
21
66
|
Upgrading from 7.9.0. Impact: none.
|
package/README.md
CHANGED
|
@@ -27,6 +27,7 @@ Read them here rather than guessing from the type declarations, which carry sign
|
|
|
27
27
|
| a symbol on the server side — `defineServer` and what a match's server is handed | [`docs/api/api-reference-server.md`](docs/api/api-reference-server.md) |
|
|
28
28
|
| saving a player's progress | [`docs/saving-player-progress.md`](docs/saving-player-progress.md) |
|
|
29
29
|
| asking the player to sign in | [`docs/player-sign-in.md`](docs/player-sign-in.md) |
|
|
30
|
+
| vibrating the player's device, the iPhone included | [`docs/vibration.md`](docs/vibration.md) |
|
|
30
31
|
| leaderboards | [`docs/leaderboards.md`](docs/leaderboards.md) |
|
|
31
32
|
| currencies, items, shops and loot | [`docs/inventory-and-catalogs.md`](docs/inventory-and-catalogs.md), [`docs/game-economy-tutorial.md`](docs/game-economy-tutorial.md), [`docs/trading-and-gifting.md`](docs/trading-and-gifting.md) |
|
|
32
33
|
| Gems, Tickets and achievements | [`docs/arcade-economy.md`](docs/arcade-economy.md), [`docs/achievements.md`](docs/achievements.md), [`docs/brand-art.md`](docs/brand-art.md) |
|
package/dist/function.d.ts
CHANGED
|
@@ -158,6 +158,7 @@ type Boundary = {
|
|
|
158
158
|
};
|
|
159
159
|
type BucketConfig = Boundary & {
|
|
160
160
|
"grant_sources"?: OrderSource[];
|
|
161
|
+
"max_balance"?: number | null;
|
|
161
162
|
"name": string;
|
|
162
163
|
"priority": number;
|
|
163
164
|
"reset_amount"?: number | null;
|
|
@@ -721,6 +722,24 @@ interface ListFriendsOptions {
|
|
|
721
722
|
readonly cursor?: string;
|
|
722
723
|
readonly signal?: AbortSignal;
|
|
723
724
|
}
|
|
725
|
+
interface FriendChallenge {
|
|
726
|
+
readonly id: string;
|
|
727
|
+
readonly from: Friend;
|
|
728
|
+
readonly template: string;
|
|
729
|
+
readonly params: Readonly<Record<string, string | number>>;
|
|
730
|
+
readonly createdAt: number;
|
|
731
|
+
readonly openedAt?: number;
|
|
732
|
+
readonly answeredAt?: number;
|
|
733
|
+
}
|
|
734
|
+
interface FriendChallengesPage {
|
|
735
|
+
readonly challenges: readonly FriendChallenge[];
|
|
736
|
+
readonly nextCursor?: string;
|
|
737
|
+
}
|
|
738
|
+
interface ListFriendChallengesOptions {
|
|
739
|
+
readonly limit?: number;
|
|
740
|
+
readonly cursor?: string;
|
|
741
|
+
readonly signal?: AbortSignal;
|
|
742
|
+
}
|
|
724
743
|
interface FriendChallengeRequest {
|
|
725
744
|
readonly playerId: string;
|
|
726
745
|
readonly template: string;
|
|
@@ -744,12 +763,18 @@ declare class FriendChallengeError extends GemApiError {
|
|
|
744
763
|
}
|
|
745
764
|
interface FriendsApiDependencies {
|
|
746
765
|
readonly challenge?: (request: FriendChallengeRequest) => Promise<FriendChallengeOutcome>;
|
|
766
|
+
readonly launchedChallengeId?: string;
|
|
747
767
|
}
|
|
748
768
|
declare class FriendsApi {
|
|
749
769
|
#private;
|
|
750
770
|
constructor(api: GameApi, dependencies?: FriendsApiDependencies);
|
|
751
771
|
list(options?: ListFriendsOptions): Promise<FriendsPage>;
|
|
752
772
|
challenge(request: FriendChallengeRequest): Promise<FriendChallengeOutcome>;
|
|
773
|
+
inbox(options?: ListFriendChallengesOptions): Promise<FriendChallengesPage>;
|
|
774
|
+
launchedChallenge(options?: {
|
|
775
|
+
readonly signal?: AbortSignal;
|
|
776
|
+
}): Promise<FriendChallenge | null>;
|
|
777
|
+
markAnswered(id: string): Promise<void>;
|
|
753
778
|
}
|
|
754
779
|
interface LeaderboardPeriod {
|
|
755
780
|
readonly id: string;
|
|
@@ -991,4 +1016,4 @@ interface PlayerBoost {
|
|
|
991
1016
|
readonly multipliers: readonly PlayerBoostMultiplier[];
|
|
992
1017
|
readonly expiresInDays?: number;
|
|
993
1018
|
}
|
|
994
|
-
export { AnalyticsApi, type AnalyticsApiOptions, type AnalyticsFlushOptions, type AnalyticsFlushResult, type AnalyticsOptions, type AnalyticsRejection, type AnalyticsValue, AuthError, type AuthFailure, type AuthState, type Base64String, type Boundary, type BucketConfig, type BucketResetInterval, type BytesResponse, CONDITIONAL_HEADERS, type CacheParam, type Challenge, type ChallengeWindow, ChallengesApi, type Character, CharactersApi, type ClientOptions, type Clock, type ConditionalRequestHeaders, type ConfiguredPurchasePayment, type ConfiguredPurchaseRequest, type ConfiguredPurchaseResult, type CreateCharacterOptions, CurrenciesApi, type CurrencyBalance, type CurrencyBucket, type CurrencyReadOptions, type CurrencyRow, type DescribeSaveOptions, type DirectPurchaseRequest, type DirectPurchaseResult, type EarnAllowance, type EarnAllowanceEvent, type EarnAllowancePeriod, type EarnAllowanceReadOptions, type EarnAllowanceSignal, type EntityLeaderboard, type EntityLeaderboardEntry, type EntityLeaderboardOptions, EntityReadCache, type EntityRef, type EntityScope, type EntityType, type Friend, FriendChallengeError, type FriendChallengeErrorCode, type FriendChallengeOutcome, type FriendChallengeOutcomeKind, type FriendChallengeRequest, FriendsApi, type FriendsApiDependencies, type FriendsPage, type FunctionContext, type FunctionFailure, type FunctionInvokeOptions, type FunctionResult, type GameApi, type GameOrderSource, GemApiError, GemClient, type GemErrorReason, type GemFunction, GemFunctionError, type GemFunctionIdentity, GemSaveError, type GetLeaderboardOptions, type GetSaveOptions, type GetSettingOptions, type InitiateTransferOptions, InventoryApi, type InventoryItem, type InventoryOperation, type InventorySnapshot, type ItemCategory, type Leaderboard, type LeaderboardEntry, type LeaderboardPeriod, LeaderboardsApi, type ListChallengesOptions, type ListFriendsOptions, type ListSavesOptions, type ListTransfersOptions, type LootRoll, MAX_PERIODS_BACK, MutationsApi, type Order, type OrderOptions, type OrderPageOptions, type OrderResult, type OrderSource, OrdersApi, type Page, type PeriodOptions, PlatformApi, PlatformCurrenciesApi, type PlatformCurrency, type PlatformCurrencyAccess, type PlatformCurrencyPurchasePayment, type PlatformCurrencyPurchaseRequest, type PlatformCurrencyPurchaseResult, type PlatformCurrencyReadOptions, PlatformEarnAllowanceApi, type PlatformEventName, type PlatformPrice, type PlayerBadge, type PlayerBoost, type PlayerBoostMultiplier, type PlayerIdentity, type PlayerProfile, PlayerText, type ProfileCallOptions, type ProfileShowcaseEntry, ProfilesApi, type Progression, type ProgressionAchievement, ProgressionsApi, type PurchaseOptions, type PutBytesOptions, type PutSaveOptions, type PutSettingOptions, type RankedRow, type RecipeAvailability, type RecipeChange, type RecipeLock, type RecipeResult, type RecipeUsage, type RecipeUsageList, type RequestOptions, type SavePage, type SaveRecord, SavesApi, type SavesOptions, type SessionEndReason, type Setting, SettingsApi, ShowcaseApi, type ShowcaseCallOptions, type ShowcaseFriendEntry, type ShowcaseFriends, type ShowcaseValue, type SlotInfo, type SnapshotCurrency, type SnapshotItem, type SnapshotOptions, type SnapshotPageOptions, type TokenGrant, type Transfer, type TransferDirection, TransfersApi, type Transport, TransportRefusal, type TransportRequest, type TransportResponse, type VersionedGetOptions, type VersionedResponse, asPlayerText, createGem, mapIdentity, platformIconUrl, text, toBase64 };
|
|
1019
|
+
export { AnalyticsApi, type AnalyticsApiOptions, type AnalyticsFlushOptions, type AnalyticsFlushResult, type AnalyticsOptions, type AnalyticsRejection, type AnalyticsValue, AuthError, type AuthFailure, type AuthState, type Base64String, type Boundary, type BucketConfig, type BucketResetInterval, type BytesResponse, CONDITIONAL_HEADERS, type CacheParam, type Challenge, type ChallengeWindow, ChallengesApi, type Character, CharactersApi, type ClientOptions, type Clock, type ConditionalRequestHeaders, type ConfiguredPurchasePayment, type ConfiguredPurchaseRequest, type ConfiguredPurchaseResult, type CreateCharacterOptions, CurrenciesApi, type CurrencyBalance, type CurrencyBucket, type CurrencyReadOptions, type CurrencyRow, type DescribeSaveOptions, type DirectPurchaseRequest, type DirectPurchaseResult, type EarnAllowance, type EarnAllowanceEvent, type EarnAllowancePeriod, type EarnAllowanceReadOptions, type EarnAllowanceSignal, type EntityLeaderboard, type EntityLeaderboardEntry, type EntityLeaderboardOptions, EntityReadCache, type EntityRef, type EntityScope, type EntityType, type Friend, type FriendChallenge, FriendChallengeError, type FriendChallengeErrorCode, type FriendChallengeOutcome, type FriendChallengeOutcomeKind, type FriendChallengeRequest, type FriendChallengesPage, FriendsApi, type FriendsApiDependencies, type FriendsPage, type FunctionContext, type FunctionFailure, type FunctionInvokeOptions, type FunctionResult, type GameApi, type GameOrderSource, GemApiError, GemClient, type GemErrorReason, type GemFunction, GemFunctionError, type GemFunctionIdentity, GemSaveError, type GetLeaderboardOptions, type GetSaveOptions, type GetSettingOptions, type InitiateTransferOptions, InventoryApi, type InventoryItem, type InventoryOperation, type InventorySnapshot, type ItemCategory, type Leaderboard, type LeaderboardEntry, type LeaderboardPeriod, LeaderboardsApi, type ListChallengesOptions, type ListFriendChallengesOptions, type ListFriendsOptions, type ListSavesOptions, type ListTransfersOptions, type LootRoll, MAX_PERIODS_BACK, MutationsApi, type Order, type OrderOptions, type OrderPageOptions, type OrderResult, type OrderSource, OrdersApi, type Page, type PeriodOptions, PlatformApi, PlatformCurrenciesApi, type PlatformCurrency, type PlatformCurrencyAccess, type PlatformCurrencyPurchasePayment, type PlatformCurrencyPurchaseRequest, type PlatformCurrencyPurchaseResult, type PlatformCurrencyReadOptions, PlatformEarnAllowanceApi, type PlatformEventName, type PlatformPrice, type PlayerBadge, type PlayerBoost, type PlayerBoostMultiplier, type PlayerIdentity, type PlayerProfile, PlayerText, type ProfileCallOptions, type ProfileShowcaseEntry, ProfilesApi, type Progression, type ProgressionAchievement, ProgressionsApi, type PurchaseOptions, type PutBytesOptions, type PutSaveOptions, type PutSettingOptions, type RankedRow, type RecipeAvailability, type RecipeChange, type RecipeLock, type RecipeResult, type RecipeUsage, type RecipeUsageList, type RequestOptions, type SavePage, type SaveRecord, SavesApi, type SavesOptions, type SessionEndReason, type Setting, SettingsApi, ShowcaseApi, type ShowcaseCallOptions, type ShowcaseFriendEntry, type ShowcaseFriends, type ShowcaseValue, type SlotInfo, type SnapshotCurrency, type SnapshotItem, type SnapshotOptions, type SnapshotPageOptions, type TokenGrant, type Transfer, type TransferDirection, TransfersApi, type Transport, TransportRefusal, type TransportRequest, type TransportResponse, type VersionedGetOptions, type VersionedResponse, asPlayerText, createGem, mapIdentity, platformIconUrl, text, toBase64 };
|
package/dist/game.d.ts
CHANGED
|
@@ -154,6 +154,7 @@ type Boundary = {
|
|
|
154
154
|
type BucketColumn = "bucket_1" | "bucket_2";
|
|
155
155
|
type BucketConfig = Boundary & {
|
|
156
156
|
"grant_sources"?: OrderSource[];
|
|
157
|
+
"max_balance"?: number | null;
|
|
157
158
|
"name": string;
|
|
158
159
|
"priority": number;
|
|
159
160
|
"reset_amount"?: number | null;
|
|
@@ -1058,6 +1059,7 @@ interface GameConfig extends GameConfigSnapshot {
|
|
|
1058
1059
|
async_opponent_types?: GameConfigSnapshot["async_opponent_types"];
|
|
1059
1060
|
analytics_events?: GameConfigSnapshot["analytics_events"];
|
|
1060
1061
|
analytics_funnels?: GameConfigSnapshot["analytics_funnels"];
|
|
1062
|
+
"rewarded_placements"?: SnapshotRewardedPlacement[];
|
|
1061
1063
|
version: GameConfigSnapshot["version"];
|
|
1062
1064
|
hash: GameConfigSnapshot["hash"];
|
|
1063
1065
|
item(idOrSlug: string): SnapshotItem | null;
|
|
@@ -1255,6 +1257,24 @@ interface ListFriendsOptions {
|
|
|
1255
1257
|
readonly cursor?: string;
|
|
1256
1258
|
readonly signal?: AbortSignal;
|
|
1257
1259
|
}
|
|
1260
|
+
interface FriendChallenge {
|
|
1261
|
+
readonly id: string;
|
|
1262
|
+
readonly from: Friend;
|
|
1263
|
+
readonly template: string;
|
|
1264
|
+
readonly params: Readonly<Record<string, string | number>>;
|
|
1265
|
+
readonly createdAt: number;
|
|
1266
|
+
readonly openedAt?: number;
|
|
1267
|
+
readonly answeredAt?: number;
|
|
1268
|
+
}
|
|
1269
|
+
interface FriendChallengesPage {
|
|
1270
|
+
readonly challenges: readonly FriendChallenge[];
|
|
1271
|
+
readonly nextCursor?: string;
|
|
1272
|
+
}
|
|
1273
|
+
interface ListFriendChallengesOptions {
|
|
1274
|
+
readonly limit?: number;
|
|
1275
|
+
readonly cursor?: string;
|
|
1276
|
+
readonly signal?: AbortSignal;
|
|
1277
|
+
}
|
|
1258
1278
|
interface FriendChallengeRequest {
|
|
1259
1279
|
readonly playerId: string;
|
|
1260
1280
|
readonly template: string;
|
|
@@ -1278,12 +1298,18 @@ declare class FriendChallengeError extends GemApiError {
|
|
|
1278
1298
|
}
|
|
1279
1299
|
interface FriendsApiDependencies {
|
|
1280
1300
|
readonly challenge?: (request: FriendChallengeRequest) => Promise<FriendChallengeOutcome>;
|
|
1301
|
+
readonly launchedChallengeId?: string;
|
|
1281
1302
|
}
|
|
1282
1303
|
declare class FriendsApi {
|
|
1283
1304
|
#private;
|
|
1284
1305
|
constructor(api: GameApi, dependencies?: FriendsApiDependencies);
|
|
1285
1306
|
list(options?: ListFriendsOptions): Promise<FriendsPage>;
|
|
1286
1307
|
challenge(request: FriendChallengeRequest): Promise<FriendChallengeOutcome>;
|
|
1308
|
+
inbox(options?: ListFriendChallengesOptions): Promise<FriendChallengesPage>;
|
|
1309
|
+
launchedChallenge(options?: {
|
|
1310
|
+
readonly signal?: AbortSignal;
|
|
1311
|
+
}): Promise<FriendChallenge | null>;
|
|
1312
|
+
markAnswered(id: string): Promise<void>;
|
|
1287
1313
|
}
|
|
1288
1314
|
type PlatformCurrencyAccess = "read" | "spend";
|
|
1289
1315
|
interface PlatformCurrency {
|
|
@@ -2695,6 +2721,7 @@ declare class GemFrame {
|
|
|
2695
2721
|
reportMuted(muted: boolean): boolean;
|
|
2696
2722
|
reportEngaged(): boolean;
|
|
2697
2723
|
cueReward(cue: RewardCue): boolean;
|
|
2724
|
+
showPortraitBorders(name: string | null): boolean;
|
|
2698
2725
|
setWalletVisible(visible: boolean, options?: {
|
|
2699
2726
|
only?: readonly string[];
|
|
2700
2727
|
}): boolean;
|
|
@@ -2706,6 +2733,7 @@ declare class GemFrame {
|
|
|
2706
2733
|
readonly key: string;
|
|
2707
2734
|
readonly value: string;
|
|
2708
2735
|
}>): boolean;
|
|
2736
|
+
requestVibrate(pattern: readonly number[]): boolean;
|
|
2709
2737
|
reportFrameStats(stats: {
|
|
2710
2738
|
fps: number;
|
|
2711
2739
|
frameTimeP95Ms: number;
|
|
@@ -2737,6 +2765,18 @@ interface ShareApi {
|
|
|
2737
2765
|
readonly available: boolean;
|
|
2738
2766
|
request(request?: ShareRequest): void;
|
|
2739
2767
|
}
|
|
2768
|
+
interface VibrationApi {
|
|
2769
|
+
readonly available: boolean;
|
|
2770
|
+
vibrate(pattern: number | readonly number[]): boolean;
|
|
2771
|
+
}
|
|
2772
|
+
interface RewardedStatus {
|
|
2773
|
+
readonly declared: boolean;
|
|
2774
|
+
readonly grantable: boolean;
|
|
2775
|
+
readonly remainingToday?: number;
|
|
2776
|
+
readonly nextEligibleAt?: number;
|
|
2777
|
+
readonly heldLimitReached: boolean;
|
|
2778
|
+
readonly resetsAt?: number;
|
|
2779
|
+
}
|
|
2740
2780
|
type AdFormat = "interstitial" | "rewarded";
|
|
2741
2781
|
interface AdRequest {
|
|
2742
2782
|
placement: string;
|
|
@@ -2748,6 +2788,7 @@ interface AdOutcome {
|
|
|
2748
2788
|
}
|
|
2749
2789
|
interface AdsApi {
|
|
2750
2790
|
requestAd(req: AdRequest): Promise<AdOutcome>;
|
|
2791
|
+
rewardedStatus(placement: string): Promise<RewardedStatus>;
|
|
2751
2792
|
}
|
|
2752
2793
|
type DeviceSettings = Readonly<Record<string, unknown>>;
|
|
2753
2794
|
type DeviceSettingsPutOutcome = "stored" | "too_large" | "unavailable";
|
|
@@ -2864,6 +2905,7 @@ interface Gem {
|
|
|
2864
2905
|
readonly ads: AdsApi;
|
|
2865
2906
|
readonly account: AccountApi;
|
|
2866
2907
|
readonly share: ShareApi;
|
|
2908
|
+
readonly vibration: VibrationApi;
|
|
2867
2909
|
readonly analytics: AnalyticsApi;
|
|
2868
2910
|
readonly leaderboards: LeaderboardsApi;
|
|
2869
2911
|
readonly challenges: ChallengesApi;
|
|
@@ -2878,6 +2920,7 @@ interface Gem {
|
|
|
2878
2920
|
readonly viewport: GemViewport | null;
|
|
2879
2921
|
awaitCohorts(timeoutMs?: number): Promise<GemCohorts | null>;
|
|
2880
2922
|
reportMuted(muted: boolean): void;
|
|
2923
|
+
showPortraitBorders(name: string | null): void;
|
|
2881
2924
|
cueReward(cue: RewardCue): boolean;
|
|
2882
2925
|
setWalletVisible(visible: boolean, options?: WalletVisibleOptions): boolean;
|
|
2883
2926
|
setMenu(menu: GameMenu): boolean;
|
|
@@ -2906,4 +2949,4 @@ interface ExitAnalytics {
|
|
|
2906
2949
|
}
|
|
2907
2950
|
declare function leaveAndExit(rooms: ExitRooms, bridge: ExitBridge | null, reason?: string, analytics?: ExitAnalytics): Promise<void>;
|
|
2908
2951
|
declare function createGem(options?: GemOptions): Gem;
|
|
2909
|
-
export { ARCADE_EMBEDDERS, type AccountApi, type AdFormat, type AdOutcome, type AdOutcomeKind, type AdRequest, type AdsApi, AnalyticsApi, type AnalyticsFlushOptions, type AnalyticsFlushResult, type AnalyticsOptions, type AnalyticsRejection, type AnalyticsValue, AuthError, type AuthFailure, type AuthState, type BootMark, type BootTimeline, type Challenge, type ChallengeWindow, ChallengesApi, type ConfiguredPurchasePayment, type ConfiguredPurchaseRequest, type ConfiguredPurchaseResult, DEVICE_SETTINGS_MAX_BYTES, DedicatedServerError, type DedicatedServerFailure, type DedicatedServerSession, type DevToolsOpener, type DeviceSettings, type DeviceSettingsApi, type DeviceSettingsPutOutcome, type DirectPurchaseRequest, type DirectPurchaseResult, type EarnAllowance, type EarnAllowanceEvent, type EarnAllowancePeriod, type EarnAllowanceReadOptions, type EntityLeaderboard, type EntityLeaderboardEntry, type EntityLeaderboardOptions, type EntityType, type ExitAnalytics, type ExitBridge, type ExitRooms, type FrameState, type Friend, FriendChallengeError, type FriendChallengeErrorCode, type FriendChallengeOutcome, type FriendChallengeOutcomeKind, type FriendChallengeRequest, FriendsApi, type FriendsPage, type FunctionFailure, type FunctionInvokeOptions, type FunctionResult, FunctionsApi, type GameConfig, type GameMenu, type GameMenuItem, type GameServerLink, type Gem, GemApiError, GemClient, type GemCohort, type GemCohorts, GemConfigError, type GemDevTools, GemFrame, GemFunctionError, type GemIdentity, type GemInsets, type GemMatchApi, type GemMatchServerModule, type GemOptions, type GemPlayer, type GemPrefs, type GemReservedArea, GemSaveError, type GemServerBundle, type GemServerFactory, type GemServerHost, type GemServerHostProfile, type GemServerLifecycle, type GemTerminationNotice, GemUnframedError, type GemViewport, type GetLeaderboardOptions, type JoinWelcome, type Leaderboard, type LeaderboardEntry, type LeaderboardPeriod, LeaderboardsApi, type ListChallengesOptions, type ListFriendsOptions, MAX_PERIODS_BACK, type MatchConnectOptions, type MatchConnection, type MatchHosting, type MatchHostingMode, type MatchServeOptions, type MatchTransport, type MessageMeta, type MultiTransportSession, PLATFORM_EVENTS, type PeriodOptions, PlatformApi, PlatformCurrenciesApi, type PlatformCurrency, type PlatformCurrencyAccess, type PlatformCurrencyPurchasePayment, type PlatformCurrencyPurchaseRequest, type PlatformCurrencyPurchaseResult, type PlatformCurrencyReadOptions, PlatformEarnAllowanceApi, type PlatformEventName, type PlayerBadge, type PlayerBoost, type PlayerBoostMultiplier, type PlayerIdentity, type PlayerProfile, PlayerText, type ProfileCallOptions, type ProfileShowcaseEntry, ProfilesApi, type PurchaseApi, type PurchaseOptions, type PurchaseOutcome, PurchaseRefusal, type PurchaseRefusalCode, type PurchaseRequest, type PutBytesOptions, type PutSaveOptions, type RankedRow, type RecipeAvailability, type RecipeLock, type RewardCue, type SavePage, type SaveRecord, type SendOptions$1 as SendOptions, type ServerTokenGrant, type SessionEndReason, type ShareApi, type ShareRequest, ShowcaseApi, type ShowcaseCallOptions, type ShowcaseFriendEntry, type ShowcaseFriends, type ShowcaseValue, type SignInOutcome, type SignInOutcomeKind, type SnapshotCurrency, type SnapshotItem, type TransportAdvert, type TransportKind, TransportRefusal, UNRELIABLE_CHANNEL_LABEL, type WalletVisibleOptions, asPlayerText, createBootTimeline, createGem, leaveAndExit, mapIdentity, markOnResolve, platformIconUrl, presentJoinCredential, readTemplateTransports, readTransportAdvert, reportOnResolve, text, webTransportAvailable };
|
|
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 };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var GemWebSdkBridgeBundle=(function(){'use strict';var w="GemWebSdkHandshake";function B(){return typeof document>"u"?void 0:document.readyState}var E=()=>Date.now();function I(t={}){let e=t.win??window,n=e,r=n[w];if(r!==void 0)return r;let o=t.readyState??B,i=t.now??E,l=[],s=[],m=c=>{let p=c.data;!p||p.type!=="gem.handshake"||(l.length>=4&&(l.shift(),s.shift(),u.dropped+=1),l.push(c),s.push(i()));};e.addEventListener("message",m);let u={events:l,times:s,dropped:0,late:o()==="complete",uninstall(){e.removeEventListener("message",m);}};return n[w]=u,u}function q(t,e,n={}){let r=t[w];if(r===void 0)return null;let o=n.ttlMs??9500,i=n.now??E,l=r.events.splice(0),s=r.times?.splice(0),m=0,u=0,c=false,p=i()-o;for(let g=l.length-1;g>=0;g--){let P=s?.[g];if(P!==void 0&&P<p){u+=1;continue}if(m+=1,e(l[g])===true){c=true;break}}return r.uninstall(),{capture:r,delivered:m,stale:u,accepted:c}}var d="gem-web-bridge",f={min:1,max:1},y=65536,L=8,v=5e3,A=1024;function R(t){return Object.freeze(Object.assign(Object.create(null),t))}var j=R({"gem.handshake":30,"gem.handshake.accept":5,"gem.token":30,"gem.token.denied":30,"gem.player":12,"gem.pause":120,"gem.prefs":60,"gem.cohorts":12,"gem.earnAllowanceChanged":30,"gem.viewport":60,"gem.deviceSettings":12,"gem.willTerminate":10,"gem.roomEvent":120,"gem.socketState":12,"gem.seatedEvent":60,"gem.autoStartFailedEvent":30,"gem.signalEvent":1800,"gem.dedicatedEvent":120,"gem.partyResult":30,"gem.clusterTarget":12,"gem.devtools":30,"gem.screenshot":6,"gem.screenshot.denied":12,"gem.requestContext":12,"gem.gameContext":12,"gem.signal":1200,"gem.dedicatedOffer":60,"gem.partyRequest":12,"gem.ready":5,"gem.engaged":5,"gem.progress":600,"gem.requestToken":12,"gem.requestLocalServer":6,"gem.localServer":30,"gem.localServer.denied":30,"gem.exit":5,"gem.openExternal":6,"gem.requestFullscreen":30,"gem.audioState":120,"gem.rewardCue":60,"gem.walletDisplay":60,"gem.menu":60,"gem.menuSelect":60,"gem.requestShare":6,"gem.frameStats":120,"gem.error":60,"gem.requestPurchase":12,"gem.purchaseResult":30,"gem.deviceSettings.put":30,"gem.deviceSettings.result":30,"gem.requestAd":6,"gem.adResult":12,"gem.requestSignIn":6,"gem.signInResult":12,"gem.requestFriendChallenge":12,"gem.friendChallengeResult":30,__malformed:60}),x="__malformed";var z=R({"gem.requestAd":"ads","gem.adResult":"ads","gem.requestSignIn":"signIn","gem.signInResult":"signIn","gem.requestPurchase":"purchases","gem.purchaseResult":"purchases","gem.requestFriendChallenge":"friendChallenges","gem.friendChallengeResult":"friendChallenges","gem.devtools":"devtools","gem.screenshot":"screenshot","gem.screenshot.denied":"screenshot","gem.requestContext":"feedbackContext","gem.gameContext":"feedbackContext","gem.roomEvent":"rooms","gem.signal":"p2p","gem.signalEvent":"p2p","gem.dedicatedOffer":"dedicated","gem.dedicatedEvent":"dedicated","gem.clusterTarget":"clusterTarget","gem.partyRequest":"parties","gem.partyResult":"parties","gem.autoStartFailedEvent":"autoStartFailure","gem.seatedEvent":"partySeating","gem.socketState":"socketState","gem.audioState":"audioState","gem.rewardCue":"rewardCue","gem.frameStats":"frameStats","gem.engaged":"engagement","gem.viewport":"viewport","gem.walletDisplay":"walletDisplay","gem.requestLocalServer":"localHost","gem.localServer":"localHost","gem.localServer.denied":"localHost","gem.cohorts":"cohorts","gem.earnAllowanceChanged":"earnAllowance","gem.deviceSettings":"deviceSettings","gem.deviceSettings.put":"deviceSettings","gem.deviceSettings.result":"deviceSettings","gem.requestShare":"share","gem.menu":"gameMenu","gem.menuSelect":"gameMenu"}),K=Object.freeze([["gem.asyncOpponents.","asyncOpponents"],["gem.viewport.","reservedAreas"]]);function _(t){let e=z[t];if(e!==void 0)return e;for(let[n,r]of K)if(t.startsWith(n))return r}function Y(t){let e=/^([a-z][a-z0-9+.-]*):\/\/([a-z0-9.-]+|\[[0-9a-f:.]+\])(:([0-9]{1,5}))?$/i.exec(t);return e===null?false:e[4]===void 0||Number(e[4])<=65535}function X(t){let e;try{e=new URL(t);}catch{return false}return e.username!==""||e.password!==""?false:e.protocol==="https:"?true:e.protocol==="http:"&&(e.hostname==="localhost"||e.hostname==="127.0.0.1")}function J(t){return /^[a-z]{2,8}(-[a-z0-9]{1,8})*$/i.test(t)}function Q(t){return /^[a-z_]+$/.test(t)}function S(t,e,n){if(e>L)return `nesting deeper than ${L}`;if(++n.nodes>v)return `more than ${v} values`;if(n.bytes>y)return `over the ${y} byte limit`;if(t==null)return n.bytes+=4,null;let r=typeof t;if(r==="boolean")return n.bytes+=5,null;if(r==="number")return n.bytes+=8,null;if(r==="string")return n.bytes+=t.length*3+2,null;if(r!=="object")return `${r} is not plain data`;let o=t;if(n.seen.has(o))return "a repeated or cyclic object reference";if(n.seen.add(o),Array.isArray(t)){if(t.length>A)return `an array of ${t.length} entries, over the ${A} limit`;n.bytes+=2;for(let s of t){let m=S(s,e+1,n);if(m)return m}return null}let i=Object.getPrototypeOf(t);if(i!==Object.prototype&&i!==null)return "a value that is not a plain object";n.bytes+=2;let l=t;for(let s in l){if(!Object.prototype.hasOwnProperty.call(l,s))continue;if(++n.nodes>v)return `more than ${v} values`;if(n.bytes+=s.length*3+4,n.bytes>y)return `over the ${y} byte limit`;let m=S(l[s],e+1,n);if(m)return m}return null}function Z(t){let e={nodes:0,bytes:0,seen:new Set},n=S(t,0,e);return n?`message contains ${n}`:e.bytes>y?`message is over the ${y} byte limit`:null}var ee={origin:[Y,"not a well-formed origin"],url:[X,"not a safe absolute http(s) URL"],bcp47:[J,"not a well-formed BCP 47 tag"],code:[Q,"not a code of lower-case letters and underscores"]};function M(t,e,n){for(let r of e){let o=n===""?r.n:`${n}.${r.n}`,i=t[r.n];if(i==null){if(r.o)continue;return `${o}: required`}let l=D(i,r,o);if(l)return l}return null}function D(t,e,n){switch(e.k){case "string":{if(typeof t!="string")return `${n}: expected string`;if(t.length>e.max)return `${n}: exceeds ${e.max} characters`;if(e.f){let[r,o]=ee[e.f];if(!r(t))return `${n}: ${o}`}return null}case "int":return typeof t!="number"||!Number.isInteger(t)?`${n}: expected integer`:t<e.lo||t>e.hi?`${n}: out of range ${e.lo}..${e.hi}`:null;case "boolean":return typeof t=="boolean"?null:`${n}: expected boolean`;case "enum":{let r=e.v;return r.includes(t)?null:`${n}: not one of ${r.join("|")}`}case "object":return typeof t!="object"||t===null||Array.isArray(t)?`${n}: expected object`:M(t,e.fs,n);case "json":return typeof t!="object"||t===null||Array.isArray(t)?`${n}: expected a plain object`:null;case "array":{if(!Array.isArray(t))return `${n}: expected array`;if(t.length>e.max)return `${n}: exceeds ${e.max} items`;let r=e.it,o=`${n}[]`;for(let i of t){if(i==null){if(r.o)continue;return `${o}: required`}let l=D(i,r,o);if(l)return l}return null}default:{let r=e.k;return `${n}: unknown kind ${String(r)}`}}}function a(t,e){return n=>{let r=Z(n);if(r)return r;if(typeof n!="object"||n===null||Array.isArray(n))return "message: expected object";let o=n;return o.gem!==d?"gem: wrong protocol marker":o.type!==t?`type: expected ${t}`:M(o,e,"")}}var ne=a("gem.handshake",[{n:"versions",k:"object",fs:[{n:"min",k:"int",lo:1,hi:1e3},{n:"max",k:"int",lo:1,hi:1e3}]},{n:"capabilities",k:"array",o:1,max:64,it:{n:"",k:"string",max:64}},{n:"embedder",k:"string",max:2048,f:"origin"},{n:"unbidden",k:"boolean",o:1}]),te=a("gem.handshake.accept",[{n:"v",k:"int",lo:1,hi:1e3},{n:"capabilities",k:"array",o:1,max:64,it:{n:"",k:"string",max:64}}]),re=a("gem.token",[{n:"token",k:"string",max:4096},{n:"requestId",k:"string",o:1,max:64},{n:"generation",k:"int",lo:0,hi:2147483647},{n:"apiBaseUrl",k:"string",o:1,max:512,f:"url"},{n:"playerId",k:"string",max:64},{n:"gameId",k:"string",max:64},{n:"channel",k:"enum",v:["dev","test","release"]},{n:"gameVersion",k:"string",o:1,max:64},{n:"expiresAt",k:"int",lo:0,hi:4102444800},{n:"chainEndsAt",k:"int",lo:0,hi:4102444800},{n:"allowDevTools",k:"boolean",o:1}]),oe=a("gem.token.denied",[{n:"requestId",k:"string",max:64},{n:"retryable",k:"boolean"},{n:"retryAfterMs",k:"int",o:1,lo:0,hi:36e5},{n:"reason",k:"enum",v:["chain_exhausted","unavailable"]},{n:"correlationId",k:"string",max:64}]),ae=a("gem.player",[{n:"untrusted",k:"object",fs:[{n:"displayName",k:"string",max:64},{n:"displayTag",k:"string",o:1,max:80},{n:"displayHandle",k:"string",max:80}]},{n:"playerId",k:"string",o:1,max:64},{n:"discriminator",k:"string",o:1,max:8},{n:"avatarIconUrl",k:"string",o:1,max:2048,f:"url"},{n:"badges",k:"array",o:1,max:2,it:{n:"",k:"object",fs:[{n:"itemId",k:"string",max:64},{n:"iconUrl",k:"string",max:2048,f:"url"}]}},{n:"displayTag",k:"string",max:8},{n:"avatarUrl",k:"string",o:1,max:2048,f:"url"},{n:"boost",k:"object",o:1,fs:[{n:"multipliers",k:"array",max:8,it:{n:"",k:"object",fs:[{n:"currencyId",k:"string",max:64},{n:"currencySlug",k:"string",max:32},{n:"multiplierBp",k:"int",lo:1e4,hi:1e6}]}},{n:"expiresInDays",k:"int",o:1,lo:1,hi:7}]}]),se=a("gem.pause",[{n:"paused",k:"boolean"}]),ie=a("gem.prefs",[{n:"reducedMotion",k:"boolean"},{n:"muted",k:"boolean"},{n:"showFrameStats",k:"boolean",o:1},{n:"locale",k:"string",max:35,f:"bcp47"}]),le=a("gem.cohorts",[{n:"cohorts",k:"array",max:8,it:{n:"",k:"object",fs:[{n:"experimentId",k:"string",max:36},{n:"variantKey",k:"string",max:32}]}}]),de=a("gem.earnAllowanceChanged",[]),me=a("gem.viewport",[{n:"insets",k:"object",fs:[{n:"top",k:"int",lo:0,hi:4096},{n:"right",k:"int",lo:0,hi:4096},{n:"bottom",k:"int",lo:0,hi:4096},{n:"left",k:"int",lo:0,hi:4096}]},{n:"reserved",k:"array",o:1,max:4,it:{n:"",k:"object",fs:[{n:"x",k:"int",lo:0,hi:16384},{n:"y",k:"int",lo:0,hi:16384},{n:"width",k:"int",lo:0,hi:16384},{n:"height",k:"int",lo:0,hi:16384}]}}]),ge=a("gem.deviceSettings",[{n:"settings",k:"json",o:1}]),ue=a("gem.willTerminate",[{n:"reason",k:"enum",v:["grant_expiring","session_ended","navigating","kill_switch"]},{n:"graceMs",k:"int",lo:0,hi:6e4}]),ce=a("gem.roomEvent",[{n:"event",k:"enum",v:["updated","match_started","match_ready","match_failed","version_stale"]},{n:"roomId",k:"string",max:64},{n:"matchId",k:"string",o:1,max:64},{n:"version",k:"int",o:1,lo:0,hi:2147483647},{n:"reason",k:"string",o:1,max:64},{n:"platform",k:"enum",o:1,v:["universal","mobile"]}]),pe=a("gem.socketState",[{n:"connected",k:"boolean"},{n:"reason",k:"enum",o:1,v:["connecting","dropped","watchdog","terminal"]}]),ye=a("gem.seatedEvent",[{n:"roomId",k:"string",max:64}]),fe=a("gem.autoStartFailedEvent",[{n:"roomId",k:"string",max:64},{n:"code",k:"string",max:64}]),he=a("gem.signalEvent",[{n:"event",k:"enum",v:["hello","offer","answer","ice","peerJoined","peerLeft","migration","matchEnded","error"]},{n:"matchId",k:"string",max:64},{n:"data",k:"json"}]),ke=a("gem.dedicatedEvent",[{n:"event",k:"enum",v:["answer","error","matchEnded"]},{n:"matchId",k:"string",max:64},{n:"sdp",k:"string",o:1,max:10240},{n:"sessionId",k:"string",o:1,max:64},{n:"code",k:"string",o:1,max:64},{n:"message",k:"string",o:1,max:256},{n:"reason",k:"string",o:1,max:64}]),ve=a("gem.partyResult",[{n:"requestId",k:"string",max:64},{n:"partyId",k:"string",o:1,max:64}]),xe=a("gem.clusterTarget",[{n:"clusterTargetId",k:"string",max:64},{n:"clusterTargetIds",k:"array",o:1,max:3,it:{n:"",k:"string",max:64}}]),be=a("gem.devtools",[{n:"action",k:"enum",v:["open","close","toggle"]}]),we=a("gem.screenshot",[{n:"maxWidth",k:"int",lo:1,hi:7680},{n:"maxHeight",k:"int",lo:1,hi:4320}]),Se=a("gem.screenshot.denied",[{n:"reason",k:"enum",v:["not_wired","no_source","unsupported","unreadable","tainted","too_large","busy","declined","failed"]},{n:"retryable",k:"boolean"}]),Re=a("gem.requestContext",[]),Ge=a("gem.gameContext",[{n:"context",k:"json"}]),Oe=a("gem.signal",[{n:"signal",k:"enum",v:["join","offer","answer","ice","migrationAck","hostUnreachable"]},{n:"matchId",k:"string",max:64},{n:"data",k:"json"}]),Ce=a("gem.dedicatedOffer",[{n:"matchId",k:"string",max:64},{n:"sdp",k:"string",max:10240},{n:"intent",k:"enum",v:["initial","ice_restart","full_reconnect"]}]),Te=a("gem.partyRequest",[{n:"requestId",k:"string",max:64}]),Pe=a("gem.ready",[]),Ee=a("gem.engaged",[]),Ie=a("gem.progress",[{n:"loaded",k:"int",lo:0,hi:1099511627776},{n:"total",k:"int",lo:0,hi:1099511627776}]),qe=a("gem.requestToken",[{n:"requestId",k:"string",max:64},{n:"reason",k:"enum",v:["initial","expiring","rejected"]}]),Le=a("gem.requestLocalServer",[{n:"requestId",k:"string",max:64},{n:"gameRoomId",k:"string",max:64}]),Ae=a("gem.localServer",[{n:"requestId",k:"string",max:64},{n:"serverId",k:"string",o:1,max:128}]),je=a("gem.localServer.denied",[{n:"requestId",k:"string",max:64},{n:"retryable",k:"boolean"},{n:"reason",k:"enum",v:["refused","unavailable"]}]),_e=a("gem.exit",[{n:"reason",k:"string",o:1,max:64}]),Me=a("gem.openExternal",[{n:"url",k:"string",max:2048,f:"url"}]),De=a("gem.requestFullscreen",[{n:"enabled",k:"boolean"}]),Fe=a("gem.audioState",[{n:"muted",k:"boolean"}]),$e=a("gem.rewardCue",[{n:"currencySlug",k:"string",max:32},{n:"expected",k:"int",o:1,lo:1,hi:1e9},{n:"origin",k:"object",o:1,fs:[{n:"x",k:"int",lo:0,hi:16384},{n:"y",k:"int",lo:0,hi:16384}]}]),He=a("gem.walletDisplay",[{n:"visible",k:"boolean"},{n:"currencies",k:"array",o:1,max:8,it:{n:"",k:"string",max:64}},{n:"score",k:"boolean",o:1}]),Ue=a("gem.menu",[{n:"settings",k:"boolean"},{n:"items",k:"array",o:1,max:4,it:{n:"",k:"object",fs:[{n:"id",k:"string",max:32},{n:"label",k:"string",max:40}]}}]),We=a("gem.menuSelect",[{n:"entry",k:"enum",v:["settings","item"]},{n:"id",k:"string",o:1,max:32}]),Ne=a("gem.requestShare",[{n:"params",k:"array",max:16,it:{n:"",k:"object",fs:[{n:"key",k:"string",max:64},{n:"value",k:"string",max:512}]}}]),Ve=a("gem.frameStats",[{n:"fps",k:"int",lo:0,hi:1e3},{n:"frameTimeP95Ms",k:"int",lo:0,hi:1e5}]),Be=a("gem.error",[{n:"code",k:"enum",v:["version_mismatch","handshake_timeout","handshake_duplicate","invalid_message","rate_limited","token_unavailable","unsupported","unsupported_capability","internal"]},{n:"message",k:"string",o:1,max:256}]),ze=a("gem.requestPurchase",[{n:"requestId",k:"string",max:64},{n:"purchaseKind",k:"enum",v:["item","recipe"]},{n:"targetId",k:"string",max:64},{n:"currencySlug",k:"string",max:32},{n:"quantity",k:"int",o:1,lo:1,hi:10},{n:"catalogId",k:"string",o:1,max:64}]),Ke=a("gem.purchaseResult",[{n:"requestId",k:"string",max:64},{n:"outcome",k:"enum",v:["ok","declined","unavailable"]},{n:"reason",k:"string",o:1,max:64,f:"code"},{n:"purchaseId",k:"string",o:1,max:64}]),Ye=a("gem.deviceSettings.put",[{n:"requestId",k:"string",max:64},{n:"settings",k:"json"}]),Xe=a("gem.deviceSettings.result",[{n:"requestId",k:"string",max:64},{n:"outcome",k:"enum",v:["stored","too_large","unavailable"]}]),Je=a("gem.requestAd",[{n:"requestId",k:"string",max:64},{n:"placement",k:"string",max:32},{n:"format",k:"enum",v:["interstitial","rewarded"]}]),Qe=a("gem.adResult",[{n:"requestId",k:"string",max:64},{n:"outcome",k:"enum",v:["shown","no_ad","unavailable"]}]),Ze=a("gem.requestSignIn",[{n:"requestId",k:"string",max:64}]),en=a("gem.signInResult",[{n:"requestId",k:"string",max:64},{n:"outcome",k:"enum",v:["signed_in","declined","unavailable"]}]),nn=a("gem.requestFriendChallenge",[{n:"requestId",k:"string",max:64},{n:"playerId",k:"string",max:64},{n:"template",k:"string",max:64},{n:"params",k:"json",o:1}]),tn=a("gem.friendChallengeResult",[{n:"requestId",k:"string",max:64},{n:"outcome",k:"enum",v:["accepted","cancelled","refused","unavailable","rate_limited","invalid"]},{n:"code",k:"string",o:1,max:64},{n:"param",k:"string",o:1,max:64},{n:"channel",k:"string",o:1,max:16},{n:"configVersion",k:"int",o:1,lo:0,hi:9007199254740991},{n:"retryAfterMs",k:"int",o:1,lo:0,hi:864e5},{n:"detail",k:"string",o:1,max:300}]),b=R({"gem.handshake":ne,"gem.handshake.accept":te,"gem.token":re,"gem.token.denied":oe,"gem.player":ae,"gem.pause":se,"gem.prefs":ie,"gem.cohorts":le,"gem.earnAllowanceChanged":de,"gem.viewport":me,"gem.deviceSettings":ge,"gem.willTerminate":ue,"gem.roomEvent":ce,"gem.socketState":pe,"gem.seatedEvent":ye,"gem.autoStartFailedEvent":fe,"gem.signalEvent":he,"gem.dedicatedEvent":ke,"gem.partyResult":ve,"gem.clusterTarget":xe,"gem.devtools":be,"gem.screenshot":we,"gem.screenshot.denied":Se,"gem.requestContext":Re,"gem.gameContext":Ge,"gem.signal":Oe,"gem.dedicatedOffer":Ce,"gem.partyRequest":Te,"gem.ready":Pe,"gem.engaged":Ee,"gem.progress":Ie,"gem.requestToken":qe,"gem.requestLocalServer":Le,"gem.localServer":Ae,"gem.localServer.denied":je,"gem.exit":_e,"gem.openExternal":Me,"gem.requestFullscreen":De,"gem.audioState":Fe,"gem.rewardCue":$e,"gem.walletDisplay":He,"gem.menu":Ue,"gem.menuSelect":We,"gem.requestShare":Ne,"gem.frameStats":Ve,"gem.error":Be,"gem.requestPurchase":ze,"gem.purchaseResult":Ke,"gem.deviceSettings.put":Ye,"gem.deviceSettings.result":Xe,"gem.requestAd":Je,"gem.adResult":Qe,"gem.requestSignIn":Ze,"gem.signInResult":en,"gem.requestFriendChallenge":nn,"gem.friendChallengeResult":tn});var G=class{#e;constructor(e){this.#e=e,Object.freeze(this);}toString(){return "[gem: use gem.text.toPlain()]"}toJSON(){return this.toString()}get[Symbol.toStringTag](){return "PlayerText"}static unwrap(e){return e.#e}};function O(t){return new G(t)}var C={now:()=>Date.now(),setTimeout:(t,e)=>setTimeout(t,e),clearTimeout:t=>clearTimeout(t)},h=class{constructor(e=C){this.clock=e;}clock;tokens=new Map;lastRefill=new Map;allow(e){let n=j[e];if(n===void 0)return false;let r=this.clock.now(),o=this.lastRefill.get(e)??r,i=this.tokens.get(e)??n,l=Math.max(0,r-o),s=Math.min(n,i+l*n/6e4);return s<1?(this.tokens.set(e,s),this.lastRefill.set(e,r),false):(this.tokens.set(e,s-1),this.lastRefill.set(e,r),true)}};function T(t,e){return t.toLowerCase()===e.toLowerCase()}function F(t){let e=t.toLowerCase();return e==="localhost"||e.endsWith(".localhost")||e==="[::1]"||e==="::1"?true:/^127(\.\d{1,3}){3}$/.test(e)}function $(t,e){if(typeof e!="string"||e==="")return false;let n,r;try{n=new URL(t),r=new URL(e);}catch{return false}return n.protocol!=="http:"&&n.protocol!=="https:"||r.protocol!=="http:"&&r.protocol!=="https:"||n.username!==""||n.password!==""||n.pathname!=="/"||n.search!==""||n.hash!==""||n.port===""?false:F(n.hostname)&&F(r.hostname)}function H(t,e){if(t.min>t.max||e.min>e.max)return null;let n=Math.min(t.max,e.max),r=Math.max(t.min,e.min);return n>=r?n:null}function U(t){return Math.min(16384,Math.max(0,Math.round(Number.isFinite(t)?t:0)))}function rn(t,e){if(t!==true)return {visible:false};let n=[],r=false;for(let o of Array.isArray(e)?e:[])o==="score"?r=true:typeof o=="string"&&o.length>0&&o.length<=64&&!n.includes(o)&&n.push(o);return !r&&n.length===0?{visible:true}:{visible:true,currencies:n.slice(0,8),score:r}}function on(t,e){let n=[];for(let r of Array.isArray(e)?e:[]){if(n.length===4)break;if(typeof r!="object"||r===null)continue;let{id:o,label:i}=r;typeof o!="string"||o.length===0||o.length>32||typeof i!="string"||i.trim().length===0||n.some(l=>l.id===o)||n.push({id:o,label:i.trim().slice(0,40)});}return n.length===0?{settings:t===true}:{settings:t===true,items:n}}function W(t,e){return Math.min(e,Math.max(0,Math.round(Number.isFinite(t)?t:0)))}function an(t){let e=t.untrusted,n=O(e.displayName),r=e.displayTag||e.displayHandle,o=r?O(r):void 0,i=t.discriminator||t.displayTag,l=i&&/^[0-9]{1,8}$/.test(i)?i:void 0,s=t.avatarIconUrl||t.avatarUrl,m={displayName:n,displayHandle:o??n,badges:(t.badges??[]).map(g=>({itemId:g.itemId,iconUrl:g.iconUrl}))};t.playerId&&(m.playerId=t.playerId),l&&(m.discriminator=l),o&&(m.displayTag=o),s&&(m.avatarIconUrl=m.avatarUrl=s);let u=t.boost,c=(u?.multipliers??[]).map(g=>({currencyId:g.currencyId,currencySlug:g.currencySlug,multiplier:g.multiplierBp/1e4})),p=c.some(g=>g.multiplier>1);return m.boost=p&&u?.expiresInDays?{active:p,multipliers:c,expiresInDays:u.expiresInDays}:{active:p,multipliers:c},m}var sn=1e4,k=class{constructor(e){this.options=e;if(e.expectedSource===void 0||e.expectedSource===null)throw new Error("GemFrame: expectedSource is required and must not be null \u2014 pass window.parent. The handshake transfers the MessagePort, and origin alone does not say WHICH document on that origin sent it.");this.expectedSource=e.expectedSource,this.clock=e.clock??C,this.inbound=new h(this.clock),this.outbound=new h(this.clock);}options;state="waiting";port=null;version=null;peerCapabilities=[];unbidden=false;engagedSent=false;readyPending=false;readySent=false;settleWaiters=[];clock;inbound;outbound;expectedSource;get currentState(){return this.state}get parentCapabilities(){return this.peerCapabilities}parentSupports(e){return this.peerCapabilities.includes(e)}get protocolVersion(){return this.version}get unbiddenLaunch(){return this.unbidden}handleWindowMessage(e){if(e.source!==this.expectedSource)return this.refuse(e,"handshake did not come from the expected embedder window"),false;if(!(this.options.allowedEmbedders.some(s=>T(s,e.origin))||$(e.origin,this.options.selfOrigin)))return this.refuse(e,`embedder '${e.origin}' is not in allowedEmbedders`),this.state==="waiting"&&this.transition("refused"),false;if(this.state==="connected")return this.fail("handshake_duplicate","this document already has a port"),false;if(this.state!=="waiting")return false;let r=b["gem.handshake"]?.(e.data);if(r)return this.refuse(e,`malformed handshake: ${r}`),false;let o=e.data;if(!T(o.embedder,e.origin))return this.refuse(e,`handshake claims embedder '${o.embedder}' but arrived from '${e.origin}'`),false;let i=e.ports?.[0];if(!i)return this.refuse(e,"handshake transferred no MessagePort"),false;let l=H(f,o.versions);return l===null?(i.onmessage=null,i.postMessage({gem:d,type:"gem.error",code:"version_mismatch",message:`frame supports v${f.min}..v${f.max}`}),i.close(),this.transition("refused"),this.options.onError?.("version_mismatch"),false):(this.port=i,this.version=l,i.onmessage=s=>this.receive(s.data,s.ports??[]),i.start?.(),this.peerCapabilities=o.capabilities??[],this.unbidden=o.unbidden===true,i.postMessage({gem:d,type:"gem.handshake.accept",v:l,...this.options.capabilities===void 0?{}:{capabilities:[...this.options.capabilities]}}),this.transition("connected"),this.readyPending&&(this.readyPending=false,this.ready()),true)}ready(){if(this.state!=="connected"||!this.port){this.readyPending=true;return}if(this.readySent){this.options.onDropped?.("internal","gem.ready was already sent; duplicate suppressed");return}this.readySent=true,this.send({gem:d,type:"gem.ready"});}settled(e=sn){return this.state!=="waiting"?Promise.resolve(this.state):new Promise(n=>{let r=i=>{this.clock.clearTimeout(o),n(i);},o=this.clock.setTimeout(()=>{let i=this.settleWaiters.indexOf(r);i>=0&&this.settleWaiters.splice(i,1),n(this.state);},e);this.settleWaiters.push(r);})}progress(e,n){this.send({gem:d,type:"gem.progress",loaded:e,total:n});}requestToken(e,n){this.send({gem:d,type:"gem.requestToken",requestId:e,reason:n});}requestLocalServer(e,n){return this.parentSupports("localHost")?(this.send({gem:d,type:"gem.requestLocalServer",requestId:e,gameRoomId:n}),true):false}exit(e){this.send(e===void 0?{gem:d,type:"gem.exit"}:{gem:d,type:"gem.exit",reason:e});}openExternal(e){this.send({gem:d,type:"gem.openExternal",url:e});}requestFullscreen(e){this.send({gem:d,type:"gem.requestFullscreen",enabled:e});}reportMuted(e){return this.state!=="connected"||!this.parentSupports("audioState")?false:(this.send({gem:d,type:"gem.audioState",muted:e}),true)}reportEngaged(){return this.engagedSent||this.state!=="connected"||!this.parentSupports("engagement")||!this.send({gem:d,type:"gem.engaged"})?false:(this.engagedSent=true,true)}cueReward(e){if(this.state!=="connected"||!this.parentSupports("rewardCue"))return false;let n={gem:d,type:"gem.rewardCue",currencySlug:String(e.currencySlug).slice(0,32)};return e.expected!==void 0&&Number.isFinite(e.expected)&&e.expected>=1&&(n.expected=Math.min(1e9,Math.round(e.expected))),e.origin&&(n.origin={x:U(e.origin.x),y:U(e.origin.y)}),this.send(n),true}setWalletVisible(e,n){return this.state!=="connected"||!this.parentSupports("walletDisplay")?false:this.send({gem:d,type:"gem.walletDisplay",...rn(e,n?.only)})}setMenu(e,n){return this.state!=="connected"||!this.parentSupports("gameMenu")?false:this.send({gem:d,type:"gem.menu",...on(e,n)})}requestShare(e){return this.state!=="connected"||!this.parentSupports("share")?false:this.send({gem:d,type:"gem.requestShare",params:e.map(({key:n,value:r})=>({key:n,value:r}))})}reportFrameStats(e){return this.state!=="connected"||!this.parentSupports("frameStats")?false:(this.send({gem:d,type:"gem.frameStats",fps:W(e.fps,1e3),frameTimeP95Ms:W(e.frameTimeP95Ms,1e5)}),true)}sendGameContext(e){return this.state!=="connected"?false:(this.send({gem:d,type:"gem.gameContext",context:e}),true)}signal(e,n,r){this.send({gem:d,type:"gem.signal",signal:e,matchId:n,data:r});}dedicatedOffer(e,n,r){this.send({gem:d,type:"gem.dedicatedOffer",matchId:e,sdp:n,intent:r});}requestParty(e){return this.send({gem:d,type:"gem.partyRequest",requestId:e})}requestPurchase(e,n,r,o,i,l){return this.send({gem:d,type:"gem.requestPurchase",requestId:e,purchaseKind:n,targetId:r,currencySlug:o,...i===void 0?{}:{quantity:i},...l===void 0?{}:{catalogId:l}})}putDeviceSettings(e,n){return this.send({gem:d,type:"gem.deviceSettings.put",requestId:e,settings:n})}requestAd(e,n,r){return this.send({gem:d,type:"gem.requestAd",requestId:e,placement:n,format:r})}requestSignIn(e){return this.send({gem:d,type:"gem.requestSignIn",requestId:e})}requestFriendChallenge(e,n,r,o){return this.send({gem:d,type:"gem.requestFriendChallenge",requestId:e,playerId:n,template:r,...o===void 0?{}:{params:o}})}close(){this.port&&(this.port.onmessage=null,this.port.close(),this.port=null),this.state!=="refused"&&this.transition("closed");}transition(e){if(this.state!==e){this.state=e;for(let n of this.settleWaiters.splice(0))n(e);this.options.onStateChange?.(e);}}refuseMalformed(e,n){if(!this.inbound.allow(x)){this.options.onDropped?.(e,n);return}this.fail(e,n);}dropUnknownType(e){this.inbound.allow(x)&&this.options.onDropped?.("unsupported",`ignored unknown message type '${e}'`);}refuse(e,n){e.ports?.[0]?.close?.(),this.inbound.allow(x)&&this.options.onRefused?.(n);}fail(e,n){this.options.onError?.(e,n),this.state==="connected"&&this.port&&this.send({gem:d,type:"gem.error",code:e,...n===void 0?{}:{message:n}});}send(e){if(this.state!=="connected"||!this.port)return this.options.onDropped?.("internal",`dropped ${String(e.type)} before connect`),false;let n=e.type;if(!this.outbound.allow(n))return this.options.onError?.("rate_limited",`frame exceeded its own limit for ${n}`),false;let r=b[n]?.(e);return r?(this.options.onError?.("internal",`refusing to send malformed ${n}: ${r}`),false):(this.port.postMessage(this.version===null?e:{...e,v:this.version}),true)}receive(e,n=[]){let r=false;try{r=this.dispatchInbound(e,n);}finally{r||N(n);}}dispatchInbound(e,n){if(this.state!=="connected")return false;let r=typeof e=="object"&&e!==null?e.type:void 0;if(typeof r!="string")return this.refuseMalformed("invalid_message","message has no type"),false;let o=b[r];if(!o)return this.dropUnknownType(r),false;if(!this.inbound.allow(r))return this.fail("rate_limited",`parent exceeded the limit for ${r}`),false;let i=_(r);if(i!==void 0&&!this.options.capabilities?.includes(i))return this.fail("unsupported_capability",`${r} requires the '${i}' capability, which this frame did not advertise`),false;let l=o(e);if(l)return this.fail("invalid_message",`${r}: ${l}`),false;let s=e;if(s.v!==this.version)return this.fail("invalid_message",`${r}: expected v ${String(this.version)}`),false;switch(r){case "gem.token":this.options.onToken?.(s);break;case "gem.pause":this.options.onPause?.(s);break;case "gem.menuSelect":this.options.onMenuSelect?.(s);break;case "gem.prefs":this.options.onPrefs?.(s);break;case "gem.cohorts":this.options.onCohorts?.(s);break;case "gem.earnAllowanceChanged":this.options.onEarnAllowanceChanged?.();break;case "gem.viewport":this.options.onViewport?.(s);break;case "gem.willTerminate":this.options.onWillTerminate?.(s);break;case "gem.devtools":this.options.onDevtools?.(s.action);break;case "gem.requestContext":this.options.onRequestContext?.();break;case "gem.screenshot":{let m=n[0];if(!m){this.options.onError?.("invalid_message","gem.screenshot transferred no MessagePort");break}let u={maxWidth:s.maxWidth,maxHeight:s.maxHeight};if(!this.options.onScreenshot){m.close(),this.screenshotDenied("not_wired",false);break}return N(n.slice(1)),this.options.onScreenshot(u,m,(c,p)=>this.screenshotDenied(c,p)),true}case "gem.token.denied":this.options.onTokenDenied?.(s);break;case "gem.localServer":this.options.onLocalServer?.(s);break;case "gem.localServer.denied":this.options.onLocalServerDenied?.(s);break;case "gem.player":{this.options.onPlayer?.(an(s));break}case "gem.roomEvent":this.options.onRoomEvent?.(s);break;case "gem.seatedEvent":this.options.onSeatedEvent?.(s);break;case "gem.autoStartFailedEvent":this.options.onAutoStartFailedEvent?.(s);break;case "gem.socketState":this.options.onSocketState?.(s);break;case "gem.signalEvent":this.options.onSignalEvent?.(s);break;case "gem.dedicatedEvent":this.options.onDedicatedEvent?.(s);break;case "gem.clusterTarget":this.options.onClusterTarget?.(s);break;case "gem.partyResult":this.options.onPartyResult?.(s);break;case "gem.purchaseResult":this.options.onPurchaseResult?.(s);break;case "gem.deviceSettings":this.options.onDeviceSettings?.(s);break;case "gem.deviceSettings.result":this.options.onDeviceSettingsResult?.(s);break;case "gem.adResult":this.options.onAdResult?.(s);break;case "gem.signInResult":this.options.onSignInResult?.(s);break;case "gem.friendChallengeResult":this.options.onFriendChallengeResult?.(s);break;case "gem.error":this.options.onError?.(s.code,s.message);break;default:this.fail("unsupported",`no frame handler for '${r}'`);}return false}screenshotDenied(e,n){this.send({gem:d,type:"gem.screenshot.denied",reason:e,retryable:n});}};function N(t){for(let e of t)try{e?.close?.();}catch{}}I();function ln(t){if((t.expectedSource??window.parent)===window)throw new Error("GemWebSdkBridge.connect: this document is not framed (window.parent === window), so there is no embedder to hand it a port. A game runs inside the Gem Arcade iframe; opening it directly will never complete a handshake.");let e=new k({...t,expectedSource:t.expectedSource??window.parent}),n=r=>{let o=e.handleWindowMessage({data:r.data,origin:r.origin,source:r.source,ports:r.ports});return o&&window.removeEventListener("message",n),o};return window.addEventListener("message",n),q(window,n),e}var V={connect:ln,GemFrame:k,PROTOCOL:d,SUPPORTED_VERSIONS:f};window.GemWebSdkBridge=V;var bn=V;return bn;})();
|
|
1
|
+
var GemWebSdkBridgeBundle=(function(){'use strict';var w="GemWebSdkHandshake";function 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;})();
|