@indiegems/gem-web-sdk 10.1.0 → 10.2.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 +22 -0
- package/dist/game.d.ts +3 -0
- package/dist/gem-web-sdk.bridge.js +1 -1
- package/dist/gem-web-sdk.esm.js +2 -2
- package/dist/gem-web-sdk.function.js +2 -2
- package/dist/gem-web-sdk.game.js +2 -2
- package/dist/gem-web-sdk.min.js +2 -2
- package/dist/gem-web-sdk.sdk.js +2 -2
- package/dist/gem-web-sdk.server-api.js +1 -1
- package/dist/gem-web-sdk.server.js +2 -2
- package/dist/index.d.ts +13 -3
- package/dist/sdk.d.ts +114 -11
- package/dist/server-api.d.ts +70 -2
- package/dist/server.d.ts +103 -3
- package/docs/api/api-reference-game.md +104 -8
- package/docs/api/api-reference-server.md +244 -4
- package/docs/api/reference.json +319 -11
- package/docs/changelog.md +22 -0
- package/docs/getting-started.md +1 -1
- package/docs/manifest.json +10 -10
- package/docs/rooms-and-matches.md +7 -0
- package/docs/server-bundles.md +46 -2
- package/docs/what-a-game-must-do.md +38 -0
- package/package.json +1 -1
- package/schema/bridge.v1.json +93 -1
- package/schema/capabilities.public.json +6 -0
package/CHANGELOG.md
CHANGED
|
@@ -16,6 +16,28 @@ Its entries are grouped under up to five headings:
|
|
|
16
16
|
- **Rebuild**: a type changed. Recompile against the new version; code that compiles today keeps compiling unless the entry says otherwise.
|
|
17
17
|
- **New capability**: something a game can now do. Nothing changes unless you use it.
|
|
18
18
|
|
|
19
|
+
## 10.2.0
|
|
20
|
+
|
|
21
|
+
Upgrading from 10.1.1. Impact: required.
|
|
22
|
+
|
|
23
|
+
### Rebuild
|
|
24
|
+
|
|
25
|
+
- The match object on the server types now has two more methods, setBackfill and reportPlayers, besides end. Recompile your server. If you wrote your own implementation or test double of the server or match server types, add the two new methods or it will no longer type-check.
|
|
26
|
+
- The list of frame-to-parent message names, the frame message type and the capability type each gained a new member for the avatar picker. Recompile. If your code switches exhaustively over any of them, or checks that every member is handled, add a case for the new avatar picker member.
|
|
27
|
+
- The order source type gained two new values, one for test account provisioning and one for developer grants, and each progression state entry in a paginated response may now carry an optional completion threshold. Recompile. If you switch exhaustively over order sources, handle the new values.
|
|
28
|
+
|
|
29
|
+
### New capability
|
|
30
|
+
|
|
31
|
+
- Games running inside the Arcade can now read the player's current Arcade avatar from GemPlayer.avatarIconId. It is only set when the value is a valid identifier, and the Arcade sends the player again whenever the worn avatar changes, so listen for player updates rather than reading it once. Games can also ask the Arcade to open its avatar picker. Check Gem.avatarPickerAvailable first, then call Gem.openAvatarPicker. It returns false outside the Arcade, before the connection is ready, when the Arcade does not offer the picker, or when you call it too often, and it never throws or waits. Nothing answers the request directly; the outcome is an updated player.
|
|
32
|
+
- If your code hosts a game frame, you can now pass the avatar identifier when sending player information and handle the avatar picker request through the new host callback and option. Incoming picker requests have a new message type with its own validator. Without a handler, the request is refused.
|
|
33
|
+
- Dedicated game servers can now control matchmaking backfill. Call setBackfill to stop or restart the platform topping up a running match from the matchmaking queue, optionally with a seat count, and it returns the resulting backfill state. Call reportPlayers to tell the platform whether each player has connected, never showed up, or left. The last two remove the player from the room. The server SDK also reports each joining player as connected on its own, which gives a seat filled from the queue a time limit. If the platform does not offer these routes, it stops trying for that match after one refused call. The matching low-level server API operations and request and response types are available too.
|
|
34
|
+
|
|
35
|
+
## 10.1.1
|
|
36
|
+
|
|
37
|
+
Upgrading from 10.1.0. Impact: none.
|
|
38
|
+
|
|
39
|
+
Nothing in this release asks anything of a game.
|
|
40
|
+
|
|
19
41
|
## 10.1.0
|
|
20
42
|
|
|
21
43
|
Upgrading from 10.0.0. Impact: required.
|
package/dist/game.d.ts
CHANGED
|
@@ -2791,6 +2791,7 @@ declare class GemFrame {
|
|
|
2791
2791
|
readonly key: string;
|
|
2792
2792
|
readonly value: string;
|
|
2793
2793
|
}>): boolean;
|
|
2794
|
+
requestAvatarPicker(): boolean;
|
|
2794
2795
|
requestVibrate(pattern: readonly number[]): boolean;
|
|
2795
2796
|
reportFrameStats(stats: {
|
|
2796
2797
|
fps: number;
|
|
@@ -2971,6 +2972,8 @@ interface Gem {
|
|
|
2971
2972
|
readonly ads: AdsApi;
|
|
2972
2973
|
readonly account: AccountApi;
|
|
2973
2974
|
readonly share: ShareApi;
|
|
2975
|
+
readonly avatarPickerAvailable: boolean;
|
|
2976
|
+
openAvatarPicker(): boolean;
|
|
2974
2977
|
readonly vibration: VibrationApi;
|
|
2975
2978
|
readonly analytics: AnalyticsApi;
|
|
2976
2979
|
readonly leaderboards: LeaderboardsApi;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var GemWebSdkBridgeBundle=(function(){'use strict';var w="GemWebSdkHandshake";function z(){return typeof document>"u"?void 0:document.readyState}var E=()=>Date.now();function I(n={}){let e=n.win??window,t=e,r=t[w];if(r!==void 0)return r;let a=n.readyState??z,i=n.now??E,d=[],s=[],m=g=>{let p=g.data;!p||p.type!=="gem.handshake"||(d.length>=4&&(d.shift(),s.shift(),c.dropped+=1),d.push(g),s.push(i()));};e.addEventListener("message",m);let c={events:d,times:s,dropped:0,late:a()==="complete",uninstall(){e.removeEventListener("message",m);}};return t[w]=c,c}function q(n,e,t={}){let r=n[w];if(r===void 0)return null;let a=t.ttlMs??9500,i=t.now??E,d=r.events.splice(0),s=r.times?.splice(0),m=0,c=0,g=false,p=i()-a;for(let u=d.length-1;u>=0;u--){let P=s?.[u];if(P!==void 0&&P<p){c+=1;continue}if(m+=1,e(d[u])===true){g=true;break}}return r.uninstall(),{capture:r,delivered:m,stale:c,accepted:g}}var l="gem-web-bridge",f={min:1,max:1},y=65536,L=8,v=5e3,A=1024;function R(n){return Object.freeze(Object.assign(Object.create(null),n))}var _=R({"gem.handshake":30,"gem.handshake.accept":5,"gem.token":30,"gem.token.denied":30,"gem.player":12,"gem.pause":120,"gem.prefs":60,"gem.cohorts":12,"gem.earnAllowanceChanged":30,"gem.viewport":60,"gem.deviceSettings":12,"gem.willTerminate":10,"gem.roomEvent":120,"gem.socketState":12,"gem.seatedEvent":60,"gem.autoStartFailedEvent":30,"gem.signalEvent":1800,"gem.dedicatedEvent":120,"gem.partyResult":30,"gem.clusterTarget":12,"gem.devtools":30,"gem.screenshot":6,"gem.screenshot.denied":12,"gem.requestContext":12,"gem.gameContext":12,"gem.signal":1200,"gem.dedicatedOffer":60,"gem.partyRequest":12,"gem.ready":5,"gem.engaged":5,"gem.progress":600,"gem.requestToken":12,"gem.requestLocalServer":6,"gem.localServer":30,"gem.localServer.denied":30,"gem.exit":5,"gem.openExternal":6,"gem.requestFullscreen":30,"gem.audioState":120,"gem.rewardCue":60,"gem.walletDisplay":60,"gem.menu":60,"gem.menuSelect":60,"gem.requestShare":6,"gem.vibrate":600,"gem.frameStats":120,"gem.portraitBorders":60,"gem.error":60,"gem.requestPurchase":12,"gem.purchaseResult":30,"gem.deviceSettings.put":30,"gem.deviceSettings.result":30,"gem.requestAd":6,"gem.adResult":12,"gem.requestSignIn":6,"gem.signInResult":12,"gem.requestFriendChallenge":12,"gem.friendChallengeResult":30,__malformed:60}),x="__malformed";var K=R({"gem.requestAd":"ads","gem.adResult":"ads","gem.requestSignIn":"signIn","gem.signInResult":"signIn","gem.requestPurchase":"purchases","gem.purchaseResult":"purchases","gem.requestFriendChallenge":"friendChallenges","gem.friendChallengeResult":"friendChallenges","gem.devtools":"devtools","gem.screenshot":"screenshot","gem.screenshot.denied":"screenshot","gem.requestContext":"feedbackContext","gem.gameContext":"feedbackContext","gem.roomEvent":"rooms","gem.signal":"p2p","gem.signalEvent":"p2p","gem.dedicatedOffer":"dedicated","gem.dedicatedEvent":"dedicated","gem.clusterTarget":"clusterTarget","gem.partyRequest":"parties","gem.partyResult":"parties","gem.autoStartFailedEvent":"autoStartFailure","gem.seatedEvent":"partySeating","gem.socketState":"socketState","gem.audioState":"audioState","gem.rewardCue":"rewardCue","gem.frameStats":"frameStats","gem.portraitBorders":"portraitBorders","gem.engaged":"engagement","gem.viewport":"viewport","gem.walletDisplay":"walletDisplay","gem.requestLocalServer":"localHost","gem.localServer":"localHost","gem.localServer.denied":"localHost","gem.cohorts":"cohorts","gem.earnAllowanceChanged":"earnAllowance","gem.deviceSettings":"deviceSettings","gem.deviceSettings.put":"deviceSettings","gem.deviceSettings.result":"deviceSettings","gem.requestShare":"share","gem.vibrate":"vibration","gem.menu":"gameMenu","gem.menuSelect":"gameMenu"}),Y=Object.freeze([["gem.asyncOpponents.","asyncOpponents"],["gem.vibration.","vibration"],["gem.viewport.","reservedAreas"]]);function j(n){let e=K[n];if(e!==void 0)return e;for(let[t,r]of Y)if(n.startsWith(t))return r}function J(n){let e=/^([a-z][a-z0-9+.-]*):\/\/([a-z0-9.-]+|\[[0-9a-f:.]+\])(:([0-9]{1,5}))?$/i.exec(n);return e===null?false:e[4]===void 0||Number(e[4])<=65535}function X(n){let e;try{e=new URL(n);}catch{return false}return e.username!==""||e.password!==""?false:e.protocol==="https:"?true:e.protocol==="http:"&&(e.hostname==="localhost"||e.hostname==="127.0.0.1")}function Q(n){return /^[a-z]{2,8}(-[a-z0-9]{1,8})*$/i.test(n)}function Z(n){return /^[a-z_]+$/.test(n)}function S(n,e,t){if(e>L)return `nesting deeper than ${L}`;if(++t.nodes>v)return `more than ${v} values`;if(t.bytes>y)return `over the ${y} byte limit`;if(n==null)return t.bytes+=4,null;let r=typeof n;if(r==="boolean")return t.bytes+=5,null;if(r==="number")return t.bytes+=8,null;if(r==="string")return t.bytes+=n.length*3+2,null;if(r!=="object")return `${r} is not plain data`;let a=n;if(t.seen.has(a))return "a repeated or cyclic object reference";if(t.seen.add(a),Array.isArray(n)){if(n.length>A)return `an array of ${n.length} entries, over the ${A} limit`;t.bytes+=2;for(let s of n){let m=S(s,e+1,t);if(m)return m}return null}let i=Object.getPrototypeOf(n);if(i!==Object.prototype&&i!==null)return "a value that is not a plain object";t.bytes+=2;let d=n;for(let s in d){if(!Object.prototype.hasOwnProperty.call(d,s))continue;if(++t.nodes>v)return `more than ${v} values`;if(t.bytes+=s.length*3+4,t.bytes>y)return `over the ${y} byte limit`;let m=S(d[s],e+1,t);if(m)return m}return null}function ee(n){let e={nodes:0,bytes:0,seen:new Set},t=S(n,0,e);return t?`message contains ${t}`:e.bytes>y?`message is over the ${y} byte limit`:null}var te={origin:[J,"not a well-formed origin"],url:[X,"not a safe absolute http(s) URL"],bcp47:[Q,"not a well-formed BCP 47 tag"],code:[Z,"not a code of lower-case letters and underscores"]};function M(n,e,t){for(let r of e){let a=t===""?r.n:`${t}.${r.n}`,i=n[r.n];if(i==null){if(r.o)continue;return `${a}: required`}let d=D(i,r,a);if(d)return d}return null}function D(n,e,t){switch(e.k){case "s":{if(typeof n!="string")return `${t}: expected string`;if(n.length>e.max)return `${t}: exceeds ${e.max} characters`;if(e.f){let[r,a]=te[e.f];if(!r(n))return `${t}: ${a}`}return null}case "i":return typeof n!="number"||!Number.isInteger(n)?`${t}: expected integer`:n<e.lo||n>e.hi?`${t}: out of range ${e.lo}..${e.hi}`:null;case "b":return typeof n=="boolean"?null:`${t}: expected boolean`;case "e":{let r=e.v;return r.includes(n)?null:`${t}: not one of ${r.join("|")}`}case "o":return typeof n!="object"||n===null||Array.isArray(n)?`${t}: expected object`:M(n,e.fs,t);case "j":return typeof n!="object"||n===null||Array.isArray(n)?`${t}: expected a plain object`:null;case "a":{if(!Array.isArray(n))return `${t}: expected array`;if(n.length>e.max)return `${t}: exceeds ${e.max} items`;let r=e.it,a=`${t}[]`;for(let i of n){if(i==null){if(r.o)continue;return `${a}: required`}let d=D(i,r,a);if(d)return d}return null}default:{let r=e.k;return `${t}: unknown kind ${String(r)}`}}}function o(n,e){return t=>{let r=ee(t);if(r)return r;if(typeof t!="object"||t===null||Array.isArray(t))return "message: expected object";let a=t;return a.gem!==l?"gem: wrong protocol marker":a.type!==n?`type: expected ${n}`:M(a,e,"")}}var ne=o("gem.handshake",[{n:"versions",k:"o",fs:[{n:"min",k:"i",lo:1,hi:1e3},{n:"max",k:"i",lo:1,hi:1e3}]},{n:"capabilities",k:"a",o:1,max:64,it:{n:"",k:"s",max:64}},{n:"embedder",k:"s",max:2048,f:"origin"},{n:"unbidden",k:"b",o:1}]),re=o("gem.handshake.accept",[{n:"v",k:"i",lo:1,hi:1e3},{n:"capabilities",k:"a",o:1,max:64,it:{n:"",k:"s",max:64}}]),oe=o("gem.token",[{n:"token",k:"s",max:4096},{n:"requestId",k:"s",o:1,max:64},{n:"generation",k:"i",lo:0,hi:2147483647},{n:"apiBaseUrl",k:"s",o:1,max:512,f:"url"},{n:"playerId",k:"s",max:64},{n:"gameId",k:"s",max:64},{n:"channel",k:"e",v:["dev","test","release"]},{n:"gameVersion",k:"s",o:1,max:64},{n:"expiresAt",k:"i",lo:0,hi:4102444800},{n:"chainEndsAt",k:"i",lo:0,hi:4102444800},{n:"allowDevTools",k:"b",o:1}]),ae=o("gem.token.denied",[{n:"requestId",k:"s",max:64},{n:"retryable",k:"b"},{n:"retryAfterMs",k:"i",o:1,lo:0,hi:36e5},{n:"reason",k:"e",v:["chain_exhausted","unavailable"]},{n:"correlationId",k:"s",max:64}]),se=o("gem.player",[{n:"untrusted",k:"o",fs:[{n:"displayName",k:"s",max:64},{n:"displayTag",k:"s",o:1,max:80},{n:"displayHandle",k:"s",max:80}]},{n:"playerId",k:"s",o:1,max:64},{n:"discriminator",k:"s",o:1,max:8},{n:"avatarIconUrl",k:"s",o:1,max:2048,f:"url"},{n:"badges",k:"a",o:1,max:2,it:{n:"",k:"o",fs:[{n:"itemId",k:"s",max:64},{n:"iconUrl",k:"s",max:2048,f:"url"}]}},{n:"displayTag",k:"s",max:8},{n:"avatarUrl",k:"s",o:1,max:2048,f:"url"},{n:"boost",k:"o",o:1,fs:[{n:"multipliers",k:"a",max:8,it:{n:"",k:"o",fs:[{n:"currencyId",k:"s",max:64},{n:"currencySlug",k:"s",max:32},{n:"multiplierBp",k:"i",lo:1e4,hi:1e6}]}},{n:"expiresInDays",k:"i",o:1,lo:1,hi:7}]}]),ie=o("gem.pause",[{n:"paused",k:"b"}]),le=o("gem.prefs",[{n:"reducedMotion",k:"b"},{n:"muted",k:"b"},{n:"showFrameStats",k:"b",o:1},{n:"locale",k:"s",max:35,f:"bcp47"},{n:"recommended",k:"o",o:1,fs:[{n:"volume",k:"i",lo:0,hi:100},{n:"batterySaver",k:"b"},{n:"keyboardLayout",k:"e",v:["wasd","arrows"]},{n:"gamepadConfirm",k:"e",v:["south","east"]},{n:"vibration",k:"b"}]}]),de=o("gem.cohorts",[{n:"cohorts",k:"a",max:8,it:{n:"",k:"o",fs:[{n:"experimentId",k:"s",max:36},{n:"variantKey",k:"s",max:32}]}}]),me=o("gem.earnAllowanceChanged",[]),ue=o("gem.viewport",[{n:"insets",k:"o",fs:[{n:"top",k:"i",lo:0,hi:4096},{n:"right",k:"i",lo:0,hi:4096},{n:"bottom",k:"i",lo:0,hi:4096},{n:"left",k:"i",lo:0,hi:4096}]},{n:"reserved",k:"a",o:1,max:4,it:{n:"",k:"o",fs:[{n:"x",k:"i",lo:0,hi:16384},{n:"y",k:"i",lo:0,hi:16384},{n:"width",k:"i",lo:0,hi:16384},{n:"height",k:"i",lo:0,hi:16384}]}}]),ce=o("gem.deviceSettings",[{n:"settings",k:"j",o:1}]),ge=o("gem.willTerminate",[{n:"reason",k:"e",v:["grant_expiring","session_ended","navigating","kill_switch"]},{n:"graceMs",k:"i",lo:0,hi:6e4}]),pe=o("gem.roomEvent",[{n:"event",k:"e",v:["updated","match_started","match_ready","match_failed","version_stale"]},{n:"roomId",k:"s",max:64},{n:"matchId",k:"s",o:1,max:64},{n:"version",k:"i",o:1,lo:0,hi:2147483647},{n:"reason",k:"s",o:1,max:64},{n:"platform",k:"e",o:1,v:["universal","mobile"]}]),ye=o("gem.socketState",[{n:"connected",k:"b"},{n:"reason",k:"e",o:1,v:["connecting","dropped","watchdog","terminal"]}]),fe=o("gem.seatedEvent",[{n:"roomId",k:"s",max:64}]),he=o("gem.autoStartFailedEvent",[{n:"roomId",k:"s",max:64},{n:"code",k:"s",max:64}]),ke=o("gem.signalEvent",[{n:"event",k:"e",v:["hello","offer","answer","ice","peerJoined","peerLeft","migration","matchEnded","error"]},{n:"matchId",k:"s",max:64},{n:"data",k:"j"}]),ve=o("gem.dedicatedEvent",[{n:"event",k:"e",v:["answer","error","matchEnded"]},{n:"matchId",k:"s",max:64},{n:"sdp",k:"s",o:1,max:10240},{n:"sessionId",k:"s",o:1,max:64},{n:"code",k:"s",o:1,max:64},{n:"message",k:"s",o:1,max:256},{n:"reason",k:"s",o:1,max:64}]),xe=o("gem.partyResult",[{n:"requestId",k:"s",max:64},{n:"partyId",k:"s",o:1,max:64}]),be=o("gem.clusterTarget",[{n:"clusterTargetId",k:"s",max:64},{n:"clusterTargetIds",k:"a",o:1,max:3,it:{n:"",k:"s",max:64}}]),we=o("gem.devtools",[{n:"action",k:"e",v:["open","close","toggle"]}]),Se=o("gem.screenshot",[{n:"maxWidth",k:"i",lo:1,hi:7680},{n:"maxHeight",k:"i",lo:1,hi:4320}]),Re=o("gem.screenshot.denied",[{n:"reason",k:"e",v:["not_wired","no_source","unsupported","unreadable","tainted","too_large","busy","declined","failed"]},{n:"retryable",k:"b"}]),Ge=o("gem.requestContext",[]),Oe=o("gem.gameContext",[{n:"context",k:"j"}]),Ce=o("gem.signal",[{n:"signal",k:"e",v:["join","offer","answer","ice","migrationAck","hostUnreachable"]},{n:"matchId",k:"s",max:64},{n:"data",k:"j"}]),Te=o("gem.dedicatedOffer",[{n:"matchId",k:"s",max:64},{n:"sdp",k:"s",max:10240},{n:"intent",k:"e",v:["initial","ice_restart","full_reconnect"]}]),Pe=o("gem.partyRequest",[{n:"requestId",k:"s",max:64}]),Ee=o("gem.ready",[]),Ie=o("gem.engaged",[]),qe=o("gem.progress",[{n:"loaded",k:"i",lo:0,hi:1099511627776},{n:"total",k:"i",lo:0,hi:1099511627776}]),Le=o("gem.requestToken",[{n:"requestId",k:"s",max:64},{n:"reason",k:"e",v:["initial","expiring","rejected"]}]),Ae=o("gem.requestLocalServer",[{n:"requestId",k:"s",max:64},{n:"gameRoomId",k:"s",max:64}]),_e=o("gem.localServer",[{n:"requestId",k:"s",max:64},{n:"serverId",k:"s",o:1,max:128}]),je=o("gem.localServer.denied",[{n:"requestId",k:"s",max:64},{n:"retryable",k:"b"},{n:"reason",k:"e",v:["refused","unavailable"]}]),Me=o("gem.exit",[{n:"reason",k:"s",o:1,max:64}]),De=o("gem.openExternal",[{n:"url",k:"s",max:2048,f:"url"}]),Fe=o("gem.requestFullscreen",[{n:"enabled",k:"b"}]),$e=o("gem.audioState",[{n:"muted",k:"b"}]),He=o("gem.rewardCue",[{n:"currencySlug",k:"s",max:32},{n:"expected",k:"i",o:1,lo:1,hi:1e9},{n:"origin",k:"o",o:1,fs:[{n:"x",k:"i",lo:0,hi:16384},{n:"y",k:"i",lo:0,hi:16384}]}]),Be=o("gem.walletDisplay",[{n:"visible",k:"b"},{n:"currencies",k:"a",o:1,max:8,it:{n:"",k:"s",max:64}},{n:"score",k:"b",o:1}]),Ue=o("gem.menu",[{n:"settings",k:"b"},{n:"items",k:"a",o:1,max:4,it:{n:"",k:"o",fs:[{n:"id",k:"s",max:32},{n:"label",k:"s",max:40}]}}]),We=o("gem.menuSelect",[{n:"entry",k:"e",v:["settings","item"]},{n:"id",k:"s",o:1,max:32}]),Ne=o("gem.requestShare",[{n:"params",k:"a",max:16,it:{n:"",k:"o",fs:[{n:"key",k:"s",max:64},{n:"value",k:"s",max:512}]}}]),Ve=o("gem.vibrate",[{n:"pattern",k:"a",max:99,it:{n:"",k:"i",lo:0,hi:1e4}}]),ze=o("gem.frameStats",[{n:"fps",k:"i",lo:0,hi:1e3},{n:"frameTimeP95Ms",k:"i",lo:0,hi:1e5}]),Ke=o("gem.portraitBorders",[{n:"name",k:"s",o:1,max:40}]),Ye=o("gem.error",[{n:"code",k:"e",v:["version_mismatch","handshake_timeout","handshake_duplicate","invalid_message","rate_limited","token_unavailable","unsupported","unsupported_capability","internal"]},{n:"message",k:"s",o:1,max:256}]),Je=o("gem.requestPurchase",[{n:"requestId",k:"s",max:64},{n:"purchaseKind",k:"e",v:["item","recipe"]},{n:"targetId",k:"s",max:64},{n:"currencySlug",k:"s",max:32},{n:"quantity",k:"i",o:1,lo:1,hi:10},{n:"catalogId",k:"s",o:1,max:64}]),Xe=o("gem.purchaseResult",[{n:"requestId",k:"s",max:64},{n:"outcome",k:"e",v:["ok","declined","unavailable"]},{n:"reason",k:"s",o:1,max:64,f:"code"},{n:"purchaseId",k:"s",o:1,max:64}]),Qe=o("gem.deviceSettings.put",[{n:"requestId",k:"s",max:64},{n:"settings",k:"j"}]),Ze=o("gem.deviceSettings.result",[{n:"requestId",k:"s",max:64},{n:"outcome",k:"e",v:["stored","too_large","unavailable"]}]),et=o("gem.requestAd",[{n:"requestId",k:"s",max:64},{n:"placement",k:"s",max:32},{n:"format",k:"e",v:["interstitial","rewarded"]}]),tt=o("gem.adResult",[{n:"requestId",k:"s",max:64},{n:"outcome",k:"e",v:["shown","no_ad","unavailable"]}]),nt=o("gem.requestSignIn",[{n:"requestId",k:"s",max:64}]),rt=o("gem.signInResult",[{n:"requestId",k:"s",max:64},{n:"outcome",k:"e",v:["signed_in","declined","unavailable"]}]),ot=o("gem.requestFriendChallenge",[{n:"requestId",k:"s",max:64},{n:"playerId",k:"s",max:64},{n:"template",k:"s",max:64},{n:"params",k:"j",o:1}]),at=o("gem.friendChallengeResult",[{n:"requestId",k:"s",max:64},{n:"outcome",k:"e",v:["accepted","cancelled","refused","unavailable","rate_limited","invalid"]},{n:"code",k:"s",o:1,max:64},{n:"param",k:"s",o:1,max:64},{n:"channel",k:"s",o:1,max:16},{n:"configVersion",k:"i",o:1,lo:0,hi:9007199254740991},{n:"retryAfterMs",k:"i",o:1,lo:0,hi:864e5},{n:"detail",k:"s",o:1,max:300}]),b=R({"gem.handshake":ne,"gem.handshake.accept":re,"gem.token":oe,"gem.token.denied":ae,"gem.player":se,"gem.pause":ie,"gem.prefs":le,"gem.cohorts":de,"gem.earnAllowanceChanged":me,"gem.viewport":ue,"gem.deviceSettings":ce,"gem.willTerminate":ge,"gem.roomEvent":pe,"gem.socketState":ye,"gem.seatedEvent":fe,"gem.autoStartFailedEvent":he,"gem.signalEvent":ke,"gem.dedicatedEvent":ve,"gem.partyResult":xe,"gem.clusterTarget":be,"gem.devtools":we,"gem.screenshot":Se,"gem.screenshot.denied":Re,"gem.requestContext":Ge,"gem.gameContext":Oe,"gem.signal":Ce,"gem.dedicatedOffer":Te,"gem.partyRequest":Pe,"gem.ready":Ee,"gem.engaged":Ie,"gem.progress":qe,"gem.requestToken":Le,"gem.requestLocalServer":Ae,"gem.localServer":_e,"gem.localServer.denied":je,"gem.exit":Me,"gem.openExternal":De,"gem.requestFullscreen":Fe,"gem.audioState":$e,"gem.rewardCue":He,"gem.walletDisplay":Be,"gem.menu":Ue,"gem.menuSelect":We,"gem.requestShare":Ne,"gem.vibrate":Ve,"gem.frameStats":ze,"gem.portraitBorders":Ke,"gem.error":Ye,"gem.requestPurchase":Je,"gem.purchaseResult":Xe,"gem.deviceSettings.put":Qe,"gem.deviceSettings.result":Ze,"gem.requestAd":et,"gem.adResult":tt,"gem.requestSignIn":nt,"gem.signInResult":rt,"gem.requestFriendChallenge":ot,"gem.friendChallengeResult":at});var st=/^[a-z0-9][a-z0-9_-]{0,39}$/;function it(n){return typeof n=="string"&&st.test(n)}function F(n){if(n===null||it(n))return n;let e=typeof n=="string"?JSON.stringify(n.length>48?`${n.slice(0,48)}\u2026`:n):`a value of type ${typeof n}`;console.warn(`[gem] showPortraitBorders: ${e} is not a border name, so nothing was sent. A name is 1 to 40 of a-z, 0-9, _ and -, starting with a letter or digit, exactly as your store page declares it under media.portrait_borders. Pass null for no art.`);}var G=class{#e;constructor(e){this.#e=e,Object.freeze(this);}toString(){return "[gem: use gem.text.toPlain()]"}toJSON(){return this.toString()}get[Symbol.toStringTag](){return "PlayerText"}static unwrap(e){return e.#e}};function O(n){return new G(n)}var C={now:()=>Date.now(),setTimeout:(n,e)=>setTimeout(n,e),clearTimeout:n=>clearTimeout(n)},h=class{constructor(e=C){this.clock=e;}clock;tokens=new Map;lastRefill=new Map;allow(e){let t=_[e];if(t===void 0)return false;let r=this.clock.now(),a=this.lastRefill.get(e)??r,i=this.tokens.get(e)??t,d=Math.max(0,r-a),s=Math.min(t,i+d*t/6e4);return s<1?(this.tokens.set(e,s),this.lastRefill.set(e,r),false):(this.tokens.set(e,s-1),this.lastRefill.set(e,r),true)}};function T(n,e){return n.toLowerCase()===e.toLowerCase()}function $(n){let e=n.toLowerCase();return e==="localhost"||e.endsWith(".localhost")||e==="[::1]"||e==="::1"?true:/^127(\.\d{1,3}){3}$/.test(e)}function H(n,e){if(typeof e!="string"||e==="")return false;let t,r;try{t=new URL(n),r=new URL(e);}catch{return false}return t.protocol!=="http:"&&t.protocol!=="https:"||r.protocol!=="http:"&&r.protocol!=="https:"||t.username!==""||t.password!==""||t.pathname!=="/"||t.search!==""||t.hash!==""||t.port===""?false:$(t.hostname)&&$(r.hostname)}function B(n,e){if(n.min>n.max||e.min>e.max)return null;let t=Math.min(n.max,e.max),r=Math.max(n.min,e.min);return t>=r?t:null}function U(n){return Math.min(16384,Math.max(0,Math.round(Number.isFinite(n)?n:0)))}function lt(n,e){if(n!==true)return {visible:false};let t=[],r=false;for(let a of Array.isArray(e)?e:[])a==="score"?r=true:typeof a=="string"&&a.length>0&&a.length<=64&&!t.includes(a)&&t.push(a);return !r&&t.length===0?{visible:true}:{visible:true,currencies:t.slice(0,8),score:r}}function dt(n,e){let t=[];for(let r of Array.isArray(e)?e:[]){if(t.length===4)break;if(typeof r!="object"||r===null)continue;let{id:a,label:i}=r;typeof a!="string"||a.length===0||a.length>32||typeof i!="string"||i.trim().length===0||t.some(d=>d.id===a)||t.push({id:a,label:i.trim().slice(0,40)});}return t.length===0?{settings:n===true}:{settings:n===true,items:t}}function W(n,e){return Math.min(e,Math.max(0,Math.round(Number.isFinite(n)?n:0)))}function mt(n){let e=n.untrusted,t=O(e.displayName),r=e.displayTag||e.displayHandle,a=r?O(r):void 0,i=n.discriminator||n.displayTag,d=i&&/^[0-9]{1,8}$/.test(i)?i:void 0,s=n.avatarIconUrl||n.avatarUrl,m={displayName:t,displayHandle:a??t,badges:(n.badges??[]).map(u=>({itemId:u.itemId,iconUrl:u.iconUrl}))};n.playerId&&(m.playerId=n.playerId),d&&(m.discriminator=d),a&&(m.displayTag=a),s&&(m.avatarIconUrl=m.avatarUrl=s);let c=n.boost,g=(c?.multipliers??[]).map(u=>({currencyId:u.currencyId,currencySlug:u.currencySlug,multiplier:u.multiplierBp/1e4})),p=g.some(u=>u.multiplier>1);return m.boost=p&&c?.expiresInDays?{active:p,multipliers:g,expiresInDays:c.expiresInDays}:{active:p,multipliers:g},m}var ut=1e4,k=class{constructor(e){this.options=e;if(e.expectedSource===void 0||e.expectedSource===null)throw new Error("GemFrame: expectedSource is required and must not be null \u2014 pass window.parent. The handshake transfers the MessagePort, and origin alone does not say WHICH document on that origin sent it.");this.expectedSource=e.expectedSource,this.clock=e.clock??C,this.inbound=new h(this.clock),this.outbound=new h(this.clock);}options;state="waiting";port=null;version=null;peerCapabilities=[];unbidden=false;engagedSent=false;readyPending=false;readySent=false;settleWaiters=[];clock;inbound;outbound;expectedSource;get currentState(){return this.state}get parentCapabilities(){return this.peerCapabilities}parentSupports(e){return this.peerCapabilities.includes(e)}get protocolVersion(){return this.version}get unbiddenLaunch(){return this.unbidden}handleWindowMessage(e){if(e.source!==this.expectedSource)return this.refuse(e,"handshake did not come from the expected embedder window"),false;if(!(this.options.allowedEmbedders.some(s=>T(s,e.origin))||H(e.origin,this.options.selfOrigin)))return this.refuse(e,`embedder '${e.origin}' is not in allowedEmbedders`),this.state==="waiting"&&this.transition("refused"),false;if(this.state==="connected")return this.fail("handshake_duplicate","this document already has a port"),false;if(this.state!=="waiting")return false;let r=b["gem.handshake"]?.(e.data);if(r)return this.refuse(e,`malformed handshake: ${r}`),false;let a=e.data;if(!T(a.embedder,e.origin))return this.refuse(e,`handshake claims embedder '${a.embedder}' but arrived from '${e.origin}'`),false;let i=e.ports?.[0];if(!i)return this.refuse(e,"handshake transferred no MessagePort"),false;let d=B(f,a.versions);return d===null?(i.onmessage=null,i.postMessage({gem:l,type:"gem.error",code:"version_mismatch",message:`frame supports v${f.min}..v${f.max}`}),i.close(),this.transition("refused"),this.options.onError?.("version_mismatch"),false):(this.port=i,this.version=d,i.onmessage=s=>this.receive(s.data,s.ports??[]),i.start?.(),this.peerCapabilities=a.capabilities??[],this.unbidden=a.unbidden===true,i.postMessage({gem:l,type:"gem.handshake.accept",v:d,...this.options.capabilities===void 0?{}:{capabilities:[...this.options.capabilities]}}),this.transition("connected"),this.readyPending&&(this.readyPending=false,this.ready()),true)}ready(){if(this.state!=="connected"||!this.port){this.readyPending=true;return}if(this.readySent){this.options.onDropped?.("internal","gem.ready was already sent; duplicate suppressed");return}this.readySent=true,this.send({gem:l,type:"gem.ready"});}settled(e=ut){return this.state!=="waiting"?Promise.resolve(this.state):new Promise(t=>{let r=i=>{this.clock.clearTimeout(a),t(i);},a=this.clock.setTimeout(()=>{let i=this.settleWaiters.indexOf(r);i>=0&&this.settleWaiters.splice(i,1),t(this.state);},e);this.settleWaiters.push(r);})}progress(e,t){this.send({gem:l,type:"gem.progress",loaded:e,total:t});}requestToken(e,t){this.send({gem:l,type:"gem.requestToken",requestId:e,reason:t});}requestLocalServer(e,t){return this.parentSupports("localHost")?(this.send({gem:l,type:"gem.requestLocalServer",requestId:e,gameRoomId:t}),true):false}exit(e){this.send(e===void 0?{gem:l,type:"gem.exit"}:{gem:l,type:"gem.exit",reason:e});}openExternal(e){this.send({gem:l,type:"gem.openExternal",url:e});}requestFullscreen(e){this.send({gem:l,type:"gem.requestFullscreen",enabled:e});}reportMuted(e){return this.state!=="connected"||!this.parentSupports("audioState")?false:(this.send({gem:l,type:"gem.audioState",muted:e}),true)}reportEngaged(){return this.engagedSent||this.state!=="connected"||!this.parentSupports("engagement")||!this.send({gem:l,type:"gem.engaged"})?false:(this.engagedSent=true,true)}cueReward(e){if(this.state!=="connected"||!this.parentSupports("rewardCue"))return false;let t={gem:l,type:"gem.rewardCue",currencySlug:String(e.currencySlug).slice(0,32)};return e.expected!==void 0&&Number.isFinite(e.expected)&&e.expected>=1&&(t.expected=Math.min(1e9,Math.round(e.expected))),e.origin&&(t.origin={x:U(e.origin.x),y:U(e.origin.y)}),this.send(t),true}showPortraitBorders(e){let t=F(e);return t===void 0||this.state!=="connected"||!this.parentSupports("portraitBorders")?false:this.send(t===null?{gem:l,type:"gem.portraitBorders"}:{gem:l,type:"gem.portraitBorders",name:t})}setWalletVisible(e,t){return this.state!=="connected"||!this.parentSupports("walletDisplay")?false:this.send({gem:l,type:"gem.walletDisplay",...lt(e,t?.only)})}setMenu(e,t){return this.state!=="connected"||!this.parentSupports("gameMenu")?false:this.send({gem:l,type:"gem.menu",...dt(e,t)})}requestShare(e){return this.state!=="connected"||!this.parentSupports("share")?false:this.send({gem:l,type:"gem.requestShare",params:e.map(({key:t,value:r})=>({key:t,value:r}))})}requestVibrate(e){return this.state!=="connected"||!this.parentSupports("vibration")?false:this.send({gem:l,type:"gem.vibrate",pattern:[...e]})}reportFrameStats(e){return this.state!=="connected"||!this.parentSupports("frameStats")?false:(this.send({gem:l,type:"gem.frameStats",fps:W(e.fps,1e3),frameTimeP95Ms:W(e.frameTimeP95Ms,1e5)}),true)}sendGameContext(e){return this.state!=="connected"?false:(this.send({gem:l,type:"gem.gameContext",context:e}),true)}signal(e,t,r){this.send({gem:l,type:"gem.signal",signal:e,matchId:t,data:r});}dedicatedOffer(e,t,r){this.send({gem:l,type:"gem.dedicatedOffer",matchId:e,sdp:t,intent:r});}requestParty(e){return this.send({gem:l,type:"gem.partyRequest",requestId:e})}requestPurchase(e,t,r,a,i,d){return this.send({gem:l,type:"gem.requestPurchase",requestId:e,purchaseKind:t,targetId:r,currencySlug:a,...i===void 0?{}:{quantity:i},...d===void 0?{}:{catalogId:d}})}putDeviceSettings(e,t){return this.send({gem:l,type:"gem.deviceSettings.put",requestId:e,settings:t})}requestAd(e,t,r){return this.send({gem:l,type:"gem.requestAd",requestId:e,placement:t,format:r})}requestSignIn(e){return this.send({gem:l,type:"gem.requestSignIn",requestId:e})}requestFriendChallenge(e,t,r,a){return this.send({gem:l,type:"gem.requestFriendChallenge",requestId:e,playerId:t,template:r,...a===void 0?{}:{params:a}})}close(){this.port&&(this.port.onmessage=null,this.port.close(),this.port=null),this.state!=="refused"&&this.transition("closed");}transition(e){if(this.state!==e){this.state=e;for(let t of this.settleWaiters.splice(0))t(e);this.options.onStateChange?.(e);}}refuseMalformed(e,t){if(!this.inbound.allow(x)){this.options.onDropped?.(e,t);return}this.fail(e,t);}dropUnknownType(e){this.inbound.allow(x)&&this.options.onDropped?.("unsupported",`ignored unknown message type '${e}'`);}refuse(e,t){e.ports?.[0]?.close?.(),this.inbound.allow(x)&&this.options.onRefused?.(t);}fail(e,t){this.options.onError?.(e,t),this.state==="connected"&&this.port&&this.send({gem:l,type:"gem.error",code:e,...t===void 0?{}:{message:t}});}send(e){if(this.state!=="connected"||!this.port)return this.options.onDropped?.("internal",`dropped ${String(e.type)} before connect`),false;let t=e.type;if(!this.outbound.allow(t))return this.options.onError?.("rate_limited",`frame exceeded its own limit for ${t}`),false;let r=b[t]?.(e);return r?(this.options.onError?.("internal",`refusing to send malformed ${t}: ${r}`),false):(this.port.postMessage(this.version===null?e:{...e,v:this.version}),true)}receive(e,t=[]){let r=false;try{r=this.dispatchInbound(e,t);}finally{r||N(t);}}dispatchInbound(e,t){if(this.state!=="connected")return false;let r=typeof e=="object"&&e!==null?e.type:void 0;if(typeof r!="string")return this.refuseMalformed("invalid_message","message has no type"),false;let a=b[r];if(!a)return this.dropUnknownType(r),false;if(!this.inbound.allow(r))return this.fail("rate_limited",`parent exceeded the limit for ${r}`),false;let i=j(r);if(i!==void 0&&!this.options.capabilities?.includes(i))return this.fail("unsupported_capability",`${r} requires the '${i}' capability, which this frame did not advertise`),false;let d=a(e);if(d)return this.fail("invalid_message",`${r}: ${d}`),false;let s=e;if(s.v!==this.version)return this.fail("invalid_message",`${r}: expected v ${String(this.version)}`),false;switch(r){case "gem.token":this.options.onToken?.(s);break;case "gem.pause":this.options.onPause?.(s);break;case "gem.menuSelect":this.options.onMenuSelect?.(s);break;case "gem.prefs":this.options.onPrefs?.(s);break;case "gem.cohorts":this.options.onCohorts?.(s);break;case "gem.earnAllowanceChanged":this.options.onEarnAllowanceChanged?.();break;case "gem.viewport":this.options.onViewport?.(s);break;case "gem.willTerminate":this.options.onWillTerminate?.(s);break;case "gem.devtools":this.options.onDevtools?.(s.action);break;case "gem.requestContext":this.options.onRequestContext?.();break;case "gem.screenshot":{let m=t[0];if(!m){this.options.onError?.("invalid_message","gem.screenshot transferred no MessagePort");break}let c={maxWidth:s.maxWidth,maxHeight:s.maxHeight};if(!this.options.onScreenshot){m.close(),this.screenshotDenied("not_wired",false);break}return N(t.slice(1)),this.options.onScreenshot(c,m,(g,p)=>this.screenshotDenied(g,p)),true}case "gem.token.denied":this.options.onTokenDenied?.(s);break;case "gem.localServer":this.options.onLocalServer?.(s);break;case "gem.localServer.denied":this.options.onLocalServerDenied?.(s);break;case "gem.player":{this.options.onPlayer?.(mt(s));break}case "gem.roomEvent":this.options.onRoomEvent?.(s);break;case "gem.seatedEvent":this.options.onSeatedEvent?.(s);break;case "gem.autoStartFailedEvent":this.options.onAutoStartFailedEvent?.(s);break;case "gem.socketState":this.options.onSocketState?.(s);break;case "gem.signalEvent":this.options.onSignalEvent?.(s);break;case "gem.dedicatedEvent":this.options.onDedicatedEvent?.(s);break;case "gem.clusterTarget":this.options.onClusterTarget?.(s);break;case "gem.partyResult":this.options.onPartyResult?.(s);break;case "gem.purchaseResult":this.options.onPurchaseResult?.(s);break;case "gem.deviceSettings":this.options.onDeviceSettings?.(s);break;case "gem.deviceSettings.result":this.options.onDeviceSettingsResult?.(s);break;case "gem.adResult":this.options.onAdResult?.(s);break;case "gem.signInResult":this.options.onSignInResult?.(s);break;case "gem.friendChallengeResult":this.options.onFriendChallengeResult?.(s);break;case "gem.error":this.options.onError?.(s.code,s.message);break;default:this.fail("unsupported",`no frame handler for '${r}'`);}return false}screenshotDenied(e,t){this.send({gem:l,type:"gem.screenshot.denied",reason:e,retryable:t});}};function N(n){for(let e of n)try{e?.close?.();}catch{}}I();function ct(n){if((n.expectedSource??window.parent)===window)throw new Error("GemWebSdkBridge.connect: this document is not framed (window.parent === window), so there is no embedder to hand it a port. A game runs inside the Gem Arcade iframe; opening it directly will never complete a handshake.");let e=new k({...n,expectedSource:n.expectedSource??window.parent}),t=r=>{let a=e.handleWindowMessage({data:r.data,origin:r.origin,source:r.source,ports:r.ports});return a&&window.removeEventListener("message",t),a};return window.addEventListener("message",t),q(window,t),e}var V={connect:ct,GemFrame:k,PROTOCOL:l,SUPPORTED_VERSIONS:f};window.GemWebSdkBridge=V;var Ct=V;return Ct;})();
|
|
1
|
+
var GemWebSdkBridgeBundle=(function(){'use strict';var S="GemWebSdkHandshake";function z(){return typeof document>"u"?void 0:document.readyState}var E=()=>Date.now();function I(n={}){let e=n.win??window,t=e,r=t[S];if(r!==void 0)return r;let o=n.readyState??z,i=n.now??E,d=[],s=[],m=c=>{let p=c.data;!p||p.type!=="gem.handshake"||(d.length>=4&&(d.shift(),s.shift(),u.dropped+=1),d.push(c),s.push(i()));};e.addEventListener("message",m);let u={events:d,times:s,dropped:0,late:o()==="complete",uninstall(){e.removeEventListener("message",m);}};return t[S]=u,u}function q(n,e,t={}){let r=n[S];if(r===void 0)return null;let o=t.ttlMs??9500,i=t.now??E,d=r.events.splice(0),s=r.times?.splice(0),m=0,u=0,c=false,p=i()-o;for(let y=d.length-1;y>=0;y--){let g=s?.[y];if(g!==void 0&&g<p){u+=1;continue}if(m+=1,e(d[y])===true){c=true;break}}return r.uninstall(),{capture:r,delivered:m,stale:u,accepted:c}}var l="gem-web-bridge",h={min:1,max:1},f=65536,A=8,x=5e3,L=1024;function G(n){return Object.freeze(Object.assign(Object.create(null),n))}var _=G({"gem.handshake":30,"gem.handshake.accept":5,"gem.token":30,"gem.token.denied":30,"gem.player":12,"gem.pause":120,"gem.prefs":60,"gem.cohorts":12,"gem.earnAllowanceChanged":30,"gem.viewport":60,"gem.deviceSettings":12,"gem.willTerminate":10,"gem.roomEvent":120,"gem.socketState":12,"gem.seatedEvent":60,"gem.autoStartFailedEvent":30,"gem.signalEvent":1800,"gem.dedicatedEvent":120,"gem.partyResult":30,"gem.clusterTarget":12,"gem.devtools":30,"gem.screenshot":6,"gem.screenshot.denied":12,"gem.requestContext":12,"gem.gameContext":12,"gem.signal":1200,"gem.dedicatedOffer":60,"gem.partyRequest":12,"gem.ready":5,"gem.engaged":5,"gem.progress":600,"gem.requestToken":12,"gem.requestLocalServer":6,"gem.localServer":30,"gem.localServer.denied":30,"gem.exit":5,"gem.openExternal":6,"gem.requestFullscreen":30,"gem.audioState":120,"gem.rewardCue":60,"gem.walletDisplay":60,"gem.menu":60,"gem.menuSelect":60,"gem.requestShare":6,"gem.requestAvatarPicker":6,"gem.vibrate":600,"gem.frameStats":120,"gem.portraitBorders":60,"gem.error":60,"gem.requestPurchase":12,"gem.purchaseResult":30,"gem.deviceSettings.put":30,"gem.deviceSettings.result":30,"gem.requestAd":6,"gem.adResult":12,"gem.requestSignIn":6,"gem.signInResult":12,"gem.requestFriendChallenge":12,"gem.friendChallengeResult":30,__malformed:60}),b="__malformed";var K=G({"gem.requestAd":"ads","gem.adResult":"ads","gem.requestSignIn":"signIn","gem.signInResult":"signIn","gem.requestPurchase":"purchases","gem.purchaseResult":"purchases","gem.requestFriendChallenge":"friendChallenges","gem.friendChallengeResult":"friendChallenges","gem.devtools":"devtools","gem.screenshot":"screenshot","gem.screenshot.denied":"screenshot","gem.requestContext":"feedbackContext","gem.gameContext":"feedbackContext","gem.roomEvent":"rooms","gem.signal":"p2p","gem.signalEvent":"p2p","gem.dedicatedOffer":"dedicated","gem.dedicatedEvent":"dedicated","gem.clusterTarget":"clusterTarget","gem.partyRequest":"parties","gem.partyResult":"parties","gem.autoStartFailedEvent":"autoStartFailure","gem.seatedEvent":"partySeating","gem.socketState":"socketState","gem.audioState":"audioState","gem.rewardCue":"rewardCue","gem.frameStats":"frameStats","gem.portraitBorders":"portraitBorders","gem.engaged":"engagement","gem.viewport":"viewport","gem.walletDisplay":"walletDisplay","gem.requestLocalServer":"localHost","gem.localServer":"localHost","gem.localServer.denied":"localHost","gem.cohorts":"cohorts","gem.earnAllowanceChanged":"earnAllowance","gem.deviceSettings":"deviceSettings","gem.deviceSettings.put":"deviceSettings","gem.deviceSettings.result":"deviceSettings","gem.requestShare":"share","gem.requestAvatarPicker":"avatarPicker","gem.vibrate":"vibration","gem.menu":"gameMenu","gem.menuSelect":"gameMenu"}),Y=Object.freeze([["gem.asyncOpponents.","asyncOpponents"],["gem.vibration.","vibration"],["gem.viewport.","reservedAreas"]]);function j(n){let e=K[n];if(e!==void 0)return e;for(let[t,r]of Y)if(n.startsWith(t))return r}function J(n){let e=/^([a-z][a-z0-9+.-]*):\/\/([a-z0-9.-]+|\[[0-9a-f:.]+\])(:([0-9]{1,5}))?$/i.exec(n);return e===null?false:e[4]===void 0||Number(e[4])<=65535}function X(n){let e;try{e=new URL(n);}catch{return false}return e.username!==""||e.password!==""?false:e.protocol==="https:"?true:e.protocol==="http:"&&(e.hostname==="localhost"||e.hostname==="127.0.0.1")}function Q(n){return /^[a-z]{2,8}(-[a-z0-9]{1,8})*$/i.test(n)}function Z(n){return /^[a-z_]+$/.test(n)}function R(n,e,t){if(e>A)return `nesting deeper than ${A}`;if(++t.nodes>x)return `more than ${x} values`;if(t.bytes>f)return `over the ${f} byte limit`;if(n==null)return t.bytes+=4,null;let r=typeof n;if(r==="boolean")return t.bytes+=5,null;if(r==="number")return t.bytes+=8,null;if(r==="string")return t.bytes+=n.length*3+2,null;if(r!=="object")return `${r} is not plain data`;let 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>L)return `an array of ${n.length} entries, over the ${L} limit`;t.bytes+=2;for(let s of n){let m=R(s,e+1,t);if(m)return m}return null}let i=Object.getPrototypeOf(n);if(i!==Object.prototype&&i!==null)return "a value that is not a plain object";t.bytes+=2;let d=n;for(let s in d){if(!Object.prototype.hasOwnProperty.call(d,s))continue;if(++t.nodes>x)return `more than ${x} values`;if(t.bytes+=s.length*3+4,t.bytes>f)return `over the ${f} byte limit`;let m=R(d[s],e+1,t);if(m)return m}return null}function ee(n){let e={nodes:0,bytes:0,seen:new Set},t=R(n,0,e);return t?`message contains ${t}`:e.bytes>f?`message is over the ${f} byte limit`:null}var te={origin:[J,"not a well-formed origin"],url:[X,"not a safe absolute http(s) URL"],bcp47:[Q,"not a well-formed BCP 47 tag"],code:[Z,"not a code of lower-case letters and underscores"]};function M(n,e,t){for(let r of e){let o=t===""?r.n:`${t}.${r.n}`,i=n[r.n];if(i==null){if(r.o)continue;return `${o}: required`}let d=D(i,r,o);if(d)return d}return null}function D(n,e,t){switch(e.k){case "s":{if(typeof n!="string")return `${t}: expected string`;if(n.length>e.max)return `${t}: exceeds ${e.max} characters`;if(e.f){let[r,o]=te[e.f];if(!r(n))return `${t}: ${o}`}return null}case "i":return typeof n!="number"||!Number.isInteger(n)?`${t}: expected integer`:n<e.lo||n>e.hi?`${t}: out of range ${e.lo}..${e.hi}`:null;case "b":return typeof n=="boolean"?null:`${t}: expected boolean`;case "e":{let r=e.v;return r.includes(n)?null:`${t}: not one of ${r.join("|")}`}case "o":return typeof n!="object"||n===null||Array.isArray(n)?`${t}: expected object`:M(n,e.fs,t);case "j":return typeof n!="object"||n===null||Array.isArray(n)?`${t}: expected a plain object`:null;case "a":{if(!Array.isArray(n))return `${t}: expected array`;if(n.length>e.max)return `${t}: exceeds ${e.max} items`;let r=e.it,o=`${t}[]`;for(let i of n){if(i==null){if(r.o)continue;return `${o}: required`}let d=D(i,r,o);if(d)return d}return null}default:{let r=e.k;return `${t}: unknown kind ${String(r)}`}}}function a(n,e){return t=>{let r=ee(t);if(r)return r;if(typeof t!="object"||t===null||Array.isArray(t))return "message: expected object";let o=t;return o.gem!==l?"gem: wrong protocol marker":o.type!==n?`type: expected ${n}`:M(o,e,"")}}var ne=a("gem.handshake",[{n:"versions",k:"o",fs:[{n:"min",k:"i",lo:1,hi:1e3},{n:"max",k:"i",lo:1,hi:1e3}]},{n:"capabilities",k:"a",o:1,max:64,it:{n:"",k:"s",max:64}},{n:"embedder",k:"s",max:2048,f:"origin"},{n:"unbidden",k:"b",o:1}]),re=a("gem.handshake.accept",[{n:"v",k:"i",lo:1,hi:1e3},{n:"capabilities",k:"a",o:1,max:64,it:{n:"",k:"s",max:64}}]),ae=a("gem.token",[{n:"token",k:"s",max:4096},{n:"requestId",k:"s",o:1,max:64},{n:"generation",k:"i",lo:0,hi:2147483647},{n:"apiBaseUrl",k:"s",o:1,max:512,f:"url"},{n:"playerId",k:"s",max:64},{n:"gameId",k:"s",max:64},{n:"channel",k:"e",v:["dev","test","release"]},{n:"gameVersion",k:"s",o:1,max:64},{n:"expiresAt",k:"i",lo:0,hi:4102444800},{n:"chainEndsAt",k:"i",lo:0,hi:4102444800},{n:"allowDevTools",k:"b",o:1}]),oe=a("gem.token.denied",[{n:"requestId",k:"s",max:64},{n:"retryable",k:"b"},{n:"retryAfterMs",k:"i",o:1,lo:0,hi:36e5},{n:"reason",k:"e",v:["chain_exhausted","unavailable"]},{n:"correlationId",k:"s",max:64}]),se=a("gem.player",[{n:"untrusted",k:"o",fs:[{n:"displayName",k:"s",max:64},{n:"displayTag",k:"s",o:1,max:80},{n:"displayHandle",k:"s",max:80}]},{n:"playerId",k:"s",o:1,max:64},{n:"discriminator",k:"s",o:1,max:8},{n:"avatarIconUrl",k:"s",o:1,max:2048,f:"url"},{n:"avatarIconId",k:"s",o:1,max:64},{n:"badges",k:"a",o:1,max:2,it:{n:"",k:"o",fs:[{n:"itemId",k:"s",max:64},{n:"iconUrl",k:"s",max:2048,f:"url"}]}},{n:"displayTag",k:"s",max:8},{n:"avatarUrl",k:"s",o:1,max:2048,f:"url"},{n:"boost",k:"o",o:1,fs:[{n:"multipliers",k:"a",max:8,it:{n:"",k:"o",fs:[{n:"currencyId",k:"s",max:64},{n:"currencySlug",k:"s",max:32},{n:"multiplierBp",k:"i",lo:1e4,hi:1e6}]}},{n:"expiresInDays",k:"i",o:1,lo:1,hi:7}]}]),ie=a("gem.pause",[{n:"paused",k:"b"}]),le=a("gem.prefs",[{n:"reducedMotion",k:"b"},{n:"muted",k:"b"},{n:"showFrameStats",k:"b",o:1},{n:"locale",k:"s",max:35,f:"bcp47"},{n:"recommended",k:"o",o:1,fs:[{n:"volume",k:"i",lo:0,hi:100},{n:"batterySaver",k:"b"},{n:"keyboardLayout",k:"e",v:["wasd","arrows"]},{n:"gamepadConfirm",k:"e",v:["south","east"]},{n:"vibration",k:"b"}]}]),de=a("gem.cohorts",[{n:"cohorts",k:"a",max:8,it:{n:"",k:"o",fs:[{n:"experimentId",k:"s",max:36},{n:"variantKey",k:"s",max:32}]}}]),me=a("gem.earnAllowanceChanged",[]),ue=a("gem.viewport",[{n:"insets",k:"o",fs:[{n:"top",k:"i",lo:0,hi:4096},{n:"right",k:"i",lo:0,hi:4096},{n:"bottom",k:"i",lo:0,hi:4096},{n:"left",k:"i",lo:0,hi:4096}]},{n:"reserved",k:"a",o:1,max:4,it:{n:"",k:"o",fs:[{n:"x",k:"i",lo:0,hi:16384},{n:"y",k:"i",lo:0,hi:16384},{n:"width",k:"i",lo:0,hi:16384},{n:"height",k:"i",lo:0,hi:16384}]}}]),ce=a("gem.deviceSettings",[{n:"settings",k:"j",o:1}]),ge=a("gem.willTerminate",[{n:"reason",k:"e",v:["grant_expiring","session_ended","navigating","kill_switch"]},{n:"graceMs",k:"i",lo:0,hi:6e4}]),pe=a("gem.roomEvent",[{n:"event",k:"e",v:["updated","match_started","match_ready","match_failed","version_stale"]},{n:"roomId",k:"s",max:64},{n:"matchId",k:"s",o:1,max:64},{n:"version",k:"i",o:1,lo:0,hi:2147483647},{n:"reason",k:"s",o:1,max:64},{n:"platform",k:"e",o:1,v:["universal","mobile"]}]),ye=a("gem.socketState",[{n:"connected",k:"b"},{n:"reason",k:"e",o:1,v:["connecting","dropped","watchdog","terminal"]}]),fe=a("gem.seatedEvent",[{n:"roomId",k:"s",max:64}]),he=a("gem.autoStartFailedEvent",[{n:"roomId",k:"s",max:64},{n:"code",k:"s",max:64}]),ke=a("gem.signalEvent",[{n:"event",k:"e",v:["hello","offer","answer","ice","peerJoined","peerLeft","migration","matchEnded","error"]},{n:"matchId",k:"s",max:64},{n:"data",k:"j"}]),ve=a("gem.dedicatedEvent",[{n:"event",k:"e",v:["answer","error","matchEnded"]},{n:"matchId",k:"s",max:64},{n:"sdp",k:"s",o:1,max:10240},{n:"sessionId",k:"s",o:1,max:64},{n:"code",k:"s",o:1,max:64},{n:"message",k:"s",o:1,max:256},{n:"reason",k:"s",o:1,max:64}]),xe=a("gem.partyResult",[{n:"requestId",k:"s",max:64},{n:"partyId",k:"s",o:1,max:64}]),be=a("gem.clusterTarget",[{n:"clusterTargetId",k:"s",max:64},{n:"clusterTargetIds",k:"a",o:1,max:3,it:{n:"",k:"s",max:64}}]),we=a("gem.devtools",[{n:"action",k:"e",v:["open","close","toggle"]}]),Se=a("gem.screenshot",[{n:"maxWidth",k:"i",lo:1,hi:7680},{n:"maxHeight",k:"i",lo:1,hi:4320}]),Re=a("gem.screenshot.denied",[{n:"reason",k:"e",v:["not_wired","no_source","unsupported","unreadable","tainted","too_large","busy","declined","failed"]},{n:"retryable",k:"b"}]),Ge=a("gem.requestContext",[]),Oe=a("gem.gameContext",[{n:"context",k:"j"}]),Ce=a("gem.signal",[{n:"signal",k:"e",v:["join","offer","answer","ice","migrationAck","hostUnreachable"]},{n:"matchId",k:"s",max:64},{n:"data",k:"j"}]),Pe=a("gem.dedicatedOffer",[{n:"matchId",k:"s",max:64},{n:"sdp",k:"s",max:10240},{n:"intent",k:"e",v:["initial","ice_restart","full_reconnect"]}]),Te=a("gem.partyRequest",[{n:"requestId",k:"s",max:64}]),Ee=a("gem.ready",[]),Ie=a("gem.engaged",[]),qe=a("gem.progress",[{n:"loaded",k:"i",lo:0,hi:1099511627776},{n:"total",k:"i",lo:0,hi:1099511627776}]),Ae=a("gem.requestToken",[{n:"requestId",k:"s",max:64},{n:"reason",k:"e",v:["initial","expiring","rejected"]}]),Le=a("gem.requestLocalServer",[{n:"requestId",k:"s",max:64},{n:"gameRoomId",k:"s",max:64}]),_e=a("gem.localServer",[{n:"requestId",k:"s",max:64},{n:"serverId",k:"s",o:1,max:128}]),je=a("gem.localServer.denied",[{n:"requestId",k:"s",max:64},{n:"retryable",k:"b"},{n:"reason",k:"e",v:["refused","unavailable"]}]),Me=a("gem.exit",[{n:"reason",k:"s",o:1,max:64}]),De=a("gem.openExternal",[{n:"url",k:"s",max:2048,f:"url"}]),Fe=a("gem.requestFullscreen",[{n:"enabled",k:"b"}]),$e=a("gem.audioState",[{n:"muted",k:"b"}]),He=a("gem.rewardCue",[{n:"currencySlug",k:"s",max:32},{n:"expected",k:"i",o:1,lo:1,hi:1e9},{n:"origin",k:"o",o:1,fs:[{n:"x",k:"i",lo:0,hi:16384},{n:"y",k:"i",lo:0,hi:16384}]}]),Be=a("gem.walletDisplay",[{n:"visible",k:"b"},{n:"currencies",k:"a",o:1,max:8,it:{n:"",k:"s",max:64}},{n:"score",k:"b",o:1}]),Ue=a("gem.menu",[{n:"settings",k:"b"},{n:"items",k:"a",o:1,max:4,it:{n:"",k:"o",fs:[{n:"id",k:"s",max:32},{n:"label",k:"s",max:40}]}}]),We=a("gem.menuSelect",[{n:"entry",k:"e",v:["settings","item"]},{n:"id",k:"s",o:1,max:32}]),Ne=a("gem.requestShare",[{n:"params",k:"a",max:16,it:{n:"",k:"o",fs:[{n:"key",k:"s",max:64},{n:"value",k:"s",max:512}]}}]),Ve=a("gem.requestAvatarPicker",[]),ze=a("gem.vibrate",[{n:"pattern",k:"a",max:99,it:{n:"",k:"i",lo:0,hi:1e4}}]),Ke=a("gem.frameStats",[{n:"fps",k:"i",lo:0,hi:1e3},{n:"frameTimeP95Ms",k:"i",lo:0,hi:1e5}]),Ye=a("gem.portraitBorders",[{n:"name",k:"s",o:1,max:40}]),Je=a("gem.error",[{n:"code",k:"e",v:["version_mismatch","handshake_timeout","handshake_duplicate","invalid_message","rate_limited","token_unavailable","unsupported","unsupported_capability","internal"]},{n:"message",k:"s",o:1,max:256}]),Xe=a("gem.requestPurchase",[{n:"requestId",k:"s",max:64},{n:"purchaseKind",k:"e",v:["item","recipe"]},{n:"targetId",k:"s",max:64},{n:"currencySlug",k:"s",max:32},{n:"quantity",k:"i",o:1,lo:1,hi:10},{n:"catalogId",k:"s",o:1,max:64}]),Qe=a("gem.purchaseResult",[{n:"requestId",k:"s",max:64},{n:"outcome",k:"e",v:["ok","declined","unavailable"]},{n:"reason",k:"s",o:1,max:64,f:"code"},{n:"purchaseId",k:"s",o:1,max:64}]),Ze=a("gem.deviceSettings.put",[{n:"requestId",k:"s",max:64},{n:"settings",k:"j"}]),et=a("gem.deviceSettings.result",[{n:"requestId",k:"s",max:64},{n:"outcome",k:"e",v:["stored","too_large","unavailable"]}]),tt=a("gem.requestAd",[{n:"requestId",k:"s",max:64},{n:"placement",k:"s",max:32},{n:"format",k:"e",v:["interstitial","rewarded"]}]),nt=a("gem.adResult",[{n:"requestId",k:"s",max:64},{n:"outcome",k:"e",v:["shown","no_ad","unavailable"]}]),rt=a("gem.requestSignIn",[{n:"requestId",k:"s",max:64}]),at=a("gem.signInResult",[{n:"requestId",k:"s",max:64},{n:"outcome",k:"e",v:["signed_in","declined","unavailable"]}]),ot=a("gem.requestFriendChallenge",[{n:"requestId",k:"s",max:64},{n:"playerId",k:"s",max:64},{n:"template",k:"s",max:64},{n:"params",k:"j",o:1}]),st=a("gem.friendChallengeResult",[{n:"requestId",k:"s",max:64},{n:"outcome",k:"e",v:["accepted","cancelled","refused","unavailable","rate_limited","invalid"]},{n:"code",k:"s",o:1,max:64},{n:"param",k:"s",o:1,max:64},{n:"channel",k:"s",o:1,max:16},{n:"configVersion",k:"i",o:1,lo:0,hi:9007199254740991},{n:"retryAfterMs",k:"i",o:1,lo:0,hi:864e5},{n:"detail",k:"s",o:1,max:300}]),w=G({"gem.handshake":ne,"gem.handshake.accept":re,"gem.token":ae,"gem.token.denied":oe,"gem.player":se,"gem.pause":ie,"gem.prefs":le,"gem.cohorts":de,"gem.earnAllowanceChanged":me,"gem.viewport":ue,"gem.deviceSettings":ce,"gem.willTerminate":ge,"gem.roomEvent":pe,"gem.socketState":ye,"gem.seatedEvent":fe,"gem.autoStartFailedEvent":he,"gem.signalEvent":ke,"gem.dedicatedEvent":ve,"gem.partyResult":xe,"gem.clusterTarget":be,"gem.devtools":we,"gem.screenshot":Se,"gem.screenshot.denied":Re,"gem.requestContext":Ge,"gem.gameContext":Oe,"gem.signal":Ce,"gem.dedicatedOffer":Pe,"gem.partyRequest":Te,"gem.ready":Ee,"gem.engaged":Ie,"gem.progress":qe,"gem.requestToken":Ae,"gem.requestLocalServer":Le,"gem.localServer":_e,"gem.localServer.denied":je,"gem.exit":Me,"gem.openExternal":De,"gem.requestFullscreen":Fe,"gem.audioState":$e,"gem.rewardCue":He,"gem.walletDisplay":Be,"gem.menu":Ue,"gem.menuSelect":We,"gem.requestShare":Ne,"gem.requestAvatarPicker":Ve,"gem.vibrate":ze,"gem.frameStats":Ke,"gem.portraitBorders":Ye,"gem.error":Je,"gem.requestPurchase":Xe,"gem.purchaseResult":Qe,"gem.deviceSettings.put":Ze,"gem.deviceSettings.result":et,"gem.requestAd":tt,"gem.adResult":nt,"gem.requestSignIn":rt,"gem.signInResult":at,"gem.requestFriendChallenge":ot,"gem.friendChallengeResult":st});var it=/^[a-z0-9][a-z0-9_-]{0,39}$/;function lt(n){return typeof n=="string"&&it.test(n)}function F(n){if(n===null||lt(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 O=class{#e;constructor(e){this.#e=e,Object.freeze(this);}toString(){return "[gem: use gem.text.toPlain()]"}toJSON(){return this.toString()}get[Symbol.toStringTag](){return "PlayerText"}static unwrap(e){return e.#e}};function C(n){return new O(n)}var P={now:()=>Date.now(),setTimeout:(n,e)=>setTimeout(n,e),clearTimeout:n=>clearTimeout(n)},k=class{constructor(e=P){this.clock=e;}clock;tokens=new Map;lastRefill=new Map;allow(e){let t=_[e];if(t===void 0)return false;let r=this.clock.now(),o=this.lastRefill.get(e)??r,i=this.tokens.get(e)??t,d=Math.max(0,r-o),s=Math.min(t,i+d*t/6e4);return s<1?(this.tokens.set(e,s),this.lastRefill.set(e,r),false):(this.tokens.set(e,s-1),this.lastRefill.set(e,r),true)}};function T(n,e){return n.toLowerCase()===e.toLowerCase()}function $(n){let e=n.toLowerCase();return e==="localhost"||e.endsWith(".localhost")||e==="[::1]"||e==="::1"?true:/^127(\.\d{1,3}){3}$/.test(e)}function H(n,e){if(typeof e!="string"||e==="")return false;let t,r;try{t=new URL(n),r=new URL(e);}catch{return false}return t.protocol!=="http:"&&t.protocol!=="https:"||r.protocol!=="http:"&&r.protocol!=="https:"||t.username!==""||t.password!==""||t.pathname!=="/"||t.search!==""||t.hash!==""||t.port===""?false:$(t.hostname)&&$(r.hostname)}function B(n,e){if(n.min>n.max||e.min>e.max)return null;let t=Math.min(n.max,e.max),r=Math.max(n.min,e.min);return t>=r?t:null}function U(n){return Math.min(16384,Math.max(0,Math.round(Number.isFinite(n)?n:0)))}function dt(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 mt(n,e){let t=[];for(let r of Array.isArray(e)?e:[]){if(t.length===4)break;if(typeof r!="object"||r===null)continue;let{id:o,label:i}=r;typeof o!="string"||o.length===0||o.length>32||typeof i!="string"||i.trim().length===0||t.some(d=>d.id===o)||t.push({id:o,label:i.trim().slice(0,40)});}return t.length===0?{settings:n===true}:{settings:n===true,items:t}}function W(n,e){return Math.min(e,Math.max(0,Math.round(Number.isFinite(n)?n:0)))}function ut(n){let e=n.untrusted,t=C(e.displayName),r=e.displayTag||e.displayHandle,o=r?C(r):void 0,i=n.discriminator||n.displayTag,d=i&&/^[0-9]{1,8}$/.test(i)?i:void 0,s=n.avatarIconUrl||n.avatarUrl,m=n.avatarIconId,u={displayName:t,displayHandle:o??t,badges:(n.badges??[]).map(g=>({itemId:g.itemId,iconUrl:g.iconUrl}))};n.playerId&&(u.playerId=n.playerId),d&&(u.discriminator=d),o&&(u.displayTag=o),s&&(u.avatarIconUrl=u.avatarUrl=s),m&&/^[\da-f]{8}(-[\da-f]{4}){3}-[\da-f]{12}$/i.test(m)&&(u.avatarIconId=m);let c=n.boost,p=(c?.multipliers??[]).map(g=>({currencyId:g.currencyId,currencySlug:g.currencySlug,multiplier:g.multiplierBp/1e4})),y=p.some(g=>g.multiplier>1);return u.boost=y&&c?.expiresInDays?{active:y,multipliers:p,expiresInDays:c.expiresInDays}:{active:y,multipliers:p},u}var ct=1e4,v=class{constructor(e){this.options=e;if(e.expectedSource===void 0||e.expectedSource===null)throw new Error("GemFrame: expectedSource is required and must not be null \u2014 pass window.parent. The handshake transfers the MessagePort, and origin alone does not say WHICH document on that origin sent it.");this.expectedSource=e.expectedSource,this.clock=e.clock??P,this.inbound=new k(this.clock),this.outbound=new k(this.clock);}options;state="waiting";port=null;version=null;peerCapabilities=[];unbidden=false;engagedSent=false;readyPending=false;readySent=false;settleWaiters=[];clock;inbound;outbound;expectedSource;get currentState(){return this.state}get parentCapabilities(){return this.peerCapabilities}parentSupports(e){return this.peerCapabilities.includes(e)}get protocolVersion(){return this.version}get unbiddenLaunch(){return this.unbidden}handleWindowMessage(e){if(e.source!==this.expectedSource)return this.refuse(e,"handshake did not come from the expected embedder window"),false;if(!(this.options.allowedEmbedders.some(s=>T(s,e.origin))||H(e.origin,this.options.selfOrigin)))return this.refuse(e,`embedder '${e.origin}' is not in allowedEmbedders`),this.state==="waiting"&&this.transition("refused"),false;if(this.state==="connected")return this.fail("handshake_duplicate","this document already has a port"),false;if(this.state!=="waiting")return false;let r=w["gem.handshake"]?.(e.data);if(r)return this.refuse(e,`malformed handshake: ${r}`),false;let o=e.data;if(!T(o.embedder,e.origin))return this.refuse(e,`handshake claims embedder '${o.embedder}' but arrived from '${e.origin}'`),false;let i=e.ports?.[0];if(!i)return this.refuse(e,"handshake transferred no MessagePort"),false;let d=B(h,o.versions);return d===null?(i.onmessage=null,i.postMessage({gem:l,type:"gem.error",code:"version_mismatch",message:`frame supports v${h.min}..v${h.max}`}),i.close(),this.transition("refused"),this.options.onError?.("version_mismatch"),false):(this.port=i,this.version=d,i.onmessage=s=>this.receive(s.data,s.ports??[]),i.start?.(),this.peerCapabilities=o.capabilities??[],this.unbidden=o.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=ct){return this.state!=="waiting"?Promise.resolve(this.state):new Promise(t=>{let r=i=>{this.clock.clearTimeout(o),t(i);},o=this.clock.setTimeout(()=>{let i=this.settleWaiters.indexOf(r);i>=0&&this.settleWaiters.splice(i,1),t(this.state);},e);this.settleWaiters.push(r);})}progress(e,t){this.send({gem:l,type:"gem.progress",loaded:e,total:t});}requestToken(e,t){this.send({gem:l,type:"gem.requestToken",requestId:e,reason:t});}requestLocalServer(e,t){return this.parentSupports("localHost")?(this.send({gem:l,type:"gem.requestLocalServer",requestId:e,gameRoomId:t}),true):false}exit(e){this.send(e===void 0?{gem:l,type:"gem.exit"}:{gem:l,type:"gem.exit",reason:e});}openExternal(e){this.send({gem:l,type:"gem.openExternal",url:e});}requestFullscreen(e){this.send({gem:l,type:"gem.requestFullscreen",enabled:e});}reportMuted(e){return this.state!=="connected"||!this.parentSupports("audioState")?false:(this.send({gem:l,type:"gem.audioState",muted:e}),true)}reportEngaged(){return this.engagedSent||this.state!=="connected"||!this.parentSupports("engagement")||!this.send({gem:l,type:"gem.engaged"})?false:(this.engagedSent=true,true)}cueReward(e){if(this.state!=="connected"||!this.parentSupports("rewardCue"))return false;let t={gem:l,type:"gem.rewardCue",currencySlug:String(e.currencySlug).slice(0,32)};return e.expected!==void 0&&Number.isFinite(e.expected)&&e.expected>=1&&(t.expected=Math.min(1e9,Math.round(e.expected))),e.origin&&(t.origin={x:U(e.origin.x),y:U(e.origin.y)}),this.send(t),true}showPortraitBorders(e){let t=F(e);return t===void 0||this.state!=="connected"||!this.parentSupports("portraitBorders")?false:this.send(t===null?{gem:l,type:"gem.portraitBorders"}:{gem:l,type:"gem.portraitBorders",name:t})}setWalletVisible(e,t){return this.state!=="connected"||!this.parentSupports("walletDisplay")?false:this.send({gem:l,type:"gem.walletDisplay",...dt(e,t?.only)})}setMenu(e,t){return this.state!=="connected"||!this.parentSupports("gameMenu")?false:this.send({gem:l,type:"gem.menu",...mt(e,t)})}requestShare(e){return this.state!=="connected"||!this.parentSupports("share")?false:this.send({gem:l,type:"gem.requestShare",params:e.map(({key:t,value:r})=>({key:t,value:r}))})}requestAvatarPicker(){return this.state!=="connected"||!this.parentSupports("avatarPicker")?false:this.send({gem:l,type:"gem.requestAvatarPicker"})}requestVibrate(e){return this.state!=="connected"||!this.parentSupports("vibration")?false:this.send({gem:l,type:"gem.vibrate",pattern:[...e]})}reportFrameStats(e){return this.state!=="connected"||!this.parentSupports("frameStats")?false:(this.send({gem:l,type:"gem.frameStats",fps:W(e.fps,1e3),frameTimeP95Ms:W(e.frameTimeP95Ms,1e5)}),true)}sendGameContext(e){return this.state!=="connected"?false:(this.send({gem:l,type:"gem.gameContext",context:e}),true)}signal(e,t,r){this.send({gem:l,type:"gem.signal",signal:e,matchId:t,data:r});}dedicatedOffer(e,t,r){this.send({gem:l,type:"gem.dedicatedOffer",matchId:e,sdp:t,intent:r});}requestParty(e){return this.send({gem:l,type:"gem.partyRequest",requestId:e})}requestPurchase(e,t,r,o,i,d){return this.send({gem:l,type:"gem.requestPurchase",requestId:e,purchaseKind:t,targetId:r,currencySlug:o,...i===void 0?{}:{quantity:i},...d===void 0?{}:{catalogId:d}})}putDeviceSettings(e,t){return this.send({gem:l,type:"gem.deviceSettings.put",requestId:e,settings:t})}requestAd(e,t,r){return this.send({gem:l,type:"gem.requestAd",requestId:e,placement:t,format:r})}requestSignIn(e){return this.send({gem:l,type:"gem.requestSignIn",requestId:e})}requestFriendChallenge(e,t,r,o){return this.send({gem:l,type:"gem.requestFriendChallenge",requestId:e,playerId:t,template:r,...o===void 0?{}:{params:o}})}close(){this.port&&(this.port.onmessage=null,this.port.close(),this.port=null),this.state!=="refused"&&this.transition("closed");}transition(e){if(this.state!==e){this.state=e;for(let t of this.settleWaiters.splice(0))t(e);this.options.onStateChange?.(e);}}refuseMalformed(e,t){if(!this.inbound.allow(b)){this.options.onDropped?.(e,t);return}this.fail(e,t);}dropUnknownType(e){this.inbound.allow(b)&&this.options.onDropped?.("unsupported",`ignored unknown message type '${e}'`);}refuse(e,t){e.ports?.[0]?.close?.(),this.inbound.allow(b)&&this.options.onRefused?.(t);}fail(e,t){this.options.onError?.(e,t),this.state==="connected"&&this.port&&this.send({gem:l,type:"gem.error",code:e,...t===void 0?{}:{message:t}});}send(e){if(this.state!=="connected"||!this.port)return this.options.onDropped?.("internal",`dropped ${String(e.type)} before connect`),false;let t=e.type;if(!this.outbound.allow(t))return this.options.onError?.("rate_limited",`frame exceeded its own limit for ${t}`),false;let r=w[t]?.(e);return r?(this.options.onError?.("internal",`refusing to send malformed ${t}: ${r}`),false):(this.port.postMessage(this.version===null?e:{...e,v:this.version}),true)}receive(e,t=[]){let r=false;try{r=this.dispatchInbound(e,t);}finally{r||N(t);}}dispatchInbound(e,t){if(this.state!=="connected")return false;let r=typeof e=="object"&&e!==null?e.type:void 0;if(typeof r!="string")return this.refuseMalformed("invalid_message","message has no type"),false;let o=w[r];if(!o)return this.dropUnknownType(r),false;if(!this.inbound.allow(r))return this.fail("rate_limited",`parent exceeded the limit for ${r}`),false;let i=j(r);if(i!==void 0&&!this.options.capabilities?.includes(i))return this.fail("unsupported_capability",`${r} requires the '${i}' capability, which this frame did not advertise`),false;let d=o(e);if(d)return this.fail("invalid_message",`${r}: ${d}`),false;let s=e;if(s.v!==this.version)return this.fail("invalid_message",`${r}: expected v ${String(this.version)}`),false;switch(r){case "gem.token":this.options.onToken?.(s);break;case "gem.pause":this.options.onPause?.(s);break;case "gem.menuSelect":this.options.onMenuSelect?.(s);break;case "gem.prefs":this.options.onPrefs?.(s);break;case "gem.cohorts":this.options.onCohorts?.(s);break;case "gem.earnAllowanceChanged":this.options.onEarnAllowanceChanged?.();break;case "gem.viewport":this.options.onViewport?.(s);break;case "gem.willTerminate":this.options.onWillTerminate?.(s);break;case "gem.devtools":this.options.onDevtools?.(s.action);break;case "gem.requestContext":this.options.onRequestContext?.();break;case "gem.screenshot":{let m=t[0];if(!m){this.options.onError?.("invalid_message","gem.screenshot transferred no MessagePort");break}let u={maxWidth:s.maxWidth,maxHeight:s.maxHeight};if(!this.options.onScreenshot){m.close(),this.screenshotDenied("not_wired",false);break}return N(t.slice(1)),this.options.onScreenshot(u,m,(c,p)=>this.screenshotDenied(c,p)),true}case "gem.token.denied":this.options.onTokenDenied?.(s);break;case "gem.localServer":this.options.onLocalServer?.(s);break;case "gem.localServer.denied":this.options.onLocalServerDenied?.(s);break;case "gem.player":{this.options.onPlayer?.(ut(s));break}case "gem.roomEvent":this.options.onRoomEvent?.(s);break;case "gem.seatedEvent":this.options.onSeatedEvent?.(s);break;case "gem.autoStartFailedEvent":this.options.onAutoStartFailedEvent?.(s);break;case "gem.socketState":this.options.onSocketState?.(s);break;case "gem.signalEvent":this.options.onSignalEvent?.(s);break;case "gem.dedicatedEvent":this.options.onDedicatedEvent?.(s);break;case "gem.clusterTarget":this.options.onClusterTarget?.(s);break;case "gem.partyResult":this.options.onPartyResult?.(s);break;case "gem.purchaseResult":this.options.onPurchaseResult?.(s);break;case "gem.deviceSettings":this.options.onDeviceSettings?.(s);break;case "gem.deviceSettings.result":this.options.onDeviceSettingsResult?.(s);break;case "gem.adResult":this.options.onAdResult?.(s);break;case "gem.signInResult":this.options.onSignInResult?.(s);break;case "gem.friendChallengeResult":this.options.onFriendChallengeResult?.(s);break;case "gem.error":this.options.onError?.(s.code,s.message);break;default:this.fail("unsupported",`no frame handler for '${r}'`);}return false}screenshotDenied(e,t){this.send({gem:l,type:"gem.screenshot.denied",reason:e,retryable:t});}};function N(n){for(let e of n)try{e?.close?.();}catch{}}I();function gt(n){if((n.expectedSource??window.parent)===window)throw new Error("GemWebSdkBridge.connect: this document is not framed (window.parent === window), so there is no embedder to hand it a port. A game runs inside the Gem Arcade iframe; opening it directly will never complete a handshake.");let e=new v({...n,expectedSource:n.expectedSource??window.parent}),t=r=>{let 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),q(window,t),e}var V={connect:gt,GemFrame:v,PROTOCOL:l,SUPPORTED_VERSIONS:h};window.GemWebSdkBridge=V;var Pt=V;return Pt;})();
|