@indiegems/gem-web-sdk 7.5.0 → 7.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,3 +1,3 @@
1
- var ve=Object.defineProperty;var Re=(n,e)=>{for(var t in e)ve(n,t,{get:e[t],enumerable:true});};globalThis.__gemWebSdkVersion="[gem-web-sdk:sdkVersion:7.5.0]";function xe(n,e){return e!==void 0?!e:n==="chain_exhausted"}var $=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 _(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 _("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 _("internal","token arrived for a superseded generation");return this.grant=o,this.rejected=false,this.enter("ready"),o.token}).catch(o=>{let s=Se(o),a=o?.retryable;throw t===this.generation&&this.enter(xe(s,typeof a=="boolean"?a:void 0)?"lost":"degraded",s),o instanceof _?o:new _(s,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)}},_=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 Se(n){if(n instanceof _)return n.reason;let e=n?.reason;return typeof e=="string"&&["chain_exhausted","unavailable","timeout","internal"].includes(e)?e:"internal"}var p=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}},j=["if-match","if-none-match"],W=4096;function ke(n){if(!n)return;let e={};for(let[t,r]of Object.entries(n)){let o=t.toLowerCase();if(!j.includes(o)||r===void 0)continue;let s=typeof r=="string"?we(r):r;if(typeof s!="string"||s.length>W||!Ae(s))throw new p(`the ${o} header value cannot be sent \u2014 it is not a string, is longer than ${W} 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.`);s!==""&&(e[o]=s);}return Object.freeze(e)}function we(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 Ae(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 p("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 p("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 z(n,e){let t=e.replayUnauthorizedOnce??true;return {async request(r){let o={...r},s=ke(o.headers),a=Te(o),l=Object.freeze({...o,headers:s,...a===void 0?{}:{bytes:a}}),d=await e.tokenSource.get(),c=await n(l,d);if(c.status!==401||!t)return c;e.tokenSource.invalidate(d);let g=await e.tokenSource.get(),b=await n(l,g);if(b.status===401)throw e.tokenSource.close("unavailable"),new _("unavailable","the server refused a freshly minted token");return b}}}function K(n){let e=typeof n=="string"?new TextEncoder().encode(n):n;return btoa(Pe(e))}function Pe(n){let t="";for(let r=0;r<n.length;r+=32768)t+=String.fromCharCode(...n.subarray(r,r+32768));return t}var m=class extends Error{constructor(t,r,o,s,a){super(`${t} (${r}): ${o}`);this.reason=t;this.status=r;this.detail=o;this.retryAfterSeconds=s;this.code=a;this.name="GemApiError";}reason;status;detail;retryAfterSeconds;code;get retryable(){return this.reason==="unavailable"||this.reason==="rate_limited"}},J=new WeakMap;function X(n){return J.get(n)??{}}var Oe=new Set([408,429,500,502,503,504]),Ge=6e4;function Ee(n){if(n===void 0)return 2;if(!Number.isInteger(n)||n<0||n>10)throw new p(`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 P=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,...C(o)},o.replaySafe===true)}async post(e,t,r,o={}){return this.send({method:"POST",path:e,body:t,signal:r,...C(o)},o.replaySafe===true)}async postBytes(e,t,r,o={}){let s=await this.sendRaw({method:"POST",path:e,bytes:t,responseType:"bytes",signal:r,...C(o)},o.replaySafe===true);return {bytes:Ce(s.body),...s.invocationId===void 0?{}:{invocationId:s.invocationId}}}async patch(e,t,r,o={}){return this.send({method:"PATCH",path:e,body:t,signal:r,...C(o)},o.replaySafe===true)}async delete(e,t,r={}){return this.send({method:"DELETE",path:e,signal:t,...C(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 Y(e.signal);for(let s=0;s<r;s++){if(s>0&&await this.backoff(s,o,e.signal),e.signal?.aborted)throw Y(e.signal);let a;try{a=await this.options.transport.request(e);}catch(d){if(_.isAuthError(d)||p.isRefusal(d)||e.signal?.aborted||Ie(d))throw d;o=new m("unavailable",0,String(d));continue}if(a.status>=200&&a.status<300||a.status===304)return a;let l=qe(a);if(!Oe.has(a.status))throw l;o=l;}throw o??new m("unavailable",0,"no attempt was made")}backoff(e,t,r){if(r?.aborted)return Promise.resolve();let o=t?.retryAfterSeconds,s=o!==void 0?o*1e3:2**(e-1)*250,a=2**(e-1)*250,l=Math.min(Math.max(s,a),Ge);return new Promise(d=>{let c=this.options.clock,g=false,b=false,x,f=()=>{g||(g=true,b&&c.clearTimeout(x),r?.removeEventListener("abort",f),d());};r?.addEventListener("abort",f,{once:true}),x=c.setTimeout(f,l),b=true,g&&c.clearTimeout(x);})}};function Ce(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 C(n){return {...n.keepalive===void 0?{}:{keepalive:n.keepalive},...n.ifMatch===void 0?{}:{headers:{"if-match":n.ifMatch}}}}function Y(n){return n.reason!==void 0?n.reason:new DOMException("The operation was aborted.","AbortError")}function Ie(n){let e=n?.name;return e==="AbortError"||e==="TimeoutError"}function qe(n){let e=$e(n),t=Me(n.body),r={...t===void 0?{}:{details:t},...n.invocationId===void 0?{}:{invocationId:n.invocationId}};return Object.keys(r).length>0&&J.set(e,r),e}var Le=new Map([["insufficient_funds","insufficient_funds"]]);function $e(n){let{status:e,body:t}=n,r=je(t),o=n.retryAfterSeconds??Ue(t),s=Fe(t),a=s===void 0?void 0:Le.get(s);if(a!==void 0)return new m(a,e,r,void 0,s);switch(e){case 304:return new m("not_modified",e,r);case 400:case 422:return new m("invalid",e,r,void 0,s);case 403:return new m("forbidden",e,r,void 0,s);case 404:return new m("not_found",e,r,void 0,s);case 402:return new m("insufficient_funds",e,r,void 0,s);case 409:return new m("conflict",e,r,void 0,s);case 412:return new m("precondition_failed",e,r,void 0,s);case 413:return new m("too_large",e,r,void 0,s);case 429:return new m("rate_limited",e,r,o,s);default:return new m("unavailable",e,r,o,s)}}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 Me(n){let t=n?.error?.details;return t===null?void 0:t}function Fe(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 Be(n){let e=n.lastIndexOf("@");return (e===-1?n:`***@${n.slice(e+1)}`).slice(0,200)}var Ne=new Set(j);function De(n){if(!n)return {};let e={};for(let[t,r]of Object.entries(n))Ne.has(t.toLowerCase())&&(e[t.toLowerCase()]=r);return e}function Q(n){let e=n.fetch??globalThis.fetch.bind(globalThis);return z(async(t,r)=>{let o;try{o=new URL(n.baseUrl.replace(/\/+$/,""));}catch{throw new p("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 s;try{s=new URL(o.href.replace(/\/+$/,"")+t.path);}catch{throw new p(`${JSON.stringify(typeof t.path=="string"?Be(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(s.protocol!==o.protocol||s.host!==o.host)throw new p(`${JSON.stringify(s.pathname)} resolves to ${s.protocol}//${s.host}, not ${o.protocol}//${o.host}. A request path may not change the request's origin \u2014 it carries the play token.`);if(s.username!==""||s.password!==""){let f=o.username!==""||o.password!=="",v=s.username!==o.username||s.password!==o.password,y=f?v?"baseUrl (and possibly the request path)":"baseUrl":"request path";throw new p(`the ${y} puts credentials in the URL, which cannot be fetched (${t.method} ${s.pathname}). The value is withheld here rather than written to logs. This is a malformed request, not a server failure.`)}for(let[f,v]of Object.entries(n.defaultQuery??{}))s.searchParams.has(f)||s.searchParams.set(f,v);let a=t.bytes,l=t.bytes===void 0?void 0:"application/octet-stream";try{t.body!==void 0&&(a=JSON.stringify(t.body),l="application/json");}catch(f){throw new p(`the body of ${t.method} ${JSON.stringify(s.pathname)} could not be serialised to JSON: ${String(f)}. This is a bug in the request, not a server failure \u2014 retrying sends the same unserialisable value.`)}let d=await e(s.toString(),{method:t.method,headers:{authorization:`Bearer ${r}`,...l===void 0?{}:{"content-type":l},...De(t.headers)},body:a,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"&&d.status>=200&&d.status<300)c=new Uint8Array(await d.arrayBuffer());else {let f=await d.text();if(f.length>0)try{c=JSON.parse(f);}catch{c=f;}}let g=d.headers.get("etag"),b=He(d.headers.get("retry-after")),x=d.headers.get("x-gem-invocation-id");return {status:d.status,body:c,...g===null?{}:{etag:g},...b===void 0?{}:{retryAfterSeconds:b},...x===null||x===""?{}:{invocationId:x}}},n)}function He(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 Ve="gem-web-bridge";var O=65536,Z=8,M=5e3,ee=1024;function B(n){return Object.freeze(Object.assign(Object.create(null),n))}B({"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.requestShare":6,"gem.frameStats":120,"gem.error":60,"gem.requestPurchase":12,"gem.purchaseResult":30,"gem.deviceSettings.put":30,"gem.deviceSettings.result":30,"gem.requestAd":6,"gem.adResult":12,"gem.requestSignIn":6,"gem.signInResult":12,"gem.requestFriendChallenge":12,"gem.friendChallengeResult":30,__malformed:60});B({"gem.requestAd":"ads","gem.adResult":"ads","gem.requestSignIn":"signIn","gem.signInResult":"signIn","gem.requestPurchase":"purchases","gem.purchaseResult":"purchases","gem.requestFriendChallenge":"friendChallenges","gem.friendChallengeResult":"friendChallenges","gem.devtools":"devtools","gem.screenshot":"screenshot","gem.screenshot.denied":"screenshot","gem.requestContext":"feedbackContext","gem.gameContext":"feedbackContext","gem.roomEvent":"rooms","gem.signal":"p2p","gem.signalEvent":"p2p","gem.dedicatedOffer":"dedicated","gem.dedicatedEvent":"dedicated","gem.clusterTarget":"clusterTarget","gem.partyRequest":"parties","gem.partyResult":"parties","gem.autoStartFailedEvent":"autoStartFailure","gem.seatedEvent":"partySeating","gem.socketState":"socketState","gem.audioState":"audioState","gem.rewardCue":"rewardCue","gem.frameStats":"frameStats","gem.engaged":"engagement","gem.viewport":"viewport","gem.walletDisplay":"walletDisplay","gem.requestLocalServer":"localHost","gem.localServer":"localHost","gem.localServer.denied":"localHost","gem.cohorts":"cohorts","gem.earnAllowanceChanged":"earnAllowance","gem.deviceSettings":"deviceSettings","gem.deviceSettings.put":"deviceSettings","gem.deviceSettings.result":"deviceSettings","gem.requestShare":"share"});function ze(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 Ke(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 Ye(n){return /^[a-z]{2,8}(-[a-z0-9]{1,8})*$/i.test(n)}function Je(n){return /^[a-z_]+$/.test(n)}function U(n,e,t){if(e>Z)return `nesting deeper than ${Z}`;if(++t.nodes>M)return `more than ${M} 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>ee)return `an array of ${n.length} entries, over the ${ee} limit`;t.bytes+=2;for(let l of n){let d=U(l,e+1,t);if(d)return d}return null}let s=Object.getPrototypeOf(n);if(s!==Object.prototype&&s!==null)return "a value that is not a plain object";t.bytes+=2;let a=n;for(let l in a){if(!Object.prototype.hasOwnProperty.call(a,l))continue;if(++t.nodes>M)return `more than ${M} values`;if(t.bytes+=l.length*3+4,t.bytes>O)return `over the ${O} byte limit`;let d=U(a[l],e+1,t);if(d)return d}return null}function Xe(n){let e={nodes:0,bytes:0,seen:new Set},t=U(n,0,e);return t?`message contains ${t}`:e.bytes>O?`message is over the ${O} byte limit`:null}var Qe={origin:[ze,"not a well-formed origin"],url:[Ke,"not a safe absolute http(s) URL"],bcp47:[Ye,"not a well-formed BCP 47 tag"],code:[Je,"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}`,s=n[r.n];if(s==null){if(r.o)continue;return `${o}: required`}let a=te(s,r,o);if(a)return a}return null}function te(n,e,t){switch(e.k){case "string":{if(typeof n!="string")return `${t}: expected string`;if(n.length>e.max)return `${t}: exceeds ${e.max} characters`;if(e.f){let[r,o]=Qe[e.f];if(!r(n))return `${t}: ${o}`}return null}case "int":return typeof n!="number"||!Number.isInteger(n)?`${t}: expected integer`:n<e.lo||n>e.hi?`${t}: out of range ${e.lo}..${e.hi}`:null;case "boolean":return typeof n=="boolean"?null:`${t}: expected boolean`;case "enum":{let r=e.v;return r.includes(n)?null:`${t}: not one of ${r.join("|")}`}case "object":return typeof n!="object"||n===null||Array.isArray(n)?`${t}: expected object`:ne(n,e.fs,t);case "json":return typeof n!="object"||n===null||Array.isArray(n)?`${t}: expected a plain object`:null;case "array":{if(!Array.isArray(n))return `${t}: expected array`;if(n.length>e.max)return `${t}: exceeds ${e.max} items`;let r=e.it,o=`${t}[]`;for(let s of n){if(s==null){if(r.o)continue;return `${o}: required`}let a=te(s,r,o);if(a)return a}return null}default:{let r=e.k;return `${t}: unknown kind ${String(r)}`}}}function u(n,e){return t=>{let r=Xe(t);if(r)return r;if(typeof t!="object"||t===null||Array.isArray(t))return "message: expected object";let o=t;return o.gem!==Ve?"gem: wrong protocol marker":o.type!==n?`type: expected ${n}`:ne(o,e,"")}}var Ze=u("gem.handshake",[{n:"versions",k:"object",fs:[{n:"min",k:"int",lo:1,hi:1e3},{n:"max",k:"int",lo:1,hi:1e3}]},{n:"capabilities",k:"array",o:1,max:64,it:{n:"",k:"string",max:64}},{n:"embedder",k:"string",max:2048,f:"origin"},{n:"unbidden",k:"boolean",o:1}]),en=u("gem.handshake.accept",[{n:"v",k:"int",lo:1,hi:1e3},{n:"capabilities",k:"array",o:1,max:64,it:{n:"",k:"string",max:64}}]),nn=u("gem.token",[{n:"token",k:"string",max:4096},{n:"requestId",k:"string",o:1,max:64},{n:"generation",k:"int",lo:0,hi:2147483647},{n:"apiBaseUrl",k:"string",o:1,max:512,f:"url"},{n:"playerId",k:"string",max:64},{n:"gameId",k:"string",max:64},{n:"channel",k:"enum",v:["dev","test","release"]},{n:"gameVersion",k:"string",o:1,max:64},{n:"expiresAt",k:"int",lo:0,hi:4102444800},{n:"chainEndsAt",k:"int",lo:0,hi:4102444800},{n:"allowDevTools",k:"boolean",o:1}]),tn=u("gem.token.denied",[{n:"requestId",k:"string",max:64},{n:"retryable",k:"boolean"},{n:"retryAfterMs",k:"int",o:1,lo:0,hi:36e5},{n:"reason",k:"enum",v:["chain_exhausted","unavailable"]},{n:"correlationId",k:"string",max:64}]),rn=u("gem.player",[{n:"untrusted",k:"object",fs:[{n:"displayName",k:"string",max:64},{n:"displayTag",k:"string",o:1,max:80},{n:"displayHandle",k:"string",max:80}]},{n:"playerId",k:"string",o:1,max:64},{n:"discriminator",k:"string",o:1,max:8},{n:"avatarIconUrl",k:"string",o:1,max:2048,f:"url"},{n:"badges",k:"array",o:1,max:2,it:{n:"",k:"object",fs:[{n:"itemId",k:"string",max:64},{n:"iconUrl",k:"string",max:2048,f:"url"}]}},{n:"displayTag",k:"string",max:8},{n:"avatarUrl",k:"string",o:1,max:2048,f:"url"},{n:"boost",k:"object",o:1,fs:[{n:"multipliers",k:"array",max:8,it:{n:"",k:"object",fs:[{n:"currencyId",k:"string",max:64},{n:"currencySlug",k:"string",max:32},{n:"multiplierBp",k:"int",lo:1e4,hi:1e6}]}},{n:"expiresInDays",k:"int",o:1,lo:1,hi:7}]}]),on=u("gem.pause",[{n:"paused",k:"boolean"}]),sn=u("gem.prefs",[{n:"reducedMotion",k:"boolean"},{n:"muted",k:"boolean"},{n:"showFrameStats",k:"boolean",o:1},{n:"locale",k:"string",max:35,f:"bcp47"}]),an=u("gem.cohorts",[{n:"cohorts",k:"array",max:8,it:{n:"",k:"object",fs:[{n:"experimentId",k:"string",max:36},{n:"variantKey",k:"string",max:32}]}}]),ln=u("gem.earnAllowanceChanged",[]),dn=u("gem.viewport",[{n:"insets",k:"object",fs:[{n:"top",k:"int",lo:0,hi:4096},{n:"right",k:"int",lo:0,hi:4096},{n:"bottom",k:"int",lo:0,hi:4096},{n:"left",k:"int",lo:0,hi:4096}]},{n:"reserved",k:"array",o:1,max:4,it:{n:"",k:"object",fs:[{n:"x",k:"int",lo:0,hi:16384},{n:"y",k:"int",lo:0,hi:16384},{n:"width",k:"int",lo:0,hi:16384},{n:"height",k:"int",lo:0,hi:16384}]}}]),un=u("gem.deviceSettings",[{n:"settings",k:"json",o:1}]),cn=u("gem.willTerminate",[{n:"reason",k:"enum",v:["grant_expiring","session_ended","navigating","kill_switch"]},{n:"graceMs",k:"int",lo:0,hi:6e4}]),gn=u("gem.roomEvent",[{n:"event",k:"enum",v:["updated","match_started","match_ready","match_failed","version_stale"]},{n:"roomId",k:"string",max:64},{n:"matchId",k:"string",o:1,max:64},{n:"version",k:"int",o:1,lo:0,hi:2147483647},{n:"reason",k:"string",o:1,max:64},{n:"platform",k:"enum",o:1,v:["universal","mobile"]}]),mn=u("gem.socketState",[{n:"connected",k:"boolean"},{n:"reason",k:"enum",o:1,v:["connecting","dropped","watchdog","terminal"]}]),pn=u("gem.seatedEvent",[{n:"roomId",k:"string",max:64}]),yn=u("gem.autoStartFailedEvent",[{n:"roomId",k:"string",max:64},{n:"code",k:"string",max:64}]),fn=u("gem.signalEvent",[{n:"event",k:"enum",v:["hello","offer","answer","ice","peerJoined","peerLeft","migration","matchEnded","error"]},{n:"matchId",k:"string",max:64},{n:"data",k:"json"}]),hn=u("gem.dedicatedEvent",[{n:"event",k:"enum",v:["answer","error","matchEnded"]},{n:"matchId",k:"string",max:64},{n:"sdp",k:"string",o:1,max:10240},{n:"sessionId",k:"string",o:1,max:64},{n:"code",k:"string",o:1,max:64},{n:"message",k:"string",o:1,max:256},{n:"reason",k:"string",o:1,max:64}]),_n=u("gem.partyResult",[{n:"requestId",k:"string",max:64},{n:"partyId",k:"string",o:1,max:64}]),bn=u("gem.clusterTarget",[{n:"clusterTargetId",k:"string",max:64},{n:"clusterTargetIds",k:"array",o:1,max:3,it:{n:"",k:"string",max:64}}]),vn=u("gem.devtools",[{n:"action",k:"enum",v:["open","close","toggle"]}]),Rn=u("gem.screenshot",[{n:"maxWidth",k:"int",lo:1,hi:7680},{n:"maxHeight",k:"int",lo:1,hi:4320}]),xn=u("gem.screenshot.denied",[{n:"reason",k:"enum",v:["not_wired","no_source","unsupported","unreadable","tainted","too_large","busy","declined","failed"]},{n:"retryable",k:"boolean"}]),Sn=u("gem.requestContext",[]),kn=u("gem.gameContext",[{n:"context",k:"json"}]),wn=u("gem.signal",[{n:"signal",k:"enum",v:["join","offer","answer","ice","migrationAck","hostUnreachable"]},{n:"matchId",k:"string",max:64},{n:"data",k:"json"}]),An=u("gem.dedicatedOffer",[{n:"matchId",k:"string",max:64},{n:"sdp",k:"string",max:10240},{n:"intent",k:"enum",v:["initial","ice_restart","full_reconnect"]}]),Tn=u("gem.partyRequest",[{n:"requestId",k:"string",max:64}]),Pn=u("gem.ready",[]),On=u("gem.engaged",[]),Gn=u("gem.progress",[{n:"loaded",k:"int",lo:0,hi:1099511627776},{n:"total",k:"int",lo:0,hi:1099511627776}]),En=u("gem.requestToken",[{n:"requestId",k:"string",max:64},{n:"reason",k:"enum",v:["initial","expiring","rejected"]}]),Cn=u("gem.requestLocalServer",[{n:"requestId",k:"string",max:64},{n:"gameRoomId",k:"string",max:64}]),In=u("gem.localServer",[{n:"requestId",k:"string",max:64},{n:"serverId",k:"string",o:1,max:128}]),qn=u("gem.localServer.denied",[{n:"requestId",k:"string",max:64},{n:"retryable",k:"boolean"},{n:"reason",k:"enum",v:["refused","unavailable"]}]),Ln=u("gem.exit",[{n:"reason",k:"string",o:1,max:64}]),$n=u("gem.openExternal",[{n:"url",k:"string",max:2048,f:"url"}]),jn=u("gem.requestFullscreen",[{n:"enabled",k:"boolean"}]),Mn=u("gem.audioState",[{n:"muted",k:"boolean"}]),Fn=u("gem.rewardCue",[{n:"currencySlug",k:"string",max:32},{n:"expected",k:"int",o:1,lo:1,hi:1e9},{n:"origin",k:"object",o:1,fs:[{n:"x",k:"int",lo:0,hi:16384},{n:"y",k:"int",lo:0,hi:16384}]}]),Un=u("gem.walletDisplay",[{n:"visible",k:"boolean"},{n:"currencies",k:"array",o:1,max:8,it:{n:"",k:"string",max:64}},{n:"score",k:"boolean",o:1}]),Bn=u("gem.requestShare",[{n:"params",k:"array",max:16,it:{n:"",k:"object",fs:[{n:"key",k:"string",max:64},{n:"value",k:"string",max:512}]}}]),Nn=u("gem.frameStats",[{n:"fps",k:"int",lo:0,hi:1e3},{n:"frameTimeP95Ms",k:"int",lo:0,hi:1e5}]),Dn=u("gem.error",[{n:"code",k:"enum",v:["version_mismatch","handshake_timeout","handshake_duplicate","invalid_message","rate_limited","token_unavailable","unsupported","unsupported_capability","internal"]},{n:"message",k:"string",o:1,max:256}]),Hn=u("gem.requestPurchase",[{n:"requestId",k:"string",max:64},{n:"purchaseKind",k:"enum",v:["item","recipe"]},{n:"targetId",k:"string",max:64},{n:"currencySlug",k:"string",max:32},{n:"quantity",k:"int",o:1,lo:1,hi:10},{n:"catalogId",k:"string",o:1,max:64}]),Vn=u("gem.purchaseResult",[{n:"requestId",k:"string",max:64},{n:"outcome",k:"enum",v:["ok","declined","unavailable"]},{n:"reason",k:"string",o:1,max:64,f:"code"},{n:"purchaseId",k:"string",o:1,max:64}]),Wn=u("gem.deviceSettings.put",[{n:"requestId",k:"string",max:64},{n:"settings",k:"json"}]),zn=u("gem.deviceSettings.result",[{n:"requestId",k:"string",max:64},{n:"outcome",k:"enum",v:["stored","too_large","unavailable"]}]),Kn=u("gem.requestAd",[{n:"requestId",k:"string",max:64},{n:"placement",k:"string",max:32},{n:"format",k:"enum",v:["interstitial","rewarded"]}]),Yn=u("gem.adResult",[{n:"requestId",k:"string",max:64},{n:"outcome",k:"enum",v:["shown","no_ad","unavailable"]}]),Jn=u("gem.requestSignIn",[{n:"requestId",k:"string",max:64}]),Xn=u("gem.signInResult",[{n:"requestId",k:"string",max:64},{n:"outcome",k:"enum",v:["signed_in","declined","unavailable"]}]),Qn=u("gem.requestFriendChallenge",[{n:"requestId",k:"string",max:64},{n:"playerId",k:"string",max:64},{n:"template",k:"string",max:64},{n:"params",k:"json",o:1}]),Zn=u("gem.friendChallengeResult",[{n:"requestId",k:"string",max:64},{n:"outcome",k:"enum",v:["accepted","cancelled","refused","unavailable","rate_limited","invalid"]},{n:"code",k:"string",o:1,max:64},{n:"param",k:"string",o:1,max:64},{n:"channel",k:"string",o:1,max:16},{n:"configVersion",k:"int",o:1,lo:0,hi:9007199254740991},{n:"retryAfterMs",k:"int",o:1,lo:0,hi:864e5},{n:"detail",k:"string",o:1,max:300}]);B({"gem.handshake":Ze,"gem.handshake.accept":en,"gem.token":nn,"gem.token.denied":tn,"gem.player":rn,"gem.pause":on,"gem.prefs":sn,"gem.cohorts":an,"gem.earnAllowanceChanged":ln,"gem.viewport":dn,"gem.deviceSettings":un,"gem.willTerminate":cn,"gem.roomEvent":gn,"gem.socketState":mn,"gem.seatedEvent":pn,"gem.autoStartFailedEvent":yn,"gem.signalEvent":fn,"gem.dedicatedEvent":hn,"gem.partyResult":_n,"gem.clusterTarget":bn,"gem.devtools":vn,"gem.screenshot":Rn,"gem.screenshot.denied":xn,"gem.requestContext":Sn,"gem.gameContext":kn,"gem.signal":wn,"gem.dedicatedOffer":An,"gem.partyRequest":Tn,"gem.ready":Pn,"gem.engaged":On,"gem.progress":Gn,"gem.requestToken":En,"gem.requestLocalServer":Cn,"gem.localServer":In,"gem.localServer.denied":qn,"gem.exit":Ln,"gem.openExternal":$n,"gem.requestFullscreen":jn,"gem.audioState":Mn,"gem.rewardCue":Fn,"gem.walletDisplay":Un,"gem.requestShare":Bn,"gem.frameStats":Nn,"gem.error":Dn,"gem.requestPurchase":Hn,"gem.purchaseResult":Vn,"gem.deviceSettings.put":Wn,"gem.deviceSettings.result":zn,"gem.requestAd":Kn,"gem.adResult":Yn,"gem.requestSignIn":Jn,"gem.signInResult":Xn,"gem.requestFriendChallenge":Qn,"gem.friendChallengeResult":Zn});var G={now:()=>Date.now(),setTimeout:(n,e)=>setTimeout(n,e),clearTimeout:n=>clearTimeout(n)};var et=1e4;function re(n,e){return N(n,e)}function N(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=a=>({token:a.token,expiresAt:a.expiresAt,chainEndsAt:Number.POSITIVE_INFINITY}),r=null,o=new $({clock:e.clock,...e.onStateChange===void 0?{}:{onStateChange:e.onStateChange},request:()=>new Promise((a,l)=>{let d=e.clock.setTimeout(()=>{r=null,l({reason:"unavailable",retryable:true});},e.timeoutMs??et);r={resolve:c=>{e.clock.clearTimeout(d),a(c);},reject:l,timer:d};})}),s=n.onServerToken(a=>{let l=t(a),d=r;if(d){r=null,d.resolve(l);return}o.accept(l);});return {source:o,dispose(){s(),r&&(e.clock.clearTimeout(r.timer),r.reject({reason:"unavailable",retryable:false}),r=null);}}}var H={};Re(H,{acceptTransfer:()=>nt,addEntityProgression:()=>tt,adminAction:()=>rt,cancelInventoryTransfer:()=>ot,claimEntityProgressionRewards:()=>st,closeGameRoom:()=>it,createEntityBatchOrder:()=>at,createEntityOrder:()=>lt,createSession:()=>dt,deleteEntityGameSetting:()=>ut,deleteEntitySave:()=>ct,deleteSession:()=>gt,deleteShowcaseValue:()=>mt,executeEntityRecipe:()=>pt,finalizeSaveUpload:()=>yt,getChannelAssignment:()=>ft,getDropRates:()=>ht,getEntityCurrency:()=>_t,getEntityGameSetting:()=>bt,getEntityInventory:()=>vt,getEntityInventoryItem:()=>Rt,getEntityLeaderboard:()=>xt,getEntityOrder:()=>St,getEntityProgression:()=>kt,getEntityRecipeAvailability:()=>wt,getEntityRecipeUsage:()=>At,getEntitySave:()=>Tt,getEvent:()=>Pt,getGameRoomV2:()=>Ot,getLeaderboard:()=>Gt,getPlayerGameProfile:()=>Et,getPurchaseCatalog:()=>Ct,getResolvedTemplate:()=>It,getRoomArgs:()=>qt,getShowcaseValue:()=>Lt,getTransferDetails:()=>$t,ingestAnalyticsEvents:()=>D,initiateInventoryTransfer:()=>jt,invokeFunction:()=>Mt,kickPlayer:()=>Ft,listChallenges:()=>Ut,listEntityGameSettings:()=>Bt,listEntityOrders:()=>Nt,listEntityProgressions:()=>Dt,listEntitySaves:()=>Ht,listEvents:()=>Vt,listGameRooms:()=>Wt,listResolvedTemplates:()=>zt,listTransfers:()=>Kt,maxEntityProgression:()=>Yt,putEntityGameSetting:()=>Jt,putRoomArgs:()=>Xt,putShowcaseValue:()=>Qt,rejectTransfer:()=>Zt,requestSaveUploadUrl:()=>er,resetEntityProgression:()=>nr,simulateEntityOrder:()=>tr,transferHostV2:()=>rr,updateGameRoomV2:()=>or});function i(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 nt(n,e,t){let r=`/v1/inventory/transfers/${i(e)}/accept`;return n.client.post(r,void 0,t?.signal)}async function tt(n,e,t,r,o,s){let a=`/v1/inventory/${i(e)}/${i(t)}/progressions/${i(r)}/add`;return n.client.post(a,o,s?.signal)}async function rt(n,e,t,r){let o=`/v1/voice/sessions/${i(e)}/admin`;return n.client.post(o,t,r?.signal)}async function ot(n,e,t){let r=`/v1/inventory/transfers/${i(e)}/cancel`;return n.client.post(r,void 0,t?.signal)}async function st(n,e,t,r,o,s){let a=`/v1/inventory/${i(e)}/${i(t)}/progressions/${i(r)}/claim`;return n.client.post(a,o,s?.signal)}async function it(n,e,t){let r=`/v1/games/${i(n.gameId())}/game-rooms/${i(e)}`;return n.client.delete(r,t?.signal)}async function at(n,e,t,r,o){let s=`/v1/inventory/${i(e)}/${i(t)}/orders/batch`;return n.client.post(s,r,o?.signal,{...o?.ifMatch===void 0?{}:{ifMatch:o.ifMatch}})}async function lt(n,e,t,r,o){let s=`/v1/inventory/${i(e)}/${i(t)}/orders`;return n.client.post(s,r,o?.signal,{...o?.ifMatch===void 0?{}:{ifMatch:o.ifMatch}})}async function dt(n,e,t){return n.client.post("/v1/voice/sessions",e,t?.signal)}async function ut(n,e,t,r,o){let s=`/v1/settings/${i(e)}/${i(t)}/${i(r)}`;return n.client.delete(s,o?.signal)}async function ct(n,e,t,r,o){let s=`/v1/saves/${i(e)}/${i(t)}/${i(r)}`;return n.client.delete(s,o?.signal)}async function gt(n,e,t){let r=`/v1/voice/sessions/${i(e)}`;return n.client.delete(r,t?.signal)}async function mt(n,e,t,r){let o=`/v1/showcase/players/${i(e)}/${i(t)}`;return n.client.delete(o,r?.signal)}async function pt(n,e,t,r,o){let s=`/v1/inventory/${i(e)}/${i(t)}/recipes/execute`;return n.client.post(s,r,o?.signal,{...o?.ifMatch===void 0?{}:{ifMatch:o.ifMatch}})}async function yt(n,e,t,r,o,s){let a=`/v1/saves/${i(e)}/${i(t)}/${i(r)}/finalize`;return n.client.post(a,o,s?.signal)}async function ft(n,e,t){let r=`/v1/games/${i(n.gameId())}/config/channels/${i(e)}`;return n.client.getWithEtag(r,{...t?.signal===void 0?{}:{signal:t.signal},...t?.ifNoneMatch===void 0?{}:{ifNoneMatch:t.ifNoneMatch}})}async function ht(n,e,t){let r=`/v1/inventory/loot-tables/${i(e)}/drop-rates`;return n.client.get(r,t?.signal)}async function _t(n,e,t,r,o){let s=`/v1/inventory/${i(e)}/${i(t)}/currencies/${i(r)}`;return n.client.get(s,o?.signal)}async function bt(n,e,t,r,o){let s=`/v1/settings/${i(e)}/${i(t)}/${i(r)}`;return n.client.getWithEtag(s,{...o?.signal===void 0?{}:{signal:o.signal},...o?.ifNoneMatch===void 0?{}:{ifNoneMatch:o.ifNoneMatch}})}async function vt(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 s=o.toString(),a=`/v1/inventory/${i(e)}/${i(t)}`+(s?`?${s}`:"");return n.client.get(a,r?.signal)}async function Rt(n,e,t,r,o){let s=`/v1/inventory/${i(e)}/${i(t)}/items/${i(r)}`;return n.client.get(s,o?.signal)}async function xt(n,e,t,r,o){let s=new URLSearchParams;o?.bucket_1!==void 0&&s.set("bucket_1",String(o?.bucket_1)),o?.bucket_2!==void 0&&s.set("bucket_2",String(o?.bucket_2)),o?.limit!==void 0&&s.set("limit",String(o?.limit));let a=s.toString(),l=`/v1/leaderboards/${i(e)}/${i(t)}/${i(r)}`+(a?`?${a}`:"");return n.client.get(l,o?.signal)}async function St(n,e,t,r,o){let s=`/v1/inventory/${i(e)}/${i(t)}/orders/${i(r)}`;return n.client.get(s,o?.signal)}async function kt(n,e,t,r,o){let s=`/v1/inventory/${i(e)}/${i(t)}/progressions/${i(r)}`;return n.client.get(s,o?.signal)}async function wt(n,e,t,r,o,s){let a=`/v1/inventory/${i(e)}/${i(t)}/catalogs/${i(r)}/recipes/${i(o)}/availability`;return n.client.get(a,s?.signal)}async function At(n,e,t,r){let o=new URLSearchParams;r?.limit!==void 0&&o.set("limit",String(r?.limit));let s=o.toString(),a=`/v1/inventory/${i(e)}/${i(t)}/recipe-usage`+(s?`?${s}`:"");return n.client.get(a,r?.signal)}async function Tt(n,e,t,r,o){let s=`/v1/saves/${i(e)}/${i(t)}/${i(r)}`;return n.client.getWithEtag(s,{...o?.signal===void 0?{}:{signal:o.signal},...o?.ifNoneMatch===void 0?{}:{ifNoneMatch:o.ifNoneMatch}})}async function Pt(n,e,t){let r=`/v1/events/${i(e)}`;return n.client.get(r,t?.signal)}async function Ot(n,e,t){let r=`/v2/games/${i(n.gameId())}/game-rooms/${i(e)}`;return n.client.getWithEtag(r,{...t?.signal===void 0?{}:{signal:t.signal},...t?.ifNoneMatch===void 0?{}:{ifNoneMatch:t.ifNoneMatch}})}async function Gt(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));let o=r.toString(),s=`/v1/leaderboards/${i(e)}`+(o?`?${o}`:"");return n.client.get(s,t?.signal)}async function Et(n,e,t){let r=`/v1/profiles/players/${i(e)}`;return n.client.get(r,t?.signal)}async function Ct(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 It(n,e,t){let r=`/v1/game-room-templates/${i(e)}`;return n.client.get(r,t?.signal)}async function qt(n,e,t){let r=`/v1/games/${i(n.gameId())}/game-rooms/${i(e)}/room-args`;return n.client.get(r,t?.signal)}async function Lt(n,e,t,r){let o=`/v1/showcase/players/${i(e)}/${i(t)}`;return n.client.get(o,r?.signal)}async function $t(n,e,t){let r=`/v1/inventory/transfers/${i(e)}`;return n.client.get(r,t?.signal)}async function D(n,e,t){let r=`/v1/games/${i(n.gameId())}/analytics/events`;return n.client.post(r,e,t?.signal,{replaySafe:true})}async function jt(n,e,t){return n.client.post("/v1/inventory/transfers",e,t?.signal)}async function Mt(n,e,t){return n.client.postBytes("/v1/functions/invoke",e,t?.signal)}async function Ft(n,e,t,r){let o=`/v1/games/${i(n.gameId())}/game-rooms/${i(e)}/kick/${i(t)}`;return n.client.post(o,void 0,r?.signal)}async function Ut(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 Bt(n,e,t,r){let o=`/v1/settings/${i(e)}/${i(t)}`;return n.client.get(o,r?.signal)}async function Nt(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 s=o.toString(),a=`/v1/inventory/${i(e)}/${i(t)}/orders`+(s?`?${s}`:"");return n.client.get(a,r?.signal)}async function Dt(n,e,t,r){let o=`/v1/inventory/${i(e)}/${i(t)}/progressions`;return n.client.get(o,r?.signal)}async function Ht(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 s=o.toString(),a=`/v1/saves/${i(e)}/${i(t)}`+(s?`?${s}`:"");return n.client.get(a,r?.signal)}async function Vt(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 Wt(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/${i(n.gameId())}/game-rooms`+(r?`?${r}`:"");return n.client.get(o,e?.signal)}async function zt(n,e){return n.client.get("/v1/game-room-templates",e?.signal)}async function Kt(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 Yt(n,e,t,r,o,s){let a=`/v1/inventory/${i(e)}/${i(t)}/progressions/${i(r)}/max`;return n.client.post(a,o,s?.signal)}async function Jt(n,e,t,r,o,s){let a=`/v1/settings/${i(e)}/${i(t)}/${i(r)}`;return n.client.put(a,o,s?.signal,{...s?.ifMatch===void 0?{}:{ifMatch:s.ifMatch}})}async function Xt(n,e,t,r){let o=`/v1/games/${i(n.gameId())}/game-rooms/${i(e)}/room-args`;return n.client.put(o,t,r?.signal)}async function Qt(n,e,t,r,o){let s=`/v1/showcase/players/${i(e)}/${i(t)}`;return n.client.put(s,r,o?.signal)}async function Zt(n,e,t){let r=`/v1/inventory/transfers/${i(e)}/reject`;return n.client.post(r,void 0,t?.signal)}async function er(n,e,t,r,o,s){let a=`/v1/saves/${i(e)}/${i(t)}/${i(r)}/upload-url`;return n.client.post(a,o,s?.signal,{replaySafe:true})}async function nr(n,e,t,r,o,s){let a=`/v1/inventory/${i(e)}/${i(t)}/progressions/${i(r)}/reset`;return n.client.post(a,o,s?.signal)}async function tr(n,e,t,r,o){let s=`/v1/inventory/${i(e)}/${i(t)}/orders/simulate`;return n.client.post(s,r,o?.signal)}async function rr(n,e,t,r){let o=`/v2/games/${i(n.gameId())}/game-rooms/${i(e)}/transfer/${i(t)}`;return n.client.post(o,void 0,r?.signal)}async function or(n,e,t,r){let o=`/v2/games/${i(n.gameId())}/game-rooms/${i(e)}`;return n.client.patch(o,t,r?.signal,{...r?.ifMatch===void 0?{}:{ifMatch:r.ifMatch}})}var oe="gem_";var ar=1e4,lr=50,dr=1e3,ur=65536-4*1024,se=n=>typeof n=="number"?n:0,cr=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 gr(n){return n?.retryable===true}function mr(n,e){let t=n??{},r=Array.isArray(t.rejected)?t.rejected.map(o=>{let s=o??{};return {index:se(s.index),code:cr(s.code)}}):[];return {accepted:se(t.accepted),rejected:r,dropped:e,duplicate:t.duplicate===true}}function ae(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 le(n){let e=Math.max(1,Math.floor(n.maxQueue??dr)),t={client:n.client,gameId:()=>n.gameId},r=[],o=0,s=null,a=false,l=false,d=false,c=false,g=y=>{n.log?.(y);},b=()=>{s!==null&&(n.clock.clearTimeout(s),s=null);},x=()=>{s!==null||a||l||(s=n.clock.setTimeout(()=>{s=null,v().catch(()=>{});},ar));},f=()=>{let y=Math.min(r.length,100),h=128;for(let w=0;w<y;w+=1){let A=r[w];if(A===void 0)break;if(h+=JSON.stringify(ae(A,0)).length+1,h>ur)return Math.max(1,w)}return y};async function v(y){if(r.length===0)return {accepted:0,rejected:[],dropped:0,duplicate:false};b();let h=r.splice(0,f()),w=o;o=0;let A=Math.round(n.clock.now()),L={batch_id:ie(),sent_at_ms:A,events:h.map(S=>ae(S,A))};l=true;try{let S=await D(t,L,y===void 0?void 0:{signal:y}),T=mr(S,w);for(let be of T.rejected)g(`[gem] analytics: an event was refused (${be.code}). See the analytics_events section of your game config.`);return T}catch(S){if(gr(S))for(r=[...h,...r],o+=w;r.length>e;)r.shift(),o+=1;else g(`[gem] analytics: ${h.length} event(s) were discarded \u2014 the platform refused the batch and will refuse it again: ${String(S)}`);throw S}finally{l=false,r.length>0&&x();}}return {track(y,h,w={}){if(a)return;if(typeof y!="string"||y===""){c||(c=true,g(`[gem] analytics: '${h}' 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(h.startsWith(oe)){d||(d=true,g(`[gem] analytics: '${h}' 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[S,T]of Object.entries(w))typeof T=="string"?A[S]=T:typeof T=="number"&&Number.isFinite(T)&&(L[S]=T);for(;r.length>=e;)r.shift(),o+=1;r.push({uid:ie(),playerId:y,name:h,atMs:n.clock.now(),dimensions:A,measures:L}),r.length>=lr?v().catch(()=>{}):x();},flush:y=>v(y),get pending(){return r.length},dispose(){a=true,b(),r=[],o=0;}}}var pr=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 m{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:pr.get(this.code))??super.retryable}},E=class{#e;constructor(e){this.#e=e;}async invoke(e,t={}){let r=yr(e),o;try{o=await this.#e(r,t.signal===void 0?{}:{signal:t.signal});}catch(s){throw s instanceof m?hr(s):s}return fr(o)}};function yr(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 p(`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 p(`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 fr(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 hr(n){let{details:e,invocationId:t}=X(n),o=e?.untrusted?.message,s=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 s=="string"?{failure:s}:{}})}var k=n=>typeof n=="string"?n:"",_r=/(?:Z|[+-]\d{2}:?\d{2})$/i;function de(n){let e=k(n);if(!_r.test(e))return 0;let t=Date.parse(e);return Number.isFinite(t)?Math.floor(t/1e3):0}var br=/^[0-9a-f]{1,64}$/,vr=/^[0-9a-f]{16}$/,Rr=/^[A-Za-z][A-Za-z0-9_+\-/]{0,63}$/,xr=/^(?:[01]\d|2[0-3]):[0-5]\d$/;function Sr(n){let e=k(n),t=/^(\d{4})-(\d{2})-(\d{2})$/.exec(e);if(!t)return;let[r,o,s]=[Number(t[1]),Number(t[2]),Number(t[3])],a=new Date(Date.UTC(r,o-1,s));return a.getUTCFullYear()===r&&a.getUTCMonth()===o-1&&a.getUTCDate()===s?e:void 0}var kr=4096,wr=new TextEncoder;function Ar(n){let e=k(n.challenge_data),t=k(n.challenge_data_hash);return e===""||!vr.test(t)?{}:wr.encode(e).length>kr?{}:{data:e,dataHash:t}}function Tr(n){let e=n??{},t=de(e.period_start_at),r=de(e.period_ends_at);if(t===0||r===0)return;let o=k(e.slug),s=k(e.seed),a=Sr(e.period_local_date),l=k(e.boundary),d=k(e.reset_time);return {id:k(e.progression_definition_id),...o===""?{}:{slug:o},window:k(e.window),periodStartAt:t,periodEndsAt:r,...a===void 0?{}:{periodLocalDate:a},boundary:Rr.test(l)?l:"",resetTime:xr.test(d)?d:"",seed:br.test(s)?s:"",...Ar(e)}}function ue(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 ce(n){let e=n??{};return Array.isArray(e.challenges)?e.challenges.map(Tr).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().");ue(r);let s=await n({player_id:t,...r===void 0?{}:{periods_back:r},...o===void 0?{}:{signal:o}});return ce(s)}}}function Pr(n){let e={};for(let[t,r]of Object.entries(H))if(typeof r=="function"){let o=r;e[t]=(...s)=>o(n,...s);}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=N(n,{clock:t,...e.onAuthStateChange===void 0?{}:{onStateChange:e.onAuthStateChange}}),s=Q({baseUrl:r,tokenSource:o.source,defaultQuery:{game_id:n.gameId,channel:n.channel},...e.fetch===void 0?{}:{fetch:e.fetch}}),a=new P({transport:s,clock:t}),l={gameId:n.gameId,channel:n.channel,matchId:n.matchId,...n.gameRoomId===void 0?{}:{gameRoomId:n.gameRoomId}},d=Pr({client:a,gameId:()=>l.gameId}),c=l.gameRoomId,g=n.endMatch,b=n.log,x=le({client:a,clock:t,gameId:l.gameId,...typeof b=="function"?{log:v=>b.call(n,v)}:{}});return {identity:l,client:a,api:d,match:{end:async()=>{if(g===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 g.call(n);}},analytics:x,functions:new E(d.invokeFunction),challenges:ge(d.listChallenges),...c===void 0?{}:{room:{get:v=>d.getGameRoomV2(c,v),args:async v=>{let y=await d.getGameRoomV2(c,v?.signal===void 0?{}:{signal:v.signal}),h=y.modified?y.body:void 0;if(h?.room_args==null||h.room_args_template==null)throw new m("not_found",404,"this room's template declares no room args",void 0,"room_args_not_defined");return {room_args:h.room_args,room_args_template:h.room_args_template}}}},dispose:()=>{x.dispose(),o.dispose();}}}var Or=["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"],Gr=new Set(Or);function me(n){return typeof n=="string"&&Gr.has(n)?n:"unknown"}var R=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 R(n)}var pe={toPlain(n){return R.unwrap(n)},compare(n,e,t){let r=n instanceof R?R.unwrap(n):n,o=e instanceof R?R.unwrap(e):e,s;try{s=new Intl.Collator(t);}catch{s=new Intl.Collator;}return s.compare(r,o)},equals(n,e){let t=n instanceof R?R.unwrap(n):n,r=e instanceof R?R.unwrap(e):e;return t.normalize("NFC")===r.normalize("NFC")}};var ye="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 V(n,e={}){let t=e.clock??G,r=()=>{let l=n();if(l===null)throw new Error(ye);return l},o=null,s=()=>{if(o===null)throw new Error(ye);return o};return {server:{get identity(){return s().identity},get client(){return s().client},get api(){return s().api},get match(){return s().match},get analytics(){return s().analytics},get functions(){return s().functions},get challenges(){return s().challenges},get room(){return s().room},dispose(){o?.dispose();},get sizeClass(){return r().sizeClass},get roomArgs(){return r().roomArgs},get roster(){return r().roster},players(){return r().players()},profile(l){let c=r().profile?.(l);if(!c)return null;let g=c.displayName;return typeof g!="string"||g===""?null:{displayName:q(g),...typeof c.displayTag=="string"&&c.displayTag!==""?{displayTag:q(c.displayTag)}:{},...typeof c.discriminator=="string"?{discriminator:c.discriminator}:{}}},playerNumber(l){return r().playerNumber?.(l)},send(l,d,c){c===void 0?r().send(l,d):r().send(l,d,c);},broadcast(l,d){d===void 0?r().broadcast(l):r().broadcast(l,d);},kick(l,d){d===void 0?r().kick(l):r().kick(l,d);},log(l){r().log(l);},warn(l){r().warn(l);}},attach:()=>{o=F(r(),{...e,clock:t});}}}function fe(n,e={}){let{server:t,attach:r}=V(()=>n,e);return r(),t}function Er(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:me(e)}}}function he(n,e={}){return ()=>{let t=null,{server:r,attach:o}=V(()=>t,e),s=n(r),a={async init(l){t=l,o(),await s.init?.();},async shutdown(l){let d=Er(l);try{await s.shutdown?.(d);}finally{r.dispose();}}};return s.join&&(a.join=(l,d)=>s.join?.(l,d)),s.leave&&(a.leave=(l,d)=>s.leave?.(l,d)),s.message&&(a.message=(l,d,c,g)=>s.message?.(l,d,c,g)),a}}var Cr=new Set(["unlocked","already_unlocked","suppressed"]);function _e(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"||!Cr.has(o.outcome)||typeof o.achievement_id!="string"||o.achievement_id==="")continue;let s=o.outcome;t.push({achievementId:o.achievement_id,progressionDefinitionId:typeof o.progression_definition_id=="string"?o.progression_definition_id:"",points:s==="unlocked"&&typeof o.points=="number"&&Number.isFinite(o.points)?o.points:0,outcome:s,...typeof o.reason=="string"?{reason:o.reason}:{}});}return t}
1
+ var ve=Object.defineProperty;var Re=(n,e)=>{for(var t in e)ve(n,t,{get:e[t],enumerable:true});};globalThis.__gemWebSdkVersion="[gem-web-sdk:sdkVersion:7.6.0]";function xe(n,e){return e!==void 0?!e:n==="chain_exhausted"}var $=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 _(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 _("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 _("internal","token arrived for a superseded generation");return this.grant=o,this.rejected=false,this.enter("ready"),o.token}).catch(o=>{let s=Se(o),a=o?.retryable;throw t===this.generation&&this.enter(xe(s,typeof a=="boolean"?a:void 0)?"lost":"degraded",s),o instanceof _?o:new _(s,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)}},_=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 Se(n){if(n instanceof _)return n.reason;let e=n?.reason;return typeof e=="string"&&["chain_exhausted","unavailable","timeout","internal"].includes(e)?e:"internal"}var p=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}},j=["if-match","if-none-match"],W=4096;function ke(n){if(!n)return;let e={};for(let[t,r]of Object.entries(n)){let o=t.toLowerCase();if(!j.includes(o)||r===void 0)continue;let s=typeof r=="string"?we(r):r;if(typeof s!="string"||s.length>W||!Ae(s))throw new p(`the ${o} header value cannot be sent \u2014 it is not a string, is longer than ${W} 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.`);s!==""&&(e[o]=s);}return Object.freeze(e)}function we(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 Ae(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 p("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 p("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 z(n,e){let t=e.replayUnauthorizedOnce??true;return {async request(r){let o={...r},s=ke(o.headers),a=Te(o),l=Object.freeze({...o,headers:s,...a===void 0?{}:{bytes:a}}),d=await e.tokenSource.get(),c=await n(l,d);if(c.status!==401||!t)return c;e.tokenSource.invalidate(d);let g=await e.tokenSource.get(),b=await n(l,g);if(b.status===401)throw e.tokenSource.close("unavailable"),new _("unavailable","the server refused a freshly minted token");return b}}}function K(n){let e=typeof n=="string"?new TextEncoder().encode(n):n;return btoa(Pe(e))}function Pe(n){let t="";for(let r=0;r<n.length;r+=32768)t+=String.fromCharCode(...n.subarray(r,r+32768));return t}var m=class extends Error{constructor(t,r,o,s,a){super(`${t} (${r}): ${o}`);this.reason=t;this.status=r;this.detail=o;this.retryAfterSeconds=s;this.code=a;this.name="GemApiError";}reason;status;detail;retryAfterSeconds;code;get retryable(){return this.reason==="unavailable"||this.reason==="rate_limited"}},J=new WeakMap;function X(n){return J.get(n)??{}}var Oe=new Set([408,429,500,502,503,504]),Ge=6e4;function Ee(n){if(n===void 0)return 2;if(!Number.isInteger(n)||n<0||n>10)throw new p(`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 P=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,...C(o)},o.replaySafe===true)}async post(e,t,r,o={}){return this.send({method:"POST",path:e,body:t,signal:r,...C(o)},o.replaySafe===true)}async postBytes(e,t,r,o={}){let s=await this.sendRaw({method:"POST",path:e,bytes:t,responseType:"bytes",signal:r,...C(o)},o.replaySafe===true);return {bytes:Ce(s.body),...s.invocationId===void 0?{}:{invocationId:s.invocationId}}}async patch(e,t,r,o={}){return this.send({method:"PATCH",path:e,body:t,signal:r,...C(o)},o.replaySafe===true)}async delete(e,t,r={}){return this.send({method:"DELETE",path:e,signal:t,...C(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 Y(e.signal);for(let s=0;s<r;s++){if(s>0&&await this.backoff(s,o,e.signal),e.signal?.aborted)throw Y(e.signal);let a;try{a=await this.options.transport.request(e);}catch(d){if(_.isAuthError(d)||p.isRefusal(d)||e.signal?.aborted||Ie(d))throw d;o=new m("unavailable",0,String(d));continue}if(a.status>=200&&a.status<300||a.status===304)return a;let l=qe(a);if(!Oe.has(a.status))throw l;o=l;}throw o??new m("unavailable",0,"no attempt was made")}backoff(e,t,r){if(r?.aborted)return Promise.resolve();let o=t?.retryAfterSeconds,s=o!==void 0?o*1e3:2**(e-1)*250,a=2**(e-1)*250,l=Math.min(Math.max(s,a),Ge);return new Promise(d=>{let c=this.options.clock,g=false,b=false,x,f=()=>{g||(g=true,b&&c.clearTimeout(x),r?.removeEventListener("abort",f),d());};r?.addEventListener("abort",f,{once:true}),x=c.setTimeout(f,l),b=true,g&&c.clearTimeout(x);})}};function Ce(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 C(n){return {...n.keepalive===void 0?{}:{keepalive:n.keepalive},...n.ifMatch===void 0?{}:{headers:{"if-match":n.ifMatch}}}}function Y(n){return n.reason!==void 0?n.reason:new DOMException("The operation was aborted.","AbortError")}function Ie(n){let e=n?.name;return e==="AbortError"||e==="TimeoutError"}function qe(n){let e=$e(n),t=Me(n.body),r={...t===void 0?{}:{details:t},...n.invocationId===void 0?{}:{invocationId:n.invocationId}};return Object.keys(r).length>0&&J.set(e,r),e}var Le=new Map([["insufficient_funds","insufficient_funds"]]);function $e(n){let{status:e,body:t}=n,r=je(t),o=n.retryAfterSeconds??Ue(t),s=Fe(t),a=s===void 0?void 0:Le.get(s);if(a!==void 0)return new m(a,e,r,void 0,s);switch(e){case 304:return new m("not_modified",e,r);case 400:case 422:return new m("invalid",e,r,void 0,s);case 403:return new m("forbidden",e,r,void 0,s);case 404:return new m("not_found",e,r,void 0,s);case 402:return new m("insufficient_funds",e,r,void 0,s);case 409:return new m("conflict",e,r,void 0,s);case 412:return new m("precondition_failed",e,r,void 0,s);case 413:return new m("too_large",e,r,void 0,s);case 429:return new m("rate_limited",e,r,o,s);default:return new m("unavailable",e,r,o,s)}}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 Me(n){let t=n?.error?.details;return t===null?void 0:t}function Fe(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 Be(n){let e=n.lastIndexOf("@");return (e===-1?n:`***@${n.slice(e+1)}`).slice(0,200)}var Ne=new Set(j);function De(n){if(!n)return {};let e={};for(let[t,r]of Object.entries(n))Ne.has(t.toLowerCase())&&(e[t.toLowerCase()]=r);return e}function Q(n){let e=n.fetch??globalThis.fetch.bind(globalThis);return z(async(t,r)=>{let o;try{o=new URL(n.baseUrl.replace(/\/+$/,""));}catch{throw new p("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 s;try{s=new URL(o.href.replace(/\/+$/,"")+t.path);}catch{throw new p(`${JSON.stringify(typeof t.path=="string"?Be(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(s.protocol!==o.protocol||s.host!==o.host)throw new p(`${JSON.stringify(s.pathname)} resolves to ${s.protocol}//${s.host}, not ${o.protocol}//${o.host}. A request path may not change the request's origin \u2014 it carries the play token.`);if(s.username!==""||s.password!==""){let f=o.username!==""||o.password!=="",v=s.username!==o.username||s.password!==o.password,y=f?v?"baseUrl (and possibly the request path)":"baseUrl":"request path";throw new p(`the ${y} puts credentials in the URL, which cannot be fetched (${t.method} ${s.pathname}). The value is withheld here rather than written to logs. This is a malformed request, not a server failure.`)}for(let[f,v]of Object.entries(n.defaultQuery??{}))s.searchParams.has(f)||s.searchParams.set(f,v);let a=t.bytes,l=t.bytes===void 0?void 0:"application/octet-stream";try{t.body!==void 0&&(a=JSON.stringify(t.body),l="application/json");}catch(f){throw new p(`the body of ${t.method} ${JSON.stringify(s.pathname)} could not be serialised to JSON: ${String(f)}. This is a bug in the request, not a server failure \u2014 retrying sends the same unserialisable value.`)}let d=await e(s.toString(),{method:t.method,headers:{authorization:`Bearer ${r}`,...l===void 0?{}:{"content-type":l},...De(t.headers)},body:a,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"&&d.status>=200&&d.status<300)c=new Uint8Array(await d.arrayBuffer());else {let f=await d.text();if(f.length>0)try{c=JSON.parse(f);}catch{c=f;}}let g=d.headers.get("etag"),b=He(d.headers.get("retry-after")),x=d.headers.get("x-gem-invocation-id");return {status:d.status,body:c,...g===null?{}:{etag:g},...b===void 0?{}:{retryAfterSeconds:b},...x===null||x===""?{}:{invocationId:x}}},n)}function He(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 Ve="gem-web-bridge";var O=65536,Z=8,M=5e3,ee=1024;function B(n){return Object.freeze(Object.assign(Object.create(null),n))}B({"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.requestShare":6,"gem.frameStats":120,"gem.error":60,"gem.requestPurchase":12,"gem.purchaseResult":30,"gem.deviceSettings.put":30,"gem.deviceSettings.result":30,"gem.requestAd":6,"gem.adResult":12,"gem.requestSignIn":6,"gem.signInResult":12,"gem.requestFriendChallenge":12,"gem.friendChallengeResult":30,__malformed:60});B({"gem.requestAd":"ads","gem.adResult":"ads","gem.requestSignIn":"signIn","gem.signInResult":"signIn","gem.requestPurchase":"purchases","gem.purchaseResult":"purchases","gem.requestFriendChallenge":"friendChallenges","gem.friendChallengeResult":"friendChallenges","gem.devtools":"devtools","gem.screenshot":"screenshot","gem.screenshot.denied":"screenshot","gem.requestContext":"feedbackContext","gem.gameContext":"feedbackContext","gem.roomEvent":"rooms","gem.signal":"p2p","gem.signalEvent":"p2p","gem.dedicatedOffer":"dedicated","gem.dedicatedEvent":"dedicated","gem.clusterTarget":"clusterTarget","gem.partyRequest":"parties","gem.partyResult":"parties","gem.autoStartFailedEvent":"autoStartFailure","gem.seatedEvent":"partySeating","gem.socketState":"socketState","gem.audioState":"audioState","gem.rewardCue":"rewardCue","gem.frameStats":"frameStats","gem.engaged":"engagement","gem.viewport":"viewport","gem.walletDisplay":"walletDisplay","gem.requestLocalServer":"localHost","gem.localServer":"localHost","gem.localServer.denied":"localHost","gem.cohorts":"cohorts","gem.earnAllowanceChanged":"earnAllowance","gem.deviceSettings":"deviceSettings","gem.deviceSettings.put":"deviceSettings","gem.deviceSettings.result":"deviceSettings","gem.requestShare":"share"});function ze(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 Ke(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 Ye(n){return /^[a-z]{2,8}(-[a-z0-9]{1,8})*$/i.test(n)}function Je(n){return /^[a-z_]+$/.test(n)}function U(n,e,t){if(e>Z)return `nesting deeper than ${Z}`;if(++t.nodes>M)return `more than ${M} 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>ee)return `an array of ${n.length} entries, over the ${ee} limit`;t.bytes+=2;for(let l of n){let d=U(l,e+1,t);if(d)return d}return null}let s=Object.getPrototypeOf(n);if(s!==Object.prototype&&s!==null)return "a value that is not a plain object";t.bytes+=2;let a=n;for(let l in a){if(!Object.prototype.hasOwnProperty.call(a,l))continue;if(++t.nodes>M)return `more than ${M} values`;if(t.bytes+=l.length*3+4,t.bytes>O)return `over the ${O} byte limit`;let d=U(a[l],e+1,t);if(d)return d}return null}function Xe(n){let e={nodes:0,bytes:0,seen:new Set},t=U(n,0,e);return t?`message contains ${t}`:e.bytes>O?`message is over the ${O} byte limit`:null}var Qe={origin:[ze,"not a well-formed origin"],url:[Ke,"not a safe absolute http(s) URL"],bcp47:[Ye,"not a well-formed BCP 47 tag"],code:[Je,"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}`,s=n[r.n];if(s==null){if(r.o)continue;return `${o}: required`}let a=te(s,r,o);if(a)return a}return null}function te(n,e,t){switch(e.k){case "string":{if(typeof n!="string")return `${t}: expected string`;if(n.length>e.max)return `${t}: exceeds ${e.max} characters`;if(e.f){let[r,o]=Qe[e.f];if(!r(n))return `${t}: ${o}`}return null}case "int":return typeof n!="number"||!Number.isInteger(n)?`${t}: expected integer`:n<e.lo||n>e.hi?`${t}: out of range ${e.lo}..${e.hi}`:null;case "boolean":return typeof n=="boolean"?null:`${t}: expected boolean`;case "enum":{let r=e.v;return r.includes(n)?null:`${t}: not one of ${r.join("|")}`}case "object":return typeof n!="object"||n===null||Array.isArray(n)?`${t}: expected object`:ne(n,e.fs,t);case "json":return typeof n!="object"||n===null||Array.isArray(n)?`${t}: expected a plain object`:null;case "array":{if(!Array.isArray(n))return `${t}: expected array`;if(n.length>e.max)return `${t}: exceeds ${e.max} items`;let r=e.it,o=`${t}[]`;for(let s of n){if(s==null){if(r.o)continue;return `${o}: required`}let a=te(s,r,o);if(a)return a}return null}default:{let r=e.k;return `${t}: unknown kind ${String(r)}`}}}function u(n,e){return t=>{let r=Xe(t);if(r)return r;if(typeof t!="object"||t===null||Array.isArray(t))return "message: expected object";let o=t;return o.gem!==Ve?"gem: wrong protocol marker":o.type!==n?`type: expected ${n}`:ne(o,e,"")}}var Ze=u("gem.handshake",[{n:"versions",k:"object",fs:[{n:"min",k:"int",lo:1,hi:1e3},{n:"max",k:"int",lo:1,hi:1e3}]},{n:"capabilities",k:"array",o:1,max:64,it:{n:"",k:"string",max:64}},{n:"embedder",k:"string",max:2048,f:"origin"},{n:"unbidden",k:"boolean",o:1}]),en=u("gem.handshake.accept",[{n:"v",k:"int",lo:1,hi:1e3},{n:"capabilities",k:"array",o:1,max:64,it:{n:"",k:"string",max:64}}]),nn=u("gem.token",[{n:"token",k:"string",max:4096},{n:"requestId",k:"string",o:1,max:64},{n:"generation",k:"int",lo:0,hi:2147483647},{n:"apiBaseUrl",k:"string",o:1,max:512,f:"url"},{n:"playerId",k:"string",max:64},{n:"gameId",k:"string",max:64},{n:"channel",k:"enum",v:["dev","test","release"]},{n:"gameVersion",k:"string",o:1,max:64},{n:"expiresAt",k:"int",lo:0,hi:4102444800},{n:"chainEndsAt",k:"int",lo:0,hi:4102444800},{n:"allowDevTools",k:"boolean",o:1}]),tn=u("gem.token.denied",[{n:"requestId",k:"string",max:64},{n:"retryable",k:"boolean"},{n:"retryAfterMs",k:"int",o:1,lo:0,hi:36e5},{n:"reason",k:"enum",v:["chain_exhausted","unavailable"]},{n:"correlationId",k:"string",max:64}]),rn=u("gem.player",[{n:"untrusted",k:"object",fs:[{n:"displayName",k:"string",max:64},{n:"displayTag",k:"string",o:1,max:80},{n:"displayHandle",k:"string",max:80}]},{n:"playerId",k:"string",o:1,max:64},{n:"discriminator",k:"string",o:1,max:8},{n:"avatarIconUrl",k:"string",o:1,max:2048,f:"url"},{n:"badges",k:"array",o:1,max:2,it:{n:"",k:"object",fs:[{n:"itemId",k:"string",max:64},{n:"iconUrl",k:"string",max:2048,f:"url"}]}},{n:"displayTag",k:"string",max:8},{n:"avatarUrl",k:"string",o:1,max:2048,f:"url"},{n:"boost",k:"object",o:1,fs:[{n:"multipliers",k:"array",max:8,it:{n:"",k:"object",fs:[{n:"currencyId",k:"string",max:64},{n:"currencySlug",k:"string",max:32},{n:"multiplierBp",k:"int",lo:1e4,hi:1e6}]}},{n:"expiresInDays",k:"int",o:1,lo:1,hi:7}]}]),on=u("gem.pause",[{n:"paused",k:"boolean"}]),sn=u("gem.prefs",[{n:"reducedMotion",k:"boolean"},{n:"muted",k:"boolean"},{n:"showFrameStats",k:"boolean",o:1},{n:"locale",k:"string",max:35,f:"bcp47"}]),an=u("gem.cohorts",[{n:"cohorts",k:"array",max:8,it:{n:"",k:"object",fs:[{n:"experimentId",k:"string",max:36},{n:"variantKey",k:"string",max:32}]}}]),ln=u("gem.earnAllowanceChanged",[]),dn=u("gem.viewport",[{n:"insets",k:"object",fs:[{n:"top",k:"int",lo:0,hi:4096},{n:"right",k:"int",lo:0,hi:4096},{n:"bottom",k:"int",lo:0,hi:4096},{n:"left",k:"int",lo:0,hi:4096}]},{n:"reserved",k:"array",o:1,max:4,it:{n:"",k:"object",fs:[{n:"x",k:"int",lo:0,hi:16384},{n:"y",k:"int",lo:0,hi:16384},{n:"width",k:"int",lo:0,hi:16384},{n:"height",k:"int",lo:0,hi:16384}]}}]),un=u("gem.deviceSettings",[{n:"settings",k:"json",o:1}]),cn=u("gem.willTerminate",[{n:"reason",k:"enum",v:["grant_expiring","session_ended","navigating","kill_switch"]},{n:"graceMs",k:"int",lo:0,hi:6e4}]),gn=u("gem.roomEvent",[{n:"event",k:"enum",v:["updated","match_started","match_ready","match_failed","version_stale"]},{n:"roomId",k:"string",max:64},{n:"matchId",k:"string",o:1,max:64},{n:"version",k:"int",o:1,lo:0,hi:2147483647},{n:"reason",k:"string",o:1,max:64},{n:"platform",k:"enum",o:1,v:["universal","mobile"]}]),mn=u("gem.socketState",[{n:"connected",k:"boolean"},{n:"reason",k:"enum",o:1,v:["connecting","dropped","watchdog","terminal"]}]),pn=u("gem.seatedEvent",[{n:"roomId",k:"string",max:64}]),yn=u("gem.autoStartFailedEvent",[{n:"roomId",k:"string",max:64},{n:"code",k:"string",max:64}]),fn=u("gem.signalEvent",[{n:"event",k:"enum",v:["hello","offer","answer","ice","peerJoined","peerLeft","migration","matchEnded","error"]},{n:"matchId",k:"string",max:64},{n:"data",k:"json"}]),hn=u("gem.dedicatedEvent",[{n:"event",k:"enum",v:["answer","error","matchEnded"]},{n:"matchId",k:"string",max:64},{n:"sdp",k:"string",o:1,max:10240},{n:"sessionId",k:"string",o:1,max:64},{n:"code",k:"string",o:1,max:64},{n:"message",k:"string",o:1,max:256},{n:"reason",k:"string",o:1,max:64}]),_n=u("gem.partyResult",[{n:"requestId",k:"string",max:64},{n:"partyId",k:"string",o:1,max:64}]),bn=u("gem.clusterTarget",[{n:"clusterTargetId",k:"string",max:64},{n:"clusterTargetIds",k:"array",o:1,max:3,it:{n:"",k:"string",max:64}}]),vn=u("gem.devtools",[{n:"action",k:"enum",v:["open","close","toggle"]}]),Rn=u("gem.screenshot",[{n:"maxWidth",k:"int",lo:1,hi:7680},{n:"maxHeight",k:"int",lo:1,hi:4320}]),xn=u("gem.screenshot.denied",[{n:"reason",k:"enum",v:["not_wired","no_source","unsupported","unreadable","tainted","too_large","busy","declined","failed"]},{n:"retryable",k:"boolean"}]),Sn=u("gem.requestContext",[]),kn=u("gem.gameContext",[{n:"context",k:"json"}]),wn=u("gem.signal",[{n:"signal",k:"enum",v:["join","offer","answer","ice","migrationAck","hostUnreachable"]},{n:"matchId",k:"string",max:64},{n:"data",k:"json"}]),An=u("gem.dedicatedOffer",[{n:"matchId",k:"string",max:64},{n:"sdp",k:"string",max:10240},{n:"intent",k:"enum",v:["initial","ice_restart","full_reconnect"]}]),Tn=u("gem.partyRequest",[{n:"requestId",k:"string",max:64}]),Pn=u("gem.ready",[]),On=u("gem.engaged",[]),Gn=u("gem.progress",[{n:"loaded",k:"int",lo:0,hi:1099511627776},{n:"total",k:"int",lo:0,hi:1099511627776}]),En=u("gem.requestToken",[{n:"requestId",k:"string",max:64},{n:"reason",k:"enum",v:["initial","expiring","rejected"]}]),Cn=u("gem.requestLocalServer",[{n:"requestId",k:"string",max:64},{n:"gameRoomId",k:"string",max:64}]),In=u("gem.localServer",[{n:"requestId",k:"string",max:64},{n:"serverId",k:"string",o:1,max:128}]),qn=u("gem.localServer.denied",[{n:"requestId",k:"string",max:64},{n:"retryable",k:"boolean"},{n:"reason",k:"enum",v:["refused","unavailable"]}]),Ln=u("gem.exit",[{n:"reason",k:"string",o:1,max:64}]),$n=u("gem.openExternal",[{n:"url",k:"string",max:2048,f:"url"}]),jn=u("gem.requestFullscreen",[{n:"enabled",k:"boolean"}]),Mn=u("gem.audioState",[{n:"muted",k:"boolean"}]),Fn=u("gem.rewardCue",[{n:"currencySlug",k:"string",max:32},{n:"expected",k:"int",o:1,lo:1,hi:1e9},{n:"origin",k:"object",o:1,fs:[{n:"x",k:"int",lo:0,hi:16384},{n:"y",k:"int",lo:0,hi:16384}]}]),Un=u("gem.walletDisplay",[{n:"visible",k:"boolean"},{n:"currencies",k:"array",o:1,max:8,it:{n:"",k:"string",max:64}},{n:"score",k:"boolean",o:1}]),Bn=u("gem.requestShare",[{n:"params",k:"array",max:16,it:{n:"",k:"object",fs:[{n:"key",k:"string",max:64},{n:"value",k:"string",max:512}]}}]),Nn=u("gem.frameStats",[{n:"fps",k:"int",lo:0,hi:1e3},{n:"frameTimeP95Ms",k:"int",lo:0,hi:1e5}]),Dn=u("gem.error",[{n:"code",k:"enum",v:["version_mismatch","handshake_timeout","handshake_duplicate","invalid_message","rate_limited","token_unavailable","unsupported","unsupported_capability","internal"]},{n:"message",k:"string",o:1,max:256}]),Hn=u("gem.requestPurchase",[{n:"requestId",k:"string",max:64},{n:"purchaseKind",k:"enum",v:["item","recipe"]},{n:"targetId",k:"string",max:64},{n:"currencySlug",k:"string",max:32},{n:"quantity",k:"int",o:1,lo:1,hi:10},{n:"catalogId",k:"string",o:1,max:64}]),Vn=u("gem.purchaseResult",[{n:"requestId",k:"string",max:64},{n:"outcome",k:"enum",v:["ok","declined","unavailable"]},{n:"reason",k:"string",o:1,max:64,f:"code"},{n:"purchaseId",k:"string",o:1,max:64}]),Wn=u("gem.deviceSettings.put",[{n:"requestId",k:"string",max:64},{n:"settings",k:"json"}]),zn=u("gem.deviceSettings.result",[{n:"requestId",k:"string",max:64},{n:"outcome",k:"enum",v:["stored","too_large","unavailable"]}]),Kn=u("gem.requestAd",[{n:"requestId",k:"string",max:64},{n:"placement",k:"string",max:32},{n:"format",k:"enum",v:["interstitial","rewarded"]}]),Yn=u("gem.adResult",[{n:"requestId",k:"string",max:64},{n:"outcome",k:"enum",v:["shown","no_ad","unavailable"]}]),Jn=u("gem.requestSignIn",[{n:"requestId",k:"string",max:64}]),Xn=u("gem.signInResult",[{n:"requestId",k:"string",max:64},{n:"outcome",k:"enum",v:["signed_in","declined","unavailable"]}]),Qn=u("gem.requestFriendChallenge",[{n:"requestId",k:"string",max:64},{n:"playerId",k:"string",max:64},{n:"template",k:"string",max:64},{n:"params",k:"json",o:1}]),Zn=u("gem.friendChallengeResult",[{n:"requestId",k:"string",max:64},{n:"outcome",k:"enum",v:["accepted","cancelled","refused","unavailable","rate_limited","invalid"]},{n:"code",k:"string",o:1,max:64},{n:"param",k:"string",o:1,max:64},{n:"channel",k:"string",o:1,max:16},{n:"configVersion",k:"int",o:1,lo:0,hi:9007199254740991},{n:"retryAfterMs",k:"int",o:1,lo:0,hi:864e5},{n:"detail",k:"string",o:1,max:300}]);B({"gem.handshake":Ze,"gem.handshake.accept":en,"gem.token":nn,"gem.token.denied":tn,"gem.player":rn,"gem.pause":on,"gem.prefs":sn,"gem.cohorts":an,"gem.earnAllowanceChanged":ln,"gem.viewport":dn,"gem.deviceSettings":un,"gem.willTerminate":cn,"gem.roomEvent":gn,"gem.socketState":mn,"gem.seatedEvent":pn,"gem.autoStartFailedEvent":yn,"gem.signalEvent":fn,"gem.dedicatedEvent":hn,"gem.partyResult":_n,"gem.clusterTarget":bn,"gem.devtools":vn,"gem.screenshot":Rn,"gem.screenshot.denied":xn,"gem.requestContext":Sn,"gem.gameContext":kn,"gem.signal":wn,"gem.dedicatedOffer":An,"gem.partyRequest":Tn,"gem.ready":Pn,"gem.engaged":On,"gem.progress":Gn,"gem.requestToken":En,"gem.requestLocalServer":Cn,"gem.localServer":In,"gem.localServer.denied":qn,"gem.exit":Ln,"gem.openExternal":$n,"gem.requestFullscreen":jn,"gem.audioState":Mn,"gem.rewardCue":Fn,"gem.walletDisplay":Un,"gem.requestShare":Bn,"gem.frameStats":Nn,"gem.error":Dn,"gem.requestPurchase":Hn,"gem.purchaseResult":Vn,"gem.deviceSettings.put":Wn,"gem.deviceSettings.result":zn,"gem.requestAd":Kn,"gem.adResult":Yn,"gem.requestSignIn":Jn,"gem.signInResult":Xn,"gem.requestFriendChallenge":Qn,"gem.friendChallengeResult":Zn});var G={now:()=>Date.now(),setTimeout:(n,e)=>setTimeout(n,e),clearTimeout:n=>clearTimeout(n)};var et=1e4;function re(n,e){return N(n,e)}function N(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=a=>({token:a.token,expiresAt:a.expiresAt,chainEndsAt:Number.POSITIVE_INFINITY}),r=null,o=new $({clock:e.clock,...e.onStateChange===void 0?{}:{onStateChange:e.onStateChange},request:()=>new Promise((a,l)=>{let d=e.clock.setTimeout(()=>{r=null,l({reason:"unavailable",retryable:true});},e.timeoutMs??et);r={resolve:c=>{e.clock.clearTimeout(d),a(c);},reject:l,timer:d};})}),s=n.onServerToken(a=>{let l=t(a),d=r;if(d){r=null,d.resolve(l);return}o.accept(l);});return {source:o,dispose(){s(),r&&(e.clock.clearTimeout(r.timer),r.reject({reason:"unavailable",retryable:false}),r=null);}}}var H={};Re(H,{acceptTransfer:()=>nt,addEntityProgression:()=>tt,adminAction:()=>rt,cancelInventoryTransfer:()=>ot,claimEntityProgressionRewards:()=>st,closeGameRoom:()=>it,createEntityBatchOrder:()=>at,createEntityOrder:()=>lt,createSession:()=>dt,deleteEntityGameSetting:()=>ut,deleteEntitySave:()=>ct,deleteSession:()=>gt,deleteShowcaseValue:()=>mt,executeEntityRecipe:()=>pt,finalizeSaveUpload:()=>yt,getChannelAssignment:()=>ft,getDropRates:()=>ht,getEntityCurrency:()=>_t,getEntityGameSetting:()=>bt,getEntityInventory:()=>vt,getEntityInventoryItem:()=>Rt,getEntityLeaderboard:()=>xt,getEntityOrder:()=>St,getEntityProgression:()=>kt,getEntityRecipeAvailability:()=>wt,getEntityRecipeUsage:()=>At,getEntitySave:()=>Tt,getEvent:()=>Pt,getGameRoomV2:()=>Ot,getLeaderboard:()=>Gt,getPlayerGameProfile:()=>Et,getPurchaseCatalog:()=>Ct,getResolvedTemplate:()=>It,getRoomArgs:()=>qt,getShowcaseValue:()=>Lt,getTransferDetails:()=>$t,ingestAnalyticsEvents:()=>D,initiateInventoryTransfer:()=>jt,invokeFunction:()=>Mt,kickPlayer:()=>Ft,listChallenges:()=>Ut,listEntityGameSettings:()=>Bt,listEntityOrders:()=>Nt,listEntityProgressions:()=>Dt,listEntitySaves:()=>Ht,listEvents:()=>Vt,listGameRooms:()=>Wt,listResolvedTemplates:()=>zt,listTransfers:()=>Kt,maxEntityProgression:()=>Yt,putEntityGameSetting:()=>Jt,putRoomArgs:()=>Xt,putShowcaseValue:()=>Qt,rejectTransfer:()=>Zt,requestSaveUploadUrl:()=>er,resetEntityProgression:()=>nr,simulateEntityOrder:()=>tr,transferHostV2:()=>rr,updateGameRoomV2:()=>or});function i(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 nt(n,e,t){let r=`/v1/inventory/transfers/${i(e)}/accept`;return n.client.post(r,void 0,t?.signal)}async function tt(n,e,t,r,o,s){let a=`/v1/inventory/${i(e)}/${i(t)}/progressions/${i(r)}/add`;return n.client.post(a,o,s?.signal)}async function rt(n,e,t,r){let o=`/v1/voice/sessions/${i(e)}/admin`;return n.client.post(o,t,r?.signal)}async function ot(n,e,t){let r=`/v1/inventory/transfers/${i(e)}/cancel`;return n.client.post(r,void 0,t?.signal)}async function st(n,e,t,r,o,s){let a=`/v1/inventory/${i(e)}/${i(t)}/progressions/${i(r)}/claim`;return n.client.post(a,o,s?.signal)}async function it(n,e,t){let r=`/v1/games/${i(n.gameId())}/game-rooms/${i(e)}`;return n.client.delete(r,t?.signal)}async function at(n,e,t,r,o){let s=`/v1/inventory/${i(e)}/${i(t)}/orders/batch`;return n.client.post(s,r,o?.signal,{...o?.ifMatch===void 0?{}:{ifMatch:o.ifMatch}})}async function lt(n,e,t,r,o){let s=`/v1/inventory/${i(e)}/${i(t)}/orders`;return n.client.post(s,r,o?.signal,{...o?.ifMatch===void 0?{}:{ifMatch:o.ifMatch}})}async function dt(n,e,t){return n.client.post("/v1/voice/sessions",e,t?.signal)}async function ut(n,e,t,r,o){let s=`/v1/settings/${i(e)}/${i(t)}/${i(r)}`;return n.client.delete(s,o?.signal)}async function ct(n,e,t,r,o){let s=`/v1/saves/${i(e)}/${i(t)}/${i(r)}`;return n.client.delete(s,o?.signal)}async function gt(n,e,t){let r=`/v1/voice/sessions/${i(e)}`;return n.client.delete(r,t?.signal)}async function mt(n,e,t,r){let o=`/v1/showcase/players/${i(e)}/${i(t)}`;return n.client.delete(o,r?.signal)}async function pt(n,e,t,r,o){let s=`/v1/inventory/${i(e)}/${i(t)}/recipes/execute`;return n.client.post(s,r,o?.signal,{...o?.ifMatch===void 0?{}:{ifMatch:o.ifMatch}})}async function yt(n,e,t,r,o,s){let a=`/v1/saves/${i(e)}/${i(t)}/${i(r)}/finalize`;return n.client.post(a,o,s?.signal)}async function ft(n,e,t){let r=`/v1/games/${i(n.gameId())}/config/channels/${i(e)}`;return n.client.getWithEtag(r,{...t?.signal===void 0?{}:{signal:t.signal},...t?.ifNoneMatch===void 0?{}:{ifNoneMatch:t.ifNoneMatch}})}async function ht(n,e,t){let r=`/v1/inventory/loot-tables/${i(e)}/drop-rates`;return n.client.get(r,t?.signal)}async function _t(n,e,t,r,o){let s=`/v1/inventory/${i(e)}/${i(t)}/currencies/${i(r)}`;return n.client.get(s,o?.signal)}async function bt(n,e,t,r,o){let s=`/v1/settings/${i(e)}/${i(t)}/${i(r)}`;return n.client.getWithEtag(s,{...o?.signal===void 0?{}:{signal:o.signal},...o?.ifNoneMatch===void 0?{}:{ifNoneMatch:o.ifNoneMatch}})}async function vt(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 s=o.toString(),a=`/v1/inventory/${i(e)}/${i(t)}`+(s?`?${s}`:"");return n.client.get(a,r?.signal)}async function Rt(n,e,t,r,o){let s=`/v1/inventory/${i(e)}/${i(t)}/items/${i(r)}`;return n.client.get(s,o?.signal)}async function xt(n,e,t,r,o){let s=new URLSearchParams;o?.bucket_1!==void 0&&s.set("bucket_1",String(o?.bucket_1)),o?.bucket_2!==void 0&&s.set("bucket_2",String(o?.bucket_2)),o?.limit!==void 0&&s.set("limit",String(o?.limit));let a=s.toString(),l=`/v1/leaderboards/${i(e)}/${i(t)}/${i(r)}`+(a?`?${a}`:"");return n.client.get(l,o?.signal)}async function St(n,e,t,r,o){let s=`/v1/inventory/${i(e)}/${i(t)}/orders/${i(r)}`;return n.client.get(s,o?.signal)}async function kt(n,e,t,r,o){let s=`/v1/inventory/${i(e)}/${i(t)}/progressions/${i(r)}`;return n.client.get(s,o?.signal)}async function wt(n,e,t,r,o,s){let a=`/v1/inventory/${i(e)}/${i(t)}/catalogs/${i(r)}/recipes/${i(o)}/availability`;return n.client.get(a,s?.signal)}async function At(n,e,t,r){let o=new URLSearchParams;r?.limit!==void 0&&o.set("limit",String(r?.limit));let s=o.toString(),a=`/v1/inventory/${i(e)}/${i(t)}/recipe-usage`+(s?`?${s}`:"");return n.client.get(a,r?.signal)}async function Tt(n,e,t,r,o){let s=`/v1/saves/${i(e)}/${i(t)}/${i(r)}`;return n.client.getWithEtag(s,{...o?.signal===void 0?{}:{signal:o.signal},...o?.ifNoneMatch===void 0?{}:{ifNoneMatch:o.ifNoneMatch}})}async function Pt(n,e,t){let r=`/v1/events/${i(e)}`;return n.client.get(r,t?.signal)}async function Ot(n,e,t){let r=`/v2/games/${i(n.gameId())}/game-rooms/${i(e)}`;return n.client.getWithEtag(r,{...t?.signal===void 0?{}:{signal:t.signal},...t?.ifNoneMatch===void 0?{}:{ifNoneMatch:t.ifNoneMatch}})}async function Gt(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));let o=r.toString(),s=`/v1/leaderboards/${i(e)}`+(o?`?${o}`:"");return n.client.get(s,t?.signal)}async function Et(n,e,t){let r=`/v1/profiles/players/${i(e)}`;return n.client.get(r,t?.signal)}async function Ct(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 It(n,e,t){let r=`/v1/game-room-templates/${i(e)}`;return n.client.get(r,t?.signal)}async function qt(n,e,t){let r=`/v1/games/${i(n.gameId())}/game-rooms/${i(e)}/room-args`;return n.client.get(r,t?.signal)}async function Lt(n,e,t,r){let o=`/v1/showcase/players/${i(e)}/${i(t)}`;return n.client.get(o,r?.signal)}async function $t(n,e,t){let r=`/v1/inventory/transfers/${i(e)}`;return n.client.get(r,t?.signal)}async function D(n,e,t){let r=`/v1/games/${i(n.gameId())}/analytics/events`;return n.client.post(r,e,t?.signal,{replaySafe:true})}async function jt(n,e,t){return n.client.post("/v1/inventory/transfers",e,t?.signal)}async function Mt(n,e,t){return n.client.postBytes("/v1/functions/invoke",e,t?.signal)}async function Ft(n,e,t,r){let o=`/v1/games/${i(n.gameId())}/game-rooms/${i(e)}/kick/${i(t)}`;return n.client.post(o,void 0,r?.signal)}async function Ut(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 Bt(n,e,t,r){let o=`/v1/settings/${i(e)}/${i(t)}`;return n.client.get(o,r?.signal)}async function Nt(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 s=o.toString(),a=`/v1/inventory/${i(e)}/${i(t)}/orders`+(s?`?${s}`:"");return n.client.get(a,r?.signal)}async function Dt(n,e,t,r){let o=`/v1/inventory/${i(e)}/${i(t)}/progressions`;return n.client.get(o,r?.signal)}async function Ht(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 s=o.toString(),a=`/v1/saves/${i(e)}/${i(t)}`+(s?`?${s}`:"");return n.client.get(a,r?.signal)}async function Vt(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 Wt(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/${i(n.gameId())}/game-rooms`+(r?`?${r}`:"");return n.client.get(o,e?.signal)}async function zt(n,e){return n.client.get("/v1/game-room-templates",e?.signal)}async function Kt(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 Yt(n,e,t,r,o,s){let a=`/v1/inventory/${i(e)}/${i(t)}/progressions/${i(r)}/max`;return n.client.post(a,o,s?.signal)}async function Jt(n,e,t,r,o,s){let a=`/v1/settings/${i(e)}/${i(t)}/${i(r)}`;return n.client.put(a,o,s?.signal,{...s?.ifMatch===void 0?{}:{ifMatch:s.ifMatch}})}async function Xt(n,e,t,r){let o=`/v1/games/${i(n.gameId())}/game-rooms/${i(e)}/room-args`;return n.client.put(o,t,r?.signal)}async function Qt(n,e,t,r,o){let s=`/v1/showcase/players/${i(e)}/${i(t)}`;return n.client.put(s,r,o?.signal)}async function Zt(n,e,t){let r=`/v1/inventory/transfers/${i(e)}/reject`;return n.client.post(r,void 0,t?.signal)}async function er(n,e,t,r,o,s){let a=`/v1/saves/${i(e)}/${i(t)}/${i(r)}/upload-url`;return n.client.post(a,o,s?.signal,{replaySafe:true})}async function nr(n,e,t,r,o,s){let a=`/v1/inventory/${i(e)}/${i(t)}/progressions/${i(r)}/reset`;return n.client.post(a,o,s?.signal)}async function tr(n,e,t,r,o){let s=`/v1/inventory/${i(e)}/${i(t)}/orders/simulate`;return n.client.post(s,r,o?.signal)}async function rr(n,e,t,r){let o=`/v2/games/${i(n.gameId())}/game-rooms/${i(e)}/transfer/${i(t)}`;return n.client.post(o,void 0,r?.signal)}async function or(n,e,t,r){let o=`/v2/games/${i(n.gameId())}/game-rooms/${i(e)}`;return n.client.patch(o,t,r?.signal,{...r?.ifMatch===void 0?{}:{ifMatch:r.ifMatch}})}var oe="gem_";var ar=1e4,lr=50,dr=1e3,ur=65536-4*1024,se=n=>typeof n=="number"?n:0,cr=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 gr(n){return n?.retryable===true}function mr(n,e){let t=n??{},r=Array.isArray(t.rejected)?t.rejected.map(o=>{let s=o??{};return {index:se(s.index),code:cr(s.code)}}):[];return {accepted:se(t.accepted),rejected:r,dropped:e,duplicate:t.duplicate===true}}function ae(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 le(n){let e=Math.max(1,Math.floor(n.maxQueue??dr)),t={client:n.client,gameId:()=>n.gameId},r=[],o=0,s=null,a=false,l=false,d=false,c=false,g=y=>{n.log?.(y);},b=()=>{s!==null&&(n.clock.clearTimeout(s),s=null);},x=()=>{s!==null||a||l||(s=n.clock.setTimeout(()=>{s=null,v().catch(()=>{});},ar));},f=()=>{let y=Math.min(r.length,100),h=128;for(let w=0;w<y;w+=1){let A=r[w];if(A===void 0)break;if(h+=JSON.stringify(ae(A,0)).length+1,h>ur)return Math.max(1,w)}return y};async function v(y){if(r.length===0)return {accepted:0,rejected:[],dropped:0,duplicate:false};b();let h=r.splice(0,f()),w=o;o=0;let A=Math.round(n.clock.now()),L={batch_id:ie(),sent_at_ms:A,events:h.map(S=>ae(S,A))};l=true;try{let S=await D(t,L,y===void 0?void 0:{signal:y}),T=mr(S,w);for(let be of T.rejected)g(`[gem] analytics: an event was refused (${be.code}). See the analytics_events section of your game config.`);return T}catch(S){if(gr(S))for(r=[...h,...r],o+=w;r.length>e;)r.shift(),o+=1;else g(`[gem] analytics: ${h.length} event(s) were discarded \u2014 the platform refused the batch and will refuse it again: ${String(S)}`);throw S}finally{l=false,r.length>0&&x();}}return {track(y,h,w={}){if(a)return;if(typeof y!="string"||y===""){c||(c=true,g(`[gem] analytics: '${h}' 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(h.startsWith(oe)){d||(d=true,g(`[gem] analytics: '${h}' 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[S,T]of Object.entries(w))typeof T=="string"?A[S]=T:typeof T=="number"&&Number.isFinite(T)&&(L[S]=T);for(;r.length>=e;)r.shift(),o+=1;r.push({uid:ie(),playerId:y,name:h,atMs:n.clock.now(),dimensions:A,measures:L}),r.length>=lr?v().catch(()=>{}):x();},flush:y=>v(y),get pending(){return r.length},dispose(){a=true,b(),r=[],o=0;}}}var pr=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 m{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:pr.get(this.code))??super.retryable}},E=class{#e;constructor(e){this.#e=e;}async invoke(e,t={}){let r=yr(e),o;try{o=await this.#e(r,t.signal===void 0?{}:{signal:t.signal});}catch(s){throw s instanceof m?hr(s):s}return fr(o)}};function yr(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 p(`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 p(`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 fr(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 hr(n){let{details:e,invocationId:t}=X(n),o=e?.untrusted?.message,s=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 s=="string"?{failure:s}:{}})}var k=n=>typeof n=="string"?n:"",_r=/(?:Z|[+-]\d{2}:?\d{2})$/i;function de(n){let e=k(n);if(!_r.test(e))return 0;let t=Date.parse(e);return Number.isFinite(t)?Math.floor(t/1e3):0}var br=/^[0-9a-f]{1,64}$/,vr=/^[0-9a-f]{16}$/,Rr=/^[A-Za-z][A-Za-z0-9_+\-/]{0,63}$/,xr=/^(?:[01]\d|2[0-3]):[0-5]\d$/;function Sr(n){let e=k(n),t=/^(\d{4})-(\d{2})-(\d{2})$/.exec(e);if(!t)return;let[r,o,s]=[Number(t[1]),Number(t[2]),Number(t[3])],a=new Date(Date.UTC(r,o-1,s));return a.getUTCFullYear()===r&&a.getUTCMonth()===o-1&&a.getUTCDate()===s?e:void 0}var kr=4096,wr=new TextEncoder;function Ar(n){let e=k(n.challenge_data),t=k(n.challenge_data_hash);return e===""||!vr.test(t)?{}:wr.encode(e).length>kr?{}:{data:e,dataHash:t}}function Tr(n){let e=n??{},t=de(e.period_start_at),r=de(e.period_ends_at);if(t===0||r===0)return;let o=k(e.slug),s=k(e.seed),a=Sr(e.period_local_date),l=k(e.boundary),d=k(e.reset_time);return {id:k(e.progression_definition_id),...o===""?{}:{slug:o},window:k(e.window),periodStartAt:t,periodEndsAt:r,...a===void 0?{}:{periodLocalDate:a},boundary:Rr.test(l)?l:"",resetTime:xr.test(d)?d:"",seed:br.test(s)?s:"",...Ar(e)}}function ue(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 ce(n){let e=n??{};return Array.isArray(e.challenges)?e.challenges.map(Tr).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().");ue(r);let s=await n({player_id:t,...r===void 0?{}:{periods_back:r},...o===void 0?{}:{signal:o}});return ce(s)}}}function Pr(n){let e={};for(let[t,r]of Object.entries(H))if(typeof r=="function"){let o=r;e[t]=(...s)=>o(n,...s);}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=N(n,{clock:t,...e.onAuthStateChange===void 0?{}:{onStateChange:e.onAuthStateChange}}),s=Q({baseUrl:r,tokenSource:o.source,defaultQuery:{game_id:n.gameId,channel:n.channel},...e.fetch===void 0?{}:{fetch:e.fetch}}),a=new P({transport:s,clock:t}),l={gameId:n.gameId,channel:n.channel,matchId:n.matchId,...n.gameRoomId===void 0?{}:{gameRoomId:n.gameRoomId}},d=Pr({client:a,gameId:()=>l.gameId}),c=l.gameRoomId,g=n.endMatch,b=n.log,x=le({client:a,clock:t,gameId:l.gameId,...typeof b=="function"?{log:v=>b.call(n,v)}:{}});return {identity:l,client:a,api:d,match:{end:async()=>{if(g===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 g.call(n);}},analytics:x,functions:new E(d.invokeFunction),challenges:ge(d.listChallenges),...c===void 0?{}:{room:{get:v=>d.getGameRoomV2(c,v),args:async v=>{let y=await d.getGameRoomV2(c,v?.signal===void 0?{}:{signal:v.signal}),h=y.modified?y.body:void 0;if(h?.room_args==null||h.room_args_template==null)throw new m("not_found",404,"this room's template declares no room args",void 0,"room_args_not_defined");return {room_args:h.room_args,room_args_template:h.room_args_template}}}},dispose:()=>{x.dispose(),o.dispose();}}}var Or=["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"],Gr=new Set(Or);function me(n){return typeof n=="string"&&Gr.has(n)?n:"unknown"}var R=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 R(n)}var pe={toPlain(n){return R.unwrap(n)},compare(n,e,t){let r=n instanceof R?R.unwrap(n):n,o=e instanceof R?R.unwrap(e):e,s;try{s=new Intl.Collator(t);}catch{s=new Intl.Collator;}return s.compare(r,o)},equals(n,e){let t=n instanceof R?R.unwrap(n):n,r=e instanceof R?R.unwrap(e):e;return t.normalize("NFC")===r.normalize("NFC")}};var ye="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 V(n,e={}){let t=e.clock??G,r=()=>{let l=n();if(l===null)throw new Error(ye);return l},o=null,s=()=>{if(o===null)throw new Error(ye);return o};return {server:{get identity(){return s().identity},get client(){return s().client},get api(){return s().api},get match(){return s().match},get analytics(){return s().analytics},get functions(){return s().functions},get challenges(){return s().challenges},get room(){return s().room},dispose(){o?.dispose();},get sizeClass(){return r().sizeClass},get roomArgs(){return r().roomArgs},get roster(){return r().roster},players(){return r().players()},profile(l){let c=r().profile?.(l);if(!c)return null;let g=c.displayName;return typeof g!="string"||g===""?null:{displayName:q(g),...typeof c.displayTag=="string"&&c.displayTag!==""?{displayTag:q(c.displayTag)}:{},...typeof c.discriminator=="string"?{discriminator:c.discriminator}:{}}},playerNumber(l){return r().playerNumber?.(l)},send(l,d,c){c===void 0?r().send(l,d):r().send(l,d,c);},broadcast(l,d){d===void 0?r().broadcast(l):r().broadcast(l,d);},kick(l,d){d===void 0?r().kick(l):r().kick(l,d);},log(l){r().log(l);},warn(l){r().warn(l);}},attach:()=>{o=F(r(),{...e,clock:t});}}}function fe(n,e={}){let{server:t,attach:r}=V(()=>n,e);return r(),t}function Er(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:me(e)}}}function he(n,e={}){return ()=>{let t=null,{server:r,attach:o}=V(()=>t,e),s=n(r),a={async init(l){t=l,o(),await s.init?.();},async shutdown(l){let d=Er(l);try{await s.shutdown?.(d);}finally{r.dispose();}}};return s.join&&(a.join=(l,d)=>s.join?.(l,d)),s.leave&&(a.leave=(l,d)=>s.leave?.(l,d)),s.message&&(a.message=(l,d,c,g)=>s.message?.(l,d,c,g)),a}}var Cr=new Set(["unlocked","already_unlocked","suppressed"]);function _e(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"||!Cr.has(o.outcome)||typeof o.achievement_id!="string"||o.achievement_id==="")continue;let s=o.outcome;t.push({achievementId:o.achievement_id,progressionDefinitionId:typeof o.progression_definition_id=="string"?o.progression_definition_id:"",points:s==="unlocked"&&typeof o.points=="number"&&Number.isFinite(o.points)?o.points:0,outcome:s,...typeof o.reason=="string"?{reason:o.reason}:{}});}return t}
2
2
  export{_ as AuthError,j as CONDITIONAL_HEADERS,E as FunctionsApi,m as GemApiError,P as GemClient,I as GemFunctionError,R as PlayerText,p as TransportRefusal,_e as achievementReceipts,q as asPlayerText,F as createGemServer,re as createHostTokenSource,fe as createMatchServer,he as defineServer,G as systemClock,pe as text,K as toBase64};//# sourceMappingURL=gem-web-sdk.server.js.map
3
3
  //# sourceMappingURL=gem-web-sdk.server.js.map
package/dist/sdk.d.ts CHANGED
@@ -4234,6 +4234,9 @@ interface DeviceSettingsApi {
4234
4234
  wait(timeoutMs?: number): Promise<DeviceSettings | null>;
4235
4235
  put(settings: DeviceSettings): Promise<DeviceSettingsPutOutcome>;
4236
4236
  }
4237
+ declare class GemUnframedError extends Error {
4238
+ constructor();
4239
+ }
4237
4240
  declare const DEVICE_SETTINGS_MAX_BYTES = 16384;
4238
4241
  declare const ARCADE_EMBEDDERS: readonly string[];
4239
4242
  interface GemOptions {
@@ -4370,4 +4373,4 @@ interface ExitAnalytics {
4370
4373
  }
4371
4374
  declare function leaveAndExit(rooms: ExitRooms, bridge: ExitBridge | null, reason?: string, analytics?: ExitAnalytics): Promise<void>;
4372
4375
  declare function createGem(options?: GemOptions): Gem;
4373
- export { ARCADE_EMBEDDERS, type AccountApi, type AdFormat, type AdOutcome, type AdOutcomeKind, type AdRequest, type AdsApi, AnalyticsApi, type AnalyticsFlushOptions, type AnalyticsFlushResult, type AnalyticsOptions, type AnalyticsRejection$1 as AnalyticsRejection, type AnalyticsValue, AuthError, type AuthFailure, type AuthState, type Base64String, type BootMark, type BootTimeline, type BroadcastOptions, type BytesResponse, CONDITIONAL_HEADERS, type Challenge, type ChallengeWindow, ChallengesApi, type ClientOptions, type Clock, type ConditionalRequestHeaders, type ConfiguredPurchasePayment, type ConfiguredPurchaseRequest, type ConfiguredPurchaseResult, DEVICE_SETTINGS_MAX_BYTES, DedicatedServerError, type DedicatedServerFailure, type DedicatedServerSession, type DevToolsOpener, type DeviceSettings, type DeviceSettingsApi, type DeviceSettingsPutOutcome, type DirectPurchaseRequest, type DirectPurchaseResult, type EarnAllowance, type EarnAllowanceEvent, type EarnAllowancePeriod, type EarnAllowanceReadOptions, type EntityLeaderboard, type EntityLeaderboardEntry, type EntityLeaderboardOptions, type EntityType$1 as EntityType, type ExitAnalytics, type ExitBridge, type ExitRooms, type FrameState, type Friend, FriendChallengeError, type FriendChallengeErrorCode, type FriendChallengeOutcome, type FriendChallengeOutcomeKind, type FriendChallengeRequest, FriendsApi, type FriendsPage, type FunctionFailure, type FunctionInvokeOptions, type FunctionResult, FunctionsApi, type GameApi, type GameConfig, type GameServerLink, type Gem, GemApiError, GemClient, type GemCohort, type GemCohorts, GemConfigError, type GemDevTools, type GemErrorReason, GemFrame, GemFunctionError, type GemIdentity, type GemInsets, type GemMatchApi, type GemMatchServer, type GemMatchServerModule, type GemOptions, type GemPlayer, type GemPrefs, type GemReservedArea, GemSaveError, type GemServer, type GemServerBundle, type GemServerFactory, type GemServerHost, type GemServerHostProfile, type GemServerIdentity, type GemServerLifecycle, type GemServerOptions, type GemServerProfile, type GemTerminationNotice, type GemViewport, type GetLeaderboardOptions, type HostTokenSource, type HostTokenSourceOptions, type JoinWelcome, type Leaderboard, type LeaderboardEntry, LeaderboardsApi, type ListChallengesOptions, type ListFriendsOptions, MAX_PERIODS_BACK, type MatchConnectOptions, type MatchConnection, type MatchHosting, type MatchHostingMode, type MatchServeOptions, type MatchTransport, type MessageMeta, type MultiTransportSession, PLATFORM_EVENTS, PlatformApi, PlatformCurrenciesApi, type PlatformCurrency, type PlatformCurrencyAccess, type PlatformCurrencyPurchasePayment, type PlatformCurrencyPurchaseRequest, type PlatformCurrencyPurchaseResult, type PlatformCurrencyReadOptions, PlatformEarnAllowanceApi, type PlatformEventName, type PlayerBadge$1 as PlayerBadge, type PlayerBoost, type PlayerBoostMultiplier, type PlayerIdentity, type PlayerProfile, PlayerText, type ProfileCallOptions, type ProfileShowcaseEntry$1 as ProfileShowcaseEntry, ProfilesApi, type PurchaseApi, type PurchaseOptions, type PurchaseOutcome, PurchaseRefusal, type PurchaseRefusalCode, type PurchaseRequest, type PutBytesOptions, type PutSaveOptions, type RankedRow, type RecipeAvailability, type RecipeLock, type RequestOptions, type RewardCue, type RoomArgValue, type SavePage, type SaveRecord, type SendOptions$1 as SendOptions, type ServerApi, type ServerBundleHost, type ServerTokenGrant, type SessionEndReason, type ShareApi, type ShareRequest, ShowcaseApi, type ShowcaseCallOptions, type ShowcaseFriendEntry, type ShowcaseFriends, type ShowcaseValue, type SignInOutcome, type SignInOutcomeKind, type SnapshotCurrency, type SnapshotItem, type TokenGrant, type Transport, type TransportAdvert, type TransportKind, TransportRefusal, type TransportRequest, type TransportResponse, UNRELIABLE_CHANNEL_LABEL, type VersionedGetOptions, type VersionedResponse, type WalletVisibleOptions, asPlayerText, createBootTimeline, createGem, createGemServer, createHostTokenSource, createMatchServer, defineServer, leaveAndExit, mapIdentity, markOnResolve, platformIconUrl, presentJoinCredential, readTemplateTransports, readTransportAdvert, reportOnResolve, systemClock, text, toBase64, webTransportAvailable };
4376
+ export { ARCADE_EMBEDDERS, type AccountApi, type AdFormat, type AdOutcome, type AdOutcomeKind, type AdRequest, type AdsApi, AnalyticsApi, type AnalyticsFlushOptions, type AnalyticsFlushResult, type AnalyticsOptions, type AnalyticsRejection$1 as AnalyticsRejection, type AnalyticsValue, AuthError, type AuthFailure, type AuthState, type Base64String, type BootMark, type BootTimeline, type BroadcastOptions, type BytesResponse, CONDITIONAL_HEADERS, type Challenge, type ChallengeWindow, ChallengesApi, type ClientOptions, type Clock, type ConditionalRequestHeaders, type ConfiguredPurchasePayment, type ConfiguredPurchaseRequest, type ConfiguredPurchaseResult, DEVICE_SETTINGS_MAX_BYTES, DedicatedServerError, type DedicatedServerFailure, type DedicatedServerSession, type DevToolsOpener, type DeviceSettings, type DeviceSettingsApi, type DeviceSettingsPutOutcome, type DirectPurchaseRequest, type DirectPurchaseResult, type EarnAllowance, type EarnAllowanceEvent, type EarnAllowancePeriod, type EarnAllowanceReadOptions, type EntityLeaderboard, type EntityLeaderboardEntry, type EntityLeaderboardOptions, type EntityType$1 as EntityType, type ExitAnalytics, type ExitBridge, type ExitRooms, type FrameState, type Friend, FriendChallengeError, type FriendChallengeErrorCode, type FriendChallengeOutcome, type FriendChallengeOutcomeKind, type FriendChallengeRequest, FriendsApi, type FriendsPage, type FunctionFailure, type FunctionInvokeOptions, type FunctionResult, FunctionsApi, type GameApi, type GameConfig, type GameServerLink, type Gem, GemApiError, GemClient, type GemCohort, type GemCohorts, GemConfigError, type GemDevTools, type GemErrorReason, GemFrame, GemFunctionError, type GemIdentity, type GemInsets, type GemMatchApi, type GemMatchServer, type GemMatchServerModule, type GemOptions, type GemPlayer, type GemPrefs, type GemReservedArea, GemSaveError, type GemServer, type GemServerBundle, type GemServerFactory, type GemServerHost, type GemServerHostProfile, type GemServerIdentity, type GemServerLifecycle, type GemServerOptions, type GemServerProfile, type GemTerminationNotice, GemUnframedError, type GemViewport, type GetLeaderboardOptions, type HostTokenSource, type HostTokenSourceOptions, type JoinWelcome, type Leaderboard, type LeaderboardEntry, LeaderboardsApi, type ListChallengesOptions, type ListFriendsOptions, MAX_PERIODS_BACK, type MatchConnectOptions, type MatchConnection, type MatchHosting, type MatchHostingMode, type MatchServeOptions, type MatchTransport, type MessageMeta, type MultiTransportSession, PLATFORM_EVENTS, PlatformApi, PlatformCurrenciesApi, type PlatformCurrency, type PlatformCurrencyAccess, type PlatformCurrencyPurchasePayment, type PlatformCurrencyPurchaseRequest, type PlatformCurrencyPurchaseResult, type PlatformCurrencyReadOptions, PlatformEarnAllowanceApi, type PlatformEventName, type PlayerBadge$1 as PlayerBadge, type PlayerBoost, type PlayerBoostMultiplier, type PlayerIdentity, type PlayerProfile, PlayerText, type ProfileCallOptions, type ProfileShowcaseEntry$1 as ProfileShowcaseEntry, ProfilesApi, type PurchaseApi, type PurchaseOptions, type PurchaseOutcome, PurchaseRefusal, type PurchaseRefusalCode, type PurchaseRequest, type PutBytesOptions, type PutSaveOptions, type RankedRow, type RecipeAvailability, type RecipeLock, type RequestOptions, type RewardCue, type RoomArgValue, type SavePage, type SaveRecord, type SendOptions$1 as SendOptions, type ServerApi, type ServerBundleHost, type ServerTokenGrant, type SessionEndReason, type ShareApi, type ShareRequest, ShowcaseApi, type ShowcaseCallOptions, type ShowcaseFriendEntry, type ShowcaseFriends, type ShowcaseValue, type SignInOutcome, type SignInOutcomeKind, type SnapshotCurrency, type SnapshotItem, type TokenGrant, type Transport, type TransportAdvert, type TransportKind, TransportRefusal, type TransportRequest, type TransportResponse, UNRELIABLE_CHANNEL_LABEL, type VersionedGetOptions, type VersionedResponse, type WalletVisibleOptions, asPlayerText, createBootTimeline, createGem, createGemServer, createHostTokenSource, createMatchServer, defineServer, leaveAndExit, mapIdentity, markOnResolve, platformIconUrl, presentJoinCredential, readTemplateTransports, readTransportAdvert, reportOnResolve, systemClock, text, toBase64, webTransportAvailable };
package/docs/analytics.md CHANGED
@@ -121,9 +121,8 @@ what the table says, however much context you have set.
121
121
 
122
122
  Three of these are worth knowing the shape of before you build a report on them:
123
123
 
124
- - **`gem_session_start` is the handshake, not the first frame.** A game opened outside the arcade
125
- never establishes a play session, so it starts no session and sends nothing. That is expected
126
- while you are developing locally.
124
+ - **`gem_session_start` is the handshake, not the first frame.** A game whose frame never connects
125
+ establishes no play session, so it starts no session and sends nothing.
127
126
  - **A game the Arcade starts on its own is not a session until the player touches it.** On a
128
127
  desktop the Arcade may autoplay your game on its information page before anyone has asked for
129
128
  it, and a view is not a play. The SDK then holds **everything** — `gem_session_start`,
@@ -1,6 +1,6 @@
1
1
  # The browser surface — API reference
2
2
 
3
- Generated from `@indiegems/gem-web-sdk/sdk` v7.5.0. Every symbol below links to its page on the Gem Arcade developer site.
3
+ Generated from `@indiegems/gem-web-sdk/sdk` v7.6.0. Every symbol below links to its page on the Gem Arcade developer site.
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
 
@@ -4613,11 +4613,11 @@ type FrameState = "waiting" | "connected" | "refused" | "closed"
4613
4613
 
4614
4614
  Where the bridge to the arcade stands.
4615
4615
 
4616
- `waiting` is the state a game boots in and the one it may sit in forever —
4617
- outside the arcade there is no parent to answer, and that is not an error.
4618
- `connected` is the only state in which the arcade is listening. `refused`
4619
- means a page tried to embed this game and its origin was not in
4620
- `allowedEmbedders`; `closed` means a connection existed and ended.
4616
+ `waiting` is the state a game boots in: framed, and its parent has not
4617
+ answered yet. `connected` is the only state in which the arcade is
4618
+ listening. `refused` is final: the page that framed this game is not one it
4619
+ accepts (its origin is not in `allowedEmbedders`), or it speaks no protocol
4620
+ version in common. `closed` means a connection existed and ended.
4621
4621
 
4622
4622
  Received by `onStateChange` and resolved by `awaitBridge`, both of which are
4623
4623
  documented — so without a name for this union a game could observe the value
@@ -4655,15 +4655,15 @@ Where the bridge is right now, without waiting.
4655
4655
 
4656
4656
  - `waiting` — the arcade has not connected yet. Normal at startup.
4657
4657
  - `connected` — the bridge is up and everything works.
4658
- - `refused` — the arcade declined the connection.
4658
+ - `refused` — final: the page that framed the game is not one it accepts,
4659
+ or no protocol version is shared.
4659
4660
  - `closed` — the session has ended.
4660
4661
 
4661
4662
  A snapshot, so it can change immediately after you read it. To wait for the
4662
4663
  question to be settled once, use [GemFrame.settled](https://gemarcade.com/developer/api/game#gemframe-settled).
4663
4664
 
4664
- A game outside the arcade — opened directly during development — stays
4665
- `waiting` forever, which is the case worth handling: boot anyway, without a
4666
- bridge.
4665
+ A page that frames the game and never answers leaves it `waiting`, which
4666
+ is the case worth handling: boot anyway, and say there is no session.
4667
4667
 
4668
4668
  ## GemFrame.parentSupports
4669
4669
 
@@ -4723,10 +4723,9 @@ parsing several megabytes of JavaScript, the offer waits behind that work —
4723
4723
  and by the time it arrives the connection it carried may already be gone.
4724
4724
  Awaiting this first keeps the thread free long enough to accept.
4725
4725
 
4726
- THE WAIT IS BOUNDED ON PURPOSE, because an embedder is optional: your game
4727
- must still start when nothing ever answers, just without a bridge. Proceed
4728
- on either outcome and read the resolved state to know which kind of boot
4729
- this is.
4726
+ THE WAIT IS BOUNDED ON PURPOSE, because the page framing your game may
4727
+ never answer, and your game must still start and say so. Proceed on either
4728
+ outcome and read the resolved state to know which kind of boot this is.
4730
4729
 
4731
4730
  ```js
4732
4731
  const state = await gem.frame.settled();
@@ -6752,7 +6751,7 @@ readonly reserved: readonly GemReservedArea[]
6752
6751
  ```
6753
6752
 
6754
6753
  Rectangles of your frame the arcade's own controls cover — its Back tab in
6755
- the top-left corner, and the wallets beside it while they are shown (see
6754
+ the top-left corner, and the wallets in the top-right while they are shown (see
6756
6755
  `setWalletVisible`). Keep essential UI and touch targets out of them. Empty
6757
6756
  when the arcade covers nothing.
6758
6757
 
@@ -7019,7 +7018,9 @@ single round trip to the page hosting your game.
7019
7018
 
7020
7019
  Rejects rather than resolving `null` if the wait runs out: a session that
7021
7020
  cannot sign in cannot do anything else either, and a `null` you might not
7022
- check is how a game carries on into a failure it could have reported.
7021
+ check is how a game carries on into a failure it could have reported. It
7022
+ rejects at once, without waiting, when the page that framed the game was
7023
+ refused: no token can arrive from it.
7023
7024
 
7024
7025
  | Parameter | Type | Description |
7025
7026
  | --- | --- | --- |
@@ -7042,10 +7043,10 @@ Waits for the connection to the arcade to settle, one way or the other.
7042
7043
  Resolves with the state it settled into — connected, refused or closed — or
7043
7044
  with whatever it had reached by `timeoutMs`, which defaults to 10 seconds.
7044
7045
 
7045
- OUTSIDE THE ARCADE IT WAITS THE FULL TIMEOUT and then resolves `waiting`,
7046
- because nothing ever answers. It does not return early. That is ten seconds
7047
- on every local run, so pass a shorter `timeoutMs` during development if the
7048
- wait gets in your way.
7046
+ A game is always framed (`createGem` throws [GemUnframedError](https://gemarcade.com/developer/api/game#gemunframederror)
7047
+ otherwise), so this normally resolves `connected` within a moment. It
7048
+ resolves `refused` at once when the page that framed the game is not one it
7049
+ accepts, and `waiting` only when the page framing it never answers.
7049
7050
 
7050
7051
  **Await this in your boot entry before importing your main bundle.** The
7051
7052
  arcade hands your game its connection as a one-off delivery rather than
@@ -7054,9 +7055,10 @@ parsing several megabytes of JavaScript when it arrives, your game can miss
7054
7055
  it. Awaiting this keeps the thread free through that window; the moment it
7055
7056
  resolves, load everything.
7056
7057
 
7057
- Carry on whatever it resolves to. `connected` means you are in the arcade;
7058
- anything else means you are running without it, which your game has to
7059
- survive anyway — during local development, that is the normal case.
7058
+ Carry on whatever it resolves to. `connected` means a Gem host is
7059
+ listening — the Arcade, the Editor or the dev host on your machine;
7060
+ anything else means no session, which your game has to survive with a
7061
+ message rather than a hang.
7060
7062
 
7061
7063
  | Parameter | Type | Description |
7062
7064
  | --- | --- | --- |
@@ -7075,8 +7077,7 @@ readonly player: GemPlayer | null
7075
7077
 
7076
7078
  The player's display identity — the name, handle and avatar you show them.
7077
7079
 
7078
- `null` until the arcade sends it, and always `null` outside the arcade.
7079
- Nothing obliges it to be sent at all, so treat its absence as normal and
7080
+ `null` until the arcade sends it. Nothing obliges it to be sent at all, so treat its absence as normal and
7080
7081
  have a fallback: a game with no display name is fine, a game that waits
7081
7082
  forever for one is not.
7082
7083
 
@@ -7523,8 +7524,8 @@ awaitCohorts(timeoutMs?: number): Promise<GemCohorts | null>
7523
7524
 
7524
7525
  The experiment cohorts, waiting up to `timeoutMs` for them.
7525
7526
 
7526
- Resolves `null` rather than rejecting — outside the arcade too, once the
7527
- wait is out, because no parent is there to answer. Use it at the ONE point
7527
+ Resolves `null` rather than rejecting once the wait is out, or at once if
7528
+ the page that framed the game was refused. Use it at the ONE point
7528
7529
  your game branches on a cohort — typically
7529
7530
  the first run's opening — and give it a short budget: the answer normally
7530
7531
  arrives within the first second, and a player kept on a splash screen for a
@@ -7647,7 +7648,7 @@ ticketStore.onOpen = () => gem.setWalletVisible(true, { only: ['ARCADE_TICKETS']
7647
7648
  replaces the last. While hidden, the arcade still pops a wallet up for a
7648
7649
  moment when something happens to it — a reward you cued, a spend, a
7649
7650
  landing — and your state never cancels that. Shown wallets cover part of
7650
- your frame beside the Back tab, which arrives as a rectangle in
7651
+ your frame's top-right corner, which arrives as a rectangle in
7651
7652
  `gem.viewport.reserved`; hiding them gives that space back. A wallet the
7652
7653
  arcade pops up for a moment floats over your game and moves nothing.
7653
7654
 
@@ -7715,9 +7716,9 @@ readonly frame: GemFrame
7715
7716
 
7716
7717
  Your game's connection to the arcade.
7717
7718
 
7718
- ALWAYS PRESENT, even when nothing is on the other end. Running outside the
7719
- arcade does not make this `null` — the frame simply stays in `waiting`
7720
- forever, which is the state to read when you want to know whether anyone
7719
+ ALWAYS PRESENT, even when nothing is on the other end yet: a page that
7720
+ never answers leaves the frame in `waiting`, and a refused one ends it in
7721
+ `refused`, which is the state to read when you want to know whether anyone
7721
7722
  ever answered. Do not write a `=== null` branch; it can never run.
7722
7723
 
7723
7724
  **This is where the loading contract lives.** Call `progress()` as your
@@ -7833,8 +7834,9 @@ Connect your game to the Gem Arcade. This is the one call every game makes.
7833
7834
 
7834
7835
  It assembles everything and connects to the arcade that framed your game. The
7835
7836
  same code runs on your machine and in production without a flag — but it needs
7836
- a parent either way: run it framed, and until one answers the SDK says so
7837
- rather than letting you assume a session you do not have.
7837
+ a frame either way. Opened at the top level it throws
7838
+ [GemUnframedError](https://gemarcade.com/developer/api/game#gemunframederror), which says how to run it: in the Arcade, the Editor,
7839
+ or the Gem dev host on your machine (`npm run dev`, signed in to `gemctl`).
7838
7840
 
7839
7841
  One dependency, imported like anything else. The install is at
7840
7842
  https://gemarcade.com/developer/docs/getting-started#3-add-the-sdk
@@ -11011,6 +11013,31 @@ theirs. Use this for display-level comparisons, not for identity.
11011
11013
  | `a` | `string \| PlayerText` |
11012
11014
  | `b` | `string \| PlayerText` |
11013
11015
 
11016
+ ## GemUnframedError
11017
+
11018
+ [GemUnframedError](https://gemarcade.com/developer/api/game#gemunframederror)
11019
+
11020
+ ```ts
11021
+ class GemUnframedError
11022
+ ```
11023
+
11024
+ Your game was opened without a Gem frame around it.
11025
+
11026
+ Thrown by `createGem` when the page is the top-level document: nothing
11027
+ framed it, so nothing can hand it a player, saves, config or rooms. The SDK
11028
+ needs that frame — the Gem Arcade, the Gem Editor, or the Gem dev host on
11029
+ your own machine — and refuses to start without one rather than running a
11030
+ game that silently has no player.
11031
+
11032
+ You do not construct this. Run the game framed instead: `npm run dev`
11033
+ (`gemctl serve start . --dev`) while you edit, `gemctl serve start .` for a
11034
+ build, signed in to `gemctl` either way. Never open the address the dev
11035
+ server itself prints.
11036
+
11037
+ A unit test that constructs the SDK in a simulated DOM has to give its
11038
+ window a parent of its own, because a simulated top-level window is exactly
11039
+ what this refuses.
11040
+
11014
11041
  ## LeaderboardEntry.playerId
11015
11042
 
11016
11043
  [LeaderboardEntry.playerId](https://gemarcade.com/developer/api/game#leaderboardentry-playerid)
@@ -1,6 +1,6 @@
1
1
  # The server surface — API reference
2
2
 
3
- Generated from `@indiegems/gem-web-sdk/sdk` v7.5.0. Every symbol below links to its page on the Gem Arcade developer site.
3
+ Generated from `@indiegems/gem-web-sdk/sdk` v7.6.0. Every symbol below links to its page on the Gem Arcade developer site.
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