@indiegems/gem-web-sdk 10.3.0 → 10.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +6 -0
- package/dist/gem-web-sdk.esm.js +1 -1
- package/dist/gem-web-sdk.function.js +1 -1
- package/dist/gem-web-sdk.game.js +1 -1
- package/dist/gem-web-sdk.min.js +1 -1
- package/dist/gem-web-sdk.sdk.js +1 -1
- package/dist/gem-web-sdk.server.js +1 -1
- package/docs/api/api-reference-game.md +34 -34
- package/docs/api/api-reference-server.md +1 -1
- package/docs/api/reference.json +9 -9
- package/docs/brand-art.md +6 -4
- package/docs/changelog.md +6 -0
- package/docs/daily-challenges.md +4 -4
- package/docs/getting-started.md +1 -1
- package/docs/inventory-and-catalogs.md +11 -7
- package/docs/manifest.json +14 -14
- package/docs/server-bundles.md +2 -2
- package/docs/what-a-game-must-do.md +67 -90
- package/package.json +1 -1
- package/schema/bridge.v1.json +15 -8
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
var Re=Object.defineProperty;var xe=(n,e)=>{for(var t in e)Re(n,t,{get:e[t],enumerable:true});};globalThis.__gemWebSdkVersion="[gem-web-sdk:sdkVersion:10.3.0]";function Se(n,e){return e!==void 0?!e:n==="chain_exhausted"}var M=class{constructor(e){this.options=e;}options;grant=null;state="pending";failure=null;generation=0;inFlight=null;rejected=false;get currentState(){return this.state}get lastFailure(){return this.failure}async get(){if(this.state==="lost")throw new R(this.failure??"unavailable","the session cannot be renewed");let e=this.seconds();if(this.grant&&e<this.grant.expiresAt-this.renewBefore())return this.grant.token;if(this.grant&&e>=this.grant.chainEndsAt)throw this.enter("lost","chain_exhausted"),new R("chain_exhausted","the token chain reached its ceiling");return this.refresh(this.nextReason())}nextReason(){return this.rejected?"rejected":this.grant?"expiring":"initial"}invalidate(e){e!==void 0&&this.grant!==null&&this.grant.token!==e||this.rejected&&this.grant===null||(this.grant=null,this.generation+=1,this.inFlight=null,this.rejected=true,this.state!=="lost"&&this.enter("pending"));}accept(e){this.state!=="lost"&&(this.grant=e,this.rejected=false,this.enter("ready"));}close(e="unavailable"){this.grant=null,this.generation+=1,this.inFlight=null,this.enter("lost",e);}refresh(e){if(this.inFlight)return this.inFlight;let t=this.generation;this.enter("pending");let r=this.options.request(e).then(o=>{if(t!==this.generation)throw new R("internal","token arrived for a superseded generation");return this.grant=o,this.rejected=false,this.enter("ready"),o.token}).catch(o=>{let a=ke(o),i=o?.retryable;throw t===this.generation&&this.enter(Se(a,typeof i=="boolean"?i:void 0)?"lost":"degraded",a),o instanceof R?o:new R(a,String(o))}).finally(()=>{this.inFlight===r&&(this.inFlight=null);});return this.inFlight=r,r}enter(e,t){this.failure=t??(e==="ready"?null:this.failure),this.state!==e&&(this.state=e,this.options.onStateChange?.(e,t));}renewBefore(){return this.options.renewBeforeSeconds??60}seconds(){return Math.floor(this.options.clock.now()/1e3)}},R=class n extends Error{constructor(t,r){super(`auth ${t}: ${r}`);this.reason=t;this.name="AuthError";}reason;static isAuthError(t){if(t instanceof n)return true;let r=t;return r?.name==="AuthError"&&typeof r.reason=="string"}};function ke(n){if(n instanceof R)return n.reason;let e=n?.reason;return typeof e=="string"&&["chain_exhausted","unavailable","timeout","internal"].includes(e)?e:"internal"}var h=class n extends Error{retryable=false;constructor(e){super(e),this.name="TransportRefusal";}static isRefusal(e){if(e instanceof n)return true;let t=e;return t?.name==="TransportRefusal"&&t.retryable===false}},$=["if-match","if-none-match"],V=4096;function we(n){if(!n)return;let e={};for(let[t,r]of Object.entries(n)){let o=t.toLowerCase();if(!$.includes(o)||r===void 0)continue;let a=typeof r=="string"?Ae(r):r;if(typeof a!="string"||a.length>V||!Pe(a))throw new h(`the ${o} header value cannot be sent \u2014 it is not a string, is longer than ${V} characters, or contains a character outside the range an HTTP header value may carry. This is a malformed request, not a server failure; the value is withheld here rather than written to logs.`);a!==""&&(e[o]=a);}return Object.freeze(e)}function Ae(n){let e=o=>o===32||o===9||o===10||o===13,t=0,r=n.length;for(;t<r&&e(n.charCodeAt(t));)t++;for(;r>t&&e(n.charCodeAt(r-1));)r--;return n.slice(t,r)}function Pe(n){for(let e=0;e<n.length;e++){let t=n.charCodeAt(e);if(t!==9&&(t<32||t===127||t>255))return false}return true}function Te(n){let{bytes:e}=n;if(e!==void 0){if(Object.prototype.toString.call(e)!=="[object Uint8Array]")throw new h("the raw body is not a Uint8Array, so it cannot be sent as bytes. This is a malformed request, not a server failure.");if(n.body!==void 0)throw new h("the request carries both a JSON body and a raw body, and only one can be sent. This is a malformed request, not a server failure.");return new Uint8Array(e)}}function W(n,e){let t=e.replayUnauthorizedOnce??true;return {async request(r){let o={...r},a=we(o.headers),i=Te(o),d=Object.freeze({...o,headers:a,...i===void 0?{}:{bytes:i}}),l=await e.tokenSource.get(),c=await n(d,l);if(c.status!==401||!t)return c;e.tokenSource.invalidate(l);let p=await e.tokenSource.get(),b=await n(d,p);if(b.status===401)throw e.tokenSource.close("unavailable"),new R("unavailable","the server refused a freshly minted token");return b}}}function z(n){let e=typeof n=="string"?new TextEncoder().encode(n):n;return btoa(Oe(e))}function Oe(n){let t="";for(let r=0;r<n.length;r+=32768)t+=String.fromCharCode(...n.subarray(r,r+32768));return t}var g=class extends Error{constructor(t,r,o,a,i){super(`${t} (${r}): ${o}`);this.reason=t;this.status=r;this.detail=o;this.retryAfterSeconds=a;this.code=i;this.name="GemApiError";}reason;status;detail;retryAfterSeconds;code;get retryable(){return this.reason==="unavailable"||this.reason==="rate_limited"}},Y=new WeakMap;function J(n){return Y.get(n)??{}}var Ge=new Set([408,429,500,502,503,504]),Ce=6e4;function Ee(n){if(n===void 0)return 2;if(!Number.isInteger(n)||n<0||n>10)throw new h(`maxRetries must be a whole number between 0 and 10; received ${JSON.stringify(n)}. This is a configuration fault, not a server failure.`);return n}var T=class{constructor(e){this.options=e;}options;async get(e,t){return this.send({method:"GET",path:e,signal:t},true)}async getWithEtag(e,t={}){let r=await this.sendRaw({method:"GET",path:e,...t.signal===void 0?{}:{signal:t.signal},...t.ifNoneMatch===void 0?{}:{headers:{"if-none-match":t.ifNoneMatch}}},true),o=r.etag===void 0?{}:{etag:r.etag};return r.status===304?{modified:false,...o}:{modified:true,body:r.body,...o}}async put(e,t,r,o={}){return this.send({method:"PUT",path:e,body:t,signal:r,...E(o)},o.replaySafe===true)}async post(e,t,r,o={}){return this.send({method:"POST",path:e,body:t,signal:r,...E(o)},o.replaySafe===true)}async postBytes(e,t,r,o={}){let a=await this.sendRaw({method:"POST",path:e,bytes:t,responseType:"bytes",signal:r,...E(o)},o.replaySafe===true);return {bytes:Ie(a.body),...a.invocationId===void 0?{}:{invocationId:a.invocationId}}}async patch(e,t,r,o={}){return this.send({method:"PATCH",path:e,body:t,signal:r,...E(o)},o.replaySafe===true)}async delete(e,t,r={}){return this.send({method:"DELETE",path:e,signal:t,...E(r)},r.replaySafe===true)}async send(e,t){return (await this.sendRaw(e,t)).body}async sendRaw(e,t){let r=t?Ee(this.options.maxRetries)+1:1,o=null;if(e.signal?.aborted)throw K(e.signal);for(let a=0;a<r;a++){if(a>0&&await this.backoff(a,o,e.signal),e.signal?.aborted)throw K(e.signal);let i;try{i=await this.options.transport.request(e);}catch(l){if(R.isAuthError(l)||h.isRefusal(l)||e.signal?.aborted||qe(l))throw l;o=new g("unavailable",0,String(l));continue}if(i.status>=200&&i.status<300||i.status===304)return i;let d=Le(i);if(!Ge.has(i.status))throw d;o=d;}throw o??new g("unavailable",0,"no attempt was made")}backoff(e,t,r){if(r?.aborted)return Promise.resolve();let o=t?.retryAfterSeconds,a=o!==void 0?o*1e3:2**(e-1)*250,i=2**(e-1)*250,d=Math.min(Math.max(a,i),Ce);return new Promise(l=>{let c=this.options.clock,p=false,b=false,S,_=()=>{p||(p=true,b&&c.clearTimeout(S),r?.removeEventListener("abort",_),l());};r?.addEventListener("abort",_,{once:true}),S=c.setTimeout(_,d),b=true,p&&c.clearTimeout(S);})}};function Ie(n){if(n instanceof Uint8Array)return n;if(n==null)return new Uint8Array(0);let e=typeof n=="string"?n:JSON.stringify(n);return new TextEncoder().encode(e)}function E(n){return {...n.keepalive===void 0?{}:{keepalive:n.keepalive},...n.ifMatch===void 0?{}:{headers:{"if-match":n.ifMatch}}}}function K(n){return n.reason!==void 0?n.reason:new DOMException("The operation was aborted.","AbortError")}function qe(n){let e=n?.name;return e==="AbortError"||e==="TimeoutError"}function Le(n){let e=$e(n),t=Fe(n.body),r={...t===void 0?{}:{details:t},...n.invocationId===void 0?{}:{invocationId:n.invocationId}};return Object.keys(r).length>0&&Y.set(e,r),e}var Me=new Map([["insufficient_funds","insufficient_funds"]]);function $e(n){let{status:e,body:t}=n,r=je(t),o=n.retryAfterSeconds??Ue(t),a=Be(t),i=a===void 0?void 0:Me.get(a);if(i!==void 0)return new g(i,e,r,void 0,a);switch(e){case 304:return new g("not_modified",e,r);case 400:case 422:return new g("invalid",e,r,void 0,a);case 403:return new g("forbidden",e,r,void 0,a);case 404:return new g("not_found",e,r,void 0,a);case 402:return new g("insufficient_funds",e,r,void 0,a);case 409:return new g("conflict",e,r,void 0,a);case 412:return new g("precondition_failed",e,r,void 0,a);case 413:return new g("too_large",e,r,void 0,a);case 429:return new g("rate_limited",e,r,o,a);default:return new g("unavailable",e,r,o,a)}}function je(n){if(typeof n=="string")return n;let e=n?.message;if(typeof e=="string")return e;let t=n?.error;if(typeof t=="string")return t;let r=t?.message;return typeof r=="string"?r:"no detail"}function Fe(n){let t=n?.error?.details;return t===null?void 0:t}function Be(n){let t=n?.error?.code;return typeof t=="string"&&t.length>0?t:void 0}function Ue(n){let e=n?.retryAfterSeconds;return typeof e=="number"&&Number.isFinite(e)&&e>=0?e:void 0}function Ne(n){let e=n.lastIndexOf("@");return (e===-1?n:`***@${n.slice(e+1)}`).slice(0,200)}var De=new Set($);function He(n){if(!n)return {};let e={};for(let[t,r]of Object.entries(n))De.has(t.toLowerCase())&&(e[t.toLowerCase()]=r);return e}function X(n){let e=n.fetch??globalThis.fetch.bind(globalThis);return W(async(t,r)=>{let o;try{o=new URL(n.baseUrl.replace(/\/+$/,""));}catch{throw new h("the configured baseUrl is not a valid URL. Its value is withheld here rather than written to logs. This is a configuration fault, not a server failure.")}let a;try{a=new URL(o.href.replace(/\/+$/,"")+t.path);}catch{throw new h(`${JSON.stringify(typeof t.path=="string"?Ne(t.path):"(a non-string path)")} does not form a valid URL against ${o.protocol}//${o.host}. This is a malformed request, not a server failure.`)}if(a.protocol!==o.protocol||a.host!==o.host)throw new h(`${JSON.stringify(a.pathname)} resolves to ${a.protocol}//${a.host}, not ${o.protocol}//${o.host}. A request path may not change the request's origin \u2014 it carries the play token.`);if(a.username!==""||a.password!==""){let _=o.username!==""||o.password!=="",y=a.username!==o.username||a.password!==o.password,m=_?y?"baseUrl (and possibly the request path)":"baseUrl":"request path";throw new h(`the ${m} puts credentials in the URL, which cannot be fetched (${t.method} ${a.pathname}). The value is withheld here rather than written to logs. This is a malformed request, not a server failure.`)}for(let[_,y]of Object.entries(n.defaultQuery??{}))a.searchParams.has(_)||a.searchParams.set(_,y);let i=t.bytes,d=t.bytes===void 0?void 0:"application/octet-stream";try{t.body!==void 0&&(i=JSON.stringify(t.body),d="application/json");}catch(_){throw new h(`the body of ${t.method} ${JSON.stringify(a.pathname)} could not be serialised to JSON: ${String(_)}. This is a bug in the request, not a server failure \u2014 retrying sends the same unserialisable value.`)}let l=await e(a.toString(),{method:t.method,headers:{authorization:`Bearer ${r}`,...d===void 0?{}:{"content-type":d},...He(t.headers)},body:i,signal:t.signal,...t.keepalive===void 0?{}:{keepalive:t.keepalive},credentials:"omit",mode:"cors",redirect:"error",cache:"no-store",referrerPolicy:"no-referrer"}),c=null;if(t.responseType==="bytes"&&l.status>=200&&l.status<300)c=new Uint8Array(await l.arrayBuffer());else {let _=await l.text();if(_.length>0)try{c=JSON.parse(_);}catch{c=_;}}let p=l.headers.get("etag"),b=Ve(l.headers.get("retry-after")),S=l.headers.get("x-gem-invocation-id");return {status:l.status,body:c,...p===null?{}:{etag:p},...b===void 0?{}:{retryAfterSeconds:b},...S===null||S===""?{}:{invocationId:S}}},n)}function Ve(n){if(n===null)return;let e=n.trim();if(!/^\d+$/.test(e))return;let t=Number(e);return Number.isFinite(t)?t:void 0}var We="gem-web-bridge";var O=65536,Q=8,j=5e3,Z=1024;function ee(n){return Object.freeze(Object.assign(Object.create(null),n))}ee({"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.controlsDeclare":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});ee({"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","gem.controlsDeclare":"controls"});function Ke(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 Ye(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 Je(n){return /^[a-z]{2,8}(-[a-z0-9]{1,8})*$/i.test(n)}function Xe(n){return /^[a-z_]+$/.test(n)}function B(n,e,t){if(e>Q)return `nesting deeper than ${Q}`;if(++t.nodes>j)return `more than ${j} values`;if(t.bytes>O)return `over the ${O} 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>Z)return `an array of ${n.length} entries, over the ${Z} limit`;t.bytes+=2;for(let d of n){let l=B(d,e+1,t);if(l)return l}return null}let a=Object.getPrototypeOf(n);if(a!==Object.prototype&&a!==null)return "a value that is not a plain object";t.bytes+=2;let i=n;for(let d in i){if(!Object.prototype.hasOwnProperty.call(i,d))continue;if(++t.nodes>j)return `more than ${j} values`;if(t.bytes+=d.length*3+4,t.bytes>O)return `over the ${O} byte limit`;let l=B(i[d],e+1,t);if(l)return l}return null}function Qe(n){let e={nodes:0,bytes:0,seen:new Set},t=B(n,0,e);return t?`message contains ${t}`:e.bytes>O?`message is over the ${O} byte limit`:null}var Ze={origin:[Ke,"not a well-formed origin"],url:[Ye,"not a safe absolute http(s) URL"],bcp47:[Je,"not a well-formed BCP 47 tag"],code:[Xe,"not a code of lower-case letters and underscores"]};function ne(n,e,t){for(let r of e){let o=t===""?r.n:`${t}.${r.n}`,a=n[r.n];if(a==null){if(r.o)continue;return `${o}: required`}let i=te(a,r,o);if(i)return i}return null}function te(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]=Ze[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`:ne(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 a of n){if(a==null){if(r.o)continue;return `${o}: required`}let i=te(a,r,o);if(i)return i}return null}default:{let r=e.k;return `${t}: unknown kind ${String(r)}`}}}var re=Object.create(null);function u(n,e){return re[n]=t=>{let r=Qe(t);if(r)return r;if(typeof t!="object"||t===null||Array.isArray(t))return "message: expected object";let o=t;return o.gem!==We?"gem: wrong protocol marker":o.type!==n?`type: expected ${n}`:ne(o,e,"")}}u("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}]);u("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}}]);u("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}]);u("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}]);u("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}]}]);u("gem.pause",[{n:"paused",k:"b"}]);u("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"},{n:"lookSensitivity",k:"i",o:1,lo:20,hi:400},{n:"gamepadLookSensitivity",k:"i",o:1,lo:20,hi:400},{n:"invertLookY",k:"b",o:1},{n:"touchMovement",k:"s",o:1,max:16,f:"code"}]}]);u("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}]}}]);u("gem.earnAllowanceChanged",[]);u("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}]}}]);u("gem.deviceSettings",[{n:"settings",k:"j",o:1}]);u("gem.willTerminate",[{n:"reason",k:"e",v:["grant_expiring","session_ended","navigating","kill_switch"]},{n:"graceMs",k:"i",lo:0,hi:6e4}]);u("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"]}]);u("gem.socketState",[{n:"connected",k:"b"},{n:"reason",k:"e",o:1,v:["connecting","dropped","watchdog","terminal"]}]);u("gem.seatedEvent",[{n:"roomId",k:"s",max:64}]);u("gem.autoStartFailedEvent",[{n:"roomId",k:"s",max:64},{n:"code",k:"s",max:64}]);u("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"}]);u("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}]);u("gem.partyResult",[{n:"requestId",k:"s",max:64},{n:"partyId",k:"s",o:1,max:64}]);u("gem.clusterTarget",[{n:"clusterTargetId",k:"s",max:64},{n:"clusterTargetIds",k:"a",o:1,max:3,it:{n:"",k:"s",max:64}}]);u("gem.devtools",[{n:"action",k:"e",v:["open","close","toggle"]}]);u("gem.screenshot",[{n:"maxWidth",k:"i",lo:1,hi:7680},{n:"maxHeight",k:"i",lo:1,hi:4320}]);u("gem.screenshot.denied",[{n:"reason",k:"e",v:["not_wired","no_source","unsupported","unreadable","tainted","too_large","busy","declined","failed"]},{n:"retryable",k:"b"}]);u("gem.requestContext",[]);u("gem.gameContext",[{n:"context",k:"j"}]);u("gem.signal",[{n:"signal",k:"e",v:["join","offer","answer","ice","migrationAck","hostUnreachable"]},{n:"matchId",k:"s",max:64},{n:"data",k:"j"}]);u("gem.dedicatedOffer",[{n:"matchId",k:"s",max:64},{n:"sdp",k:"s",max:10240},{n:"intent",k:"e",v:["initial","ice_restart","full_reconnect"]}]);u("gem.partyRequest",[{n:"requestId",k:"s",max:64}]);u("gem.ready",[]);u("gem.engaged",[]);u("gem.progress",[{n:"loaded",k:"i",lo:0,hi:1099511627776},{n:"total",k:"i",lo:0,hi:1099511627776}]);u("gem.requestToken",[{n:"requestId",k:"s",max:64},{n:"reason",k:"e",v:["initial","expiring","rejected"]}]);u("gem.requestLocalServer",[{n:"requestId",k:"s",max:64},{n:"gameRoomId",k:"s",max:64}]);u("gem.localServer",[{n:"requestId",k:"s",max:64},{n:"serverId",k:"s",o:1,max:128}]);u("gem.localServer.denied",[{n:"requestId",k:"s",max:64},{n:"retryable",k:"b"},{n:"reason",k:"e",v:["refused","unavailable"]}]);u("gem.exit",[{n:"reason",k:"s",o:1,max:64}]);u("gem.openExternal",[{n:"url",k:"s",max:2048,f:"url"}]);u("gem.requestFullscreen",[{n:"enabled",k:"b"}]);u("gem.audioState",[{n:"muted",k:"b"}]);u("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}]}]);u("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}]);u("gem.controlsDeclare",[{n:"uses",k:"o",fs:[{n:"lookSensitivity",k:"s",o:1,max:16,f:"code"},{n:"gamepadLookSensitivity",k:"s",o:1,max:16,f:"code"},{n:"invertLookY",k:"s",o:1,max:16,f:"code"},{n:"touchMovement",k:"s",o:1,max:16,f:"code"}]}]);u("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}]}}]);u("gem.menuSelect",[{n:"entry",k:"e",v:["settings","item"]},{n:"id",k:"s",o:1,max:32}]);u("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}]}}]);u("gem.requestAvatarPicker",[]);u("gem.vibrate",[{n:"pattern",k:"a",max:99,it:{n:"",k:"i",lo:0,hi:1e4}}]);u("gem.frameStats",[{n:"fps",k:"i",lo:0,hi:1e3},{n:"frameTimeP95Ms",k:"i",lo:0,hi:1e5}]);u("gem.portraitBorders",[{n:"name",k:"s",o:1,max:40}]);u("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}]);u("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}]);u("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}]);u("gem.deviceSettings.put",[{n:"requestId",k:"s",max:64},{n:"settings",k:"j"}]);u("gem.deviceSettings.result",[{n:"requestId",k:"s",max:64},{n:"outcome",k:"e",v:["stored","too_large","unavailable"]}]);u("gem.requestAd",[{n:"requestId",k:"s",max:64},{n:"placement",k:"s",max:32},{n:"format",k:"e",v:["interstitial","rewarded"]}]);u("gem.adResult",[{n:"requestId",k:"s",max:64},{n:"outcome",k:"e",v:["shown","no_ad","unavailable"]}]);u("gem.requestSignIn",[{n:"requestId",k:"s",max:64}]);u("gem.signInResult",[{n:"requestId",k:"s",max:64},{n:"outcome",k:"e",v:["signed_in","declined","unavailable"]}]);u("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}]);u("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}]);Object.freeze(re);var G={now:()=>Date.now(),setTimeout:(n,e)=>setTimeout(n,e),clearTimeout:n=>clearTimeout(n)};var en=1e4;function oe(n,e){return U(n,e)}function U(n,e){if(typeof n.serverToken!="function"||typeof n.onServerToken!="function")throw new Error("this runtime delivers no game-server token: host.serverToken/onServerToken are missing. The server image running this bundle predates token delivery \u2014 the bundle cannot call gem-api on it.");let t=i=>({token:i.token,expiresAt:i.expiresAt,chainEndsAt:Number.POSITIVE_INFINITY}),r=null,o=new M({clock:e.clock,...e.onStateChange===void 0?{}:{onStateChange:e.onStateChange},request:()=>new Promise((i,d)=>{let l=e.clock.setTimeout(()=>{r=null,d({reason:"unavailable",retryable:true});},e.timeoutMs??en);r={resolve:c=>{e.clock.clearTimeout(l),i(c);},reject:d,timer:l};})}),a=n.onServerToken(i=>{let d=t(i),l=r;if(l){r=null,l.resolve(d);return}o.accept(d);});return {source:o,dispose(){a(),r&&(e.clock.clearTimeout(r.timer),r.reject({reason:"unavailable",retryable:false}),r=null);}}}var D={};xe(D,{acceptTransfer:()=>nn,addEntityProgression:()=>tn,adminAction:()=>rn,cancelInventoryTransfer:()=>on,claimEntityProgressionRewards:()=>an,closeGameRoom:()=>sn,createEntityBatchOrder:()=>ln,createEntityOrder:()=>dn,createSession:()=>un,deleteEntityGameSetting:()=>cn,deleteEntitySave:()=>mn,deleteSession:()=>gn,deleteShowcaseValue:()=>pn,executeEntityRecipe:()=>yn,finalizeSaveUpload:()=>fn,getChannelAssignment:()=>hn,getDropRates:()=>_n,getEntityCurrency:()=>bn,getEntityGameSetting:()=>vn,getEntityInventory:()=>Rn,getEntityInventoryItem:()=>xn,getEntityLeaderboard:()=>Sn,getEntityOrder:()=>kn,getEntityProgression:()=>wn,getEntityRecipeAvailability:()=>An,getEntityRecipeUsage:()=>Pn,getEntitySave:()=>Tn,getEvent:()=>On,getGameRoomV2:()=>Gn,getLeaderboard:()=>Cn,getPlayerGameProfile:()=>En,getPurchaseCatalog:()=>In,getResolvedTemplate:()=>qn,getRoomArgs:()=>Ln,getShowcaseValue:()=>Mn,getTransferDetails:()=>$n,ingestAnalyticsEvents:()=>N,initiateInventoryTransfer:()=>jn,invokeFunction:()=>Fn,kickPlayer:()=>Bn,listChallenges:()=>Un,listEntityGameSettings:()=>Nn,listEntityOrders:()=>Dn,listEntityProgressions:()=>Hn,listEntitySaves:()=>Vn,listEvents:()=>Wn,listGameRooms:()=>zn,listResolvedTemplates:()=>Kn,listTransfers:()=>Yn,maxEntityProgression:()=>Jn,putEntityGameSetting:()=>Xn,putRoomArgs:()=>Qn,putShowcaseValue:()=>Zn,rejectTransfer:()=>et,reportMatchPlayers:()=>nt,requestSaveUploadUrl:()=>tt,resetEntityProgression:()=>rt,setMatchBackfill:()=>ot,simulateEntityOrder:()=>at,transferHostV2:()=>st,updateGameRoomV2:()=>it});function s(n){let e=String(n);if(!/^[A-Za-z0-9_.-]{1,128}$/.test(e)||e==="."||e==="..")throw new TypeError(`${JSON.stringify(e)} is not a usable path segment \u2014 it is interpolated into a URL`);return encodeURIComponent(e)}async function nn(n,e,t){let r=`/v1/inventory/transfers/${s(e)}/accept`;return n.client.post(r,void 0,t?.signal)}async function tn(n,e,t,r,o,a){let i=`/v1/inventory/${s(e)}/${s(t)}/progressions/${s(r)}/add`;return n.client.post(i,o,a?.signal)}async function rn(n,e,t,r){let o=`/v1/voice/sessions/${s(e)}/admin`;return n.client.post(o,t,r?.signal)}async function on(n,e,t){let r=`/v1/inventory/transfers/${s(e)}/cancel`;return n.client.post(r,void 0,t?.signal)}async function an(n,e,t,r,o,a){let i=`/v1/inventory/${s(e)}/${s(t)}/progressions/${s(r)}/claim`;return n.client.post(i,o,a?.signal)}async function sn(n,e,t){let r=`/v1/games/${s(n.gameId())}/game-rooms/${s(e)}`;return n.client.delete(r,t?.signal)}async function ln(n,e,t,r,o){let a=`/v1/inventory/${s(e)}/${s(t)}/orders/batch`;return n.client.post(a,r,o?.signal,{...o?.ifMatch===void 0?{}:{ifMatch:o.ifMatch}})}async function dn(n,e,t,r,o){let a=`/v1/inventory/${s(e)}/${s(t)}/orders`;return n.client.post(a,r,o?.signal,{...o?.ifMatch===void 0?{}:{ifMatch:o.ifMatch}})}async function un(n,e,t){return n.client.post("/v1/voice/sessions",e,t?.signal)}async function cn(n,e,t,r,o){let a=`/v1/settings/${s(e)}/${s(t)}/${s(r)}`;return n.client.delete(a,o?.signal)}async function mn(n,e,t,r,o){let a=`/v1/saves/${s(e)}/${s(t)}/${s(r)}`;return n.client.delete(a,o?.signal)}async function gn(n,e,t){let r=`/v1/voice/sessions/${s(e)}`;return n.client.delete(r,t?.signal)}async function pn(n,e,t,r){let o=`/v1/showcase/players/${s(e)}/${s(t)}`;return n.client.delete(o,r?.signal)}async function yn(n,e,t,r,o){let a=`/v1/inventory/${s(e)}/${s(t)}/recipes/execute`;return n.client.post(a,r,o?.signal,{...o?.ifMatch===void 0?{}:{ifMatch:o.ifMatch}})}async function fn(n,e,t,r,o,a){let i=`/v1/saves/${s(e)}/${s(t)}/${s(r)}/finalize`;return n.client.post(i,o,a?.signal)}async function hn(n,e,t){let r=`/v1/games/${s(n.gameId())}/config/channels/${s(e)}`;return n.client.getWithEtag(r,{...t?.signal===void 0?{}:{signal:t.signal},...t?.ifNoneMatch===void 0?{}:{ifNoneMatch:t.ifNoneMatch}})}async function _n(n,e,t){let r=`/v1/inventory/loot-tables/${s(e)}/drop-rates`;return n.client.get(r,t?.signal)}async function bn(n,e,t,r,o){let a=`/v1/inventory/${s(e)}/${s(t)}/currencies/${s(r)}`;return n.client.get(a,o?.signal)}async function vn(n,e,t,r,o){let a=`/v1/settings/${s(e)}/${s(t)}/${s(r)}`;return n.client.getWithEtag(a,{...o?.signal===void 0?{}:{signal:o.signal},...o?.ifNoneMatch===void 0?{}:{ifNoneMatch:o.ifNoneMatch}})}async function Rn(n,e,t,r){let o=new URLSearchParams;r?.include_buckets!==void 0&&o.set("include_buckets",String(r?.include_buckets)),r?.include_custom_data!==void 0&&o.set("include_custom_data",String(r?.include_custom_data)),r?.currency_limit!==void 0&&o.set("currency_limit",String(r?.currency_limit)),r?.currency_cursor!==void 0&&o.set("currency_cursor",String(r?.currency_cursor)),r?.item_limit!==void 0&&o.set("item_limit",String(r?.item_limit)),r?.item_cursor!==void 0&&o.set("item_cursor",String(r?.item_cursor)),r?.progression_limit!==void 0&&o.set("progression_limit",String(r?.progression_limit)),r?.progression_cursor!==void 0&&o.set("progression_cursor",String(r?.progression_cursor));let a=o.toString(),i=`/v1/inventory/${s(e)}/${s(t)}`+(a?`?${a}`:"");return n.client.get(i,r?.signal)}async function xn(n,e,t,r,o){let a=`/v1/inventory/${s(e)}/${s(t)}/items/${s(r)}`;return n.client.get(a,o?.signal)}async function Sn(n,e,t,r,o){let a=new URLSearchParams;o?.bucket_1!==void 0&&a.set("bucket_1",String(o?.bucket_1)),o?.bucket_2!==void 0&&a.set("bucket_2",String(o?.bucket_2)),o?.limit!==void 0&&a.set("limit",String(o?.limit)),o?.periods_back!==void 0&&a.set("periods_back",String(o?.periods_back)),o?.period!==void 0&&a.set("period",String(o?.period)),o?.player_id!==void 0&&a.set("player_id",String(o?.player_id));let i=a.toString(),d=`/v1/leaderboards/${s(e)}/${s(t)}/${s(r)}`+(i?`?${i}`:"");return n.client.get(d,o?.signal)}async function kn(n,e,t,r,o){let a=`/v1/inventory/${s(e)}/${s(t)}/orders/${s(r)}`;return n.client.get(a,o?.signal)}async function wn(n,e,t,r,o){let a=`/v1/inventory/${s(e)}/${s(t)}/progressions/${s(r)}`;return n.client.get(a,o?.signal)}async function An(n,e,t,r,o,a){let i=`/v1/inventory/${s(e)}/${s(t)}/catalogs/${s(r)}/recipes/${s(o)}/availability`;return n.client.get(i,a?.signal)}async function Pn(n,e,t,r){let o=new URLSearchParams;r?.limit!==void 0&&o.set("limit",String(r?.limit));let a=o.toString(),i=`/v1/inventory/${s(e)}/${s(t)}/recipe-usage`+(a?`?${a}`:"");return n.client.get(i,r?.signal)}async function Tn(n,e,t,r,o){let a=`/v1/saves/${s(e)}/${s(t)}/${s(r)}`;return n.client.getWithEtag(a,{...o?.signal===void 0?{}:{signal:o.signal},...o?.ifNoneMatch===void 0?{}:{ifNoneMatch:o.ifNoneMatch}})}async function On(n,e,t){let r=`/v1/events/${s(e)}`;return n.client.get(r,t?.signal)}async function Gn(n,e,t){let r=`/v2/games/${s(n.gameId())}/game-rooms/${s(e)}`;return n.client.getWithEtag(r,{...t?.signal===void 0?{}:{signal:t.signal},...t?.ifNoneMatch===void 0?{}:{ifNoneMatch:t.ifNoneMatch}})}async function Cn(n,e,t){let r=new URLSearchParams;t?.bucket_1!==void 0&&r.set("bucket_1",String(t?.bucket_1)),t?.bucket_2!==void 0&&r.set("bucket_2",String(t?.bucket_2)),t?.periods_back!==void 0&&r.set("periods_back",String(t?.periods_back)),t?.period!==void 0&&r.set("period",String(t?.period)),t?.player_id!==void 0&&r.set("player_id",String(t?.player_id));let o=r.toString(),a=`/v1/leaderboards/${s(e)}`+(o?`?${o}`:"");return n.client.get(a,t?.signal)}async function En(n,e,t){let r=`/v1/profiles/players/${s(e)}`;return n.client.get(r,t?.signal)}async function In(n,e){let t=new URLSearchParams;e?.config_version!==void 0&&t.set("config_version",String(e?.config_version));let r=t.toString(),o="/v1/inventory/platform-funded-game-inventory-purchase-catalog"+(r?`?${r}`:"");return n.client.get(o,e?.signal)}async function qn(n,e,t){let r=`/v1/game-room-templates/${s(e)}`;return n.client.get(r,t?.signal)}async function Ln(n,e,t){let r=`/v1/games/${s(n.gameId())}/game-rooms/${s(e)}/room-args`;return n.client.get(r,t?.signal)}async function Mn(n,e,t,r){let o=`/v1/showcase/players/${s(e)}/${s(t)}`;return n.client.get(o,r?.signal)}async function $n(n,e,t){let r=`/v1/inventory/transfers/${s(e)}`;return n.client.get(r,t?.signal)}async function N(n,e,t){let r=`/v1/games/${s(n.gameId())}/analytics/events`;return n.client.post(r,e,t?.signal,{replaySafe:true})}async function jn(n,e,t){return n.client.post("/v1/inventory/transfers",e,t?.signal)}async function Fn(n,e,t){return n.client.postBytes("/v1/functions/invoke",e,t?.signal)}async function Bn(n,e,t,r){let o=`/v1/games/${s(n.gameId())}/game-rooms/${s(e)}/kick/${s(t)}`;return n.client.post(o,void 0,r?.signal)}async function Un(n,e){let t=new URLSearchParams;e?.periods_back!==void 0&&t.set("periods_back",String(e?.periods_back)),e?.player_id!==void 0&&t.set("player_id",String(e?.player_id));let r=t.toString(),o="/v1/challenges"+(r?`?${r}`:"");return n.client.get(o,e?.signal)}async function Nn(n,e,t,r){let o=`/v1/settings/${s(e)}/${s(t)}`;return n.client.get(o,r?.signal)}async function Dn(n,e,t,r){let o=new URLSearchParams;r?.limit!==void 0&&o.set("limit",String(r?.limit)),r?.cursor!==void 0&&o.set("cursor",String(r?.cursor));let a=o.toString(),i=`/v1/inventory/${s(e)}/${s(t)}/orders`+(a?`?${a}`:"");return n.client.get(i,r?.signal)}async function Hn(n,e,t,r){let o=`/v1/inventory/${s(e)}/${s(t)}/progressions`;return n.client.get(o,r?.signal)}async function Vn(n,e,t,r){let o=new URLSearchParams;r?.limit!==void 0&&o.set("limit",String(r?.limit)),r?.cursor!==void 0&&o.set("cursor",String(r?.cursor));let a=o.toString(),i=`/v1/saves/${s(e)}/${s(t)}`+(a?`?${a}`:"");return n.client.get(i,r?.signal)}async function Wn(n,e){let t=new URLSearchParams;e?.include_inactive!==void 0&&t.set("include_inactive",String(e?.include_inactive)),e?.limit!==void 0&&t.set("limit",String(e?.limit)),e?.offset!==void 0&&t.set("offset",String(e?.offset));let r=t.toString(),o="/v1/events"+(r?`?${r}`:"");return n.client.get(o,e?.signal)}async function zn(n,e){let t=new URLSearchParams;e?.status!==void 0&&t.set("status",String(e?.status)),e?.game_channel!==void 0&&t.set("game_channel",String(e?.game_channel)),e?.game_room_type!==void 0&&t.set("game_room_type",String(e?.game_room_type)),e?.template_id!==void 0&&t.set("template_id",String(e?.template_id)),e?.template_slug!==void 0&&t.set("template_slug",String(e?.template_slug)),e?.limit!==void 0&&t.set("limit",String(e?.limit)),e?.cursor!==void 0&&t.set("cursor",String(e?.cursor));let r=t.toString(),o=`/v1/games/${s(n.gameId())}/game-rooms`+(r?`?${r}`:"");return n.client.get(o,e?.signal)}async function Kn(n,e){return n.client.get("/v1/game-room-templates",e?.signal)}async function Yn(n,e){let t=new URLSearchParams;e.entity_type!==void 0&&t.set("entity_type",String(e.entity_type)),e.entity_id!==void 0&&t.set("entity_id",String(e.entity_id)),e?.direction!==void 0&&t.set("direction",String(e?.direction)),e?.status!==void 0&&t.set("status",String(e?.status)),e?.cursor!==void 0&&t.set("cursor",String(e?.cursor)),e?.limit!==void 0&&t.set("limit",String(e?.limit));let r=t.toString(),o="/v1/inventory/transfers"+(r?`?${r}`:"");return n.client.get(o,e?.signal)}async function Jn(n,e,t,r,o,a){let i=`/v1/inventory/${s(e)}/${s(t)}/progressions/${s(r)}/max`;return n.client.post(i,o,a?.signal)}async function Xn(n,e,t,r,o,a){let i=`/v1/settings/${s(e)}/${s(t)}/${s(r)}`;return n.client.put(i,o,a?.signal,{...a?.ifMatch===void 0?{}:{ifMatch:a.ifMatch}})}async function Qn(n,e,t,r){let o=`/v1/games/${s(n.gameId())}/game-rooms/${s(e)}/room-args`;return n.client.put(o,t,r?.signal)}async function Zn(n,e,t,r,o){let a=`/v1/showcase/players/${s(e)}/${s(t)}`;return n.client.put(a,r,o?.signal)}async function et(n,e,t){let r=`/v1/inventory/transfers/${s(e)}/reject`;return n.client.post(r,void 0,t?.signal)}async function nt(n,e,t,r){let o=`/v1/games/${s(n.gameId())}/matches/${s(e)}/players/report`;return n.client.post(o,t,r?.signal)}async function tt(n,e,t,r,o,a){let i=`/v1/saves/${s(e)}/${s(t)}/${s(r)}/upload-url`;return n.client.post(i,o,a?.signal,{replaySafe:true})}async function rt(n,e,t,r,o,a){let i=`/v1/inventory/${s(e)}/${s(t)}/progressions/${s(r)}/reset`;return n.client.post(i,o,a?.signal)}async function ot(n,e,t,r){let o=`/v1/games/${s(n.gameId())}/matches/${s(e)}/backfill`;return n.client.put(o,t,r?.signal)}async function at(n,e,t,r,o){let a=`/v1/inventory/${s(e)}/${s(t)}/orders/simulate`;return n.client.post(a,r,o?.signal)}async function st(n,e,t,r){let o=`/v2/games/${s(n.gameId())}/game-rooms/${s(e)}/transfer/${s(t)}`;return n.client.post(o,void 0,r?.signal)}async function it(n,e,t,r){let o=`/v2/games/${s(n.gameId())}/game-rooms/${s(e)}`;return n.client.patch(o,t,r?.signal,{...r?.ifMatch===void 0?{}:{ifMatch:r.ifMatch}})}var ae="gem_";var ut=1e4,ct=50,mt=1e3,gt=65536-4*1024,se=n=>typeof n=="number"?n:0,pt=n=>typeof n=="string"?n:"";function ie(){let n=globalThis.crypto;return typeof n?.randomUUID=="function"?n.randomUUID():"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,e=>{let t=Math.floor(Math.random()*16);return (e==="x"?t:t&3|8).toString(16)})}function yt(n){return n?.retryable===true}function ft(n,e){let t=n??{},r=Array.isArray(t.rejected)?t.rejected.map(o=>{let a=o??{};return {index:se(a.index),code:pt(a.code)}}):[];return {accepted:se(t.accepted),rejected:r,dropped:e,duplicate:t.duplicate===true}}function le(n,e){return {event_uid:n.uid,name:n.name,offset_ms:Math.round(n.atMs)-e,player_id:n.playerId,dimensions:n.dimensions,measures:n.measures}}function de(n){let e=Math.max(1,Math.floor(n.maxQueue??mt)),t={client:n.client,gameId:()=>n.gameId},r=[],o=0,a=null,i=false,d=false,l=false,c=false,p=m=>{n.log?.(m);},b=()=>{a!==null&&(n.clock.clearTimeout(a),a=null);},S=()=>{a!==null||i||d||(a=n.clock.setTimeout(()=>{a=null,y().catch(()=>{});},ut));},_=()=>{let m=Math.min(r.length,100),f=128;for(let v=0;v<m;v+=1){let A=r[v];if(A===void 0)break;if(f+=JSON.stringify(le(A,0)).length+1,f>gt)return Math.max(1,v)}return m};async function y(m){if(r.length===0)return {accepted:0,rejected:[],dropped:0,duplicate:false};b();let f=r.splice(0,_()),v=o;o=0;let A=Math.round(n.clock.now()),L={batch_id:ie(),sent_at_ms:A,events:f.map(k=>le(k,A))};d=true;try{let k=await N(t,L,m===void 0?void 0:{signal:m}),P=ft(k,v);for(let ve of P.rejected)p(`[gem] analytics: an event was refused (${ve.code}). See the analytics_events section of your game config.`);return P}catch(k){if(yt(k))for(r=[...f,...r],o+=v;r.length>e;)r.shift(),o+=1;else p(`[gem] analytics: ${f.length} event(s) were discarded \u2014 the platform refused the batch and will refuse it again: ${String(k)}`);throw k}finally{d=false,r.length>0&&S();}}return {track(m,f,v={}){if(i)return;if(typeof m!="string"||m===""){c||(c=true,p(`[gem] analytics: '${f}' was not recorded \u2014 an event from a server has to name the player it is about. A game-server token names no player, so the platform cannot infer one; pass the id from join() or host.players().`));return}if(f.startsWith(ae)){l||(l=true,p(`[gem] analytics: '${f}' was not recorded \u2014 the gem_ prefix is reserved, and the platform's own events are client-sourced, so a server may not emit one at all. Name your event something else.`));return}let A={},L={};for(let[k,P]of Object.entries(v))typeof P=="string"?A[k]=P:typeof P=="number"&&Number.isFinite(P)&&(L[k]=P);for(;r.length>=e;)r.shift(),o+=1;r.push({uid:ie(),playerId:m,name:f,atMs:n.clock.now(),dimensions:A,measures:L}),r.length>=ct?y().catch(()=>{}):S();},flush:m=>y(m),get pending(){return r.length},dispose(){i=true,b(),r=[],o=0;}}}var ht=new Map([["function_error",false],["function_failed",false],["function_timeout",false],["function_not_published",false],["function_input_too_large",false],["functions_not_configured",false],["forbidden",false],["function_capacity_unavailable",true],["function_host_unreachable",true],["function_host_error",true],["rate_limited",true],["service_unavailable",true]]),I=class extends g{constructor(e,t){super(e.reason,e.status,e.detail,e.retryAfterSeconds,e.code),this.name="GemFunctionError",Object.assign(this,t);}get retryable(){return (this.code===void 0?void 0:ht.get(this.code))??super.retryable}},C=class{#e;constructor(e){this.#e=e;}async invoke(e,t={}){let r=_t(e),o;try{o=await this.#e(r,t.signal===void 0?{}:{signal:t.signal});}catch(a){throw a instanceof g?vt(a):a}return bt(o)}};function _t(n){if(n instanceof ArrayBuffer)return new Uint8Array(n);if(ArrayBuffer.isView(n))return new Uint8Array(n.buffer,n.byteOffset,n.byteLength);let e;try{e=JSON.stringify(n);}catch(t){throw new h(`the function input could not be serialised to JSON: ${String(t)}. Pass bytes, or a value JSON can carry. This is a bug in the call, not a server failure.`)}if(e===void 0)throw new h(`the function input is ${typeof n}, which JSON cannot carry. Pass bytes \u2014 an empty Uint8Array for no input \u2014 or a JSON value. This is a bug in the call, not a server failure.`);return new TextEncoder().encode(e)}function bt(n){let{bytes:e}=n,t=()=>new TextDecoder("utf-8",{fatal:true}).decode(e);return {bytes:e,...n.invocationId===void 0?{}:{invocationId:n.invocationId},text:t,json:()=>JSON.parse(t())}}function vt(n){let{details:e,invocationId:t}=J(n),o=e?.untrusted?.message,a=e?.reason;return new I(n,{...t===void 0?{}:{invocationId:t},...n.code==="function_error"&&typeof o=="string"?{functionMessage:o}:{},...n.code==="function_failed"&&typeof a=="string"?{failure:a}:{}})}var w=n=>typeof n=="string"?n:"",Rt=/(?:Z|[+-]\d{2}:?\d{2})$/i;function ue(n){let e=w(n);if(!Rt.test(e))return 0;let t=Date.parse(e);return Number.isFinite(t)?Math.floor(t/1e3):0}var xt=/^[0-9a-f]{1,64}$/,St=/^[0-9a-f]{16}$/,kt=/^[A-Za-z][A-Za-z0-9_+\-/]{0,63}$/,wt=/^(?:[01]\d|2[0-3]):[0-5]\d$/;function At(n){let e=w(n),t=/^(\d{4})-(\d{2})-(\d{2})$/.exec(e);if(!t)return;let[r,o,a]=[Number(t[1]),Number(t[2]),Number(t[3])],i=new Date(Date.UTC(r,o-1,a));return i.getUTCFullYear()===r&&i.getUTCMonth()===o-1&&i.getUTCDate()===a?e:void 0}var Pt=4096,Tt=new TextEncoder;function Ot(n){let e=w(n.challenge_data),t=w(n.challenge_data_hash);return e===""||!St.test(t)?{}:Tt.encode(e).length>Pt?{}:{data:e,dataHash:t}}function Gt(n){let e=n??{},t=ue(e.period_start_at),r=ue(e.period_ends_at);if(t===0||r===0)return;let o=w(e.slug),a=w(e.seed),i=At(e.period_local_date),d=w(e.boundary),l=w(e.reset_time);return {id:w(e.progression_definition_id),...o===""?{}:{slug:o},window:w(e.window),periodStartAt:t,periodEndsAt:r,...i===void 0?{}:{periodLocalDate:i},boundary:kt.test(d)?d:"",resetTime:wt.test(l)?l:"",seed:xt.test(a)?a:"",...Ot(e)}}function ce(n){if(n!==void 0&&(!Number.isInteger(n)||n<0||n>400))throw new TypeError(`periodsBack must be an integer between 0 and 400, got ${String(n)}`)}function me(n){let e=n??{};return Array.isArray(e.challenges)?e.challenges.map(Gt).filter(t=>t!==void 0):[]}function ge(n){return {async list(e){let{playerId:t,periodsBack:r,signal:o}=e??{};if(typeof t!="string"||t==="")throw new TypeError("gem.challenges.list needs { playerId }: a game-server token names no player, so the platform cannot tell whose period you mean. Pass the id from join() or gem.players().");ce(r);let a=await n({player_id:t,...r===void 0?{}:{periods_back:r},...o===void 0?{}:{signal:o}});return me(a)}}}function Ct(n){let e={};for(let[t,r]of Object.entries(D))if(typeof r=="function"){let o=r;e[t]=(...a)=>o(n,...a);}return e}function F(n,e={}){let t=e.clock??G,r=e.baseUrl??n.apiBaseUrl;if(!r)throw new Error("this runtime names no gem-api host (host.apiBaseUrl is missing). The server image running this bundle predates token delivery \u2014 the bundle cannot call gem-api on it.");let o=U(n,{clock:t,...e.onAuthStateChange===void 0?{}:{onStateChange:e.onAuthStateChange}}),a=X({baseUrl:r,tokenSource:o.source,defaultQuery:{game_id:n.gameId,channel:n.channel},...e.fetch===void 0?{}:{fetch:e.fetch}}),i=new T({transport:a,clock:t}),d={gameId:n.gameId,channel:n.channel,matchId:n.matchId,...n.gameRoomId===void 0?{}:{gameRoomId:n.gameRoomId}},l=Ct({client:i,gameId:()=>d.gameId}),c=d.gameRoomId,p=n.endMatch,b=n.log,S=de({client:i,clock:t,gameId:d.gameId,...typeof b=="function"?{log:y=>b.call(n,y)}:{}});return {identity:d,client:i,api:l,match:{end:async()=>{if(p===void 0)throw new Error("this runtime cannot end the match: the server image running this bundle predates host.endMatch, and only the platform half holds the allocation proof an end needs.");await p.call(n);},setBackfill:async(y,m)=>{let f=await l.setMatchBackfill(d.matchId,{open:y.open,...y.seats===void 0?{}:{seats:y.seats}},m===void 0?{}:{signal:m});return {open:f.open,seats:f.seats??null}},reportPlayers:async(y,m)=>(await l.reportMatchPlayers(d.matchId,{players:y.map(v=>({player_id:v.playerId,state:v.state}))},m===void 0?{}:{signal:m})).players.map(v=>({playerId:v.player_id,outcome:v.outcome}))},analytics:S,functions:new C(l.invokeFunction),challenges:ge(l.listChallenges),...c===void 0?{}:{room:{get:y=>l.getGameRoomV2(c,y),args:async y=>{let m=await l.getGameRoomV2(c,y?.signal===void 0?{}:{signal:y.signal}),f=m.modified?m.body:void 0;if(f?.room_args==null||f.room_args_template==null)throw new g("not_found",404,"this room's template declares no room args",void 0,"room_args_not_defined");return {room_args:f.room_args,room_args_template:f.room_args_template}}}},dispose:()=>{S.dispose(),o.dispose();}}}var Et=["explicit","stale_cleanup","game_room_closed","replaced","migration_failed","host_left","insufficient_players","all_left","expired","migration_rate_exceeded","game_room_gone","failed","idle","reclaimed"],It=new Set(Et);function pe(n){return typeof n=="string"&&It.has(n)?n:"unknown"}var x=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 q(n){return new x(n)}var ye={toPlain(n){return x.unwrap(n)},compare(n,e,t){let r=n instanceof x?x.unwrap(n):n,o=e instanceof x?x.unwrap(e):e,a;try{a=new Intl.Collator(t);}catch{a=new Intl.Collator;}return a.compare(r,o)},equals(n,e){let t=n instanceof x?x.unwrap(n):n,r=e instanceof x?x.unwrap(e):e;return t.normalize("NFC")===r.normalize("NFC")}};var fe="the match has not started yet: the runtime hands over the host at `init`, and this was read before that. Read it from `init` or later \u2014 a bundle that needs a value at module scope is reading it one call too early.";function H(n,e={}){let t=e.clock??G,r=()=>{let d=n();if(d===null)throw new Error(fe);return d},o=null,a=()=>{if(o===null)throw new Error(fe);return o};return {server:{get identity(){return a().identity},get client(){return a().client},get api(){return a().api},get match(){return a().match},get analytics(){return a().analytics},get functions(){return a().functions},get challenges(){return a().challenges},get room(){return a().room},dispose(){o?.dispose();},get sizeClass(){return r().sizeClass},get roomArgs(){return r().roomArgs},get roster(){return r().roster},players(){return r().players()},profile(d){let c=r().profile?.(d);if(!c)return null;let p=c.displayName;return typeof p!="string"||p===""?null:{displayName:q(p),...typeof c.displayTag=="string"&&c.displayTag!==""?{displayTag:q(c.displayTag)}:{},...typeof c.discriminator=="string"?{discriminator:c.discriminator}:{}}},playerNumber(d){return r().playerNumber?.(d)},send(d,l,c){c===void 0?r().send(d,l):r().send(d,l,c);},broadcast(d,l){l===void 0?r().broadcast(d):r().broadcast(d,l);},kick(d,l){l===void 0?r().kick(d):r().kick(d,l);},log(d){r().log(d);},warn(d){r().warn(d);}},attach:()=>{o=F(r(),{...e,clock:t});}}}function he(n,e={}){let{server:t,attach:r}=H(()=>n,e);return r(),t}function qt(n){if(n===void 0||typeof n.reason!="string"||n.reason==="")return;let e=n.platform_reason??n.endedReason;return {reason:n.reason,...e===void 0?{}:{endedReason:pe(e)}}}var Lt=1e4;function Mt(n){let e=false;return t=>{if(e)return;let r;try{r=n.match.reportPlayers([{playerId:t,state:"connected"}],AbortSignal.timeout(Lt));}catch{return}r.catch(o=>{o instanceof g&&o.status>=400&&o.status<500&&(e=o.status!==429);});}}function _e(n,e={}){return ()=>{let t=null,{server:r,attach:o}=H(()=>t,e),a=n(r),i={async init(l){t=l,o(),await a.init?.();},async shutdown(l){let c=qt(l);try{await a.shutdown?.(c);}finally{r.dispose();}}},d=Mt(r);return i.join=(l,c)=>(d(l),a.join?.(l,c)),a.leave&&(i.leave=(l,c)=>a.leave?.(l,c)),a.message&&(i.message=(l,c,p,b)=>a.message?.(l,c,p,b)),i}}var $t=new Set(["unlocked","already_unlocked","suppressed"]);function be(n){let e=n?.changes;if(!Array.isArray(e))return [];let t=[];for(let r of e){let o=r??{};if(o.type!=="achievement_unlocked"||typeof o.outcome!="string"||!$t.has(o.outcome)||typeof o.achievement_id!="string"||o.achievement_id==="")continue;let a=o.outcome;t.push({achievementId:o.achievement_id,progressionDefinitionId:typeof o.progression_definition_id=="string"?o.progression_definition_id:"",points:a==="unlocked"&&typeof o.points=="number"&&Number.isFinite(o.points)?o.points:0,outcome:a,...typeof o.reason=="string"?{reason:o.reason}:{}});}return t}
|
|
1
|
+
var Re=Object.defineProperty;var xe=(n,e)=>{for(var t in e)Re(n,t,{get:e[t],enumerable:true});};globalThis.__gemWebSdkVersion="[gem-web-sdk:sdkVersion:10.3.1]";function Se(n,e){return e!==void 0?!e:n==="chain_exhausted"}var M=class{constructor(e){this.options=e;}options;grant=null;state="pending";failure=null;generation=0;inFlight=null;rejected=false;get currentState(){return this.state}get lastFailure(){return this.failure}async get(){if(this.state==="lost")throw new R(this.failure??"unavailable","the session cannot be renewed");let e=this.seconds();if(this.grant&&e<this.grant.expiresAt-this.renewBefore())return this.grant.token;if(this.grant&&e>=this.grant.chainEndsAt)throw this.enter("lost","chain_exhausted"),new R("chain_exhausted","the token chain reached its ceiling");return this.refresh(this.nextReason())}nextReason(){return this.rejected?"rejected":this.grant?"expiring":"initial"}invalidate(e){e!==void 0&&this.grant!==null&&this.grant.token!==e||this.rejected&&this.grant===null||(this.grant=null,this.generation+=1,this.inFlight=null,this.rejected=true,this.state!=="lost"&&this.enter("pending"));}accept(e){this.state!=="lost"&&(this.grant=e,this.rejected=false,this.enter("ready"));}close(e="unavailable"){this.grant=null,this.generation+=1,this.inFlight=null,this.enter("lost",e);}refresh(e){if(this.inFlight)return this.inFlight;let t=this.generation;this.enter("pending");let r=this.options.request(e).then(o=>{if(t!==this.generation)throw new R("internal","token arrived for a superseded generation");return this.grant=o,this.rejected=false,this.enter("ready"),o.token}).catch(o=>{let a=ke(o),i=o?.retryable;throw t===this.generation&&this.enter(Se(a,typeof i=="boolean"?i:void 0)?"lost":"degraded",a),o instanceof R?o:new R(a,String(o))}).finally(()=>{this.inFlight===r&&(this.inFlight=null);});return this.inFlight=r,r}enter(e,t){this.failure=t??(e==="ready"?null:this.failure),this.state!==e&&(this.state=e,this.options.onStateChange?.(e,t));}renewBefore(){return this.options.renewBeforeSeconds??60}seconds(){return Math.floor(this.options.clock.now()/1e3)}},R=class n extends Error{constructor(t,r){super(`auth ${t}: ${r}`);this.reason=t;this.name="AuthError";}reason;static isAuthError(t){if(t instanceof n)return true;let r=t;return r?.name==="AuthError"&&typeof r.reason=="string"}};function ke(n){if(n instanceof R)return n.reason;let e=n?.reason;return typeof e=="string"&&["chain_exhausted","unavailable","timeout","internal"].includes(e)?e:"internal"}var h=class n extends Error{retryable=false;constructor(e){super(e),this.name="TransportRefusal";}static isRefusal(e){if(e instanceof n)return true;let t=e;return t?.name==="TransportRefusal"&&t.retryable===false}},$=["if-match","if-none-match"],V=4096;function we(n){if(!n)return;let e={};for(let[t,r]of Object.entries(n)){let o=t.toLowerCase();if(!$.includes(o)||r===void 0)continue;let a=typeof r=="string"?Ae(r):r;if(typeof a!="string"||a.length>V||!Pe(a))throw new h(`the ${o} header value cannot be sent \u2014 it is not a string, is longer than ${V} characters, or contains a character outside the range an HTTP header value may carry. This is a malformed request, not a server failure; the value is withheld here rather than written to logs.`);a!==""&&(e[o]=a);}return Object.freeze(e)}function Ae(n){let e=o=>o===32||o===9||o===10||o===13,t=0,r=n.length;for(;t<r&&e(n.charCodeAt(t));)t++;for(;r>t&&e(n.charCodeAt(r-1));)r--;return n.slice(t,r)}function Pe(n){for(let e=0;e<n.length;e++){let t=n.charCodeAt(e);if(t!==9&&(t<32||t===127||t>255))return false}return true}function Te(n){let{bytes:e}=n;if(e!==void 0){if(Object.prototype.toString.call(e)!=="[object Uint8Array]")throw new h("the raw body is not a Uint8Array, so it cannot be sent as bytes. This is a malformed request, not a server failure.");if(n.body!==void 0)throw new h("the request carries both a JSON body and a raw body, and only one can be sent. This is a malformed request, not a server failure.");return new Uint8Array(e)}}function W(n,e){let t=e.replayUnauthorizedOnce??true;return {async request(r){let o={...r},a=we(o.headers),i=Te(o),d=Object.freeze({...o,headers:a,...i===void 0?{}:{bytes:i}}),l=await e.tokenSource.get(),c=await n(d,l);if(c.status!==401||!t)return c;e.tokenSource.invalidate(l);let p=await e.tokenSource.get(),b=await n(d,p);if(b.status===401)throw e.tokenSource.close("unavailable"),new R("unavailable","the server refused a freshly minted token");return b}}}function z(n){let e=typeof n=="string"?new TextEncoder().encode(n):n;return btoa(Oe(e))}function Oe(n){let t="";for(let r=0;r<n.length;r+=32768)t+=String.fromCharCode(...n.subarray(r,r+32768));return t}var g=class extends Error{constructor(t,r,o,a,i){super(`${t} (${r}): ${o}`);this.reason=t;this.status=r;this.detail=o;this.retryAfterSeconds=a;this.code=i;this.name="GemApiError";}reason;status;detail;retryAfterSeconds;code;get retryable(){return this.reason==="unavailable"||this.reason==="rate_limited"}},Y=new WeakMap;function J(n){return Y.get(n)??{}}var Ge=new Set([408,429,500,502,503,504]),Ce=6e4;function Ee(n){if(n===void 0)return 2;if(!Number.isInteger(n)||n<0||n>10)throw new h(`maxRetries must be a whole number between 0 and 10; received ${JSON.stringify(n)}. This is a configuration fault, not a server failure.`);return n}var T=class{constructor(e){this.options=e;}options;async get(e,t){return this.send({method:"GET",path:e,signal:t},true)}async getWithEtag(e,t={}){let r=await this.sendRaw({method:"GET",path:e,...t.signal===void 0?{}:{signal:t.signal},...t.ifNoneMatch===void 0?{}:{headers:{"if-none-match":t.ifNoneMatch}}},true),o=r.etag===void 0?{}:{etag:r.etag};return r.status===304?{modified:false,...o}:{modified:true,body:r.body,...o}}async put(e,t,r,o={}){return this.send({method:"PUT",path:e,body:t,signal:r,...E(o)},o.replaySafe===true)}async post(e,t,r,o={}){return this.send({method:"POST",path:e,body:t,signal:r,...E(o)},o.replaySafe===true)}async postBytes(e,t,r,o={}){let a=await this.sendRaw({method:"POST",path:e,bytes:t,responseType:"bytes",signal:r,...E(o)},o.replaySafe===true);return {bytes:Ie(a.body),...a.invocationId===void 0?{}:{invocationId:a.invocationId}}}async patch(e,t,r,o={}){return this.send({method:"PATCH",path:e,body:t,signal:r,...E(o)},o.replaySafe===true)}async delete(e,t,r={}){return this.send({method:"DELETE",path:e,signal:t,...E(r)},r.replaySafe===true)}async send(e,t){return (await this.sendRaw(e,t)).body}async sendRaw(e,t){let r=t?Ee(this.options.maxRetries)+1:1,o=null;if(e.signal?.aborted)throw K(e.signal);for(let a=0;a<r;a++){if(a>0&&await this.backoff(a,o,e.signal),e.signal?.aborted)throw K(e.signal);let i;try{i=await this.options.transport.request(e);}catch(l){if(R.isAuthError(l)||h.isRefusal(l)||e.signal?.aborted||qe(l))throw l;o=new g("unavailable",0,String(l));continue}if(i.status>=200&&i.status<300||i.status===304)return i;let d=Le(i);if(!Ge.has(i.status))throw d;o=d;}throw o??new g("unavailable",0,"no attempt was made")}backoff(e,t,r){if(r?.aborted)return Promise.resolve();let o=t?.retryAfterSeconds,a=o!==void 0?o*1e3:2**(e-1)*250,i=2**(e-1)*250,d=Math.min(Math.max(a,i),Ce);return new Promise(l=>{let c=this.options.clock,p=false,b=false,S,_=()=>{p||(p=true,b&&c.clearTimeout(S),r?.removeEventListener("abort",_),l());};r?.addEventListener("abort",_,{once:true}),S=c.setTimeout(_,d),b=true,p&&c.clearTimeout(S);})}};function Ie(n){if(n instanceof Uint8Array)return n;if(n==null)return new Uint8Array(0);let e=typeof n=="string"?n:JSON.stringify(n);return new TextEncoder().encode(e)}function E(n){return {...n.keepalive===void 0?{}:{keepalive:n.keepalive},...n.ifMatch===void 0?{}:{headers:{"if-match":n.ifMatch}}}}function K(n){return n.reason!==void 0?n.reason:new DOMException("The operation was aborted.","AbortError")}function qe(n){let e=n?.name;return e==="AbortError"||e==="TimeoutError"}function Le(n){let e=$e(n),t=Fe(n.body),r={...t===void 0?{}:{details:t},...n.invocationId===void 0?{}:{invocationId:n.invocationId}};return Object.keys(r).length>0&&Y.set(e,r),e}var Me=new Map([["insufficient_funds","insufficient_funds"]]);function $e(n){let{status:e,body:t}=n,r=je(t),o=n.retryAfterSeconds??Ue(t),a=Be(t),i=a===void 0?void 0:Me.get(a);if(i!==void 0)return new g(i,e,r,void 0,a);switch(e){case 304:return new g("not_modified",e,r);case 400:case 422:return new g("invalid",e,r,void 0,a);case 403:return new g("forbidden",e,r,void 0,a);case 404:return new g("not_found",e,r,void 0,a);case 402:return new g("insufficient_funds",e,r,void 0,a);case 409:return new g("conflict",e,r,void 0,a);case 412:return new g("precondition_failed",e,r,void 0,a);case 413:return new g("too_large",e,r,void 0,a);case 429:return new g("rate_limited",e,r,o,a);default:return new g("unavailable",e,r,o,a)}}function je(n){if(typeof n=="string")return n;let e=n?.message;if(typeof e=="string")return e;let t=n?.error;if(typeof t=="string")return t;let r=t?.message;return typeof r=="string"?r:"no detail"}function Fe(n){let t=n?.error?.details;return t===null?void 0:t}function Be(n){let t=n?.error?.code;return typeof t=="string"&&t.length>0?t:void 0}function Ue(n){let e=n?.retryAfterSeconds;return typeof e=="number"&&Number.isFinite(e)&&e>=0?e:void 0}function Ne(n){let e=n.lastIndexOf("@");return (e===-1?n:`***@${n.slice(e+1)}`).slice(0,200)}var De=new Set($);function He(n){if(!n)return {};let e={};for(let[t,r]of Object.entries(n))De.has(t.toLowerCase())&&(e[t.toLowerCase()]=r);return e}function X(n){let e=n.fetch??globalThis.fetch.bind(globalThis);return W(async(t,r)=>{let o;try{o=new URL(n.baseUrl.replace(/\/+$/,""));}catch{throw new h("the configured baseUrl is not a valid URL. Its value is withheld here rather than written to logs. This is a configuration fault, not a server failure.")}let a;try{a=new URL(o.href.replace(/\/+$/,"")+t.path);}catch{throw new h(`${JSON.stringify(typeof t.path=="string"?Ne(t.path):"(a non-string path)")} does not form a valid URL against ${o.protocol}//${o.host}. This is a malformed request, not a server failure.`)}if(a.protocol!==o.protocol||a.host!==o.host)throw new h(`${JSON.stringify(a.pathname)} resolves to ${a.protocol}//${a.host}, not ${o.protocol}//${o.host}. A request path may not change the request's origin \u2014 it carries the play token.`);if(a.username!==""||a.password!==""){let _=o.username!==""||o.password!=="",y=a.username!==o.username||a.password!==o.password,m=_?y?"baseUrl (and possibly the request path)":"baseUrl":"request path";throw new h(`the ${m} puts credentials in the URL, which cannot be fetched (${t.method} ${a.pathname}). The value is withheld here rather than written to logs. This is a malformed request, not a server failure.`)}for(let[_,y]of Object.entries(n.defaultQuery??{}))a.searchParams.has(_)||a.searchParams.set(_,y);let i=t.bytes,d=t.bytes===void 0?void 0:"application/octet-stream";try{t.body!==void 0&&(i=JSON.stringify(t.body),d="application/json");}catch(_){throw new h(`the body of ${t.method} ${JSON.stringify(a.pathname)} could not be serialised to JSON: ${String(_)}. This is a bug in the request, not a server failure \u2014 retrying sends the same unserialisable value.`)}let l=await e(a.toString(),{method:t.method,headers:{authorization:`Bearer ${r}`,...d===void 0?{}:{"content-type":d},...He(t.headers)},body:i,signal:t.signal,...t.keepalive===void 0?{}:{keepalive:t.keepalive},credentials:"omit",mode:"cors",redirect:"error",cache:"no-store",referrerPolicy:"no-referrer"}),c=null;if(t.responseType==="bytes"&&l.status>=200&&l.status<300)c=new Uint8Array(await l.arrayBuffer());else {let _=await l.text();if(_.length>0)try{c=JSON.parse(_);}catch{c=_;}}let p=l.headers.get("etag"),b=Ve(l.headers.get("retry-after")),S=l.headers.get("x-gem-invocation-id");return {status:l.status,body:c,...p===null?{}:{etag:p},...b===void 0?{}:{retryAfterSeconds:b},...S===null||S===""?{}:{invocationId:S}}},n)}function Ve(n){if(n===null)return;let e=n.trim();if(!/^\d+$/.test(e))return;let t=Number(e);return Number.isFinite(t)?t:void 0}var We="gem-web-bridge";var O=65536,Q=8,j=5e3,Z=1024;function ee(n){return Object.freeze(Object.assign(Object.create(null),n))}ee({"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.controlsDeclare":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});ee({"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","gem.controlsDeclare":"controls"});function Ke(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 Ye(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 Je(n){return /^[a-z]{2,8}(-[a-z0-9]{1,8})*$/i.test(n)}function Xe(n){return /^[a-z_]+$/.test(n)}function B(n,e,t){if(e>Q)return `nesting deeper than ${Q}`;if(++t.nodes>j)return `more than ${j} values`;if(t.bytes>O)return `over the ${O} 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>Z)return `an array of ${n.length} entries, over the ${Z} limit`;t.bytes+=2;for(let d of n){let l=B(d,e+1,t);if(l)return l}return null}let a=Object.getPrototypeOf(n);if(a!==Object.prototype&&a!==null)return "a value that is not a plain object";t.bytes+=2;let i=n;for(let d in i){if(!Object.prototype.hasOwnProperty.call(i,d))continue;if(++t.nodes>j)return `more than ${j} values`;if(t.bytes+=d.length*3+4,t.bytes>O)return `over the ${O} byte limit`;let l=B(i[d],e+1,t);if(l)return l}return null}function Qe(n){let e={nodes:0,bytes:0,seen:new Set},t=B(n,0,e);return t?`message contains ${t}`:e.bytes>O?`message is over the ${O} byte limit`:null}var Ze={origin:[Ke,"not a well-formed origin"],url:[Ye,"not a safe absolute http(s) URL"],bcp47:[Je,"not a well-formed BCP 47 tag"],code:[Xe,"not a code of lower-case letters and underscores"]};function ne(n,e,t){for(let r of e){let o=t===""?r.n:`${t}.${r.n}`,a=n[r.n];if(a==null){if(r.o)continue;return `${o}: required`}let i=te(a,r,o);if(i)return i}return null}function te(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]=Ze[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`:ne(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 a of n){if(a==null){if(r.o)continue;return `${o}: required`}let i=te(a,r,o);if(i)return i}return null}default:{let r=e.k;return `${t}: unknown kind ${String(r)}`}}}var re=Object.create(null);function u(n,e){return re[n]=t=>{let r=Qe(t);if(r)return r;if(typeof t!="object"||t===null||Array.isArray(t))return "message: expected object";let o=t;return o.gem!==We?"gem: wrong protocol marker":o.type!==n?`type: expected ${n}`:ne(o,e,"")}}u("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}]);u("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}}]);u("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}]);u("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}]);u("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}]}]);u("gem.pause",[{n:"paused",k:"b"}]);u("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"},{n:"lookSensitivity",k:"i",o:1,lo:20,hi:400},{n:"gamepadLookSensitivity",k:"i",o:1,lo:20,hi:400},{n:"invertLookY",k:"b",o:1},{n:"touchMovement",k:"s",o:1,max:16,f:"code"}]}]);u("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}]}}]);u("gem.earnAllowanceChanged",[]);u("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}]}}]);u("gem.deviceSettings",[{n:"settings",k:"j",o:1}]);u("gem.willTerminate",[{n:"reason",k:"e",v:["grant_expiring","session_ended","navigating","kill_switch"]},{n:"graceMs",k:"i",lo:0,hi:6e4}]);u("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"]}]);u("gem.socketState",[{n:"connected",k:"b"},{n:"reason",k:"e",o:1,v:["connecting","dropped","watchdog","terminal"]}]);u("gem.seatedEvent",[{n:"roomId",k:"s",max:64}]);u("gem.autoStartFailedEvent",[{n:"roomId",k:"s",max:64},{n:"code",k:"s",max:64}]);u("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"}]);u("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}]);u("gem.partyResult",[{n:"requestId",k:"s",max:64},{n:"partyId",k:"s",o:1,max:64}]);u("gem.clusterTarget",[{n:"clusterTargetId",k:"s",max:64},{n:"clusterTargetIds",k:"a",o:1,max:3,it:{n:"",k:"s",max:64}}]);u("gem.devtools",[{n:"action",k:"e",v:["open","close","toggle"]}]);u("gem.screenshot",[{n:"maxWidth",k:"i",lo:1,hi:7680},{n:"maxHeight",k:"i",lo:1,hi:4320}]);u("gem.screenshot.denied",[{n:"reason",k:"e",v:["not_wired","no_source","unsupported","unreadable","tainted","too_large","busy","declined","failed"]},{n:"retryable",k:"b"}]);u("gem.requestContext",[]);u("gem.gameContext",[{n:"context",k:"j"}]);u("gem.signal",[{n:"signal",k:"e",v:["join","offer","answer","ice","migrationAck","hostUnreachable"]},{n:"matchId",k:"s",max:64},{n:"data",k:"j"}]);u("gem.dedicatedOffer",[{n:"matchId",k:"s",max:64},{n:"sdp",k:"s",max:10240},{n:"intent",k:"e",v:["initial","ice_restart","full_reconnect"]}]);u("gem.partyRequest",[{n:"requestId",k:"s",max:64}]);u("gem.ready",[]);u("gem.engaged",[]);u("gem.progress",[{n:"loaded",k:"i",lo:0,hi:1099511627776},{n:"total",k:"i",lo:0,hi:1099511627776}]);u("gem.requestToken",[{n:"requestId",k:"s",max:64},{n:"reason",k:"e",v:["initial","expiring","rejected"]}]);u("gem.requestLocalServer",[{n:"requestId",k:"s",max:64},{n:"gameRoomId",k:"s",max:64}]);u("gem.localServer",[{n:"requestId",k:"s",max:64},{n:"serverId",k:"s",o:1,max:128}]);u("gem.localServer.denied",[{n:"requestId",k:"s",max:64},{n:"retryable",k:"b"},{n:"reason",k:"e",v:["refused","unavailable"]}]);u("gem.exit",[{n:"reason",k:"s",o:1,max:64}]);u("gem.openExternal",[{n:"url",k:"s",max:2048,f:"url"}]);u("gem.requestFullscreen",[{n:"enabled",k:"b"}]);u("gem.audioState",[{n:"muted",k:"b"}]);u("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}]}]);u("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}]);u("gem.controlsDeclare",[{n:"uses",k:"o",fs:[{n:"lookSensitivity",k:"s",o:1,max:16,f:"code"},{n:"gamepadLookSensitivity",k:"s",o:1,max:16,f:"code"},{n:"invertLookY",k:"s",o:1,max:16,f:"code"},{n:"touchMovement",k:"s",o:1,max:16,f:"code"}]}]);u("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}]}}]);u("gem.menuSelect",[{n:"entry",k:"e",v:["settings","item"]},{n:"id",k:"s",o:1,max:32}]);u("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}]}}]);u("gem.requestAvatarPicker",[]);u("gem.vibrate",[{n:"pattern",k:"a",max:99,it:{n:"",k:"i",lo:0,hi:1e4}}]);u("gem.frameStats",[{n:"fps",k:"i",lo:0,hi:1e3},{n:"frameTimeP95Ms",k:"i",lo:0,hi:1e5}]);u("gem.portraitBorders",[{n:"name",k:"s",o:1,max:40}]);u("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}]);u("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}]);u("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}]);u("gem.deviceSettings.put",[{n:"requestId",k:"s",max:64},{n:"settings",k:"j"}]);u("gem.deviceSettings.result",[{n:"requestId",k:"s",max:64},{n:"outcome",k:"e",v:["stored","too_large","unavailable"]}]);u("gem.requestAd",[{n:"requestId",k:"s",max:64},{n:"placement",k:"s",max:32},{n:"format",k:"e",v:["interstitial","rewarded"]}]);u("gem.adResult",[{n:"requestId",k:"s",max:64},{n:"outcome",k:"e",v:["shown","no_ad","unavailable"]}]);u("gem.requestSignIn",[{n:"requestId",k:"s",max:64}]);u("gem.signInResult",[{n:"requestId",k:"s",max:64},{n:"outcome",k:"e",v:["signed_in","declined","unavailable"]}]);u("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}]);u("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}]);Object.freeze(re);var G={now:()=>Date.now(),setTimeout:(n,e)=>setTimeout(n,e),clearTimeout:n=>clearTimeout(n)};var en=1e4;function oe(n,e){return U(n,e)}function U(n,e){if(typeof n.serverToken!="function"||typeof n.onServerToken!="function")throw new Error("this runtime delivers no game-server token: host.serverToken/onServerToken are missing. The server image running this bundle predates token delivery \u2014 the bundle cannot call gem-api on it.");let t=i=>({token:i.token,expiresAt:i.expiresAt,chainEndsAt:Number.POSITIVE_INFINITY}),r=null,o=new M({clock:e.clock,...e.onStateChange===void 0?{}:{onStateChange:e.onStateChange},request:()=>new Promise((i,d)=>{let l=e.clock.setTimeout(()=>{r=null,d({reason:"unavailable",retryable:true});},e.timeoutMs??en);r={resolve:c=>{e.clock.clearTimeout(l),i(c);},reject:d,timer:l};})}),a=n.onServerToken(i=>{let d=t(i),l=r;if(l){r=null,l.resolve(d);return}o.accept(d);});return {source:o,dispose(){a(),r&&(e.clock.clearTimeout(r.timer),r.reject({reason:"unavailable",retryable:false}),r=null);}}}var D={};xe(D,{acceptTransfer:()=>nn,addEntityProgression:()=>tn,adminAction:()=>rn,cancelInventoryTransfer:()=>on,claimEntityProgressionRewards:()=>an,closeGameRoom:()=>sn,createEntityBatchOrder:()=>ln,createEntityOrder:()=>dn,createSession:()=>un,deleteEntityGameSetting:()=>cn,deleteEntitySave:()=>mn,deleteSession:()=>gn,deleteShowcaseValue:()=>pn,executeEntityRecipe:()=>yn,finalizeSaveUpload:()=>fn,getChannelAssignment:()=>hn,getDropRates:()=>_n,getEntityCurrency:()=>bn,getEntityGameSetting:()=>vn,getEntityInventory:()=>Rn,getEntityInventoryItem:()=>xn,getEntityLeaderboard:()=>Sn,getEntityOrder:()=>kn,getEntityProgression:()=>wn,getEntityRecipeAvailability:()=>An,getEntityRecipeUsage:()=>Pn,getEntitySave:()=>Tn,getEvent:()=>On,getGameRoomV2:()=>Gn,getLeaderboard:()=>Cn,getPlayerGameProfile:()=>En,getPurchaseCatalog:()=>In,getResolvedTemplate:()=>qn,getRoomArgs:()=>Ln,getShowcaseValue:()=>Mn,getTransferDetails:()=>$n,ingestAnalyticsEvents:()=>N,initiateInventoryTransfer:()=>jn,invokeFunction:()=>Fn,kickPlayer:()=>Bn,listChallenges:()=>Un,listEntityGameSettings:()=>Nn,listEntityOrders:()=>Dn,listEntityProgressions:()=>Hn,listEntitySaves:()=>Vn,listEvents:()=>Wn,listGameRooms:()=>zn,listResolvedTemplates:()=>Kn,listTransfers:()=>Yn,maxEntityProgression:()=>Jn,putEntityGameSetting:()=>Xn,putRoomArgs:()=>Qn,putShowcaseValue:()=>Zn,rejectTransfer:()=>et,reportMatchPlayers:()=>nt,requestSaveUploadUrl:()=>tt,resetEntityProgression:()=>rt,setMatchBackfill:()=>ot,simulateEntityOrder:()=>at,transferHostV2:()=>st,updateGameRoomV2:()=>it});function s(n){let e=String(n);if(!/^[A-Za-z0-9_.-]{1,128}$/.test(e)||e==="."||e==="..")throw new TypeError(`${JSON.stringify(e)} is not a usable path segment \u2014 it is interpolated into a URL`);return encodeURIComponent(e)}async function nn(n,e,t){let r=`/v1/inventory/transfers/${s(e)}/accept`;return n.client.post(r,void 0,t?.signal)}async function tn(n,e,t,r,o,a){let i=`/v1/inventory/${s(e)}/${s(t)}/progressions/${s(r)}/add`;return n.client.post(i,o,a?.signal)}async function rn(n,e,t,r){let o=`/v1/voice/sessions/${s(e)}/admin`;return n.client.post(o,t,r?.signal)}async function on(n,e,t){let r=`/v1/inventory/transfers/${s(e)}/cancel`;return n.client.post(r,void 0,t?.signal)}async function an(n,e,t,r,o,a){let i=`/v1/inventory/${s(e)}/${s(t)}/progressions/${s(r)}/claim`;return n.client.post(i,o,a?.signal)}async function sn(n,e,t){let r=`/v1/games/${s(n.gameId())}/game-rooms/${s(e)}`;return n.client.delete(r,t?.signal)}async function ln(n,e,t,r,o){let a=`/v1/inventory/${s(e)}/${s(t)}/orders/batch`;return n.client.post(a,r,o?.signal,{...o?.ifMatch===void 0?{}:{ifMatch:o.ifMatch}})}async function dn(n,e,t,r,o){let a=`/v1/inventory/${s(e)}/${s(t)}/orders`;return n.client.post(a,r,o?.signal,{...o?.ifMatch===void 0?{}:{ifMatch:o.ifMatch}})}async function un(n,e,t){return n.client.post("/v1/voice/sessions",e,t?.signal)}async function cn(n,e,t,r,o){let a=`/v1/settings/${s(e)}/${s(t)}/${s(r)}`;return n.client.delete(a,o?.signal)}async function mn(n,e,t,r,o){let a=`/v1/saves/${s(e)}/${s(t)}/${s(r)}`;return n.client.delete(a,o?.signal)}async function gn(n,e,t){let r=`/v1/voice/sessions/${s(e)}`;return n.client.delete(r,t?.signal)}async function pn(n,e,t,r){let o=`/v1/showcase/players/${s(e)}/${s(t)}`;return n.client.delete(o,r?.signal)}async function yn(n,e,t,r,o){let a=`/v1/inventory/${s(e)}/${s(t)}/recipes/execute`;return n.client.post(a,r,o?.signal,{...o?.ifMatch===void 0?{}:{ifMatch:o.ifMatch}})}async function fn(n,e,t,r,o,a){let i=`/v1/saves/${s(e)}/${s(t)}/${s(r)}/finalize`;return n.client.post(i,o,a?.signal)}async function hn(n,e,t){let r=`/v1/games/${s(n.gameId())}/config/channels/${s(e)}`;return n.client.getWithEtag(r,{...t?.signal===void 0?{}:{signal:t.signal},...t?.ifNoneMatch===void 0?{}:{ifNoneMatch:t.ifNoneMatch}})}async function _n(n,e,t){let r=`/v1/inventory/loot-tables/${s(e)}/drop-rates`;return n.client.get(r,t?.signal)}async function bn(n,e,t,r,o){let a=`/v1/inventory/${s(e)}/${s(t)}/currencies/${s(r)}`;return n.client.get(a,o?.signal)}async function vn(n,e,t,r,o){let a=`/v1/settings/${s(e)}/${s(t)}/${s(r)}`;return n.client.getWithEtag(a,{...o?.signal===void 0?{}:{signal:o.signal},...o?.ifNoneMatch===void 0?{}:{ifNoneMatch:o.ifNoneMatch}})}async function Rn(n,e,t,r){let o=new URLSearchParams;r?.include_buckets!==void 0&&o.set("include_buckets",String(r?.include_buckets)),r?.include_custom_data!==void 0&&o.set("include_custom_data",String(r?.include_custom_data)),r?.currency_limit!==void 0&&o.set("currency_limit",String(r?.currency_limit)),r?.currency_cursor!==void 0&&o.set("currency_cursor",String(r?.currency_cursor)),r?.item_limit!==void 0&&o.set("item_limit",String(r?.item_limit)),r?.item_cursor!==void 0&&o.set("item_cursor",String(r?.item_cursor)),r?.progression_limit!==void 0&&o.set("progression_limit",String(r?.progression_limit)),r?.progression_cursor!==void 0&&o.set("progression_cursor",String(r?.progression_cursor));let a=o.toString(),i=`/v1/inventory/${s(e)}/${s(t)}`+(a?`?${a}`:"");return n.client.get(i,r?.signal)}async function xn(n,e,t,r,o){let a=`/v1/inventory/${s(e)}/${s(t)}/items/${s(r)}`;return n.client.get(a,o?.signal)}async function Sn(n,e,t,r,o){let a=new URLSearchParams;o?.bucket_1!==void 0&&a.set("bucket_1",String(o?.bucket_1)),o?.bucket_2!==void 0&&a.set("bucket_2",String(o?.bucket_2)),o?.limit!==void 0&&a.set("limit",String(o?.limit)),o?.periods_back!==void 0&&a.set("periods_back",String(o?.periods_back)),o?.period!==void 0&&a.set("period",String(o?.period)),o?.player_id!==void 0&&a.set("player_id",String(o?.player_id));let i=a.toString(),d=`/v1/leaderboards/${s(e)}/${s(t)}/${s(r)}`+(i?`?${i}`:"");return n.client.get(d,o?.signal)}async function kn(n,e,t,r,o){let a=`/v1/inventory/${s(e)}/${s(t)}/orders/${s(r)}`;return n.client.get(a,o?.signal)}async function wn(n,e,t,r,o){let a=`/v1/inventory/${s(e)}/${s(t)}/progressions/${s(r)}`;return n.client.get(a,o?.signal)}async function An(n,e,t,r,o,a){let i=`/v1/inventory/${s(e)}/${s(t)}/catalogs/${s(r)}/recipes/${s(o)}/availability`;return n.client.get(i,a?.signal)}async function Pn(n,e,t,r){let o=new URLSearchParams;r?.limit!==void 0&&o.set("limit",String(r?.limit));let a=o.toString(),i=`/v1/inventory/${s(e)}/${s(t)}/recipe-usage`+(a?`?${a}`:"");return n.client.get(i,r?.signal)}async function Tn(n,e,t,r,o){let a=`/v1/saves/${s(e)}/${s(t)}/${s(r)}`;return n.client.getWithEtag(a,{...o?.signal===void 0?{}:{signal:o.signal},...o?.ifNoneMatch===void 0?{}:{ifNoneMatch:o.ifNoneMatch}})}async function On(n,e,t){let r=`/v1/events/${s(e)}`;return n.client.get(r,t?.signal)}async function Gn(n,e,t){let r=`/v2/games/${s(n.gameId())}/game-rooms/${s(e)}`;return n.client.getWithEtag(r,{...t?.signal===void 0?{}:{signal:t.signal},...t?.ifNoneMatch===void 0?{}:{ifNoneMatch:t.ifNoneMatch}})}async function Cn(n,e,t){let r=new URLSearchParams;t?.bucket_1!==void 0&&r.set("bucket_1",String(t?.bucket_1)),t?.bucket_2!==void 0&&r.set("bucket_2",String(t?.bucket_2)),t?.periods_back!==void 0&&r.set("periods_back",String(t?.periods_back)),t?.period!==void 0&&r.set("period",String(t?.period)),t?.player_id!==void 0&&r.set("player_id",String(t?.player_id));let o=r.toString(),a=`/v1/leaderboards/${s(e)}`+(o?`?${o}`:"");return n.client.get(a,t?.signal)}async function En(n,e,t){let r=`/v1/profiles/players/${s(e)}`;return n.client.get(r,t?.signal)}async function In(n,e){let t=new URLSearchParams;e?.config_version!==void 0&&t.set("config_version",String(e?.config_version));let r=t.toString(),o="/v1/inventory/platform-funded-game-inventory-purchase-catalog"+(r?`?${r}`:"");return n.client.get(o,e?.signal)}async function qn(n,e,t){let r=`/v1/game-room-templates/${s(e)}`;return n.client.get(r,t?.signal)}async function Ln(n,e,t){let r=`/v1/games/${s(n.gameId())}/game-rooms/${s(e)}/room-args`;return n.client.get(r,t?.signal)}async function Mn(n,e,t,r){let o=`/v1/showcase/players/${s(e)}/${s(t)}`;return n.client.get(o,r?.signal)}async function $n(n,e,t){let r=`/v1/inventory/transfers/${s(e)}`;return n.client.get(r,t?.signal)}async function N(n,e,t){let r=`/v1/games/${s(n.gameId())}/analytics/events`;return n.client.post(r,e,t?.signal,{replaySafe:true})}async function jn(n,e,t){return n.client.post("/v1/inventory/transfers",e,t?.signal)}async function Fn(n,e,t){return n.client.postBytes("/v1/functions/invoke",e,t?.signal)}async function Bn(n,e,t,r){let o=`/v1/games/${s(n.gameId())}/game-rooms/${s(e)}/kick/${s(t)}`;return n.client.post(o,void 0,r?.signal)}async function Un(n,e){let t=new URLSearchParams;e?.periods_back!==void 0&&t.set("periods_back",String(e?.periods_back)),e?.player_id!==void 0&&t.set("player_id",String(e?.player_id));let r=t.toString(),o="/v1/challenges"+(r?`?${r}`:"");return n.client.get(o,e?.signal)}async function Nn(n,e,t,r){let o=`/v1/settings/${s(e)}/${s(t)}`;return n.client.get(o,r?.signal)}async function Dn(n,e,t,r){let o=new URLSearchParams;r?.limit!==void 0&&o.set("limit",String(r?.limit)),r?.cursor!==void 0&&o.set("cursor",String(r?.cursor));let a=o.toString(),i=`/v1/inventory/${s(e)}/${s(t)}/orders`+(a?`?${a}`:"");return n.client.get(i,r?.signal)}async function Hn(n,e,t,r){let o=`/v1/inventory/${s(e)}/${s(t)}/progressions`;return n.client.get(o,r?.signal)}async function Vn(n,e,t,r){let o=new URLSearchParams;r?.limit!==void 0&&o.set("limit",String(r?.limit)),r?.cursor!==void 0&&o.set("cursor",String(r?.cursor));let a=o.toString(),i=`/v1/saves/${s(e)}/${s(t)}`+(a?`?${a}`:"");return n.client.get(i,r?.signal)}async function Wn(n,e){let t=new URLSearchParams;e?.include_inactive!==void 0&&t.set("include_inactive",String(e?.include_inactive)),e?.limit!==void 0&&t.set("limit",String(e?.limit)),e?.offset!==void 0&&t.set("offset",String(e?.offset));let r=t.toString(),o="/v1/events"+(r?`?${r}`:"");return n.client.get(o,e?.signal)}async function zn(n,e){let t=new URLSearchParams;e?.status!==void 0&&t.set("status",String(e?.status)),e?.game_channel!==void 0&&t.set("game_channel",String(e?.game_channel)),e?.game_room_type!==void 0&&t.set("game_room_type",String(e?.game_room_type)),e?.template_id!==void 0&&t.set("template_id",String(e?.template_id)),e?.template_slug!==void 0&&t.set("template_slug",String(e?.template_slug)),e?.limit!==void 0&&t.set("limit",String(e?.limit)),e?.cursor!==void 0&&t.set("cursor",String(e?.cursor));let r=t.toString(),o=`/v1/games/${s(n.gameId())}/game-rooms`+(r?`?${r}`:"");return n.client.get(o,e?.signal)}async function Kn(n,e){return n.client.get("/v1/game-room-templates",e?.signal)}async function Yn(n,e){let t=new URLSearchParams;e.entity_type!==void 0&&t.set("entity_type",String(e.entity_type)),e.entity_id!==void 0&&t.set("entity_id",String(e.entity_id)),e?.direction!==void 0&&t.set("direction",String(e?.direction)),e?.status!==void 0&&t.set("status",String(e?.status)),e?.cursor!==void 0&&t.set("cursor",String(e?.cursor)),e?.limit!==void 0&&t.set("limit",String(e?.limit));let r=t.toString(),o="/v1/inventory/transfers"+(r?`?${r}`:"");return n.client.get(o,e?.signal)}async function Jn(n,e,t,r,o,a){let i=`/v1/inventory/${s(e)}/${s(t)}/progressions/${s(r)}/max`;return n.client.post(i,o,a?.signal)}async function Xn(n,e,t,r,o,a){let i=`/v1/settings/${s(e)}/${s(t)}/${s(r)}`;return n.client.put(i,o,a?.signal,{...a?.ifMatch===void 0?{}:{ifMatch:a.ifMatch}})}async function Qn(n,e,t,r){let o=`/v1/games/${s(n.gameId())}/game-rooms/${s(e)}/room-args`;return n.client.put(o,t,r?.signal)}async function Zn(n,e,t,r,o){let a=`/v1/showcase/players/${s(e)}/${s(t)}`;return n.client.put(a,r,o?.signal)}async function et(n,e,t){let r=`/v1/inventory/transfers/${s(e)}/reject`;return n.client.post(r,void 0,t?.signal)}async function nt(n,e,t,r){let o=`/v1/games/${s(n.gameId())}/matches/${s(e)}/players/report`;return n.client.post(o,t,r?.signal)}async function tt(n,e,t,r,o,a){let i=`/v1/saves/${s(e)}/${s(t)}/${s(r)}/upload-url`;return n.client.post(i,o,a?.signal,{replaySafe:true})}async function rt(n,e,t,r,o,a){let i=`/v1/inventory/${s(e)}/${s(t)}/progressions/${s(r)}/reset`;return n.client.post(i,o,a?.signal)}async function ot(n,e,t,r){let o=`/v1/games/${s(n.gameId())}/matches/${s(e)}/backfill`;return n.client.put(o,t,r?.signal)}async function at(n,e,t,r,o){let a=`/v1/inventory/${s(e)}/${s(t)}/orders/simulate`;return n.client.post(a,r,o?.signal)}async function st(n,e,t,r){let o=`/v2/games/${s(n.gameId())}/game-rooms/${s(e)}/transfer/${s(t)}`;return n.client.post(o,void 0,r?.signal)}async function it(n,e,t,r){let o=`/v2/games/${s(n.gameId())}/game-rooms/${s(e)}`;return n.client.patch(o,t,r?.signal,{...r?.ifMatch===void 0?{}:{ifMatch:r.ifMatch}})}var ae="gem_";var ut=1e4,ct=50,mt=1e3,gt=65536-4*1024,se=n=>typeof n=="number"?n:0,pt=n=>typeof n=="string"?n:"";function ie(){let n=globalThis.crypto;return typeof n?.randomUUID=="function"?n.randomUUID():"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,e=>{let t=Math.floor(Math.random()*16);return (e==="x"?t:t&3|8).toString(16)})}function yt(n){return n?.retryable===true}function ft(n,e){let t=n??{},r=Array.isArray(t.rejected)?t.rejected.map(o=>{let a=o??{};return {index:se(a.index),code:pt(a.code)}}):[];return {accepted:se(t.accepted),rejected:r,dropped:e,duplicate:t.duplicate===true}}function le(n,e){return {event_uid:n.uid,name:n.name,offset_ms:Math.round(n.atMs)-e,player_id:n.playerId,dimensions:n.dimensions,measures:n.measures}}function de(n){let e=Math.max(1,Math.floor(n.maxQueue??mt)),t={client:n.client,gameId:()=>n.gameId},r=[],o=0,a=null,i=false,d=false,l=false,c=false,p=m=>{n.log?.(m);},b=()=>{a!==null&&(n.clock.clearTimeout(a),a=null);},S=()=>{a!==null||i||d||(a=n.clock.setTimeout(()=>{a=null,y().catch(()=>{});},ut));},_=()=>{let m=Math.min(r.length,100),f=128;for(let v=0;v<m;v+=1){let A=r[v];if(A===void 0)break;if(f+=JSON.stringify(le(A,0)).length+1,f>gt)return Math.max(1,v)}return m};async function y(m){if(r.length===0)return {accepted:0,rejected:[],dropped:0,duplicate:false};b();let f=r.splice(0,_()),v=o;o=0;let A=Math.round(n.clock.now()),L={batch_id:ie(),sent_at_ms:A,events:f.map(k=>le(k,A))};d=true;try{let k=await N(t,L,m===void 0?void 0:{signal:m}),P=ft(k,v);for(let ve of P.rejected)p(`[gem] analytics: an event was refused (${ve.code}). See the analytics_events section of your game config.`);return P}catch(k){if(yt(k))for(r=[...f,...r],o+=v;r.length>e;)r.shift(),o+=1;else p(`[gem] analytics: ${f.length} event(s) were discarded \u2014 the platform refused the batch and will refuse it again: ${String(k)}`);throw k}finally{d=false,r.length>0&&S();}}return {track(m,f,v={}){if(i)return;if(typeof m!="string"||m===""){c||(c=true,p(`[gem] analytics: '${f}' was not recorded \u2014 an event from a server has to name the player it is about. A game-server token names no player, so the platform cannot infer one; pass the id from join() or host.players().`));return}if(f.startsWith(ae)){l||(l=true,p(`[gem] analytics: '${f}' was not recorded \u2014 the gem_ prefix is reserved, and the platform's own events are client-sourced, so a server may not emit one at all. Name your event something else.`));return}let A={},L={};for(let[k,P]of Object.entries(v))typeof P=="string"?A[k]=P:typeof P=="number"&&Number.isFinite(P)&&(L[k]=P);for(;r.length>=e;)r.shift(),o+=1;r.push({uid:ie(),playerId:m,name:f,atMs:n.clock.now(),dimensions:A,measures:L}),r.length>=ct?y().catch(()=>{}):S();},flush:m=>y(m),get pending(){return r.length},dispose(){i=true,b(),r=[],o=0;}}}var ht=new Map([["function_error",false],["function_failed",false],["function_timeout",false],["function_not_published",false],["function_input_too_large",false],["functions_not_configured",false],["forbidden",false],["function_capacity_unavailable",true],["function_host_unreachable",true],["function_host_error",true],["rate_limited",true],["service_unavailable",true]]),I=class extends g{constructor(e,t){super(e.reason,e.status,e.detail,e.retryAfterSeconds,e.code),this.name="GemFunctionError",Object.assign(this,t);}get retryable(){return (this.code===void 0?void 0:ht.get(this.code))??super.retryable}},C=class{#e;constructor(e){this.#e=e;}async invoke(e,t={}){let r=_t(e),o;try{o=await this.#e(r,t.signal===void 0?{}:{signal:t.signal});}catch(a){throw a instanceof g?vt(a):a}return bt(o)}};function _t(n){if(n instanceof ArrayBuffer)return new Uint8Array(n);if(ArrayBuffer.isView(n))return new Uint8Array(n.buffer,n.byteOffset,n.byteLength);let e;try{e=JSON.stringify(n);}catch(t){throw new h(`the function input could not be serialised to JSON: ${String(t)}. Pass bytes, or a value JSON can carry. This is a bug in the call, not a server failure.`)}if(e===void 0)throw new h(`the function input is ${typeof n}, which JSON cannot carry. Pass bytes \u2014 an empty Uint8Array for no input \u2014 or a JSON value. This is a bug in the call, not a server failure.`);return new TextEncoder().encode(e)}function bt(n){let{bytes:e}=n,t=()=>new TextDecoder("utf-8",{fatal:true}).decode(e);return {bytes:e,...n.invocationId===void 0?{}:{invocationId:n.invocationId},text:t,json:()=>JSON.parse(t())}}function vt(n){let{details:e,invocationId:t}=J(n),o=e?.untrusted?.message,a=e?.reason;return new I(n,{...t===void 0?{}:{invocationId:t},...n.code==="function_error"&&typeof o=="string"?{functionMessage:o}:{},...n.code==="function_failed"&&typeof a=="string"?{failure:a}:{}})}var w=n=>typeof n=="string"?n:"",Rt=/(?:Z|[+-]\d{2}:?\d{2})$/i;function ue(n){let e=w(n);if(!Rt.test(e))return 0;let t=Date.parse(e);return Number.isFinite(t)?Math.floor(t/1e3):0}var xt=/^[0-9a-f]{1,64}$/,St=/^[0-9a-f]{16}$/,kt=/^[A-Za-z][A-Za-z0-9_+\-/]{0,63}$/,wt=/^(?:[01]\d|2[0-3]):[0-5]\d$/;function At(n){let e=w(n),t=/^(\d{4})-(\d{2})-(\d{2})$/.exec(e);if(!t)return;let[r,o,a]=[Number(t[1]),Number(t[2]),Number(t[3])],i=new Date(Date.UTC(r,o-1,a));return i.getUTCFullYear()===r&&i.getUTCMonth()===o-1&&i.getUTCDate()===a?e:void 0}var Pt=4096,Tt=new TextEncoder;function Ot(n){let e=w(n.challenge_data),t=w(n.challenge_data_hash);return e===""||!St.test(t)?{}:Tt.encode(e).length>Pt?{}:{data:e,dataHash:t}}function Gt(n){let e=n??{},t=ue(e.period_start_at),r=ue(e.period_ends_at);if(t===0||r===0)return;let o=w(e.slug),a=w(e.seed),i=At(e.period_local_date),d=w(e.boundary),l=w(e.reset_time);return {id:w(e.progression_definition_id),...o===""?{}:{slug:o},window:w(e.window),periodStartAt:t,periodEndsAt:r,...i===void 0?{}:{periodLocalDate:i},boundary:kt.test(d)?d:"",resetTime:wt.test(l)?l:"",seed:xt.test(a)?a:"",...Ot(e)}}function ce(n){if(n!==void 0&&(!Number.isInteger(n)||n<0||n>400))throw new TypeError(`periodsBack must be an integer between 0 and 400, got ${String(n)}`)}function me(n){let e=n??{};return Array.isArray(e.challenges)?e.challenges.map(Gt).filter(t=>t!==void 0):[]}function ge(n){return {async list(e){let{playerId:t,periodsBack:r,signal:o}=e??{};if(typeof t!="string"||t==="")throw new TypeError("gem.challenges.list needs { playerId }: a game-server token names no player, so the platform cannot tell whose period you mean. Pass the id from join() or gem.players().");ce(r);let a=await n({player_id:t,...r===void 0?{}:{periods_back:r},...o===void 0?{}:{signal:o}});return me(a)}}}function Ct(n){let e={};for(let[t,r]of Object.entries(D))if(typeof r=="function"){let o=r;e[t]=(...a)=>o(n,...a);}return e}function F(n,e={}){let t=e.clock??G,r=e.baseUrl??n.apiBaseUrl;if(!r)throw new Error("this runtime names no gem-api host (host.apiBaseUrl is missing). The server image running this bundle predates token delivery \u2014 the bundle cannot call gem-api on it.");let o=U(n,{clock:t,...e.onAuthStateChange===void 0?{}:{onStateChange:e.onAuthStateChange}}),a=X({baseUrl:r,tokenSource:o.source,defaultQuery:{game_id:n.gameId,channel:n.channel},...e.fetch===void 0?{}:{fetch:e.fetch}}),i=new T({transport:a,clock:t}),d={gameId:n.gameId,channel:n.channel,matchId:n.matchId,...n.gameRoomId===void 0?{}:{gameRoomId:n.gameRoomId}},l=Ct({client:i,gameId:()=>d.gameId}),c=d.gameRoomId,p=n.endMatch,b=n.log,S=de({client:i,clock:t,gameId:d.gameId,...typeof b=="function"?{log:y=>b.call(n,y)}:{}});return {identity:d,client:i,api:l,match:{end:async()=>{if(p===void 0)throw new Error("this runtime cannot end the match: the server image running this bundle predates host.endMatch, and only the platform half holds the allocation proof an end needs.");await p.call(n);},setBackfill:async(y,m)=>{let f=await l.setMatchBackfill(d.matchId,{open:y.open,...y.seats===void 0?{}:{seats:y.seats}},m===void 0?{}:{signal:m});return {open:f.open,seats:f.seats??null}},reportPlayers:async(y,m)=>(await l.reportMatchPlayers(d.matchId,{players:y.map(v=>({player_id:v.playerId,state:v.state}))},m===void 0?{}:{signal:m})).players.map(v=>({playerId:v.player_id,outcome:v.outcome}))},analytics:S,functions:new C(l.invokeFunction),challenges:ge(l.listChallenges),...c===void 0?{}:{room:{get:y=>l.getGameRoomV2(c,y),args:async y=>{let m=await l.getGameRoomV2(c,y?.signal===void 0?{}:{signal:y.signal}),f=m.modified?m.body:void 0;if(f?.room_args==null||f.room_args_template==null)throw new g("not_found",404,"this room's template declares no room args",void 0,"room_args_not_defined");return {room_args:f.room_args,room_args_template:f.room_args_template}}}},dispose:()=>{S.dispose(),o.dispose();}}}var Et=["explicit","stale_cleanup","game_room_closed","replaced","migration_failed","host_left","insufficient_players","all_left","expired","migration_rate_exceeded","game_room_gone","failed","idle","reclaimed"],It=new Set(Et);function pe(n){return typeof n=="string"&&It.has(n)?n:"unknown"}var x=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 q(n){return new x(n)}var ye={toPlain(n){return x.unwrap(n)},compare(n,e,t){let r=n instanceof x?x.unwrap(n):n,o=e instanceof x?x.unwrap(e):e,a;try{a=new Intl.Collator(t);}catch{a=new Intl.Collator;}return a.compare(r,o)},equals(n,e){let t=n instanceof x?x.unwrap(n):n,r=e instanceof x?x.unwrap(e):e;return t.normalize("NFC")===r.normalize("NFC")}};var fe="the match has not started yet: the runtime hands over the host at `init`, and this was read before that. Read it from `init` or later \u2014 a bundle that needs a value at module scope is reading it one call too early.";function H(n,e={}){let t=e.clock??G,r=()=>{let d=n();if(d===null)throw new Error(fe);return d},o=null,a=()=>{if(o===null)throw new Error(fe);return o};return {server:{get identity(){return a().identity},get client(){return a().client},get api(){return a().api},get match(){return a().match},get analytics(){return a().analytics},get functions(){return a().functions},get challenges(){return a().challenges},get room(){return a().room},dispose(){o?.dispose();},get sizeClass(){return r().sizeClass},get roomArgs(){return r().roomArgs},get roster(){return r().roster},players(){return r().players()},profile(d){let c=r().profile?.(d);if(!c)return null;let p=c.displayName;return typeof p!="string"||p===""?null:{displayName:q(p),...typeof c.displayTag=="string"&&c.displayTag!==""?{displayTag:q(c.displayTag)}:{},...typeof c.discriminator=="string"?{discriminator:c.discriminator}:{}}},playerNumber(d){return r().playerNumber?.(d)},send(d,l,c){c===void 0?r().send(d,l):r().send(d,l,c);},broadcast(d,l){l===void 0?r().broadcast(d):r().broadcast(d,l);},kick(d,l){l===void 0?r().kick(d):r().kick(d,l);},log(d){r().log(d);},warn(d){r().warn(d);}},attach:()=>{o=F(r(),{...e,clock:t});}}}function he(n,e={}){let{server:t,attach:r}=H(()=>n,e);return r(),t}function qt(n){if(n===void 0||typeof n.reason!="string"||n.reason==="")return;let e=n.platform_reason??n.endedReason;return {reason:n.reason,...e===void 0?{}:{endedReason:pe(e)}}}var Lt=1e4;function Mt(n){let e=false;return t=>{if(e)return;let r;try{r=n.match.reportPlayers([{playerId:t,state:"connected"}],AbortSignal.timeout(Lt));}catch{return}r.catch(o=>{o instanceof g&&o.status>=400&&o.status<500&&(e=o.status!==429);});}}function _e(n,e={}){return ()=>{let t=null,{server:r,attach:o}=H(()=>t,e),a=n(r),i={async init(l){t=l,o(),await a.init?.();},async shutdown(l){let c=qt(l);try{await a.shutdown?.(c);}finally{r.dispose();}}},d=Mt(r);return i.join=(l,c)=>(d(l),a.join?.(l,c)),a.leave&&(i.leave=(l,c)=>a.leave?.(l,c)),a.message&&(i.message=(l,c,p,b)=>a.message?.(l,c,p,b)),i}}var $t=new Set(["unlocked","already_unlocked","suppressed"]);function be(n){let e=n?.changes;if(!Array.isArray(e))return [];let t=[];for(let r of e){let o=r??{};if(o.type!=="achievement_unlocked"||typeof o.outcome!="string"||!$t.has(o.outcome)||typeof o.achievement_id!="string"||o.achievement_id==="")continue;let a=o.outcome;t.push({achievementId:o.achievement_id,progressionDefinitionId:typeof o.progression_definition_id=="string"?o.progression_definition_id:"",points:a==="unlocked"&&typeof o.points=="number"&&Number.isFinite(o.points)?o.points:0,outcome:a,...typeof o.reason=="string"?{reason:o.reason}:{}});}return t}
|
|
2
2
|
export{R as AuthError,$ as CONDITIONAL_HEADERS,C as FunctionsApi,g as GemApiError,T as GemClient,I as GemFunctionError,x as PlayerText,h as TransportRefusal,be as achievementReceipts,q as asPlayerText,F as createGemServer,oe as createHostTokenSource,he as createMatchServer,_e as defineServer,G as systemClock,ye as text,z as toBase64};//# sourceMappingURL=gem-web-sdk.server.js.map
|
|
3
3
|
//# sourceMappingURL=gem-web-sdk.server.js.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# The browser surface — API reference
|
|
2
2
|
|
|
3
|
-
Generated from `@indiegems/gem-web-sdk/sdk` v10.3.
|
|
3
|
+
Generated from `@indiegems/gem-web-sdk/sdk` v10.3.1, the version of the package this file ships in. Every symbol below carries an explicit anchor, its `anchor` in `reference.json` beside this file.
|
|
4
4
|
|
|
5
5
|
`@indiegems/gem-web-sdk/sdk` is the one import a game writes, wherever its code runs. `@indiegems/gem-web-sdk/game` exports exactly the symbols on this page and nothing else, for a build that wants only this half.
|
|
6
6
|
|
|
@@ -5193,7 +5193,8 @@ Whether the panel is on screen right now.
|
|
|
5193
5193
|
interface RewardCue
|
|
5194
5194
|
```
|
|
5195
5195
|
|
|
5196
|
-
A platform-currency reward on its way to the arcade
|
|
5196
|
+
A platform-currency reward on its way to the arcade — in the Gem Arcade, a
|
|
5197
|
+
flight into the Gem button at the top-left of your frame — what
|
|
5197
5198
|
`gem.cueReward` takes.
|
|
5198
5199
|
|
|
5199
5200
|
<a id="rewardcue-currencyslug"></a>
|
|
@@ -5205,8 +5206,8 @@ currencySlug: string
|
|
|
5205
5206
|
```
|
|
5206
5207
|
|
|
5207
5208
|
The platform currency's slug, as `gem.platform.currencies.get()` lists it —
|
|
5208
|
-
`GEMS` or `ARCADE_TICKETS`. It decides
|
|
5209
|
-
the payout
|
|
5209
|
+
`GEMS` or `ARCADE_TICKETS`. It decides what flies — gems or tickets — and
|
|
5210
|
+
which of the player's totals the payout moves.
|
|
5210
5211
|
|
|
5211
5212
|
<a id="rewardcue-expected"></a>
|
|
5212
5213
|
|
|
@@ -5231,8 +5232,8 @@ origin?: { x: number; y: number }
|
|
|
5231
5232
|
Where the flight starts, in CSS px of YOUR viewport: the centre of the
|
|
5232
5233
|
currency's icon (or hero) your screen draws beside the reward — the gem
|
|
5233
5234
|
for Gems, the ticket for Tickets. Measure that element's own box, not a
|
|
5234
|
-
row or panel around it. Leave it out and the
|
|
5235
|
-
|
|
5235
|
+
row or panel around it. Leave it out and the Gem Arcade flies the payout
|
|
5236
|
+
from the middle of your frame once the platform confirms it.
|
|
5236
5237
|
|
|
5237
5238
|
<a id="rewardcue-origin-x"></a>
|
|
5238
5239
|
|
|
@@ -5500,9 +5501,9 @@ while connected, and only to an arcade that mirrors a game's mute.
|
|
|
5500
5501
|
cueReward(cue: RewardCue): boolean
|
|
5501
5502
|
```
|
|
5502
5503
|
|
|
5503
|
-
Tell the arcade a platform-currency reward is on its way, so
|
|
5504
|
-
|
|
5505
|
-
|
|
5504
|
+
Tell the arcade a platform-currency reward is on its way, so it can show it
|
|
5505
|
+
landing — in the Gem Arcade, the currency flying from `origin` into the Gem
|
|
5506
|
+
button, the total moving once the platform confirms the grant.
|
|
5506
5507
|
|
|
5507
5508
|
Prefer `gem.cueReward`, which says what the arcade does with it. This one
|
|
5508
5509
|
sends only while connected, and only to an arcade that draws a wallet.
|
|
@@ -7998,10 +7999,11 @@ The unsafe margin on each edge of your frame.
|
|
|
7998
7999
|
readonly reserved: readonly GemReservedArea[]
|
|
7999
8000
|
```
|
|
8000
8001
|
|
|
8001
|
-
Rectangles of your frame the arcade's own controls cover —
|
|
8002
|
-
in the top-
|
|
8003
|
-
|
|
8004
|
-
|
|
8002
|
+
Rectangles of your frame the arcade's own controls cover — in the Gem
|
|
8003
|
+
Arcade, its Gem button in the top-left corner, and the frame-rate readout
|
|
8004
|
+
beside it while the player shows it; an embedder that draws wallets over
|
|
8005
|
+
your game adds theirs (see `setWalletVisible`). Keep essential UI and touch
|
|
8006
|
+
targets out of them. Empty when the arcade covers nothing.
|
|
8005
8007
|
|
|
8006
8008
|
A stylesheet reads the per-corner custom properties the SDK stamps from
|
|
8007
8009
|
these instead — `--gem-reserved-tl-height` and friends.
|
|
@@ -8080,8 +8082,8 @@ While shown, show ONLY these: platform currency slugs as
|
|
|
8080
8082
|
`gem.platform.currencies.get()` lists them (`GEMS`, `ARCADE_TICKETS`),
|
|
8081
8083
|
matched exactly, and the literal `'score'` for the achievement score. Only
|
|
8082
8084
|
for a screen about one currency, such as a ticket store; leave it out and
|
|
8083
|
-
every wallet shows, which is always safe. The Gem Arcade
|
|
8084
|
-
|
|
8085
|
+
every wallet shows, which is always safe. The Gem Arcade draws no wallet
|
|
8086
|
+
over a game, so it has nothing to narrow and ignores it.
|
|
8085
8087
|
|
|
8086
8088
|
<a id="gamemenuitem"></a>
|
|
8087
8089
|
|
|
@@ -9084,10 +9086,13 @@ is ignored by the arcade, which keeps the image it is showing.
|
|
|
9084
9086
|
cueReward(cue: RewardCue): boolean
|
|
9085
9087
|
```
|
|
9086
9088
|
|
|
9087
|
-
Tell the arcade a platform-currency reward is on its way, so
|
|
9088
|
-
|
|
9089
|
-
|
|
9090
|
-
|
|
9089
|
+
Tell the arcade a platform-currency reward is on its way, so it **shows it
|
|
9090
|
+
landing**: in the Gem Arcade the currency flies from `origin` into the Gem
|
|
9091
|
+
button at the top-left of your frame, which pops as each mark lands, and
|
|
9092
|
+
the player's total moves once the platform confirms the grant. The Gem
|
|
9093
|
+
Arcade draws no wallet over your game: the player sees their Gems and
|
|
9094
|
+
Tickets in the Gem menu. A payout you do not cue still flies, from the
|
|
9095
|
+
middle of your frame, so cue the ones the player earns on screen.
|
|
9091
9096
|
|
|
9092
9097
|
Call it the moment your game decides to award — when your server has moved
|
|
9093
9098
|
(or is about to move) the progression mapped onto a platform currency —
|
|
@@ -9135,28 +9140,23 @@ setWalletVisible(visible: boolean, options?: WalletVisibleOptions): boolean
|
|
|
9135
9140
|
Show or hide the player's wallets — Gems, Tickets, the achievement score —
|
|
9136
9141
|
that an embedder draws over your game.
|
|
9137
9142
|
|
|
9138
|
-
**
|
|
9139
|
-
|
|
9140
|
-
|
|
9141
|
-
|
|
9142
|
-
|
|
9143
|
-
|
|
9143
|
+
**The Gem Arcade draws no wallet over a game** (since 2026-10-11): the
|
|
9144
|
+
player sees their balances in the Gem menu, and payouts fly into the Gem
|
|
9145
|
+
button. So under the Gem Arcade this changes nothing on screen — it is
|
|
9146
|
+
accepted and harmless, and a game that already calls it keeps working.
|
|
9147
|
+
Call it for an embedder that does draw wallets over your game: hide them
|
|
9148
|
+
while you play, show them on your menus.
|
|
9144
9149
|
|
|
9145
9150
|
```js
|
|
9146
9151
|
level.onStart = () => gem.setWalletVisible(false);
|
|
9147
9152
|
menu.onOpen = () => gem.setWalletVisible(true);
|
|
9148
9153
|
```
|
|
9149
9154
|
|
|
9150
|
-
The Gem Arcade does NOT act on `only`: a shown wallet there is every
|
|
9151
|
-
wallet. Another embedder may honour it.
|
|
9152
|
-
|
|
9153
9155
|
**It is screen state, not a toggle.** Each call is the whole answer and
|
|
9154
|
-
replaces the last.
|
|
9155
|
-
|
|
9156
|
-
|
|
9157
|
-
|
|
9158
|
-
`gem.viewport.reserved`; hiding them gives that space back. A wallet the
|
|
9159
|
-
arcade pops up for a moment floats over your game and moves nothing.
|
|
9156
|
+
replaces the last. Where an embedder draws wallets, shown ones arrive as
|
|
9157
|
+
rectangles in `gem.viewport.reserved` and hiding them gives that space
|
|
9158
|
+
back; the Gem Arcade sends none for wallets. `only` narrows what shows,
|
|
9159
|
+
where an embedder honours it; the Gem Arcade does not.
|
|
9160
9160
|
|
|
9161
9161
|
**Never draw a platform balance yourself**, and never show a pending state
|
|
9162
9162
|
for one: the arcade takes every figure from the platform. If this returns
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# The server surface — API reference
|
|
2
2
|
|
|
3
|
-
Generated from `@indiegems/gem-web-sdk/sdk` v10.3.
|
|
3
|
+
Generated from `@indiegems/gem-web-sdk/sdk` v10.3.1, the version of the package this file ships in. Every symbol below carries an explicit anchor, its `anchor` in `reference.json` beside this file.
|
|
4
4
|
|
|
5
5
|
`@indiegems/gem-web-sdk/sdk` is the one import a game writes, wherever its code runs. `@indiegems/gem-web-sdk/server` exports exactly the symbols on this page and nothing else, for a build that wants only this half.
|
|
6
6
|
|
package/docs/api/reference.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"schema_version": 2,
|
|
3
3
|
"source": {
|
|
4
4
|
"repo": "IndieGems/gem-web-sdk",
|
|
5
|
-
"version": "10.3.
|
|
5
|
+
"version": "10.3.1"
|
|
6
6
|
},
|
|
7
7
|
"entries": [
|
|
8
8
|
{
|
|
@@ -6152,7 +6152,7 @@
|
|
|
6152
6152
|
"group": "platform",
|
|
6153
6153
|
"signature": "interface RewardCue",
|
|
6154
6154
|
"documented": true,
|
|
6155
|
-
"summary": "A platform-currency reward on its way to the arcade
|
|
6155
|
+
"summary": "A platform-currency reward on its way to the arcade — in the Gem Arcade, a\nflight into the Gem button at the top-left of your frame — what\n`gem.cueReward` takes.",
|
|
6156
6156
|
"deprecated": null,
|
|
6157
6157
|
"params": [],
|
|
6158
6158
|
"returns": null,
|
|
@@ -6168,7 +6168,7 @@
|
|
|
6168
6168
|
"group": "platform",
|
|
6169
6169
|
"signature": "currencySlug: string",
|
|
6170
6170
|
"documented": true,
|
|
6171
|
-
"summary": "The platform currency's slug, as `gem.platform.currencies.get()` lists it —\n`GEMS` or `ARCADE_TICKETS`. It decides
|
|
6171
|
+
"summary": "The platform currency's slug, as `gem.platform.currencies.get()` lists it —\n`GEMS` or `ARCADE_TICKETS`. It decides what flies — gems or tickets — and\nwhich of the player's totals the payout moves.",
|
|
6172
6172
|
"deprecated": null,
|
|
6173
6173
|
"params": [],
|
|
6174
6174
|
"returns": null,
|
|
@@ -6200,7 +6200,7 @@
|
|
|
6200
6200
|
"group": "platform",
|
|
6201
6201
|
"signature": "origin?: { x: number; y: number }",
|
|
6202
6202
|
"documented": true,
|
|
6203
|
-
"summary": "Where the flight starts, in CSS px of YOUR viewport: the centre of the\ncurrency's icon (or hero) your screen draws beside the reward — the gem\nfor Gems, the ticket for Tickets. Measure that element's own box, not a\nrow or panel around it. Leave it out and the
|
|
6203
|
+
"summary": "Where the flight starts, in CSS px of YOUR viewport: the centre of the\ncurrency's icon (or hero) your screen draws beside the reward — the gem\nfor Gems, the ticket for Tickets. Measure that element's own box, not a\nrow or panel around it. Leave it out and the Gem Arcade flies the payout\nfrom the middle of your frame once the platform confirms it.",
|
|
6204
6204
|
"deprecated": null,
|
|
6205
6205
|
"params": [],
|
|
6206
6206
|
"returns": null,
|
|
@@ -6484,7 +6484,7 @@
|
|
|
6484
6484
|
"group": "frame",
|
|
6485
6485
|
"signature": "cueReward(cue: RewardCue): boolean",
|
|
6486
6486
|
"documented": true,
|
|
6487
|
-
"summary": "Tell the arcade a platform-currency reward is on its way, so
|
|
6487
|
+
"summary": "Tell the arcade a platform-currency reward is on its way, so it can show it\nlanding — in the Gem Arcade, the currency flying from `origin` into the Gem\nbutton, the total moving once the platform confirms the grant.\n\nPrefer `gem.cueReward`, which says what the arcade does with it. This one\nsends only while connected, and only to an arcade that draws a wallet.",
|
|
6488
6488
|
"deprecated": null,
|
|
6489
6489
|
"params": [
|
|
6490
6490
|
{
|
|
@@ -9069,7 +9069,7 @@
|
|
|
9069
9069
|
"group": "player",
|
|
9070
9070
|
"signature": "readonly reserved: readonly GemReservedArea[]",
|
|
9071
9071
|
"documented": true,
|
|
9072
|
-
"summary": "Rectangles of your frame the arcade's own controls cover — its
|
|
9072
|
+
"summary": "Rectangles of your frame the arcade's own controls cover — in the Gem\nArcade, its Gem button in the top-left corner, and the frame-rate readout\nbeside it while the player shows it; an embedder that draws wallets over\nyour game adds theirs (see `setWalletVisible`). Keep essential UI and touch\ntargets out of them. Empty when the arcade covers nothing.\n\nA stylesheet reads the per-corner custom properties the SDK stamps from\nthese instead — `--gem-reserved-tl-height` and friends.",
|
|
9073
9073
|
"deprecated": null,
|
|
9074
9074
|
"params": [],
|
|
9075
9075
|
"returns": null,
|
|
@@ -9181,7 +9181,7 @@
|
|
|
9181
9181
|
"group": "platform",
|
|
9182
9182
|
"signature": "readonly only?: readonly string[]",
|
|
9183
9183
|
"documented": true,
|
|
9184
|
-
"summary": "While shown, show ONLY these: platform currency slugs as\n`gem.platform.currencies.get()` lists them (`GEMS`, `ARCADE_TICKETS`),\nmatched exactly, and the literal `'score'` for the achievement score. Only\nfor a screen about one currency, such as a ticket store; leave it out and\nevery wallet shows, which is always safe. The Gem Arcade
|
|
9184
|
+
"summary": "While shown, show ONLY these: platform currency slugs as\n`gem.platform.currencies.get()` lists them (`GEMS`, `ARCADE_TICKETS`),\nmatched exactly, and the literal `'score'` for the achievement score. Only\nfor a screen about one currency, such as a ticket store; leave it out and\nevery wallet shows, which is always safe. The Gem Arcade draws no wallet\nover a game, so it has nothing to narrow and ignores it.",
|
|
9185
9185
|
"deprecated": null,
|
|
9186
9186
|
"params": [],
|
|
9187
9187
|
"returns": null,
|
|
@@ -10057,7 +10057,7 @@
|
|
|
10057
10057
|
"group": "start",
|
|
10058
10058
|
"signature": "cueReward(cue: RewardCue): boolean",
|
|
10059
10059
|
"documented": true,
|
|
10060
|
-
"summary": "Tell the arcade a platform-currency reward is on its way, so
|
|
10060
|
+
"summary": "Tell the arcade a platform-currency reward is on its way, so it **shows it\nlanding**: in the Gem Arcade the currency flies from `origin` into the Gem\nbutton at the top-left of your frame, which pops as each mark lands, and\nthe player's total moves once the platform confirms the grant. The Gem\nArcade draws no wallet over your game: the player sees their Gems and\nTickets in the Gem menu. A payout you do not cue still flies, from the\nmiddle of your frame, so cue the ones the player earns on screen.\n\nCall it the moment your game decides to award — when your server has moved\n(or is about to move) the progression mapped onto a platform currency —\nand pass the centre of that currency's icon (or hero) on your screen, so\nthe flight starts from the mark the player is looking at:\n\n```js\nconst { x, y, width, height } = rewardGem.getBoundingClientRect(); // the gem's own box\ngem.cueReward({\n currencySlug: 'GEMS', // or 'ARCADE_TICKETS', from the ticket\n expected: 15,\n origin: { x: x + width / 2, y: y + height / 2 },\n});\n```\n\n**This is the platform-currency animation, and the only one.** The display\nof every platform currency — Gems and Tickets alike — belongs to the\narcade: a game draws no flight or celebration of its own for one and keeps\nno counter of one. **If this returns `false`, do nothing** — there is no\nfallback celebration.\n\n**The arcade never takes your word for the amount.** What lands, and the\nplayer's new total, come from the platform itself; `expected` is drawn as\nprovisional, and a cue the platform never confirms fades on its own — a\ngrant clamped to zero, say, or one the receipt reports `suppressed`. So\nthe cue can only ever make the wallet move for a reward that really\nlanded — which it does on every channel, dev and test included.",
|
|
10061
10061
|
"deprecated": null,
|
|
10062
10062
|
"params": [
|
|
10063
10063
|
{
|
|
@@ -10080,7 +10080,7 @@
|
|
|
10080
10080
|
"group": "start",
|
|
10081
10081
|
"signature": "setWalletVisible(visible: boolean, options?: WalletVisibleOptions): boolean",
|
|
10082
10082
|
"documented": true,
|
|
10083
|
-
"summary": "Show or hide the player's wallets — Gems, Tickets, the achievement score —\nthat an embedder draws over your game.\n\n**
|
|
10083
|
+
"summary": "Show or hide the player's wallets — Gems, Tickets, the achievement score —\nthat an embedder draws over your game.\n\n**The Gem Arcade draws no wallet over a game** (since 2026-10-11): the\nplayer sees their balances in the Gem menu, and payouts fly into the Gem\nbutton. So under the Gem Arcade this changes nothing on screen — it is\naccepted and harmless, and a game that already calls it keeps working.\nCall it for an embedder that does draw wallets over your game: hide them\nwhile you play, show them on your menus.\n\n```js\nlevel.onStart = () => gem.setWalletVisible(false);\nmenu.onOpen = () => gem.setWalletVisible(true);\n```\n\n**It is screen state, not a toggle.** Each call is the whole answer and\nreplaces the last. Where an embedder draws wallets, shown ones arrive as\nrectangles in `gem.viewport.reserved` and hiding them gives that space\nback; the Gem Arcade sends none for wallets. `only` narrows what shows,\nwhere an embedder honours it; the Gem Arcade does not.\n\n**Never draw a platform balance yourself**, and never show a pending state\nfor one: the arcade takes every figure from the platform. If this returns\n`false`, do nothing in its place.",
|
|
10084
10084
|
"deprecated": null,
|
|
10085
10085
|
"params": [
|
|
10086
10086
|
{
|
package/docs/brand-art.md
CHANGED
|
@@ -75,7 +75,7 @@ These are the Arcade's own icon renders — the files its wallet draws — with
|
|
|
75
75
|
for byte, apart from stripping the colour-space and resolution tags every browser already assumes. They are the gem
|
|
76
76
|
of the arcade's Gems flight — a 3D model rendered in Blender, a round cut with the icon's six facet
|
|
77
77
|
colours — at rest and without its motion blur, so the gem a player sees in your price is the gem
|
|
78
|
-
that flies into
|
|
78
|
+
that flies into the Gem button when they are paid. Each size has its own recipe, in CSS px, so it carries the same visual
|
|
79
79
|
weight on every screen:
|
|
80
80
|
|
|
81
81
|
| Size | Outline | Girdle line | Facet lines | Sparkle |
|
|
@@ -282,7 +282,8 @@ too, with the ticket in place of the gem. Amended 2026-09-30 for the earn allowa
|
|
|
282
282
|
decision of that date); the ruling's other rules are unchanged. In rules:
|
|
283
283
|
|
|
284
284
|
- **Keep no Gems counter.** Your game shows no Gems balance, running total or wallet of its own, on
|
|
285
|
-
any screen. The arcade's wallet is the only place Gems accrue, and the only place a total is shown
|
|
285
|
+
any screen. The arcade's wallet is the only place Gems accrue, and the only place a total is shown
|
|
286
|
+
— in the Gem Arcade, the Gem menu, which the player opens from the Gem button at the top-left.
|
|
286
287
|
- **Draw no Gems flight or celebration of your own.** No particles flying to a corner, no counting-up
|
|
287
288
|
number, no burst of gems. `gem.cueReward` is the animation, and the arcade draws it.
|
|
288
289
|
- **Show no Gems amount at all when you are not connected to the arcade.** Without the arcade there is
|
|
@@ -306,8 +307,9 @@ decision of that date); the ruling's other rules are unchanged. In rules:
|
|
|
306
307
|
with the canvas's `getBoundingClientRect()`.
|
|
307
308
|
|
|
308
309
|
A Tickets payout is cued the same way, from the ticket, with `currencySlug: 'ARCADE_TICKETS'`. The
|
|
309
|
-
|
|
310
|
-
|
|
310
|
+
slug decides what flies — gems or tickets — and which total the platform moves. In the Gem Arcade
|
|
311
|
+
every payout flies into the Gem button at the top-left of your frame; no wallet is drawn over
|
|
312
|
+
your game.
|
|
311
313
|
- **If `cueReward` returns `false`, do nothing.** There is no fallback celebration. `false` means the
|
|
312
314
|
arcade will not show the payout here — the bridge is not up, or the embedder has no wallet — and
|
|
313
315
|
your game does not replace it with one of its own. Your reward screen still says what was earned;
|
package/docs/changelog.md
CHANGED
|
@@ -16,6 +16,12 @@ 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.3.1
|
|
20
|
+
|
|
21
|
+
Upgrading from 10.3.0. Impact: none.
|
|
22
|
+
|
|
23
|
+
Nothing in this release asks anything of a game.
|
|
24
|
+
|
|
19
25
|
## 10.3.0
|
|
20
26
|
|
|
21
27
|
Upgrading from 10.2.0. Impact: required.
|