@indiegems/gem-web-sdk 13.2.0 → 13.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,3 +1,3 @@
1
- var Pe=Object.defineProperty;var Oe=(n,e)=>{for(var t in e)Pe(n,t,{get:e[t],enumerable:true});};globalThis.__gemWebSdkVersion="[gem-web-sdk:sdkVersion:13.2.0]";var Te={initialDelayMs:2e3,maxDelayMs:6e4};function Ge(n,e){return e!==void 0?!e:n==="chain_exhausted"}var B=class{constructor(e){this.options=e;}options;grant=null;state="pending";failure=null;generation=0;inFlight=null;rejected=false;retry=null;failures=0;notBefore=0;disposed=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.pastChainCeiling())throw new _("chain_exhausted","the token chain reached its ceiling");if(this.inFlight===null&&this.options.clock.now()<this.notBefore)throw new _(this.failure??"unavailable","the embedder asked for no new token yet; one is asked for when that wait is over");return this.refresh(this.nextReason())}pastChainCeiling(){return this.grant===null||this.seconds()<this.grant.chainEndsAt?false:(this.enter("lost","chain_exhausted"),true)}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);}dispose(){this.disposed=true,this.cancelRetry();}scheduleRetry(e){if(this.cancelRetry(),this.failures+=1,this.notBefore=e===void 0?0:this.options.clock.now()+e,this.disposed)return;let{initialDelayMs:t,maxDelayMs:r}=Te,o=Math.min(r,t*2**(this.failures-1)),a=Math.max(o/2,e??0)+Math.random()*(o/2);this.retry={handle:this.options.clock.setTimeout(()=>this.retryNow(),a)};}retryNow(){this.retry=null,this.notBefore=0,!(this.state==="lost"||this.pastChainCeiling())&&this.refresh(this.nextReason()).catch(()=>{});}cancelRetry(){this.retry!==null&&(this.options.clock.clearTimeout(this.retry.handle),this.retry=null);}refresh(e){if(this.inFlight)return this.inFlight;this.cancelRetry();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 a=Ce(o),{retryable:i,retryAfterMs:l}=o??{};throw t===this.generation&&(Ge(a,typeof i=="boolean"?i:void 0)?this.enter("lost",a):(this.scheduleRetry(typeof l=="number"&&Number.isFinite(l)&&l>0?l:void 0),this.enter("degraded",a))),o instanceof _?o:new _(a,String(o))}).finally(()=>{this.inFlight===r&&(this.inFlight=null);});return this.inFlight=r,r}enter(e,t){(e==="ready"||e==="lost")&&this.cancelRetry(),e==="ready"&&(this.failures=0,this.notBefore=0),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 Ce(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 y=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}},F=["if-match","if-none-match"],Y=4096;function Ie(n){if(!n)return;let e={};for(let[t,r]of Object.entries(n)){let o=t.toLowerCase();if(!F.includes(o)||r===void 0)continue;let a=typeof r=="string"?Ee(r):r;if(typeof a!="string"||a.length>Y||!Me(a))throw new y(`the ${o} header value cannot be sent \u2014 it is not a string, is longer than ${Y} characters, or contains a character outside the range an HTTP header value may carry. This is a malformed request, not a server failure; the value is withheld here rather than written to logs.`);a!==""&&(e[o]=a);}return Object.freeze(e)}function Ee(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 Me(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 qe(n){let{bytes:e}=n;if(e!==void 0){if(Object.prototype.toString.call(e)!=="[object Uint8Array]")throw new y("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 y("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 J(n,e){let t=e.replayUnauthorizedOnce??true;return {async request(r){let o={...r},a=Ie(o.headers),i=qe(o),l=Object.freeze({...o,headers:a,...i===void 0?{}:{bytes:i}}),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(),h=await n(l,g);if(h.status===401)throw e.tokenSource.close("unavailable"),new _("unavailable","the server refused a freshly minted token");return h}}}function X(n){let e=typeof n=="string"?new TextEncoder().encode(n):n;return btoa(Le(e))}function Le(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,a,i){super(`${t} (${r}): ${o}`);this.reason=t;this.status=r;this.detail=o;this.retryAfterSeconds=a;this.code=i;this.name="GemApiError";}reason;status;detail;retryAfterSeconds;code;get retryable(){return this.reason==="unavailable"||this.reason==="rate_limited"}},Z=new WeakMap;function ee(n){return Z.get(n)??{}}var $e=new Set([408,429,500,502,503,504]),je=6e4;function Be(n){if(n===void 0)return 2;if(!Number.isInteger(n)||n<0||n>10)throw new y(`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 C=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,...q(o)},o.replaySafe===true,o.retryRateLimited!==false)}async post(e,t,r,o={}){return this.send({method:"POST",path:e,body:t,signal:r,...q(o)},o.replaySafe===true,o.retryRateLimited!==false)}async postBytes(e,t,r,o={}){let a=await this.sendRaw({method:"POST",path:e,bytes:t,responseType:"bytes",signal:r,...q(o)},o.replaySafe===true,o.retryRateLimited!==false);return {bytes:Fe(a.body),...a.invocationId===void 0?{}:{invocationId:a.invocationId}}}async patch(e,t,r,o={}){return this.send({method:"PATCH",path:e,body:t,signal:r,...q(o)},o.replaySafe===true,o.retryRateLimited!==false)}async delete(e,t,r={}){return this.send({method:"DELETE",path:e,signal:t,...q(r)},r.replaySafe===true,r.retryRateLimited!==false)}async send(e,t,r=true){return (await this.sendRaw(e,t,r)).body}async sendRaw(e,t,r=true){let o=t?Be(this.options.maxRetries)+1:1,a=null;if(e.signal?.aborted)throw Q(e.signal);for(let i=0;i<o;i++){if(i>0&&await this.backoff(i,a,e.signal),e.signal?.aborted)throw Q(e.signal);let l;try{l=await this.options.transport.request(e);}catch(c){if(_.isAuthError(c)||y.isRefusal(c)||e.signal?.aborted||Ue(c))throw c;a=new m("unavailable",0,String(c));continue}if(l.status>=200&&l.status<300||l.status===304)return l;let d=Ne(l);if(!$e.has(l.status)||l.status===429&&!r)throw d;a=d;}throw a??new m("unavailable",0,"no attempt was made")}backoff(e,t,r){if(r?.aborted)return Promise.resolve();let o=t?.retryAfterSeconds,a=o!==void 0?o*1e3:2**(e-1)*250,i=2**(e-1)*250,l=Math.min(Math.max(a,i),je);return new Promise(d=>{let c=this.options.clock,g=false,h=false,b,f=()=>{g||(g=true,h&&c.clearTimeout(b),r?.removeEventListener("abort",f),d());};r?.addEventListener("abort",f,{once:true}),b=c.setTimeout(f,l),h=true,g&&c.clearTimeout(b);})}};function Fe(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 q(n){return {...n.keepalive===void 0?{}:{keepalive:n.keepalive},...n.ifMatch===void 0?{}:{headers:{"if-match":n.ifMatch}}}}function Q(n){return n.reason!==void 0?n.reason:new DOMException("The operation was aborted.","AbortError")}function Ue(n){let e=n?.name;return e==="AbortError"||e==="TimeoutError"}function Ne(n){let e=He(n),t=We(n.body),r={...t===void 0?{}:{details:t},...n.invocationId===void 0?{}:{invocationId:n.invocationId}};return Object.keys(r).length>0&&Z.set(e,r),e}var De=new Map([["insufficient_funds","insufficient_funds"]]);function He(n){let{status:e,body:t}=n,r=Ve(t),o=n.retryAfterSeconds??Ke(t),a=ze(t),i=a===void 0?void 0:De.get(a);if(i!==void 0)return new m(i,e,r,void 0,a);switch(e){case 304:return new m("not_modified",e,r);case 400:case 422:return new m("invalid",e,r,void 0,a);case 403:return new m("forbidden",e,r,void 0,a);case 404:return new m("not_found",e,r,void 0,a);case 402:return new m("insufficient_funds",e,r,void 0,a);case 409:return new m("conflict",e,r,void 0,a);case 412:return new m("precondition_failed",e,r,void 0,a);case 413:return new m("too_large",e,r,void 0,a);case 429:return new m("rate_limited",e,r,o,a);default:return new m("unavailable",e,r,o,a)}}function Ve(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 We(n){let t=n?.error?.details;return t===null?void 0:t}function ze(n){let t=n?.error?.code;return typeof t=="string"&&t.length>0?t:void 0}function Ke(n){let e=n?.retryAfterSeconds;return typeof e=="number"&&Number.isFinite(e)&&e>=0?e:void 0}function Ye(n){let e=n.lastIndexOf("@");return (e===-1?n:`***@${n.slice(e+1)}`).slice(0,200)}var Je=new Set(F);function Xe(n){if(!n)return {};let e={};for(let[t,r]of Object.entries(n))Je.has(t.toLowerCase())&&(e[t.toLowerCase()]=r);return e}function ne(n){let e=n.fetch??globalThis.fetch.bind(globalThis);return J(async(t,r)=>{let o;try{o=new URL(n.baseUrl.replace(/\/+$/,""));}catch{throw new y("the configured baseUrl is not a valid URL. Its value is withheld here rather than written to logs. This is a configuration fault, not a server failure.")}let a;try{a=new URL(o.href.replace(/\/+$/,"")+t.path);}catch{throw new y(`${JSON.stringify(typeof t.path=="string"?Ye(t.path):"(a non-string path)")} does not form a valid URL against ${o.protocol}//${o.host}. This is a malformed request, not a server failure.`)}if(a.protocol!==o.protocol||a.host!==o.host)throw new y(`${JSON.stringify(a.pathname)} resolves to ${a.protocol}//${a.host}, not ${o.protocol}//${o.host}. A request path may not change the request's origin \u2014 it carries the play token.`);if(a.username!==""||a.password!==""){let f=o.username!==""||o.password!=="",p=a.username!==o.username||a.password!==o.password,k=f?p?"baseUrl (and possibly the request path)":"baseUrl":"request path";throw new y(`the ${k} puts credentials in the URL, which cannot be fetched (${t.method} ${a.pathname}). The value is withheld here rather than written to logs. This is a malformed request, not a server failure.`)}for(let[f,p]of Object.entries(n.defaultQuery??{}))a.searchParams.has(f)||a.searchParams.set(f,p);let i=t.bytes,l=t.bytes===void 0?void 0:"application/octet-stream";try{t.body!==void 0&&(i=JSON.stringify(t.body),l="application/json");}catch(f){throw new y(`the body of ${t.method} ${JSON.stringify(a.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(a.toString(),{method:t.method,headers:{authorization:`Bearer ${r}`,...l===void 0?{}:{"content-type":l},...Xe(t.headers)},body:i,signal:t.signal,...t.keepalive===void 0?{}:{keepalive:t.keepalive},credentials:"omit",mode:"cors",redirect:"error",cache:"no-store",referrerPolicy:"no-referrer"}),c=null;if(t.responseType==="bytes"&&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"),h=Qe(d.headers.get("retry-after")),b=d.headers.get("x-gem-invocation-id");return {status:d.status,body:c,...g===null?{}:{etag:g},...h===void 0?{}:{retryAfterSeconds:h},...b===null||b===""?{}:{invocationId:b}}},n)}function Qe(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 Ze="gem-web-bridge";var I=65536,te=8,U=5e3,re=1024;var N=Object.create(null);var oe=Object.create(null);function en(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 nn(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 tn(n){return /^[a-z]{2,8}(-[a-z0-9]{1,8})*$/i.test(n)}function rn(n){return /^[a-z_]+$/.test(n)}function H(n,e,t){if(e>te)return `nesting deeper than ${te}`;if(++t.nodes>U)return `more than ${U} values`;if(t.bytes>I)return `over the ${I} 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>re)return `an array of ${n.length} entries, over the ${re} limit`;t.bytes+=2;for(let l of n){let d=H(l,e+1,t);if(d)return d}return null}let a=Object.getPrototypeOf(n);if(a!==Object.prototype&&a!==null)return "a value that is not a plain object";t.bytes+=2;let i=n;for(let l in i){if(!Object.prototype.hasOwnProperty.call(i,l))continue;if(++t.nodes>U)return `more than ${U} values`;if(t.bytes+=l.length*3+4,t.bytes>I)return `over the ${I} byte limit`;let d=H(i[l],e+1,t);if(d)return d}return null}function on(n){let e={nodes:0,bytes:0,seen:new Set},t=H(n,0,e);return t?`message contains ${t}`:e.bytes>I?`message is over the ${I} byte limit`:null}var an={origin:[en,"not a well-formed origin"],url:[nn,"not a safe absolute http(s) URL"],bcp47:[tn,"not a well-formed BCP 47 tag"],code:[rn,"not a code of lower-case letters and underscores"]};function ae(n,e,t){for(let r of e){let o=t===""?r.n:`${t}.${r.n}`,a=n[r.n];if(a==null){if(r.o)continue;return `${o}: required`}let i=se(a,r,o);if(i)return i}return null}function se(n,e,t){switch(e.k){case "s":{if(typeof n!="string")return `${t}: expected string`;if(n.length>e.max)return `${t}: exceeds ${e.max} characters`;if(e.f){let[r,o]=an[e.f];if(!r(n))return `${t}: ${o}`}return null}case "i":return typeof n!="number"||!Number.isInteger(n)?`${t}: expected integer`:n<e.lo||n>e.hi?`${t}: out of range ${e.lo}..${e.hi}`:null;case "b":return typeof n=="boolean"?null:`${t}: expected boolean`;case "e":{let r=e.v;return r.includes(n)?null:`${t}: not one of ${r.join("|")}`}case "o":return typeof n!="object"||n===null||Array.isArray(n)?`${t}: expected object`:ae(n,e.fs,t);case "j":return typeof n!="object"||n===null||Array.isArray(n)?`${t}: expected a plain object`:null;case "a":{if(!Array.isArray(n))return `${t}: expected array`;if(n.length>e.max)return `${t}: exceeds ${e.max} items`;let r=e.it,o=`${t}[]`;for(let a of n){if(a==null){if(r.o)continue;return `${o}: required`}let i=se(a,r,o);if(i)return i}return null}default:{let r=e.k;return `${t}: unknown kind ${String(r)}`}}}var ie=Object.create(null);function u(n,e,t,r){return N[n]=t,r&&(oe[n]=r),ie[n]=o=>{let a=on(o);if(a)return a;if(typeof o!="object"||o===null||Array.isArray(o))return "message: expected object";let i=o;return i.gem!==Ze?"gem: wrong protocol marker":i.type!==n?`type: expected ${n}`:ae(i,e,"")}}u("gem.handshake",[{n:"versions",k:"o",fs:[{n:"min",k:"i",lo:1,hi:1e3},{n:"max",k:"i",lo:1,hi:1e3}]},{n:"capabilities",k:"a",o:1,max:64,it:{n:"",k:"s",max:64}},{n:"embedder",k:"s",max:2048,f:"origin"},{n:"unbidden",k:"b",o:1}],30);u("gem.handshake.accept",[{n:"v",k:"i",lo:1,hi:1e3},{n:"capabilities",k:"a",o:1,max:64,it:{n:"",k:"s",max:64}}],5);u("gem.token",[{n:"token",k:"s",max:4096},{n:"requestId",k:"s",o:1,max:64},{n:"generation",k:"i",lo:0,hi:2147483647},{n:"apiBaseUrl",k:"s",o:1,max:512,f:"url"},{n:"playerId",k:"s",max:64},{n:"gameId",k:"s",max:64},{n:"channel",k:"e",v:["dev","test","release"]},{n:"gameVersion",k:"s",o:1,max:64},{n:"expiresAt",k:"i",lo:0,hi:4102444800},{n:"chainEndsAt",k:"i",lo:0,hi:4102444800},{n:"allowDevTools",k:"b",o:1}],30);u("gem.token.denied",[{n:"requestId",k:"s",max:64},{n:"retryable",k:"b"},{n:"retryAfterMs",k:"i",o:1,lo:0,hi:36e5},{n:"reason",k:"e",v:["chain_exhausted","unavailable"]},{n:"correlationId",k:"s",max:64}],30);u("gem.player",[{n:"untrusted",k:"o",fs:[{n:"displayName",k:"s",max:64},{n:"displayTag",k:"s",o:1,max:80},{n:"displayHandle",k:"s",max:80}]},{n:"playerId",k:"s",o:1,max:64},{n:"discriminator",k:"s",o:1,max:8},{n:"avatarIconUrl",k:"s",o:1,max:2048,f:"url"},{n:"avatarIconId",k:"s",o:1,max:64},{n:"avatar3dId",k:"s",o:1,max:64},{n:"avatar3dModelUrl",k:"s",o:1,max:2048,f:"url"},{n:"avatar3dIconUrl",k:"s",o:1,max:2048,f:"url"},{n:"avatars3d",k:"a",o:1,max:8,it:{n:"",k:"o",fs:[{n:"family",k:"s",max:32},{n:"id",k:"s",max:64},{n:"modelUrl",k:"s",max:256,f:"url"},{n:"iconUrl",k:"s",max:256,f:"url"}]}},{n:"badges",k:"a",o:1,max:2,it:{n:"",k:"o",fs:[{n:"itemId",k:"s",max:64},{n:"iconUrl",k:"s",max:2048,f:"url"}]}},{n:"displayTag",k:"s",max:8},{n:"avatarUrl",k:"s",o:1,max:2048,f:"url"},{n:"boost",k:"o",o:1,fs:[{n:"multipliers",k:"a",max:8,it:{n:"",k:"o",fs:[{n:"currencyId",k:"s",max:64},{n:"currencySlug",k:"s",max:32},{n:"multiplierBp",k:"i",lo:1e4,hi:1e6}]}},{n:"expiresInDays",k:"i",o:1,lo:1,hi:7}]}],12);u("gem.pause",[{n:"paused",k:"b"}],120);u("gem.prefs",[{n:"reducedMotion",k:"b"},{n:"muted",k:"b"},{n:"showFrameStats",k:"b",o:1},{n:"locale",k:"s",max:35,f:"bcp47"},{n:"recommended",k:"o",o:1,fs:[{n:"volume",k:"i",lo:0,hi:100},{n:"batterySaver",k:"b"},{n:"keyboardLayout",k:"e",v:["wasd","arrows"]},{n:"gamepadConfirm",k:"e",v:["south","east"]},{n:"vibration",k:"b"},{n:"lookSensitivity",k:"i",o:1,lo:20,hi:400},{n:"gamepadLookSensitivity",k:"i",o:1,lo:20,hi:400},{n:"invertLookY",k:"b",o:1},{n:"touchMovement",k:"s",o:1,max:16,f:"code"},{n:"graphicsQuality",k:"s",o:1,max:16,f:"code"},{n:"graphicsQualityAuto",k:"b",o:1}]}],60);u("gem.cohorts",[{n:"cohorts",k:"a",max:8,it:{n:"",k:"o",fs:[{n:"experimentId",k:"s",max:36},{n:"variantKey",k:"s",max:32}]}}],12,"cohorts");u("gem.earnAllowanceChanged",[],30,"earnAllowance");u("gem.viewport",[{n:"insets",k:"o",fs:[{n:"top",k:"i",lo:0,hi:4096},{n:"right",k:"i",lo:0,hi:4096},{n:"bottom",k:"i",lo:0,hi:4096},{n:"left",k:"i",lo:0,hi:4096}]},{n:"reserved",k:"a",o:1,max:4,it:{n:"",k:"o",fs:[{n:"x",k:"i",lo:0,hi:16384},{n:"y",k:"i",lo:0,hi:16384},{n:"width",k:"i",lo:0,hi:16384},{n:"height",k:"i",lo:0,hi:16384}]}}],60,"viewport");u("gem.deviceSettings",[{n:"settings",k:"j",o:1}],12,"deviceSettings");u("gem.willTerminate",[{n:"reason",k:"e",v:["grant_expiring","session_ended","navigating","kill_switch"]},{n:"graceMs",k:"i",lo:0,hi:6e4}],10);u("gem.roomEvent",[{n:"event",k:"e",v:["updated","match_started","match_ready","match_failed","version_stale"]},{n:"roomId",k:"s",max:64},{n:"matchId",k:"s",o:1,max:64},{n:"version",k:"i",o:1,lo:0,hi:2147483647},{n:"reason",k:"s",o:1,max:64},{n:"platform",k:"e",o:1,v:["universal","mobile"]}],120,"rooms");u("gem.socketState",[{n:"connected",k:"b"},{n:"reason",k:"e",o:1,v:["connecting","dropped","watchdog","terminal"]}],12,"socketState");u("gem.seatedEvent",[{n:"roomId",k:"s",max:64}],60,"partySeating");u("gem.autoStartFailedEvent",[{n:"roomId",k:"s",max:64},{n:"code",k:"s",max:64}],30,"autoStartFailure");u("gem.ticketEvent",[{n:"event",k:"e",v:["queued","matched","expired","cancelled","failed"]},{n:"ticketId",k:"s",max:64},{n:"partySize",k:"i",o:1,lo:1,hi:64},{n:"queuedAt",k:"i",o:1,lo:0,hi:4102444800},{n:"expiresAt",k:"i",o:1,lo:0,hi:4102444800},{n:"reason",k:"s",o:1,max:64},{n:"roomId",k:"s",o:1,max:64}],60,"ticketEvents");u("gem.signalEvent",[{n:"event",k:"e",v:["hello","offer","answer","ice","peerJoined","peerLeft","migration","matchEnded","error"]},{n:"matchId",k:"s",max:64},{n:"data",k:"j"}],1800,"p2p");u("gem.dedicatedEvent",[{n:"event",k:"e",v:["answer","error","matchEnded"]},{n:"matchId",k:"s",max:64},{n:"sdp",k:"s",o:1,max:10240},{n:"sessionId",k:"s",o:1,max:64},{n:"code",k:"s",o:1,max:64},{n:"message",k:"s",o:1,max:256},{n:"reason",k:"s",o:1,max:64}],120,"dedicated");u("gem.partyResult",[{n:"requestId",k:"s",max:64},{n:"partyId",k:"s",o:1,max:64}],30,"parties");u("gem.clusterTarget",[{n:"clusterTargetId",k:"s",max:64},{n:"clusterTargetIds",k:"a",o:1,max:3,it:{n:"",k:"s",max:64}}],12,"clusterTarget");u("gem.devtools",[{n:"action",k:"e",v:["open","close","toggle"]}],30,"devtools");u("gem.screenshot",[{n:"maxWidth",k:"i",lo:1,hi:7680},{n:"maxHeight",k:"i",lo:1,hi:4320}],6,"screenshot");u("gem.screenshot.denied",[{n:"reason",k:"e",v:["not_wired","no_source","unsupported","unreadable","tainted","too_large","busy","declined","failed"]},{n:"retryable",k:"b"}],12,"screenshot");u("gem.requestContext",[],12,"feedbackContext");u("gem.gameContext",[{n:"context",k:"j"}],12,"feedbackContext");u("gem.signal",[{n:"signal",k:"e",v:["join","offer","answer","ice","migrationAck","hostUnreachable"]},{n:"matchId",k:"s",max:64},{n:"data",k:"j"}],1200,"p2p");u("gem.dedicatedOffer",[{n:"matchId",k:"s",max:64},{n:"sdp",k:"s",max:10240},{n:"intent",k:"e",v:["initial","ice_restart","full_reconnect"]}],60,"dedicated");u("gem.partyRequest",[{n:"requestId",k:"s",max:64}],12,"parties");u("gem.ready",[],5);u("gem.engaged",[],5,"engagement");u("gem.progress",[{n:"loaded",k:"i",lo:0,hi:1099511627776},{n:"total",k:"i",lo:0,hi:1099511627776}],600);u("gem.requestToken",[{n:"requestId",k:"s",max:64},{n:"reason",k:"e",v:["initial","expiring","rejected"]}],12);u("gem.requestLocalServer",[{n:"requestId",k:"s",max:64},{n:"gameRoomId",k:"s",max:64}],6,"localHost");u("gem.localServer",[{n:"requestId",k:"s",max:64},{n:"serverId",k:"s",o:1,max:128}],30,"localHost");u("gem.localServer.denied",[{n:"requestId",k:"s",max:64},{n:"retryable",k:"b"},{n:"reason",k:"e",v:["refused","unavailable"]}],30,"localHost");u("gem.exit",[{n:"reason",k:"s",o:1,max:64}],5);u("gem.openExternal",[{n:"url",k:"s",max:2048,f:"url"}],6);u("gem.requestFullscreen",[{n:"enabled",k:"b"}],30);u("gem.audioState",[{n:"muted",k:"b"}],120,"audioState");u("gem.rewardCue",[{n:"currencySlug",k:"s",max:32},{n:"expected",k:"i",o:1,lo:1,hi:1e9},{n:"origin",k:"o",o:1,fs:[{n:"x",k:"i",lo:0,hi:16384},{n:"y",k:"i",lo:0,hi:16384}]}],60,"rewardCue");u("gem.walletDisplay",[{n:"visible",k:"b"},{n:"currencies",k:"a",o:1,max:8,it:{n:"",k:"s",max:64}},{n:"score",k:"b",o:1}],60,"walletDisplay");u("gem.controlsDeclare",[{n:"uses",k:"o",fs:[{n:"lookSensitivity",k:"s",o:1,max:16,f:"code"},{n:"gamepadLookSensitivity",k:"s",o:1,max:16,f:"code"},{n:"invertLookY",k:"s",o:1,max:16,f:"code"},{n:"touchMovement",k:"s",o:1,max:16,f:"code"}]}],60,"controls");u("gem.menu",[{n:"settings",k:"b"},{n:"items",k:"a",o:1,max:4,it:{n:"",k:"o",fs:[{n:"id",k:"s",max:32},{n:"label",k:"s",max:40}]}}],60,"gameMenu");u("gem.menuSelect",[{n:"entry",k:"e",v:["settings","item"]},{n:"id",k:"s",o:1,max:32}],60,"gameMenu");u("gem.gemCorner",[{n:"corner",k:"e",v:["top-left","top-right","bottom-left","bottom-right"]}],12,"gemCorner");u("gem.requestShare",[{n:"params",k:"a",max:16,it:{n:"",k:"o",fs:[{n:"key",k:"s",max:64},{n:"value",k:"s",max:512}]}}],6,"share");u("gem.requestAvatarPicker",[{n:"tab",k:"e",o:1,v:["2d","3d"]}],6,"avatarPicker");u("gem.vibrate",[{n:"pattern",k:"a",max:99,it:{n:"",k:"i",lo:0,hi:1e4}}],600,"vibration");u("gem.frameStats",[{n:"fps",k:"i",lo:0,hi:1e3},{n:"frameTimeP95Ms",k:"i",lo:0,hi:1e5}],120,"frameStats");u("gem.portraitBorders",[{n:"name",k:"s",o:1,max:40}],60,"portraitBorders");u("gem.error",[{n:"code",k:"e",v:["version_mismatch","handshake_timeout","handshake_duplicate","invalid_message","rate_limited","token_unavailable","unsupported","unsupported_capability","internal"]},{n:"message",k:"s",o:1,max:256}],60);u("gem.requestPurchase",[{n:"requestId",k:"s",max:64},{n:"purchaseKind",k:"e",v:["item","recipe"]},{n:"targetId",k:"s",max:64},{n:"currencySlug",k:"s",max:32},{n:"quantity",k:"i",o:1,lo:1,hi:10},{n:"catalogId",k:"s",o:1,max:64}],12,"purchases");u("gem.requestAvatar3dPurchase",[{n:"requestId",k:"s",max:64},{n:"itemId",k:"s",max:64},{n:"currencySlug",k:"s",max:32}],12,"avatar3dPurchases");u("gem.purchaseResult",[{n:"requestId",k:"s",max:64},{n:"outcome",k:"e",v:["ok","declined","unavailable"]},{n:"reason",k:"s",o:1,max:64,f:"code"},{n:"purchaseId",k:"s",o:1,max:64}],30,"purchases");u("gem.deviceSettings.put",[{n:"requestId",k:"s",max:64},{n:"settings",k:"j"}],30,"deviceSettings");u("gem.deviceSettings.result",[{n:"requestId",k:"s",max:64},{n:"outcome",k:"e",v:["stored","too_large","unavailable"]}],30,"deviceSettings");u("gem.requestAd",[{n:"requestId",k:"s",max:64},{n:"placement",k:"s",max:32},{n:"format",k:"e",v:["interstitial","rewarded"]}],6,"ads");u("gem.adResult",[{n:"requestId",k:"s",max:64},{n:"outcome",k:"e",v:["shown","no_ad","unavailable"]}],12,"ads");u("gem.signalMoment",[{n:"requestId",k:"s",max:64},{n:"kind",k:"e",v:["level_end","run_end","match_end","menu_return","other_break"]},{n:"placement",k:"s",o:1,max:32}],6,"moments");u("gem.momentResult",[{n:"requestId",k:"s",max:64},{n:"shown",k:"b"}],12,"moments");u("gem.requestSignIn",[{n:"requestId",k:"s",max:64}],6,"signIn");u("gem.signInResult",[{n:"requestId",k:"s",max:64},{n:"outcome",k:"e",v:["signed_in","declined","unavailable"]}],12,"signIn");u("gem.requestFriendChallenge",[{n:"requestId",k:"s",max:64},{n:"playerId",k:"s",max:64},{n:"template",k:"s",max:64},{n:"params",k:"j",o:1}],12,"friendChallenges");u("gem.friendChallengeResult",[{n:"requestId",k:"s",max:64},{n:"outcome",k:"e",v:["accepted","cancelled","refused","unavailable","rate_limited","invalid"]},{n:"code",k:"s",o:1,max:64},{n:"param",k:"s",o:1,max:64},{n:"channel",k:"s",o:1,max:16},{n:"configVersion",k:"i",o:1,lo:0,hi:9007199254740991},{n:"retryAfterMs",k:"i",o:1,lo:0,hi:864e5},{n:"detail",k:"s",o:1,max:300}],30,"friendChallenges");Object.freeze(ie);N.__malformed=60;Object.freeze(N);Object.freeze(oe);var E={now:()=>Date.now(),setTimeout:(n,e)=>setTimeout(n,e),clearTimeout:n=>clearTimeout(n)};var sn=1e4;function le(n,e){return V(n,e)}function V(n,e){if(typeof n.serverToken!="function"||typeof n.onServerToken!="function")throw new Error("this runtime delivers no game-server token: host.serverToken/onServerToken are missing. The server image running this bundle predates token delivery \u2014 the bundle cannot call gem-api on it.");let t=i=>({token:i.token,expiresAt:i.expiresAt,chainEndsAt:Number.POSITIVE_INFINITY}),r=null,o=new B({clock:e.clock,...e.onStateChange===void 0?{}:{onStateChange:e.onStateChange},request:()=>new Promise((i,l)=>{let d=e.clock.setTimeout(()=>{r=null,l({reason:"unavailable",retryable:true});},e.timeoutMs??sn);r={resolve:c=>{e.clock.clearTimeout(d),i(c);},reject:l,timer:d};})}),a=n.onServerToken(i=>{let l=t(i),d=r;if(d){r=null,d.resolve(l);return}o.accept(l);});return {source:o,dispose(){a(),o.dispose(),r&&(e.clock.clearTimeout(r.timer),r.reject({reason:"unavailable",retryable:false}),r=null);}}}var z={};Oe(z,{acceptTransfer:()=>ln,addEntityProgression:()=>dn,adminAction:()=>un,cancelInventoryTransfer:()=>cn,claimEntityProgressionRewards:()=>mn,closeGameRoom:()=>gn,createEntityBatchOrder:()=>pn,createEntityOrder:()=>yn,createSession:()=>fn,deleteEntityGameSetting:()=>hn,deleteEntitySave:()=>_n,deleteSession:()=>bn,deleteShowcaseValue:()=>vn,executeEntityRecipe:()=>Rn,finalizeSaveUpload:()=>xn,getChannelAssignment:()=>kn,getDropRates:()=>Sn,getEntityCurrency:()=>wn,getEntityGameSetting:()=>An,getEntityInventory:()=>Pn,getEntityInventoryItem:()=>On,getEntityLeaderboard:()=>Tn,getEntityOrder:()=>Gn,getEntityProgression:()=>Cn,getEntityRecipeAvailability:()=>In,getEntityRecipeUsage:()=>En,getEntitySave:()=>Mn,getEvent:()=>qn,getGameRoomV2:()=>Ln,getLeaderboard:()=>$n,getPlayerGameProfile:()=>jn,getPurchaseCatalog:()=>Bn,getResolvedTemplate:()=>Fn,getRoomArgs:()=>Un,getShowcaseValue:()=>Nn,getTransferDetails:()=>Dn,ingestAnalyticsEvents:()=>W,initiateInventoryTransfer:()=>Hn,invokeFunction:()=>Vn,kickPlayer:()=>Wn,listChallenges:()=>zn,listEntityGameSettings:()=>Kn,listEntityOrders:()=>Yn,listEntityProgressions:()=>Jn,listEntitySaves:()=>Xn,listEvents:()=>Qn,listGameRooms:()=>Zn,listResolvedTemplates:()=>et,listTransfers:()=>nt,maxEntityProgression:()=>tt,putEntityGameSetting:()=>rt,putRoomArgs:()=>ot,putShowcaseValue:()=>at,rejectTransfer:()=>st,reportMatchPlayers:()=>it,requestSaveUploadUrl:()=>lt,resetEntityProgression:()=>dt,setMatchBackfill:()=>ut,simulateEntityOrder:()=>ct,transferHostV2:()=>mt,updateGameRoomV2:()=>gt});function s(n){let e=String(n);if(!/^[A-Za-z0-9_.-]{1,128}$/.test(e)||e==="."||e==="..")throw new TypeError(`${JSON.stringify(e)} is not a usable path segment \u2014 it is interpolated into a URL`);return encodeURIComponent(e)}async function ln(n,e,t){let r=`/v1/inventory/transfers/${s(e)}/accept`;return n.client.post(r,void 0,t?.signal)}async function dn(n,e,t,r,o,a){let i=`/v1/inventory/${s(e)}/${s(t)}/progressions/${s(r)}/add`;return n.client.post(i,o,a?.signal)}async function un(n,e,t,r){let o=`/v1/voice/sessions/${s(e)}/admin`;return n.client.post(o,t,r?.signal)}async function cn(n,e,t){let r=`/v1/inventory/transfers/${s(e)}/cancel`;return n.client.post(r,void 0,t?.signal)}async function mn(n,e,t,r,o,a){let i=`/v1/inventory/${s(e)}/${s(t)}/progressions/${s(r)}/claim`;return n.client.post(i,o,a?.signal)}async function gn(n,e,t){let r=`/v1/games/${s(n.gameId())}/game-rooms/${s(e)}`;return n.client.delete(r,t?.signal)}async function pn(n,e,t,r,o){let a=`/v1/inventory/${s(e)}/${s(t)}/orders/batch`;return n.client.post(a,r,o?.signal,{...o?.ifMatch===void 0?{}:{ifMatch:o.ifMatch}})}async function yn(n,e,t,r,o){let a=`/v1/inventory/${s(e)}/${s(t)}/orders`;return n.client.post(a,r,o?.signal,{...o?.ifMatch===void 0?{}:{ifMatch:o.ifMatch}})}async function fn(n,e,t){return n.client.post("/v1/voice/sessions",e,t?.signal)}async function hn(n,e,t,r,o){let a=`/v1/settings/${s(e)}/${s(t)}/${s(r)}`;return n.client.delete(a,o?.signal)}async function _n(n,e,t,r,o){let a=`/v1/saves/${s(e)}/${s(t)}/${s(r)}`;return n.client.delete(a,o?.signal)}async function bn(n,e,t){let r=`/v1/voice/sessions/${s(e)}`;return n.client.delete(r,t?.signal)}async function vn(n,e,t,r){let o=`/v1/showcase/players/${s(e)}/${s(t)}`;return n.client.delete(o,r?.signal)}async function Rn(n,e,t,r,o){let a=`/v1/inventory/${s(e)}/${s(t)}/recipes/execute`;return n.client.post(a,r,o?.signal,{...o?.ifMatch===void 0?{}:{ifMatch:o.ifMatch}})}async function xn(n,e,t,r,o,a){let i=`/v1/saves/${s(e)}/${s(t)}/${s(r)}/finalize`;return n.client.post(i,o,a?.signal)}async function kn(n,e,t){let r=`/v1/games/${s(n.gameId())}/config/channels/${s(e)}`;return n.client.getWithEtag(r,{...t?.signal===void 0?{}:{signal:t.signal},...t?.ifNoneMatch===void 0?{}:{ifNoneMatch:t.ifNoneMatch}})}async function Sn(n,e,t){let r=`/v1/inventory/loot-tables/${s(e)}/drop-rates`;return n.client.get(r,t?.signal)}async function wn(n,e,t,r,o){let a=`/v1/inventory/${s(e)}/${s(t)}/currencies/${s(r)}`;return n.client.get(a,o?.signal)}async function An(n,e,t,r,o){let a=`/v1/settings/${s(e)}/${s(t)}/${s(r)}`;return n.client.getWithEtag(a,{...o?.signal===void 0?{}:{signal:o.signal},...o?.ifNoneMatch===void 0?{}:{ifNoneMatch:o.ifNoneMatch}})}async function Pn(n,e,t,r){let o=new URLSearchParams;r?.include_buckets!==void 0&&o.set("include_buckets",String(r?.include_buckets)),r?.include_custom_data!==void 0&&o.set("include_custom_data",String(r?.include_custom_data)),r?.currency_limit!==void 0&&o.set("currency_limit",String(r?.currency_limit)),r?.currency_cursor!==void 0&&o.set("currency_cursor",String(r?.currency_cursor)),r?.item_limit!==void 0&&o.set("item_limit",String(r?.item_limit)),r?.item_cursor!==void 0&&o.set("item_cursor",String(r?.item_cursor)),r?.progression_limit!==void 0&&o.set("progression_limit",String(r?.progression_limit)),r?.progression_cursor!==void 0&&o.set("progression_cursor",String(r?.progression_cursor));let a=o.toString(),i=`/v1/inventory/${s(e)}/${s(t)}`+(a?`?${a}`:"");return n.client.get(i,r?.signal)}async function On(n,e,t,r,o){let a=`/v1/inventory/${s(e)}/${s(t)}/items/${s(r)}`;return n.client.get(a,o?.signal)}async function Tn(n,e,t,r,o){let a=new URLSearchParams;o?.bucket_1!==void 0&&a.set("bucket_1",String(o?.bucket_1)),o?.bucket_2!==void 0&&a.set("bucket_2",String(o?.bucket_2)),o?.limit!==void 0&&a.set("limit",String(o?.limit)),o?.periods_back!==void 0&&a.set("periods_back",String(o?.periods_back)),o?.period!==void 0&&a.set("period",String(o?.period)),o?.player_id!==void 0&&a.set("player_id",String(o?.player_id));let i=a.toString(),l=`/v1/leaderboards/${s(e)}/${s(t)}/${s(r)}`+(i?`?${i}`:"");return n.client.get(l,o?.signal)}async function Gn(n,e,t,r,o){let a=`/v1/inventory/${s(e)}/${s(t)}/orders/${s(r)}`;return n.client.get(a,o?.signal)}async function Cn(n,e,t,r,o){let a=`/v1/inventory/${s(e)}/${s(t)}/progressions/${s(r)}`;return n.client.get(a,o?.signal)}async function In(n,e,t,r,o,a){let i=`/v1/inventory/${s(e)}/${s(t)}/catalogs/${s(r)}/recipes/${s(o)}/availability`;return n.client.get(i,a?.signal)}async function En(n,e,t,r){let o=new URLSearchParams;r?.limit!==void 0&&o.set("limit",String(r?.limit));let a=o.toString(),i=`/v1/inventory/${s(e)}/${s(t)}/recipe-usage`+(a?`?${a}`:"");return n.client.get(i,r?.signal)}async function Mn(n,e,t,r,o){let a=`/v1/saves/${s(e)}/${s(t)}/${s(r)}`;return n.client.getWithEtag(a,{...o?.signal===void 0?{}:{signal:o.signal},...o?.ifNoneMatch===void 0?{}:{ifNoneMatch:o.ifNoneMatch}})}async function qn(n,e,t){let r=`/v1/events/${s(e)}`;return n.client.get(r,t?.signal)}async function Ln(n,e,t){let r=`/v2/games/${s(n.gameId())}/game-rooms/${s(e)}`;return n.client.getWithEtag(r,{...t?.signal===void 0?{}:{signal:t.signal},...t?.ifNoneMatch===void 0?{}:{ifNoneMatch:t.ifNoneMatch}})}async function $n(n,e,t){let r=new URLSearchParams;t?.bucket_1!==void 0&&r.set("bucket_1",String(t?.bucket_1)),t?.bucket_2!==void 0&&r.set("bucket_2",String(t?.bucket_2)),t?.periods_back!==void 0&&r.set("periods_back",String(t?.periods_back)),t?.period!==void 0&&r.set("period",String(t?.period)),t?.player_id!==void 0&&r.set("player_id",String(t?.player_id));let o=r.toString(),a=`/v1/leaderboards/${s(e)}`+(o?`?${o}`:"");return n.client.get(a,t?.signal)}async function jn(n,e,t){let r=`/v1/profiles/players/${s(e)}`;return n.client.get(r,t?.signal)}async function Bn(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 Fn(n,e,t){let r=`/v1/game-room-templates/${s(e)}`;return n.client.get(r,t?.signal)}async function Un(n,e,t){let r=`/v1/games/${s(n.gameId())}/game-rooms/${s(e)}/room-args`;return n.client.get(r,t?.signal)}async function Nn(n,e,t,r){let o=`/v1/showcase/players/${s(e)}/${s(t)}`;return n.client.get(o,r?.signal)}async function Dn(n,e,t){let r=`/v1/inventory/transfers/${s(e)}`;return n.client.get(r,t?.signal)}async function W(n,e,t){let r=`/v1/games/${s(n.gameId())}/analytics/events`;return n.client.post(r,e,t?.signal,{replaySafe:true,retryRateLimited:false})}async function Hn(n,e,t){return n.client.post("/v1/inventory/transfers",e,t?.signal)}async function Vn(n,e,t){return n.client.postBytes("/v1/functions/invoke",e,t?.signal)}async function Wn(n,e,t,r){let o=`/v1/games/${s(n.gameId())}/game-rooms/${s(e)}/kick/${s(t)}`;return n.client.post(o,void 0,r?.signal)}async function zn(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 Kn(n,e,t,r){let o=`/v1/settings/${s(e)}/${s(t)}`;return n.client.get(o,r?.signal)}async function Yn(n,e,t,r){let o=new URLSearchParams;r?.limit!==void 0&&o.set("limit",String(r?.limit)),r?.cursor!==void 0&&o.set("cursor",String(r?.cursor));let a=o.toString(),i=`/v1/inventory/${s(e)}/${s(t)}/orders`+(a?`?${a}`:"");return n.client.get(i,r?.signal)}async function Jn(n,e,t,r){let o=`/v1/inventory/${s(e)}/${s(t)}/progressions`;return n.client.get(o,r?.signal)}async function Xn(n,e,t,r){let o=new URLSearchParams;r?.limit!==void 0&&o.set("limit",String(r?.limit)),r?.cursor!==void 0&&o.set("cursor",String(r?.cursor));let a=o.toString(),i=`/v1/saves/${s(e)}/${s(t)}`+(a?`?${a}`:"");return n.client.get(i,r?.signal)}async function Qn(n,e){let t=new URLSearchParams;e?.include_inactive!==void 0&&t.set("include_inactive",String(e?.include_inactive)),e?.limit!==void 0&&t.set("limit",String(e?.limit)),e?.offset!==void 0&&t.set("offset",String(e?.offset));let r=t.toString(),o="/v1/events"+(r?`?${r}`:"");return n.client.get(o,e?.signal)}async function Zn(n,e){let t=new URLSearchParams;e?.status!==void 0&&t.set("status",String(e?.status)),e?.game_channel!==void 0&&t.set("game_channel",String(e?.game_channel)),e?.game_room_type!==void 0&&t.set("game_room_type",String(e?.game_room_type)),e?.template_id!==void 0&&t.set("template_id",String(e?.template_id)),e?.template_slug!==void 0&&t.set("template_slug",String(e?.template_slug)),e?.limit!==void 0&&t.set("limit",String(e?.limit)),e?.cursor!==void 0&&t.set("cursor",String(e?.cursor));let r=t.toString(),o=`/v1/games/${s(n.gameId())}/game-rooms`+(r?`?${r}`:"");return n.client.get(o,e?.signal)}async function et(n,e){return n.client.get("/v1/game-room-templates",e?.signal)}async function nt(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 tt(n,e,t,r,o,a){let i=`/v1/inventory/${s(e)}/${s(t)}/progressions/${s(r)}/max`;return n.client.post(i,o,a?.signal)}async function rt(n,e,t,r,o,a){let i=`/v1/settings/${s(e)}/${s(t)}/${s(r)}`;return n.client.put(i,o,a?.signal,{...a?.ifMatch===void 0?{}:{ifMatch:a.ifMatch}})}async function ot(n,e,t,r){let o=`/v1/games/${s(n.gameId())}/game-rooms/${s(e)}/room-args`;return n.client.put(o,t,r?.signal)}async function at(n,e,t,r,o){let a=`/v1/showcase/players/${s(e)}/${s(t)}`;return n.client.put(a,r,o?.signal)}async function st(n,e,t){let r=`/v1/inventory/transfers/${s(e)}/reject`;return n.client.post(r,void 0,t?.signal)}async function it(n,e,t,r){let o=`/v1/games/${s(n.gameId())}/matches/${s(e)}/players/report`;return n.client.post(o,t,r?.signal)}async function lt(n,e,t,r,o,a){let i=`/v1/saves/${s(e)}/${s(t)}/${s(r)}/upload-url`;return n.client.post(i,o,a?.signal,{replaySafe:true})}async function dt(n,e,t,r,o,a){let i=`/v1/inventory/${s(e)}/${s(t)}/progressions/${s(r)}/reset`;return n.client.post(i,o,a?.signal)}async function ut(n,e,t,r){let o=`/v1/games/${s(n.gameId())}/matches/${s(e)}/backfill`;return n.client.put(o,t,r?.signal)}async function ct(n,e,t,r,o){let a=`/v1/inventory/${s(e)}/${s(t)}/orders/simulate`;return n.client.post(a,r,o?.signal)}async function mt(n,e,t,r){let o=`/v2/games/${s(n.gameId())}/game-rooms/${s(e)}/transfer/${s(t)}`;return n.client.post(o,void 0,r?.signal)}async function gt(n,e,t,r){let o=`/v2/games/${s(n.gameId())}/game-rooms/${s(e)}`;return n.client.patch(o,t,r?.signal,{...r?.ifMatch===void 0?{}:{ifMatch:r.ifMatch}})}var de="gem_";function ue(n,e){let t=e?.retryAfterSeconds,r=typeof t=="number"&&Number.isFinite(t)&&t>0?t*1e3:0,o=1e4*2**Math.min(Math.max(0,n-1),16);return Math.min(Math.max(r,o),3e5)}var ft=1e4,ht=50,_t=1e3,bt=65536-4*1024,ce=n=>typeof n=="number"?n:0,vt=n=>typeof n=="string"?n:"";function me(){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 Rt(n){return n?.retryable===true}function xt(n,e){let t=n??{},r=Array.isArray(t.rejected)?t.rejected.map(o=>{let a=o??{};return {index:ce(a.index),code:vt(a.code)}}):[];return {accepted:ce(t.accepted),rejected:r,dropped:e,duplicate:t.duplicate===true}}function ge(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 pe(n){let e=Math.max(1,Math.floor(n.maxQueue??_t)),t={client:n.client,gameId:()=>n.gameId},r=[],o=0,a=null,i=false,l=null,d=0,c=0,g=false,h=false,b=v=>{n.log?.(v);},f=()=>{a!==null&&(n.clock.clearTimeout(a),a=null);},p=()=>Math.max(0,c-n.clock.now()),k=()=>{a!==null||i||l!==null||(a=n.clock.setTimeout(()=>{a=null,P().catch(()=>{});},Math.max(ft,p())));},w=()=>{let v=Math.min(r.length,100),R=128;for(let O=0;O<v;O+=1){let T=r[O];if(T===void 0)break;if(R+=JSON.stringify(ge(T,0)).length+1,R>bt)return Math.max(1,O)}return v};async function P(v){for(;l!==null;)await l.catch(()=>{});if(r.length===0)return {accepted:0,rejected:[],dropped:0,duplicate:false};let R=we(v);l=R;try{return await R}finally{l===R&&(l=null),r.length>0&&k();}}async function we(v){f();let R=r.splice(0,w()),O=o;o=0;let T=Math.round(n.clock.now()),j={batch_id:me(),sent_at_ms:T,events:R.map(S=>ge(S,T))};try{let S=await W(t,j,v===void 0?void 0:{signal:v}),G=xt(S,O);d=0,c=0;for(let Ae of G.rejected)b(`[gem] analytics: an event was refused (${Ae.code}). See the analytics_events section of your game config.`);return G}catch(S){if(Rt(S)){for(r=[...R,...r],o+=O;r.length>e;)r.shift(),o+=1;d+=1,c=n.clock.now()+ue(d,S);}else b(`[gem] analytics: ${R.length} event(s) were discarded \u2014 the platform refused the batch and will refuse it again: ${String(S)}`);throw S}}return {track(v,R,O={}){if(i)return;if(typeof v!="string"||v===""){h||(h=true,b(`[gem] analytics: '${R}' 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(R.startsWith(de)){g||(g=true,b(`[gem] analytics: '${R}' 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 T={},j={};for(let[S,G]of Object.entries(O))typeof G=="string"?T[S]=G:typeof G=="number"&&Number.isFinite(G)&&(j[S]=G);for(;r.length>=e;)r.shift(),o+=1;r.push({uid:me(),playerId:v,name:R,atMs:n.clock.now(),dimensions:T,measures:j}),r.length>=ht&&l===null&&p()===0?P().catch(()=>{}):k();},flush:v=>P(v),get pending(){return r.length},dispose(){i=true,f(),r=[],o=0;}}}var kt=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]]),L=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:kt.get(this.code))??super.retryable}},M=class{#e;constructor(e){this.#e=e;}async invoke(e,t={}){let r=St(e),o;try{o=await this.#e(r,t.signal===void 0?{}:{signal:t.signal});}catch(a){throw a instanceof m?At(a):a}return wt(o)}};function St(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 y(`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 y(`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 wt(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 At(n){let{details:e,invocationId:t}=ee(n),o=e?.untrusted?.message,a=e?.reason;return new L(n,{...t===void 0?{}:{invocationId:t},...n.code==="function_error"&&typeof o=="string"?{functionMessage:o}:{},...n.code==="function_failed"&&typeof a=="string"?{failure:a}:{}})}var A=n=>typeof n=="string"?n:"",Pt=/(?:Z|[+-]\d{2}:?\d{2})$/i;function ye(n){let e=A(n);if(!Pt.test(e))return 0;let t=Date.parse(e);return Number.isFinite(t)?Math.floor(t/1e3):0}var Ot=/^[0-9a-f]{1,64}$/,Tt=/^[0-9a-f]{16}$/,Gt=/^[A-Za-z][A-Za-z0-9_+\-/]{0,63}$/,Ct=/^(?:[01]\d|2[0-3]):[0-5]\d$/;function It(n){let e=A(n),t=/^(\d{4})-(\d{2})-(\d{2})$/.exec(e);if(!t)return;let[r,o,a]=[Number(t[1]),Number(t[2]),Number(t[3])],i=new Date(Date.UTC(r,o-1,a));return i.getUTCFullYear()===r&&i.getUTCMonth()===o-1&&i.getUTCDate()===a?e:void 0}var Et=4096,Mt=new TextEncoder;function qt(n){let e=A(n.challenge_data),t=A(n.challenge_data_hash);return e===""||!Tt.test(t)?{}:Mt.encode(e).length>Et?{}:{data:e,dataHash:t}}function Lt(n){let e=n??{},t=ye(e.period_start_at),r=ye(e.period_ends_at);if(t===0||r===0)return;let o=A(e.slug),a=A(e.seed),i=It(e.period_local_date),l=A(e.boundary),d=A(e.reset_time);return {id:A(e.progression_definition_id),...o===""?{}:{slug:o},window:A(e.window),periodStartAt:t,periodEndsAt:r,...i===void 0?{}:{periodLocalDate:i},boundary:Gt.test(l)?l:"",resetTime:Ct.test(d)?d:"",seed:Ot.test(a)?a:"",...qt(e)}}function fe(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 he(n){let e=n??{};return Array.isArray(e.challenges)?e.challenges.map(Lt).filter(t=>t!==void 0):[]}function _e(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().");fe(r);let a=await n({player_id:t,...r===void 0?{}:{periods_back:r},...o===void 0?{}:{signal:o}});return he(a)}}}function $t(n){let e={};for(let[t,r]of Object.entries(z))if(typeof r=="function"){let o=r;e[t]=(...a)=>o(n,...a);}return e}function D(n,e={}){let t=e.clock??E,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=V(n,{clock:t,...e.onAuthStateChange===void 0?{}:{onStateChange:e.onAuthStateChange}}),a=ne({baseUrl:r,tokenSource:o.source,defaultQuery:{game_id:n.gameId,channel:n.channel},...e.fetch===void 0?{}:{fetch:e.fetch}}),i=new C({transport:a,clock:t}),l={gameId:n.gameId,channel:n.channel,matchId:n.matchId,...n.gameRoomId===void 0?{}:{gameRoomId:n.gameRoomId}},d=$t({client:i,gameId:()=>l.gameId}),c=l.gameRoomId,g=n.endMatch,h=n.log,b=pe({client:i,clock:t,gameId:l.gameId,...typeof h=="function"?{log:p=>h.call(n,p)}:{}});return {identity:l,client:i,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);},setBackfill:async(p,k)=>{let w=await d.setMatchBackfill(l.matchId,{open:p.open,...p.seats===void 0?{}:{seats:p.seats}},k===void 0?{}:{signal:k});return {open:w.open,seats:w.seats??null}},reportPlayers:async(p,k)=>(await d.reportMatchPlayers(l.matchId,{players:p.map(P=>({player_id:P.playerId,state:P.state}))},k===void 0?{}:{signal:k})).players.map(P=>({playerId:P.player_id,outcome:P.outcome}))},analytics:b,functions:new M(d.invokeFunction),challenges:_e(d.listChallenges),...c===void 0?{}:{room:{get:p=>d.getGameRoomV2(c,p),args:async p=>{let k=await d.getGameRoomV2(c,p?.signal===void 0?{}:{signal:p.signal}),w=k.modified?k.body:void 0;if(w?.room_args==null||w.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:w.room_args,room_args_template:w.room_args_template}}}},dispose:()=>{b.dispose(),o.dispose();}}}var jt=["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"],Bt=new Set(jt);function be(n){return typeof n=="string"&&Bt.has(n)?n:"unknown"}var x=class{#e;constructor(e){this.#e=e,Object.freeze(this);}toString(){return "[gem: use gem.text.toPlain()]"}toJSON(){return this.toString()}get[Symbol.toStringTag](){return "PlayerText"}static unwrap(e){return e.#e}};function $(n){return new x(n)}var ve={toPlain(n){return x.unwrap(n)},compare(n,e,t){let r=n instanceof x?x.unwrap(n):n,o=e instanceof x?x.unwrap(e):e;if(typeof Intl>"u"||typeof Intl.Collator!="function")return r<o?-1:r>o?1:0;let a;try{a=new Intl.Collator(t);}catch{a=new Intl.Collator;}return a.compare(r,o)},equals(n,e){let t=n instanceof x?x.unwrap(n):n,r=e instanceof x?x.unwrap(e):e;return t.normalize("NFC")===r.normalize("NFC")}};var Re="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 K(n,e={}){let t=e.clock??E,r=()=>{let l=n();if(l===null)throw new Error(Re);return l},o=null,a=()=>{if(o===null)throw new Error(Re);return o};return {server:{get identity(){return a().identity},get client(){return a().client},get api(){return a().api},get match(){return a().match},get analytics(){return a().analytics},get functions(){return a().functions},get challenges(){return a().challenges},get room(){return a().room},dispose(){o?.dispose();},get sizeClass(){return r().sizeClass},get roomArgs(){return r().roomArgs},get roster(){return r().roster},players(){return r().players()},profile(l){let c=r().profile?.(l);if(!c)return null;let g=c.displayName;return typeof g!="string"||g===""?null:{displayName:$(g),...typeof c.displayTag=="string"&&c.displayTag!==""?{displayTag:$(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=D(r(),{...e,clock:t});}}}function xe(n,e={}){let{server:t,attach:r}=K(()=>n,e);return r(),t}function Ft(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:be(e)}}}var Ut=1e4;function Nt(n){let e=false;return t=>{if(e)return;let r;try{r=n.match.reportPlayers([{playerId:t,state:"connected"}],AbortSignal.timeout(Ut));}catch{return}r.catch(o=>{o instanceof m&&o.status>=400&&o.status<500&&(e=o.status!==429);});}}function ke(n,e={}){return ()=>{let t=null,{server:r,attach:o}=K(()=>t,e),a=n(r),i={async init(d){t=d,o(),await a.init?.();},async shutdown(d){let c=Ft(d);try{await a.shutdown?.(c);}finally{r.dispose();}}},l=Nt(r);return i.join=(d,c)=>(l(d),a.join?.(d,c)),a.leave&&(i.leave=(d,c)=>a.leave?.(d,c)),a.message&&(i.message=(d,c,g,h)=>a.message?.(d,c,g,h)),i}}var Dt=new Set(["unlocked","already_unlocked","suppressed"]);function Se(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"||!Dt.has(o.outcome)||typeof o.achievement_id!="string"||o.achievement_id==="")continue;let a=o.outcome;t.push({achievementId:o.achievement_id,progressionDefinitionId:typeof o.progression_definition_id=="string"?o.progression_definition_id:"",points:a==="unlocked"&&typeof o.points=="number"&&Number.isFinite(o.points)?o.points:0,outcome:a,...typeof o.reason=="string"?{reason:o.reason}:{}});}return t}
1
+ var Pe=Object.defineProperty;var Oe=(n,e)=>{for(var t in e)Pe(n,t,{get:e[t],enumerable:true});};globalThis.__gemWebSdkVersion="[gem-web-sdk:sdkVersion:13.2.1]";var Te={initialDelayMs:2e3,maxDelayMs:6e4};function Ge(n,e){return e!==void 0?!e:n==="chain_exhausted"}var B=class{constructor(e){this.options=e;}options;grant=null;state="pending";failure=null;generation=0;inFlight=null;rejected=false;retry=null;failures=0;notBefore=0;disposed=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.pastChainCeiling())throw new _("chain_exhausted","the token chain reached its ceiling");if(this.inFlight===null&&this.options.clock.now()<this.notBefore)throw new _(this.failure??"unavailable","the embedder asked for no new token yet; one is asked for when that wait is over");return this.refresh(this.nextReason())}pastChainCeiling(){return this.grant===null||this.seconds()<this.grant.chainEndsAt?false:(this.enter("lost","chain_exhausted"),true)}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);}dispose(){this.disposed=true,this.cancelRetry();}scheduleRetry(e){if(this.cancelRetry(),this.failures+=1,this.notBefore=e===void 0?0:this.options.clock.now()+e,this.disposed)return;let{initialDelayMs:t,maxDelayMs:r}=Te,o=Math.min(r,t*2**(this.failures-1)),a=Math.max(o/2,e??0)+Math.random()*(o/2);this.retry={handle:this.options.clock.setTimeout(()=>this.retryNow(),a)};}retryNow(){this.retry=null,this.notBefore=0,!(this.state==="lost"||this.pastChainCeiling())&&this.refresh(this.nextReason()).catch(()=>{});}cancelRetry(){this.retry!==null&&(this.options.clock.clearTimeout(this.retry.handle),this.retry=null);}refresh(e){if(this.inFlight)return this.inFlight;this.cancelRetry();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 a=Ce(o),{retryable:i,retryAfterMs:l}=o??{};throw t===this.generation&&(Ge(a,typeof i=="boolean"?i:void 0)?this.enter("lost",a):(this.scheduleRetry(typeof l=="number"&&Number.isFinite(l)&&l>0?l:void 0),this.enter("degraded",a))),o instanceof _?o:new _(a,String(o))}).finally(()=>{this.inFlight===r&&(this.inFlight=null);});return this.inFlight=r,r}enter(e,t){(e==="ready"||e==="lost")&&this.cancelRetry(),e==="ready"&&(this.failures=0,this.notBefore=0),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 Ce(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 y=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}},F=["if-match","if-none-match"],Y=4096;function Ie(n){if(!n)return;let e={};for(let[t,r]of Object.entries(n)){let o=t.toLowerCase();if(!F.includes(o)||r===void 0)continue;let a=typeof r=="string"?Ee(r):r;if(typeof a!="string"||a.length>Y||!Me(a))throw new y(`the ${o} header value cannot be sent \u2014 it is not a string, is longer than ${Y} characters, or contains a character outside the range an HTTP header value may carry. This is a malformed request, not a server failure; the value is withheld here rather than written to logs.`);a!==""&&(e[o]=a);}return Object.freeze(e)}function Ee(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 Me(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 qe(n){let{bytes:e}=n;if(e!==void 0){if(Object.prototype.toString.call(e)!=="[object Uint8Array]")throw new y("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 y("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 J(n,e){let t=e.replayUnauthorizedOnce??true;return {async request(r){let o={...r},a=Ie(o.headers),i=qe(o),l=Object.freeze({...o,headers:a,...i===void 0?{}:{bytes:i}}),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(),h=await n(l,g);if(h.status===401)throw e.tokenSource.close("unavailable"),new _("unavailable","the server refused a freshly minted token");return h}}}function X(n){let e=typeof n=="string"?new TextEncoder().encode(n):n;return btoa(Le(e))}function Le(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,a,i){super(`${t} (${r}): ${o}`);this.reason=t;this.status=r;this.detail=o;this.retryAfterSeconds=a;this.code=i;this.name="GemApiError";}reason;status;detail;retryAfterSeconds;code;get retryable(){return this.reason==="unavailable"||this.reason==="rate_limited"}},Z=new WeakMap;function ee(n){return Z.get(n)??{}}var $e=new Set([408,429,500,502,503,504]),je=6e4;function Be(n){if(n===void 0)return 2;if(!Number.isInteger(n)||n<0||n>10)throw new y(`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 C=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,...q(o)},o.replaySafe===true,o.retryRateLimited!==false)}async post(e,t,r,o={}){return this.send({method:"POST",path:e,body:t,signal:r,...q(o)},o.replaySafe===true,o.retryRateLimited!==false)}async postBytes(e,t,r,o={}){let a=await this.sendRaw({method:"POST",path:e,bytes:t,responseType:"bytes",signal:r,...q(o)},o.replaySafe===true,o.retryRateLimited!==false);return {bytes:Fe(a.body),...a.invocationId===void 0?{}:{invocationId:a.invocationId}}}async patch(e,t,r,o={}){return this.send({method:"PATCH",path:e,body:t,signal:r,...q(o)},o.replaySafe===true,o.retryRateLimited!==false)}async delete(e,t,r={}){return this.send({method:"DELETE",path:e,signal:t,...q(r)},r.replaySafe===true,r.retryRateLimited!==false)}async send(e,t,r=true){return (await this.sendRaw(e,t,r)).body}async sendRaw(e,t,r=true){let o=t?Be(this.options.maxRetries)+1:1,a=null;if(e.signal?.aborted)throw Q(e.signal);for(let i=0;i<o;i++){if(i>0&&await this.backoff(i,a,e.signal),e.signal?.aborted)throw Q(e.signal);let l;try{l=await this.options.transport.request(e);}catch(c){if(_.isAuthError(c)||y.isRefusal(c)||e.signal?.aborted||Ue(c))throw c;a=new m("unavailable",0,String(c));continue}if(l.status>=200&&l.status<300||l.status===304)return l;let d=Ne(l);if(!$e.has(l.status)||l.status===429&&!r)throw d;a=d;}throw a??new m("unavailable",0,"no attempt was made")}backoff(e,t,r){if(r?.aborted)return Promise.resolve();let o=t?.retryAfterSeconds,a=o!==void 0?o*1e3:2**(e-1)*250,i=2**(e-1)*250,l=Math.min(Math.max(a,i),je);return new Promise(d=>{let c=this.options.clock,g=false,h=false,b,f=()=>{g||(g=true,h&&c.clearTimeout(b),r?.removeEventListener("abort",f),d());};r?.addEventListener("abort",f,{once:true}),b=c.setTimeout(f,l),h=true,g&&c.clearTimeout(b);})}};function Fe(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 q(n){return {...n.keepalive===void 0?{}:{keepalive:n.keepalive},...n.ifMatch===void 0?{}:{headers:{"if-match":n.ifMatch}}}}function Q(n){return n.reason!==void 0?n.reason:new DOMException("The operation was aborted.","AbortError")}function Ue(n){let e=n?.name;return e==="AbortError"||e==="TimeoutError"}function Ne(n){let e=He(n),t=We(n.body),r={...t===void 0?{}:{details:t},...n.invocationId===void 0?{}:{invocationId:n.invocationId}};return Object.keys(r).length>0&&Z.set(e,r),e}var De=new Map([["insufficient_funds","insufficient_funds"]]);function He(n){let{status:e,body:t}=n,r=Ve(t),o=n.retryAfterSeconds??Ke(t),a=ze(t),i=a===void 0?void 0:De.get(a);if(i!==void 0)return new m(i,e,r,void 0,a);switch(e){case 304:return new m("not_modified",e,r);case 400:case 422:return new m("invalid",e,r,void 0,a);case 403:return new m("forbidden",e,r,void 0,a);case 404:return new m("not_found",e,r,void 0,a);case 402:return new m("insufficient_funds",e,r,void 0,a);case 409:return new m("conflict",e,r,void 0,a);case 412:return new m("precondition_failed",e,r,void 0,a);case 413:return new m("too_large",e,r,void 0,a);case 429:return new m("rate_limited",e,r,o,a);default:return new m("unavailable",e,r,o,a)}}function Ve(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 We(n){let t=n?.error?.details;return t===null?void 0:t}function ze(n){let t=n?.error?.code;return typeof t=="string"&&t.length>0?t:void 0}function Ke(n){let e=n?.retryAfterSeconds;return typeof e=="number"&&Number.isFinite(e)&&e>=0?e:void 0}function Ye(n){let e=n.lastIndexOf("@");return (e===-1?n:`***@${n.slice(e+1)}`).slice(0,200)}var Je=new Set(F);function Xe(n){if(!n)return {};let e={};for(let[t,r]of Object.entries(n))Je.has(t.toLowerCase())&&(e[t.toLowerCase()]=r);return e}function ne(n){let e=n.fetch??globalThis.fetch.bind(globalThis);return J(async(t,r)=>{let o;try{o=new URL(n.baseUrl.replace(/\/+$/,""));}catch{throw new y("the configured baseUrl is not a valid URL. Its value is withheld here rather than written to logs. This is a configuration fault, not a server failure.")}let a;try{a=new URL(o.href.replace(/\/+$/,"")+t.path);}catch{throw new y(`${JSON.stringify(typeof t.path=="string"?Ye(t.path):"(a non-string path)")} does not form a valid URL against ${o.protocol}//${o.host}. This is a malformed request, not a server failure.`)}if(a.protocol!==o.protocol||a.host!==o.host)throw new y(`${JSON.stringify(a.pathname)} resolves to ${a.protocol}//${a.host}, not ${o.protocol}//${o.host}. A request path may not change the request's origin \u2014 it carries the play token.`);if(a.username!==""||a.password!==""){let f=o.username!==""||o.password!=="",p=a.username!==o.username||a.password!==o.password,k=f?p?"baseUrl (and possibly the request path)":"baseUrl":"request path";throw new y(`the ${k} puts credentials in the URL, which cannot be fetched (${t.method} ${a.pathname}). The value is withheld here rather than written to logs. This is a malformed request, not a server failure.`)}for(let[f,p]of Object.entries(n.defaultQuery??{}))a.searchParams.has(f)||a.searchParams.set(f,p);let i=t.bytes,l=t.bytes===void 0?void 0:"application/octet-stream";try{t.body!==void 0&&(i=JSON.stringify(t.body),l="application/json");}catch(f){throw new y(`the body of ${t.method} ${JSON.stringify(a.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(a.toString(),{method:t.method,headers:{authorization:`Bearer ${r}`,...l===void 0?{}:{"content-type":l},...Xe(t.headers)},body:i,signal:t.signal,...t.keepalive===void 0?{}:{keepalive:t.keepalive},credentials:"omit",mode:"cors",redirect:"error",cache:"no-store",referrerPolicy:"no-referrer"}),c=null;if(t.responseType==="bytes"&&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"),h=Qe(d.headers.get("retry-after")),b=d.headers.get("x-gem-invocation-id");return {status:d.status,body:c,...g===null?{}:{etag:g},...h===void 0?{}:{retryAfterSeconds:h},...b===null||b===""?{}:{invocationId:b}}},n)}function Qe(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 Ze="gem-web-bridge";var I=65536,te=8,U=5e3,re=1024;var N=Object.create(null);var oe=Object.create(null);function en(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 nn(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 tn(n){return /^[a-z]{2,8}(-[a-z0-9]{1,8})*$/i.test(n)}function rn(n){return /^[a-z_]+$/.test(n)}function H(n,e,t){if(e>te)return `nesting deeper than ${te}`;if(++t.nodes>U)return `more than ${U} values`;if(t.bytes>I)return `over the ${I} 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>re)return `an array of ${n.length} entries, over the ${re} limit`;t.bytes+=2;for(let l of n){let d=H(l,e+1,t);if(d)return d}return null}let a=Object.getPrototypeOf(n);if(a!==Object.prototype&&a!==null)return "a value that is not a plain object";t.bytes+=2;let i=n;for(let l in i){if(!Object.prototype.hasOwnProperty.call(i,l))continue;if(++t.nodes>U)return `more than ${U} values`;if(t.bytes+=l.length*3+4,t.bytes>I)return `over the ${I} byte limit`;let d=H(i[l],e+1,t);if(d)return d}return null}function on(n){let e={nodes:0,bytes:0,seen:new Set},t=H(n,0,e);return t?`message contains ${t}`:e.bytes>I?`message is over the ${I} byte limit`:null}var an={origin:[en,"not a well-formed origin"],url:[nn,"not a safe absolute http(s) URL"],bcp47:[tn,"not a well-formed BCP 47 tag"],code:[rn,"not a code of lower-case letters and underscores"]};function ae(n,e,t){for(let r of e){let o=t===""?r.n:`${t}.${r.n}`,a=n[r.n];if(a==null){if(r.o)continue;return `${o}: required`}let i=se(a,r,o);if(i)return i}return null}function se(n,e,t){switch(e.k){case "s":{if(typeof n!="string")return `${t}: expected string`;if(n.length>e.max)return `${t}: exceeds ${e.max} characters`;if(e.f){let[r,o]=an[e.f];if(!r(n))return `${t}: ${o}`}return null}case "i":return typeof n!="number"||!Number.isInteger(n)?`${t}: expected integer`:n<e.lo||n>e.hi?`${t}: out of range ${e.lo}..${e.hi}`:null;case "b":return typeof n=="boolean"?null:`${t}: expected boolean`;case "e":{let r=e.v;return r.includes(n)?null:`${t}: not one of ${r.join("|")}`}case "o":return typeof n!="object"||n===null||Array.isArray(n)?`${t}: expected object`:ae(n,e.fs,t);case "j":return typeof n!="object"||n===null||Array.isArray(n)?`${t}: expected a plain object`:null;case "a":{if(!Array.isArray(n))return `${t}: expected array`;if(n.length>e.max)return `${t}: exceeds ${e.max} items`;let r=e.it,o=`${t}[]`;for(let a of n){if(a==null){if(r.o)continue;return `${o}: required`}let i=se(a,r,o);if(i)return i}return null}default:{let r=e.k;return `${t}: unknown kind ${String(r)}`}}}var ie=Object.create(null);function u(n,e,t,r){return N[n]=t,r&&(oe[n]=r),ie[n]=o=>{let a=on(o);if(a)return a;if(typeof o!="object"||o===null||Array.isArray(o))return "message: expected object";let i=o;return i.gem!==Ze?"gem: wrong protocol marker":i.type!==n?`type: expected ${n}`:ae(i,e,"")}}u("gem.handshake",[{n:"versions",k:"o",fs:[{n:"min",k:"i",lo:1,hi:1e3},{n:"max",k:"i",lo:1,hi:1e3}]},{n:"capabilities",k:"a",o:1,max:64,it:{n:"",k:"s",max:64}},{n:"embedder",k:"s",max:2048,f:"origin"},{n:"unbidden",k:"b",o:1}],30);u("gem.handshake.accept",[{n:"v",k:"i",lo:1,hi:1e3},{n:"capabilities",k:"a",o:1,max:64,it:{n:"",k:"s",max:64}}],5);u("gem.token",[{n:"token",k:"s",max:4096},{n:"requestId",k:"s",o:1,max:64},{n:"generation",k:"i",lo:0,hi:2147483647},{n:"apiBaseUrl",k:"s",o:1,max:512,f:"url"},{n:"playerId",k:"s",max:64},{n:"gameId",k:"s",max:64},{n:"channel",k:"e",v:["dev","test","release"]},{n:"gameVersion",k:"s",o:1,max:64},{n:"expiresAt",k:"i",lo:0,hi:4102444800},{n:"chainEndsAt",k:"i",lo:0,hi:4102444800},{n:"allowDevTools",k:"b",o:1}],30);u("gem.token.denied",[{n:"requestId",k:"s",max:64},{n:"retryable",k:"b"},{n:"retryAfterMs",k:"i",o:1,lo:0,hi:36e5},{n:"reason",k:"e",v:["chain_exhausted","unavailable"]},{n:"correlationId",k:"s",max:64}],30);u("gem.player",[{n:"untrusted",k:"o",fs:[{n:"displayName",k:"s",max:64},{n:"displayTag",k:"s",o:1,max:80},{n:"displayHandle",k:"s",max:80}]},{n:"playerId",k:"s",o:1,max:64},{n:"discriminator",k:"s",o:1,max:8},{n:"avatarIconUrl",k:"s",o:1,max:2048,f:"url"},{n:"avatarIconId",k:"s",o:1,max:64},{n:"avatar3dId",k:"s",o:1,max:64},{n:"avatar3dModelUrl",k:"s",o:1,max:2048,f:"url"},{n:"avatar3dIconUrl",k:"s",o:1,max:2048,f:"url"},{n:"avatars3d",k:"a",o:1,max:8,it:{n:"",k:"o",fs:[{n:"family",k:"s",max:32},{n:"id",k:"s",max:64},{n:"modelUrl",k:"s",max:256,f:"url"},{n:"iconUrl",k:"s",max:256,f:"url"}]}},{n:"badges",k:"a",o:1,max:2,it:{n:"",k:"o",fs:[{n:"itemId",k:"s",max:64},{n:"iconUrl",k:"s",max:2048,f:"url"}]}},{n:"displayTag",k:"s",max:8},{n:"avatarUrl",k:"s",o:1,max:2048,f:"url"},{n:"boost",k:"o",o:1,fs:[{n:"multipliers",k:"a",max:8,it:{n:"",k:"o",fs:[{n:"currencyId",k:"s",max:64},{n:"currencySlug",k:"s",max:32},{n:"multiplierBp",k:"i",lo:1e4,hi:1e6}]}},{n:"expiresInDays",k:"i",o:1,lo:1,hi:7}]}],12);u("gem.pause",[{n:"paused",k:"b"}],120);u("gem.prefs",[{n:"reducedMotion",k:"b"},{n:"muted",k:"b"},{n:"showFrameStats",k:"b",o:1},{n:"locale",k:"s",max:35,f:"bcp47"},{n:"recommended",k:"o",o:1,fs:[{n:"volume",k:"i",lo:0,hi:100},{n:"batterySaver",k:"b"},{n:"keyboardLayout",k:"e",v:["wasd","arrows"]},{n:"gamepadConfirm",k:"e",v:["south","east"]},{n:"vibration",k:"b"},{n:"lookSensitivity",k:"i",o:1,lo:20,hi:400},{n:"gamepadLookSensitivity",k:"i",o:1,lo:20,hi:400},{n:"invertLookY",k:"b",o:1},{n:"touchMovement",k:"s",o:1,max:16,f:"code"},{n:"graphicsQuality",k:"s",o:1,max:16,f:"code"},{n:"graphicsQualityAuto",k:"b",o:1}]}],60);u("gem.cohorts",[{n:"cohorts",k:"a",max:8,it:{n:"",k:"o",fs:[{n:"experimentId",k:"s",max:36},{n:"variantKey",k:"s",max:32}]}}],12,"cohorts");u("gem.earnAllowanceChanged",[],30,"earnAllowance");u("gem.viewport",[{n:"insets",k:"o",fs:[{n:"top",k:"i",lo:0,hi:4096},{n:"right",k:"i",lo:0,hi:4096},{n:"bottom",k:"i",lo:0,hi:4096},{n:"left",k:"i",lo:0,hi:4096}]},{n:"reserved",k:"a",o:1,max:4,it:{n:"",k:"o",fs:[{n:"x",k:"i",lo:0,hi:16384},{n:"y",k:"i",lo:0,hi:16384},{n:"width",k:"i",lo:0,hi:16384},{n:"height",k:"i",lo:0,hi:16384}]}}],60,"viewport");u("gem.deviceSettings",[{n:"settings",k:"j",o:1}],12,"deviceSettings");u("gem.willTerminate",[{n:"reason",k:"e",v:["grant_expiring","session_ended","navigating","kill_switch"]},{n:"graceMs",k:"i",lo:0,hi:6e4}],10);u("gem.roomEvent",[{n:"event",k:"e",v:["updated","match_started","match_ready","match_failed","version_stale"]},{n:"roomId",k:"s",max:64},{n:"matchId",k:"s",o:1,max:64},{n:"version",k:"i",o:1,lo:0,hi:2147483647},{n:"reason",k:"s",o:1,max:64},{n:"platform",k:"e",o:1,v:["universal","mobile"]}],120,"rooms");u("gem.socketState",[{n:"connected",k:"b"},{n:"reason",k:"e",o:1,v:["connecting","dropped","watchdog","terminal"]}],12,"socketState");u("gem.seatedEvent",[{n:"roomId",k:"s",max:64}],60,"partySeating");u("gem.autoStartFailedEvent",[{n:"roomId",k:"s",max:64},{n:"code",k:"s",max:64}],30,"autoStartFailure");u("gem.ticketEvent",[{n:"event",k:"e",v:["queued","matched","expired","cancelled","failed"]},{n:"ticketId",k:"s",max:64},{n:"partySize",k:"i",o:1,lo:1,hi:64},{n:"queuedAt",k:"i",o:1,lo:0,hi:4102444800},{n:"expiresAt",k:"i",o:1,lo:0,hi:4102444800},{n:"reason",k:"s",o:1,max:64},{n:"roomId",k:"s",o:1,max:64}],60,"ticketEvents");u("gem.signalEvent",[{n:"event",k:"e",v:["hello","offer","answer","ice","peerJoined","peerLeft","migration","matchEnded","error"]},{n:"matchId",k:"s",max:64},{n:"data",k:"j"}],1800,"p2p");u("gem.dedicatedEvent",[{n:"event",k:"e",v:["answer","error","matchEnded"]},{n:"matchId",k:"s",max:64},{n:"sdp",k:"s",o:1,max:10240},{n:"sessionId",k:"s",o:1,max:64},{n:"code",k:"s",o:1,max:64},{n:"message",k:"s",o:1,max:256},{n:"reason",k:"s",o:1,max:64}],120,"dedicated");u("gem.partyResult",[{n:"requestId",k:"s",max:64},{n:"partyId",k:"s",o:1,max:64}],30,"parties");u("gem.clusterTarget",[{n:"clusterTargetId",k:"s",max:64},{n:"clusterTargetIds",k:"a",o:1,max:3,it:{n:"",k:"s",max:64}}],12,"clusterTarget");u("gem.devtools",[{n:"action",k:"e",v:["open","close","toggle"]}],30,"devtools");u("gem.screenshot",[{n:"maxWidth",k:"i",lo:1,hi:7680},{n:"maxHeight",k:"i",lo:1,hi:4320}],6,"screenshot");u("gem.screenshot.denied",[{n:"reason",k:"e",v:["not_wired","no_source","unsupported","unreadable","tainted","too_large","busy","declined","failed"]},{n:"retryable",k:"b"}],12,"screenshot");u("gem.requestContext",[],12,"feedbackContext");u("gem.gameContext",[{n:"context",k:"j"}],12,"feedbackContext");u("gem.signal",[{n:"signal",k:"e",v:["join","offer","answer","ice","migrationAck","hostUnreachable"]},{n:"matchId",k:"s",max:64},{n:"data",k:"j"}],1200,"p2p");u("gem.dedicatedOffer",[{n:"matchId",k:"s",max:64},{n:"sdp",k:"s",max:10240},{n:"intent",k:"e",v:["initial","ice_restart","full_reconnect"]}],60,"dedicated");u("gem.partyRequest",[{n:"requestId",k:"s",max:64}],12,"parties");u("gem.ready",[],5);u("gem.engaged",[],5,"engagement");u("gem.progress",[{n:"loaded",k:"i",lo:0,hi:1099511627776},{n:"total",k:"i",lo:0,hi:1099511627776}],600);u("gem.requestToken",[{n:"requestId",k:"s",max:64},{n:"reason",k:"e",v:["initial","expiring","rejected"]}],12);u("gem.requestLocalServer",[{n:"requestId",k:"s",max:64},{n:"gameRoomId",k:"s",max:64}],6,"localHost");u("gem.localServer",[{n:"requestId",k:"s",max:64},{n:"serverId",k:"s",o:1,max:128}],30,"localHost");u("gem.localServer.denied",[{n:"requestId",k:"s",max:64},{n:"retryable",k:"b"},{n:"reason",k:"e",v:["refused","unavailable"]}],30,"localHost");u("gem.exit",[{n:"reason",k:"s",o:1,max:64}],5);u("gem.openExternal",[{n:"url",k:"s",max:2048,f:"url"}],6);u("gem.requestFullscreen",[{n:"enabled",k:"b"}],30);u("gem.audioState",[{n:"muted",k:"b"}],120,"audioState");u("gem.rewardCue",[{n:"currencySlug",k:"s",max:32},{n:"expected",k:"i",o:1,lo:1,hi:1e9},{n:"origin",k:"o",o:1,fs:[{n:"x",k:"i",lo:0,hi:16384},{n:"y",k:"i",lo:0,hi:16384}]}],60,"rewardCue");u("gem.walletDisplay",[{n:"visible",k:"b"},{n:"currencies",k:"a",o:1,max:8,it:{n:"",k:"s",max:64}},{n:"score",k:"b",o:1}],60,"walletDisplay");u("gem.controlsDeclare",[{n:"uses",k:"o",fs:[{n:"lookSensitivity",k:"s",o:1,max:16,f:"code"},{n:"gamepadLookSensitivity",k:"s",o:1,max:16,f:"code"},{n:"invertLookY",k:"s",o:1,max:16,f:"code"},{n:"touchMovement",k:"s",o:1,max:16,f:"code"}]}],60,"controls");u("gem.menu",[{n:"settings",k:"b"},{n:"items",k:"a",o:1,max:4,it:{n:"",k:"o",fs:[{n:"id",k:"s",max:32},{n:"label",k:"s",max:40}]}}],60,"gameMenu");u("gem.menuSelect",[{n:"entry",k:"e",v:["settings","item"]},{n:"id",k:"s",o:1,max:32}],60,"gameMenu");u("gem.gemCorner",[{n:"corner",k:"e",v:["top-left","top-right","bottom-left","bottom-right"]}],12,"gemCorner");u("gem.requestShare",[{n:"params",k:"a",max:16,it:{n:"",k:"o",fs:[{n:"key",k:"s",max:64},{n:"value",k:"s",max:512}]}}],6,"share");u("gem.requestAvatarPicker",[{n:"tab",k:"e",o:1,v:["2d","3d"]}],6,"avatarPicker");u("gem.vibrate",[{n:"pattern",k:"a",max:99,it:{n:"",k:"i",lo:0,hi:1e4}}],600,"vibration");u("gem.frameStats",[{n:"fps",k:"i",lo:0,hi:1e3},{n:"frameTimeP95Ms",k:"i",lo:0,hi:1e5}],120,"frameStats");u("gem.portraitBorders",[{n:"name",k:"s",o:1,max:40}],60,"portraitBorders");u("gem.error",[{n:"code",k:"e",v:["version_mismatch","handshake_timeout","handshake_duplicate","invalid_message","rate_limited","token_unavailable","unsupported","unsupported_capability","internal"]},{n:"message",k:"s",o:1,max:256}],60);u("gem.requestPurchase",[{n:"requestId",k:"s",max:64},{n:"purchaseKind",k:"e",v:["item","recipe"]},{n:"targetId",k:"s",max:64},{n:"currencySlug",k:"s",max:32},{n:"quantity",k:"i",o:1,lo:1,hi:10},{n:"catalogId",k:"s",o:1,max:64}],12,"purchases");u("gem.requestAvatar3dPurchase",[{n:"requestId",k:"s",max:64},{n:"itemId",k:"s",max:64},{n:"currencySlug",k:"s",max:32}],12,"avatar3dPurchases");u("gem.purchaseResult",[{n:"requestId",k:"s",max:64},{n:"outcome",k:"e",v:["ok","declined","unavailable"]},{n:"reason",k:"s",o:1,max:64,f:"code"},{n:"purchaseId",k:"s",o:1,max:64}],30,"purchases");u("gem.deviceSettings.put",[{n:"requestId",k:"s",max:64},{n:"settings",k:"j"}],30,"deviceSettings");u("gem.deviceSettings.result",[{n:"requestId",k:"s",max:64},{n:"outcome",k:"e",v:["stored","too_large","unavailable"]}],30,"deviceSettings");u("gem.requestAd",[{n:"requestId",k:"s",max:64},{n:"placement",k:"s",max:32},{n:"format",k:"e",v:["interstitial","rewarded"]}],6,"ads");u("gem.adResult",[{n:"requestId",k:"s",max:64},{n:"outcome",k:"e",v:["shown","no_ad","unavailable"]}],12,"ads");u("gem.signalMoment",[{n:"requestId",k:"s",max:64},{n:"kind",k:"e",v:["level_end","run_end","match_end","menu_return","other_break"]},{n:"placement",k:"s",o:1,max:32}],6,"moments");u("gem.momentResult",[{n:"requestId",k:"s",max:64},{n:"shown",k:"b"}],12,"moments");u("gem.requestSignIn",[{n:"requestId",k:"s",max:64}],6,"signIn");u("gem.signInResult",[{n:"requestId",k:"s",max:64},{n:"outcome",k:"e",v:["signed_in","declined","unavailable"]}],12,"signIn");u("gem.requestFriendChallenge",[{n:"requestId",k:"s",max:64},{n:"playerId",k:"s",max:64},{n:"template",k:"s",max:64},{n:"params",k:"j",o:1}],12,"friendChallenges");u("gem.friendChallengeResult",[{n:"requestId",k:"s",max:64},{n:"outcome",k:"e",v:["accepted","cancelled","refused","unavailable","rate_limited","invalid"]},{n:"code",k:"s",o:1,max:64},{n:"param",k:"s",o:1,max:64},{n:"channel",k:"s",o:1,max:16},{n:"configVersion",k:"i",o:1,lo:0,hi:9007199254740991},{n:"retryAfterMs",k:"i",o:1,lo:0,hi:864e5},{n:"detail",k:"s",o:1,max:300}],30,"friendChallenges");Object.freeze(ie);N.__malformed=60;Object.freeze(N);Object.freeze(oe);var E={now:()=>Date.now(),setTimeout:(n,e)=>setTimeout(n,e),clearTimeout:n=>clearTimeout(n)};var sn=1e4;function le(n,e){return V(n,e)}function V(n,e){if(typeof n.serverToken!="function"||typeof n.onServerToken!="function")throw new Error("this runtime delivers no game-server token: host.serverToken/onServerToken are missing. The server image running this bundle predates token delivery \u2014 the bundle cannot call gem-api on it.");let t=i=>({token:i.token,expiresAt:i.expiresAt,chainEndsAt:Number.POSITIVE_INFINITY}),r=null,o=new B({clock:e.clock,...e.onStateChange===void 0?{}:{onStateChange:e.onStateChange},request:()=>new Promise((i,l)=>{let d=e.clock.setTimeout(()=>{r=null,l({reason:"unavailable",retryable:true});},e.timeoutMs??sn);r={resolve:c=>{e.clock.clearTimeout(d),i(c);},reject:l,timer:d};})}),a=n.onServerToken(i=>{let l=t(i),d=r;if(d){r=null,d.resolve(l);return}o.accept(l);});return {source:o,dispose(){a(),o.dispose(),r&&(e.clock.clearTimeout(r.timer),r.reject({reason:"unavailable",retryable:false}),r=null);}}}var z={};Oe(z,{acceptTransfer:()=>ln,addEntityProgression:()=>dn,adminAction:()=>un,cancelInventoryTransfer:()=>cn,claimEntityProgressionRewards:()=>mn,closeGameRoom:()=>gn,createEntityBatchOrder:()=>pn,createEntityOrder:()=>yn,createSession:()=>fn,deleteEntityGameSetting:()=>hn,deleteEntitySave:()=>_n,deleteSession:()=>bn,deleteShowcaseValue:()=>vn,executeEntityRecipe:()=>Rn,finalizeSaveUpload:()=>xn,getChannelAssignment:()=>kn,getDropRates:()=>Sn,getEntityCurrency:()=>wn,getEntityGameSetting:()=>An,getEntityInventory:()=>Pn,getEntityInventoryItem:()=>On,getEntityLeaderboard:()=>Tn,getEntityOrder:()=>Gn,getEntityProgression:()=>Cn,getEntityRecipeAvailability:()=>In,getEntityRecipeUsage:()=>En,getEntitySave:()=>Mn,getEvent:()=>qn,getGameRoomV2:()=>Ln,getLeaderboard:()=>$n,getPlayerGameProfile:()=>jn,getPurchaseCatalog:()=>Bn,getResolvedTemplate:()=>Fn,getRoomArgs:()=>Un,getShowcaseValue:()=>Nn,getTransferDetails:()=>Dn,ingestAnalyticsEvents:()=>W,initiateInventoryTransfer:()=>Hn,invokeFunction:()=>Vn,kickPlayer:()=>Wn,listChallenges:()=>zn,listEntityGameSettings:()=>Kn,listEntityOrders:()=>Yn,listEntityProgressions:()=>Jn,listEntitySaves:()=>Xn,listEvents:()=>Qn,listGameRooms:()=>Zn,listResolvedTemplates:()=>et,listTransfers:()=>nt,maxEntityProgression:()=>tt,putEntityGameSetting:()=>rt,putRoomArgs:()=>ot,putShowcaseValue:()=>at,rejectTransfer:()=>st,reportMatchPlayers:()=>it,requestSaveUploadUrl:()=>lt,resetEntityProgression:()=>dt,setMatchBackfill:()=>ut,simulateEntityOrder:()=>ct,transferHostV2:()=>mt,updateGameRoomV2:()=>gt});function s(n){let e=String(n);if(!/^[A-Za-z0-9_.-]{1,128}$/.test(e)||e==="."||e==="..")throw new TypeError(`${JSON.stringify(e)} is not a usable path segment \u2014 it is interpolated into a URL`);return encodeURIComponent(e)}async function ln(n,e,t){let r=`/v1/inventory/transfers/${s(e)}/accept`;return n.client.post(r,void 0,t?.signal)}async function dn(n,e,t,r,o,a){let i=`/v1/inventory/${s(e)}/${s(t)}/progressions/${s(r)}/add`;return n.client.post(i,o,a?.signal)}async function un(n,e,t,r){let o=`/v1/voice/sessions/${s(e)}/admin`;return n.client.post(o,t,r?.signal)}async function cn(n,e,t){let r=`/v1/inventory/transfers/${s(e)}/cancel`;return n.client.post(r,void 0,t?.signal)}async function mn(n,e,t,r,o,a){let i=`/v1/inventory/${s(e)}/${s(t)}/progressions/${s(r)}/claim`;return n.client.post(i,o,a?.signal)}async function gn(n,e,t){let r=`/v1/games/${s(n.gameId())}/game-rooms/${s(e)}`;return n.client.delete(r,t?.signal)}async function pn(n,e,t,r,o){let a=`/v1/inventory/${s(e)}/${s(t)}/orders/batch`;return n.client.post(a,r,o?.signal,{...o?.ifMatch===void 0?{}:{ifMatch:o.ifMatch}})}async function yn(n,e,t,r,o){let a=`/v1/inventory/${s(e)}/${s(t)}/orders`;return n.client.post(a,r,o?.signal,{...o?.ifMatch===void 0?{}:{ifMatch:o.ifMatch}})}async function fn(n,e,t){return n.client.post("/v1/voice/sessions",e,t?.signal)}async function hn(n,e,t,r,o){let a=`/v1/settings/${s(e)}/${s(t)}/${s(r)}`;return n.client.delete(a,o?.signal)}async function _n(n,e,t,r,o){let a=`/v1/saves/${s(e)}/${s(t)}/${s(r)}`;return n.client.delete(a,o?.signal)}async function bn(n,e,t){let r=`/v1/voice/sessions/${s(e)}`;return n.client.delete(r,t?.signal)}async function vn(n,e,t,r){let o=`/v1/showcase/players/${s(e)}/${s(t)}`;return n.client.delete(o,r?.signal)}async function Rn(n,e,t,r,o){let a=`/v1/inventory/${s(e)}/${s(t)}/recipes/execute`;return n.client.post(a,r,o?.signal,{...o?.ifMatch===void 0?{}:{ifMatch:o.ifMatch}})}async function xn(n,e,t,r,o,a){let i=`/v1/saves/${s(e)}/${s(t)}/${s(r)}/finalize`;return n.client.post(i,o,a?.signal)}async function kn(n,e,t){let r=`/v1/games/${s(n.gameId())}/config/channels/${s(e)}`;return n.client.getWithEtag(r,{...t?.signal===void 0?{}:{signal:t.signal},...t?.ifNoneMatch===void 0?{}:{ifNoneMatch:t.ifNoneMatch}})}async function Sn(n,e,t){let r=`/v1/inventory/loot-tables/${s(e)}/drop-rates`;return n.client.get(r,t?.signal)}async function wn(n,e,t,r,o){let a=`/v1/inventory/${s(e)}/${s(t)}/currencies/${s(r)}`;return n.client.get(a,o?.signal)}async function An(n,e,t,r,o){let a=`/v1/settings/${s(e)}/${s(t)}/${s(r)}`;return n.client.getWithEtag(a,{...o?.signal===void 0?{}:{signal:o.signal},...o?.ifNoneMatch===void 0?{}:{ifNoneMatch:o.ifNoneMatch}})}async function Pn(n,e,t,r){let o=new URLSearchParams;r?.include_buckets!==void 0&&o.set("include_buckets",String(r?.include_buckets)),r?.include_custom_data!==void 0&&o.set("include_custom_data",String(r?.include_custom_data)),r?.currency_limit!==void 0&&o.set("currency_limit",String(r?.currency_limit)),r?.currency_cursor!==void 0&&o.set("currency_cursor",String(r?.currency_cursor)),r?.item_limit!==void 0&&o.set("item_limit",String(r?.item_limit)),r?.item_cursor!==void 0&&o.set("item_cursor",String(r?.item_cursor)),r?.progression_limit!==void 0&&o.set("progression_limit",String(r?.progression_limit)),r?.progression_cursor!==void 0&&o.set("progression_cursor",String(r?.progression_cursor));let a=o.toString(),i=`/v1/inventory/${s(e)}/${s(t)}`+(a?`?${a}`:"");return n.client.get(i,r?.signal)}async function On(n,e,t,r,o){let a=`/v1/inventory/${s(e)}/${s(t)}/items/${s(r)}`;return n.client.get(a,o?.signal)}async function Tn(n,e,t,r,o){let a=new URLSearchParams;o?.bucket_1!==void 0&&a.set("bucket_1",String(o?.bucket_1)),o?.bucket_2!==void 0&&a.set("bucket_2",String(o?.bucket_2)),o?.limit!==void 0&&a.set("limit",String(o?.limit)),o?.periods_back!==void 0&&a.set("periods_back",String(o?.periods_back)),o?.period!==void 0&&a.set("period",String(o?.period)),o?.player_id!==void 0&&a.set("player_id",String(o?.player_id));let i=a.toString(),l=`/v1/leaderboards/${s(e)}/${s(t)}/${s(r)}`+(i?`?${i}`:"");return n.client.get(l,o?.signal)}async function Gn(n,e,t,r,o){let a=`/v1/inventory/${s(e)}/${s(t)}/orders/${s(r)}`;return n.client.get(a,o?.signal)}async function Cn(n,e,t,r,o){let a=`/v1/inventory/${s(e)}/${s(t)}/progressions/${s(r)}`;return n.client.get(a,o?.signal)}async function In(n,e,t,r,o,a){let i=`/v1/inventory/${s(e)}/${s(t)}/catalogs/${s(r)}/recipes/${s(o)}/availability`;return n.client.get(i,a?.signal)}async function En(n,e,t,r){let o=new URLSearchParams;r?.limit!==void 0&&o.set("limit",String(r?.limit));let a=o.toString(),i=`/v1/inventory/${s(e)}/${s(t)}/recipe-usage`+(a?`?${a}`:"");return n.client.get(i,r?.signal)}async function Mn(n,e,t,r,o){let a=`/v1/saves/${s(e)}/${s(t)}/${s(r)}`;return n.client.getWithEtag(a,{...o?.signal===void 0?{}:{signal:o.signal},...o?.ifNoneMatch===void 0?{}:{ifNoneMatch:o.ifNoneMatch}})}async function qn(n,e,t){let r=`/v1/events/${s(e)}`;return n.client.get(r,t?.signal)}async function Ln(n,e,t){let r=`/v2/games/${s(n.gameId())}/game-rooms/${s(e)}`;return n.client.getWithEtag(r,{...t?.signal===void 0?{}:{signal:t.signal},...t?.ifNoneMatch===void 0?{}:{ifNoneMatch:t.ifNoneMatch}})}async function $n(n,e,t){let r=new URLSearchParams;t?.bucket_1!==void 0&&r.set("bucket_1",String(t?.bucket_1)),t?.bucket_2!==void 0&&r.set("bucket_2",String(t?.bucket_2)),t?.periods_back!==void 0&&r.set("periods_back",String(t?.periods_back)),t?.period!==void 0&&r.set("period",String(t?.period)),t?.player_id!==void 0&&r.set("player_id",String(t?.player_id));let o=r.toString(),a=`/v1/leaderboards/${s(e)}`+(o?`?${o}`:"");return n.client.get(a,t?.signal)}async function jn(n,e,t){let r=`/v1/profiles/players/${s(e)}`;return n.client.get(r,t?.signal)}async function Bn(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 Fn(n,e,t){let r=`/v1/game-room-templates/${s(e)}`;return n.client.get(r,t?.signal)}async function Un(n,e,t){let r=`/v1/games/${s(n.gameId())}/game-rooms/${s(e)}/room-args`;return n.client.get(r,t?.signal)}async function Nn(n,e,t,r){let o=`/v1/showcase/players/${s(e)}/${s(t)}`;return n.client.get(o,r?.signal)}async function Dn(n,e,t){let r=`/v1/inventory/transfers/${s(e)}`;return n.client.get(r,t?.signal)}async function W(n,e,t){let r=`/v1/games/${s(n.gameId())}/analytics/events`;return n.client.post(r,e,t?.signal,{replaySafe:true,retryRateLimited:false})}async function Hn(n,e,t){return n.client.post("/v1/inventory/transfers",e,t?.signal)}async function Vn(n,e,t){return n.client.postBytes("/v1/functions/invoke",e,t?.signal)}async function Wn(n,e,t,r){let o=`/v1/games/${s(n.gameId())}/game-rooms/${s(e)}/kick/${s(t)}`;return n.client.post(o,void 0,r?.signal)}async function zn(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 Kn(n,e,t,r){let o=`/v1/settings/${s(e)}/${s(t)}`;return n.client.get(o,r?.signal)}async function Yn(n,e,t,r){let o=new URLSearchParams;r?.limit!==void 0&&o.set("limit",String(r?.limit)),r?.cursor!==void 0&&o.set("cursor",String(r?.cursor));let a=o.toString(),i=`/v1/inventory/${s(e)}/${s(t)}/orders`+(a?`?${a}`:"");return n.client.get(i,r?.signal)}async function Jn(n,e,t,r){let o=`/v1/inventory/${s(e)}/${s(t)}/progressions`;return n.client.get(o,r?.signal)}async function Xn(n,e,t,r){let o=new URLSearchParams;r?.limit!==void 0&&o.set("limit",String(r?.limit)),r?.cursor!==void 0&&o.set("cursor",String(r?.cursor));let a=o.toString(),i=`/v1/saves/${s(e)}/${s(t)}`+(a?`?${a}`:"");return n.client.get(i,r?.signal)}async function Qn(n,e){let t=new URLSearchParams;e?.include_inactive!==void 0&&t.set("include_inactive",String(e?.include_inactive)),e?.limit!==void 0&&t.set("limit",String(e?.limit)),e?.offset!==void 0&&t.set("offset",String(e?.offset));let r=t.toString(),o="/v1/events"+(r?`?${r}`:"");return n.client.get(o,e?.signal)}async function Zn(n,e){let t=new URLSearchParams;e?.status!==void 0&&t.set("status",String(e?.status)),e?.game_channel!==void 0&&t.set("game_channel",String(e?.game_channel)),e?.game_room_type!==void 0&&t.set("game_room_type",String(e?.game_room_type)),e?.template_id!==void 0&&t.set("template_id",String(e?.template_id)),e?.template_slug!==void 0&&t.set("template_slug",String(e?.template_slug)),e?.limit!==void 0&&t.set("limit",String(e?.limit)),e?.cursor!==void 0&&t.set("cursor",String(e?.cursor));let r=t.toString(),o=`/v1/games/${s(n.gameId())}/game-rooms`+(r?`?${r}`:"");return n.client.get(o,e?.signal)}async function et(n,e){return n.client.get("/v1/game-room-templates",e?.signal)}async function nt(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 tt(n,e,t,r,o,a){let i=`/v1/inventory/${s(e)}/${s(t)}/progressions/${s(r)}/max`;return n.client.post(i,o,a?.signal)}async function rt(n,e,t,r,o,a){let i=`/v1/settings/${s(e)}/${s(t)}/${s(r)}`;return n.client.put(i,o,a?.signal,{...a?.ifMatch===void 0?{}:{ifMatch:a.ifMatch}})}async function ot(n,e,t,r){let o=`/v1/games/${s(n.gameId())}/game-rooms/${s(e)}/room-args`;return n.client.put(o,t,r?.signal)}async function at(n,e,t,r,o){let a=`/v1/showcase/players/${s(e)}/${s(t)}`;return n.client.put(a,r,o?.signal)}async function st(n,e,t){let r=`/v1/inventory/transfers/${s(e)}/reject`;return n.client.post(r,void 0,t?.signal)}async function it(n,e,t,r){let o=`/v1/games/${s(n.gameId())}/matches/${s(e)}/players/report`;return n.client.post(o,t,r?.signal)}async function lt(n,e,t,r,o,a){let i=`/v1/saves/${s(e)}/${s(t)}/${s(r)}/upload-url`;return n.client.post(i,o,a?.signal,{replaySafe:true})}async function dt(n,e,t,r,o,a){let i=`/v1/inventory/${s(e)}/${s(t)}/progressions/${s(r)}/reset`;return n.client.post(i,o,a?.signal)}async function ut(n,e,t,r){let o=`/v1/games/${s(n.gameId())}/matches/${s(e)}/backfill`;return n.client.put(o,t,r?.signal)}async function ct(n,e,t,r,o){let a=`/v1/inventory/${s(e)}/${s(t)}/orders/simulate`;return n.client.post(a,r,o?.signal)}async function mt(n,e,t,r){let o=`/v2/games/${s(n.gameId())}/game-rooms/${s(e)}/transfer/${s(t)}`;return n.client.post(o,void 0,r?.signal)}async function gt(n,e,t,r){let o=`/v2/games/${s(n.gameId())}/game-rooms/${s(e)}`;return n.client.patch(o,t,r?.signal,{...r?.ifMatch===void 0?{}:{ifMatch:r.ifMatch}})}var de="gem_";function ue(n,e){let t=e?.retryAfterSeconds,r=typeof t=="number"&&Number.isFinite(t)&&t>0?t*1e3:0,o=1e4*2**Math.min(Math.max(0,n-1),16);return Math.min(Math.max(r,o),3e5)}var ft=1e4,ht=50,_t=1e3,bt=65536-4*1024,ce=n=>typeof n=="number"?n:0,vt=n=>typeof n=="string"?n:"";function me(){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 Rt(n){return n?.retryable===true}function xt(n,e){let t=n??{},r=Array.isArray(t.rejected)?t.rejected.map(o=>{let a=o??{};return {index:ce(a.index),code:vt(a.code)}}):[];return {accepted:ce(t.accepted),rejected:r,dropped:e,duplicate:t.duplicate===true}}function ge(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 pe(n){let e=Math.max(1,Math.floor(n.maxQueue??_t)),t={client:n.client,gameId:()=>n.gameId},r=[],o=0,a=null,i=false,l=null,d=0,c=0,g=false,h=false,b=v=>{n.log?.(v);},f=()=>{a!==null&&(n.clock.clearTimeout(a),a=null);},p=()=>Math.max(0,c-n.clock.now()),k=()=>{a!==null||i||l!==null||(a=n.clock.setTimeout(()=>{a=null,P().catch(()=>{});},Math.max(ft,p())));},w=()=>{let v=Math.min(r.length,100),R=128;for(let O=0;O<v;O+=1){let T=r[O];if(T===void 0)break;if(R+=JSON.stringify(ge(T,0)).length+1,R>bt)return Math.max(1,O)}return v};async function P(v){for(;l!==null;)await l.catch(()=>{});if(r.length===0)return {accepted:0,rejected:[],dropped:0,duplicate:false};let R=we(v);l=R;try{return await R}finally{l===R&&(l=null),r.length>0&&k();}}async function we(v){f();let R=r.splice(0,w()),O=o;o=0;let T=Math.round(n.clock.now()),j={batch_id:me(),sent_at_ms:T,events:R.map(S=>ge(S,T))};try{let S=await W(t,j,v===void 0?void 0:{signal:v}),G=xt(S,O);d=0,c=0;for(let Ae of G.rejected)b(`[gem] analytics: an event was refused (${Ae.code}). See the analytics_events section of your game config.`);return G}catch(S){if(Rt(S)){for(r=[...R,...r],o+=O;r.length>e;)r.shift(),o+=1;d+=1,c=n.clock.now()+ue(d,S);}else b(`[gem] analytics: ${R.length} event(s) were discarded \u2014 the platform refused the batch and will refuse it again: ${String(S)}`);throw S}}return {track(v,R,O={}){if(i)return;if(typeof v!="string"||v===""){h||(h=true,b(`[gem] analytics: '${R}' 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(R.startsWith(de)){g||(g=true,b(`[gem] analytics: '${R}' 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 T={},j={};for(let[S,G]of Object.entries(O))typeof G=="string"?T[S]=G:typeof G=="number"&&Number.isFinite(G)&&(j[S]=G);for(;r.length>=e;)r.shift(),o+=1;r.push({uid:me(),playerId:v,name:R,atMs:n.clock.now(),dimensions:T,measures:j}),r.length>=ht&&l===null&&p()===0?P().catch(()=>{}):k();},flush:v=>P(v),get pending(){return r.length},dispose(){i=true,f(),r=[],o=0;}}}var kt=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]]),L=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:kt.get(this.code))??super.retryable}},M=class{#e;constructor(e){this.#e=e;}async invoke(e,t={}){let r=St(e),o;try{o=await this.#e(r,t.signal===void 0?{}:{signal:t.signal});}catch(a){throw a instanceof m?At(a):a}return wt(o)}};function St(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 y(`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 y(`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 wt(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 At(n){let{details:e,invocationId:t}=ee(n),o=e?.untrusted?.message,a=e?.reason;return new L(n,{...t===void 0?{}:{invocationId:t},...n.code==="function_error"&&typeof o=="string"?{functionMessage:o}:{},...n.code==="function_failed"&&typeof a=="string"?{failure:a}:{}})}var A=n=>typeof n=="string"?n:"",Pt=/(?:Z|[+-]\d{2}:?\d{2})$/i;function ye(n){let e=A(n);if(!Pt.test(e))return 0;let t=Date.parse(e);return Number.isFinite(t)?Math.floor(t/1e3):0}var Ot=/^[0-9a-f]{1,64}$/,Tt=/^[0-9a-f]{16}$/,Gt=/^[A-Za-z][A-Za-z0-9_+\-/]{0,63}$/,Ct=/^(?:[01]\d|2[0-3]):[0-5]\d$/;function It(n){let e=A(n),t=/^(\d{4})-(\d{2})-(\d{2})$/.exec(e);if(!t)return;let[r,o,a]=[Number(t[1]),Number(t[2]),Number(t[3])],i=new Date(Date.UTC(r,o-1,a));return i.getUTCFullYear()===r&&i.getUTCMonth()===o-1&&i.getUTCDate()===a?e:void 0}var Et=4096,Mt=new TextEncoder;function qt(n){let e=A(n.challenge_data),t=A(n.challenge_data_hash);return e===""||!Tt.test(t)?{}:Mt.encode(e).length>Et?{}:{data:e,dataHash:t}}function Lt(n){let e=n??{},t=ye(e.period_start_at),r=ye(e.period_ends_at);if(t===0||r===0)return;let o=A(e.slug),a=A(e.seed),i=It(e.period_local_date),l=A(e.boundary),d=A(e.reset_time);return {id:A(e.progression_definition_id),...o===""?{}:{slug:o},window:A(e.window),periodStartAt:t,periodEndsAt:r,...i===void 0?{}:{periodLocalDate:i},boundary:Gt.test(l)?l:"",resetTime:Ct.test(d)?d:"",seed:Ot.test(a)?a:"",...qt(e)}}function fe(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 he(n){let e=n??{};return Array.isArray(e.challenges)?e.challenges.map(Lt).filter(t=>t!==void 0):[]}function _e(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().");fe(r);let a=await n({player_id:t,...r===void 0?{}:{periods_back:r},...o===void 0?{}:{signal:o}});return he(a)}}}function $t(n){let e={};for(let[t,r]of Object.entries(z))if(typeof r=="function"){let o=r;e[t]=(...a)=>o(n,...a);}return e}function D(n,e={}){let t=e.clock??E,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=V(n,{clock:t,...e.onAuthStateChange===void 0?{}:{onStateChange:e.onAuthStateChange}}),a=ne({baseUrl:r,tokenSource:o.source,defaultQuery:{game_id:n.gameId,channel:n.channel},...e.fetch===void 0?{}:{fetch:e.fetch}}),i=new C({transport:a,clock:t}),l={gameId:n.gameId,channel:n.channel,matchId:n.matchId,...n.gameRoomId===void 0?{}:{gameRoomId:n.gameRoomId}},d=$t({client:i,gameId:()=>l.gameId}),c=l.gameRoomId,g=n.endMatch,h=n.log,b=pe({client:i,clock:t,gameId:l.gameId,...typeof h=="function"?{log:p=>h.call(n,p)}:{}});return {identity:l,client:i,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);},setBackfill:async(p,k)=>{let w=await d.setMatchBackfill(l.matchId,{open:p.open,...p.seats===void 0?{}:{seats:p.seats}},k===void 0?{}:{signal:k});return {open:w.open,seats:w.seats??null}},reportPlayers:async(p,k)=>(await d.reportMatchPlayers(l.matchId,{players:p.map(P=>({player_id:P.playerId,state:P.state}))},k===void 0?{}:{signal:k})).players.map(P=>({playerId:P.player_id,outcome:P.outcome}))},analytics:b,functions:new M(d.invokeFunction),challenges:_e(d.listChallenges),...c===void 0?{}:{room:{get:p=>d.getGameRoomV2(c,p),args:async p=>{let k=await d.getGameRoomV2(c,p?.signal===void 0?{}:{signal:p.signal}),w=k.modified?k.body:void 0;if(w?.room_args==null||w.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:w.room_args,room_args_template:w.room_args_template}}}},dispose:()=>{b.dispose(),o.dispose();}}}var jt=["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"],Bt=new Set(jt);function be(n){return typeof n=="string"&&Bt.has(n)?n:"unknown"}var x=class{#e;constructor(e){this.#e=e,Object.freeze(this);}toString(){return "[gem: use gem.text.toPlain()]"}toJSON(){return this.toString()}get[Symbol.toStringTag](){return "PlayerText"}static unwrap(e){return e.#e}};function $(n){return new x(n)}var ve={toPlain(n){return x.unwrap(n)},compare(n,e,t){let r=n instanceof x?x.unwrap(n):n,o=e instanceof x?x.unwrap(e):e;if(typeof Intl>"u"||typeof Intl.Collator!="function")return r<o?-1:r>o?1:0;let a;try{a=new Intl.Collator(t);}catch{a=new Intl.Collator;}return a.compare(r,o)},equals(n,e){let t=n instanceof x?x.unwrap(n):n,r=e instanceof x?x.unwrap(e):e;return t.normalize("NFC")===r.normalize("NFC")}};var Re="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 K(n,e={}){let t=e.clock??E,r=()=>{let l=n();if(l===null)throw new Error(Re);return l},o=null,a=()=>{if(o===null)throw new Error(Re);return o};return {server:{get identity(){return a().identity},get client(){return a().client},get api(){return a().api},get match(){return a().match},get analytics(){return a().analytics},get functions(){return a().functions},get challenges(){return a().challenges},get room(){return a().room},dispose(){o?.dispose();},get sizeClass(){return r().sizeClass},get roomArgs(){return r().roomArgs},get roster(){return r().roster},players(){return r().players()},profile(l){let c=r().profile?.(l);if(!c)return null;let g=c.displayName;return typeof g!="string"||g===""?null:{displayName:$(g),...typeof c.displayTag=="string"&&c.displayTag!==""?{displayTag:$(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=D(r(),{...e,clock:t});}}}function xe(n,e={}){let{server:t,attach:r}=K(()=>n,e);return r(),t}function Ft(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:be(e)}}}var Ut=1e4;function Nt(n){let e=false;return t=>{if(e)return;let r;try{r=n.match.reportPlayers([{playerId:t,state:"connected"}],AbortSignal.timeout(Ut));}catch{return}r.catch(o=>{o instanceof m&&o.status>=400&&o.status<500&&(e=o.status!==429);});}}function ke(n,e={}){return ()=>{let t=null,{server:r,attach:o}=K(()=>t,e),a=n(r),i={async init(d){t=d,o(),await a.init?.();},async shutdown(d){let c=Ft(d);try{await a.shutdown?.(c);}finally{r.dispose();}}},l=Nt(r);return i.join=(d,c)=>(l(d),a.join?.(d,c)),a.leave&&(i.leave=(d,c)=>a.leave?.(d,c)),a.message&&(i.message=(d,c,g,h)=>a.message?.(d,c,g,h)),i}}var Dt=new Set(["unlocked","already_unlocked","suppressed"]);function Se(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"||!Dt.has(o.outcome)||typeof o.achievement_id!="string"||o.achievement_id==="")continue;let a=o.outcome;t.push({achievementId:o.achievement_id,progressionDefinitionId:typeof o.progression_definition_id=="string"?o.progression_definition_id:"",points:a==="unlocked"&&typeof o.points=="number"&&Number.isFinite(o.points)?o.points:0,outcome:a,...typeof o.reason=="string"?{reason:o.reason}:{}});}return t}
2
2
  export{_ as AuthError,F as CONDITIONAL_HEADERS,M as FunctionsApi,m as GemApiError,C as GemClient,L as GemFunctionError,x as PlayerText,y as TransportRefusal,Se as achievementReceipts,$ as asPlayerText,D as createGemServer,le as createHostTokenSource,xe as createMatchServer,ke as defineServer,E as systemClock,ve as text,X as toBase64};//# sourceMappingURL=gem-web-sdk.server.js.map
3
3
  //# sourceMappingURL=gem-web-sdk.server.js.map
@@ -1,6 +1,6 @@
1
1
  # The function surface — API reference
2
2
 
3
- Generated from `@indiegems/gem-web-sdk/function` v13.2.0, the version of the package this file ships in. Every symbol below carries an explicit anchor, its `anchor` in `reference.json` beside this file.
3
+ Generated from `@indiegems/gem-web-sdk/function` v13.2.1, the version of the package this file ships in. Every symbol below carries an explicit anchor, its `anchor` in `reference.json` beside this file.
4
4
 
5
5
  `@indiegems/gem-web-sdk/function` exports exactly the symbols on this page and nothing else.
6
6
 
@@ -1,6 +1,6 @@
1
1
  # The browser surface — API reference
2
2
 
3
- Generated from `@indiegems/gem-web-sdk/sdk` v13.2.0, the version of the package this file ships in. Every symbol below carries an explicit anchor, its `anchor` in `reference.json` beside this file.
3
+ Generated from `@indiegems/gem-web-sdk/sdk` v13.2.1, the version of the package this file ships in. Every symbol below carries an explicit anchor, its `anchor` in `reference.json` beside this file.
4
4
 
5
5
  `@indiegems/gem-web-sdk/sdk` is the one import a game writes, wherever its code runs. `@indiegems/gem-web-sdk/game` exports exactly the symbols on this page and nothing else, for a build that wants only this half.
6
6
 
@@ -7221,9 +7221,8 @@ const { accepted, why } = result.json();
7221
7221
  ARCADE_EMBEDDERS: readonly string[]
7222
7222
  ```
7223
7223
 
7224
- The origins the platform embeds a game from, which every game accepts
7225
- without naming them: the Gem Arcade website, the Meme Games website, and
7226
- the Gem Arcade app.
7224
+ The origins the Gem Arcade embeds a game from, which every game accepts
7225
+ without naming them: the website, and the Gem Arcade app.
7227
7226
 
7228
7227
  You do not pass these. They are always allowed, and
7229
7228
  [GemOptions.allowedEmbedders](#gemoptions-allowedembedders) adds to them rather than replacing them.
@@ -7252,7 +7251,7 @@ readonly allowedEmbedders?: readonly string[]
7252
7251
  Extra origins allowed to embed your game, **added to** the ones the Gem
7253
7252
  Arcade uses. Most games leave this out.
7254
7253
 
7255
- The platform's websites and the Gem Arcade app are always allowed — see
7254
+ The website and the Gem Arcade app are always allowed — see
7256
7255
  [ARCADE_EMBEDDERS](#arcade_embedders) — so do not list them. Set this only when a site
7257
7256
  of your own embeds your game.
7258
7257
 
@@ -1,6 +1,6 @@
1
1
  # The server surface — API reference
2
2
 
3
- Generated from `@indiegems/gem-web-sdk/sdk` v13.2.0, the version of the package this file ships in. Every symbol below carries an explicit anchor, its `anchor` in `reference.json` beside this file.
3
+ Generated from `@indiegems/gem-web-sdk/sdk` v13.2.1, the version of the package this file ships in. Every symbol below carries an explicit anchor, its `anchor` in `reference.json` beside this file.
4
4
 
5
5
  `@indiegems/gem-web-sdk/sdk` is the one import a game writes, wherever its code runs. `@indiegems/gem-web-sdk/server` exports exactly the symbols on this page and nothing else, for a build that wants only this half.
6
6
 
@@ -2,7 +2,7 @@
2
2
  "schema_version": 2,
3
3
  "source": {
4
4
  "repo": "IndieGems/gem-web-sdk",
5
- "version": "13.2.0"
5
+ "version": "13.2.1"
6
6
  },
7
7
  "entries": [
8
8
  {
@@ -8342,7 +8342,7 @@
8342
8342
  "group": "start",
8343
8343
  "signature": "ARCADE_EMBEDDERS: readonly string[]",
8344
8344
  "documented": true,
8345
- "summary": "The origins the platform embeds a game from, which every game accepts\nwithout naming them: the Gem Arcade website, the Meme Games website, and\nthe Gem Arcade app.\n\nYou do not pass these. They are always allowed, and\n[GemOptions.allowedEmbedders](api-reference-game.md#gemoptions-allowedembedders) adds to them rather than replacing them.",
8345
+ "summary": "The origins the Gem Arcade embeds a game from, which every game accepts\nwithout naming them: the website, and the Gem Arcade app.\n\nYou do not pass these. They are always allowed, and\n[GemOptions.allowedEmbedders](api-reference-game.md#gemoptions-allowedembedders) adds to them rather than replacing them.",
8346
8346
  "deprecated": null,
8347
8347
  "params": [],
8348
8348
  "returns": null,
@@ -8374,7 +8374,7 @@
8374
8374
  "group": "start",
8375
8375
  "signature": "readonly allowedEmbedders?: readonly string[]",
8376
8376
  "documented": true,
8377
- "summary": "Extra origins allowed to embed your game, **added to** the ones the Gem\nArcade uses. Most games leave this out.\n\nThe platform's websites and the Gem Arcade app are always allowed — see\n[ARCADE_EMBEDDERS](api-reference-game.md#arcade_embedders) — so do not list them. Set this only when a site\nof your own embeds your game.\n\n```js\ncreateGem({ allowedEmbedders: ['https://my-own-site.example'] })\n```\n\nA page whose origin is not allowed gets no connection, and — deliberately —\nis told nothing about why. That means a typo here looks exactly like a\nhandshake that has not arrived: pass [GemOptions.onRefused](api-reference-game.md#gemoptions-onrefused) while you\nare integrating, because it is the only place the difference shows.\n\n⚠️ **Bake these in. Never build them from anything the page can\ninfluence** — not `location`, not a query parameter, not\n`document.referrer`. A value the embedder supplies is a check that can never\nfail. Do not add a `localhost:<port>` entry for your dev host either; the\nSDK admits one on your own machine by rule.",
8377
+ "summary": "Extra origins allowed to embed your game, **added to** the ones the Gem\nArcade uses. Most games leave this out.\n\nThe website and the Gem Arcade app are always allowed — see\n[ARCADE_EMBEDDERS](api-reference-game.md#arcade_embedders) — so do not list them. Set this only when a site\nof your own embeds your game.\n\n```js\ncreateGem({ allowedEmbedders: ['https://my-own-site.example'] })\n```\n\nA page whose origin is not allowed gets no connection, and — deliberately —\nis told nothing about why. That means a typo here looks exactly like a\nhandshake that has not arrived: pass [GemOptions.onRefused](api-reference-game.md#gemoptions-onrefused) while you\nare integrating, because it is the only place the difference shows.\n\n⚠️ **Bake these in. Never build them from anything the page can\ninfluence** — not `location`, not a query parameter, not\n`document.referrer`. A value the embedder supplies is a check that can never\nfail. Do not add a `localhost:<port>` entry for your dev host either; the\nSDK admits one on your own machine by rule.",
8378
8378
  "deprecated": null,
8379
8379
  "params": [],
8380
8380
  "returns": null,
package/docs/changelog.md CHANGED
@@ -16,6 +16,12 @@ Its entries are grouped under up to five headings:
16
16
  - **Rebuild**: a type changed. Recompile against the new version; code that compiles today keeps compiling unless the entry says otherwise.
17
17
  - **New capability**: something a game can now do. Nothing changes unless you use it.
18
18
 
19
+ ## 13.2.1
20
+
21
+ Upgrading from 13.2.0. Impact: none.
22
+
23
+ Nothing in this release asks anything of a game.
24
+
19
25
  ## 13.2.0
20
26
 
21
27
  Upgrading from 13.1.0. Impact: required.
@@ -50,7 +50,7 @@ either way.
50
50
  ```jsonc
51
51
  // package.json
52
52
  "dependencies": {
53
- "@indiegems/gem-web-sdk": "13.2.0"
53
+ "@indiegems/gem-web-sdk": "13.2.1"
54
54
  }
55
55
  ```
56
56
 
@@ -38,8 +38,8 @@
38
38
  },
39
39
  {
40
40
  "file": "changelog.md",
41
- "sha256": "f8f5f19344ac446a047ffa9862c33b0a1b580df19350b02120a5803489c29e5a",
42
- "updated": "2026-10-15T00:36:54Z"
41
+ "sha256": "474618b1fbfa9d43ae4cb797019f6c799e1ad2de9fad8fa66875f428c7fe599d",
42
+ "updated": "2026-10-15T15:43:44Z"
43
43
  },
44
44
  {
45
45
  "file": "daily-challenges.md",
@@ -68,8 +68,8 @@
68
68
  },
69
69
  {
70
70
  "file": "getting-started.md",
71
- "sha256": "2d6b7037380aa843e0f3179071fc3d2bd8d7398d851d0d4d0a2d1a7ce1f87d5d",
72
- "updated": "2026-10-15T00:36:54Z"
71
+ "sha256": "b3617f6056165a881a786f331a809f200d79ed8151d06cb26acba544a9c3dde9",
72
+ "updated": "2026-10-15T15:43:44Z"
73
73
  },
74
74
  {
75
75
  "file": "inventory-and-catalogs.md",
@@ -128,8 +128,8 @@
128
128
  },
129
129
  {
130
130
  "file": "server-bundles.md",
131
- "sha256": "adc06113f0412812ce09dfd53039247dd77db4ea702d25f02092258e21e32690",
132
- "updated": "2026-10-15T00:36:54Z"
131
+ "sha256": "3ec75df469f44b3f299c45e237fabc74ede5a42444a14f0b35e068198109558d",
132
+ "updated": "2026-10-15T15:43:44Z"
133
133
  },
134
134
  {
135
135
  "file": "serverless-functions-js.md",
@@ -138,8 +138,8 @@
138
138
  },
139
139
  {
140
140
  "file": "serverless-functions.md",
141
- "sha256": "ca2ed41db94acdd3553126a98395172f6f960199ce514b5ad8c877c5f5bdbe78",
142
- "updated": "2026-10-14T23:28:53Z"
141
+ "sha256": "eef5fa14dced0bca39b4f4b9d6688d4f81d6c4d2441ec3497380c21b7482022a",
142
+ "updated": "2026-10-15T14:37:57Z"
143
143
  },
144
144
  {
145
145
  "file": "trading-and-gifting.md",
@@ -153,8 +153,8 @@
153
153
  },
154
154
  {
155
155
  "file": "what-a-game-must-do.md",
156
- "sha256": "976cf27a12ab1ff86f685e3d4e6a0b444858ab3d780e8466c682f06121ddee2b",
157
- "updated": "2026-10-14T22:38:02Z"
156
+ "sha256": "439683ca206b2230e48ab46d5eb9a945964fb6f2e308ffcc8ec1e1b9423fc5e8",
157
+ "updated": "2026-10-15T13:34:34Z"
158
158
  }
159
159
  ]
160
160
  }
@@ -80,8 +80,8 @@ To check the download yourself: the package npm serves is, byte for byte, the fi
80
80
  also publishes on its download host, with the hash beside it:
81
81
 
82
82
  ```bash
83
- curl -fsSL -O https://downloads.gemarcade.com/sdk/v13.2.0/gem-web-sdk.tgz
84
- curl -fsSL https://downloads.gemarcade.com/sdk/v13.2.0/gem-web-sdk.tgz.sri
83
+ curl -fsSL -O https://downloads.gemarcade.com/sdk/v13.2.1/gem-web-sdk.tgz
84
+ curl -fsSL https://downloads.gemarcade.com/sdk/v13.2.1/gem-web-sdk.tgz.sri
85
85
  openssl dgst -sha384 -binary gem-web-sdk.tgz | openssl base64 -A
86
86
  ```
87
87
 
@@ -815,6 +815,60 @@ be downloaded — and its `invoke` answer is its only record.
815
815
  Every `message` was written by your function's code, and any member of your game's team can read
816
816
  it. Log ids, not anything personal about a player.
817
817
 
818
+ ### Seeing how your functions perform
819
+
820
+ `gemctl function usage` reads the platform's own counters for every call on every channel,
821
+ `release` included. Logs say why one call failed. Usage says how many calls failed, how they
822
+ failed, how slow the calls were, and how close they came to the limits in section 2.
823
+
824
+ ```bash
825
+ gemctl function usage # every channel, the platform's window
826
+ gemctl function usage --channel release --days 28 # one channel, the last 28 days
827
+ gemctl function usage --from 2026-10-01 --to 2026-10-07 --json # a chosen week, every figure
828
+ ```
829
+
830
+ - **The window** is `--days 7`, `28` or `90` (UTC days, today included), or `--from` and `--to`
831
+ (UTC `YYYY-MM-DD`, both days included; `--to` defaults to today). With neither, the platform
832
+ chooses. The answer always says which days it covered, and says so when the platform shortened
833
+ a long window.
834
+ - **`--channel`** (`dev`, `test` or `release`) shows one channel. Without it, every channel is
835
+ shown.
836
+ - **`--json`** prints every figure for every day. At a terminal you get each channel's totals over
837
+ the window first. Then comes one row per channel per day with its calls and failed calls, and
838
+ with `--channel` that row also shows `p99_ms`. A day with no calls has no row. Today is still
839
+ being counted.
840
+
841
+ The figures:
842
+
843
+ | Figure | What it counts |
844
+ | ------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
845
+ | `calls` | Every call the platform counted on that channel |
846
+ | `failed_calls` | All failed calls: `errors` (`handle` returned `Err`), `timeouts`, `cpu_exceeded`, `failed` (a trap, memory, the platform-call limit, or a result or value over its cap) and `unavailable` (the platform could not run it) |
847
+ | `avg_ms`, `p50_ms`, `p95_ms`, `p99_ms`, `max_ms` | **Wall time** in milliseconds: how long a call took from start to finish. `max_ms` is the longest call |
848
+ | `cpu_ms_total`, `cpu_ms_max` | **CPU time** in milliseconds: all calls added together, and the most one call used |
849
+ | `memory_peak_bytes` | The highest memory peak of any one call |
850
+
851
+ **Wall time and CPU time measure different things.** Wall time is the whole call, measured by the
852
+ clock. It includes time your function spends waiting on `call-api`, `download-link` and
853
+ `upload-link`. CPU time counts only the time your own code was running. The limits are 5 seconds
854
+ of wall time and 1 second of CPU time. A call with a high wall time and a low CPU time is mostly
855
+ waiting on the platform. Compare `max_ms` with 5000, `cpu_ms_max` with 1000, and
856
+ `memory_peak_bytes` with 256 MiB to see how close your function comes to its limits.
857
+
858
+ ⚠️ **p50, p95 and p99 are estimates, not exact figures.** The platform does not keep every call's
859
+ time. Each day it puts each call into one of a fixed set of time ranges, for each channel, and
860
+ reads the percentiles from those daily counts. Below 6 ms an estimate is exact. Above that it can be
861
+ off by up to about a third. `max_ms` and `avg_ms` are exact. A day counted before the platform
862
+ started keeping these counts has no percentiles: it shows `-` at a terminal and `null` in
863
+ `--json`, never 0. When a window reaches back past that day, `percentiles_cover` says how many of
864
+ the calls the totals' percentiles describe.
865
+
866
+ **The website shows the same daily counts.** Open the **Functions** tab of your game's **Builds**
867
+ page and go to **Daily usage**. It shows one channel at a time over the last 7, 28 or 90 days. You
868
+ get each day's calls, failed calls by kind, the longest call, CPU time and peak memory. It does
869
+ not show percentiles or the average call time, so use gemctl for those. Anyone at Member level or
870
+ above on your game's team can read usage, in both places, whether the game is published or not.
871
+
818
872
  ## 8. When a call is refused
819
873
 
820
874
  Every answer from a call that reached your function carries an invocation id: success,
@@ -53,9 +53,8 @@ No `baseUrl`. The Arcade names the backend on every token and the SDK routes the
53
53
  tokens only if its origin is allowed, and the pages that matter are always allowed without a word
54
54
  from you:
55
55
 
56
- - **the platform's websites (Gem Arcade and Meme Games) and the Gem Arcade app** — the SDK carries
57
- their origins as `ARCADE_EMBEDDERS`, on every platform the app runs on. Your game is listed on
58
- one of the websites, but it accepts every origin in that list;
56
+ - **the Gem Arcade website and app** — the SDK carries their origins as `ARCADE_EMBEDDERS`, on every
57
+ platform the app runs on;
59
58
  - **a dev host on your own machine** — `gemctl serve` and the Gem Editor frame a locally-served game
60
59
  from a loopback origin whose port changes every run, and the SDK admits that shape by rule, only
61
60
  while your game itself is served from loopback. Once published, nothing about the rule applies.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@indiegems/gem-web-sdk",
3
- "version": "13.2.0",
3
+ "version": "13.2.1",
4
4
  "description": "postMessage bridge contract between gem-web and browser-playable games",
5
5
  "license": "UNLICENSED",
6
6
  "type": "module",