@indiegems/gem-web-sdk 22.0.0 → 23.0.1
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 +53 -0
- package/dist/conformance.d.ts +4 -1
- package/dist/function.d.ts +9 -1
- package/dist/game.d.ts +40 -2
- package/dist/gem-web-sdk.bridge.js +2 -2
- package/dist/gem-web-sdk.conformance.js +3 -3
- package/dist/gem-web-sdk.esm.js +3 -3
- package/dist/gem-web-sdk.function.js +3 -3
- package/dist/gem-web-sdk.game.js +3 -3
- package/dist/gem-web-sdk.min.js +3 -3
- package/dist/gem-web-sdk.sdk.js +3 -3
- package/dist/gem-web-sdk.server.js +2 -2
- package/dist/index.d.ts +54 -6
- package/dist/sdk.d.ts +40 -2
- package/docs/api/api-reference-function.md +129 -9
- package/docs/api/api-reference-game.md +141 -13
- package/docs/api/api-reference-server.md +7 -1
- package/docs/api/reference.json +165 -9
- package/docs/changelog.md +53 -0
- package/docs/friends.md +120 -15
- package/docs/getting-started.md +11 -4
- package/docs/inventory-and-catalogs.md +29 -11
- package/docs/manifest.json +16 -16
- package/docs/rooms-and-matches.md +6 -3
- package/docs/server-bundles.md +2 -2
- package/docs/serverless-functions.md +21 -0
- package/docs/trading-and-gifting.md +12 -9
- package/package.json +1 -1
- package/schema/bridge.v1.json +225 -0
- package/schema/capabilities.public.json +14 -0
package/CHANGELOG.md
CHANGED
|
@@ -16,6 +16,59 @@ 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
|
+
## 23.0.1
|
|
20
|
+
|
|
21
|
+
Upgrading from 23.0.0. Impact: none.
|
|
22
|
+
|
|
23
|
+
Nothing in this release asks anything of a game.
|
|
24
|
+
|
|
25
|
+
## 23.0.0
|
|
26
|
+
|
|
27
|
+
*Written from the API facts alone; no summary was generated for this release.*
|
|
28
|
+
|
|
29
|
+
Upgrading from 22.0.0. Impact: required.
|
|
30
|
+
|
|
31
|
+
### Must change
|
|
32
|
+
|
|
33
|
+
- PARENT_CONFORMANCE_VERSION changed its signature.
|
|
34
|
+
- GemFrame.requestArcade changed its signature.
|
|
35
|
+
- FRAME_TO_PARENT changed its signature.
|
|
36
|
+
- FrameMessage changed its signature.
|
|
37
|
+
- GemCapability changed its signature.
|
|
38
|
+
- PARENT_TO_FRAME changed its signature.
|
|
39
|
+
- ParentMessage changed its signature.
|
|
40
|
+
|
|
41
|
+
### New capability
|
|
42
|
+
|
|
43
|
+
- ParentFixture.channel was added.
|
|
44
|
+
- ParentFixture.gameId was added.
|
|
45
|
+
- ParentUnderTest.deliverSocket was added.
|
|
46
|
+
- CharactersApi.refreshHeld was added.
|
|
47
|
+
- FriendsApi.inviteToPlay was added.
|
|
48
|
+
- FriendsApi.setInviteParams was added.
|
|
49
|
+
- FriendsApiDependencies.inviteToPlay was added.
|
|
50
|
+
- FriendsApiDependencies.setInviteParams was added.
|
|
51
|
+
- PlayInviteRequest was added.
|
|
52
|
+
- FrameCallbacks.onInventoryChanged was added.
|
|
53
|
+
- FrameCallbacks.onPlayInviteResult was added.
|
|
54
|
+
- FrameOptions.onInventoryChanged was added.
|
|
55
|
+
- FrameOptions.onPlayInviteResult was added.
|
|
56
|
+
- GemHost.answerPlayInvite was added.
|
|
57
|
+
- GemHost.relayInventoryEvent was added.
|
|
58
|
+
- GemHost.sendInventoryChanged was added.
|
|
59
|
+
- GemInventoryChanged was added.
|
|
60
|
+
- GemInviteParams was added.
|
|
61
|
+
- GemPlayInviteResult was added.
|
|
62
|
+
- GemRequestPlayInvite was added.
|
|
63
|
+
- HostCallbacks.onInviteParams was added.
|
|
64
|
+
- HostCallbacks.onRequestPlayInvite was added.
|
|
65
|
+
- HostOptions.onInviteParams was added.
|
|
66
|
+
- HostOptions.onRequestPlayInvite was added.
|
|
67
|
+
- validateGemInventoryChanged was added.
|
|
68
|
+
- validateGemInviteParams was added.
|
|
69
|
+
- validateGemPlayInviteResult was added.
|
|
70
|
+
- validateGemRequestPlayInvite was added.
|
|
71
|
+
|
|
19
72
|
## 22.0.0
|
|
20
73
|
|
|
21
74
|
Upgrading from 21.1.1. Impact: required.
|
package/dist/conformance.d.ts
CHANGED
|
@@ -20,6 +20,8 @@ interface ParentFixture {
|
|
|
20
20
|
readonly isActive: boolean;
|
|
21
21
|
} | undefined;
|
|
22
22
|
readonly reportError: (code: string, message?: string) => void;
|
|
23
|
+
readonly gameId: string;
|
|
24
|
+
readonly channel: "dev" | "test" | "release";
|
|
23
25
|
}
|
|
24
26
|
interface ParentUnderTest {
|
|
25
27
|
start(): void;
|
|
@@ -28,6 +30,7 @@ interface ParentUnderTest {
|
|
|
28
30
|
readonly protocolVersion: number | null;
|
|
29
31
|
readonly surfacesShown?: number;
|
|
30
32
|
dismiss?(): void;
|
|
33
|
+
deliverSocket?(raw: unknown): void;
|
|
31
34
|
}
|
|
32
35
|
type ParentFactory = (fixture: ParentFixture) => ParentUnderTest;
|
|
33
36
|
interface ParentConformanceOptions {
|
|
@@ -50,7 +53,7 @@ interface ParentConformanceResult {
|
|
|
50
53
|
readonly ok: boolean;
|
|
51
54
|
readonly message?: string;
|
|
52
55
|
}
|
|
53
|
-
declare const PARENT_CONFORMANCE_VERSION =
|
|
56
|
+
declare const PARENT_CONFORMANCE_VERSION = 7;
|
|
54
57
|
declare const PARENT_CONFORMANCE_CASES: readonly ParentConformanceCase[];
|
|
55
58
|
declare function runParentConformance(factory: ParentFactory, options: ParentConformanceOptions): Promise<readonly ParentConformanceResult[]>;
|
|
56
59
|
export { PARENT_CONFORMANCE_CASES, PARENT_CONFORMANCE_VERSION, type ParentConformanceCase, ParentConformanceError, type ParentConformanceOptions, type ParentConformanceResult, type ParentFactory, type ParentFixture, type ParentState, type ParentUnderTest, runParentConformance };
|
package/dist/function.d.ts
CHANGED
|
@@ -681,6 +681,7 @@ declare class CharactersApi {
|
|
|
681
681
|
private readonly scopes;
|
|
682
682
|
constructor(api: GameApi, saves?: SavesOptions | undefined, identity?: (() => string | null) | undefined, resolveCurrencyId?: ((slugOrId: string) => Promise<string | undefined>) | undefined);
|
|
683
683
|
private readonly scope;
|
|
684
|
+
refreshHeld(): void;
|
|
684
685
|
list(signal?: AbortSignal): Promise<readonly Character[]>;
|
|
685
686
|
get(id: string, signal?: AbortSignal): Promise<Character>;
|
|
686
687
|
create(options: CreateCharacterOptions): Promise<Character>;
|
|
@@ -826,8 +827,13 @@ declare class FriendChallengeError extends GemApiError {
|
|
|
826
827
|
readonly configVersion?: number;
|
|
827
828
|
});
|
|
828
829
|
}
|
|
830
|
+
interface PlayInviteRequest {
|
|
831
|
+
readonly params?: Readonly<Record<string, string>>;
|
|
832
|
+
}
|
|
829
833
|
interface FriendsApiDependencies {
|
|
830
834
|
readonly challenge?: (request: FriendChallengeRequest) => Promise<FriendChallengeOutcome>;
|
|
835
|
+
readonly inviteToPlay?: (request?: PlayInviteRequest) => Promise<boolean>;
|
|
836
|
+
readonly setInviteParams?: (params: Readonly<Record<string, string>> | null) => boolean;
|
|
831
837
|
readonly launchedChallengeId?: string;
|
|
832
838
|
}
|
|
833
839
|
declare class FriendsApi {
|
|
@@ -835,6 +841,8 @@ declare class FriendsApi {
|
|
|
835
841
|
constructor(api: GameApi, dependencies?: FriendsApiDependencies);
|
|
836
842
|
list(options?: ListFriendsOptions): Promise<FriendsPage>;
|
|
837
843
|
challenge(request: FriendChallengeRequest): Promise<FriendChallengeOutcome>;
|
|
844
|
+
inviteToPlay(request?: PlayInviteRequest): Promise<boolean>;
|
|
845
|
+
setInviteParams(params: Readonly<Record<string, string>> | null): boolean;
|
|
838
846
|
inbox(options?: ListFriendChallengesOptions): Promise<FriendChallengesPage>;
|
|
839
847
|
launchedChallenge(options?: {
|
|
840
848
|
readonly signal?: AbortSignal;
|
|
@@ -1082,4 +1090,4 @@ interface PlayerBoost {
|
|
|
1082
1090
|
readonly multipliers: readonly PlayerBoostMultiplier[];
|
|
1083
1091
|
readonly expiresInDays?: number;
|
|
1084
1092
|
}
|
|
1085
|
-
export { AnalyticsApi, type AnalyticsApiOptions, type AnalyticsFlushOptions, type AnalyticsFlushResult, type AnalyticsOptions, type AnalyticsRejection, type AnalyticsValue, AuthError, type AuthFailure, type AuthState, type Avatar3dFamily, type Base64String, type Boundary, type BucketConfig, type BucketResetInterval, type BytesResponse, CONDITIONAL_HEADERS, type CacheParam, type Challenge, type ChallengeWindow, ChallengesApi, type Character, CharactersApi, type ClientOptions, type Clock, type ConditionalRequestHeaders, type ConfiguredPurchasePayment, type ConfiguredPurchaseRequest, type ConfiguredPurchaseResult, type CreateCharacterOptions, CurrenciesApi, type CurrencyBalance, type CurrencyBucket, type CurrencyReadOptions, type CurrencyRow, type DescribeSaveOptions, type DirectPurchaseRequest, type DirectPurchaseResult, type EarnAllowance, type EarnAllowanceEvent, type EarnAllowancePeriod, type EarnAllowanceReadOptions, type EarnAllowanceSignal, type EntityLeaderboard, type EntityLeaderboardEntry, type EntityLeaderboardOptions, EntityReadCache, type EntityRef, type EntityScope, type EntityType, type Friend, type FriendChallenge, FriendChallengeError, type FriendChallengeErrorCode, type FriendChallengeOutcome, type FriendChallengeOutcomeKind, type FriendChallengeRequest, type FriendChallengesPage, FriendsApi, type FriendsApiDependencies, type FriendsPage, type FunctionContext, type FunctionFailure, type FunctionInvokeOptions, type FunctionResult, type GameApi, type GameOrderSource, type GamePass, 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 PassesApi, type PassesEvent, 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, type PlayerScope, 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 RefusedPurchase, type RequestOptions, type SavePage, type SaveRecord, SavesApi, type SavesOptions, type SessionEndReason, type Setting, SettingsApi, ShowcaseApi, type ShowcaseCallOptions, type ShowcaseFriendEntry, type ShowcaseFriends, type ShowcaseValue, type SlotInfo, type SnapshotCurrency, type SnapshotItem, type SnapshotOptions, type SnapshotPageOptions, type TokenGrant, type Transfer, type TransferDirection, TransfersApi, type Transport, TransportRefusal, type TransportRequest, type TransportResponse, type VersionedGetOptions, type VersionedResponse, type WornAvatar3d, asPlayerText, createGem, mapIdentity, platformIconUrl, text, toBase64 };
|
|
1093
|
+
export { AnalyticsApi, type AnalyticsApiOptions, type AnalyticsFlushOptions, type AnalyticsFlushResult, type AnalyticsOptions, type AnalyticsRejection, type AnalyticsValue, AuthError, type AuthFailure, type AuthState, type Avatar3dFamily, type Base64String, type Boundary, type BucketConfig, type BucketResetInterval, type BytesResponse, CONDITIONAL_HEADERS, type CacheParam, type Challenge, type ChallengeWindow, ChallengesApi, type Character, CharactersApi, type ClientOptions, type Clock, type ConditionalRequestHeaders, type ConfiguredPurchasePayment, type ConfiguredPurchaseRequest, type ConfiguredPurchaseResult, type CreateCharacterOptions, CurrenciesApi, type CurrencyBalance, type CurrencyBucket, type CurrencyReadOptions, type CurrencyRow, type DescribeSaveOptions, type DirectPurchaseRequest, type DirectPurchaseResult, type EarnAllowance, type EarnAllowanceEvent, type EarnAllowancePeriod, type EarnAllowanceReadOptions, type EarnAllowanceSignal, type EntityLeaderboard, type EntityLeaderboardEntry, type EntityLeaderboardOptions, EntityReadCache, type EntityRef, type EntityScope, type EntityType, type Friend, type FriendChallenge, FriendChallengeError, type FriendChallengeErrorCode, type FriendChallengeOutcome, type FriendChallengeOutcomeKind, type FriendChallengeRequest, type FriendChallengesPage, FriendsApi, type FriendsApiDependencies, type FriendsPage, type FunctionContext, type FunctionFailure, type FunctionInvokeOptions, type FunctionResult, type GameApi, type GameOrderSource, type GamePass, 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 PassesApi, type PassesEvent, type PeriodOptions, PlatformApi, PlatformCurrenciesApi, type PlatformCurrency, type PlatformCurrencyAccess, type PlatformCurrencyPurchasePayment, type PlatformCurrencyPurchaseRequest, type PlatformCurrencyPurchaseResult, type PlatformCurrencyReadOptions, PlatformEarnAllowanceApi, type PlatformEventName, type PlatformPrice, type PlayInviteRequest, type PlayerBadge, type PlayerBoost, type PlayerBoostMultiplier, type PlayerIdentity, type PlayerProfile, type PlayerScope, 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 RefusedPurchase, type RequestOptions, type SavePage, type SaveRecord, SavesApi, type SavesOptions, type SessionEndReason, type Setting, SettingsApi, ShowcaseApi, type ShowcaseCallOptions, type ShowcaseFriendEntry, type ShowcaseFriends, type ShowcaseValue, type SlotInfo, type SnapshotCurrency, type SnapshotItem, type SnapshotOptions, type SnapshotPageOptions, type TokenGrant, type Transfer, type TransferDirection, TransfersApi, type Transport, TransportRefusal, type TransportRequest, type TransportResponse, type VersionedGetOptions, type VersionedResponse, type WornAvatar3d, asPlayerText, createGem, mapIdentity, platformIconUrl, text, toBase64 };
|
package/dist/game.d.ts
CHANGED
|
@@ -1076,6 +1076,7 @@ declare class CharactersApi {
|
|
|
1076
1076
|
private readonly scopes;
|
|
1077
1077
|
constructor(api: GameApi, saves?: SavesOptions | undefined, identity?: (() => string | null) | undefined, resolveCurrencyId?: ((slugOrId: string) => Promise<string | undefined>) | undefined);
|
|
1078
1078
|
private readonly scope;
|
|
1079
|
+
refreshHeld(): void;
|
|
1079
1080
|
list(signal?: AbortSignal): Promise<readonly Character[]>;
|
|
1080
1081
|
get(id: string, signal?: AbortSignal): Promise<Character>;
|
|
1081
1082
|
create(options: CreateCharacterOptions): Promise<Character>;
|
|
@@ -1406,8 +1407,13 @@ declare class FriendChallengeError extends GemApiError {
|
|
|
1406
1407
|
readonly configVersion?: number;
|
|
1407
1408
|
});
|
|
1408
1409
|
}
|
|
1410
|
+
interface PlayInviteRequest {
|
|
1411
|
+
readonly params?: Readonly<Record<string, string>>;
|
|
1412
|
+
}
|
|
1409
1413
|
interface FriendsApiDependencies {
|
|
1410
1414
|
readonly challenge?: (request: FriendChallengeRequest) => Promise<FriendChallengeOutcome>;
|
|
1415
|
+
readonly inviteToPlay?: (request?: PlayInviteRequest) => Promise<boolean>;
|
|
1416
|
+
readonly setInviteParams?: (params: Readonly<Record<string, string>> | null) => boolean;
|
|
1411
1417
|
readonly launchedChallengeId?: string;
|
|
1412
1418
|
}
|
|
1413
1419
|
declare class FriendsApi {
|
|
@@ -1415,6 +1421,8 @@ declare class FriendsApi {
|
|
|
1415
1421
|
constructor(api: GameApi, dependencies?: FriendsApiDependencies);
|
|
1416
1422
|
list(options?: ListFriendsOptions): Promise<FriendsPage>;
|
|
1417
1423
|
challenge(request: FriendChallengeRequest): Promise<FriendChallengeOutcome>;
|
|
1424
|
+
inviteToPlay(request?: PlayInviteRequest): Promise<boolean>;
|
|
1425
|
+
setInviteParams(params: Readonly<Record<string, string>> | null): boolean;
|
|
1418
1426
|
inbox(options?: ListFriendChallengesOptions): Promise<FriendChallengesPage>;
|
|
1419
1427
|
launchedChallenge(options?: {
|
|
1420
1428
|
readonly signal?: AbortSignal;
|
|
@@ -2198,6 +2206,10 @@ interface GemCohorts$1 {
|
|
|
2198
2206
|
variantKey: string;
|
|
2199
2207
|
}[];
|
|
2200
2208
|
}
|
|
2209
|
+
interface GemInventoryChanged {
|
|
2210
|
+
readonly gem: typeof PROTOCOL;
|
|
2211
|
+
readonly type: "gem.inventoryChanged";
|
|
2212
|
+
}
|
|
2201
2213
|
interface GemViewport$1 {
|
|
2202
2214
|
readonly gem: typeof PROTOCOL;
|
|
2203
2215
|
readonly type: "gem.viewport";
|
|
@@ -2435,6 +2447,29 @@ interface GemFriendChallengeResult {
|
|
|
2435
2447
|
readonly retryAfterMs?: number;
|
|
2436
2448
|
readonly detail?: string;
|
|
2437
2449
|
}
|
|
2450
|
+
interface GemRequestPlayInvite {
|
|
2451
|
+
readonly gem: typeof PROTOCOL;
|
|
2452
|
+
readonly type: "gem.requestPlayInvite";
|
|
2453
|
+
readonly requestId: string;
|
|
2454
|
+
readonly params?: {
|
|
2455
|
+
key: string;
|
|
2456
|
+
value: string;
|
|
2457
|
+
}[];
|
|
2458
|
+
}
|
|
2459
|
+
interface GemPlayInviteResult {
|
|
2460
|
+
readonly gem: typeof PROTOCOL;
|
|
2461
|
+
readonly type: "gem.playInviteResult";
|
|
2462
|
+
readonly requestId: string;
|
|
2463
|
+
readonly shown: boolean;
|
|
2464
|
+
}
|
|
2465
|
+
interface GemInviteParams {
|
|
2466
|
+
readonly gem: typeof PROTOCOL;
|
|
2467
|
+
readonly type: "gem.inviteParams";
|
|
2468
|
+
readonly params?: {
|
|
2469
|
+
key: string;
|
|
2470
|
+
value: string;
|
|
2471
|
+
}[];
|
|
2472
|
+
}
|
|
2438
2473
|
interface GemRequestAppLinks {
|
|
2439
2474
|
readonly gem: typeof PROTOCOL;
|
|
2440
2475
|
readonly type: "gem.requestAppLinks";
|
|
@@ -3152,6 +3187,7 @@ interface FramePlayer extends PlayerIdentity {
|
|
|
3152
3187
|
readonly boost: PlayerBoost;
|
|
3153
3188
|
}
|
|
3154
3189
|
type GemArcadeAsk = Omit<GemRequestAppLinks, "gem"> | Omit<GemRequestOpenApp, "gem"> | Omit<GemRequestOpenGame, "gem"> | Omit<GemRequestSimilarGames, "gem"> | Omit<GemRequestStoreOffers, "gem"> | Omit<GemRequestStorePurchase, "gem"> | Omit<GemRequestStoreOfferSheet, "gem">;
|
|
3190
|
+
type GemFriendsWindowAsk = Omit<GemRequestPlayInvite, "gem"> | Omit<GemInviteParams, "gem">;
|
|
3155
3191
|
type GemArcadeAnswer = GemAppLinksResult | GemOpenAppResult | GemOpenGameResult | GemSimilarGamesResult | GemStoreOffersResult | GemStorePurchaseResult | GemStorePurchaseSettled | GemStoreOfferSheetResult;
|
|
3156
3192
|
interface FrameCallbacks {
|
|
3157
3193
|
onToken?(msg: GemToken): void;
|
|
@@ -3161,6 +3197,7 @@ interface FrameCallbacks {
|
|
|
3161
3197
|
onPrefs?(msg: GemPrefs$1): void;
|
|
3162
3198
|
onCohorts?(msg: GemCohorts$1): void;
|
|
3163
3199
|
onEarnAllowanceChanged?(): void;
|
|
3200
|
+
onInventoryChanged?(msg: GemInventoryChanged): void;
|
|
3164
3201
|
onViewport?(msg: GemViewport$1): void;
|
|
3165
3202
|
onWillTerminate?(msg: GemWillTerminate): void;
|
|
3166
3203
|
onDevtools?(action: "open" | "close" | "toggle"): void;
|
|
@@ -3194,6 +3231,7 @@ interface FrameCallbacks {
|
|
|
3194
3231
|
onSignInResult?(msg: GemSignInResult): void;
|
|
3195
3232
|
onFriendChallengeResult?(msg: GemFriendChallengeResult): void;
|
|
3196
3233
|
onArcadeAnswer?(msg: GemArcadeAnswer): void;
|
|
3234
|
+
onPlayInviteResult?(msg: GemPlayInviteResult): void;
|
|
3197
3235
|
onError?(code: GemErrorCode, message?: string): void;
|
|
3198
3236
|
onDropped?(code: GemErrorCode, message?: string): void;
|
|
3199
3237
|
onStateChange?(state: FrameState): void;
|
|
@@ -3274,7 +3312,7 @@ declare class GemFrame {
|
|
|
3274
3312
|
readyCalled(): boolean;
|
|
3275
3313
|
requestSignIn(requestId: string): boolean;
|
|
3276
3314
|
requestFriendChallenge(requestId: string, playerId: string, template: string, params?: Readonly<Record<string, string | number>>): boolean;
|
|
3277
|
-
requestArcade(msg: GemArcadeAsk): boolean;
|
|
3315
|
+
requestArcade(msg: GemArcadeAsk | GemFriendsWindowAsk): boolean;
|
|
3278
3316
|
close(): void;
|
|
3279
3317
|
private transition;
|
|
3280
3318
|
private refuseMalformed;
|
|
@@ -3735,4 +3773,4 @@ interface ExitAnalytics {
|
|
|
3735
3773
|
}
|
|
3736
3774
|
declare function leaveAndExit(rooms: ExitRooms, bridge: ExitBridge | null, reason?: string, analytics?: ExitAnalytics): Promise<void>;
|
|
3737
3775
|
declare function createGem(options?: GemOptions): Gem;
|
|
3738
|
-
export { ARCADE_EMBEDDERS, AVATAR_RIGS, type AccountApi, type AdFormat, type AdOutcome, type AdOutcomeKind, type AdRequest, type AdsApi, AnalyticsApi, type AnalyticsFlushOptions, type AnalyticsFlushResult, type AnalyticsOptions, type AnalyticsRejection, type AnalyticsValue, type AppLinksOutcome, type AppListing, type AppStore, type ArcadeApi, type ArcadeAvailability, type ArcadeOffer, type ArcadeOutcome, type ArcadeOutcomeKind, AuthError, type AuthFailure, type AuthState, type Avatar3dFamily, type Avatar3dOffer, type Avatar3dPrice, type Avatar3dPurchaseRequest, type AvatarRigNode, type AvatarRigs, type Avatars3dApi, type BootMark, type BootTimeline, type BrandingApi, type BrandingAsset, type BrandingAssetOptions, type BrandingCurrency, type BrandingImageOptions, type BrandingList, type BrandingLookup, type BrandingTheme, type BrandingVariant, type Challenge, type ChallengeWindow, ChallengesApi, type ConfiguredPurchasePayment, type ConfiguredPurchaseRequest, type ConfiguredPurchaseResult, type ControlsApi, DEVICE_SETTINGS_MAX_BYTES, DedicatedServerError, type DedicatedServerFailure, type DedicatedServerSession, type DevToolsOpener, type DeviceSettings, type DeviceSettingsApi, type DeviceSettingsPutOutcome, type DirectPurchaseRequest, type DirectPurchaseResult, type EarnAllowance, type EarnAllowanceEvent, type EarnAllowancePeriod, type EarnAllowanceReadOptions, type EntityLeaderboard, type EntityLeaderboardEntry, type EntityLeaderboardOptions, type EntityType, type ExitAnalytics, type ExitBridge, type ExitRooms, type FrameState, type Friend, type FriendChallenge, FriendChallengeError, type FriendChallengeErrorCode, type FriendChallengeOutcome, type FriendChallengeOutcomeKind, type FriendChallengeRequest, type FriendChallengesPage, FriendsApi, type FriendsPage, type FunctionFailure, type FunctionInvokeOptions, type FunctionResult, FunctionsApi, type GameCard, type GameConfig, type GameMenu, type GameMenuItem, type GamePass, type GameServerLink, type GameSettingsApi, type Gem, GemApiError, type GemAudioChannels, GemClient, type GemCohort, type GemCohorts, GemConfigError, type GemControlBox, type GemCorner, type GemDevTools, GemFrame, GemFunctionError, type GemGameChoiceSetting, type GemGameSetting, type GemGameSettingBase, type GemGameSettingChange, type GemGameSettingIcon, type GemGameSettingOption, type GemGameSettingValue, type GemGameSliderSetting, type GemGameToggleSetting, type GemGraphicsQuality, type GemGraphicsRoute, type GemGraphicsRouteEntry, type GemIdentity, type GemInsets, type GemLook, type GemLookBase, type GemLookDelta, type GemLookOptions, type GemLookSpeed, type GemMatchApi, type GemMatchServerModule, type GemOptions, type GemPlayer, type GemPreferredRoute, type GemPrefs, type GemRecommendedSettings, type GemReservedArea, GemSaveError, type GemServerBundle, type GemServerFactory, type GemServerHost, type GemServerHostProfile, type GemServerLifecycle, type GemTerminationNotice, GemUnframedError, type GemViewport, type GetLeaderboardOptions, type GraphicsApi, 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 MenuStyle, type MessageMeta, type MomentKind, type MomentResult, type MomentSignal, type MomentsApi, type MultiTransportSession, PLATFORM_EVENTS, type PassesApi, type PassesEvent, 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, type PlayerScope, PlayerText, type PreferredRouteOptions, type ProfileCallOptions, type ProfileShowcaseEntry, ProfilesApi, type PurchaseApi, type PurchaseOptions, type PurchaseOutcome, PurchaseRefusal, type PurchaseRefusalCode, type PurchaseRequest, type PurchaseSettlement, type PutBytesOptions, type PutSaveOptions, type RankedRow, type RecipeAvailability, type RecipeLock, type RewardCue, type RewardPresentation, type RewardedStatus, type SavePage, type SaveRecord, type SendOptions$1 as SendOptions, type ServerTokenGrant, type SessionEndReason, type ShareApi, ShareRefusal, type ShareRequest, ShowcaseApi, type ShowcaseCallOptions, type ShowcaseFriendEntry, type ShowcaseFriends, type ShowcaseValue, type SignInOutcome, type SignInOutcomeKind, type SimilarGamesOutcome, type SnapshotCurrency, type SnapshotItem, type StoreApi, type StoreOffersOutcome, type StoreSettlement, type TransportAdvert, type TransportKind, TransportRefusal, UNRELIABLE_CHANNEL_LABEL, type VibrationApi, type WalletVisibleOptions, type WornAvatar3d, asPlayerText, createBootTimeline, createGem, experimentSelection, leaveAndExit, mapIdentity, markOnResolve, platformIconUrl, presentJoinCredential, readTemplateTransports, readTransportAdvert, reportOnResolve, text, webTransportAvailable };
|
|
3776
|
+
export { ARCADE_EMBEDDERS, AVATAR_RIGS, type AccountApi, type AdFormat, type AdOutcome, type AdOutcomeKind, type AdRequest, type AdsApi, AnalyticsApi, type AnalyticsFlushOptions, type AnalyticsFlushResult, type AnalyticsOptions, type AnalyticsRejection, type AnalyticsValue, type AppLinksOutcome, type AppListing, type AppStore, type ArcadeApi, type ArcadeAvailability, type ArcadeOffer, type ArcadeOutcome, type ArcadeOutcomeKind, AuthError, type AuthFailure, type AuthState, type Avatar3dFamily, type Avatar3dOffer, type Avatar3dPrice, type Avatar3dPurchaseRequest, type AvatarRigNode, type AvatarRigs, type Avatars3dApi, type BootMark, type BootTimeline, type BrandingApi, type BrandingAsset, type BrandingAssetOptions, type BrandingCurrency, type BrandingImageOptions, type BrandingList, type BrandingLookup, type BrandingTheme, type BrandingVariant, type Challenge, type ChallengeWindow, ChallengesApi, type ConfiguredPurchasePayment, type ConfiguredPurchaseRequest, type ConfiguredPurchaseResult, type ControlsApi, DEVICE_SETTINGS_MAX_BYTES, DedicatedServerError, type DedicatedServerFailure, type DedicatedServerSession, type DevToolsOpener, type DeviceSettings, type DeviceSettingsApi, type DeviceSettingsPutOutcome, type DirectPurchaseRequest, type DirectPurchaseResult, type EarnAllowance, type EarnAllowanceEvent, type EarnAllowancePeriod, type EarnAllowanceReadOptions, type EntityLeaderboard, type EntityLeaderboardEntry, type EntityLeaderboardOptions, type EntityType, type ExitAnalytics, type ExitBridge, type ExitRooms, type FrameState, type Friend, type FriendChallenge, FriendChallengeError, type FriendChallengeErrorCode, type FriendChallengeOutcome, type FriendChallengeOutcomeKind, type FriendChallengeRequest, type FriendChallengesPage, FriendsApi, type FriendsPage, type FunctionFailure, type FunctionInvokeOptions, type FunctionResult, FunctionsApi, type GameCard, type GameConfig, type GameMenu, type GameMenuItem, type GamePass, type GameServerLink, type GameSettingsApi, type Gem, GemApiError, type GemAudioChannels, GemClient, type GemCohort, type GemCohorts, GemConfigError, type GemControlBox, type GemCorner, type GemDevTools, GemFrame, GemFunctionError, type GemGameChoiceSetting, type GemGameSetting, type GemGameSettingBase, type GemGameSettingChange, type GemGameSettingIcon, type GemGameSettingOption, type GemGameSettingValue, type GemGameSliderSetting, type GemGameToggleSetting, type GemGraphicsQuality, type GemGraphicsRoute, type GemGraphicsRouteEntry, type GemIdentity, type GemInsets, type GemLook, type GemLookBase, type GemLookDelta, type GemLookOptions, type GemLookSpeed, type GemMatchApi, type GemMatchServerModule, type GemOptions, type GemPlayer, type GemPreferredRoute, type GemPrefs, type GemRecommendedSettings, type GemReservedArea, GemSaveError, type GemServerBundle, type GemServerFactory, type GemServerHost, type GemServerHostProfile, type GemServerLifecycle, type GemTerminationNotice, GemUnframedError, type GemViewport, type GetLeaderboardOptions, type GraphicsApi, 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 MenuStyle, type MessageMeta, type MomentKind, type MomentResult, type MomentSignal, type MomentsApi, type MultiTransportSession, PLATFORM_EVENTS, type PassesApi, type PassesEvent, type PeriodOptions, PlatformApi, PlatformCurrenciesApi, type PlatformCurrency, type PlatformCurrencyAccess, type PlatformCurrencyPurchasePayment, type PlatformCurrencyPurchaseRequest, type PlatformCurrencyPurchaseResult, type PlatformCurrencyReadOptions, PlatformEarnAllowanceApi, type PlatformEventName, type PlayInviteRequest, type PlayerBadge, type PlayerBoost, type PlayerBoostMultiplier, type PlayerIdentity, type PlayerProfile, type PlayerScope, PlayerText, type PreferredRouteOptions, type ProfileCallOptions, type ProfileShowcaseEntry, ProfilesApi, type PurchaseApi, type PurchaseOptions, type PurchaseOutcome, PurchaseRefusal, type PurchaseRefusalCode, type PurchaseRequest, type PurchaseSettlement, type PutBytesOptions, type PutSaveOptions, type RankedRow, type RecipeAvailability, type RecipeLock, type RewardCue, type RewardPresentation, type RewardedStatus, type SavePage, type SaveRecord, type SendOptions$1 as SendOptions, type ServerTokenGrant, type SessionEndReason, type ShareApi, ShareRefusal, type ShareRequest, ShowcaseApi, type ShowcaseCallOptions, type ShowcaseFriendEntry, type ShowcaseFriends, type ShowcaseValue, type SignInOutcome, type SignInOutcomeKind, type SimilarGamesOutcome, type SnapshotCurrency, type SnapshotItem, type StoreApi, type StoreOffersOutcome, type StoreSettlement, type TransportAdvert, type TransportKind, TransportRefusal, UNRELIABLE_CHANNEL_LABEL, type VibrationApi, type WalletVisibleOptions, type WornAvatar3d, asPlayerText, createBootTimeline, createGem, experimentSelection, leaveAndExit, mapIdentity, markOnResolve, platformIconUrl, presentJoinCredential, readTemplateTransports, readTransportAdvert, reportOnResolve, text, webTransportAvailable };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
var GemWebSdkBridgeBundle=(function(){'use strict';var j="GemWebSdkHandshake";function ie(){return typeof document>"u"?void 0:document.readyState}var B=()=>Date.now();function N(n={}){let e=n.win??window,t=e,r=t[j];if(r!==void 0)return r;let o=n.readyState??ie,s=n.now??B,d=[],i=[],u=y=>{let c=y.data;!c||c.type!=="gem.handshake"||(d.length>=4&&(d.shift(),i.shift(),p.dropped+=1),d.push(y),i.push(s()));};e.addEventListener("message",u);let p={events:d,times:i,dropped:0,late:o()==="complete",uninstall(){e.removeEventListener("message",u);}};return t[j]=p,p}function W(n,e,t={}){let r=n[j];if(r===void 0)return null;let o=t.ttlMs??9500,s=t.now??B,d=r.events.splice(0),i=r.times?.splice(0),u=0,p=0,y=false,c=s()-o;for(let h=d.length-1;h>=0;h--){let R=i?.[h];if(R!==void 0&&R<c){p+=1;continue}if(u+=1,e(d[h])===true){y=true;break}}return r.uninstall(),{capture:r,delivered:u,stale:p,accepted:y}}var l="gem-web-bridge",S={min:1,max:1},le=65536,z=8,x=5e3,V=1024;var w=Object.create(null),P="__malformed";var F=Object.create(null),de=Object.freeze([["gem.asyncOpponents.","asyncOpponents"],["gem.vibration.","vibration"],["gem.viewport.","reservedAreas"],["gem.moments.","moments"],["gem.prefs.","audioChannels"],["gem.share.","shareRemap"]]);function C(n){let e=F[n];if(e!==void 0)return e;for(let[t,r]of de)if(n.startsWith(t))return r}function me(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 ue(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 ce(n){return /^[a-z]{2,8}(-[a-z0-9]{1,8})*$/i.test(n)}function ge(n){return /^[a-z_]+$/.test(n)}function pe(n){return /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(n)||/^[a-z0-9][a-z0-9-]{1,38}[a-z0-9]$/.test(n)&&!n.includes("--")}function D(n,e,t){if(e>z)return `nesting deeper than ${z}`;if(++t.nodes>x)return `more than ${x} values`;if(t.bytes>t.cap)return `over the ${t.cap} 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 o=n;if(t.seen.has(o))return "a repeated or cyclic object reference";if(t.seen.add(o),Array.isArray(n)){if(n.length>V)return `an array of ${n.length} entries, over the ${V} limit`;t.bytes+=2;for(let i of n){let u=D(i,e+1,t);if(u)return u}return null}let s=Object.getPrototypeOf(n);if(s!==Object.prototype&&s!==null)return "a value that is not a plain object";t.bytes+=2;let d=n;for(let i in d){if(!Object.prototype.hasOwnProperty.call(d,i))continue;if(++t.nodes>x)return `more than ${x} values`;if(t.bytes+=i.length*3+4,t.bytes>t.cap)return `over the ${t.cap} byte limit`;let u=D(d[i],e+1,t);if(u)return u}return null}function ye(n,e=le){let t={nodes:0,bytes:0,seen:new Set,cap:e},r=D(n,0,t);return r?`message contains ${r}`:t.bytes>e?`message is over the ${e} byte limit`:null}var fe={origin:[me,"not a well-formed origin"],url:[ue,"not a safe absolute http(s) URL"],bcp47:[ce,"not a well-formed BCP 47 tag"],code:[ge,"not a code of lower-case letters and underscores"],gameRef:[pe,"not a game id or web address"]};function K(n,e,t){for(let r of e){let o=t===""?r[0]:`${t}.${r[0]}`,s=n[r[0]];if(s==null){if(r[1]<"a")continue;return `${o}: required`}let d=M(s,r,o);if(d)return d}return null}function M(n,e,t){let r=e[1].toLowerCase();switch(r){case "u":return typeof n=="boolean"?null:M(n,typeof n=="string"?[e[0],"s",e[2]]:[e[0],"n",e[3],e[4]],t);case "s":{if(typeof n!="string")return `${t}: expected string`;if(n.length>e[2])return `${t}: exceeds ${e[2]} characters`;if(e[3]){let[o,s]=fe[e[3]];if(!o(n))return `${t}: ${s}`}return null}case "n":case "i":return typeof n!="number"||!(r=="i"?Number.isInteger:Number.isFinite)(n)?`${t}: expected ${r=="i"?"integer":"number"}`:n<e[2]||n>e[3]?`${t}: out of range ${e[2]}..${e[3]}`:null;case "b":return typeof n=="boolean"?null:`${t}: expected boolean`;case "e":{let o=e[2];return o.includes(n)?null:`${t}: not one of ${o.join("|")}`}case "o":return typeof n!="object"||n===null||Array.isArray(n)?`${t}: expected object`:K(n,e[2],t);case "j":return typeof n!="object"||n===null||Array.isArray(n)?`${t}: expected a plain object`:null;case "a":{if(!Array.isArray(n))return `${t}: expected array`;if(n.length>e[2])return `${t}: exceeds ${e[2]} items`;let o=e[3],s=`${t}[]`;for(let d of n){if(d==null){if(o[1]<"a")continue;return `${s}: required`}let i=M(d,o,s);if(i)return i}return null}default:return `${t}: unknown kind ${String(r)}`}}var Y=Object.create(null);function a(n,e,t,r,o){return w[n]=t,r&&(F[n]=r),Y[n]=s=>{let d=ye(s,o);if(d)return d;if(typeof s!="object"||s===null||Array.isArray(s))return "message: expected object";let i=s;return i.gem!==l?"gem: wrong protocol marker":i.type!==n?`type: expected ${n}`:K(i,e,"")}}var b=["","s",64],m=["requestId","s",64],G=["matchId","s",64],f=["reason","S",64,"code"],v=["outcome","e",["ok","declined","unavailable"]];a("gem.handshake",[["versions","o",[["min","i",1,1e3],["max","i",1,1e3]]],["capabilities","A",64,b],["embedder","s",2048,"origin"],["unbidden","B"]],30);a("gem.handshake.accept",[["v","i",1,1e3],["capabilities","A",64,b]],5);a("gem.token",[["token","s",4096],["requestId","S",64],["generation","i",0,2147483647],["apiBaseUrl","S",512,"url"],["playerId","s",64],["gameId","s",64],["channel","e",["dev","test","release"]],["gameVersion","S",64],["expiresAt","i",0,4102444800],["chainEndsAt","i",0,4102444800],["allowDevTools","B"]],30);a("gem.token.denied",[m,["retryable","b"],["retryAfterMs","I",0,36e5],["reason","e",["chain_exhausted","unavailable"]],["correlationId","s",64]],30);a("gem.player",[["untrusted","o",[["displayName","s",64],["displayTag","S",80],["displayHandle","s",80]]],["playerId","S",64],["discriminator","S",8],["avatarIconUrl","S",2048,"url"],["avatarIconId","S",64],["avatar3dId","S",64],["avatar3dModelUrl","S",2048,"url"],["avatar3dIconUrl","S",2048,"url"],["avatars3d","A",8,["","o",[["family","s",32],["id","s",64],["modelUrl","s",256,"url"],["iconUrl","s",256,"url"]]]],["badges","A",2,["","o",[["itemId","s",64],["iconUrl","s",2048,"url"]]]],["displayTag","s",8],["avatarUrl","S",2048,"url"],["boost","O",[["multipliers","a",8,["","o",[["currencyId","s",64],["currencySlug","s",32],["multiplierBp","i",1e4,1e6]]]],["expiresInDays","I",1,7]]]],12);a("gem.pause",[["paused","b"]],120);a("gem.prefs",[["reducedMotion","b"],["muted","b"],["showFrameStats","B"],["music","B"],["sounds","B"],["locale","s",35,"bcp47"],["recommended","O",[["volume","i",0,100],["batterySaver","b"],["keyboardLayout","e",["wasd","arrows"]],["gamepadConfirm","e",["south","east"]],["vibration","b"],["lookSensitivity","I",20,400],["gamepadLookSensitivity","I",20,400],["invertLookY","B"],["touchMovement","S",16,"code"],["graphicsQuality","S",16,"code"],["graphicsQualityAuto","B"],["colorHelp","B"]]]],60);a("gem.cohorts",[["cohorts","a",8,["","o",[["experimentId","s",36],["variantKey","s",32]]]]],12,"cohorts");a("gem.earnAllowanceChanged",[],30,"earnAllowance");a("gem.viewport",[["insets","o",[["top","i",0,4096],["right","i",0,4096],["bottom","i",0,4096],["left","i",0,4096]]],["reserved","A",4,["","o",[["x","i",0,16384],["y","i",0,16384],["width","i",0,16384],["height","i",0,16384],["control","O",[["x","i",0,16384],["y","i",0,16384],["width","i",0,16384],["height","i",0,16384]]]]]]],60,"viewport");a("gem.deviceSettings",[["settings","J"]],12,"deviceSettings");a("gem.willTerminate",[["reason","e",["grant_expiring","session_ended","navigating","kill_switch"]],["graceMs","i",0,6e4]],10);a("gem.roomEvent",[["event","e",["updated","match_started","match_ready","match_failed","version_stale"]],["roomId","s",64],["matchId","S",64],["version","I",0,2147483647],["reason","S",64],["platform","E",["universal","mobile"]]],120,"rooms");a("gem.socketState",[["connected","b"],["reason","E",["connecting","dropped","watchdog","terminal"]]],12,"socketState");a("gem.seatedEvent",[["roomId","s",64]],60,"partySeating");a("gem.autoStartFailedEvent",[["roomId","s",64],["code","s",64]],30,"autoStartFailure");a("gem.ticketEvent",[["event","e",["queued","matched","expired","cancelled","failed"]],["ticketId","s",64],["partySize","I",1,64],["queuedAt","I",0,4102444800],["expiresAt","I",0,4102444800],["reason","S",64],["roomId","S",64]],60,"ticketEvents");a("gem.signalEvent",[["event","e",["hello","offer","answer","ice","peerJoined","peerLeft","migration","matchEnded","error"]],G,["data","j"]],1800,"p2p");a("gem.relayDraining",[G,["clusterTargetId","s",64],["relayIps","a",16,b],["drainingSince","s",40],["deadline","s",40]],60,"p2pRelayDrain");a("gem.dedicatedEvent",[["event","e",["answer","error","matchEnded"]],G,["sdp","S",10240],["sessionId","S",64],["code","S",64],["message","S",256],["reason","S",64]],120,"dedicated");a("gem.partyResult",[m,["partyId","S",64]],30,"parties");a("gem.clusterTarget",[["clusterTargetId","s",64],["clusterTargetIds","A",3,b]],12,"clusterTarget");a("gem.graphicsRoutes",[["entries","a",32,["","o",[["gpu","s",32],["route","S",32],["host","S",32]]]]],12,"graphicsRoutes");a("gem.devtools",[["action","e",["open","close","toggle"]]],30,"devtools");a("gem.screenshot",[["maxWidth","i",1,7680],["maxHeight","i",1,4320]],6,"screenshot");a("gem.screenshot.denied",[["reason","e",["not_wired","no_source","unsupported","unreadable","tainted","too_large","busy","declined","failed"]],["retryable","b"]],12,"screenshot");a("gem.requestContext",[],12,"feedbackContext");a("gem.gameContext",[["context","j"]],12,"feedbackContext");a("gem.signal",[["signal","e",["join","offer","answer","ice","migrationAck","hostUnreachable"]],G,["data","j"]],1200,"p2p");a("gem.dedicatedOffer",[G,["sdp","s",10240],["intent","e",["initial","ice_restart","full_reconnect"]]],60,"dedicated");a("gem.partyRequest",[m],12,"parties");a("gem.ready",[],5);a("gem.engaged",[],5,"engagement");a("gem.progress",[["loaded","i",0,1099511627776],["total","i",0,1099511627776]],600);a("gem.requestToken",[m,["reason","e",["initial","expiring","rejected"]]],12);a("gem.requestLocalServer",[m,["gameRoomId","s",64]],6,"localHost");a("gem.localServer",[m,["serverId","S",128]],30,"localHost");a("gem.localServer.denied",[m,["retryable","b"],["reason","e",["refused","unavailable"]]],30,"localHost");a("gem.exit",[["reason","S",64]],5);a("gem.openExternal",[["url","s",2048,"url"]],6);a("gem.requestFullscreen",[["enabled","b"]],30);a("gem.audioState",[["muted","b"]],120,"audioState");a("gem.rewardCue",[["currencySlug","s",32],["cueId","S",64],["expected","I",1,1e9],["origin","O",[["x","i",0,16384],["y","i",0,16384]]]],60,"rewardCue");a("gem.rewardPresentation",[["mode","e",["arcade","game"]]],12,"rewardPresentation");a("gem.walletDisplay",[["visible","b"],["currencies","A",8,b],["score","B"]],60,"walletDisplay");a("gem.controlsDeclare",[["uses","o",[["lookSensitivity","S",16,"code"],["gamepadLookSensitivity","S",16,"code"],["invertLookY","S",16,"code"],["touchMovement","S",16,"code"]]]],60,"controls");a("gem.menu",[["settings","b"],["items","A",4,["","o",[["id","s",32],["label","s",40]]]]],60,"gameMenu");a("gem.menuSelect",[["entry","e",["settings","item"]],["id","S",32]],60,"gameMenu");a("gem.gemCorner",[["corner","e",["top-left","top-right","bottom-left","bottom-right"]]],12,"gemCorner");a("gem.menuStyle",[["ground","S",7],["accent","S",7]],12,"menuStyle");a("gem.settingsDeclare",[["settings","a",8,["","o",[["id","s",40],["label","s",40],["kind","e",["toggle","slider","choice"]],["value","u",40,-1e6,1e6],["quick","B"],["icon","S",16,"code"],["min","N",-1e6,1e6],["max","N",-1e6,1e6],["step","N",0,1e6],["options","A",4,["","o",[["id","s",40],["label","s",40]]]]]]]],120,"gameSettings");a("gem.settingChange",[["id","s",40],["value","u",40,-1e6,1e6]],120,"gameSettings");a("gem.requestShare",[["requestId","S",64],["params","a",16,["","o",[["key","s",64],["value","s",512]]]]],6,"share");a("gem.shareResult",[m,["outcome","e",["accepted","refused"]],f,["key","S",64]],30,"shareResult");a("gem.requestAvatarPicker",[["tab","E",["2d","3d"]]],6,"avatarPicker");a("gem.vibrate",[["pattern","a",99,["","i",0,1e4]]],600,"vibration");a("gem.frameStats",[["fps","i",0,1e3],["frameTimeP95Ms","i",0,1e5],["counts","E",["pageFrames","gameDraws"]]],120,"frameStats");a("gem.portraitBorders",[["name","S",40]],60,"portraitBorders");a("gem.error",[["code","e",["version_mismatch","handshake_timeout","handshake_duplicate","invalid_message","rate_limited","token_unavailable","unsupported","unsupported_capability","internal"]],["message","S",256]],60);a("gem.requestPurchase",[m,["purchaseKind","e",["item","recipe"]],["targetId","s",64],["currencySlug","s",32],["quantity","I",1,10],["catalogId","S",64],["origin","E",["sheet","direct_refused"]]],12,"purchases");a("gem.requestAvatar3dPurchase",[m,["itemId","s",64],["currencySlug","s",32]],12,"avatar3dPurchases");a("gem.purchaseResult",[m,v,f,["purchaseId","S",64]],30,"purchases");a("gem.purchaseSettled",[["purchaseKind","e",["item","recipe"]],["targetId","s",64],["catalogId","S",64],["quantity","i",1,10],["purchaseId","S",64]],30,"purchaseSettled");a("gem.deviceSettings.put",[m,["settings","j"]],30,"deviceSettings");a("gem.deviceSettings.result",[m,["outcome","e",["stored","too_large","unavailable"]]],30,"deviceSettings");a("gem.requestAd",[m,["placement","s",32],["format","e",["interstitial","rewarded"]]],6,"ads");a("gem.adResult",[m,["outcome","e",["shown","no_ad","unavailable"]]],12,"ads");a("gem.signalMoment",[m,["kind","e",["level_end","run_end","match_end","menu_return","other_break"]],["placement","S",32],["wall","B"]],6,"moments");a("gem.momentResult",[m,["shown","b"]],12,"moments");a("gem.requestSignIn",[m],6,"signIn");a("gem.signInResult",[m,["outcome","e",["signed_in","declined","unavailable"]]],12,"signIn");a("gem.requestFriendChallenge",[m,["playerId","s",64],["template","s",64],["params","J"]],12,"friendChallenges");a("gem.friendChallengeResult",[m,["outcome","e",["accepted","cancelled","refused","unavailable","rate_limited","invalid"]],["code","S",64],["param","S",64],["channel","S",16],["configVersion","I",0,9007199254740991],["retryAfterMs","I",0,864e5],["detail","S",300]],30,"friendChallenges");a("gem.requestAppLinks",[m],12,"appLinks");a("gem.appLinksResult",[m,v,f,["arcade","O",[["store","e",["app_store","google_play"]]]],["game","O",[["store","e",["app_store","google_play"]]]]],30,"appLinks");a("gem.requestOpenApp",[m,["target","e",["arcade","game"]]],6,"appLinks");a("gem.openAppResult",[m,v,f],30,"appLinks");a("gem.requestOpenGame",[m,["ref","s",40,"gameRef"]],6,"openGame");a("gem.openGameResult",[m,v,f],30,"openGame");a("gem.requestSimilarGames",[m,["limit","I",1,24]],12,"openGame");a("gem.similarGamesResult",[m,v,f,["games","a",24,["","o",[["gameId","s",36,"gameRef"],["slug","S",40,"gameRef"],["iconUrl","s",1024,"url"],["capsuleLandscapeUrl","s",1024,"url"],["capsulePortraitUrl","s",1024,"url"],["previewVideoUrl","S",1024,"url"],["previewPosterUrl","S",1024,"url"],["untrusted","o",[["name","s",64],["tagline","s",64],["shortDescription","s",320],["tags","a",10,["","s",32]]]]]]]],30,"openGame",524288);a("gem.requestStoreOffers",[m],12,"store");a("gem.storeOffersResult",[m,v,f,["offers","a",32,["","o",[["skuId","s",64],["kind","e",["gem_pack","boost","pass","bundle"]],["name","s",80],["description","s",400],["imageUrl","S",1024,"url"],["priceDisplay","s",32],["grant","O",[["currency","s",32],["amount","i",1,1e9]]]]]]],30,"store",262144);a("gem.requestStorePurchase",[m,["skuId","s",64]],12,"store");a("gem.storePurchaseResult",[m,v,f],30,"store");a("gem.storePurchaseSettled",[["skuId","s",64]],30,"store");a("gem.requestStoreOfferSheet",[m,["skuId","s",64]],12,"storeOfferSheet");a("gem.storeOfferSheetResult",[m,v,f],30,"storeOfferSheet");var T=Object.freeze(Y);w.__malformed=60;Object.freeze(w);Object.freeze(F);var he=/^[a-z0-9][a-z0-9_-]{0,39}$/;function ve(n){return typeof n=="string"&&he.test(n)}function J(n){if(n===null||ve(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.`);}function Q(n){return typeof n=="string"&&/^[\w-]{1,64}$/.test(n)}var $={now:()=>Date.now(),setTimeout:(n,e)=>setTimeout(n,e),clearTimeout:n=>clearTimeout(n)},k=class{constructor(e=$){this.clock=e;}clock;tokens=new Map;lastRefill=new Map;allow(e){let t=w[e];if(t===void 0)return false;let r=this.clock.now(),o=this.lastRefill.get(e)??r,s=this.tokens.get(e)??t,d=Math.max(0,r-o),i=Math.min(t,s+d*t/6e4);return i<1?(this.tokens.set(e,i),this.lastRefill.set(e,r),false):(this.tokens.set(e,i-1),this.lastRefill.set(e,r),true)}};function q(n,e){return n.toLowerCase()===e.toLowerCase()}function I(n){let e=n.toLowerCase();return e==="localhost"||e.endsWith(".localhost")||e==="[::1]"||e==="::1"?true:/^127(\.\d{1,3}){3}$/.test(e)}function X(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:I(t.hostname)&&I(r.hostname)}function Z(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}var ne="[gem: use gem.text.toPlain()]",ee=new Set,te;function Re(n){try{if(ee.has(n))return;let e=globalThis.location;if(te??=!!e?.port&&I(e.hostname??""),!te)return;ee.add(n),console.warn(`[gem] ${n} is PlayerText, turned into a string: players see ${ne}. Render text.toPlain(value) (text is in @indiegems/gem-web-sdk/sdk).
|
|
2
|
-
${new Error().stack}`);}catch{}}var U=class{#e;#t;constructor(e,t="player text"){this.#e=e,this.#t=t,Object.freeze(this);}toString(){return Re(this.#t),ne}toJSON(){return this.toString()}get[Symbol.toStringTag](){return "PlayerText"}static unwrap(e){return e.#e}};function H(n,e){return new U(n,e)}function re(n){return Math.min(16384,Math.max(0,Math.round(Number.isFinite(n)?n:0)))}function Se(n,e){if(n!==true)return {visible:false};let t=[],r=false;for(let o of Array.isArray(e)?e:[])o==="score"?r=true:typeof o=="string"&&o.length>0&&o.length<=64&&!t.includes(o)&&t.push(o);return !r&&t.length===0?{visible:true}:{visible:true,currencies:t.slice(0,8),score:r}}function we(n){let e=[];for(let t of Array.isArray(n)?n:[]){if(e.length===4)break;if(typeof t!="object"||t===null)continue;let{id:r,label:o}=t;typeof r!="string"||r.length===0||r.length>32||typeof o!="string"||o.trim().length===0||e.some(s=>s.id===r)||e.push({id:r,label:o.trim().slice(0,40)});}return e.length===0?{settings:false}:{settings:false,items:e}}function ae(n,e){return Math.min(e,Math.max(0,Math.round(Number.isFinite(n)?n:0)))}function be(n){let e=n.untrusted,t=H(e.displayName,"gem.player.displayName"),r=e.displayTag||e.displayHandle,o=r?H(r,"gem.player.displayTag"):void 0,s=n.discriminator||n.displayTag,d=s&&/^[0-9]{1,8}$/.test(s)?s:void 0,i=n.avatarIconUrl||n.avatarUrl,u=/^[\da-f]{8}(-[\da-f]{4}){3}-[\da-f]{12}$/i,p=n.avatarIconId,y=n.avatar3dId,c={displayName:t,displayHandle:o??t,badges:(n.badges??[]).map(g=>({itemId:g.itemId,iconUrl:g.iconUrl}))};n.playerId&&(c.playerId=n.playerId),d&&(c.discriminator=d),o&&(c.displayTag=o),i&&(c.avatarIconUrl=c.avatarUrl=i),p&&u.test(p)&&(c.avatarIconId=p),y&&u.test(y)&&(c.avatar3dId=y),n.avatar3dModelUrl&&(c.avatar3dModelUrl=n.avatar3dModelUrl),n.avatar3dIconUrl&&(c.avatar3dIconUrl=n.avatar3dIconUrl),n.avatars3d&&(c.avatars3d=n.avatars3d.filter(g=>u.test(g.id)&&/^[a-z][a-z0-9_]*$/.test(g.family)).filter((g,A,L)=>L.findIndex(_=>_.family==g.family)==A).map(({family:g,id:A,modelUrl:L,iconUrl:_})=>({family:g,id:A,modelUrl:L,iconUrl:_})));let h=n.boost,R=(h?.multipliers??[]).map(g=>({currencyId:g.currencyId,currencySlug:g.currencySlug,multiplier:g.multiplierBp/1e4})),E=R.some(g=>g.multiplier>1);return c.boost=E&&h?.expiresInDays?{active:E,multipliers:R,expiresInDays:h.expiresInDays}:{active:E,multipliers:R},c}var Ge=1e4,ke=["appLinks","openGame","store","storeOfferSheet"],Oe=["token","pause","menuSelect","settingChange","prefs","cohorts","viewport","willTerminate","localServer","roomEvent","seatedEvent","autoStartFailedEvent","ticketEvent","socketState","signalEvent","relayDraining","dedicatedEvent","clusterTarget","graphicsRoutes","partyResult","purchaseResult","purchaseSettled","shareResult","deviceSettings","adResult","momentResult","signInResult","friendChallengeResult"],xe=new WeakMap;var O=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??$,this.inbound=new k(this.clock),this.outbound=new k(this.clock);}options;state="waiting";port=null;version=null;peerCapabilities=[];unbidden=false;engagedSent=false;readyPending=false;readySent=false;settleWaiters=[];clock;inbound;outbound;expectedSource;get currentState(){return this.state}get parentCapabilities(){return this.peerCapabilities}parentSupports(e){return this.peerCapabilities.includes(e)}get protocolVersion(){return this.version}get unbiddenLaunch(){return this.unbidden}handleWindowMessage(e){if(e.source!==this.expectedSource)return this.refuse(e,"handshake did not come from the expected embedder window"),false;if(!(this.options.allowedEmbedders.some(i=>q(i,e.origin))||X(e.origin,this.options.selfOrigin)||(xe.get(this)??[]).some(i=>q(i,e.origin))))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=T["gem.handshake"]?.(e.data);if(r)return this.refuse(e,`malformed handshake: ${r}`),false;let o=e.data;if(!q(o.embedder,e.origin))return this.refuse(e,`handshake claims embedder '${o.embedder}' but arrived from '${e.origin}'`),false;let s=e.ports?.[0];if(!s)return this.refuse(e,"handshake transferred no MessagePort"),false;let d=Z(S,o.versions);return d===null?(s.onmessage=null,s.postMessage({gem:l,type:"gem.error",code:"version_mismatch",message:`frame supports v${S.min}..v${S.max}`}),s.close(),this.transition("refused"),this.options.onError?.("version_mismatch"),false):(this.port=s,this.version=d,s.onmessage=i=>this.receive(i.data,i.ports??[]),s.start?.(),this.peerCapabilities=o.capabilities??[],this.unbidden=o.unbidden===true,s.postMessage({gem:l,type:"gem.handshake.accept",v:d,...this.options.capabilities===void 0?{}:{capabilities:[...this.options.capabilities]}}),this.transition("connected"),this.readyPending&&(this.readyPending=false,this.ready()),true)}ready(){if(this.state!=="connected"||!this.port){this.readyPending=true;return}if(this.readySent){this.options.onDropped?.("internal","gem.ready was already sent; duplicate suppressed");return}this.readySent=true,this.send({gem:l,type:"gem.ready"});}settled(e=Ge){return this.state!=="waiting"?Promise.resolve(this.state):new Promise(t=>{let r=s=>{this.clock.clearTimeout(o),t(s);},o=this.clock.setTimeout(()=>{let s=this.settleWaiters.indexOf(r);s>=0&&this.settleWaiters.splice(s,1),t(this.state);},e);this.settleWaiters.push(r);})}progress(e,t){this.send({gem:l,type:"gem.progress",loaded:e,total:t});}requestToken(e,t){this.send({gem:l,type:"gem.requestToken",requestId:e,reason:t});}requestLocalServer(e,t){return this.parentSupports("localHost")?(this.send({gem:l,type:"gem.requestLocalServer",requestId:e,gameRoomId:t}),true):false}exit(e){this.send(e===void 0?{gem:l,type:"gem.exit"}:{gem:l,type:"gem.exit",reason:e});}openExternal(e){this.send({gem:l,type:"gem.openExternal",url:e});}requestFullscreen(e){this.send({gem:l,type:"gem.requestFullscreen",enabled:e});}reportMuted(e){return this.gated("audioState")?(this.send({gem:l,type:"gem.audioState",muted:e}),true):false}reportEngaged(){return this.engagedSent||!this.gated("engagement")||!this.send({gem:l,type:"gem.engaged"})?false:(this.engagedSent=true,true)}cueReward(e){if(!this.gated("rewardCue"))return false;let t={gem:l,type:"gem.rewardCue",currencySlug:String(e.currencySlug).slice(0,32)};return Q(e.cueId)&&(t.cueId=e.cueId),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:re(e.origin.x),y:re(e.origin.y)}),this.send(t),true}showPortraitBorders(e){let t=J(e);return t===void 0||!this.gated("portraitBorders")?false:this.send(t===null?{gem:l,type:"gem.portraitBorders"}:{gem:l,type:"gem.portraitBorders",name:t})}setWalletVisible(e,t){return this.gated("walletDisplay")?this.send({gem:l,type:"gem.walletDisplay",...Se(e,t?.only)}):false}setMenu(e){return this.gated("gameMenu")?this.send({gem:l,type:"gem.menu",...we(e)}):false}declareSettings(e){return this.gated("gameSettings")?this.send({gem:l,type:"gem.settingsDeclare",settings:e}):false}setGemCorner(e){return this.gated("gemCorner")?this.send({gem:l,type:"gem.gemCorner",corner:e}):false}setRewardPresentation(e){return this.gated("rewardPresentation")?this.send({gem:l,type:"gem.rewardPresentation",mode:e}):false}setMenuStyle(e){return this.gated("menuStyle")?this.send(e===null?{gem:l,type:"gem.menuStyle"}:{gem:l,type:"gem.menuStyle",ground:e.ground,accent:e.accent}):false}requestShare(e,t){return this.gated("share")?this.send({gem:l,type:"gem.requestShare",...t===void 0?{}:{requestId:t},params:e.map(({key:r,value:o})=>({key:r,value:o}))}):false}requestAvatarPicker(e){return this.gated("avatarPicker")?this.send({gem:l,type:"gem.requestAvatarPicker",...e==="2d"||e==="3d"?{tab:e}:{}}):false}requestVibrate(e){return this.gated("vibration")?this.send({gem:l,type:"gem.vibrate",pattern:[...e]}):false}reportFrameStats(e){return this.gated("frameStats")?(this.send({gem:l,type:"gem.frameStats",fps:ae(e.fps,1e3),frameTimeP95Ms:ae(e.frameTimeP95Ms,1e5),counts:e.counts==="gameDraws"?"gameDraws":"pageFrames"}),true):false}sendGameContext(e){return this.state!=="connected"?false:(this.send({gem:l,type:"gem.gameContext",context:e}),true)}signal(e,t,r){this.send({gem:l,type:"gem.signal",signal:e,matchId:t,data:r});}dedicatedOffer(e,t,r){this.send({gem:l,type:"gem.dedicatedOffer",matchId:e,sdp:t,intent:r});}requestParty(e){return this.send({gem:l,type:"gem.partyRequest",requestId:e})}requestPurchase(e,t,r,o,s,d,i){return this.send({gem:l,type:"gem.requestPurchase",requestId:e,purchaseKind:t,targetId:r,currencySlug:o,...s===void 0?{}:{quantity:s},...d===void 0?{}:{catalogId:d},...i===void 0?{}:{origin:i}})}requestAvatar3dPurchase(e,t,r){return this.parentSupports("avatar3dPurchases")?this.send({gem:l,type:"gem.requestAvatar3dPurchase",requestId:e,itemId:t,currencySlug:r}):false}putDeviceSettings(e,t){return this.send({gem:l,type:"gem.deviceSettings.put",requestId:e,settings:t})}requestAd(e,t,r){return this.send({gem:l,type:"gem.requestAd",requestId:e,placement:t,format:r})}signalMoment(e,t,r,o){return this.send({gem:l,type:"gem.signalMoment",requestId:e,kind:t,...r===void 0?{}:{placement:r},...o===true?{wall:true}:{}})}readyCalled(){return this.readySent||this.readyPending}requestSignIn(e){return this.send({gem:l,type:"gem.requestSignIn",requestId:e})}requestFriendChallenge(e,t,r,o){return this.send({gem:l,type:"gem.requestFriendChallenge",requestId:e,playerId:t,template:r,...o===void 0?{}:{params:o}})}requestArcade(e){return this.gated(C(e.type))&&this.send({gem:l,...e})}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(P)){this.options.onDropped?.(e,t);return}this.fail(e,t);}dropUnknownType(e){this.inbound.allow(P)&&this.options.onDropped?.("unsupported",`ignored unknown message type '${e}'`);}refuse(e,t){e.ports?.[0]?.close?.(),this.inbound.allow(P)&&this.options.onRefused?.(t);}fail(e,t){this.options.onError?.(e,t),this.state==="connected"&&this.port&&this.send({gem:l,type:"gem.error",code:e,...t===void 0?{}:{message:t}});}gated(e){return this.state==="connected"&&this.parentSupports(e)}send(e){if(this.state!=="connected"||!this.port)return this.options.onDropped?.("internal",`dropped ${String(e.type)} before connect`),false;let t=e.type;if(!this.outbound.allow(t))return this.options.onError?.("rate_limited",`frame exceeded its own limit for ${t}`),false;let r=T[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||oe(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 o=T[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 s=C(r);if(s!==void 0&&!this.options.capabilities?.includes(s))return this.fail("unsupported_capability",`${r} requires the '${s}' capability, which this frame did not advertise`),false;let d=o(e);if(d)return this.fail("invalid_message",`${r}: ${d}`),false;let i=e;if(i.v!==this.version)return this.fail("invalid_message",`${r}: expected v ${String(this.version)}`),false;switch(r){case "gem.earnAllowanceChanged":this.options.onEarnAllowanceChanged?.();break;case "gem.devtools":this.options.onDevtools?.(i.action);break;case "gem.requestContext":this.options.onRequestContext?.();break;case "gem.screenshot":{let u=t[0];if(!u){this.options.onError?.("invalid_message","gem.screenshot transferred no MessagePort");break}let p={maxWidth:i.maxWidth,maxHeight:i.maxHeight};if(!this.options.onScreenshot){u.close(),this.screenshotDenied("not_wired",false);break}return oe(t.slice(1)),this.options.onScreenshot(p,u,(y,c)=>this.screenshotDenied(y,c)),true}case "gem.token.denied":this.options.onTokenDenied?.(i);break;case "gem.localServer.denied":this.options.onLocalServerDenied?.(i);break;case "gem.player":{this.options.onPlayer?.(be(i));break}case "gem.deviceSettings.result":this.options.onDeviceSettingsResult?.(i);break;case "gem.error":this.options.onError?.(i.code,i.message);break;default:if(Oe.includes(r.slice(4))){this.options[`on${r[4].toUpperCase()}${r.slice(5)}`]?.(i);break}if(ke.includes(C(r))){this.options.onArcadeAnswer?.(i);break}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 oe(n){for(let e of n)try{e?.close?.();}catch{}}N();function Pe(n){if((n.expectedSource??window.parent)===window)throw new Error("GemWebSdkBridge.connect: this document is not framed (window.parent === window), so there is no embedder to hand it a port. A game runs inside the Gem Arcade iframe; opening it directly will never complete a handshake.");let e=new O({...n,expectedSource:n.expectedSource??window.parent}),t=r=>{let o=e.handleWindowMessage({data:r.data,origin:r.origin,source:r.source,ports:r.ports});return o&&window.removeEventListener("message",t),o};return window.addEventListener("message",t),W(window,t),e}var se={connect:Pe,GemFrame:O,PROTOCOL:l,SUPPORTED_VERSIONS:S};window.GemWebSdkBridge=se;var xn=se;return xn;})();
|
|
1
|
+
var GemWebSdkBridgeBundle=(function(){'use strict';var j="GemWebSdkHandshake";function ie(){return typeof document>"u"?void 0:document.readyState}var B=()=>Date.now();function N(n={}){let e=n.win??window,t=e,r=t[j];if(r!==void 0)return r;let o=n.readyState??ie,s=n.now??B,m=[],i=[],u=y=>{let c=y.data;!c||c.type!=="gem.handshake"||(m.length>=4&&(m.shift(),i.shift(),p.dropped+=1),m.push(y),i.push(s()));};e.addEventListener("message",u);let p={events:m,times:i,dropped:0,late:o()==="complete",uninstall(){e.removeEventListener("message",u);}};return t[j]=p,p}function W(n,e,t={}){let r=n[j];if(r===void 0)return null;let o=t.ttlMs??9500,s=t.now??B,m=r.events.splice(0),i=r.times?.splice(0),u=0,p=0,y=false,c=s()-o;for(let h=m.length-1;h>=0;h--){let R=i?.[h];if(R!==void 0&&R<c){p+=1;continue}if(u+=1,e(m[h])===true){y=true;break}}return r.uninstall(),{capture:r,delivered:u,stale:p,accepted:y}}var l="gem-web-bridge",S={min:1,max:1},le=65536,z=8,x=5e3,V=1024;var w=Object.create(null),P="__malformed";var F=Object.create(null),de=Object.freeze([["gem.asyncOpponents.","asyncOpponents"],["gem.vibration.","vibration"],["gem.viewport.","reservedAreas"],["gem.moments.","moments"],["gem.prefs.","audioChannels"],["gem.share.","shareRemap"]]);function C(n){let e=F[n];if(e!==void 0)return e;for(let[t,r]of de)if(n.startsWith(t))return r}function me(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 ue(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 ce(n){return /^[a-z]{2,8}(-[a-z0-9]{1,8})*$/i.test(n)}function ge(n){return /^[a-z_]+$/.test(n)}function pe(n){return /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(n)||/^[a-z0-9][a-z0-9-]{1,38}[a-z0-9]$/.test(n)&&!n.includes("--")}function D(n,e,t){if(e>z)return `nesting deeper than ${z}`;if(++t.nodes>x)return `more than ${x} values`;if(t.bytes>t.cap)return `over the ${t.cap} 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 o=n;if(t.seen.has(o))return "a repeated or cyclic object reference";if(t.seen.add(o),Array.isArray(n)){if(n.length>V)return `an array of ${n.length} entries, over the ${V} limit`;t.bytes+=2;for(let i of n){let u=D(i,e+1,t);if(u)return u}return null}let s=Object.getPrototypeOf(n);if(s!==Object.prototype&&s!==null)return "a value that is not a plain object";t.bytes+=2;let m=n;for(let i in m){if(!Object.prototype.hasOwnProperty.call(m,i))continue;if(++t.nodes>x)return `more than ${x} values`;if(t.bytes+=i.length*3+4,t.bytes>t.cap)return `over the ${t.cap} byte limit`;let u=D(m[i],e+1,t);if(u)return u}return null}function ye(n,e=le){let t={nodes:0,bytes:0,seen:new Set,cap:e},r=D(n,0,t);return r?`message contains ${r}`:t.bytes>e?`message is over the ${e} byte limit`:null}var fe={origin:[me,"not a well-formed origin"],url:[ue,"not a safe absolute http(s) URL"],bcp47:[ce,"not a well-formed BCP 47 tag"],code:[ge,"not a code of lower-case letters and underscores"],gameRef:[pe,"not a game id or web address"]};function K(n,e,t){for(let r of e){let o=t===""?r[0]:`${t}.${r[0]}`,s=n[r[0]];if(s==null){if(r[1]<"a")continue;return `${o}: required`}let m=M(s,r,o);if(m)return m}return null}function M(n,e,t){let r=e[1].toLowerCase();switch(r){case "u":return typeof n=="boolean"?null:M(n,typeof n=="string"?[e[0],"s",e[2]]:[e[0],"n",e[3],e[4]],t);case "s":{if(typeof n!="string")return `${t}: expected string`;if(n.length>e[2])return `${t}: exceeds ${e[2]} characters`;if(e[3]){let[o,s]=fe[e[3]];if(!o(n))return `${t}: ${s}`}return null}case "n":case "i":return typeof n!="number"||!(r=="i"?Number.isInteger:Number.isFinite)(n)?`${t}: expected ${r=="i"?"integer":"number"}`:n<e[2]||n>e[3]?`${t}: out of range ${e[2]}..${e[3]}`:null;case "b":return typeof n=="boolean"?null:`${t}: expected boolean`;case "e":{let o=e[2];return o.includes(n)?null:`${t}: not one of ${o.join("|")}`}case "o":return typeof n!="object"||n===null||Array.isArray(n)?`${t}: expected object`:K(n,e[2],t);case "j":return typeof n!="object"||n===null||Array.isArray(n)?`${t}: expected a plain object`:null;case "a":{if(!Array.isArray(n))return `${t}: expected array`;if(n.length>e[2])return `${t}: exceeds ${e[2]} items`;let o=e[3],s=`${t}[]`;for(let m of n){if(m==null){if(o[1]<"a")continue;return `${s}: required`}let i=M(m,o,s);if(i)return i}return null}default:return `${t}: unknown kind ${String(r)}`}}var Y=Object.create(null);function a(n,e,t,r,o){return w[n]=t,r&&(F[n]=r),Y[n]=s=>{let m=ye(s,o);if(m)return m;if(typeof s!="object"||s===null||Array.isArray(s))return "message: expected object";let i=s;return i.gem!==l?"gem: wrong protocol marker":i.type!==n?`type: expected ${n}`:K(i,e,"")}}var G=["","s",64],d=["requestId","s",64],b=["matchId","s",64],f=["reason","S",64,"code"],v=["outcome","e",["ok","declined","unavailable"]];a("gem.handshake",[["versions","o",[["min","i",1,1e3],["max","i",1,1e3]]],["capabilities","A",64,G],["embedder","s",2048,"origin"],["unbidden","B"]],30);a("gem.handshake.accept",[["v","i",1,1e3],["capabilities","A",64,G]],5);a("gem.token",[["token","s",4096],["requestId","S",64],["generation","i",0,2147483647],["apiBaseUrl","S",512,"url"],["playerId","s",64],["gameId","s",64],["channel","e",["dev","test","release"]],["gameVersion","S",64],["expiresAt","i",0,4102444800],["chainEndsAt","i",0,4102444800],["allowDevTools","B"]],30);a("gem.token.denied",[d,["retryable","b"],["retryAfterMs","I",0,36e5],["reason","e",["chain_exhausted","unavailable"]],["correlationId","s",64]],30);a("gem.player",[["untrusted","o",[["displayName","s",64],["displayTag","S",80],["displayHandle","s",80]]],["playerId","S",64],["discriminator","S",8],["avatarIconUrl","S",2048,"url"],["avatarIconId","S",64],["avatar3dId","S",64],["avatar3dModelUrl","S",2048,"url"],["avatar3dIconUrl","S",2048,"url"],["avatars3d","A",8,["","o",[["family","s",32],["id","s",64],["modelUrl","s",256,"url"],["iconUrl","s",256,"url"]]]],["badges","A",2,["","o",[["itemId","s",64],["iconUrl","s",2048,"url"]]]],["displayTag","s",8],["avatarUrl","S",2048,"url"],["boost","O",[["multipliers","a",8,["","o",[["currencyId","s",64],["currencySlug","s",32],["multiplierBp","i",1e4,1e6]]]],["expiresInDays","I",1,7]]]],12);a("gem.pause",[["paused","b"]],120);a("gem.prefs",[["reducedMotion","b"],["muted","b"],["showFrameStats","B"],["music","B"],["sounds","B"],["locale","s",35,"bcp47"],["recommended","O",[["volume","i",0,100],["batterySaver","b"],["keyboardLayout","e",["wasd","arrows"]],["gamepadConfirm","e",["south","east"]],["vibration","b"],["lookSensitivity","I",20,400],["gamepadLookSensitivity","I",20,400],["invertLookY","B"],["touchMovement","S",16,"code"],["graphicsQuality","S",16,"code"],["graphicsQualityAuto","B"],["colorHelp","B"]]]],60);a("gem.cohorts",[["cohorts","a",8,["","o",[["experimentId","s",36],["variantKey","s",32]]]]],12,"cohorts");a("gem.earnAllowanceChanged",[],30,"earnAllowance");a("gem.inventoryChanged",[],30,"inventoryChanged");a("gem.viewport",[["insets","o",[["top","i",0,4096],["right","i",0,4096],["bottom","i",0,4096],["left","i",0,4096]]],["reserved","A",4,["","o",[["x","i",0,16384],["y","i",0,16384],["width","i",0,16384],["height","i",0,16384],["control","O",[["x","i",0,16384],["y","i",0,16384],["width","i",0,16384],["height","i",0,16384]]]]]]],60,"viewport");a("gem.deviceSettings",[["settings","J"]],12,"deviceSettings");a("gem.willTerminate",[["reason","e",["grant_expiring","session_ended","navigating","kill_switch"]],["graceMs","i",0,6e4]],10);a("gem.roomEvent",[["event","e",["updated","match_started","match_ready","match_failed","version_stale"]],["roomId","s",64],["matchId","S",64],["version","I",0,2147483647],["reason","S",64],["platform","E",["universal","mobile"]]],120,"rooms");a("gem.socketState",[["connected","b"],["reason","E",["connecting","dropped","watchdog","terminal"]]],12,"socketState");a("gem.seatedEvent",[["roomId","s",64]],60,"partySeating");a("gem.autoStartFailedEvent",[["roomId","s",64],["code","s",64]],30,"autoStartFailure");a("gem.ticketEvent",[["event","e",["queued","matched","expired","cancelled","failed"]],["ticketId","s",64],["partySize","I",1,64],["queuedAt","I",0,4102444800],["expiresAt","I",0,4102444800],["reason","S",64],["roomId","S",64]],60,"ticketEvents");a("gem.signalEvent",[["event","e",["hello","offer","answer","ice","peerJoined","peerLeft","migration","matchEnded","error"]],b,["data","j"]],1800,"p2p");a("gem.relayDraining",[b,["clusterTargetId","s",64],["relayIps","a",16,G],["drainingSince","s",40],["deadline","s",40]],60,"p2pRelayDrain");a("gem.dedicatedEvent",[["event","e",["answer","error","matchEnded"]],b,["sdp","S",10240],["sessionId","S",64],["code","S",64],["message","S",256],["reason","S",64]],120,"dedicated");a("gem.partyResult",[d,["partyId","S",64]],30,"parties");a("gem.clusterTarget",[["clusterTargetId","s",64],["clusterTargetIds","A",3,G]],12,"clusterTarget");a("gem.graphicsRoutes",[["entries","a",32,["","o",[["gpu","s",32],["route","S",32],["host","S",32]]]]],12,"graphicsRoutes");a("gem.devtools",[["action","e",["open","close","toggle"]]],30,"devtools");a("gem.screenshot",[["maxWidth","i",1,7680],["maxHeight","i",1,4320]],6,"screenshot");a("gem.screenshot.denied",[["reason","e",["not_wired","no_source","unsupported","unreadable","tainted","too_large","busy","declined","failed"]],["retryable","b"]],12,"screenshot");a("gem.requestContext",[],12,"feedbackContext");a("gem.gameContext",[["context","j"]],12,"feedbackContext");a("gem.signal",[["signal","e",["join","offer","answer","ice","migrationAck","hostUnreachable"]],b,["data","j"]],1200,"p2p");a("gem.dedicatedOffer",[b,["sdp","s",10240],["intent","e",["initial","ice_restart","full_reconnect"]]],60,"dedicated");a("gem.partyRequest",[d],12,"parties");a("gem.ready",[],5);a("gem.engaged",[],5,"engagement");a("gem.progress",[["loaded","i",0,1099511627776],["total","i",0,1099511627776]],600);a("gem.requestToken",[d,["reason","e",["initial","expiring","rejected"]]],12);a("gem.requestLocalServer",[d,["gameRoomId","s",64]],6,"localHost");a("gem.localServer",[d,["serverId","S",128]],30,"localHost");a("gem.localServer.denied",[d,["retryable","b"],["reason","e",["refused","unavailable"]]],30,"localHost");a("gem.exit",[["reason","S",64]],5);a("gem.openExternal",[["url","s",2048,"url"]],6);a("gem.requestFullscreen",[["enabled","b"]],30);a("gem.audioState",[["muted","b"]],120,"audioState");a("gem.rewardCue",[["currencySlug","s",32],["cueId","S",64],["expected","I",1,1e9],["origin","O",[["x","i",0,16384],["y","i",0,16384]]]],60,"rewardCue");a("gem.rewardPresentation",[["mode","e",["arcade","game"]]],12,"rewardPresentation");a("gem.walletDisplay",[["visible","b"],["currencies","A",8,G],["score","B"]],60,"walletDisplay");a("gem.controlsDeclare",[["uses","o",[["lookSensitivity","S",16,"code"],["gamepadLookSensitivity","S",16,"code"],["invertLookY","S",16,"code"],["touchMovement","S",16,"code"]]]],60,"controls");a("gem.menu",[["settings","b"],["items","A",4,["","o",[["id","s",32],["label","s",40]]]]],60,"gameMenu");a("gem.menuSelect",[["entry","e",["settings","item"]],["id","S",32]],60,"gameMenu");a("gem.gemCorner",[["corner","e",["top-left","top-right","bottom-left","bottom-right"]]],12,"gemCorner");a("gem.menuStyle",[["ground","S",7],["accent","S",7]],12,"menuStyle");a("gem.settingsDeclare",[["settings","a",8,["","o",[["id","s",40],["label","s",40],["kind","e",["toggle","slider","choice"]],["value","u",40,-1e6,1e6],["quick","B"],["icon","S",16,"code"],["min","N",-1e6,1e6],["max","N",-1e6,1e6],["step","N",0,1e6],["options","A",4,["","o",[["id","s",40],["label","s",40]]]]]]]],120,"gameSettings");a("gem.settingChange",[["id","s",40],["value","u",40,-1e6,1e6]],120,"gameSettings");a("gem.requestShare",[["requestId","S",64],["params","a",16,["","o",[["key","s",64],["value","s",512]]]]],6,"share");a("gem.shareResult",[d,["outcome","e",["accepted","refused"]],f,["key","S",64]],30,"shareResult");a("gem.requestAvatarPicker",[["tab","E",["2d","3d"]]],6,"avatarPicker");a("gem.vibrate",[["pattern","a",99,["","i",0,1e4]]],600,"vibration");a("gem.frameStats",[["fps","i",0,1e3],["frameTimeP95Ms","i",0,1e5],["counts","E",["pageFrames","gameDraws"]]],120,"frameStats");a("gem.portraitBorders",[["name","S",40]],60,"portraitBorders");a("gem.error",[["code","e",["version_mismatch","handshake_timeout","handshake_duplicate","invalid_message","rate_limited","token_unavailable","unsupported","unsupported_capability","internal"]],["message","S",256]],60);a("gem.requestPurchase",[d,["purchaseKind","e",["item","recipe"]],["targetId","s",64],["currencySlug","s",32],["quantity","I",1,10],["catalogId","S",64],["origin","E",["sheet","direct_refused"]]],12,"purchases");a("gem.requestAvatar3dPurchase",[d,["itemId","s",64],["currencySlug","s",32]],12,"avatar3dPurchases");a("gem.purchaseResult",[d,v,f,["purchaseId","S",64]],30,"purchases");a("gem.purchaseSettled",[["purchaseKind","e",["item","recipe"]],["targetId","s",64],["catalogId","S",64],["quantity","i",1,10],["purchaseId","S",64]],30,"purchaseSettled");a("gem.deviceSettings.put",[d,["settings","j"]],30,"deviceSettings");a("gem.deviceSettings.result",[d,["outcome","e",["stored","too_large","unavailable"]]],30,"deviceSettings");a("gem.requestAd",[d,["placement","s",32],["format","e",["interstitial","rewarded"]]],6,"ads");a("gem.adResult",[d,["outcome","e",["shown","no_ad","unavailable"]]],12,"ads");a("gem.signalMoment",[d,["kind","e",["level_end","run_end","match_end","menu_return","other_break"]],["placement","S",32],["wall","B"]],6,"moments");a("gem.momentResult",[d,["shown","b"]],12,"moments");a("gem.requestSignIn",[d],6,"signIn");a("gem.signInResult",[d,["outcome","e",["signed_in","declined","unavailable"]]],12,"signIn");a("gem.requestFriendChallenge",[d,["playerId","s",64],["template","s",64],["params","J"]],12,"friendChallenges");a("gem.friendChallengeResult",[d,["outcome","e",["accepted","cancelled","refused","unavailable","rate_limited","invalid"]],["code","S",64],["param","S",64],["channel","S",16],["configVersion","I",0,9007199254740991],["retryAfterMs","I",0,864e5],["detail","S",300]],30,"friendChallenges");a("gem.requestPlayInvite",[d,["params","A",16,["","o",[["key","s",64],["value","s",512]]]]],6,"playInvites");a("gem.playInviteResult",[d,["shown","b"]],12,"playInvites");a("gem.inviteParams",[["params","A",16,["","o",[["key","s",64],["value","s",512]]]]],30,"playInvites");a("gem.requestAppLinks",[d],12,"appLinks");a("gem.appLinksResult",[d,v,f,["arcade","O",[["store","e",["app_store","google_play"]]]],["game","O",[["store","e",["app_store","google_play"]]]]],30,"appLinks");a("gem.requestOpenApp",[d,["target","e",["arcade","game"]]],6,"appLinks");a("gem.openAppResult",[d,v,f],30,"appLinks");a("gem.requestOpenGame",[d,["ref","s",40,"gameRef"]],6,"openGame");a("gem.openGameResult",[d,v,f],30,"openGame");a("gem.requestSimilarGames",[d,["limit","I",1,24]],12,"openGame");a("gem.similarGamesResult",[d,v,f,["games","a",24,["","o",[["gameId","s",36,"gameRef"],["slug","S",40,"gameRef"],["iconUrl","s",1024,"url"],["capsuleLandscapeUrl","s",1024,"url"],["capsulePortraitUrl","s",1024,"url"],["previewVideoUrl","S",1024,"url"],["previewPosterUrl","S",1024,"url"],["untrusted","o",[["name","s",64],["tagline","s",64],["shortDescription","s",320],["tags","a",10,["","s",32]]]]]]]],30,"openGame",524288);a("gem.requestStoreOffers",[d],12,"store");a("gem.storeOffersResult",[d,v,f,["offers","a",32,["","o",[["skuId","s",64],["kind","e",["gem_pack","boost","pass","bundle"]],["name","s",80],["description","s",400],["imageUrl","S",1024,"url"],["priceDisplay","s",32],["grant","O",[["currency","s",32],["amount","i",1,1e9]]]]]]],30,"store",262144);a("gem.requestStorePurchase",[d,["skuId","s",64]],12,"store");a("gem.storePurchaseResult",[d,v,f],30,"store");a("gem.storePurchaseSettled",[["skuId","s",64]],30,"store");a("gem.requestStoreOfferSheet",[d,["skuId","s",64]],12,"storeOfferSheet");a("gem.storeOfferSheetResult",[d,v,f],30,"storeOfferSheet");var I=Object.freeze(Y);w.__malformed=60;Object.freeze(w);Object.freeze(F);var he=/^[a-z0-9][a-z0-9_-]{0,39}$/;function ve(n){return typeof n=="string"&&he.test(n)}function J(n){if(n===null||ve(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.`);}function Q(n){return typeof n=="string"&&/^[\w-]{1,64}$/.test(n)}var $={now:()=>Date.now(),setTimeout:(n,e)=>setTimeout(n,e),clearTimeout:n=>clearTimeout(n)},O=class{constructor(e=$){this.clock=e;}clock;tokens=new Map;lastRefill=new Map;allow(e){let t=w[e];if(t===void 0)return false;let r=this.clock.now(),o=this.lastRefill.get(e)??r,s=this.tokens.get(e)??t,m=Math.max(0,r-o),i=Math.min(t,s+m*t/6e4);return i<1?(this.tokens.set(e,i),this.lastRefill.set(e,r),false):(this.tokens.set(e,i-1),this.lastRefill.set(e,r),true)}};function q(n,e){return n.toLowerCase()===e.toLowerCase()}function T(n){let e=n.toLowerCase();return e==="localhost"||e.endsWith(".localhost")||e==="[::1]"||e==="::1"?true:/^127(\.\d{1,3}){3}$/.test(e)}function X(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(t.hostname)&&T(r.hostname)}function Z(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}var ne="[gem: use gem.text.toPlain()]",ee=new Set,te;function Re(n){try{if(ee.has(n))return;let e=globalThis.location;if(te??=!!e?.port&&T(e.hostname??""),!te)return;ee.add(n),console.warn(`[gem] ${n} is PlayerText, turned into a string: players see ${ne}. Render text.toPlain(value) (text is in @indiegems/gem-web-sdk/sdk).
|
|
2
|
+
${new Error().stack}`);}catch{}}var U=class{#e;#t;constructor(e,t="player text"){this.#e=e,this.#t=t,Object.freeze(this);}toString(){return Re(this.#t),ne}toJSON(){return this.toString()}get[Symbol.toStringTag](){return "PlayerText"}static unwrap(e){return e.#e}};function H(n,e){return new U(n,e)}function re(n){return Math.min(16384,Math.max(0,Math.round(Number.isFinite(n)?n:0)))}function Se(n,e){if(n!==true)return {visible:false};let t=[],r=false;for(let o of Array.isArray(e)?e:[])o==="score"?r=true:typeof o=="string"&&o.length>0&&o.length<=64&&!t.includes(o)&&t.push(o);return !r&&t.length===0?{visible:true}:{visible:true,currencies:t.slice(0,8),score:r}}function we(n){let e=[];for(let t of Array.isArray(n)?n:[]){if(e.length===4)break;if(typeof t!="object"||t===null)continue;let{id:r,label:o}=t;typeof r!="string"||r.length===0||r.length>32||typeof o!="string"||o.trim().length===0||e.some(s=>s.id===r)||e.push({id:r,label:o.trim().slice(0,40)});}return e.length===0?{settings:false}:{settings:false,items:e}}function ae(n,e){return Math.min(e,Math.max(0,Math.round(Number.isFinite(n)?n:0)))}function Ge(n){let e=n.untrusted,t=H(e.displayName,"gem.player.displayName"),r=e.displayTag||e.displayHandle,o=r?H(r,"gem.player.displayTag"):void 0,s=n.discriminator||n.displayTag,m=s&&/^[0-9]{1,8}$/.test(s)?s:void 0,i=n.avatarIconUrl||n.avatarUrl,u=/^[\da-f]{8}(-[\da-f]{4}){3}-[\da-f]{12}$/i,p=n.avatarIconId,y=n.avatar3dId,c={displayName:t,displayHandle:o??t,badges:(n.badges??[]).map(g=>({itemId:g.itemId,iconUrl:g.iconUrl}))};n.playerId&&(c.playerId=n.playerId),m&&(c.discriminator=m),o&&(c.displayTag=o),i&&(c.avatarIconUrl=c.avatarUrl=i),p&&u.test(p)&&(c.avatarIconId=p),y&&u.test(y)&&(c.avatar3dId=y),n.avatar3dModelUrl&&(c.avatar3dModelUrl=n.avatar3dModelUrl),n.avatar3dIconUrl&&(c.avatar3dIconUrl=n.avatar3dIconUrl),n.avatars3d&&(c.avatars3d=n.avatars3d.filter(g=>u.test(g.id)&&/^[a-z][a-z0-9_]*$/.test(g.family)).filter((g,E,L)=>L.findIndex(_=>_.family==g.family)==E).map(({family:g,id:E,modelUrl:L,iconUrl:_})=>({family:g,id:E,modelUrl:L,iconUrl:_})));let h=n.boost,R=(h?.multipliers??[]).map(g=>({currencyId:g.currencyId,currencySlug:g.currencySlug,multiplier:g.multiplierBp/1e4})),A=R.some(g=>g.multiplier>1);return c.boost=A&&h?.expiresInDays?{active:A,multipliers:R,expiresInDays:h.expiresInDays}:{active:A,multipliers:R},c}var be=1e4,Oe=["appLinks","openGame","store","storeOfferSheet"],ke=["token","pause","menuSelect","settingChange","prefs","cohorts","viewport","willTerminate","localServer","roomEvent","seatedEvent","autoStartFailedEvent","ticketEvent","socketState","signalEvent","relayDraining","dedicatedEvent","clusterTarget","graphicsRoutes","partyResult","purchaseResult","purchaseSettled","inventoryChanged","shareResult","deviceSettings","adResult","momentResult","signInResult","friendChallengeResult","playInviteResult"],xe=new WeakMap;var 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??$,this.inbound=new O(this.clock),this.outbound=new O(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(i=>q(i,e.origin))||X(e.origin,this.options.selfOrigin)||(xe.get(this)??[]).some(i=>q(i,e.origin))))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=I["gem.handshake"]?.(e.data);if(r)return this.refuse(e,`malformed handshake: ${r}`),false;let o=e.data;if(!q(o.embedder,e.origin))return this.refuse(e,`handshake claims embedder '${o.embedder}' but arrived from '${e.origin}'`),false;let s=e.ports?.[0];if(!s)return this.refuse(e,"handshake transferred no MessagePort"),false;let m=Z(S,o.versions);return m===null?(s.onmessage=null,s.postMessage({gem:l,type:"gem.error",code:"version_mismatch",message:`frame supports v${S.min}..v${S.max}`}),s.close(),this.transition("refused"),this.options.onError?.("version_mismatch"),false):(this.port=s,this.version=m,s.onmessage=i=>this.receive(i.data,i.ports??[]),s.start?.(),this.peerCapabilities=o.capabilities??[],this.unbidden=o.unbidden===true,s.postMessage({gem:l,type:"gem.handshake.accept",v:m,...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=be){return this.state!=="waiting"?Promise.resolve(this.state):new Promise(t=>{let r=s=>{this.clock.clearTimeout(o),t(s);},o=this.clock.setTimeout(()=>{let s=this.settleWaiters.indexOf(r);s>=0&&this.settleWaiters.splice(s,1),t(this.state);},e);this.settleWaiters.push(r);})}progress(e,t){this.send({gem:l,type:"gem.progress",loaded:e,total:t});}requestToken(e,t){this.send({gem:l,type:"gem.requestToken",requestId:e,reason:t});}requestLocalServer(e,t){return this.parentSupports("localHost")?(this.send({gem:l,type:"gem.requestLocalServer",requestId:e,gameRoomId:t}),true):false}exit(e){this.send(e===void 0?{gem:l,type:"gem.exit"}:{gem:l,type:"gem.exit",reason:e});}openExternal(e){this.send({gem:l,type:"gem.openExternal",url:e});}requestFullscreen(e){this.send({gem:l,type:"gem.requestFullscreen",enabled:e});}reportMuted(e){return this.gated("audioState")?(this.send({gem:l,type:"gem.audioState",muted:e}),true):false}reportEngaged(){return this.engagedSent||!this.gated("engagement")||!this.send({gem:l,type:"gem.engaged"})?false:(this.engagedSent=true,true)}cueReward(e){if(!this.gated("rewardCue"))return false;let t={gem:l,type:"gem.rewardCue",currencySlug:String(e.currencySlug).slice(0,32)};return Q(e.cueId)&&(t.cueId=e.cueId),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:re(e.origin.x),y:re(e.origin.y)}),this.send(t),true}showPortraitBorders(e){let t=J(e);return t===void 0||!this.gated("portraitBorders")?false:this.send(t===null?{gem:l,type:"gem.portraitBorders"}:{gem:l,type:"gem.portraitBorders",name:t})}setWalletVisible(e,t){return this.gated("walletDisplay")?this.send({gem:l,type:"gem.walletDisplay",...Se(e,t?.only)}):false}setMenu(e){return this.gated("gameMenu")?this.send({gem:l,type:"gem.menu",...we(e)}):false}declareSettings(e){return this.gated("gameSettings")?this.send({gem:l,type:"gem.settingsDeclare",settings:e}):false}setGemCorner(e){return this.gated("gemCorner")?this.send({gem:l,type:"gem.gemCorner",corner:e}):false}setRewardPresentation(e){return this.gated("rewardPresentation")?this.send({gem:l,type:"gem.rewardPresentation",mode:e}):false}setMenuStyle(e){return this.gated("menuStyle")?this.send(e===null?{gem:l,type:"gem.menuStyle"}:{gem:l,type:"gem.menuStyle",ground:e.ground,accent:e.accent}):false}requestShare(e,t){return this.gated("share")?this.send({gem:l,type:"gem.requestShare",...t===void 0?{}:{requestId:t},params:e.map(({key:r,value:o})=>({key:r,value:o}))}):false}requestAvatarPicker(e){return this.gated("avatarPicker")?this.send({gem:l,type:"gem.requestAvatarPicker",...e==="2d"||e==="3d"?{tab:e}:{}}):false}requestVibrate(e){return this.gated("vibration")?this.send({gem:l,type:"gem.vibrate",pattern:[...e]}):false}reportFrameStats(e){return this.gated("frameStats")?(this.send({gem:l,type:"gem.frameStats",fps:ae(e.fps,1e3),frameTimeP95Ms:ae(e.frameTimeP95Ms,1e5),counts:e.counts==="gameDraws"?"gameDraws":"pageFrames"}),true):false}sendGameContext(e){return this.state!=="connected"?false:(this.send({gem:l,type:"gem.gameContext",context:e}),true)}signal(e,t,r){this.send({gem:l,type:"gem.signal",signal:e,matchId:t,data:r});}dedicatedOffer(e,t,r){this.send({gem:l,type:"gem.dedicatedOffer",matchId:e,sdp:t,intent:r});}requestParty(e){return this.send({gem:l,type:"gem.partyRequest",requestId:e})}requestPurchase(e,t,r,o,s,m,i){return this.send({gem:l,type:"gem.requestPurchase",requestId:e,purchaseKind:t,targetId:r,currencySlug:o,...s===void 0?{}:{quantity:s},...m===void 0?{}:{catalogId:m},...i===void 0?{}:{origin:i}})}requestAvatar3dPurchase(e,t,r){return this.parentSupports("avatar3dPurchases")?this.send({gem:l,type:"gem.requestAvatar3dPurchase",requestId:e,itemId:t,currencySlug:r}):false}putDeviceSettings(e,t){return this.send({gem:l,type:"gem.deviceSettings.put",requestId:e,settings:t})}requestAd(e,t,r){return this.send({gem:l,type:"gem.requestAd",requestId:e,placement:t,format:r})}signalMoment(e,t,r,o){return this.send({gem:l,type:"gem.signalMoment",requestId:e,kind:t,...r===void 0?{}:{placement:r},...o===true?{wall:true}:{}})}readyCalled(){return this.readySent||this.readyPending}requestSignIn(e){return this.send({gem:l,type:"gem.requestSignIn",requestId:e})}requestFriendChallenge(e,t,r,o){return this.send({gem:l,type:"gem.requestFriendChallenge",requestId:e,playerId:t,template:r,...o===void 0?{}:{params:o}})}requestArcade(e){return this.gated(C(e.type))&&this.send({gem:l,...e})}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(P)){this.options.onDropped?.(e,t);return}this.fail(e,t);}dropUnknownType(e){this.inbound.allow(P)&&this.options.onDropped?.("unsupported",`ignored unknown message type '${e}'`);}refuse(e,t){e.ports?.[0]?.close?.(),this.inbound.allow(P)&&this.options.onRefused?.(t);}fail(e,t){this.options.onError?.(e,t),this.state==="connected"&&this.port&&this.send({gem:l,type:"gem.error",code:e,...t===void 0?{}:{message:t}});}gated(e){return this.state==="connected"&&this.parentSupports(e)}send(e){if(this.state!=="connected"||!this.port)return this.options.onDropped?.("internal",`dropped ${String(e.type)} before connect`),false;let t=e.type;if(!this.outbound.allow(t))return this.options.onError?.("rate_limited",`frame exceeded its own limit for ${t}`),false;let r=I[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||oe(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 o=I[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 s=C(r);if(s!==void 0&&!this.options.capabilities?.includes(s))return this.fail("unsupported_capability",`${r} requires the '${s}' capability, which this frame did not advertise`),false;let m=o(e);if(m)return this.fail("invalid_message",`${r}: ${m}`),false;let i=e;if(i.v!==this.version)return this.fail("invalid_message",`${r}: expected v ${String(this.version)}`),false;switch(r){case "gem.earnAllowanceChanged":this.options.onEarnAllowanceChanged?.();break;case "gem.devtools":this.options.onDevtools?.(i.action);break;case "gem.requestContext":this.options.onRequestContext?.();break;case "gem.screenshot":{let u=t[0];if(!u){this.options.onError?.("invalid_message","gem.screenshot transferred no MessagePort");break}let p={maxWidth:i.maxWidth,maxHeight:i.maxHeight};if(!this.options.onScreenshot){u.close(),this.screenshotDenied("not_wired",false);break}return oe(t.slice(1)),this.options.onScreenshot(p,u,(y,c)=>this.screenshotDenied(y,c)),true}case "gem.token.denied":this.options.onTokenDenied?.(i);break;case "gem.localServer.denied":this.options.onLocalServerDenied?.(i);break;case "gem.player":{this.options.onPlayer?.(Ge(i));break}case "gem.deviceSettings.result":this.options.onDeviceSettingsResult?.(i);break;case "gem.error":this.options.onError?.(i.code,i.message);break;default:if(ke.includes(r.slice(4))){this.options[`on${r[4].toUpperCase()}${r.slice(5)}`]?.(i);break}if(Oe.includes(C(r))){this.options.onArcadeAnswer?.(i);break}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 oe(n){for(let e of n)try{e?.close?.();}catch{}}N();function Pe(n){if((n.expectedSource??window.parent)===window)throw new Error("GemWebSdkBridge.connect: this document is not framed (window.parent === window), so there is no embedder to hand it a port. A game runs inside the Gem Arcade iframe; opening it directly will never complete a handshake.");let e=new k({...n,expectedSource:n.expectedSource??window.parent}),t=r=>{let o=e.handleWindowMessage({data:r.data,origin:r.origin,source:r.source,ports:r.ports});return o&&window.removeEventListener("message",t),o};return window.addEventListener("message",t),W(window,t),e}var se={connect:Pe,GemFrame:k,PROTOCOL:l,SUPPORTED_VERSIONS:S};window.GemWebSdkBridge=se;var Tn=se;return Tn;})();
|