@indiegems/gem-web-sdk 16.3.1 → 17.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +27 -0
- package/dist/conformance.d.ts +1 -1
- package/dist/game.d.ts +17 -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 +2 -2
- 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 +1 -1
- package/dist/index.d.ts +27 -8
- package/dist/sdk.d.ts +17 -2
- package/docs/api/api-reference-function.md +1 -1
- package/docs/api/api-reference-game.md +55 -3
- package/docs/api/api-reference-server.md +1 -1
- package/docs/api/reference.json +41 -2
- package/docs/arcade-and-store.md +70 -10
- package/docs/arcade-economy.md +6 -5
- package/docs/changelog.md +27 -0
- package/docs/getting-started.md +1 -1
- package/docs/inventory-and-catalogs.md +3 -2
- package/docs/manifest.json +12 -12
- package/docs/server-bundles.md +2 -2
- package/package.json +1 -1
- package/schema/bridge.v1.json +108 -0
- package/schema/capabilities.public.json +7 -0
package/CHANGELOG.md
CHANGED
|
@@ -16,6 +16,33 @@ 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
|
+
## 17.0.0
|
|
20
|
+
|
|
21
|
+
*Written from the API facts alone; no summary was generated for this release.*
|
|
22
|
+
|
|
23
|
+
Upgrading from 16.3.1. Impact: required.
|
|
24
|
+
|
|
25
|
+
### Must change
|
|
26
|
+
|
|
27
|
+
- PARENT_CONFORMANCE_VERSION changed its signature.
|
|
28
|
+
- FRAME_TO_PARENT changed its signature.
|
|
29
|
+
- FrameMessage changed its signature.
|
|
30
|
+
- GemCapability changed its signature.
|
|
31
|
+
- PARENT_TO_FRAME changed its signature.
|
|
32
|
+
- ParentMessage changed its signature.
|
|
33
|
+
|
|
34
|
+
### New capability
|
|
35
|
+
|
|
36
|
+
- StoreApi.showOffer was added.
|
|
37
|
+
- StoreApi.showOfferAvailable was added.
|
|
38
|
+
- GemHost.answerStoreOfferSheet was added.
|
|
39
|
+
- GemRequestStoreOfferSheet was added.
|
|
40
|
+
- GemStoreOfferSheetResult was added.
|
|
41
|
+
- HostCallbacks.onRequestStoreOfferSheet was added.
|
|
42
|
+
- HostOptions.onRequestStoreOfferSheet was added.
|
|
43
|
+
- validateGemRequestStoreOfferSheet was added.
|
|
44
|
+
- validateGemStoreOfferSheetResult was added.
|
|
45
|
+
|
|
19
46
|
## 16.3.1
|
|
20
47
|
|
|
21
48
|
Upgrading from 16.3.0. Impact: none.
|
package/dist/conformance.d.ts
CHANGED
|
@@ -50,7 +50,7 @@ interface ParentConformanceResult {
|
|
|
50
50
|
readonly ok: boolean;
|
|
51
51
|
readonly message?: string;
|
|
52
52
|
}
|
|
53
|
-
declare const PARENT_CONFORMANCE_VERSION =
|
|
53
|
+
declare const PARENT_CONFORMANCE_VERSION = 3;
|
|
54
54
|
declare const PARENT_CONFORMANCE_CASES: readonly ParentConformanceCase[];
|
|
55
55
|
declare function runParentConformance(factory: ParentFactory, options: ParentConformanceOptions): Promise<readonly ParentConformanceResult[]>;
|
|
56
56
|
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/game.d.ts
CHANGED
|
@@ -2464,6 +2464,19 @@ interface GemStorePurchaseSettled {
|
|
|
2464
2464
|
readonly type: "gem.storePurchaseSettled";
|
|
2465
2465
|
readonly skuId: string;
|
|
2466
2466
|
}
|
|
2467
|
+
interface GemRequestStoreOfferSheet {
|
|
2468
|
+
readonly gem: typeof PROTOCOL;
|
|
2469
|
+
readonly type: "gem.requestStoreOfferSheet";
|
|
2470
|
+
readonly requestId: string;
|
|
2471
|
+
readonly skuId: string;
|
|
2472
|
+
}
|
|
2473
|
+
interface GemStoreOfferSheetResult {
|
|
2474
|
+
readonly gem: typeof PROTOCOL;
|
|
2475
|
+
readonly type: "gem.storeOfferSheetResult";
|
|
2476
|
+
readonly requestId: string;
|
|
2477
|
+
readonly outcome: "ok" | "declined" | "unavailable";
|
|
2478
|
+
readonly reason?: string;
|
|
2479
|
+
}
|
|
2467
2480
|
interface ConnectOptions {
|
|
2468
2481
|
readonly clusterTargetId?: ClusterTargetLike;
|
|
2469
2482
|
readonly retry?: StartMatchRetryOptions;
|
|
@@ -3007,8 +3020,8 @@ interface FramePlayer extends PlayerIdentity {
|
|
|
3007
3020
|
readonly avatarUrl?: string;
|
|
3008
3021
|
readonly boost: PlayerBoost;
|
|
3009
3022
|
}
|
|
3010
|
-
type GemArcadeAsk = Omit<GemRequestAppLinks, "gem"> | Omit<GemRequestOpenApp, "gem"> | Omit<GemRequestOpenGame, "gem"> | Omit<GemRequestSimilarGames, "gem"> | Omit<GemRequestStoreOffers, "gem"> | Omit<GemRequestStorePurchase, "gem">;
|
|
3011
|
-
type GemArcadeAnswer = GemAppLinksResult | GemOpenAppResult | GemOpenGameResult | GemSimilarGamesResult | GemStoreOffersResult | GemStorePurchaseResult | GemStorePurchaseSettled;
|
|
3023
|
+
type GemArcadeAsk = Omit<GemRequestAppLinks, "gem"> | Omit<GemRequestOpenApp, "gem"> | Omit<GemRequestOpenGame, "gem"> | Omit<GemRequestSimilarGames, "gem"> | Omit<GemRequestStoreOffers, "gem"> | Omit<GemRequestStorePurchase, "gem"> | Omit<GemRequestStoreOfferSheet, "gem">;
|
|
3024
|
+
type GemArcadeAnswer = GemAppLinksResult | GemOpenAppResult | GemOpenGameResult | GemSimilarGamesResult | GemStoreOffersResult | GemStorePurchaseResult | GemStorePurchaseSettled | GemStoreOfferSheetResult;
|
|
3012
3025
|
interface FrameCallbacks {
|
|
3013
3026
|
onToken?(msg: GemToken): void;
|
|
3014
3027
|
onPause?(msg: GemPause): void;
|
|
@@ -3206,8 +3219,10 @@ interface StoreSettlement {
|
|
|
3206
3219
|
}
|
|
3207
3220
|
interface StoreApi {
|
|
3208
3221
|
readonly available: boolean;
|
|
3222
|
+
readonly showOfferAvailable: boolean;
|
|
3209
3223
|
offers(): Promise<StoreOffersOutcome>;
|
|
3210
3224
|
purchase(skuId: string): Promise<ArcadeOutcome>;
|
|
3225
|
+
showOffer(skuId: string): Promise<ArcadeOutcome>;
|
|
3211
3226
|
onSettled(listener: (settlement: StoreSettlement) => void): () => void;
|
|
3212
3227
|
}
|
|
3213
3228
|
type BrandingTheme = "light" | "dark";
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
var GemWebSdkBridgeBundle=(function(){'use strict';var L="GemWebSdkHandshake";function oe(){return typeof document>"u"?void 0:document.readyState}var U=()=>Date.now();function H(n={}){let e=n.win??window,t=e,r=t[L];if(r!==void 0)return r;let s=n.readyState??oe,i=n.now??U,d=[],a=[],u=y=>{let c=y.data;!c||c.type!=="gem.handshake"||(d.length>=4&&(d.shift(),a.shift(),p.dropped+=1),d.push(y),a.push(i()));};e.addEventListener("message",u);let p={events:d,times:a,dropped:0,late:s()==="complete",uninstall(){e.removeEventListener("message",u);}};return t[L]=p,p}function B(n,e,t={}){let r=n[L];if(r===void 0)return null;let s=t.ttlMs??9500,i=t.now??U,d=r.events.splice(0),a=r.times?.splice(0),u=0,p=0,y=false,c=i()-s;for(let f=d.length-1;f>=0;f--){let b=a?.[f];if(b!==void 0&&b<c){p+=1;continue}if(u+=1,e(d[f])===true){y=true;break}}return r.uninstall(),{capture:r,delivered:u,stale:p,accepted:y}}var l="gem-web-bridge",R={min:1,max:1},ae=65536,N=8,G=5e3,W=1024;var w=Object.create(null),x="__malformed";var j=Object.create(null),se=Object.freeze([["gem.asyncOpponents.","asyncOpponents"],["gem.vibration.","vibration"],["gem.viewport.","reservedAreas"],["gem.moments.","moments"],["gem.prefs.","audioChannels"]]);function O(n){let e=j[n];if(e!==void 0)return e;for(let[t,r]of se)if(n.startsWith(t))return r}function ie(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 le(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 de(n){return /^[a-z]{2,8}(-[a-z0-9]{1,8})*$/i.test(n)}function me(n){return /^[a-z_]+$/.test(n)}function ue(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 _(n,e,t){if(e>N)return `nesting deeper than ${N}`;if(++t.nodes>G)return `more than ${G} 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 s=n;if(t.seen.has(s))return "a repeated or cyclic object reference";if(t.seen.add(s),Array.isArray(n)){if(n.length>W)return `an array of ${n.length} entries, over the ${W} limit`;t.bytes+=2;for(let a of n){let u=_(a,e+1,t);if(u)return u}return null}let i=Object.getPrototypeOf(n);if(i!==Object.prototype&&i!==null)return "a value that is not a plain object";t.bytes+=2;let d=n;for(let a in d){if(!Object.prototype.hasOwnProperty.call(d,a))continue;if(++t.nodes>G)return `more than ${G} values`;if(t.bytes+=a.length*3+4,t.bytes>t.cap)return `over the ${t.cap} byte limit`;let u=_(d[a],e+1,t);if(u)return u}return null}function ce(n,e=ae){let t={nodes:0,bytes:0,seen:new Set,cap:e},r=_(n,0,t);return r?`message contains ${r}`:t.bytes>e?`message is over the ${e} byte limit`:null}var ge={origin:[ie,"not a well-formed origin"],url:[le,"not a safe absolute http(s) URL"],bcp47:[de,"not a well-formed BCP 47 tag"],code:[me,"not a code of lower-case letters and underscores"],gameRef:[ue,"not a game id or web address"]};function V(n,e,t){for(let r of e){let s=t===""?r[0]:`${t}.${r[0]}`,i=n[r[0]];if(i==null){if(r[1]<"a")continue;return `${s}: required`}let d=M(i,r,s);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[s,i]=ge[e[3]];if(!s(n))return `${t}: ${i}`}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 s=e[2];return s.includes(n)?null:`${t}: not one of ${s.join("|")}`}case "o":return typeof n!="object"||n===null||Array.isArray(n)?`${t}: expected object`:V(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 s=e[3],i=`${t}[]`;for(let d of n){if(d==null){if(s[1]<"a")continue;return `${i}: required`}let a=M(d,s,i);if(a)return a}return null}default:return `${t}: unknown kind ${String(r)}`}}var z=Object.create(null);function o(n,e,t,r,s){return w[n]=t,r&&(j[n]=r),z[n]=i=>{let d=ce(i,s);if(d)return d;if(typeof i!="object"||i===null||Array.isArray(i))return "message: expected object";let a=i;return a.gem!==l?"gem: wrong protocol marker":a.type!==n?`type: expected ${n}`:V(a,e,"")}}var m=["requestId","s",64],h=["outcome","e",["ok","declined","unavailable"]],v=["reason","S",64,"code"];o("gem.handshake",[["versions","o",[["min","i",1,1e3],["max","i",1,1e3]]],["capabilities","A",64,["","s",64]],["embedder","s",2048,"origin"],["unbidden","B"]],30);o("gem.handshake.accept",[["v","i",1,1e3],["capabilities","A",64,["","s",64]]],5);o("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);o("gem.token.denied",[m,["retryable","b"],["retryAfterMs","I",0,36e5],["reason","e",["chain_exhausted","unavailable"]],["correlationId","s",64]],30);o("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);o("gem.pause",[["paused","b"]],120);o("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);o("gem.cohorts",[["cohorts","a",8,["","o",[["experimentId","s",36],["variantKey","s",32]]]]],12,"cohorts");o("gem.earnAllowanceChanged",[],30,"earnAllowance");o("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");o("gem.deviceSettings",[["settings","J"]],12,"deviceSettings");o("gem.willTerminate",[["reason","e",["grant_expiring","session_ended","navigating","kill_switch"]],["graceMs","i",0,6e4]],10);o("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");o("gem.socketState",[["connected","b"],["reason","E",["connecting","dropped","watchdog","terminal"]]],12,"socketState");o("gem.seatedEvent",[["roomId","s",64]],60,"partySeating");o("gem.autoStartFailedEvent",[["roomId","s",64],["code","s",64]],30,"autoStartFailure");o("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");o("gem.signalEvent",[["event","e",["hello","offer","answer","ice","peerJoined","peerLeft","migration","matchEnded","error"]],["matchId","s",64],["data","j"]],1800,"p2p");o("gem.dedicatedEvent",[["event","e",["answer","error","matchEnded"]],["matchId","s",64],["sdp","S",10240],["sessionId","S",64],["code","S",64],["message","S",256],["reason","S",64]],120,"dedicated");o("gem.partyResult",[m,["partyId","S",64]],30,"parties");o("gem.clusterTarget",[["clusterTargetId","s",64],["clusterTargetIds","A",3,["","s",64]]],12,"clusterTarget");o("gem.devtools",[["action","e",["open","close","toggle"]]],30,"devtools");o("gem.screenshot",[["maxWidth","i",1,7680],["maxHeight","i",1,4320]],6,"screenshot");o("gem.screenshot.denied",[["reason","e",["not_wired","no_source","unsupported","unreadable","tainted","too_large","busy","declined","failed"]],["retryable","b"]],12,"screenshot");o("gem.requestContext",[],12,"feedbackContext");o("gem.gameContext",[["context","j"]],12,"feedbackContext");o("gem.signal",[["signal","e",["join","offer","answer","ice","migrationAck","hostUnreachable"]],["matchId","s",64],["data","j"]],1200,"p2p");o("gem.dedicatedOffer",[["matchId","s",64],["sdp","s",10240],["intent","e",["initial","ice_restart","full_reconnect"]]],60,"dedicated");o("gem.partyRequest",[m],12,"parties");o("gem.ready",[],5);o("gem.engaged",[],5,"engagement");o("gem.progress",[["loaded","i",0,1099511627776],["total","i",0,1099511627776]],600);o("gem.requestToken",[m,["reason","e",["initial","expiring","rejected"]]],12);o("gem.requestLocalServer",[m,["gameRoomId","s",64]],6,"localHost");o("gem.localServer",[m,["serverId","S",128]],30,"localHost");o("gem.localServer.denied",[m,["retryable","b"],["reason","e",["refused","unavailable"]]],30,"localHost");o("gem.exit",[["reason","S",64]],5);o("gem.openExternal",[["url","s",2048,"url"]],6);o("gem.requestFullscreen",[["enabled","b"]],30);o("gem.audioState",[["muted","b"]],120,"audioState");o("gem.rewardCue",[["currencySlug","s",32],["expected","I",1,1e9],["origin","O",[["x","i",0,16384],["y","i",0,16384]]]],60,"rewardCue");o("gem.walletDisplay",[["visible","b"],["currencies","A",8,["","s",64]],["score","B"]],60,"walletDisplay");o("gem.controlsDeclare",[["uses","o",[["lookSensitivity","S",16,"code"],["gamepadLookSensitivity","S",16,"code"],["invertLookY","S",16,"code"],["touchMovement","S",16,"code"]]]],60,"controls");o("gem.menu",[["settings","b"],["items","A",4,["","o",[["id","s",32],["label","s",40]]]]],60,"gameMenu");o("gem.menuSelect",[["entry","e",["settings","item"]],["id","S",32]],60,"gameMenu");o("gem.gemCorner",[["corner","e",["top-left","top-right","bottom-left","bottom-right"]]],12,"gemCorner");o("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");o("gem.settingChange",[["id","s",40],["value","u",40,-1e6,1e6]],120,"gameSettings");o("gem.requestShare",[["params","a",16,["","o",[["key","s",64],["value","s",512]]]]],6,"share");o("gem.requestAvatarPicker",[["tab","E",["2d","3d"]]],6,"avatarPicker");o("gem.vibrate",[["pattern","a",99,["","i",0,1e4]]],600,"vibration");o("gem.frameStats",[["fps","i",0,1e3],["frameTimeP95Ms","i",0,1e5],["counts","E",["pageFrames","gameDraws"]]],120,"frameStats");o("gem.portraitBorders",[["name","S",40]],60,"portraitBorders");o("gem.error",[["code","e",["version_mismatch","handshake_timeout","handshake_duplicate","invalid_message","rate_limited","token_unavailable","unsupported","unsupported_capability","internal"]],["message","S",256]],60);o("gem.requestPurchase",[m,["purchaseKind","e",["item","recipe"]],["targetId","s",64],["currencySlug","s",32],["quantity","I",1,10],["catalogId","S",64]],12,"purchases");o("gem.requestAvatar3dPurchase",[m,["itemId","s",64],["currencySlug","s",32]],12,"avatar3dPurchases");o("gem.purchaseResult",[m,h,v,["purchaseId","S",64]],30,"purchases");o("gem.deviceSettings.put",[m,["settings","j"]],30,"deviceSettings");o("gem.deviceSettings.result",[m,["outcome","e",["stored","too_large","unavailable"]]],30,"deviceSettings");o("gem.requestAd",[m,["placement","s",32],["format","e",["interstitial","rewarded"]]],6,"ads");o("gem.adResult",[m,["outcome","e",["shown","no_ad","unavailable"]]],12,"ads");o("gem.signalMoment",[m,["kind","e",["level_end","run_end","match_end","menu_return","other_break"]],["placement","S",32],["wall","B"]],6,"moments");o("gem.momentResult",[m,["shown","b"]],12,"moments");o("gem.requestSignIn",[m],6,"signIn");o("gem.signInResult",[m,["outcome","e",["signed_in","declined","unavailable"]]],12,"signIn");o("gem.requestFriendChallenge",[m,["playerId","s",64],["template","s",64],["params","J"]],12,"friendChallenges");o("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");o("gem.requestAppLinks",[m],12,"appLinks");o("gem.appLinksResult",[m,h,v,["arcade","O",[["store","e",["app_store","google_play"]]]],["game","O",[["store","e",["app_store","google_play"]]]]],30,"appLinks");o("gem.requestOpenApp",[m,["target","e",["arcade","game"]]],6,"appLinks");o("gem.openAppResult",[m,h,v],30,"appLinks");o("gem.requestOpenGame",[m,["ref","s",40,"gameRef"]],6,"openGame");o("gem.openGameResult",[m,h,v],30,"openGame");o("gem.requestSimilarGames",[m,["limit","I",1,24]],12,"openGame");o("gem.similarGamesResult",[m,h,v,["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);o("gem.requestStoreOffers",[m],12,"store");o("gem.storeOffersResult",[m,h,v,["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);o("gem.requestStorePurchase",[m,["skuId","s",64]],12,"store");o("gem.storePurchaseResult",[m,h,v],30,"store");o("gem.storePurchaseSettled",[["skuId","s",64]],30,"store");var P=Object.freeze(z);w.__malformed=60;Object.freeze(w);Object.freeze(j);var pe=/^[a-z0-9][a-z0-9_-]{0,39}$/;function ye(n){return typeof n=="string"&&pe.test(n)}function K(n){if(n===null||ye(n))return n;let e=typeof n=="string"?JSON.stringify(n.length>48?`${n.slice(0,48)}\u2026`:n):`a value of type ${typeof n}`;console.warn(`[gem] showPortraitBorders: ${e} is not a border name, so nothing was sent. A name is 1 to 40 of a-z, 0-9, _ and -, starting with a letter or digit, exactly as your store page declares it under media.portrait_borders. Pass null for no art.`);}var D={now:()=>Date.now(),setTimeout:(n,e)=>setTimeout(n,e),clearTimeout:n=>clearTimeout(n)},k=class{constructor(e=D){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(),s=this.lastRefill.get(e)??r,i=this.tokens.get(e)??t,d=Math.max(0,r-s),a=Math.min(t,i+d*t/6e4);return a<1?(this.tokens.set(e,a),this.lastRefill.set(e,r),false):(this.tokens.set(e,a-1),this.lastRefill.set(e,r),true)}};function T(n,e){return n.toLowerCase()===e.toLowerCase()}function C(n){let e=n.toLowerCase();return e==="localhost"||e.endsWith(".localhost")||e==="[::1]"||e==="::1"?true:/^127(\.\d{1,3}){3}$/.test(e)}function Y(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:C(t.hostname)&&C(r.hostname)}function J(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 Z="[gem: use gem.text.toPlain()]",Q=new Set,X;function fe(n){try{if(Q.has(n))return;let e=globalThis.location;if(X??=!!e?.port&&C(e.hostname??""),!X)return;Q.add(n),console.warn(`[gem] ${n} is PlayerText, turned into a string: players see ${Z}. Render text.toPlain(value) (text is in @indiegems/gem-web-sdk/sdk).
|
|
2
|
-
${new Error().stack}`);}catch{}}var F=class{#e;#t;constructor(e,t="player text"){this.#e=e,this.#t=t,Object.freeze(this);}toString(){return fe(this.#t),Z}toJSON(){return this.toString()}get[Symbol.toStringTag](){return "PlayerText"}static unwrap(e){return e.#e}};function $(n,e){return new F(n,e)}function ee(n){return Math.min(16384,Math.max(0,Math.round(Number.isFinite(n)?n:0)))}function he(n,e){if(n!==true)return {visible:false};let t=[],r=false;for(let s of Array.isArray(e)?e:[])s==="score"?r=true:typeof s=="string"&&s.length>0&&s.length<=64&&!t.includes(s)&&t.push(s);return !r&&t.length===0?{visible:true}:{visible:true,currencies:t.slice(0,8),score:r}}function ve(n){let e=[];for(let t of Array.isArray(n)?n:[]){if(e.length===4)break;if(typeof t!="object"||t===null)continue;let{id:r,label:s}=t;typeof r!="string"||r.length===0||r.length>32||typeof s!="string"||s.trim().length===0||e.some(i=>i.id===r)||e.push({id:r,label:s.trim().slice(0,40)});}return e.length===0?{settings:false}:{settings:false,items:e}}function te(n,e){return Math.min(e,Math.max(0,Math.round(Number.isFinite(n)?n:0)))}function be(n){let e=n.untrusted,t=$(e.displayName,"gem.player.displayName"),r=e.displayTag||e.displayHandle,s=r?$(r,"gem.player.displayTag"):void 0,i=n.discriminator||n.displayTag,d=i&&/^[0-9]{1,8}$/.test(i)?i:void 0,a=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:s??t,badges:(n.badges??[]).map(g=>({itemId:g.itemId,iconUrl:g.iconUrl}))};n.playerId&&(c.playerId=n.playerId),d&&(c.discriminator=d),s&&(c.displayTag=s),a&&(c.avatarIconUrl=c.avatarUrl=a),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,I)=>I.findIndex(q=>q.family==g.family)==A).map(({family:g,id:A,modelUrl:I,iconUrl:q})=>({family:g,id:A,modelUrl:I,iconUrl:q})));let f=n.boost,b=(f?.multipliers??[]).map(g=>({currencyId:g.currencyId,currencySlug:g.currencySlug,multiplier:g.multiplierBp/1e4})),E=b.some(g=>g.multiplier>1);return c.boost=E&&f?.expiresInDays?{active:E,multipliers:b,expiresInDays:f.expiresInDays}:{active:E,multipliers:b},c}var Re=1e4,we=["appLinks","openGame","store"],ke=new WeakMap;var S=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??D,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(a=>T(a,e.origin))||Y(e.origin,this.options.selfOrigin)||(ke.get(this)??[]).some(a=>T(a,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=P["gem.handshake"]?.(e.data);if(r)return this.refuse(e,`malformed handshake: ${r}`),false;let s=e.data;if(!T(s.embedder,e.origin))return this.refuse(e,`handshake claims embedder '${s.embedder}' but arrived from '${e.origin}'`),false;let i=e.ports?.[0];if(!i)return this.refuse(e,"handshake transferred no MessagePort"),false;let d=J(R,s.versions);return d===null?(i.onmessage=null,i.postMessage({gem:l,type:"gem.error",code:"version_mismatch",message:`frame supports v${R.min}..v${R.max}`}),i.close(),this.transition("refused"),this.options.onError?.("version_mismatch"),false):(this.port=i,this.version=d,i.onmessage=a=>this.receive(a.data,a.ports??[]),i.start?.(),this.peerCapabilities=s.capabilities??[],this.unbidden=s.unbidden===true,i.postMessage({gem:l,type:"gem.handshake.accept",v:d,...this.options.capabilities===void 0?{}:{capabilities:[...this.options.capabilities]}}),this.transition("connected"),this.readyPending&&(this.readyPending=false,this.ready()),true)}ready(){if(this.state!=="connected"||!this.port){this.readyPending=true;return}if(this.readySent){this.options.onDropped?.("internal","gem.ready was already sent; duplicate suppressed");return}this.readySent=true,this.send({gem:l,type:"gem.ready"});}settled(e=Re){return this.state!=="waiting"?Promise.resolve(this.state):new Promise(t=>{let r=i=>{this.clock.clearTimeout(s),t(i);},s=this.clock.setTimeout(()=>{let i=this.settleWaiters.indexOf(r);i>=0&&this.settleWaiters.splice(i,1),t(this.state);},e);this.settleWaiters.push(r);})}progress(e,t){this.send({gem:l,type:"gem.progress",loaded:e,total:t});}requestToken(e,t){this.send({gem:l,type:"gem.requestToken",requestId:e,reason:t});}requestLocalServer(e,t){return this.parentSupports("localHost")?(this.send({gem:l,type:"gem.requestLocalServer",requestId:e,gameRoomId:t}),true):false}exit(e){this.send(e===void 0?{gem:l,type:"gem.exit"}:{gem:l,type:"gem.exit",reason:e});}openExternal(e){this.send({gem:l,type:"gem.openExternal",url:e});}requestFullscreen(e){this.send({gem:l,type:"gem.requestFullscreen",enabled:e});}reportMuted(e){return this.gated("audioState")?(this.send({gem:l,type:"gem.audioState",muted:e}),true):false}reportEngaged(){return this.engagedSent||!this.gated("engagement")||!this.send({gem:l,type:"gem.engaged"})?false:(this.engagedSent=true,true)}cueReward(e){if(!this.gated("rewardCue"))return false;let t={gem:l,type:"gem.rewardCue",currencySlug:String(e.currencySlug).slice(0,32)};return e.expected!==void 0&&Number.isFinite(e.expected)&&e.expected>=1&&(t.expected=Math.min(1e9,Math.round(e.expected))),e.origin&&(t.origin={x:ee(e.origin.x),y:ee(e.origin.y)}),this.send(t),true}showPortraitBorders(e){let t=K(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",...he(e,t?.only)}):false}setMenu(e){return this.gated("gameMenu")?this.send({gem:l,type:"gem.menu",...ve(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}requestShare(e){return this.gated("share")?this.send({gem:l,type:"gem.requestShare",params:e.map(({key:t,value:r})=>({key:t,value:r}))}):false}requestAvatarPicker(e){return this.gated("avatarPicker")?this.send({gem:l,type:"gem.requestAvatarPicker",...e==="2d"||e==="3d"?{tab:e}:{}}):false}requestVibrate(e){return this.gated("vibration")?this.send({gem:l,type:"gem.vibrate",pattern:[...e]}):false}reportFrameStats(e){return this.gated("frameStats")?(this.send({gem:l,type:"gem.frameStats",fps:te(e.fps,1e3),frameTimeP95Ms:te(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,s,i,d){return this.send({gem:l,type:"gem.requestPurchase",requestId:e,purchaseKind:t,targetId:r,currencySlug:s,...i===void 0?{}:{quantity:i},...d===void 0?{}:{catalogId:d}})}requestAvatar3dPurchase(e,t,r){return this.parentSupports("avatar3dPurchases")?this.send({gem:l,type:"gem.requestAvatar3dPurchase",requestId:e,itemId:t,currencySlug:r}):false}putDeviceSettings(e,t){return this.send({gem:l,type:"gem.deviceSettings.put",requestId:e,settings:t})}requestAd(e,t,r){return this.send({gem:l,type:"gem.requestAd",requestId:e,placement:t,format:r})}signalMoment(e,t,r,s){return this.send({gem:l,type:"gem.signalMoment",requestId:e,kind:t,...r===void 0?{}:{placement:r},...s===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,s){return this.send({gem:l,type:"gem.requestFriendChallenge",requestId:e,playerId:t,template:r,...s===void 0?{}:{params:s}})}requestArcade(e){return this.gated(O(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(x)){this.options.onDropped?.(e,t);return}this.fail(e,t);}dropUnknownType(e){this.inbound.allow(x)&&this.options.onDropped?.("unsupported",`ignored unknown message type '${e}'`);}refuse(e,t){e.ports?.[0]?.close?.(),this.inbound.allow(x)&&this.options.onRefused?.(t);}fail(e,t){this.options.onError?.(e,t),this.state==="connected"&&this.port&&this.send({gem:l,type:"gem.error",code:e,...t===void 0?{}:{message:t}});}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=P[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||ne(t);}}dispatchInbound(e,t){if(this.state!=="connected")return false;let r=typeof e=="object"&&e!==null?e.type:void 0;if(typeof r!="string")return this.refuseMalformed("invalid_message","message has no type"),false;let s=P[r];if(!s)return this.dropUnknownType(r),false;if(!this.inbound.allow(r))return this.fail("rate_limited",`parent exceeded the limit for ${r}`),false;let i=O(r);if(i!==void 0&&!this.options.capabilities?.includes(i))return this.fail("unsupported_capability",`${r} requires the '${i}' capability, which this frame did not advertise`),false;let d=s(e);if(d)return this.fail("invalid_message",`${r}: ${d}`),false;let a=e;if(a.v!==this.version)return this.fail("invalid_message",`${r}: expected v ${String(this.version)}`),false;switch(r){case "gem.token":this.options.onToken?.(a);break;case "gem.pause":this.options.onPause?.(a);break;case "gem.menuSelect":this.options.onMenuSelect?.(a);break;case "gem.settingChange":this.options.onSettingChange?.(a);break;case "gem.prefs":this.options.onPrefs?.(a);break;case "gem.cohorts":this.options.onCohorts?.(a);break;case "gem.earnAllowanceChanged":this.options.onEarnAllowanceChanged?.();break;case "gem.viewport":this.options.onViewport?.(a);break;case "gem.willTerminate":this.options.onWillTerminate?.(a);break;case "gem.devtools":this.options.onDevtools?.(a.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:a.maxWidth,maxHeight:a.maxHeight};if(!this.options.onScreenshot){u.close(),this.screenshotDenied("not_wired",false);break}return ne(t.slice(1)),this.options.onScreenshot(p,u,(y,c)=>this.screenshotDenied(y,c)),true}case "gem.token.denied":this.options.onTokenDenied?.(a);break;case "gem.localServer":this.options.onLocalServer?.(a);break;case "gem.localServer.denied":this.options.onLocalServerDenied?.(a);break;case "gem.player":{this.options.onPlayer?.(be(a));break}case "gem.roomEvent":this.options.onRoomEvent?.(a);break;case "gem.seatedEvent":this.options.onSeatedEvent?.(a);break;case "gem.autoStartFailedEvent":this.options.onAutoStartFailedEvent?.(a);break;case "gem.ticketEvent":this.options.onTicketEvent?.(a);break;case "gem.socketState":this.options.onSocketState?.(a);break;case "gem.signalEvent":this.options.onSignalEvent?.(a);break;case "gem.dedicatedEvent":this.options.onDedicatedEvent?.(a);break;case "gem.clusterTarget":this.options.onClusterTarget?.(a);break;case "gem.partyResult":this.options.onPartyResult?.(a);break;case "gem.purchaseResult":this.options.onPurchaseResult?.(a);break;case "gem.deviceSettings":this.options.onDeviceSettings?.(a);break;case "gem.deviceSettings.result":this.options.onDeviceSettingsResult?.(a);break;case "gem.adResult":this.options.onAdResult?.(a);break;case "gem.momentResult":this.options.onMomentResult?.(a);break;case "gem.signInResult":this.options.onSignInResult?.(a);break;case "gem.friendChallengeResult":this.options.onFriendChallengeResult?.(a);break;case "gem.error":this.options.onError?.(a.code,a.message);break;default:if(we.includes(O(r))){this.options.onArcadeAnswer?.(a);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 ne(n){for(let e of n)try{e?.close?.();}catch{}}H();function Se(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 S({...n,expectedSource:n.expectedSource??window.parent}),t=r=>{let s=e.handleWindowMessage({data:r.data,origin:r.origin,source:r.source,ports:r.ports});return s&&window.removeEventListener("message",t),s};return window.addEventListener("message",t),B(window,t),e}var re={connect:Se,GemFrame:S,PROTOCOL:l,SUPPORTED_VERSIONS:R};window.GemWebSdkBridge=re;var cn=re;return cn;})();
|
|
1
|
+
var GemWebSdkBridgeBundle=(function(){'use strict';var L="GemWebSdkHandshake";function oe(){return typeof document>"u"?void 0:document.readyState}var U=()=>Date.now();function H(n={}){let e=n.win??window,t=e,r=t[L];if(r!==void 0)return r;let s=n.readyState??oe,i=n.now??U,d=[],a=[],u=y=>{let c=y.data;!c||c.type!=="gem.handshake"||(d.length>=4&&(d.shift(),a.shift(),p.dropped+=1),d.push(y),a.push(i()));};e.addEventListener("message",u);let p={events:d,times:a,dropped:0,late:s()==="complete",uninstall(){e.removeEventListener("message",u);}};return t[L]=p,p}function B(n,e,t={}){let r=n[L];if(r===void 0)return null;let s=t.ttlMs??9500,i=t.now??U,d=r.events.splice(0),a=r.times?.splice(0),u=0,p=0,y=false,c=i()-s;for(let f=d.length-1;f>=0;f--){let R=a?.[f];if(R!==void 0&&R<c){p+=1;continue}if(u+=1,e(d[f])===true){y=true;break}}return r.uninstall(),{capture:r,delivered:u,stale:p,accepted:y}}var l="gem-web-bridge",b={min:1,max:1},ae=65536,N=8,G=5e3,W=1024;var S=Object.create(null),O="__malformed";var M=Object.create(null),se=Object.freeze([["gem.asyncOpponents.","asyncOpponents"],["gem.vibration.","vibration"],["gem.viewport.","reservedAreas"],["gem.moments.","moments"],["gem.prefs.","audioChannels"]]);function x(n){let e=M[n];if(e!==void 0)return e;for(let[t,r]of se)if(n.startsWith(t))return r}function ie(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 le(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 de(n){return /^[a-z]{2,8}(-[a-z0-9]{1,8})*$/i.test(n)}function me(n){return /^[a-z_]+$/.test(n)}function ue(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 _(n,e,t){if(e>N)return `nesting deeper than ${N}`;if(++t.nodes>G)return `more than ${G} 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 s=n;if(t.seen.has(s))return "a repeated or cyclic object reference";if(t.seen.add(s),Array.isArray(n)){if(n.length>W)return `an array of ${n.length} entries, over the ${W} limit`;t.bytes+=2;for(let a of n){let u=_(a,e+1,t);if(u)return u}return null}let i=Object.getPrototypeOf(n);if(i!==Object.prototype&&i!==null)return "a value that is not a plain object";t.bytes+=2;let d=n;for(let a in d){if(!Object.prototype.hasOwnProperty.call(d,a))continue;if(++t.nodes>G)return `more than ${G} values`;if(t.bytes+=a.length*3+4,t.bytes>t.cap)return `over the ${t.cap} byte limit`;let u=_(d[a],e+1,t);if(u)return u}return null}function ce(n,e=ae){let t={nodes:0,bytes:0,seen:new Set,cap:e},r=_(n,0,t);return r?`message contains ${r}`:t.bytes>e?`message is over the ${e} byte limit`:null}var ge={origin:[ie,"not a well-formed origin"],url:[le,"not a safe absolute http(s) URL"],bcp47:[de,"not a well-formed BCP 47 tag"],code:[me,"not a code of lower-case letters and underscores"],gameRef:[ue,"not a game id or web address"]};function V(n,e,t){for(let r of e){let s=t===""?r[0]:`${t}.${r[0]}`,i=n[r[0]];if(i==null){if(r[1]<"a")continue;return `${s}: required`}let d=j(i,r,s);if(d)return d}return null}function j(n,e,t){let r=e[1].toLowerCase();switch(r){case "u":return typeof n=="boolean"?null:j(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[s,i]=ge[e[3]];if(!s(n))return `${t}: ${i}`}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 s=e[2];return s.includes(n)?null:`${t}: not one of ${s.join("|")}`}case "o":return typeof n!="object"||n===null||Array.isArray(n)?`${t}: expected object`:V(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 s=e[3],i=`${t}[]`;for(let d of n){if(d==null){if(s[1]<"a")continue;return `${i}: required`}let a=j(d,s,i);if(a)return a}return null}default:return `${t}: unknown kind ${String(r)}`}}var z=Object.create(null);function o(n,e,t,r,s){return S[n]=t,r&&(M[n]=r),z[n]=i=>{let d=ce(i,s);if(d)return d;if(typeof i!="object"||i===null||Array.isArray(i))return "message: expected object";let a=i;return a.gem!==l?"gem: wrong protocol marker":a.type!==n?`type: expected ${n}`:V(a,e,"")}}var m=["requestId","s",64],h=["outcome","e",["ok","declined","unavailable"]],v=["reason","S",64,"code"];o("gem.handshake",[["versions","o",[["min","i",1,1e3],["max","i",1,1e3]]],["capabilities","A",64,["","s",64]],["embedder","s",2048,"origin"],["unbidden","B"]],30);o("gem.handshake.accept",[["v","i",1,1e3],["capabilities","A",64,["","s",64]]],5);o("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);o("gem.token.denied",[m,["retryable","b"],["retryAfterMs","I",0,36e5],["reason","e",["chain_exhausted","unavailable"]],["correlationId","s",64]],30);o("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);o("gem.pause",[["paused","b"]],120);o("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);o("gem.cohorts",[["cohorts","a",8,["","o",[["experimentId","s",36],["variantKey","s",32]]]]],12,"cohorts");o("gem.earnAllowanceChanged",[],30,"earnAllowance");o("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");o("gem.deviceSettings",[["settings","J"]],12,"deviceSettings");o("gem.willTerminate",[["reason","e",["grant_expiring","session_ended","navigating","kill_switch"]],["graceMs","i",0,6e4]],10);o("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");o("gem.socketState",[["connected","b"],["reason","E",["connecting","dropped","watchdog","terminal"]]],12,"socketState");o("gem.seatedEvent",[["roomId","s",64]],60,"partySeating");o("gem.autoStartFailedEvent",[["roomId","s",64],["code","s",64]],30,"autoStartFailure");o("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");o("gem.signalEvent",[["event","e",["hello","offer","answer","ice","peerJoined","peerLeft","migration","matchEnded","error"]],["matchId","s",64],["data","j"]],1800,"p2p");o("gem.dedicatedEvent",[["event","e",["answer","error","matchEnded"]],["matchId","s",64],["sdp","S",10240],["sessionId","S",64],["code","S",64],["message","S",256],["reason","S",64]],120,"dedicated");o("gem.partyResult",[m,["partyId","S",64]],30,"parties");o("gem.clusterTarget",[["clusterTargetId","s",64],["clusterTargetIds","A",3,["","s",64]]],12,"clusterTarget");o("gem.devtools",[["action","e",["open","close","toggle"]]],30,"devtools");o("gem.screenshot",[["maxWidth","i",1,7680],["maxHeight","i",1,4320]],6,"screenshot");o("gem.screenshot.denied",[["reason","e",["not_wired","no_source","unsupported","unreadable","tainted","too_large","busy","declined","failed"]],["retryable","b"]],12,"screenshot");o("gem.requestContext",[],12,"feedbackContext");o("gem.gameContext",[["context","j"]],12,"feedbackContext");o("gem.signal",[["signal","e",["join","offer","answer","ice","migrationAck","hostUnreachable"]],["matchId","s",64],["data","j"]],1200,"p2p");o("gem.dedicatedOffer",[["matchId","s",64],["sdp","s",10240],["intent","e",["initial","ice_restart","full_reconnect"]]],60,"dedicated");o("gem.partyRequest",[m],12,"parties");o("gem.ready",[],5);o("gem.engaged",[],5,"engagement");o("gem.progress",[["loaded","i",0,1099511627776],["total","i",0,1099511627776]],600);o("gem.requestToken",[m,["reason","e",["initial","expiring","rejected"]]],12);o("gem.requestLocalServer",[m,["gameRoomId","s",64]],6,"localHost");o("gem.localServer",[m,["serverId","S",128]],30,"localHost");o("gem.localServer.denied",[m,["retryable","b"],["reason","e",["refused","unavailable"]]],30,"localHost");o("gem.exit",[["reason","S",64]],5);o("gem.openExternal",[["url","s",2048,"url"]],6);o("gem.requestFullscreen",[["enabled","b"]],30);o("gem.audioState",[["muted","b"]],120,"audioState");o("gem.rewardCue",[["currencySlug","s",32],["expected","I",1,1e9],["origin","O",[["x","i",0,16384],["y","i",0,16384]]]],60,"rewardCue");o("gem.walletDisplay",[["visible","b"],["currencies","A",8,["","s",64]],["score","B"]],60,"walletDisplay");o("gem.controlsDeclare",[["uses","o",[["lookSensitivity","S",16,"code"],["gamepadLookSensitivity","S",16,"code"],["invertLookY","S",16,"code"],["touchMovement","S",16,"code"]]]],60,"controls");o("gem.menu",[["settings","b"],["items","A",4,["","o",[["id","s",32],["label","s",40]]]]],60,"gameMenu");o("gem.menuSelect",[["entry","e",["settings","item"]],["id","S",32]],60,"gameMenu");o("gem.gemCorner",[["corner","e",["top-left","top-right","bottom-left","bottom-right"]]],12,"gemCorner");o("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");o("gem.settingChange",[["id","s",40],["value","u",40,-1e6,1e6]],120,"gameSettings");o("gem.requestShare",[["params","a",16,["","o",[["key","s",64],["value","s",512]]]]],6,"share");o("gem.requestAvatarPicker",[["tab","E",["2d","3d"]]],6,"avatarPicker");o("gem.vibrate",[["pattern","a",99,["","i",0,1e4]]],600,"vibration");o("gem.frameStats",[["fps","i",0,1e3],["frameTimeP95Ms","i",0,1e5],["counts","E",["pageFrames","gameDraws"]]],120,"frameStats");o("gem.portraitBorders",[["name","S",40]],60,"portraitBorders");o("gem.error",[["code","e",["version_mismatch","handshake_timeout","handshake_duplicate","invalid_message","rate_limited","token_unavailable","unsupported","unsupported_capability","internal"]],["message","S",256]],60);o("gem.requestPurchase",[m,["purchaseKind","e",["item","recipe"]],["targetId","s",64],["currencySlug","s",32],["quantity","I",1,10],["catalogId","S",64]],12,"purchases");o("gem.requestAvatar3dPurchase",[m,["itemId","s",64],["currencySlug","s",32]],12,"avatar3dPurchases");o("gem.purchaseResult",[m,h,v,["purchaseId","S",64]],30,"purchases");o("gem.deviceSettings.put",[m,["settings","j"]],30,"deviceSettings");o("gem.deviceSettings.result",[m,["outcome","e",["stored","too_large","unavailable"]]],30,"deviceSettings");o("gem.requestAd",[m,["placement","s",32],["format","e",["interstitial","rewarded"]]],6,"ads");o("gem.adResult",[m,["outcome","e",["shown","no_ad","unavailable"]]],12,"ads");o("gem.signalMoment",[m,["kind","e",["level_end","run_end","match_end","menu_return","other_break"]],["placement","S",32],["wall","B"]],6,"moments");o("gem.momentResult",[m,["shown","b"]],12,"moments");o("gem.requestSignIn",[m],6,"signIn");o("gem.signInResult",[m,["outcome","e",["signed_in","declined","unavailable"]]],12,"signIn");o("gem.requestFriendChallenge",[m,["playerId","s",64],["template","s",64],["params","J"]],12,"friendChallenges");o("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");o("gem.requestAppLinks",[m],12,"appLinks");o("gem.appLinksResult",[m,h,v,["arcade","O",[["store","e",["app_store","google_play"]]]],["game","O",[["store","e",["app_store","google_play"]]]]],30,"appLinks");o("gem.requestOpenApp",[m,["target","e",["arcade","game"]]],6,"appLinks");o("gem.openAppResult",[m,h,v],30,"appLinks");o("gem.requestOpenGame",[m,["ref","s",40,"gameRef"]],6,"openGame");o("gem.openGameResult",[m,h,v],30,"openGame");o("gem.requestSimilarGames",[m,["limit","I",1,24]],12,"openGame");o("gem.similarGamesResult",[m,h,v,["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);o("gem.requestStoreOffers",[m],12,"store");o("gem.storeOffersResult",[m,h,v,["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);o("gem.requestStorePurchase",[m,["skuId","s",64]],12,"store");o("gem.storePurchaseResult",[m,h,v],30,"store");o("gem.storePurchaseSettled",[["skuId","s",64]],30,"store");o("gem.requestStoreOfferSheet",[m,["skuId","s",64]],12,"storeOfferSheet");o("gem.storeOfferSheetResult",[m,h,v],30,"storeOfferSheet");var P=Object.freeze(z);S.__malformed=60;Object.freeze(S);Object.freeze(M);var pe=/^[a-z0-9][a-z0-9_-]{0,39}$/;function ye(n){return typeof n=="string"&&pe.test(n)}function K(n){if(n===null||ye(n))return n;let e=typeof n=="string"?JSON.stringify(n.length>48?`${n.slice(0,48)}\u2026`:n):`a value of type ${typeof n}`;console.warn(`[gem] showPortraitBorders: ${e} is not a border name, so nothing was sent. A name is 1 to 40 of a-z, 0-9, _ and -, starting with a letter or digit, exactly as your store page declares it under media.portrait_borders. Pass null for no art.`);}var D={now:()=>Date.now(),setTimeout:(n,e)=>setTimeout(n,e),clearTimeout:n=>clearTimeout(n)},w=class{constructor(e=D){this.clock=e;}clock;tokens=new Map;lastRefill=new Map;allow(e){let t=S[e];if(t===void 0)return false;let r=this.clock.now(),s=this.lastRefill.get(e)??r,i=this.tokens.get(e)??t,d=Math.max(0,r-s),a=Math.min(t,i+d*t/6e4);return a<1?(this.tokens.set(e,a),this.lastRefill.set(e,r),false):(this.tokens.set(e,a-1),this.lastRefill.set(e,r),true)}};function T(n,e){return n.toLowerCase()===e.toLowerCase()}function C(n){let e=n.toLowerCase();return e==="localhost"||e.endsWith(".localhost")||e==="[::1]"||e==="::1"?true:/^127(\.\d{1,3}){3}$/.test(e)}function Y(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:C(t.hostname)&&C(r.hostname)}function J(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 Z="[gem: use gem.text.toPlain()]",Q=new Set,X;function fe(n){try{if(Q.has(n))return;let e=globalThis.location;if(X??=!!e?.port&&C(e.hostname??""),!X)return;Q.add(n),console.warn(`[gem] ${n} is PlayerText, turned into a string: players see ${Z}. Render text.toPlain(value) (text is in @indiegems/gem-web-sdk/sdk).
|
|
2
|
+
${new Error().stack}`);}catch{}}var F=class{#e;#t;constructor(e,t="player text"){this.#e=e,this.#t=t,Object.freeze(this);}toString(){return fe(this.#t),Z}toJSON(){return this.toString()}get[Symbol.toStringTag](){return "PlayerText"}static unwrap(e){return e.#e}};function $(n,e){return new F(n,e)}function ee(n){return Math.min(16384,Math.max(0,Math.round(Number.isFinite(n)?n:0)))}function he(n,e){if(n!==true)return {visible:false};let t=[],r=false;for(let s of Array.isArray(e)?e:[])s==="score"?r=true:typeof s=="string"&&s.length>0&&s.length<=64&&!t.includes(s)&&t.push(s);return !r&&t.length===0?{visible:true}:{visible:true,currencies:t.slice(0,8),score:r}}function ve(n){let e=[];for(let t of Array.isArray(n)?n:[]){if(e.length===4)break;if(typeof t!="object"||t===null)continue;let{id:r,label:s}=t;typeof r!="string"||r.length===0||r.length>32||typeof s!="string"||s.trim().length===0||e.some(i=>i.id===r)||e.push({id:r,label:s.trim().slice(0,40)});}return e.length===0?{settings:false}:{settings:false,items:e}}function te(n,e){return Math.min(e,Math.max(0,Math.round(Number.isFinite(n)?n:0)))}function Re(n){let e=n.untrusted,t=$(e.displayName,"gem.player.displayName"),r=e.displayTag||e.displayHandle,s=r?$(r,"gem.player.displayTag"):void 0,i=n.discriminator||n.displayTag,d=i&&/^[0-9]{1,8}$/.test(i)?i:void 0,a=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:s??t,badges:(n.badges??[]).map(g=>({itemId:g.itemId,iconUrl:g.iconUrl}))};n.playerId&&(c.playerId=n.playerId),d&&(c.discriminator=d),s&&(c.displayTag=s),a&&(c.avatarIconUrl=c.avatarUrl=a),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,q,I)=>I.findIndex(A=>A.family==g.family)==q).map(({family:g,id:q,modelUrl:I,iconUrl:A})=>({family:g,id:q,modelUrl:I,iconUrl:A})));let f=n.boost,R=(f?.multipliers??[]).map(g=>({currencyId:g.currencyId,currencySlug:g.currencySlug,multiplier:g.multiplierBp/1e4})),E=R.some(g=>g.multiplier>1);return c.boost=E&&f?.expiresInDays?{active:E,multipliers:R,expiresInDays:f.expiresInDays}:{active:E,multipliers:R},c}var be=1e4,Se=["appLinks","openGame","store","storeOfferSheet"],we=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??D,this.inbound=new w(this.clock),this.outbound=new w(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(a=>T(a,e.origin))||Y(e.origin,this.options.selfOrigin)||(we.get(this)??[]).some(a=>T(a,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=P["gem.handshake"]?.(e.data);if(r)return this.refuse(e,`malformed handshake: ${r}`),false;let s=e.data;if(!T(s.embedder,e.origin))return this.refuse(e,`handshake claims embedder '${s.embedder}' but arrived from '${e.origin}'`),false;let i=e.ports?.[0];if(!i)return this.refuse(e,"handshake transferred no MessagePort"),false;let d=J(b,s.versions);return d===null?(i.onmessage=null,i.postMessage({gem:l,type:"gem.error",code:"version_mismatch",message:`frame supports v${b.min}..v${b.max}`}),i.close(),this.transition("refused"),this.options.onError?.("version_mismatch"),false):(this.port=i,this.version=d,i.onmessage=a=>this.receive(a.data,a.ports??[]),i.start?.(),this.peerCapabilities=s.capabilities??[],this.unbidden=s.unbidden===true,i.postMessage({gem:l,type:"gem.handshake.accept",v:d,...this.options.capabilities===void 0?{}:{capabilities:[...this.options.capabilities]}}),this.transition("connected"),this.readyPending&&(this.readyPending=false,this.ready()),true)}ready(){if(this.state!=="connected"||!this.port){this.readyPending=true;return}if(this.readySent){this.options.onDropped?.("internal","gem.ready was already sent; duplicate suppressed");return}this.readySent=true,this.send({gem:l,type:"gem.ready"});}settled(e=be){return this.state!=="waiting"?Promise.resolve(this.state):new Promise(t=>{let r=i=>{this.clock.clearTimeout(s),t(i);},s=this.clock.setTimeout(()=>{let i=this.settleWaiters.indexOf(r);i>=0&&this.settleWaiters.splice(i,1),t(this.state);},e);this.settleWaiters.push(r);})}progress(e,t){this.send({gem:l,type:"gem.progress",loaded:e,total:t});}requestToken(e,t){this.send({gem:l,type:"gem.requestToken",requestId:e,reason:t});}requestLocalServer(e,t){return this.parentSupports("localHost")?(this.send({gem:l,type:"gem.requestLocalServer",requestId:e,gameRoomId:t}),true):false}exit(e){this.send(e===void 0?{gem:l,type:"gem.exit"}:{gem:l,type:"gem.exit",reason:e});}openExternal(e){this.send({gem:l,type:"gem.openExternal",url:e});}requestFullscreen(e){this.send({gem:l,type:"gem.requestFullscreen",enabled:e});}reportMuted(e){return this.gated("audioState")?(this.send({gem:l,type:"gem.audioState",muted:e}),true):false}reportEngaged(){return this.engagedSent||!this.gated("engagement")||!this.send({gem:l,type:"gem.engaged"})?false:(this.engagedSent=true,true)}cueReward(e){if(!this.gated("rewardCue"))return false;let t={gem:l,type:"gem.rewardCue",currencySlug:String(e.currencySlug).slice(0,32)};return e.expected!==void 0&&Number.isFinite(e.expected)&&e.expected>=1&&(t.expected=Math.min(1e9,Math.round(e.expected))),e.origin&&(t.origin={x:ee(e.origin.x),y:ee(e.origin.y)}),this.send(t),true}showPortraitBorders(e){let t=K(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",...he(e,t?.only)}):false}setMenu(e){return this.gated("gameMenu")?this.send({gem:l,type:"gem.menu",...ve(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}requestShare(e){return this.gated("share")?this.send({gem:l,type:"gem.requestShare",params:e.map(({key:t,value:r})=>({key:t,value:r}))}):false}requestAvatarPicker(e){return this.gated("avatarPicker")?this.send({gem:l,type:"gem.requestAvatarPicker",...e==="2d"||e==="3d"?{tab:e}:{}}):false}requestVibrate(e){return this.gated("vibration")?this.send({gem:l,type:"gem.vibrate",pattern:[...e]}):false}reportFrameStats(e){return this.gated("frameStats")?(this.send({gem:l,type:"gem.frameStats",fps:te(e.fps,1e3),frameTimeP95Ms:te(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,s,i,d){return this.send({gem:l,type:"gem.requestPurchase",requestId:e,purchaseKind:t,targetId:r,currencySlug:s,...i===void 0?{}:{quantity:i},...d===void 0?{}:{catalogId:d}})}requestAvatar3dPurchase(e,t,r){return this.parentSupports("avatar3dPurchases")?this.send({gem:l,type:"gem.requestAvatar3dPurchase",requestId:e,itemId:t,currencySlug:r}):false}putDeviceSettings(e,t){return this.send({gem:l,type:"gem.deviceSettings.put",requestId:e,settings:t})}requestAd(e,t,r){return this.send({gem:l,type:"gem.requestAd",requestId:e,placement:t,format:r})}signalMoment(e,t,r,s){return this.send({gem:l,type:"gem.signalMoment",requestId:e,kind:t,...r===void 0?{}:{placement:r},...s===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,s){return this.send({gem:l,type:"gem.requestFriendChallenge",requestId:e,playerId:t,template:r,...s===void 0?{}:{params:s}})}requestArcade(e){return this.gated(x(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(O)){this.options.onDropped?.(e,t);return}this.fail(e,t);}dropUnknownType(e){this.inbound.allow(O)&&this.options.onDropped?.("unsupported",`ignored unknown message type '${e}'`);}refuse(e,t){e.ports?.[0]?.close?.(),this.inbound.allow(O)&&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=P[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||ne(t);}}dispatchInbound(e,t){if(this.state!=="connected")return false;let r=typeof e=="object"&&e!==null?e.type:void 0;if(typeof r!="string")return this.refuseMalformed("invalid_message","message has no type"),false;let s=P[r];if(!s)return this.dropUnknownType(r),false;if(!this.inbound.allow(r))return this.fail("rate_limited",`parent exceeded the limit for ${r}`),false;let i=x(r);if(i!==void 0&&!this.options.capabilities?.includes(i))return this.fail("unsupported_capability",`${r} requires the '${i}' capability, which this frame did not advertise`),false;let d=s(e);if(d)return this.fail("invalid_message",`${r}: ${d}`),false;let a=e;if(a.v!==this.version)return this.fail("invalid_message",`${r}: expected v ${String(this.version)}`),false;switch(r){case "gem.token":this.options.onToken?.(a);break;case "gem.pause":this.options.onPause?.(a);break;case "gem.menuSelect":this.options.onMenuSelect?.(a);break;case "gem.settingChange":this.options.onSettingChange?.(a);break;case "gem.prefs":this.options.onPrefs?.(a);break;case "gem.cohorts":this.options.onCohorts?.(a);break;case "gem.earnAllowanceChanged":this.options.onEarnAllowanceChanged?.();break;case "gem.viewport":this.options.onViewport?.(a);break;case "gem.willTerminate":this.options.onWillTerminate?.(a);break;case "gem.devtools":this.options.onDevtools?.(a.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:a.maxWidth,maxHeight:a.maxHeight};if(!this.options.onScreenshot){u.close(),this.screenshotDenied("not_wired",false);break}return ne(t.slice(1)),this.options.onScreenshot(p,u,(y,c)=>this.screenshotDenied(y,c)),true}case "gem.token.denied":this.options.onTokenDenied?.(a);break;case "gem.localServer":this.options.onLocalServer?.(a);break;case "gem.localServer.denied":this.options.onLocalServerDenied?.(a);break;case "gem.player":{this.options.onPlayer?.(Re(a));break}case "gem.roomEvent":this.options.onRoomEvent?.(a);break;case "gem.seatedEvent":this.options.onSeatedEvent?.(a);break;case "gem.autoStartFailedEvent":this.options.onAutoStartFailedEvent?.(a);break;case "gem.ticketEvent":this.options.onTicketEvent?.(a);break;case "gem.socketState":this.options.onSocketState?.(a);break;case "gem.signalEvent":this.options.onSignalEvent?.(a);break;case "gem.dedicatedEvent":this.options.onDedicatedEvent?.(a);break;case "gem.clusterTarget":this.options.onClusterTarget?.(a);break;case "gem.partyResult":this.options.onPartyResult?.(a);break;case "gem.purchaseResult":this.options.onPurchaseResult?.(a);break;case "gem.deviceSettings":this.options.onDeviceSettings?.(a);break;case "gem.deviceSettings.result":this.options.onDeviceSettingsResult?.(a);break;case "gem.adResult":this.options.onAdResult?.(a);break;case "gem.momentResult":this.options.onMomentResult?.(a);break;case "gem.signInResult":this.options.onSignInResult?.(a);break;case "gem.friendChallengeResult":this.options.onFriendChallengeResult?.(a);break;case "gem.error":this.options.onError?.(a.code,a.message);break;default:if(Se.includes(x(r))){this.options.onArcadeAnswer?.(a);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 ne(n){for(let e of n)try{e?.close?.();}catch{}}H();function ke(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 s=e.handleWindowMessage({data:r.data,origin:r.origin,source:r.source,ports:r.ports});return s&&window.removeEventListener("message",t),s};return window.addEventListener("message",t),B(window,t),e}var re={connect:ke,GemFrame:k,PROTOCOL:l,SUPPORTED_VERSIONS:b};window.GemWebSdkBridge=re;var pn=re;return pn;})();
|