@indiegems/gem-web-sdk 24.0.2 → 24.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,3 +1,3 @@
1
- var We=Object.defineProperty;var ze=(n,e)=>{for(var t in e)We(n,t,{get:e[t],enumerable:true});};globalThis.__gemWebSdkVersion="[gem-web-sdk:sdkVersion:24.0.2]";var Ke={initialDelayMs:2e3,maxDelayMs:6e4};function Ye(n,e){return e!==void 0?!e:n==="chain_exhausted"}var V=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 b(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 b("chain_exhausted","the token chain reached its ceiling");if(this.inFlight===null&&this.options.clock.now()<this.notBefore)throw new b(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}=Ke,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 b("internal","token arrived for a superseded generation");return this.grant=o,this.rejected=false,this.enter("ready"),o.token}).catch(o=>{let a=Je(o),{retryable:i,retryAfterMs:l}=o??{};throw t===this.generation&&(Ye(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 b?o:new b(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)}},b=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 Je(n){if(n instanceof b)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}},W=["if-match","if-none-match"],ae=4096;function Xe(n){if(!n)return;let e={};for(let[t,r]of Object.entries(n)){let o=t.toLowerCase();if(!W.includes(o)||r===void 0)continue;let a=typeof r=="string"?Qe(r):r;if(typeof a!="string"||a.length>ae||!Ze(a))throw new y(`the ${o} header value cannot be sent \u2014 it is not a string, is longer than ${ae} 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 Qe(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 Ze(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 en(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 se(n,e){let t=e.replayUnauthorizedOnce??true;return {async request(r){let o={...r},a=Xe(o.headers),i=en(o),l=Object.freeze({...o,headers:a,...i===void 0?{}:{bytes:i}}),u=await e.tokenSource.get(),c=await n(l,u);if(c.status!==401||!t)return c;e.tokenSource.invalidate(u);let p=await e.tokenSource.get(),f=await n(l,p);if(f.status===401)throw e.tokenSource.close("unavailable"),new b("unavailable","the server refused a freshly minted token");return f}}}function ie(n){let e=typeof n=="string"?new TextEncoder().encode(n):n;return btoa(nn(e))}function nn(n){let t="";for(let r=0;r<n.length;r+=32768)t+=String.fromCharCode(...n.subarray(r,r+32768));return t}var g=class extends Error{constructor(t,r,o,a,i){super(`${t} (${r}): ${o}`);this.reason=t;this.status=r;this.detail=o;this.retryAfterSeconds=a;this.code=i;this.name="GemApiError";}reason;status;detail;retryAfterSeconds;code;get retryable(){return this.reason==="unavailable"||this.reason==="rate_limited"}},ue=new WeakMap;function ce(n){return ue.get(n)??{}}var tn=new Set([408,429,500,502,503,504]),rn=6e4,on=new WeakMap;function le(n){return n!==null&&(n.reason==="rate_limited"||n.retryAfterSeconds!==void 0)}function an(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 L=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,...$(o)},o.replaySafe===true,o.retryRateLimited!==false)}async post(e,t,r,o={}){return this.send({method:"POST",path:e,body:t,signal:r,...$(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,...$(o)},o.replaySafe===true,o.retryRateLimited!==false);return {bytes:sn(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,...$(o)},o.replaySafe===true,o.retryRateLimited!==false)}async delete(e,t,r={}){return this.send({method:"DELETE",path:e,signal:t,...$(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?an(this.options.maxRetries)+1:1,a=null;if(e.signal?.aborted)throw de(e.signal);let i=e.signal===void 0?void 0:on.get(e.signal);for(let l=0;l<o;l++){if(l>0){let p=this.backoffMs(l,a);if(le(a)&&i!==void 0&&p>=i())throw a;await this.backoff(p,e.signal);}if(e.signal?.aborted)throw le(a)&&i!==void 0&&i()<=0?a:de(e.signal);let u;try{u=await this.options.transport.request(e);}catch(p){if(b.isAuthError(p)||y.isRefusal(p)||e.signal?.aborted||ln(p))throw p;a=new g("unavailable",0,String(p));continue}if(u.status>=200&&u.status<300||u.status===304)return u;let c=pe(u);if(!tn.has(u.status)||u.status===429&&!r)throw c;a=c;}throw a??new g("unavailable",0,"no attempt was made")}backoffMs(e,t){let r=t?.retryAfterSeconds,o=r!==void 0?r*1e3:2**(e-1)*250,a=2**(e-1)*250;return Math.min(Math.max(o,a),rn)}backoff(e,t){return t?.aborted?Promise.resolve():new Promise(r=>{let o=this.options.clock,a=false,i=false,l,u=()=>{a||(a=true,i&&o.clearTimeout(l),t?.removeEventListener("abort",u),r());};t?.addEventListener("abort",u,{once:true}),l=o.setTimeout(u,e),i=true,a&&o.clearTimeout(l);})}};function sn(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 $(n){return {...n.keepalive===void 0?{}:{keepalive:n.keepalive},...n.ifMatch===void 0?{}:{headers:{"if-match":n.ifMatch}}}}function de(n){return n.reason!==void 0?n.reason:new DOMException("The operation was aborted.","AbortError")}function ln(n){let e=n?.name;return e==="AbortError"||e==="TimeoutError"}function me(n,e){return pe({status:n,body:e})}function pe(n){let e=un(n),t=mn(n.body),r={...t===void 0?{}:{details:t},...n.invocationId===void 0?{}:{invocationId:n.invocationId}};return Object.keys(r).length>0&&ue.set(e,r),e}var dn=new Map([["insufficient_funds","insufficient_funds"]]);function un(n){let{status:e,body:t}=n,r=cn(t),o=n.retryAfterSeconds??gn(t),a=pn(t),i=a===void 0?void 0:dn.get(a);if(i!==void 0)return new g(i,e,r,void 0,a);switch(e){case 304:return new g("not_modified",e,r);case 400:case 422:return new g("invalid",e,r,void 0,a);case 403:return new g("forbidden",e,r,void 0,a);case 404:return new g("not_found",e,r,void 0,a);case 402:return new g("insufficient_funds",e,r,void 0,a);case 409:return new g("conflict",e,r,void 0,a);case 412:return new g("precondition_failed",e,r,void 0,a);case 413:return new g("too_large",e,r,void 0,a);case 429:return new g("rate_limited",e,r,o,a);default:return new g("unavailable",e,r,o,a)}}function cn(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 mn(n){let t=n?.error?.details;return t===null?void 0:t}function pn(n){let t=n?.error?.code;return typeof t=="string"&&t.length>0?t:void 0}function gn(n){let e=n?.retryAfterSeconds;return typeof e=="number"&&Number.isFinite(e)&&e>=0?e:void 0}function yn(n){let e=n.lastIndexOf("@");return (e===-1?n:`***@${n.slice(e+1)}`).slice(0,200)}var fn=new Set(W);function hn(n){if(!n)return {};let e={};for(let[t,r]of Object.entries(n))fn.has(t.toLowerCase())&&(e[t.toLowerCase()]=r);return e}function ge(n){let e=n.fetch??globalThis.fetch.bind(globalThis);return se(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"?yn(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 _=o.username!==""||o.password!=="",E=a.username!==o.username||a.password!==o.password,h=_?E?"baseUrl (and possibly the request path)":"baseUrl":"request path";throw new y(`the ${h} 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[_,E]of Object.entries(n.defaultQuery??{}))a.searchParams.has(_)||a.searchParams.set(_,E);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(_){throw new y(`the body of ${t.method} ${JSON.stringify(a.pathname)} could not be serialised to JSON: ${String(_)}. This is a bug in the request, not a server failure \u2014 retrying sends the same unserialisable value.`)}let u=await e(a.toString(),{method:t.method,headers:{authorization:`Bearer ${r}`,...l===void 0?{}:{"content-type":l},...hn(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"&&u.status>=200&&u.status<300)c=new Uint8Array(await u.arrayBuffer());else {let _=await u.text();if(_.length>0)try{c=JSON.parse(_);}catch{c=_;}}let p=u.headers.get("etag"),f=_n(u.headers.get("retry-after")),x=u.headers.get("x-gem-invocation-id");return {status:u.status,body:c,...p===null?{}:{etag:p},...f===void 0?{}:{retryAfterSeconds:f},...x===null||x===""?{}:{invocationId:x}}},n)}function _n(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 bn="gem-web-bridge";var Rn=65536,ye=8,z=5e3,fe=1024;var K=Object.create(null);var he=Object.create(null);function vn(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 Sn(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 xn(n){return /^[a-z]{2,8}(-[a-z0-9]{1,8})*$/i.test(n)}function wn(n){return /^[a-z_]+$/.test(n)}function kn(n){return /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(n)||/^[a-z0-9][a-z0-9-]{1,38}[a-z0-9]$/.test(n)&&!n.includes("--")}function J(n,e,t){if(e>ye)return `nesting deeper than ${ye}`;if(++t.nodes>z)return `more than ${z} values`;if(t.bytes>t.cap)return `over the ${t.cap} byte limit`;if(n==null)return t.bytes+=4,null;let r=typeof n;if(r==="boolean")return t.bytes+=5,null;if(r==="number")return t.bytes+=8,null;if(r==="string")return t.bytes+=n.length*3+2,null;if(r!=="object")return `${r} is not plain data`;let 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>fe)return `an array of ${n.length} entries, over the ${fe} limit`;t.bytes+=2;for(let l of n){let u=J(l,e+1,t);if(u)return u}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>z)return `more than ${z} values`;if(t.bytes+=l.length*3+4,t.bytes>t.cap)return `over the ${t.cap} byte limit`;let u=J(i[l],e+1,t);if(u)return u}return null}function An(n,e=Rn){let t={nodes:0,bytes:0,seen:new Set,cap:e},r=J(n,0,t);return r?`message contains ${r}`:t.bytes>e?`message is over the ${e} byte limit`:null}var Pn={origin:[vn,"not a well-formed origin"],url:[Sn,"not a safe absolute http(s) URL"],bcp47:[xn,"not a well-formed BCP 47 tag"],code:[wn,"not a code of lower-case letters and underscores"],gameRef:[kn,"not a game id or web address"]};function _e(n,e,t){for(let r of e){let o=t===""?r[0]:`${t}.${r[0]}`,a=n[r[0]];if(a==null){if(r[1]<"a")continue;return `${o}: required`}let i=X(a,r,o);if(i)return i}return null}function X(n,e,t){let r=e[1].toLowerCase();switch(r){case "u":return typeof n=="boolean"?null:X(n,typeof n=="string"?[e[0],"s",e[2]]:[e[0],"n",e[3],e[4]],t);case "s":{if(typeof n!="string")return `${t}: expected string`;if(n.length>e[2])return `${t}: exceeds ${e[2]} characters`;if(e[3]){let[o,a]=Pn[e[3]];if(!o(n))return `${t}: ${a}`}return null}case "n":case "i":return typeof n!="number"||!(r=="i"?Number.isInteger:Number.isFinite)(n)?`${t}: expected ${r=="i"?"integer":"number"}`:n<e[2]||n>e[3]?`${t}: out of range ${e[2]}..${e[3]}`:null;case "b":return typeof n=="boolean"?null:`${t}: expected boolean`;case "e":{let o=e[2];return o.includes(n)?null:`${t}: not one of ${o.join("|")}`}case "o":return typeof n!="object"||n===null||Array.isArray(n)?`${t}: expected object`:_e(n,e[2],t);case "j":return typeof n!="object"||n===null||Array.isArray(n)?`${t}: expected a plain object`:null;case "a":{if(!Array.isArray(n))return `${t}: expected array`;if(n.length>e[2])return `${t}: exceeds ${e[2]} items`;let o=e[3],a=`${t}[]`;for(let i of n){if(i==null){if(o[1]<"a")continue;return `${a}: required`}let l=X(i,o,a);if(l)return l}return null}default:return `${t}: unknown kind ${String(r)}`}}var be=Object.create(null);function d(n,e,t,r,o){return K[n]=t,r&&(he[n]=r),be[n]=a=>{let i=An(a,o);if(i)return i;if(typeof a!="object"||a===null||Array.isArray(a))return "message: expected object";let l=a;return l.gem!==bn?"gem: wrong protocol marker":l.type!==n?`type: expected ${n}`:_e(l,e,"")}}var B=["","s",64],m=["requestId","s",64],F=["currencySlug","s",32],D=["matchId","s",64],G=["reason","S",64,"code"],C=["outcome","e",["ok","declined","unavailable"]];d("gem.handshake",[["versions","o",[["min","i",1,1e3],["max","i",1,1e3]]],["capabilities","A",64,B],["embedder","s",2048,"origin"],["unbidden","B"]],30);d("gem.handshake.accept",[["v","i",1,1e3],["capabilities","A",64,B]],5);d("gem.token",[["token","s",4096],["requestId","S",64],["generation","i",0,2147483647],["apiBaseUrl","S",512,"url"],["playerId","s",64],["gameId","s",64],["channel","e",["dev","test","release"]],["gameVersion","S",64],["expiresAt","i",0,4102444800],["chainEndsAt","i",0,4102444800],["allowDevTools","B"]],30);d("gem.token.denied",[m,["retryable","b"],["retryAfterMs","I",0,36e5],["reason","e",["chain_exhausted","unavailable"]],["correlationId","s",64]],30);d("gem.player",[["untrusted","o",[["displayName","s",64],["displayTag","S",80],["displayHandle","s",80]]],["playerId","S",64],["discriminator","S",8],["avatarIconUrl","S",2048,"url"],["avatarIconId","S",64],["avatar3dId","S",64],["avatar3dModelUrl","S",2048,"url"],["avatar3dIconUrl","S",2048,"url"],["avatars3d","A",8,["","o",[["family","s",32],["id","s",64],["modelUrl","s",256,"url"],["iconUrl","s",256,"url"]]]],["badges","A",2,["","o",[["itemId","s",64],["iconUrl","s",2048,"url"]]]],["displayTag","s",8],["avatarUrl","S",2048,"url"],["boost","O",[["multipliers","a",8,["","o",[["currencyId","s",64],F,["multiplierBp","i",1e4,1e6]]]],["expiresInDays","I",1,7]]],["signInAvailable","B"]],12);d("gem.pause",[["paused","b"]],120);d("gem.prefs",[["reducedMotion","b"],["muted","b"],["showFrameStats","B"],["music","B"],["sounds","B"],["locale","s",35,"bcp47"],["recommended","O",[["volume","i",0,100],["batterySaver","b"],["keyboardLayout","e",["wasd","arrows"]],["gamepadConfirm","e",["south","east"]],["vibration","b"],["lookSensitivity","I",20,400],["gamepadLookSensitivity","I",20,400],["invertLookY","B"],["touchMovement","S",16,"code"],["graphicsQuality","S",16,"code"],["graphicsQualityAuto","B"],["colorHelp","B"],["textScale","I",100,200]]]],60);d("gem.cohorts",[["cohorts","a",8,["","o",[["experimentId","s",36],["variantKey","s",32]]]]],12,"cohorts");d("gem.earnAllowanceChanged",[],30,"earnAllowance");d("gem.inventoryChanged",[],30,"inventoryChanged");d("gem.viewport",[["insets","o",[["top","i",0,4096],["right","i",0,4096],["bottom","i",0,4096],["left","i",0,4096]]],["reserved","A",4,["","o",[["x","i",0,16384],["y","i",0,16384],["width","i",0,16384],["height","i",0,16384],["control","O",[["x","i",0,16384],["y","i",0,16384],["width","i",0,16384],["height","i",0,16384]]]]]]],60,"viewport");d("gem.deviceSettings",[["settings","J"]],12,"deviceSettings");d("gem.willTerminate",[["reason","e",["grant_expiring","session_ended","navigating","kill_switch"]],["graceMs","i",0,6e4]],10);d("gem.roomEvent",[["event","e",["updated","match_started","match_ready","match_failed","version_stale"]],["roomId","s",64],["matchId","S",64],["version","I",0,2147483647],["reason","S",64],["platform","E",["universal","mobile"]]],120,"rooms");d("gem.socketState",[["connected","b"],["reason","E",["connecting","dropped","watchdog","terminal"]]],12,"socketState");d("gem.seatedEvent",[["roomId","s",64]],60,"partySeating");d("gem.autoStartFailedEvent",[["roomId","s",64],["code","s",64]],30,"autoStartFailure");d("gem.ticketEvent",[["event","e",["queued","matched","expired","cancelled","failed"]],["ticketId","s",64],["partySize","I",1,64],["queuedAt","I",0,4102444800],["expiresAt","I",0,4102444800],["reason","S",64],["roomId","S",64]],60,"ticketEvents");d("gem.signalEvent",[["event","e",["hello","offer","answer","ice","peerJoined","peerLeft","migration","matchEnded","error"]],D,["data","j"]],1800,"p2p");d("gem.relayDraining",[D,["clusterTargetId","s",64],["relayIps","a",16,B],["drainingSince","s",40],["deadline","s",40]],60,"p2pRelayDrain");d("gem.dedicatedEvent",[["event","e",["answer","error","matchEnded"]],D,["sdp","S",10240],["sessionId","S",64],["code","S",64],["message","S",256],["reason","S",64]],120,"dedicated");d("gem.partyResult",[m,["partyId","S",64]],30,"parties");d("gem.clusterTarget",[["clusterTargetId","s",64],["clusterTargetIds","A",3,B]],12,"clusterTarget");d("gem.graphicsRoutes",[["entries","a",32,["","o",[["gpu","s",32],["route","S",32],["host","S",32]]]]],12,"graphicsRoutes");d("gem.devtools",[["action","e",["open","close","toggle"]]],30,"devtools");d("gem.screenshot",[["maxWidth","i",1,7680],["maxHeight","i",1,4320]],6,"screenshot");d("gem.screenshot.denied",[["reason","e",["not_wired","no_source","unsupported","unreadable","tainted","too_large","busy","declined","failed"]],["retryable","b"]],12,"screenshot");d("gem.requestContext",[],12,"feedbackContext");d("gem.gameContext",[["context","j"]],12,"feedbackContext");d("gem.signal",[["signal","e",["join","offer","answer","ice","migrationAck","hostUnreachable"]],D,["data","j"]],1200,"p2p");d("gem.dedicatedOffer",[D,["sdp","s",10240],["intent","e",["initial","ice_restart","full_reconnect"]]],60,"dedicated");d("gem.partyRequest",[m],12,"parties");d("gem.ready",[],5);d("gem.engaged",[],5,"engagement");d("gem.progress",[["loaded","i",0,1099511627776],["total","i",0,1099511627776]],600);d("gem.requestToken",[m,["reason","e",["initial","expiring","rejected"]]],12);d("gem.requestLocalServer",[m,["gameRoomId","s",64]],6,"localHost");d("gem.localServer",[m,["serverId","S",128]],30,"localHost");d("gem.localServer.denied",[m,["retryable","b"],["reason","e",["refused","unavailable"]]],30,"localHost");d("gem.exit",[["reason","S",64]],5);d("gem.openExternal",[["url","s",2048,"url"]],6);d("gem.requestFullscreen",[["enabled","b"]],30);d("gem.audioState",[["muted","b"]],120,"audioState");d("gem.rewardCue",[F,["cueId","S",64],["expected","I",1,1e9],["origin","O",[["x","i",0,16384],["y","i",0,16384]]]],60,"rewardCue");d("gem.rewardPresentation",[["mode","e",["arcade","game"]]],12,"rewardPresentation");d("gem.walletDisplay",[["visible","b"],["currencies","A",8,B],["score","B"]],60,"walletDisplay");d("gem.controlsDeclare",[["uses","o",[["lookSensitivity","S",16,"code"],["gamepadLookSensitivity","S",16,"code"],["invertLookY","S",16,"code"],["touchMovement","S",16,"code"]]]],60,"controls");d("gem.menu",[["settings","b"],["items","A",4,["","o",[["id","s",32],["label","s",40]]]]],60,"gameMenu");d("gem.menuSelect",[["entry","e",["settings","item"]],["id","S",32]],60,"gameMenu");d("gem.gemCorner",[["corner","e",["top-left","top-right","bottom-left","bottom-right"]]],12,"gemCorner");d("gem.menuStyle",[["ground","S",7],["accent","S",7]],12,"menuStyle");d("gem.settingsDeclare",[["settings","a",8,["","o",[["id","s",40],["label","s",40],["kind","e",["toggle","slider","choice"]],["value","u",40,-1e6,1e6],["quick","B"],["icon","S",16,"code"],["min","N",-1e6,1e6],["max","N",-1e6,1e6],["step","N",0,1e6],["options","A",4,["","o",[["id","s",40],["label","s",40]]]]]]]],120,"gameSettings");d("gem.settingChange",[["id","s",40],["value","u",40,-1e6,1e6]],120,"gameSettings");d("gem.requestShare",[["requestId","S",64],["params","a",16,["","o",[["key","s",64],["value","s",512]]]]],6,"share");d("gem.shareResult",[m,["outcome","e",["accepted","refused"]],G,["key","S",64]],30,"shareResult");d("gem.requestAvatarPicker",[["tab","E",["2d","3d"]]],6,"avatarPicker");d("gem.vibrate",[["pattern","a",99,["","i",0,1e4]]],600,"vibration");d("gem.frameStats",[["fps","i",0,1e3],["frameTimeP95Ms","i",0,1e5],["counts","E",["pageFrames","gameDraws"]]],120,"frameStats");d("gem.portraitBorders",[["name","S",40]],60,"portraitBorders");d("gem.error",[["code","e",["version_mismatch","handshake_timeout","handshake_duplicate","invalid_message","rate_limited","token_unavailable","unsupported","unsupported_capability","internal"]],["message","S",256]],60);d("gem.requestPurchase",[m,["purchaseKind","e",["item","recipe"]],["targetId","s",64],F,["quantity","I",1,10],["catalogId","S",64],["origin","E",["sheet","direct_refused"]]],12,"purchases");d("gem.requestAvatar3dPurchase",[m,["itemId","s",64],F],12,"avatar3dPurchases");d("gem.purchaseResult",[m,C,G,["purchaseId","S",64]],30,"purchases");d("gem.purchaseSettled",[["purchaseKind","e",["item","recipe"]],["targetId","s",64],["catalogId","S",64],["quantity","i",1,10],["purchaseId","S",64]],30,"purchaseSettled");d("gem.deviceSettings.put",[m,["settings","j"]],30,"deviceSettings");d("gem.deviceSettings.result",[m,["outcome","e",["stored","too_large","unavailable"]]],30,"deviceSettings");d("gem.requestAd",[m,["placement","s",32],["format","e",["interstitial","rewarded"]]],6,"ads");d("gem.adResult",[m,["outcome","e",["shown","no_ad","unavailable"]]],12,"ads");d("gem.signalMoment",[m,["kind","e",["level_end","run_end","match_end","menu_return","other_break"]],["placement","S",32],["wall","B"]],6,"moments");d("gem.momentResult",[m,["shown","b"]],12,"moments");d("gem.requestSignIn",[m],6,"signIn");d("gem.signInResult",[m,["outcome","e",["signed_in","declined","unavailable"]]],12,"signIn");d("gem.requestFriendChallenge",[m,["playerId","s",64],["template","s",64],["params","J"]],12,"friendChallenges");d("gem.friendChallengeResult",[m,["outcome","e",["accepted","cancelled","refused","unavailable","rate_limited","invalid"]],["code","S",64],["param","S",64],["channel","S",16],["configVersion","I",0,9007199254740991],["retryAfterMs","I",0,864e5],["detail","S",300]],30,"friendChallenges");d("gem.requestPlayInvite",[m,["params","A",16,["","o",[["key","s",64],["value","s",512]]]]],6,"playInvites");d("gem.playInviteResult",[m,["shown","b"]],12,"playInvites");d("gem.inviteParams",[["params","A",16,["","o",[["key","s",64],["value","s",512]]]]],30,"playInvites");d("gem.requestAppLinks",[m],12,"appLinks");d("gem.appLinksResult",[m,C,G,["arcade","O",[["store","e",["app_store","google_play"]]]],["game","O",[["store","e",["app_store","google_play"]]]]],30,"appLinks");d("gem.requestOpenApp",[m,["target","e",["arcade","game"]]],6,"appLinks");d("gem.openAppResult",[m,C,G],30,"appLinks");d("gem.requestOpenGame",[m,["ref","s",40,"gameRef"]],6,"openGame");d("gem.openGameResult",[m,C,G],30,"openGame");d("gem.requestSimilarGames",[m,["limit","I",1,24]],12,"openGame");d("gem.similarGamesResult",[m,C,G,["games","a",24,["","o",[["gameId","s",36,"gameRef"],["slug","S",40,"gameRef"],["iconUrl","s",1024,"url"],["capsuleLandscapeUrl","s",1024,"url"],["capsulePortraitUrl","s",1024,"url"],["previewVideoUrl","S",1024,"url"],["previewPosterUrl","S",1024,"url"],["untrusted","o",[["name","s",64],["tagline","s",64],["shortDescription","s",320],["tags","a",10,["","s",32]]]]]]]],30,"openGame",524288);d("gem.requestStoreOffers",[m],12,"store");d("gem.storeOffersResult",[m,C,G,["offers","a",32,["","o",[["skuId","s",64],["kind","e",["gem_pack","boost","pass","bundle"]],["name","s",80],["description","s",400],["imageUrl","S",1024,"url"],["priceDisplay","s",32],["grant","O",[["currency","s",32],["amount","i",1,1e9]]],["pass","S",64],["earnMultipliers","A",8,["","o",[F,["multiplierBp","i",1e4,1e6]]]]]]]],30,"store",262144);d("gem.requestStorePurchase",[m,["skuId","s",64]],12,"store");d("gem.storePurchaseResult",[m,C,G],30,"store");d("gem.storePurchaseSettled",[["skuId","s",64]],30,"store");d("gem.requestStoreOfferSheet",[m,["skuId","s",64]],12,"storeOfferSheet");d("gem.storeOfferSheetResult",[m,C,G],30,"storeOfferSheet");Object.freeze(be);K.__malformed=60;Object.freeze(K);Object.freeze(he);var q={now:()=>Date.now(),setTimeout:(n,e)=>setTimeout(n,e),clearTimeout:n=>clearTimeout(n)};function Re(n){let e=n.toLowerCase();return e==="localhost"||e.endsWith(".localhost")||e==="[::1]"||e==="::1"?true:/^127(\.\d{1,3}){3}$/.test(e)}var On=1e4;function ve(n,e){return Q(n,e)}function Q(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 V({clock:e.clock,...e.onStateChange===void 0?{}:{onStateChange:e.onStateChange},request:()=>new Promise((i,l)=>{let u=e.clock.setTimeout(()=>{r=null,l({reason:"unavailable",retryable:true});},e.timeoutMs??On);r={resolve:c=>{e.clock.clearTimeout(u),i(c);},reject:l,timer:u};})}),a=n.onServerToken(i=>{let l=t(i),u=r;if(u){r=null,u.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 ee={};ze(ee,{acceptTransfer:()=>Gn,addEntityProgression:()=>Tn,adminAction:()=>In,cancelInventoryTransfer:()=>Cn,claimEntityProgressionRewards:()=>En,closeGameRoom:()=>Mn,createEntityBatchOrder:()=>Ln,createEntityOrder:()=>qn,createSession:()=>jn,deleteEntityGameSetting:()=>$n,deleteEntitySave:()=>Bn,deleteSession:()=>Fn,deleteShowcaseValue:()=>Dn,executeEntityRecipe:()=>Un,finalizeSaveUpload:()=>Nn,getChannelAssignment:()=>Hn,getDropRates:()=>Vn,getEntityCurrency:()=>Wn,getEntityGameSetting:()=>zn,getEntityInventory:()=>Kn,getEntityInventoryItem:()=>Yn,getEntityLeaderboard:()=>Jn,getEntityOrder:()=>Xn,getEntityProgression:()=>Qn,getEntityRecipeAvailability:()=>Zn,getEntityRecipeUsage:()=>et,getEntitySave:()=>nt,getEvent:()=>tt,getGameRoomV2:()=>rt,getLeaderboard:()=>ot,getPlayerGameProfile:()=>at,getPurchaseCatalog:()=>st,getResolvedTemplate:()=>it,getRoomArgs:()=>lt,getShowcaseValue:()=>dt,getTransferDetails:()=>ut,ingestAnalyticsEvents:()=>Z,initiateInventoryTransfer:()=>ct,invokeFunction:()=>mt,kickPlayer:()=>pt,listChallenges:()=>gt,listEntityGameSettings:()=>yt,listEntityOrders:()=>ft,listEntityProgressions:()=>ht,listEntitySaves:()=>_t,listEvents:()=>bt,listGameRooms:()=>Rt,listResolvedTemplates:()=>vt,listTransfers:()=>St,maxEntityProgression:()=>xt,putEntityGameSetting:()=>wt,putRoomArgs:()=>kt,putShowcaseValue:()=>At,rejectTransfer:()=>Pt,reportMatchPlayers:()=>Ot,requestSaveUploadUrl:()=>Gt,resetEntityProgression:()=>Tt,setMatchBackfill:()=>It,simulateEntityOrder:()=>Ct,transferHostV2:()=>Et,updateGameRoomV2:()=>Mt});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 Gn(n,e,t){let r=`/v1/inventory/transfers/${s(e)}/accept`;return n.client.post(r,void 0,t?.signal)}async function Tn(n,e,t,r,o,a){let i=`/v1/inventory/${s(e)}/${s(t)}/progressions/${s(r)}/add`;return n.client.post(i,o,a?.signal)}async function In(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 En(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 Mn(n,e,t){let r=`/v1/games/${s(n.gameId())}/game-rooms/${s(e)}`;return n.client.delete(r,t?.signal)}async function Ln(n,e,t,r,o){let a=`/v1/inventory/${s(e)}/${s(t)}/orders/batch`;return n.client.post(a,r,o?.signal,{...o?.ifMatch===void 0?{}:{ifMatch:o.ifMatch}})}async function qn(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 jn(n,e,t){return n.client.post("/v1/voice/sessions",e,t?.signal)}async function $n(n,e,t,r,o){let a=`/v1/settings/${s(e)}/${s(t)}/${s(r)}`;return n.client.delete(a,o?.signal)}async function Bn(n,e,t,r,o){let a=`/v1/saves/${s(e)}/${s(t)}/${s(r)}`;return n.client.delete(a,o?.signal)}async function Fn(n,e,t){let r=`/v1/voice/sessions/${s(e)}`;return n.client.delete(r,t?.signal)}async function Dn(n,e,t,r){let o=`/v1/showcase/players/${s(e)}/${s(t)}`;return n.client.delete(o,r?.signal)}async function Un(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 Nn(n,e,t,r,o,a){let i=`/v1/saves/${s(e)}/${s(t)}/${s(r)}/finalize`;return n.client.post(i,o,a?.signal)}async function Hn(n,e,t){let r=`/v1/games/${s(n.gameId())}/config/channels/${s(e)}`;return n.client.getWithEtag(r,{...t?.signal===void 0?{}:{signal:t.signal},...t?.ifNoneMatch===void 0?{}:{ifNoneMatch:t.ifNoneMatch}})}async function Vn(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 zn(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 Kn(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 Yn(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 Jn(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 Xn(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 Qn(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 Zn(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 et(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 nt(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 tt(n,e,t){let r=`/v1/events/${s(e)}`;return n.client.get(r,t?.signal)}async function rt(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 ot(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 at(n,e,t){let r=`/v1/profiles/players/${s(e)}`;return n.client.get(r,t?.signal)}async function st(n,e){let t=new URLSearchParams;e?.config_version!==void 0&&t.set("config_version",String(e?.config_version));let r=t.toString(),o="/v1/inventory/platform-funded-game-inventory-purchase-catalog"+(r?`?${r}`:"");return n.client.get(o,e?.signal)}async function it(n,e,t){let r=`/v1/game-room-templates/${s(e)}`;return n.client.get(r,t?.signal)}async function lt(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 dt(n,e,t,r){let o=`/v1/showcase/players/${s(e)}/${s(t)}`;return n.client.get(o,r?.signal)}async function ut(n,e,t){let r=`/v1/inventory/transfers/${s(e)}`;return n.client.get(r,t?.signal)}async function Z(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 ct(n,e,t){return n.client.post("/v1/inventory/transfers",e,t?.signal)}async function mt(n,e,t){let r=new URLSearchParams;t?.cue_id!==void 0&&r.set("cue_id",String(t?.cue_id));let o=r.toString(),a="/v1/functions/invoke"+(o?`?${o}`:"");return n.client.postBytes(a,e,t?.signal)}async function pt(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 gt(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 yt(n,e,t,r){let o=`/v1/settings/${s(e)}/${s(t)}`;return n.client.get(o,r?.signal)}async function ft(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 ht(n,e,t,r){let o=`/v1/inventory/${s(e)}/${s(t)}/progressions`;return n.client.get(o,r?.signal)}async function _t(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 bt(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 Rt(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 vt(n,e){return n.client.get("/v1/game-room-templates",e?.signal)}async function St(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 xt(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 wt(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 kt(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 Pt(n,e,t){let r=`/v1/inventory/transfers/${s(e)}/reject`;return n.client.post(r,void 0,t?.signal)}async function Ot(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 Gt(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 Tt(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 It(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 Et(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 Mt(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 Se="gem_";function xe(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 jt=1e4,$t=50,Bt=1e3,Ft=65536-4*1024,we=n=>typeof n=="number"?n:0,Dt=n=>typeof n=="string"?n:"";function ke(){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 Ut(n){return n?.retryable===true}function Nt(n,e){let t=n??{},r=Array.isArray(t.rejected)?t.rejected.map(o=>{let a=o??{};return {index:we(a.index),code:Dt(a.code)}}):[];return {accepted:we(t.accepted),rejected:r,dropped:e,duplicate:t.duplicate===true}}function Ae(n,e){return {event_uid:n.uid,name:n.name,offset_ms:Math.round(n.atMs)-e,player_id:n.playerId,dimensions:n.dimensions,measures:n.measures}}function Pe(n){let e=Math.max(1,Math.floor(n.maxQueue??Bt)),t={client:n.client,gameId:()=>n.gameId},r=[],o=0,a=null,i=false,l=null,u=0,c=0,p=false,f=false,x=R=>{n.log?.(R);},_=()=>{a!==null&&(n.clock.clearTimeout(a),a=null);},E=()=>Math.max(0,c-n.clock.now()),h=()=>{a!==null||i||l!==null||(a=n.clock.setTimeout(()=>{a=null,w().catch(()=>{});},Math.max(jt,E())));},A=()=>{let R=Math.min(r.length,100),v=128;for(let O=0;O<R;O+=1){let T=r[O];if(T===void 0)break;if(v+=JSON.stringify(Ae(T,0)).length+1,v>Ft)return Math.max(1,O)}return R};async function w(R){for(;l!==null;)await l.catch(()=>{});if(r.length===0)return {accepted:0,rejected:[],dropped:0,duplicate:false};let v=M(R);l=v;try{return await v}finally{l===v&&(l=null),r.length>0&&h();}}async function M(R){_();let v=r.splice(0,A()),O=o;o=0;let T=Math.round(n.clock.now()),H={batch_id:ke(),sent_at_ms:T,events:v.map(k=>Ae(k,T))};try{let k=await Z(t,H,R===void 0?void 0:{signal:R}),I=Nt(k,O);u=0,c=0;for(let Ve of I.rejected)x(`[gem] analytics: an event was refused (${Ve.code}). See the analytics_events section of your game config.`);return I}catch(k){if(Ut(k)){for(r=[...v,...r],o+=O;r.length>e;)r.shift(),o+=1;u+=1,c=n.clock.now()+xe(u,k);}else x(`[gem] analytics: ${v.length} event(s) were discarded \u2014 the platform refused the batch and will refuse it again: ${String(k)}`);throw k}}return {track(R,v,O={}){if(i)return;if(typeof R!="string"||R===""){f||(f=true,x(`[gem] analytics: '${v}' 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(v.startsWith(Se)){p||(p=true,x(`[gem] analytics: '${v}' 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={},H={};for(let[k,I]of Object.entries(O))typeof I=="string"?T[k]=I:typeof I=="number"&&Number.isFinite(I)&&(H[k]=I);for(;r.length>=e;)r.shift(),o+=1;r.push({uid:ke(),playerId:R,name:v,atMs:n.clock.now(),dimensions:T,measures:H}),r.length>=$t&&l===null&&E()===0?w().catch(()=>{}):h();},flush:R=>w(R),get pending(){return r.length},dispose(){i=true,_(),r=[],o=0;}}}function Ht(n){return typeof n=="string"&&/^[\w-]{1,64}$/.test(n)}function Oe(n,e){if(n===void 0||Ht(n))return n;let t=typeof n=="string"?JSON.stringify(n.slice(0,72)):`a value of type ${typeof n}`;console.warn(`[gem] ${e}: cueId ${t} is not 1 to 64 letters, digits, _ or -, so it was left out. Use one crypto.randomUUID() per award.`);}var Vt=new Map([["function_error",false],["function_failed",false],["function_timeout",false],["function_not_published",false],["function_input_too_large",false],["invalid_cue_id",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]]),U=class extends g{constructor(e,t){super(e.reason,e.status,e.detail,e.retryAfterSeconds,e.code),this.name="GemFunctionError",Object.assign(this,t);}get retryable(){return (this.code===void 0?void 0:Vt.get(this.code))??super.retryable}},j=class{#e;constructor(e){this.#e=e;}async invoke(e,t={}){let r=Wt(e),o=Oe(t.cueId,"functions.invoke"),a;try{a=await this.#e(r,{...t.signal===void 0?{}:{signal:t.signal},...o===void 0?{}:{cue_id:o}});}catch(i){throw i instanceof g?Kt(i):i}return zt(a)}};function Wt(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 zt(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 Kt(n){let{details:e,invocationId:t}=ce(n),o=e?.untrusted?.message,a=e?.reason;return new U(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 P=n=>typeof n=="string"?n:"",Yt=/(?:Z|[+-]\d{2}:?\d{2})$/i;function Ge(n){let e=P(n);if(!Yt.test(e))return 0;let t=Date.parse(e);return Number.isFinite(t)?Math.floor(t/1e3):0}var Jt=/^[0-9a-f]{1,64}$/,Xt=/^[0-9a-f]{16}$/,Qt=/^[A-Za-z][A-Za-z0-9_+\-/]{0,63}$/,Zt=/^(?:[01]\d|2[0-3]):[0-5]\d$/;function er(n){let e=P(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 nr=4096,tr=new TextEncoder;function rr(n){let e=P(n.challenge_data),t=P(n.challenge_data_hash);return e===""||!Xt.test(t)?{}:tr.encode(e).length>nr?{}:{data:e,dataHash:t}}function or(n){let e=n??{},t=Ge(e.period_start_at),r=Ge(e.period_ends_at);if(t===0||r===0)return;let o=P(e.slug),a=P(e.seed),i=er(e.period_local_date),l=P(e.boundary),u=P(e.reset_time);return {id:P(e.progression_definition_id),...o===""?{}:{slug:o},window:P(e.window),periodStartAt:t,periodEndsAt:r,...i===void 0?{}:{periodLocalDate:i},boundary:Qt.test(l)?l:"",resetTime:Zt.test(u)?u:"",seed:Jt.test(a)?a:"",...rr(e)}}function Te(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 Ie(n){let e=n??{};return Array.isArray(e.challenges)?e.challenges.map(or).filter(t=>t!==void 0):[]}function Ce(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().");Te(r);let a=await n({player_id:t,...r===void 0?{}:{periods_back:r},...o===void 0?{}:{signal:o}});return Ie(a)}}}function ar(n,e){return Math.min(7,Math.max(1,Math.ceil((n-e)/864e5)))}function sr(n,e,t,r){if(!n)return 0;if(typeof e=="number"&&Number.isInteger(e))return Math.min(7,Math.max(1,e));if(t===null)return 7;let o=Date.parse(t);return Number.isFinite(o)?ar(o,r):7}function Ee(n,e){let t=n?.passes;if(!Array.isArray(t))return Object.freeze([]);let r=t.flatMap(o=>{let a=o??{};if(typeof a.pass!="string"||a.pass==="")return [];let i=a.held===true,l=i&&typeof a.ends_at=="string"?a.ends_at:null,u=sr(i,a.days_left,l,e);return [Object.freeze({pass:a.pass,held:i,daysLeft:u,endsAt:l})]});return Object.freeze(r)}var ir=7;function lr(n){let e=n??{},r=(Array.isArray(e.boosts)?e.boosts:[]).flatMap(i=>{let l=i??{};return typeof l.currency_slug!="string"||l.currency_slug===""?[]:typeof l.multiplier_bp!="number"||!Number.isInteger(l.multiplier_bp)?[]:l.multiplier_bp<=0?[]:[Object.freeze({currencySlug:l.currency_slug,multiplier:l.multiplier_bp/1e4})]}),o=e.boosted===true,a=e.expires_in_days;return Object.freeze({active:o,multipliers:Object.freeze(r),...o&&typeof a=="number"&&Number.isInteger(a)?{expiresInDays:Math.min(ir,Math.max(1,a))}:{}})}function Me(n,e=()=>Date.now()){let t=n,r=t.passes,o=t.boost,a=typeof r=="function"?r:void 0,i=typeof o=="function"?o:void 0,l=async(u,c,p)=>{if(u===void 0)throw new Error(`this runtime cannot read a player's ${c}: the server image running this bundle predates host.${c}, or this is a listen host, and only the platform half of a dedicated server holds the allocation proof the read needs.`);if(typeof p!="string"||p==="")throw new TypeError(`gem.match.player${c==="passes"?"Passes":"Boost"}: playerId must be a non-empty string`);let f;try{f=await u.call(n,p);}catch(x){throw new g("unavailable",0,`the platform half could not be asked: ${String(x)}`)}if(f.status!==200)throw me(f.status,f.body);return f.body};return {playerPasses:async u=>Ee(await l(a,"passes",u),e()),playerBoost:async u=>lr(await l(i,"boost",u))}}var te=n=>n!==null&&typeof n=="object"?n:{},re=n=>typeof n=="string"&&n!==""?n:void 0,ne=n=>typeof n=="number"&&Number.isSafeInteger(n)?n:void 0;function dr(n,e){let t=te(n);if(t.type!=="platform_grant")return null;let r=re(t.target_currency_id),o=ne(t.granted);if(r===void 0||o===void 0)return null;let a=ne(t.requested)??o,i=Math.max(0,Math.min(ne(t.base_granted)??Math.min(a,o),o)),l=o-i,u=te(t.boost_source),c=re(u.pass),p=e(r);return {...p===void 0?{}:{currencySlug:p},currencyId:r,base:i,total:o,breakdown:l<=0?[]:[c===void 0?{source:"boost",amount:l}:{source:"pass",pass:c,amount:l}]}}function Le(n){return {async fromReceipt(e){let t=re(te(e).target_currency_id),r=t===void 0?void 0:n.knownSlug(t);return t!==void 0&&r===void 0&&(r=await n.readSlugs().then(o=>o.get(t)||void 0,()=>{})),dr(e,()=>r)}}}function ur(n){let e={};for(let[t,r]of Object.entries(ee))if(typeof r=="function"){let o=r;e[t]=(...a)=>o(n,...a);}return e}function Y(n,e={}){let t=e.clock??q,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=Q(n,{clock:t,...e.onAuthStateChange===void 0?{}:{onStateChange:e.onAuthStateChange}}),a=ge({baseUrl:r,tokenSource:o.source,defaultQuery:{game_id:n.gameId,channel:n.channel},...e.fetch===void 0?{}:{fetch:e.fetch}}),i=new L({transport:a,clock:t}),l={gameId:n.gameId,channel:n.channel,matchId:n.matchId,...n.gameRoomId===void 0?{}:{gameRoomId:n.gameRoomId}},u=ur({client:i,gameId:()=>l.gameId}),c=l.gameRoomId,p=n.endMatch,f=Me(n,()=>t.now()),x=n.log,_=Pe({client:i,clock:t,gameId:l.gameId,...typeof x=="function"?{log:h=>x.call(n,h)}:{}});return {identity:l,client:i,api:u,match:{end:async()=>{if(p===void 0)throw new Error("this runtime cannot end the match: the server image running this bundle predates host.endMatch, and only the platform half holds the allocation proof an end needs.");await p.call(n);},setBackfill:async(h,A)=>{let w=await u.setMatchBackfill(l.matchId,{open:h.open,...h.seats===void 0?{}:{seats:h.seats}},A===void 0?{}:{signal:A});return {open:w.open,seats:w.seats??null}},reportPlayers:async(h,A)=>(await u.reportMatchPlayers(l.matchId,{players:h.map(M=>({player_id:M.playerId,state:M.state}))},A===void 0?{}:{signal:A})).players.map(M=>({playerId:M.player_id,outcome:M.outcome})),...f},analytics:_,earnings:Le({knownSlug:()=>{},readSlugs:async()=>new Map}),functions:new j(u.invokeFunction),challenges:Ce(u.listChallenges),...c===void 0?{}:{room:{get:h=>u.getGameRoomV2(c,h),args:async h=>{let A=await u.getGameRoomV2(c,h?.signal===void 0?{}:{signal:h.signal}),w=A.modified?A.body:void 0;if(w?.room_args==null||w.room_args_template==null)throw new g("not_found",404,"this room's template declares no room args",void 0,"room_args_not_defined");return {room_args:w.room_args,room_args_template:w.room_args_template}}}},dispose:()=>{_.dispose(),o.dispose();}}}var cr=["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"],mr=new Set(cr);function qe(n){return typeof n=="string"&&mr.has(n)?n:"unknown"}var Be="[gem: use gem.text.toPlain()]",je=new Set,$e;function pr(n){try{if(je.has(n))return;let e=globalThis.location;if($e??=!!e?.port&&Re(e.hostname??""),!$e)return;je.add(n),console.warn(`[gem] ${n} is PlayerText, turned into a string: players see ${Be}. Render text.toPlain(value) (text is in @indiegems/gem-web-sdk/sdk).
1
+ var We=Object.defineProperty;var ze=(n,e)=>{for(var t in e)We(n,t,{get:e[t],enumerable:true});};globalThis.__gemWebSdkVersion="[gem-web-sdk:sdkVersion:24.1.0]";var Ke={initialDelayMs:2e3,maxDelayMs:6e4};function Ye(n,e){return e!==void 0?!e:n==="chain_exhausted"}var V=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 b(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 b("chain_exhausted","the token chain reached its ceiling");if(this.inFlight===null&&this.options.clock.now()<this.notBefore)throw new b(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}=Ke,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 b("internal","token arrived for a superseded generation");return this.grant=o,this.rejected=false,this.enter("ready"),o.token}).catch(o=>{let a=Je(o),{retryable:i,retryAfterMs:l}=o??{};throw t===this.generation&&(Ye(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 b?o:new b(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)}},b=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 Je(n){if(n instanceof b)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}},W=["if-match","if-none-match"],ae=4096;function Xe(n){if(!n)return;let e={};for(let[t,r]of Object.entries(n)){let o=t.toLowerCase();if(!W.includes(o)||r===void 0)continue;let a=typeof r=="string"?Qe(r):r;if(typeof a!="string"||a.length>ae||!Ze(a))throw new y(`the ${o} header value cannot be sent \u2014 it is not a string, is longer than ${ae} 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 Qe(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 Ze(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 en(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 se(n,e){let t=e.replayUnauthorizedOnce??true;return {async request(r){let o={...r},a=Xe(o.headers),i=en(o),l=Object.freeze({...o,headers:a,...i===void 0?{}:{bytes:i}}),u=await e.tokenSource.get(),c=await n(l,u);if(c.status!==401||!t)return c;e.tokenSource.invalidate(u);let p=await e.tokenSource.get(),f=await n(l,p);if(f.status===401)throw e.tokenSource.close("unavailable"),new b("unavailable","the server refused a freshly minted token");return f}}}function ie(n){let e=typeof n=="string"?new TextEncoder().encode(n):n;return btoa(nn(e))}function nn(n){let t="";for(let r=0;r<n.length;r+=32768)t+=String.fromCharCode(...n.subarray(r,r+32768));return t}var g=class extends Error{constructor(t,r,o,a,i){super(`${t} (${r}): ${o}`);this.reason=t;this.status=r;this.detail=o;this.retryAfterSeconds=a;this.code=i;this.name="GemApiError";}reason;status;detail;retryAfterSeconds;code;get retryable(){return this.reason==="unavailable"||this.reason==="rate_limited"}},ue=new WeakMap;function ce(n){return ue.get(n)??{}}var tn=new Set([408,429,500,502,503,504]),rn=6e4,on=new WeakMap;function le(n){return n!==null&&(n.reason==="rate_limited"||n.retryAfterSeconds!==void 0)}function an(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 L=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,...$(o)},o.replaySafe===true,o.retryRateLimited!==false)}async post(e,t,r,o={}){return this.send({method:"POST",path:e,body:t,signal:r,...$(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,...$(o)},o.replaySafe===true,o.retryRateLimited!==false);return {bytes:sn(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,...$(o)},o.replaySafe===true,o.retryRateLimited!==false)}async delete(e,t,r={}){return this.send({method:"DELETE",path:e,signal:t,...$(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?an(this.options.maxRetries)+1:1,a=null;if(e.signal?.aborted)throw de(e.signal);let i=e.signal===void 0?void 0:on.get(e.signal);for(let l=0;l<o;l++){if(l>0){let p=this.backoffMs(l,a);if(le(a)&&i!==void 0&&p>=i())throw a;await this.backoff(p,e.signal);}if(e.signal?.aborted)throw le(a)&&i!==void 0&&i()<=0?a:de(e.signal);let u;try{u=await this.options.transport.request(e);}catch(p){if(b.isAuthError(p)||y.isRefusal(p)||e.signal?.aborted||ln(p))throw p;a=new g("unavailable",0,String(p));continue}if(u.status>=200&&u.status<300||u.status===304)return u;let c=pe(u);if(!tn.has(u.status)||u.status===429&&!r)throw c;a=c;}throw a??new g("unavailable",0,"no attempt was made")}backoffMs(e,t){let r=t?.retryAfterSeconds,o=r!==void 0?r*1e3:2**(e-1)*250,a=2**(e-1)*250;return Math.min(Math.max(o,a),rn)}backoff(e,t){return t?.aborted?Promise.resolve():new Promise(r=>{let o=this.options.clock,a=false,i=false,l,u=()=>{a||(a=true,i&&o.clearTimeout(l),t?.removeEventListener("abort",u),r());};t?.addEventListener("abort",u,{once:true}),l=o.setTimeout(u,e),i=true,a&&o.clearTimeout(l);})}};function sn(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 $(n){return {...n.keepalive===void 0?{}:{keepalive:n.keepalive},...n.ifMatch===void 0?{}:{headers:{"if-match":n.ifMatch}}}}function de(n){return n.reason!==void 0?n.reason:new DOMException("The operation was aborted.","AbortError")}function ln(n){let e=n?.name;return e==="AbortError"||e==="TimeoutError"}function me(n,e){return pe({status:n,body:e})}function pe(n){let e=un(n),t=mn(n.body),r={...t===void 0?{}:{details:t},...n.invocationId===void 0?{}:{invocationId:n.invocationId}};return Object.keys(r).length>0&&ue.set(e,r),e}var dn=new Map([["insufficient_funds","insufficient_funds"]]);function un(n){let{status:e,body:t}=n,r=cn(t),o=n.retryAfterSeconds??gn(t),a=pn(t),i=a===void 0?void 0:dn.get(a);if(i!==void 0)return new g(i,e,r,void 0,a);switch(e){case 304:return new g("not_modified",e,r);case 400:case 422:return new g("invalid",e,r,void 0,a);case 403:return new g("forbidden",e,r,void 0,a);case 404:return new g("not_found",e,r,void 0,a);case 402:return new g("insufficient_funds",e,r,void 0,a);case 409:return new g("conflict",e,r,void 0,a);case 412:return new g("precondition_failed",e,r,void 0,a);case 413:return new g("too_large",e,r,void 0,a);case 429:return new g("rate_limited",e,r,o,a);default:return new g("unavailable",e,r,o,a)}}function cn(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 mn(n){let t=n?.error?.details;return t===null?void 0:t}function pn(n){let t=n?.error?.code;return typeof t=="string"&&t.length>0?t:void 0}function gn(n){let e=n?.retryAfterSeconds;return typeof e=="number"&&Number.isFinite(e)&&e>=0?e:void 0}function yn(n){let e=n.lastIndexOf("@");return (e===-1?n:`***@${n.slice(e+1)}`).slice(0,200)}var fn=new Set(W);function hn(n){if(!n)return {};let e={};for(let[t,r]of Object.entries(n))fn.has(t.toLowerCase())&&(e[t.toLowerCase()]=r);return e}function ge(n){let e=n.fetch??globalThis.fetch.bind(globalThis);return se(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"?yn(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 _=o.username!==""||o.password!=="",E=a.username!==o.username||a.password!==o.password,h=_?E?"baseUrl (and possibly the request path)":"baseUrl":"request path";throw new y(`the ${h} 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[_,E]of Object.entries(n.defaultQuery??{}))a.searchParams.has(_)||a.searchParams.set(_,E);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(_){throw new y(`the body of ${t.method} ${JSON.stringify(a.pathname)} could not be serialised to JSON: ${String(_)}. This is a bug in the request, not a server failure \u2014 retrying sends the same unserialisable value.`)}let u=await e(a.toString(),{method:t.method,headers:{authorization:`Bearer ${r}`,...l===void 0?{}:{"content-type":l},...hn(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"&&u.status>=200&&u.status<300)c=new Uint8Array(await u.arrayBuffer());else {let _=await u.text();if(_.length>0)try{c=JSON.parse(_);}catch{c=_;}}let p=u.headers.get("etag"),f=_n(u.headers.get("retry-after")),x=u.headers.get("x-gem-invocation-id");return {status:u.status,body:c,...p===null?{}:{etag:p},...f===void 0?{}:{retryAfterSeconds:f},...x===null||x===""?{}:{invocationId:x}}},n)}function _n(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 bn="gem-web-bridge";var Rn=65536,ye=8,z=5e3,fe=1024;var K=Object.create(null);var he=Object.create(null);function vn(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 Sn(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 xn(n){return /^[a-z]{2,8}(-[a-z0-9]{1,8})*$/i.test(n)}function wn(n){return /^[a-z_]+$/.test(n)}function kn(n){return /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(n)||/^[a-z0-9][a-z0-9-]{1,38}[a-z0-9]$/.test(n)&&!n.includes("--")}function J(n,e,t){if(e>ye)return `nesting deeper than ${ye}`;if(++t.nodes>z)return `more than ${z} values`;if(t.bytes>t.cap)return `over the ${t.cap} byte limit`;if(n==null)return t.bytes+=4,null;let r=typeof n;if(r==="boolean")return t.bytes+=5,null;if(r==="number")return t.bytes+=8,null;if(r==="string")return t.bytes+=n.length*3+2,null;if(r!=="object")return `${r} is not plain data`;let 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>fe)return `an array of ${n.length} entries, over the ${fe} limit`;t.bytes+=2;for(let l of n){let u=J(l,e+1,t);if(u)return u}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>z)return `more than ${z} values`;if(t.bytes+=l.length*3+4,t.bytes>t.cap)return `over the ${t.cap} byte limit`;let u=J(i[l],e+1,t);if(u)return u}return null}function An(n,e=Rn){let t={nodes:0,bytes:0,seen:new Set,cap:e},r=J(n,0,t);return r?`message contains ${r}`:t.bytes>e?`message is over the ${e} byte limit`:null}var Pn={origin:[vn,"not a well-formed origin"],url:[Sn,"not a safe absolute http(s) URL"],bcp47:[xn,"not a well-formed BCP 47 tag"],code:[wn,"not a code of lower-case letters and underscores"],gameRef:[kn,"not a game id or web address"]};function _e(n,e,t){for(let r of e){let o=t===""?r[0]:`${t}.${r[0]}`,a=n[r[0]];if(a==null){if(r[1]<"a")continue;return `${o}: required`}let i=X(a,r,o);if(i)return i}return null}function X(n,e,t){let r=e[1].toLowerCase();switch(r){case "u":return typeof n=="boolean"?null:X(n,typeof n=="string"?[e[0],"s",e[2]]:[e[0],"n",e[3],e[4]],t);case "s":{if(typeof n!="string")return `${t}: expected string`;if(n.length>e[2])return `${t}: exceeds ${e[2]} characters`;if(e[3]){let[o,a]=Pn[e[3]];if(!o(n))return `${t}: ${a}`}return null}case "n":case "i":return typeof n!="number"||!(r=="i"?Number.isInteger:Number.isFinite)(n)?`${t}: expected ${r=="i"?"integer":"number"}`:n<e[2]||n>e[3]?`${t}: out of range ${e[2]}..${e[3]}`:null;case "b":return typeof n=="boolean"?null:`${t}: expected boolean`;case "e":{let o=e[2];return o.includes(n)?null:`${t}: not one of ${o.join("|")}`}case "o":return typeof n!="object"||n===null||Array.isArray(n)?`${t}: expected object`:_e(n,e[2],t);case "j":return typeof n!="object"||n===null||Array.isArray(n)?`${t}: expected a plain object`:null;case "a":{if(!Array.isArray(n))return `${t}: expected array`;if(n.length>e[2])return `${t}: exceeds ${e[2]} items`;let o=e[3],a=`${t}[]`;for(let i of n){if(i==null){if(o[1]<"a")continue;return `${a}: required`}let l=X(i,o,a);if(l)return l}return null}default:return `${t}: unknown kind ${String(r)}`}}var be=Object.create(null);function d(n,e,t,r,o){return K[n]=t,r&&(he[n]=r),be[n]=a=>{let i=An(a,o);if(i)return i;if(typeof a!="object"||a===null||Array.isArray(a))return "message: expected object";let l=a;return l.gem!==bn?"gem: wrong protocol marker":l.type!==n?`type: expected ${n}`:_e(l,e,"")}}var B=["","s",64],m=["requestId","s",64],F=["currencySlug","s",32],D=["matchId","s",64],G=["reason","S",64,"code"],C=["outcome","e",["ok","declined","unavailable"]];d("gem.handshake",[["versions","o",[["min","i",1,1e3],["max","i",1,1e3]]],["capabilities","A",64,B],["embedder","s",2048,"origin"],["unbidden","B"]],30);d("gem.handshake.accept",[["v","i",1,1e3],["capabilities","A",64,B]],5);d("gem.token",[["token","s",4096],["requestId","S",64],["generation","i",0,2147483647],["apiBaseUrl","S",512,"url"],["playerId","s",64],["gameId","s",64],["channel","e",["dev","test","release"]],["gameVersion","S",64],["expiresAt","i",0,4102444800],["chainEndsAt","i",0,4102444800],["allowDevTools","B"]],30);d("gem.token.denied",[m,["retryable","b"],["retryAfterMs","I",0,36e5],["reason","e",["chain_exhausted","unavailable"]],["correlationId","s",64]],30);d("gem.player",[["untrusted","o",[["displayName","s",64],["displayTag","S",80],["displayHandle","s",80]]],["playerId","S",64],["discriminator","S",8],["avatarIconUrl","S",2048,"url"],["avatarIconId","S",64],["avatar3dId","S",64],["avatar3dModelUrl","S",2048,"url"],["avatar3dIconUrl","S",2048,"url"],["avatars3d","A",8,["","o",[["family","s",32],["id","s",64],["modelUrl","s",256,"url"],["iconUrl","s",256,"url"]]]],["badges","A",2,["","o",[["itemId","s",64],["iconUrl","s",2048,"url"]]]],["displayTag","s",8],["avatarUrl","S",2048,"url"],["boost","O",[["multipliers","a",8,["","o",[["currencyId","s",64],F,["multiplierBp","i",1e4,1e6]]]],["expiresInDays","I",1,7]]],["signInAvailable","B"]],12);d("gem.pause",[["paused","b"]],120);d("gem.prefs",[["reducedMotion","b"],["muted","b"],["showFrameStats","B"],["music","B"],["sounds","B"],["locale","s",35,"bcp47"],["recommended","O",[["volume","i",0,100],["batterySaver","b"],["keyboardLayout","e",["wasd","arrows"]],["gamepadConfirm","e",["south","east"]],["vibration","b"],["lookSensitivity","I",20,400],["gamepadLookSensitivity","I",20,400],["invertLookY","B"],["touchMovement","S",16,"code"],["graphicsQuality","S",16,"code"],["graphicsQualityAuto","B"],["colorHelp","B"],["textScale","I",100,200]]]],60);d("gem.cohorts",[["cohorts","a",8,["","o",[["experimentId","s",36],["variantKey","s",32]]]]],12,"cohorts");d("gem.earnAllowanceChanged",[],30,"earnAllowance");d("gem.inventoryChanged",[],30,"inventoryChanged");d("gem.viewport",[["insets","o",[["top","i",0,4096],["right","i",0,4096],["bottom","i",0,4096],["left","i",0,4096]]],["reserved","A",4,["","o",[["x","i",0,16384],["y","i",0,16384],["width","i",0,16384],["height","i",0,16384],["control","O",[["x","i",0,16384],["y","i",0,16384],["width","i",0,16384],["height","i",0,16384]]]]]]],60,"viewport");d("gem.deviceSettings",[["settings","J"]],12,"deviceSettings");d("gem.willTerminate",[["reason","e",["grant_expiring","session_ended","navigating","kill_switch"]],["graceMs","i",0,6e4]],10);d("gem.roomEvent",[["event","e",["updated","match_started","match_ready","match_failed","version_stale"]],["roomId","s",64],["matchId","S",64],["version","I",0,2147483647],["reason","S",64],["platform","E",["universal","mobile"]]],120,"rooms");d("gem.socketState",[["connected","b"],["reason","E",["connecting","dropped","watchdog","terminal"]]],12,"socketState");d("gem.seatedEvent",[["roomId","s",64]],60,"partySeating");d("gem.autoStartFailedEvent",[["roomId","s",64],["code","s",64]],30,"autoStartFailure");d("gem.ticketEvent",[["event","e",["queued","matched","expired","cancelled","failed"]],["ticketId","s",64],["partySize","I",1,64],["queuedAt","I",0,4102444800],["expiresAt","I",0,4102444800],["reason","S",64],["roomId","S",64]],60,"ticketEvents");d("gem.signalEvent",[["event","e",["hello","offer","answer","ice","peerJoined","peerLeft","migration","matchEnded","error"]],D,["data","j"]],1800,"p2p");d("gem.relayDraining",[D,["clusterTargetId","s",64],["relayIps","a",16,B],["drainingSince","s",40],["deadline","s",40]],60,"p2pRelayDrain");d("gem.dedicatedEvent",[["event","e",["answer","error","matchEnded"]],D,["sdp","S",10240],["sessionId","S",64],["code","S",64],["message","S",256],["reason","S",64]],120,"dedicated");d("gem.partyResult",[m,["partyId","S",64]],30,"parties");d("gem.clusterTarget",[["clusterTargetId","s",64],["clusterTargetIds","A",3,B]],12,"clusterTarget");d("gem.graphicsRoutes",[["entries","a",32,["","o",[["gpu","s",32],["route","S",32],["host","S",32]]]]],12,"graphicsRoutes");d("gem.devtools",[["action","e",["open","close","toggle"]]],30,"devtools");d("gem.screenshot",[["maxWidth","i",1,7680],["maxHeight","i",1,4320]],6,"screenshot");d("gem.screenshot.denied",[["reason","e",["not_wired","no_source","unsupported","unreadable","tainted","too_large","busy","declined","failed"]],["retryable","b"]],12,"screenshot");d("gem.requestContext",[],12,"feedbackContext");d("gem.gameContext",[["context","j"]],12,"feedbackContext");d("gem.signal",[["signal","e",["join","offer","answer","ice","migrationAck","hostUnreachable"]],D,["data","j"]],1200,"p2p");d("gem.dedicatedOffer",[D,["sdp","s",10240],["intent","e",["initial","ice_restart","full_reconnect"]]],60,"dedicated");d("gem.partyRequest",[m],12,"parties");d("gem.ready",[],5);d("gem.engaged",[],5,"engagement");d("gem.progress",[["loaded","i",0,1099511627776],["total","i",0,1099511627776]],600);d("gem.requestToken",[m,["reason","e",["initial","expiring","rejected"]]],12);d("gem.requestLocalServer",[m,["gameRoomId","s",64]],6,"localHost");d("gem.localServer",[m,["serverId","S",128]],30,"localHost");d("gem.localServer.denied",[m,["retryable","b"],["reason","e",["refused","unavailable"]]],30,"localHost");d("gem.exit",[["reason","S",64]],5);d("gem.openExternal",[["url","s",2048,"url"]],6);d("gem.requestFullscreen",[["enabled","b"]],30);d("gem.audioState",[["muted","b"]],120,"audioState");d("gem.rewardCue",[F,["cueId","S",64],["expected","I",1,1e9],["origin","O",[["x","i",0,16384],["y","i",0,16384]]]],60,"rewardCue");d("gem.rewardPresentation",[["mode","e",["arcade","game"]]],12,"rewardPresentation");d("gem.walletDisplay",[["visible","b"],["currencies","A",8,B],["score","B"]],60,"walletDisplay");d("gem.controlsDeclare",[["uses","o",[["lookSensitivity","S",16,"code"],["gamepadLookSensitivity","S",16,"code"],["invertLookY","S",16,"code"],["touchMovement","S",16,"code"]]]],60,"controls");d("gem.menu",[["settings","b"],["items","A",4,["","o",[["id","s",32],["label","s",40]]]]],60,"gameMenu");d("gem.menuSelect",[["entry","e",["settings","item"]],["id","S",32]],60,"gameMenu");d("gem.gemCorner",[["corner","e",["top-left","top-right","bottom-left","bottom-right"]]],12,"gemCorner");d("gem.menuStyle",[["ground","S",7],["accent","S",7]],12,"menuStyle");d("gem.settingsDeclare",[["settings","a",8,["","o",[["id","s",40],["label","s",40],["kind","e",["toggle","slider","choice"]],["value","u",40,-1e6,1e6],["quick","B"],["icon","S",16,"code"],["min","N",-1e6,1e6],["max","N",-1e6,1e6],["step","N",0,1e6],["options","A",4,["","o",[["id","s",40],["label","s",40]]]]]]]],120,"gameSettings");d("gem.settingChange",[["id","s",40],["value","u",40,-1e6,1e6]],120,"gameSettings");d("gem.requestShare",[["requestId","S",64],["params","a",16,["","o",[["key","s",64],["value","s",512]]]]],6,"share");d("gem.shareResult",[m,["outcome","e",["accepted","refused"]],G,["key","S",64]],30,"shareResult");d("gem.requestAvatarPicker",[["tab","E",["2d","3d"]]],6,"avatarPicker");d("gem.vibrate",[["pattern","a",99,["","i",0,1e4]]],600,"vibration");d("gem.frameStats",[["fps","i",0,1e3],["frameTimeP95Ms","i",0,1e5],["counts","E",["pageFrames","gameDraws"]]],120,"frameStats");d("gem.portraitBorders",[["name","S",40]],60,"portraitBorders");d("gem.error",[["code","e",["version_mismatch","handshake_timeout","handshake_duplicate","invalid_message","rate_limited","token_unavailable","unsupported","unsupported_capability","internal"]],["message","S",256]],60);d("gem.requestPurchase",[m,["purchaseKind","e",["item","recipe"]],["targetId","s",64],F,["quantity","I",1,10],["catalogId","S",64],["origin","E",["sheet","direct_refused"]]],12,"purchases");d("gem.requestAvatar3dPurchase",[m,["itemId","s",64],F],12,"avatar3dPurchases");d("gem.purchaseResult",[m,C,G,["purchaseId","S",64]],30,"purchases");d("gem.purchaseSettled",[["purchaseKind","e",["item","recipe"]],["targetId","s",64],["catalogId","S",64],["quantity","i",1,10],["purchaseId","S",64]],30,"purchaseSettled");d("gem.deviceSettings.put",[m,["settings","j"]],30,"deviceSettings");d("gem.deviceSettings.result",[m,["outcome","e",["stored","too_large","unavailable"]]],30,"deviceSettings");d("gem.requestAd",[m,["placement","s",32],["format","e",["interstitial","rewarded"]]],6,"ads");d("gem.adResult",[m,["outcome","e",["shown","no_ad","unavailable"]]],12,"ads");d("gem.signalMoment",[m,["kind","e",["level_end","run_end","match_end","menu_return","other_break"]],["placement","S",32],["wall","B"]],6,"moments");d("gem.momentResult",[m,["shown","b"]],12,"moments");d("gem.requestSignIn",[m],6,"signIn");d("gem.signInResult",[m,["outcome","e",["signed_in","declined","unavailable"]]],12,"signIn");d("gem.requestFriendChallenge",[m,["playerId","s",64],["template","s",64],["params","J"]],12,"friendChallenges");d("gem.friendChallengeResult",[m,["outcome","e",["accepted","cancelled","refused","unavailable","rate_limited","invalid"]],["code","S",64],["param","S",64],["channel","S",16],["configVersion","I",0,9007199254740991],["retryAfterMs","I",0,864e5],["detail","S",300]],30,"friendChallenges");d("gem.requestPlayInvite",[m,["params","A",16,["","o",[["key","s",64],["value","s",512]]]]],6,"playInvites");d("gem.playInviteResult",[m,["shown","b"]],12,"playInvites");d("gem.inviteParams",[["params","A",16,["","o",[["key","s",64],["value","s",512]]]]],30,"playInvites");d("gem.requestAppLinks",[m],12,"appLinks");d("gem.appLinksResult",[m,C,G,["arcade","O",[["store","e",["app_store","google_play"]]]],["game","O",[["store","e",["app_store","google_play"]]]]],30,"appLinks");d("gem.requestOpenApp",[m,["target","e",["arcade","game"]]],6,"appLinks");d("gem.openAppResult",[m,C,G],30,"appLinks");d("gem.requestOpenGame",[m,["ref","s",40,"gameRef"]],6,"openGame");d("gem.openGameResult",[m,C,G],30,"openGame");d("gem.requestSimilarGames",[m,["limit","I",1,24]],12,"openGame");d("gem.similarGamesResult",[m,C,G,["games","a",24,["","o",[["gameId","s",36,"gameRef"],["slug","S",40,"gameRef"],["iconUrl","s",1024,"url"],["capsuleLandscapeUrl","s",1024,"url"],["capsulePortraitUrl","s",1024,"url"],["previewVideoUrl","S",1024,"url"],["previewPosterUrl","S",1024,"url"],["untrusted","o",[["name","s",64],["tagline","s",64],["shortDescription","s",320],["tags","a",10,["","s",32]]]]]]]],30,"openGame",524288);d("gem.requestStoreOffers",[m],12,"store");d("gem.storeOffersResult",[m,C,G,["offers","a",32,["","o",[["skuId","s",64],["kind","e",["gem_pack","boost","pass","bundle"]],["name","s",80],["description","s",400],["imageUrl","S",1024,"url"],["priceDisplay","s",32],["grant","O",[["currency","s",32],["amount","i",1,1e9]]],["pass","S",64],["earnMultipliers","A",8,["","o",[F,["multiplierBp","i",1e4,1e6]]]]]]]],30,"store",262144);d("gem.requestStorePurchase",[m,["skuId","s",64]],12,"store");d("gem.storePurchaseResult",[m,C,G],30,"store");d("gem.storePurchaseSettled",[["skuId","s",64]],30,"store");d("gem.requestStoreOfferSheet",[m,["skuId","s",64]],12,"storeOfferSheet");d("gem.storeOfferSheetResult",[m,C,G],30,"storeOfferSheet");Object.freeze(be);K.__malformed=60;Object.freeze(K);Object.freeze(he);var q={now:()=>Date.now(),setTimeout:(n,e)=>setTimeout(n,e),clearTimeout:n=>clearTimeout(n)};function Re(n){let e=n.toLowerCase();return e==="localhost"||e.endsWith(".localhost")||e==="[::1]"||e==="::1"?true:/^127(\.\d{1,3}){3}$/.test(e)}var On=1e4;function ve(n,e){return Q(n,e)}function Q(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 V({clock:e.clock,...e.onStateChange===void 0?{}:{onStateChange:e.onStateChange},request:()=>new Promise((i,l)=>{let u=e.clock.setTimeout(()=>{r=null,l({reason:"unavailable",retryable:true});},e.timeoutMs??On);r={resolve:c=>{e.clock.clearTimeout(u),i(c);},reject:l,timer:u};})}),a=n.onServerToken(i=>{let l=t(i),u=r;if(u){r=null,u.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 ee={};ze(ee,{acceptTransfer:()=>Gn,addEntityProgression:()=>Tn,adminAction:()=>In,cancelInventoryTransfer:()=>Cn,claimEntityProgressionRewards:()=>En,closeGameRoom:()=>Mn,createEntityBatchOrder:()=>Ln,createEntityOrder:()=>qn,createSession:()=>jn,deleteEntityGameSetting:()=>$n,deleteEntitySave:()=>Bn,deleteSession:()=>Fn,deleteShowcaseValue:()=>Dn,executeEntityRecipe:()=>Un,finalizeSaveUpload:()=>Nn,getChannelAssignment:()=>Hn,getDropRates:()=>Vn,getEntityCurrency:()=>Wn,getEntityGameSetting:()=>zn,getEntityInventory:()=>Kn,getEntityInventoryItem:()=>Yn,getEntityLeaderboard:()=>Jn,getEntityOrder:()=>Xn,getEntityProgression:()=>Qn,getEntityRecipeAvailability:()=>Zn,getEntityRecipeUsage:()=>et,getEntitySave:()=>nt,getEvent:()=>tt,getGameRoomV2:()=>rt,getLeaderboard:()=>ot,getPlayerGameProfile:()=>at,getPurchaseCatalog:()=>st,getResolvedTemplate:()=>it,getRoomArgs:()=>lt,getShowcaseValue:()=>dt,getTransferDetails:()=>ut,ingestAnalyticsEvents:()=>Z,initiateInventoryTransfer:()=>ct,invokeFunction:()=>mt,kickPlayer:()=>pt,listChallenges:()=>gt,listEntityGameSettings:()=>yt,listEntityOrders:()=>ft,listEntityProgressions:()=>ht,listEntitySaves:()=>_t,listEvents:()=>bt,listGameRooms:()=>Rt,listResolvedTemplates:()=>vt,listTransfers:()=>St,maxEntityProgression:()=>xt,putEntityGameSetting:()=>wt,putRoomArgs:()=>kt,putShowcaseValue:()=>At,rejectTransfer:()=>Pt,reportMatchPlayers:()=>Ot,requestSaveUploadUrl:()=>Gt,resetEntityProgression:()=>Tt,setMatchBackfill:()=>It,simulateEntityOrder:()=>Ct,transferHostV2:()=>Et,updateGameRoomV2:()=>Mt});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 Gn(n,e,t){let r=`/v1/inventory/transfers/${s(e)}/accept`;return n.client.post(r,void 0,t?.signal)}async function Tn(n,e,t,r,o,a){let i=`/v1/inventory/${s(e)}/${s(t)}/progressions/${s(r)}/add`;return n.client.post(i,o,a?.signal)}async function In(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 En(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 Mn(n,e,t){let r=`/v1/games/${s(n.gameId())}/game-rooms/${s(e)}`;return n.client.delete(r,t?.signal)}async function Ln(n,e,t,r,o){let a=`/v1/inventory/${s(e)}/${s(t)}/orders/batch`;return n.client.post(a,r,o?.signal,{...o?.ifMatch===void 0?{}:{ifMatch:o.ifMatch}})}async function qn(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 jn(n,e,t){return n.client.post("/v1/voice/sessions",e,t?.signal)}async function $n(n,e,t,r,o){let a=`/v1/settings/${s(e)}/${s(t)}/${s(r)}`;return n.client.delete(a,o?.signal)}async function Bn(n,e,t,r,o){let a=`/v1/saves/${s(e)}/${s(t)}/${s(r)}`;return n.client.delete(a,o?.signal)}async function Fn(n,e,t){let r=`/v1/voice/sessions/${s(e)}`;return n.client.delete(r,t?.signal)}async function Dn(n,e,t,r){let o=`/v1/showcase/players/${s(e)}/${s(t)}`;return n.client.delete(o,r?.signal)}async function Un(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 Nn(n,e,t,r,o,a){let i=`/v1/saves/${s(e)}/${s(t)}/${s(r)}/finalize`;return n.client.post(i,o,a?.signal)}async function Hn(n,e,t){let r=`/v1/games/${s(n.gameId())}/config/channels/${s(e)}`;return n.client.getWithEtag(r,{...t?.signal===void 0?{}:{signal:t.signal},...t?.ifNoneMatch===void 0?{}:{ifNoneMatch:t.ifNoneMatch}})}async function Vn(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 zn(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 Kn(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 Yn(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 Jn(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 Xn(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 Qn(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 Zn(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 et(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 nt(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 tt(n,e,t){let r=`/v1/events/${s(e)}`;return n.client.get(r,t?.signal)}async function rt(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 ot(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 at(n,e,t){let r=`/v1/profiles/players/${s(e)}`;return n.client.get(r,t?.signal)}async function st(n,e){let t=new URLSearchParams;e?.config_version!==void 0&&t.set("config_version",String(e?.config_version));let r=t.toString(),o="/v1/inventory/platform-funded-game-inventory-purchase-catalog"+(r?`?${r}`:"");return n.client.get(o,e?.signal)}async function it(n,e,t){let r=`/v1/game-room-templates/${s(e)}`;return n.client.get(r,t?.signal)}async function lt(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 dt(n,e,t,r){let o=`/v1/showcase/players/${s(e)}/${s(t)}`;return n.client.get(o,r?.signal)}async function ut(n,e,t){let r=`/v1/inventory/transfers/${s(e)}`;return n.client.get(r,t?.signal)}async function Z(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 ct(n,e,t){return n.client.post("/v1/inventory/transfers",e,t?.signal)}async function mt(n,e,t){let r=new URLSearchParams;t?.cue_id!==void 0&&r.set("cue_id",String(t?.cue_id));let o=r.toString(),a="/v1/functions/invoke"+(o?`?${o}`:"");return n.client.postBytes(a,e,t?.signal)}async function pt(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 gt(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 yt(n,e,t,r){let o=`/v1/settings/${s(e)}/${s(t)}`;return n.client.get(o,r?.signal)}async function ft(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 ht(n,e,t,r){let o=`/v1/inventory/${s(e)}/${s(t)}/progressions`;return n.client.get(o,r?.signal)}async function _t(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 bt(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 Rt(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 vt(n,e){return n.client.get("/v1/game-room-templates",e?.signal)}async function St(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 xt(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 wt(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 kt(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 Pt(n,e,t){let r=`/v1/inventory/transfers/${s(e)}/reject`;return n.client.post(r,void 0,t?.signal)}async function Ot(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 Gt(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 Tt(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 It(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 Et(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 Mt(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 Se="gem_";function xe(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 jt=1e4,$t=50,Bt=1e3,Ft=65536-4*1024,we=n=>typeof n=="number"?n:0,Dt=n=>typeof n=="string"?n:"";function ke(){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 Ut(n){return n?.retryable===true}function Nt(n,e){let t=n??{},r=Array.isArray(t.rejected)?t.rejected.map(o=>{let a=o??{};return {index:we(a.index),code:Dt(a.code)}}):[];return {accepted:we(t.accepted),rejected:r,dropped:e,duplicate:t.duplicate===true}}function Ae(n,e){return {event_uid:n.uid,name:n.name,offset_ms:Math.round(n.atMs)-e,player_id:n.playerId,dimensions:n.dimensions,measures:n.measures}}function Pe(n){let e=Math.max(1,Math.floor(n.maxQueue??Bt)),t={client:n.client,gameId:()=>n.gameId},r=[],o=0,a=null,i=false,l=null,u=0,c=0,p=false,f=false,x=R=>{n.log?.(R);},_=()=>{a!==null&&(n.clock.clearTimeout(a),a=null);},E=()=>Math.max(0,c-n.clock.now()),h=()=>{a!==null||i||l!==null||(a=n.clock.setTimeout(()=>{a=null,w().catch(()=>{});},Math.max(jt,E())));},A=()=>{let R=Math.min(r.length,100),v=128;for(let O=0;O<R;O+=1){let T=r[O];if(T===void 0)break;if(v+=JSON.stringify(Ae(T,0)).length+1,v>Ft)return Math.max(1,O)}return R};async function w(R){for(;l!==null;)await l.catch(()=>{});if(r.length===0)return {accepted:0,rejected:[],dropped:0,duplicate:false};let v=M(R);l=v;try{return await v}finally{l===v&&(l=null),r.length>0&&h();}}async function M(R){_();let v=r.splice(0,A()),O=o;o=0;let T=Math.round(n.clock.now()),H={batch_id:ke(),sent_at_ms:T,events:v.map(k=>Ae(k,T))};try{let k=await Z(t,H,R===void 0?void 0:{signal:R}),I=Nt(k,O);u=0,c=0;for(let Ve of I.rejected)x(`[gem] analytics: an event was refused (${Ve.code}). See the analytics_events section of your game config.`);return I}catch(k){if(Ut(k)){for(r=[...v,...r],o+=O;r.length>e;)r.shift(),o+=1;u+=1,c=n.clock.now()+xe(u,k);}else x(`[gem] analytics: ${v.length} event(s) were discarded \u2014 the platform refused the batch and will refuse it again: ${String(k)}`);throw k}}return {track(R,v,O={}){if(i)return;if(typeof R!="string"||R===""){f||(f=true,x(`[gem] analytics: '${v}' 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(v.startsWith(Se)){p||(p=true,x(`[gem] analytics: '${v}' 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={},H={};for(let[k,I]of Object.entries(O))typeof I=="string"?T[k]=I:typeof I=="number"&&Number.isFinite(I)&&(H[k]=I);for(;r.length>=e;)r.shift(),o+=1;r.push({uid:ke(),playerId:R,name:v,atMs:n.clock.now(),dimensions:T,measures:H}),r.length>=$t&&l===null&&E()===0?w().catch(()=>{}):h();},flush:R=>w(R),get pending(){return r.length},dispose(){i=true,_(),r=[],o=0;}}}function Ht(n){return typeof n=="string"&&/^[\w-]{1,64}$/.test(n)}function Oe(n,e){if(n===void 0||Ht(n))return n;let t=typeof n=="string"?JSON.stringify(n.slice(0,72)):`a value of type ${typeof n}`;console.warn(`[gem] ${e}: cueId ${t} is not 1 to 64 letters, digits, _ or -, so it was left out. Use one crypto.randomUUID() per award.`);}var Vt=new Map([["function_error",false],["function_failed",false],["function_timeout",false],["function_not_published",false],["function_input_too_large",false],["invalid_cue_id",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]]),U=class extends g{constructor(e,t){super(e.reason,e.status,e.detail,e.retryAfterSeconds,e.code),this.name="GemFunctionError",Object.assign(this,t);}get retryable(){return (this.code===void 0?void 0:Vt.get(this.code))??super.retryable}},j=class{#e;constructor(e){this.#e=e;}async invoke(e,t={}){let r=Wt(e),o=Oe(t.cueId,"functions.invoke"),a;try{a=await this.#e(r,{...t.signal===void 0?{}:{signal:t.signal},...o===void 0?{}:{cue_id:o}});}catch(i){throw i instanceof g?Kt(i):i}return zt(a)}};function Wt(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 zt(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 Kt(n){let{details:e,invocationId:t}=ce(n),o=e?.untrusted?.message,a=e?.reason;return new U(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 P=n=>typeof n=="string"?n:"",Yt=/(?:Z|[+-]\d{2}:?\d{2})$/i;function Ge(n){let e=P(n);if(!Yt.test(e))return 0;let t=Date.parse(e);return Number.isFinite(t)?Math.floor(t/1e3):0}var Jt=/^[0-9a-f]{1,64}$/,Xt=/^[0-9a-f]{16}$/,Qt=/^[A-Za-z][A-Za-z0-9_+\-/]{0,63}$/,Zt=/^(?:[01]\d|2[0-3]):[0-5]\d$/;function er(n){let e=P(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 nr=4096,tr=new TextEncoder;function rr(n){let e=P(n.challenge_data),t=P(n.challenge_data_hash);return e===""||!Xt.test(t)?{}:tr.encode(e).length>nr?{}:{data:e,dataHash:t}}function or(n){let e=n??{},t=Ge(e.period_start_at),r=Ge(e.period_ends_at);if(t===0||r===0)return;let o=P(e.slug),a=P(e.seed),i=er(e.period_local_date),l=P(e.boundary),u=P(e.reset_time);return {id:P(e.progression_definition_id),...o===""?{}:{slug:o},window:P(e.window),periodStartAt:t,periodEndsAt:r,...i===void 0?{}:{periodLocalDate:i},boundary:Qt.test(l)?l:"",resetTime:Zt.test(u)?u:"",seed:Jt.test(a)?a:"",...rr(e)}}function Te(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 Ie(n){let e=n??{};return Array.isArray(e.challenges)?e.challenges.map(or).filter(t=>t!==void 0):[]}function Ce(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().");Te(r);let a=await n({player_id:t,...r===void 0?{}:{periods_back:r},...o===void 0?{}:{signal:o}});return Ie(a)}}}function ar(n,e){return Math.min(7,Math.max(1,Math.ceil((n-e)/864e5)))}function sr(n,e,t,r){if(!n)return 0;if(typeof e=="number"&&Number.isInteger(e))return Math.min(7,Math.max(1,e));if(t===null)return 7;let o=Date.parse(t);return Number.isFinite(o)?ar(o,r):7}function Ee(n,e){let t=n?.passes;if(!Array.isArray(t))return Object.freeze([]);let r=t.flatMap(o=>{let a=o??{};if(typeof a.pass!="string"||a.pass==="")return [];let i=a.held===true,l=i&&typeof a.ends_at=="string"?a.ends_at:null,u=sr(i,a.days_left,l,e);return [Object.freeze({pass:a.pass,held:i,daysLeft:u,endsAt:l})]});return Object.freeze(r)}var ir=7;function lr(n){let e=n??{},r=(Array.isArray(e.boosts)?e.boosts:[]).flatMap(i=>{let l=i??{};return typeof l.currency_slug!="string"||l.currency_slug===""?[]:typeof l.multiplier_bp!="number"||!Number.isInteger(l.multiplier_bp)?[]:l.multiplier_bp<=0?[]:[Object.freeze({currencySlug:l.currency_slug,multiplier:l.multiplier_bp/1e4})]}),o=e.boosted===true,a=e.expires_in_days;return Object.freeze({active:o,multipliers:Object.freeze(r),...o&&typeof a=="number"&&Number.isInteger(a)?{expiresInDays:Math.min(ir,Math.max(1,a))}:{}})}function Me(n,e=()=>Date.now()){let t=n,r=t.passes,o=t.boost,a=typeof r=="function"?r:void 0,i=typeof o=="function"?o:void 0,l=async(u,c,p)=>{if(u===void 0)throw new Error(`this runtime cannot read a player's ${c}: the server image running this bundle predates host.${c}, or this is a listen host, and only the platform half of a dedicated server holds the allocation proof the read needs.`);if(typeof p!="string"||p==="")throw new TypeError(`gem.match.player${c==="passes"?"Passes":"Boost"}: playerId must be a non-empty string`);let f;try{f=await u.call(n,p);}catch(x){throw new g("unavailable",0,`the platform half could not be asked: ${String(x)}`)}if(f.status!==200)throw me(f.status,f.body);return f.body};return {playerPasses:async u=>Ee(await l(a,"passes",u),e()),playerBoost:async u=>lr(await l(i,"boost",u))}}var te=n=>n!==null&&typeof n=="object"?n:{},re=n=>typeof n=="string"&&n!==""?n:void 0,ne=n=>typeof n=="number"&&Number.isSafeInteger(n)?n:void 0;function dr(n,e){let t=te(n);if(t.type!=="platform_grant")return null;let r=re(t.target_currency_id),o=ne(t.granted);if(r===void 0||o===void 0)return null;let a=ne(t.requested)??o,i=Math.max(0,Math.min(ne(t.base_granted)??Math.min(a,o),o)),l=o-i,u=te(t.boost_source),c=re(u.pass),p=e(r);return {...p===void 0?{}:{currencySlug:p},currencyId:r,base:i,total:o,breakdown:l<=0?[]:[c===void 0?{source:"boost",amount:l}:{source:"pass",pass:c,amount:l}]}}function Le(n){return {async fromReceipt(e){let t=re(te(e).target_currency_id),r=t===void 0?void 0:n.knownSlug(t);return t!==void 0&&r===void 0&&(r=await n.readSlugs().then(o=>o.get(t)||void 0,()=>{})),dr(e,()=>r)}}}function ur(n){let e={};for(let[t,r]of Object.entries(ee))if(typeof r=="function"){let o=r;e[t]=(...a)=>o(n,...a);}return e}function Y(n,e={}){let t=e.clock??q,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=Q(n,{clock:t,...e.onAuthStateChange===void 0?{}:{onStateChange:e.onAuthStateChange}}),a=ge({baseUrl:r,tokenSource:o.source,defaultQuery:{game_id:n.gameId,channel:n.channel},...e.fetch===void 0?{}:{fetch:e.fetch}}),i=new L({transport:a,clock:t}),l={gameId:n.gameId,channel:n.channel,matchId:n.matchId,...n.gameRoomId===void 0?{}:{gameRoomId:n.gameRoomId}},u=ur({client:i,gameId:()=>l.gameId}),c=l.gameRoomId,p=n.endMatch,f=Me(n,()=>t.now()),x=n.log,_=Pe({client:i,clock:t,gameId:l.gameId,...typeof x=="function"?{log:h=>x.call(n,h)}:{}});return {identity:l,client:i,api:u,match:{end:async()=>{if(p===void 0)throw new Error("this runtime cannot end the match: the server image running this bundle predates host.endMatch, and only the platform half holds the allocation proof an end needs.");await p.call(n);},setBackfill:async(h,A)=>{let w=await u.setMatchBackfill(l.matchId,{open:h.open,...h.seats===void 0?{}:{seats:h.seats}},A===void 0?{}:{signal:A});return {open:w.open,seats:w.seats??null}},reportPlayers:async(h,A)=>(await u.reportMatchPlayers(l.matchId,{players:h.map(M=>({player_id:M.playerId,state:M.state}))},A===void 0?{}:{signal:A})).players.map(M=>({playerId:M.player_id,outcome:M.outcome})),...f},analytics:_,earnings:Le({knownSlug:()=>{},readSlugs:async()=>new Map}),functions:new j(u.invokeFunction),challenges:Ce(u.listChallenges),...c===void 0?{}:{room:{get:h=>u.getGameRoomV2(c,h),args:async h=>{let A=await u.getGameRoomV2(c,h?.signal===void 0?{}:{signal:h.signal}),w=A.modified?A.body:void 0;if(w?.room_args==null||w.room_args_template==null)throw new g("not_found",404,"this room's template declares no room args",void 0,"room_args_not_defined");return {room_args:w.room_args,room_args_template:w.room_args_template}}}},dispose:()=>{_.dispose(),o.dispose();}}}var cr=["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"],mr=new Set(cr);function qe(n){return typeof n=="string"&&mr.has(n)?n:"unknown"}var Be="[gem: use gem.text.toPlain()]",je=new Set,$e;function pr(n){try{if(je.has(n))return;let e=globalThis.location;if($e??=!!e?.port&&Re(e.hostname??""),!$e)return;je.add(n),console.warn(`[gem] ${n} is PlayerText, turned into a string: players see ${Be}. Render text.toPlain(value) (text is in @indiegems/gem-web-sdk/sdk).
2
2
  ${new Error().stack}`);}catch{}}var S=class{#e;#n;constructor(e,t="player text"){this.#e=e,this.#n=t,Object.freeze(this);}toString(){return pr(this.#n),Be}toJSON(){return this.toString()}get[Symbol.toStringTag](){return "PlayerText"}static unwrap(e){return e.#e}};function N(n,e){return new S(n,e)}var Fe={toPlain(n){return S.unwrap(n)},compare(n,e,t){let r=n instanceof S?S.unwrap(n):n,o=e instanceof S?S.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 S?S.unwrap(n):n,r=e instanceof S?S.unwrap(e):e;return t.normalize("NFC")===r.normalize("NFC")}};var De="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 oe(n,e={}){let t=e.clock??q,r=()=>{let l=n();if(l===null)throw new Error(De);return l},o=null,a=()=>{if(o===null)throw new Error(De);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 earnings(){return a().earnings},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 p=c.displayName;return typeof p!="string"||p===""?null:{displayName:N(p,"profile.displayName"),...typeof c.displayTag=="string"&&c.displayTag!==""?{displayTag:N(c.displayTag,"profile.displayTag")}:{},...typeof c.discriminator=="string"?{discriminator:c.discriminator}:{}}},playerNumber(l){return r().playerNumber?.(l)},send(l,u,c){c===void 0?r().send(l,u):r().send(l,u,c);},broadcast(l,u){u===void 0?r().broadcast(l):r().broadcast(l,u);},kick(l,u){u===void 0?r().kick(l):r().kick(l,u);},log(l){r().log(l);},warn(l){r().warn(l);}},attach:()=>{o=Y(r(),{...e,clock:t});}}}function Ue(n,e={}){let{server:t,attach:r}=oe(()=>n,e);return r(),t}function gr(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:qe(e)}}}var yr=1e4;function fr(n){let e=false;return t=>{if(e)return;let r;try{r=n.match.reportPlayers([{playerId:t,state:"connected"}],AbortSignal.timeout(yr));}catch{return}r.catch(o=>{o instanceof g&&o.status>=400&&o.status<500&&(e=o.status!==429);});}}function Ne(n,e={}){return ()=>{let t=null,{server:r,attach:o}=oe(()=>t,e),a=n(r),i={async init(u){t=u,o(),await a.init?.();},async shutdown(u){let c=gr(u);try{await a.shutdown?.(c);}finally{r.dispose();}}},l=fr(r);return i.join=(u,c)=>(l(u),a.join?.(u,c)),a.leave&&(i.leave=(u,c)=>a.leave?.(u,c)),a.message&&(i.message=(u,c,p,f)=>a.message?.(u,c,p,f)),i}}var hr=new Set(["unlocked","already_unlocked","suppressed"]);function He(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"||!hr.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}export{b as AuthError,W as CONDITIONAL_HEADERS,j as FunctionsApi,g as GemApiError,L as GemClient,U as GemFunctionError,S as PlayerText,y as TransportRefusal,He as achievementReceipts,N as asPlayerText,Y as createGemServer,ve as createHostTokenSource,Ue as createMatchServer,Ne as defineServer,q as systemClock,Fe as text,ie 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` v24.0.2, 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` v24.1.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.
4
4
 
5
5
  `@indiegems/gem-web-sdk/function` exports exactly the symbols on this page and nothing else.
6
6
 
@@ -3330,6 +3330,11 @@ browser. What a pass unlocks is decided by your function or server.
3330
3330
  Reads reject with a `GemApiError`, as every `gem.me` read does. That is
3331
3331
  unknown, not "not held", so keep what you drew. A guest reads as not holding.
3332
3332
 
3333
+ To test a held VIP before it is on sale, a Contributor or above gives their own
3334
+ account or a test account VIP for 1 to 30 days with
3335
+ `gemctl org test-accounts pass grant <org-id> me vip --days 7`; it reads
3336
+ here like a bought one.
3337
+
3333
3338
  **Guides.** [arcade-and-store](../arcade-and-store.md)
3334
3339
 
3335
3340
  <a id="passesapi-list"></a>
@@ -1,6 +1,6 @@
1
1
  # The browser surface — API reference
2
2
 
3
- Generated from `@indiegems/gem-web-sdk/sdk` v24.0.2, 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` v24.1.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.
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
 
@@ -5113,16 +5113,16 @@ showOffer(skuId: string): Promise<ArcadeOutcome>
5113
5113
  ```
5114
5114
 
5115
5115
  Ask the arcade to show one SKU from [StoreApi.offers](#storeapi-offers) in its own
5116
- sheet, over your paused and hidden game: its art, what the player gets, a
5117
- sale if one is on, and, for a pass the player already holds, how long it
5118
- has left. The sheet's Buy opens the same checkout as
5116
+ sheet, over your paused and hidden game: its art, what the player gets
5117
+ and a sale if one is on. The sheet's Buy opens the same checkout as
5119
5118
  [StoreApi.purchase](#storeapi-purchase). Like `purchase`, it needs no press.
5120
5119
 
5121
5120
  Use it for an offer you would have to hardcode a pitch for: VIP and other
5122
5121
  passes, and bundles. Your button only needs to say what it opens. Draw a
5123
5122
  Coin pack yourself and use `purchase` instead. For a pass, call
5124
5123
  [StoreApi.showPass](#storeapi-showpass) with its slug. Check
5125
- [StoreApi.showOfferAvailable](#storeapi-showofferavailable) first, and that the SKU is in `offers`.
5124
+ [StoreApi.showOfferAvailable](#storeapi-showofferavailable) first, and that the SKU is in `offers`:
5125
+ a pass the player already holds may or may not be there.
5126
5126
 
5127
5127
  It answers exactly as `purchase` does, with one addition: `declined` /
5128
5128
  `cancelled` also covers the player leaving the sheet without pressing Buy,
@@ -5192,9 +5192,16 @@ Whether the pass `slug` is on sale to this player here, so
5192
5192
  [StoreApi.showPass](#storeapi-showpass) would open it. For a screen that sells a pass
5193
5193
  outside a reward moment, such as a "VIP perks" panel; at a reward moment,
5194
5194
  `gem.gameConfig.preview`'s `upsells` already says so. `false` where the
5195
- store is off, for a player the platform won't sell it to, after the
5196
- player declined its sheet twice today, and on an older Arcade. A player
5197
- who holds the pass may still read `true`: the sheet adds time.
5195
+ store is off, for a player the platform won't sell it to, and on an
5196
+ older Arcade. A declined sheet never changes it: a game may open a
5197
+ pass's sheet as often as it likes. For a
5198
+ player who already holds the pass it may read `true` or `false`: assume
5199
+ neither, and read `gem.me.passes` for what they hold.
5200
+
5201
+ VIP may not be on sale where you test yet. To test what a VIP player sees, a
5202
+ Contributor or above gives their own account or a test account VIP for 1
5203
+ to 30 days with `gemctl org test-accounts pass grant <org-id> me vip --days 7`
5204
+ (`me`, or the test account's name).
5198
5205
 
5199
5206
  | Parameter | Type |
5200
5207
  | --- | --- |
@@ -7114,8 +7121,8 @@ readonly upsells: readonly PassUpsell[]
7114
7121
 
7115
7122
  One per pass on sale here, not held, that would change this answer. Empty
7116
7123
  means show no upsell: no pass would add anything, or none is on sale to
7117
- this player (a minor, a store that is off, a pass declined twice today, or
7118
- already held).
7124
+ this player (a minor, a store that is off, or a pass already held). A
7125
+ declined pass sheet never empties it.
7119
7126
 
7120
7127
  <a id="previewerror"></a>
7121
7128
 
@@ -7777,6 +7784,11 @@ browser. What a pass unlocks is decided by your function or server.
7777
7784
  Reads reject with a `GemApiError`, as every `gem.me` read does. That is
7778
7785
  unknown, not "not held", so keep what you drew. A guest reads as not holding.
7779
7786
 
7787
+ To test a held VIP before it is on sale, a Contributor or above gives their own
7788
+ account or a test account VIP for 1 to 30 days with
7789
+ `gemctl org test-accounts pass grant <org-id> me vip --days 7`; it reads
7790
+ here like a bought one.
7791
+
7780
7792
  **Guides.** [arcade-and-store](../arcade-and-store.md)
7781
7793
 
7782
7794
  <a id="passesapi-list"></a>
@@ -1,6 +1,6 @@
1
1
  # The server surface — API reference
2
2
 
3
- Generated from `@indiegems/gem-web-sdk/sdk` v24.0.2, 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` v24.1.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.
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": "24.0.2"
5
+ "version": "24.1.0"
6
6
  },
7
7
  "entries": [
8
8
  {
@@ -6066,7 +6066,7 @@
6066
6066
  "group": "store",
6067
6067
  "signature": "showOffer(skuId: string): Promise<ArcadeOutcome>",
6068
6068
  "documented": true,
6069
- "summary": "Ask the arcade to show one SKU from [StoreApi.offers](api-reference-game.md#storeapi-offers) in its own\nsheet, over your paused and hidden game: its art, what the player gets, a\nsale if one is on, and, for a pass the player already holds, how long it\nhas left. The sheet's Buy opens the same checkout as\n[StoreApi.purchase](api-reference-game.md#storeapi-purchase). Like `purchase`, it needs no press.\n\nUse it for an offer you would have to hardcode a pitch for: VIP and other\npasses, and bundles. Your button only needs to say what it opens. Draw a\nCoin pack yourself and use `purchase` instead. For a pass, call\n[StoreApi.showPass](api-reference-game.md#storeapi-showpass) with its slug. Check\n[StoreApi.showOfferAvailable](api-reference-game.md#storeapi-showofferavailable) first, and that the SKU is in `offers`.\n\nIt answers exactly as `purchase` does, with one addition: `declined` /\n`cancelled` also covers the player leaving the sheet without pressing Buy,\nand you are not told which of the two they closed. Do not ask again\nunprompted; the player's next press opens it again. `unavailable` / `unsupported`\nmeans this Arcade does not draw the sheet, and nothing was sent.\n`unavailable` / `error` means **the outcome is unknown**: re-read balances\nand inventory through `gem.me`, and keep listening with\n[StoreApi.onSettled](api-reference-game.md#storeapi-onsettled).\n\nNO TIMEOUT: it waits for as long as the arcade is connected, because a\nplayer may read a sheet and pay for as long as they like.",
6069
+ "summary": "Ask the arcade to show one SKU from [StoreApi.offers](api-reference-game.md#storeapi-offers) in its own\nsheet, over your paused and hidden game: its art, what the player gets\nand a sale if one is on. The sheet's Buy opens the same checkout as\n[StoreApi.purchase](api-reference-game.md#storeapi-purchase). Like `purchase`, it needs no press.\n\nUse it for an offer you would have to hardcode a pitch for: VIP and other\npasses, and bundles. Your button only needs to say what it opens. Draw a\nCoin pack yourself and use `purchase` instead. For a pass, call\n[StoreApi.showPass](api-reference-game.md#storeapi-showpass) with its slug. Check\n[StoreApi.showOfferAvailable](api-reference-game.md#storeapi-showofferavailable) first, and that the SKU is in `offers`:\na pass the player already holds may or may not be there.\n\nIt answers exactly as `purchase` does, with one addition: `declined` /\n`cancelled` also covers the player leaving the sheet without pressing Buy,\nand you are not told which of the two they closed. Do not ask again\nunprompted; the player's next press opens it again. `unavailable` / `unsupported`\nmeans this Arcade does not draw the sheet, and nothing was sent.\n`unavailable` / `error` means **the outcome is unknown**: re-read balances\nand inventory through `gem.me`, and keep listening with\n[StoreApi.onSettled](api-reference-game.md#storeapi-onsettled).\n\nNO TIMEOUT: it waits for as long as the arcade is connected, because a\nplayer may read a sheet and pay for as long as they like.",
6070
6070
  "deprecated": null,
6071
6071
  "params": [
6072
6072
  {
@@ -6112,7 +6112,7 @@
6112
6112
  "group": "store",
6113
6113
  "signature": "passOnSale(slug: string): Promise<boolean>",
6114
6114
  "documented": true,
6115
- "summary": "Whether the pass `slug` is on sale to this player here, so\n[StoreApi.showPass](api-reference-game.md#storeapi-showpass) would open it. For a screen that sells a pass\noutside a reward moment, such as a \"VIP perks\" panel; at a reward moment,\n`gem.gameConfig.preview`'s `upsells` already says so. `false` where the\nstore is off, for a player the platform won't sell it to, after the\nplayer declined its sheet twice today, and on an older Arcade. A player\nwho holds the pass may still read `true`: the sheet adds time.",
6115
+ "summary": "Whether the pass `slug` is on sale to this player here, so\n[StoreApi.showPass](api-reference-game.md#storeapi-showpass) would open it. For a screen that sells a pass\noutside a reward moment, such as a \"VIP perks\" panel; at a reward moment,\n`gem.gameConfig.preview`'s `upsells` already says so. `false` where the\nstore is off, for a player the platform won't sell it to, and on an\nolder Arcade. A declined sheet never changes it: a game may open a\npass's sheet as often as it likes. For a\nplayer who already holds the pass it may read `true` or `false`: assume\nneither, and read `gem.me.passes` for what they hold.\n\nVIP may not be on sale where you test yet. To test what a VIP player sees, a\nContributor or above gives their own account or a test account VIP for 1\nto 30 days with `gemctl org test-accounts pass grant <org-id> me vip --days 7`\n(`me`, or the test account's name).",
6116
6116
  "deprecated": null,
6117
6117
  "params": [
6118
6118
  {
@@ -8395,7 +8395,7 @@
8395
8395
  "group": "payout-preview",
8396
8396
  "signature": "readonly upsells: readonly PassUpsell[]",
8397
8397
  "documented": true,
8398
- "summary": "One per pass on sale here, not held, that would change this answer. Empty\nmeans show no upsell: no pass would add anything, or none is on sale to\nthis player (a minor, a store that is off, a pass declined twice today, or\nalready held).",
8398
+ "summary": "One per pass on sale here, not held, that would change this answer. Empty\nmeans show no upsell: no pass would add anything, or none is on sale to\nthis player (a minor, a store that is off, or a pass already held). A\ndeclined pass sheet never empties it.",
8399
8399
  "deprecated": null,
8400
8400
  "params": [],
8401
8401
  "returns": null,
@@ -9263,7 +9263,7 @@
9263
9263
  "group": "saves",
9264
9264
  "signature": "interface PassesApi",
9265
9265
  "documented": true,
9266
- "summary": "Which store passes the player holds, for the passes the platform lets games\nsee. Reached as `gem.me.passes`. VIP is the pass `vip`.\n\nUse it to DRAW a door open or shut, never to decide: it runs in the player's\nbrowser. What a pass unlocks is decided by your function or server.\n\nReads reject with a `GemApiError`, as every `gem.me` read does. That is\nunknown, not \"not held\", so keep what you drew. A guest reads as not holding.",
9266
+ "summary": "Which store passes the player holds, for the passes the platform lets games\nsee. Reached as `gem.me.passes`. VIP is the pass `vip`.\n\nUse it to DRAW a door open or shut, never to decide: it runs in the player's\nbrowser. What a pass unlocks is decided by your function or server.\n\nReads reject with a `GemApiError`, as every `gem.me` read does. That is\nunknown, not \"not held\", so keep what you drew. A guest reads as not holding.\n\nTo test a held VIP before it is on sale, a Contributor or above gives their own\naccount or a test account VIP for 1 to 30 days with\n`gemctl org test-accounts pass grant <org-id> me vip --days 7`; it reads\nhere like a bought one.",
9267
9267
  "deprecated": null,
9268
9268
  "params": [],
9269
9269
  "returns": null,
@@ -36053,7 +36053,7 @@
36053
36053
  "group": "player",
36054
36054
  "signature": "interface PassesApi",
36055
36055
  "documented": true,
36056
- "summary": "Which store passes the player holds, for the passes the platform lets games\nsee. Reached as `gem.me.passes`. VIP is the pass `vip`.\n\nUse it to DRAW a door open or shut, never to decide: it runs in the player's\nbrowser. What a pass unlocks is decided by your function or server.\n\nReads reject with a `GemApiError`, as every `gem.me` read does. That is\nunknown, not \"not held\", so keep what you drew. A guest reads as not holding.",
36056
+ "summary": "Which store passes the player holds, for the passes the platform lets games\nsee. Reached as `gem.me.passes`. VIP is the pass `vip`.\n\nUse it to DRAW a door open or shut, never to decide: it runs in the player's\nbrowser. What a pass unlocks is decided by your function or server.\n\nReads reject with a `GemApiError`, as every `gem.me` read does. That is\nunknown, not \"not held\", so keep what you drew. A guest reads as not holding.\n\nTo test a held VIP before it is on sale, a Contributor or above gives their own\naccount or a test account VIP for 1 to 30 days with\n`gemctl org test-accounts pass grant <org-id> me vip --days 7`; it reads\nhere like a bought one.",
36057
36057
  "deprecated": null,
36058
36058
  "params": [],
36059
36059
  "returns": null,