@indiegems/gem-web-sdk 16.0.0 → 16.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 Ee=Object.defineProperty;var Le=(n,e)=>{for(var t in e)Ee(n,t,{get:e[t],enumerable:true});};globalThis.__gemWebSdkVersion="[gem-web-sdk:sdkVersion:16.0.0]";var qe={initialDelayMs:2e3,maxDelayMs:6e4};function Me(n,e){return e!==void 0?!e:n==="chain_exhausted"}var U=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}=qe,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=$e(o),{retryable:i,retryAfterMs:l}=o??{};throw t===this.generation&&(Me(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 $e(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 f=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}},N=["if-match","if-none-match"],Q=4096;function je(n){if(!n)return;let e={};for(let[t,r]of Object.entries(n)){let o=t.toLowerCase();if(!N.includes(o)||r===void 0)continue;let a=typeof r=="string"?Be(r):r;if(typeof a!="string"||a.length>Q||!Fe(a))throw new f(`the ${o} header value cannot be sent \u2014 it is not a string, is longer than ${Q} 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 Be(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 Fe(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 Ue(n){let{bytes:e}=n;if(e!==void 0){if(Object.prototype.toString.call(e)!=="[object Uint8Array]")throw new f("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 f("the request carries both a JSON body and a raw body, and only one can be sent. This is a malformed request, not a server failure.");return new Uint8Array(e)}}function Z(n,e){let t=e.replayUnauthorizedOnce??true;return {async request(r){let o={...r},a=je(o.headers),i=Ue(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(),_=await n(l,p);if(_.status===401)throw e.tokenSource.close("unavailable"),new b("unavailable","the server refused a freshly minted token");return _}}}function ee(n){let e=typeof n=="string"?new TextEncoder().encode(n):n;return btoa(Ne(e))}function Ne(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"}},te=new WeakMap;function re(n){return te.get(n)??{}}var De=new Set([408,429,500,502,503,504]),He=6e4;function Ve(n){if(n===void 0)return 2;if(!Number.isInteger(n)||n<0||n>10)throw new f(`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:We(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?Ve(this.options.maxRetries)+1:1,a=null;if(e.signal?.aborted)throw ne(e.signal);for(let i=0;i<o;i++){if(i>0&&await this.backoff(i,a,e.signal),e.signal?.aborted)throw ne(e.signal);let l;try{l=await this.options.transport.request(e);}catch(c){if(b.isAuthError(c)||f.isRefusal(c)||e.signal?.aborted||ze(c))throw c;a=new g("unavailable",0,String(c));continue}if(l.status>=200&&l.status<300||l.status===304)return l;let u=Ke(l);if(!De.has(l.status)||l.status===429&&!r)throw u;a=u;}throw a??new g("unavailable",0,"no attempt was made")}backoff(e,t,r){if(r?.aborted)return Promise.resolve();let o=t?.retryAfterSeconds,a=o!==void 0?o*1e3:2**(e-1)*250,i=2**(e-1)*250,l=Math.min(Math.max(a,i),He);return new Promise(u=>{let c=this.options.clock,p=false,_=false,R,h=()=>{p||(p=true,_&&c.clearTimeout(R),r?.removeEventListener("abort",h),u());};r?.addEventListener("abort",h,{once:true}),R=c.setTimeout(h,l),_=true,p&&c.clearTimeout(R);})}};function We(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 ne(n){return n.reason!==void 0?n.reason:new DOMException("The operation was aborted.","AbortError")}function ze(n){let e=n?.name;return e==="AbortError"||e==="TimeoutError"}function Ke(n){let e=Je(n),t=Qe(n.body),r={...t===void 0?{}:{details:t},...n.invocationId===void 0?{}:{invocationId:n.invocationId}};return Object.keys(r).length>0&&te.set(e,r),e}var Ye=new Map([["insufficient_funds","insufficient_funds"]]);function Je(n){let{status:e,body:t}=n,r=Xe(t),o=n.retryAfterSeconds??en(t),a=Ze(t),i=a===void 0?void 0:Ye.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 Xe(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 Qe(n){let t=n?.error?.details;return t===null?void 0:t}function Ze(n){let t=n?.error?.code;return typeof t=="string"&&t.length>0?t:void 0}function en(n){let e=n?.retryAfterSeconds;return typeof e=="number"&&Number.isFinite(e)&&e>=0?e:void 0}function nn(n){let e=n.lastIndexOf("@");return (e===-1?n:`***@${n.slice(e+1)}`).slice(0,200)}var tn=new Set(N);function rn(n){if(!n)return {};let e={};for(let[t,r]of Object.entries(n))tn.has(t.toLowerCase())&&(e[t.toLowerCase()]=r);return e}function oe(n){let e=n.fetch??globalThis.fetch.bind(globalThis);return Z(async(t,r)=>{let o;try{o=new URL(n.baseUrl.replace(/\/+$/,""));}catch{throw new f("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 f(`${JSON.stringify(typeof t.path=="string"?nn(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 f(`${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 h=o.username!==""||o.password!=="",y=a.username!==o.username||a.password!==o.password,w=h?y?"baseUrl (and possibly the request path)":"baseUrl":"request path";throw new f(`the ${w} 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[h,y]of Object.entries(n.defaultQuery??{}))a.searchParams.has(h)||a.searchParams.set(h,y);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(h){throw new f(`the body of ${t.method} ${JSON.stringify(a.pathname)} could not be serialised to JSON: ${String(h)}. 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},...rn(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 h=await u.text();if(h.length>0)try{c=JSON.parse(h);}catch{c=h;}}let p=u.headers.get("etag"),_=on(u.headers.get("retry-after")),R=u.headers.get("x-gem-invocation-id");return {status:u.status,body:c,...p===null?{}:{etag:p},..._===void 0?{}:{retryAfterSeconds:_},...R===null||R===""?{}:{invocationId:R}}},n)}function on(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 an="gem-web-bridge";var sn=65536,ae=8,D=5e3,se=1024;var H=Object.create(null);var ie=Object.create(null);function ln(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 dn(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 un(n){return /^[a-z]{2,8}(-[a-z0-9]{1,8})*$/i.test(n)}function cn(n){return /^[a-z_]+$/.test(n)}function mn(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 W(n,e,t){if(e>ae)return `nesting deeper than ${ae}`;if(++t.nodes>D)return `more than ${D} 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>se)return `an array of ${n.length} entries, over the ${se} limit`;t.bytes+=2;for(let l of n){let u=W(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>D)return `more than ${D} values`;if(t.bytes+=l.length*3+4,t.bytes>t.cap)return `over the ${t.cap} byte limit`;let u=W(i[l],e+1,t);if(u)return u}return null}function gn(n,e=sn){let t={nodes:0,bytes:0,seen:new Set,cap:e},r=W(n,0,t);return r?`message contains ${r}`:t.bytes>e?`message is over the ${e} byte limit`:null}var pn={origin:[ln,"not a well-formed origin"],url:[dn,"not a safe absolute http(s) URL"],bcp47:[un,"not a well-formed BCP 47 tag"],code:[cn,"not a code of lower-case letters and underscores"],gameRef:[mn,"not a game id or web address"]};function le(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=z(a,r,o);if(i)return i}return null}function z(n,e,t){let r=e[1].toLowerCase();switch(r){case "u":return typeof n=="boolean"?null:z(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`:le(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=z(i,o,a);if(l)return l}return null}default:return `${t}: unknown kind ${String(r)}`}}var de=Object.create(null);function d(n,e,t,r,o){return H[n]=t,r&&(ie[n]=r),de[n]=a=>{let i=gn(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!==an?"gem: wrong protocol marker":l.type!==n?`type: expected ${n}`:le(l,e,"")}}var m=["requestId","s",64],I=["outcome","e",["ok","declined","unavailable"]],E=["reason","S",64,"code"];d("gem.handshake",[["versions","o",[["min","i",1,1e3],["max","i",1,1e3]]],["capabilities","A",64,["","s",64]],["embedder","s",2048,"origin"],["unbidden","B"]],30);d("gem.handshake.accept",[["v","i",1,1e3],["capabilities","A",64,["","s",64]]],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],["currencySlug","s",32],["multiplierBp","i",1e4,1e6]]]],["expiresInDays","I",1,7]]]],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"]]]],60);d("gem.cohorts",[["cohorts","a",8,["","o",[["experimentId","s",36],["variantKey","s",32]]]]],12,"cohorts");d("gem.earnAllowanceChanged",[],30,"earnAllowance");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"]],["matchId","s",64],["data","j"]],1800,"p2p");d("gem.dedicatedEvent",[["event","e",["answer","error","matchEnded"]],["matchId","s",64],["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,["","s",64]]],12,"clusterTarget");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"]],["matchId","s",64],["data","j"]],1200,"p2p");d("gem.dedicatedOffer",[["matchId","s",64],["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",[["currencySlug","s",32],["expected","I",1,1e9],["origin","O",[["x","i",0,16384],["y","i",0,16384]]]],60,"rewardCue");d("gem.walletDisplay",[["visible","b"],["currencies","A",8,["","s",64]],["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.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",[["params","a",16,["","o",[["key","s",64],["value","s",512]]]]],6,"share");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],["currencySlug","s",32],["quantity","I",1,10],["catalogId","S",64]],12,"purchases");d("gem.requestAvatar3dPurchase",[m,["itemId","s",64],["currencySlug","s",32]],12,"avatar3dPurchases");d("gem.purchaseResult",[m,I,E,["purchaseId","S",64]],30,"purchases");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]],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.requestAppLinks",[m],12,"appLinks");d("gem.appLinksResult",[m,I,E,["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,I,E],30,"appLinks");d("gem.requestOpenGame",[m,["ref","s",40,"gameRef"]],6,"openGame");d("gem.openGameResult",[m,I,E],30,"openGame");d("gem.requestSimilarGames",[m,["limit","I",1,24]],12,"openGame");d("gem.similarGamesResult",[m,I,E,["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,I,E,["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]]]]]]],30,"store",262144);d("gem.requestStorePurchase",[m,["skuId","s",64]],12,"store");d("gem.storePurchaseResult",[m,I,E],30,"store");d("gem.storePurchaseSettled",[["skuId","s",64]],30,"store");Object.freeze(de);H.__malformed=60;Object.freeze(H);Object.freeze(ie);var q={now:()=>Date.now(),setTimeout:(n,e)=>setTimeout(n,e),clearTimeout:n=>clearTimeout(n)};function ue(n){let e=n.toLowerCase();return e==="localhost"||e.endsWith(".localhost")||e==="[::1]"||e==="::1"?true:/^127(\.\d{1,3}){3}$/.test(e)}var yn=1e4;function ce(n,e){return K(n,e)}function K(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 U({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??yn);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 J={};Le(J,{acceptTransfer:()=>fn,addEntityProgression:()=>hn,adminAction:()=>_n,cancelInventoryTransfer:()=>bn,claimEntityProgressionRewards:()=>Rn,closeGameRoom:()=>vn,createEntityBatchOrder:()=>Sn,createEntityOrder:()=>xn,createSession:()=>wn,deleteEntityGameSetting:()=>kn,deleteEntitySave:()=>An,deleteSession:()=>On,deleteShowcaseValue:()=>Pn,executeEntityRecipe:()=>Gn,finalizeSaveUpload:()=>Tn,getChannelAssignment:()=>Cn,getDropRates:()=>In,getEntityCurrency:()=>En,getEntityGameSetting:()=>Ln,getEntityInventory:()=>qn,getEntityInventoryItem:()=>Mn,getEntityLeaderboard:()=>$n,getEntityOrder:()=>jn,getEntityProgression:()=>Bn,getEntityRecipeAvailability:()=>Fn,getEntityRecipeUsage:()=>Un,getEntitySave:()=>Nn,getEvent:()=>Dn,getGameRoomV2:()=>Hn,getLeaderboard:()=>Vn,getPlayerGameProfile:()=>Wn,getPurchaseCatalog:()=>zn,getResolvedTemplate:()=>Kn,getRoomArgs:()=>Yn,getShowcaseValue:()=>Jn,getTransferDetails:()=>Xn,ingestAnalyticsEvents:()=>Y,initiateInventoryTransfer:()=>Qn,invokeFunction:()=>Zn,kickPlayer:()=>et,listChallenges:()=>nt,listEntityGameSettings:()=>tt,listEntityOrders:()=>rt,listEntityProgressions:()=>ot,listEntitySaves:()=>at,listEvents:()=>st,listGameRooms:()=>it,listResolvedTemplates:()=>lt,listTransfers:()=>dt,maxEntityProgression:()=>ut,putEntityGameSetting:()=>ct,putRoomArgs:()=>mt,putShowcaseValue:()=>gt,rejectTransfer:()=>pt,reportMatchPlayers:()=>yt,requestSaveUploadUrl:()=>ft,resetEntityProgression:()=>ht,setMatchBackfill:()=>_t,simulateEntityOrder:()=>bt,transferHostV2:()=>Rt,updateGameRoomV2:()=>vt});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 fn(n,e,t){let r=`/v1/inventory/transfers/${s(e)}/accept`;return n.client.post(r,void 0,t?.signal)}async function hn(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 _n(n,e,t,r){let o=`/v1/voice/sessions/${s(e)}/admin`;return n.client.post(o,t,r?.signal)}async function bn(n,e,t){let r=`/v1/inventory/transfers/${s(e)}/cancel`;return n.client.post(r,void 0,t?.signal)}async function Rn(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 vn(n,e,t){let r=`/v1/games/${s(n.gameId())}/game-rooms/${s(e)}`;return n.client.delete(r,t?.signal)}async function Sn(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 xn(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 wn(n,e,t){return n.client.post("/v1/voice/sessions",e,t?.signal)}async function kn(n,e,t,r,o){let a=`/v1/settings/${s(e)}/${s(t)}/${s(r)}`;return n.client.delete(a,o?.signal)}async function An(n,e,t,r,o){let a=`/v1/saves/${s(e)}/${s(t)}/${s(r)}`;return n.client.delete(a,o?.signal)}async function On(n,e,t){let r=`/v1/voice/sessions/${s(e)}`;return n.client.delete(r,t?.signal)}async function Pn(n,e,t,r){let o=`/v1/showcase/players/${s(e)}/${s(t)}`;return n.client.delete(o,r?.signal)}async function Gn(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 Tn(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 Cn(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 In(n,e,t){let r=`/v1/inventory/loot-tables/${s(e)}/drop-rates`;return n.client.get(r,t?.signal)}async function En(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 Ln(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 qn(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 Mn(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 $n(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 jn(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 Bn(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 Fn(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 Un(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 Nn(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 Dn(n,e,t){let r=`/v1/events/${s(e)}`;return n.client.get(r,t?.signal)}async function Hn(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 Vn(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 Wn(n,e,t){let r=`/v1/profiles/players/${s(e)}`;return n.client.get(r,t?.signal)}async function zn(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 Kn(n,e,t){let r=`/v1/game-room-templates/${s(e)}`;return n.client.get(r,t?.signal)}async function Yn(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 Jn(n,e,t,r){let o=`/v1/showcase/players/${s(e)}/${s(t)}`;return n.client.get(o,r?.signal)}async function Xn(n,e,t){let r=`/v1/inventory/transfers/${s(e)}`;return n.client.get(r,t?.signal)}async function Y(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 Qn(n,e,t){return n.client.post("/v1/inventory/transfers",e,t?.signal)}async function Zn(n,e,t){return n.client.postBytes("/v1/functions/invoke",e,t?.signal)}async function et(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 nt(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 tt(n,e,t,r){let o=`/v1/settings/${s(e)}/${s(t)}`;return n.client.get(o,r?.signal)}async function rt(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 ot(n,e,t,r){let o=`/v1/inventory/${s(e)}/${s(t)}/progressions`;return n.client.get(o,r?.signal)}async function at(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 st(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 it(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 lt(n,e){return n.client.get("/v1/game-room-templates",e?.signal)}async function dt(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 ut(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 ct(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 mt(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 gt(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 yt(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 ft(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 ht(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 _t(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 bt(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 Rt(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 vt(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 me="gem_";function ge(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 wt=1e4,kt=50,At=1e3,Ot=65536-4*1024,pe=n=>typeof n=="number"?n:0,Pt=n=>typeof n=="string"?n:"";function ye(){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 Gt(n){return n?.retryable===true}function Tt(n,e){let t=n??{},r=Array.isArray(t.rejected)?t.rejected.map(o=>{let a=o??{};return {index:pe(a.index),code:Pt(a.code)}}):[];return {accepted:pe(t.accepted),rejected:r,dropped:e,duplicate:t.duplicate===true}}function fe(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 he(n){let e=Math.max(1,Math.floor(n.maxQueue??At)),t={client:n.client,gameId:()=>n.gameId},r=[],o=0,a=null,i=false,l=null,u=0,c=0,p=false,_=false,R=v=>{n.log?.(v);},h=()=>{a!==null&&(n.clock.clearTimeout(a),a=null);},y=()=>Math.max(0,c-n.clock.now()),w=()=>{a!==null||i||l!==null||(a=n.clock.setTimeout(()=>{a=null,P().catch(()=>{});},Math.max(wt,y())));},A=()=>{let v=Math.min(r.length,100),S=128;for(let G=0;G<v;G+=1){let T=r[G];if(T===void 0)break;if(S+=JSON.stringify(fe(T,0)).length+1,S>Ot)return Math.max(1,G)}return v};async function P(v){for(;l!==null;)await l.catch(()=>{});if(r.length===0)return {accepted:0,rejected:[],dropped:0,duplicate:false};let S=Ce(v);l=S;try{return await S}finally{l===S&&(l=null),r.length>0&&w();}}async function Ce(v){h();let S=r.splice(0,A()),G=o;o=0;let T=Math.round(n.clock.now()),F={batch_id:ye(),sent_at_ms:T,events:S.map(k=>fe(k,T))};try{let k=await Y(t,F,v===void 0?void 0:{signal:v}),C=Tt(k,G);u=0,c=0;for(let Ie of C.rejected)R(`[gem] analytics: an event was refused (${Ie.code}). See the analytics_events section of your game config.`);return C}catch(k){if(Gt(k)){for(r=[...S,...r],o+=G;r.length>e;)r.shift(),o+=1;u+=1,c=n.clock.now()+ge(u,k);}else R(`[gem] analytics: ${S.length} event(s) were discarded \u2014 the platform refused the batch and will refuse it again: ${String(k)}`);throw k}}return {track(v,S,G={}){if(i)return;if(typeof v!="string"||v===""){_||(_=true,R(`[gem] analytics: '${S}' 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(S.startsWith(me)){p||(p=true,R(`[gem] analytics: '${S}' 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={},F={};for(let[k,C]of Object.entries(G))typeof C=="string"?T[k]=C:typeof C=="number"&&Number.isFinite(C)&&(F[k]=C);for(;r.length>=e;)r.shift(),o+=1;r.push({uid:ye(),playerId:v,name:S,atMs:n.clock.now(),dimensions:T,measures:F}),r.length>=kt&&l===null&&y()===0?P().catch(()=>{}):w();},flush:v=>P(v),get pending(){return r.length},dispose(){i=true,h(),r=[],o=0;}}}var Ct=new Map([["function_error",false],["function_failed",false],["function_timeout",false],["function_not_published",false],["function_input_too_large",false],["functions_not_configured",false],["forbidden",false],["function_capacity_unavailable",true],["function_host_unreachable",true],["function_host_error",true],["rate_limited",true],["service_unavailable",true]]),j=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:Ct.get(this.code))??super.retryable}},M=class{#e;constructor(e){this.#e=e;}async invoke(e,t={}){let r=It(e),o;try{o=await this.#e(r,t.signal===void 0?{}:{signal:t.signal});}catch(a){throw a instanceof g?Lt(a):a}return Et(o)}};function It(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 f(`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 f(`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 Et(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 Lt(n){let{details:e,invocationId:t}=re(n),o=e?.untrusted?.message,a=e?.reason;return new j(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 O=n=>typeof n=="string"?n:"",qt=/(?:Z|[+-]\d{2}:?\d{2})$/i;function _e(n){let e=O(n);if(!qt.test(e))return 0;let t=Date.parse(e);return Number.isFinite(t)?Math.floor(t/1e3):0}var Mt=/^[0-9a-f]{1,64}$/,$t=/^[0-9a-f]{16}$/,jt=/^[A-Za-z][A-Za-z0-9_+\-/]{0,63}$/,Bt=/^(?:[01]\d|2[0-3]):[0-5]\d$/;function Ft(n){let e=O(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 Ut=4096,Nt=new TextEncoder;function Dt(n){let e=O(n.challenge_data),t=O(n.challenge_data_hash);return e===""||!$t.test(t)?{}:Nt.encode(e).length>Ut?{}:{data:e,dataHash:t}}function Ht(n){let e=n??{},t=_e(e.period_start_at),r=_e(e.period_ends_at);if(t===0||r===0)return;let o=O(e.slug),a=O(e.seed),i=Ft(e.period_local_date),l=O(e.boundary),u=O(e.reset_time);return {id:O(e.progression_definition_id),...o===""?{}:{slug:o},window:O(e.window),periodStartAt:t,periodEndsAt:r,...i===void 0?{}:{periodLocalDate:i},boundary:jt.test(l)?l:"",resetTime:Bt.test(u)?u:"",seed:Mt.test(a)?a:"",...Dt(e)}}function be(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 Re(n){let e=n??{};return Array.isArray(e.challenges)?e.challenges.map(Ht).filter(t=>t!==void 0):[]}function ve(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().");be(r);let a=await n({player_id:t,...r===void 0?{}:{periods_back:r},...o===void 0?{}:{signal:o}});return Re(a)}}}function Vt(n){let e={};for(let[t,r]of Object.entries(J))if(typeof r=="function"){let o=r;e[t]=(...a)=>o(n,...a);}return e}function V(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=K(n,{clock:t,...e.onAuthStateChange===void 0?{}:{onStateChange:e.onAuthStateChange}}),a=oe({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=Vt({client:i,gameId:()=>l.gameId}),c=l.gameRoomId,p=n.endMatch,_=n.log,R=he({client:i,clock:t,gameId:l.gameId,...typeof _=="function"?{log:y=>_.call(n,y)}:{}});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(y,w)=>{let A=await u.setMatchBackfill(l.matchId,{open:y.open,...y.seats===void 0?{}:{seats:y.seats}},w===void 0?{}:{signal:w});return {open:A.open,seats:A.seats??null}},reportPlayers:async(y,w)=>(await u.reportMatchPlayers(l.matchId,{players:y.map(P=>({player_id:P.playerId,state:P.state}))},w===void 0?{}:{signal:w})).players.map(P=>({playerId:P.player_id,outcome:P.outcome}))},analytics:R,functions:new M(u.invokeFunction),challenges:ve(u.listChallenges),...c===void 0?{}:{room:{get:y=>u.getGameRoomV2(c,y),args:async y=>{let w=await u.getGameRoomV2(c,y?.signal===void 0?{}:{signal:y.signal}),A=w.modified?w.body:void 0;if(A?.room_args==null||A.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:A.room_args,room_args_template:A.room_args_template}}}},dispose:()=>{R.dispose(),o.dispose();}}}var Wt=["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"],zt=new Set(Wt);function Se(n){return typeof n=="string"&&zt.has(n)?n:"unknown"}var ke="[gem: use gem.text.toPlain()]",xe=new Set,we;function Kt(n){try{if(xe.has(n))return;let e=globalThis.location;if(we??=!!e?.port&&ue(e.hostname??""),!we)return;xe.add(n),console.warn(`[gem] ${n} is PlayerText, turned into a string: players see ${ke}. Render text.toPlain(value) (text is in @indiegems/gem-web-sdk/sdk).
1
+ var Ee=Object.defineProperty;var Le=(n,e)=>{for(var t in e)Ee(n,t,{get:e[t],enumerable:true});};globalThis.__gemWebSdkVersion="[gem-web-sdk:sdkVersion:16.1.0]";var qe={initialDelayMs:2e3,maxDelayMs:6e4};function Me(n,e){return e!==void 0?!e:n==="chain_exhausted"}var U=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}=qe,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=$e(o),{retryable:i,retryAfterMs:l}=o??{};throw t===this.generation&&(Me(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 $e(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 f=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}},N=["if-match","if-none-match"],Q=4096;function je(n){if(!n)return;let e={};for(let[t,r]of Object.entries(n)){let o=t.toLowerCase();if(!N.includes(o)||r===void 0)continue;let a=typeof r=="string"?Be(r):r;if(typeof a!="string"||a.length>Q||!Fe(a))throw new f(`the ${o} header value cannot be sent \u2014 it is not a string, is longer than ${Q} 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 Be(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 Fe(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 Ue(n){let{bytes:e}=n;if(e!==void 0){if(Object.prototype.toString.call(e)!=="[object Uint8Array]")throw new f("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 f("the request carries both a JSON body and a raw body, and only one can be sent. This is a malformed request, not a server failure.");return new Uint8Array(e)}}function Z(n,e){let t=e.replayUnauthorizedOnce??true;return {async request(r){let o={...r},a=je(o.headers),i=Ue(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(),_=await n(l,p);if(_.status===401)throw e.tokenSource.close("unavailable"),new b("unavailable","the server refused a freshly minted token");return _}}}function ee(n){let e=typeof n=="string"?new TextEncoder().encode(n):n;return btoa(Ne(e))}function Ne(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"}},te=new WeakMap;function re(n){return te.get(n)??{}}var De=new Set([408,429,500,502,503,504]),He=6e4;function Ve(n){if(n===void 0)return 2;if(!Number.isInteger(n)||n<0||n>10)throw new f(`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:We(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?Ve(this.options.maxRetries)+1:1,a=null;if(e.signal?.aborted)throw ne(e.signal);for(let i=0;i<o;i++){if(i>0&&await this.backoff(i,a,e.signal),e.signal?.aborted)throw ne(e.signal);let l;try{l=await this.options.transport.request(e);}catch(c){if(b.isAuthError(c)||f.isRefusal(c)||e.signal?.aborted||ze(c))throw c;a=new g("unavailable",0,String(c));continue}if(l.status>=200&&l.status<300||l.status===304)return l;let u=Ke(l);if(!De.has(l.status)||l.status===429&&!r)throw u;a=u;}throw a??new g("unavailable",0,"no attempt was made")}backoff(e,t,r){if(r?.aborted)return Promise.resolve();let o=t?.retryAfterSeconds,a=o!==void 0?o*1e3:2**(e-1)*250,i=2**(e-1)*250,l=Math.min(Math.max(a,i),He);return new Promise(u=>{let c=this.options.clock,p=false,_=false,R,h=()=>{p||(p=true,_&&c.clearTimeout(R),r?.removeEventListener("abort",h),u());};r?.addEventListener("abort",h,{once:true}),R=c.setTimeout(h,l),_=true,p&&c.clearTimeout(R);})}};function We(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 ne(n){return n.reason!==void 0?n.reason:new DOMException("The operation was aborted.","AbortError")}function ze(n){let e=n?.name;return e==="AbortError"||e==="TimeoutError"}function Ke(n){let e=Je(n),t=Qe(n.body),r={...t===void 0?{}:{details:t},...n.invocationId===void 0?{}:{invocationId:n.invocationId}};return Object.keys(r).length>0&&te.set(e,r),e}var Ye=new Map([["insufficient_funds","insufficient_funds"]]);function Je(n){let{status:e,body:t}=n,r=Xe(t),o=n.retryAfterSeconds??en(t),a=Ze(t),i=a===void 0?void 0:Ye.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 Xe(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 Qe(n){let t=n?.error?.details;return t===null?void 0:t}function Ze(n){let t=n?.error?.code;return typeof t=="string"&&t.length>0?t:void 0}function en(n){let e=n?.retryAfterSeconds;return typeof e=="number"&&Number.isFinite(e)&&e>=0?e:void 0}function nn(n){let e=n.lastIndexOf("@");return (e===-1?n:`***@${n.slice(e+1)}`).slice(0,200)}var tn=new Set(N);function rn(n){if(!n)return {};let e={};for(let[t,r]of Object.entries(n))tn.has(t.toLowerCase())&&(e[t.toLowerCase()]=r);return e}function oe(n){let e=n.fetch??globalThis.fetch.bind(globalThis);return Z(async(t,r)=>{let o;try{o=new URL(n.baseUrl.replace(/\/+$/,""));}catch{throw new f("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 f(`${JSON.stringify(typeof t.path=="string"?nn(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 f(`${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 h=o.username!==""||o.password!=="",y=a.username!==o.username||a.password!==o.password,w=h?y?"baseUrl (and possibly the request path)":"baseUrl":"request path";throw new f(`the ${w} 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[h,y]of Object.entries(n.defaultQuery??{}))a.searchParams.has(h)||a.searchParams.set(h,y);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(h){throw new f(`the body of ${t.method} ${JSON.stringify(a.pathname)} could not be serialised to JSON: ${String(h)}. 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},...rn(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 h=await u.text();if(h.length>0)try{c=JSON.parse(h);}catch{c=h;}}let p=u.headers.get("etag"),_=on(u.headers.get("retry-after")),R=u.headers.get("x-gem-invocation-id");return {status:u.status,body:c,...p===null?{}:{etag:p},..._===void 0?{}:{retryAfterSeconds:_},...R===null||R===""?{}:{invocationId:R}}},n)}function on(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 an="gem-web-bridge";var sn=65536,ae=8,D=5e3,se=1024;var H=Object.create(null);var ie=Object.create(null);function ln(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 dn(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 un(n){return /^[a-z]{2,8}(-[a-z0-9]{1,8})*$/i.test(n)}function cn(n){return /^[a-z_]+$/.test(n)}function mn(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 W(n,e,t){if(e>ae)return `nesting deeper than ${ae}`;if(++t.nodes>D)return `more than ${D} 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>se)return `an array of ${n.length} entries, over the ${se} limit`;t.bytes+=2;for(let l of n){let u=W(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>D)return `more than ${D} values`;if(t.bytes+=l.length*3+4,t.bytes>t.cap)return `over the ${t.cap} byte limit`;let u=W(i[l],e+1,t);if(u)return u}return null}function gn(n,e=sn){let t={nodes:0,bytes:0,seen:new Set,cap:e},r=W(n,0,t);return r?`message contains ${r}`:t.bytes>e?`message is over the ${e} byte limit`:null}var pn={origin:[ln,"not a well-formed origin"],url:[dn,"not a safe absolute http(s) URL"],bcp47:[un,"not a well-formed BCP 47 tag"],code:[cn,"not a code of lower-case letters and underscores"],gameRef:[mn,"not a game id or web address"]};function le(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=z(a,r,o);if(i)return i}return null}function z(n,e,t){let r=e[1].toLowerCase();switch(r){case "u":return typeof n=="boolean"?null:z(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`:le(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=z(i,o,a);if(l)return l}return null}default:return `${t}: unknown kind ${String(r)}`}}var de=Object.create(null);function d(n,e,t,r,o){return H[n]=t,r&&(ie[n]=r),de[n]=a=>{let i=gn(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!==an?"gem: wrong protocol marker":l.type!==n?`type: expected ${n}`:le(l,e,"")}}var m=["requestId","s",64],I=["outcome","e",["ok","declined","unavailable"]],E=["reason","S",64,"code"];d("gem.handshake",[["versions","o",[["min","i",1,1e3],["max","i",1,1e3]]],["capabilities","A",64,["","s",64]],["embedder","s",2048,"origin"],["unbidden","B"]],30);d("gem.handshake.accept",[["v","i",1,1e3],["capabilities","A",64,["","s",64]]],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],["currencySlug","s",32],["multiplierBp","i",1e4,1e6]]]],["expiresInDays","I",1,7]]]],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"]]]],60);d("gem.cohorts",[["cohorts","a",8,["","o",[["experimentId","s",36],["variantKey","s",32]]]]],12,"cohorts");d("gem.earnAllowanceChanged",[],30,"earnAllowance");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"]],["matchId","s",64],["data","j"]],1800,"p2p");d("gem.dedicatedEvent",[["event","e",["answer","error","matchEnded"]],["matchId","s",64],["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,["","s",64]]],12,"clusterTarget");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"]],["matchId","s",64],["data","j"]],1200,"p2p");d("gem.dedicatedOffer",[["matchId","s",64],["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",[["currencySlug","s",32],["expected","I",1,1e9],["origin","O",[["x","i",0,16384],["y","i",0,16384]]]],60,"rewardCue");d("gem.walletDisplay",[["visible","b"],["currencies","A",8,["","s",64]],["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.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",[["params","a",16,["","o",[["key","s",64],["value","s",512]]]]],6,"share");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],["currencySlug","s",32],["quantity","I",1,10],["catalogId","S",64]],12,"purchases");d("gem.requestAvatar3dPurchase",[m,["itemId","s",64],["currencySlug","s",32]],12,"avatar3dPurchases");d("gem.purchaseResult",[m,I,E,["purchaseId","S",64]],30,"purchases");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.requestAppLinks",[m],12,"appLinks");d("gem.appLinksResult",[m,I,E,["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,I,E],30,"appLinks");d("gem.requestOpenGame",[m,["ref","s",40,"gameRef"]],6,"openGame");d("gem.openGameResult",[m,I,E],30,"openGame");d("gem.requestSimilarGames",[m,["limit","I",1,24]],12,"openGame");d("gem.similarGamesResult",[m,I,E,["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,I,E,["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]]]]]]],30,"store",262144);d("gem.requestStorePurchase",[m,["skuId","s",64]],12,"store");d("gem.storePurchaseResult",[m,I,E],30,"store");d("gem.storePurchaseSettled",[["skuId","s",64]],30,"store");Object.freeze(de);H.__malformed=60;Object.freeze(H);Object.freeze(ie);var q={now:()=>Date.now(),setTimeout:(n,e)=>setTimeout(n,e),clearTimeout:n=>clearTimeout(n)};function ue(n){let e=n.toLowerCase();return e==="localhost"||e.endsWith(".localhost")||e==="[::1]"||e==="::1"?true:/^127(\.\d{1,3}){3}$/.test(e)}var yn=1e4;function ce(n,e){return K(n,e)}function K(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 U({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??yn);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 J={};Le(J,{acceptTransfer:()=>fn,addEntityProgression:()=>hn,adminAction:()=>_n,cancelInventoryTransfer:()=>bn,claimEntityProgressionRewards:()=>Rn,closeGameRoom:()=>vn,createEntityBatchOrder:()=>Sn,createEntityOrder:()=>xn,createSession:()=>wn,deleteEntityGameSetting:()=>kn,deleteEntitySave:()=>An,deleteSession:()=>On,deleteShowcaseValue:()=>Pn,executeEntityRecipe:()=>Gn,finalizeSaveUpload:()=>Tn,getChannelAssignment:()=>Cn,getDropRates:()=>In,getEntityCurrency:()=>En,getEntityGameSetting:()=>Ln,getEntityInventory:()=>qn,getEntityInventoryItem:()=>Mn,getEntityLeaderboard:()=>$n,getEntityOrder:()=>jn,getEntityProgression:()=>Bn,getEntityRecipeAvailability:()=>Fn,getEntityRecipeUsage:()=>Un,getEntitySave:()=>Nn,getEvent:()=>Dn,getGameRoomV2:()=>Hn,getLeaderboard:()=>Vn,getPlayerGameProfile:()=>Wn,getPurchaseCatalog:()=>zn,getResolvedTemplate:()=>Kn,getRoomArgs:()=>Yn,getShowcaseValue:()=>Jn,getTransferDetails:()=>Xn,ingestAnalyticsEvents:()=>Y,initiateInventoryTransfer:()=>Qn,invokeFunction:()=>Zn,kickPlayer:()=>et,listChallenges:()=>nt,listEntityGameSettings:()=>tt,listEntityOrders:()=>rt,listEntityProgressions:()=>ot,listEntitySaves:()=>at,listEvents:()=>st,listGameRooms:()=>it,listResolvedTemplates:()=>lt,listTransfers:()=>dt,maxEntityProgression:()=>ut,putEntityGameSetting:()=>ct,putRoomArgs:()=>mt,putShowcaseValue:()=>gt,rejectTransfer:()=>pt,reportMatchPlayers:()=>yt,requestSaveUploadUrl:()=>ft,resetEntityProgression:()=>ht,setMatchBackfill:()=>_t,simulateEntityOrder:()=>bt,transferHostV2:()=>Rt,updateGameRoomV2:()=>vt});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 fn(n,e,t){let r=`/v1/inventory/transfers/${s(e)}/accept`;return n.client.post(r,void 0,t?.signal)}async function hn(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 _n(n,e,t,r){let o=`/v1/voice/sessions/${s(e)}/admin`;return n.client.post(o,t,r?.signal)}async function bn(n,e,t){let r=`/v1/inventory/transfers/${s(e)}/cancel`;return n.client.post(r,void 0,t?.signal)}async function Rn(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 vn(n,e,t){let r=`/v1/games/${s(n.gameId())}/game-rooms/${s(e)}`;return n.client.delete(r,t?.signal)}async function Sn(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 xn(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 wn(n,e,t){return n.client.post("/v1/voice/sessions",e,t?.signal)}async function kn(n,e,t,r,o){let a=`/v1/settings/${s(e)}/${s(t)}/${s(r)}`;return n.client.delete(a,o?.signal)}async function An(n,e,t,r,o){let a=`/v1/saves/${s(e)}/${s(t)}/${s(r)}`;return n.client.delete(a,o?.signal)}async function On(n,e,t){let r=`/v1/voice/sessions/${s(e)}`;return n.client.delete(r,t?.signal)}async function Pn(n,e,t,r){let o=`/v1/showcase/players/${s(e)}/${s(t)}`;return n.client.delete(o,r?.signal)}async function Gn(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 Tn(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 Cn(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 In(n,e,t){let r=`/v1/inventory/loot-tables/${s(e)}/drop-rates`;return n.client.get(r,t?.signal)}async function En(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 Ln(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 qn(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 Mn(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 $n(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 jn(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 Bn(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 Fn(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 Un(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 Nn(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 Dn(n,e,t){let r=`/v1/events/${s(e)}`;return n.client.get(r,t?.signal)}async function Hn(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 Vn(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 Wn(n,e,t){let r=`/v1/profiles/players/${s(e)}`;return n.client.get(r,t?.signal)}async function zn(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 Kn(n,e,t){let r=`/v1/game-room-templates/${s(e)}`;return n.client.get(r,t?.signal)}async function Yn(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 Jn(n,e,t,r){let o=`/v1/showcase/players/${s(e)}/${s(t)}`;return n.client.get(o,r?.signal)}async function Xn(n,e,t){let r=`/v1/inventory/transfers/${s(e)}`;return n.client.get(r,t?.signal)}async function Y(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 Qn(n,e,t){return n.client.post("/v1/inventory/transfers",e,t?.signal)}async function Zn(n,e,t){return n.client.postBytes("/v1/functions/invoke",e,t?.signal)}async function et(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 nt(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 tt(n,e,t,r){let o=`/v1/settings/${s(e)}/${s(t)}`;return n.client.get(o,r?.signal)}async function rt(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 ot(n,e,t,r){let o=`/v1/inventory/${s(e)}/${s(t)}/progressions`;return n.client.get(o,r?.signal)}async function at(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 st(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 it(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 lt(n,e){return n.client.get("/v1/game-room-templates",e?.signal)}async function dt(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 ut(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 ct(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 mt(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 gt(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 yt(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 ft(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 ht(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 _t(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 bt(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 Rt(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 vt(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 me="gem_";function ge(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 wt=1e4,kt=50,At=1e3,Ot=65536-4*1024,pe=n=>typeof n=="number"?n:0,Pt=n=>typeof n=="string"?n:"";function ye(){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 Gt(n){return n?.retryable===true}function Tt(n,e){let t=n??{},r=Array.isArray(t.rejected)?t.rejected.map(o=>{let a=o??{};return {index:pe(a.index),code:Pt(a.code)}}):[];return {accepted:pe(t.accepted),rejected:r,dropped:e,duplicate:t.duplicate===true}}function fe(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 he(n){let e=Math.max(1,Math.floor(n.maxQueue??At)),t={client:n.client,gameId:()=>n.gameId},r=[],o=0,a=null,i=false,l=null,u=0,c=0,p=false,_=false,R=v=>{n.log?.(v);},h=()=>{a!==null&&(n.clock.clearTimeout(a),a=null);},y=()=>Math.max(0,c-n.clock.now()),w=()=>{a!==null||i||l!==null||(a=n.clock.setTimeout(()=>{a=null,P().catch(()=>{});},Math.max(wt,y())));},A=()=>{let v=Math.min(r.length,100),S=128;for(let G=0;G<v;G+=1){let T=r[G];if(T===void 0)break;if(S+=JSON.stringify(fe(T,0)).length+1,S>Ot)return Math.max(1,G)}return v};async function P(v){for(;l!==null;)await l.catch(()=>{});if(r.length===0)return {accepted:0,rejected:[],dropped:0,duplicate:false};let S=Ce(v);l=S;try{return await S}finally{l===S&&(l=null),r.length>0&&w();}}async function Ce(v){h();let S=r.splice(0,A()),G=o;o=0;let T=Math.round(n.clock.now()),F={batch_id:ye(),sent_at_ms:T,events:S.map(k=>fe(k,T))};try{let k=await Y(t,F,v===void 0?void 0:{signal:v}),C=Tt(k,G);u=0,c=0;for(let Ie of C.rejected)R(`[gem] analytics: an event was refused (${Ie.code}). See the analytics_events section of your game config.`);return C}catch(k){if(Gt(k)){for(r=[...S,...r],o+=G;r.length>e;)r.shift(),o+=1;u+=1,c=n.clock.now()+ge(u,k);}else R(`[gem] analytics: ${S.length} event(s) were discarded \u2014 the platform refused the batch and will refuse it again: ${String(k)}`);throw k}}return {track(v,S,G={}){if(i)return;if(typeof v!="string"||v===""){_||(_=true,R(`[gem] analytics: '${S}' 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(S.startsWith(me)){p||(p=true,R(`[gem] analytics: '${S}' 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={},F={};for(let[k,C]of Object.entries(G))typeof C=="string"?T[k]=C:typeof C=="number"&&Number.isFinite(C)&&(F[k]=C);for(;r.length>=e;)r.shift(),o+=1;r.push({uid:ye(),playerId:v,name:S,atMs:n.clock.now(),dimensions:T,measures:F}),r.length>=kt&&l===null&&y()===0?P().catch(()=>{}):w();},flush:v=>P(v),get pending(){return r.length},dispose(){i=true,h(),r=[],o=0;}}}var Ct=new Map([["function_error",false],["function_failed",false],["function_timeout",false],["function_not_published",false],["function_input_too_large",false],["functions_not_configured",false],["forbidden",false],["function_capacity_unavailable",true],["function_host_unreachable",true],["function_host_error",true],["rate_limited",true],["service_unavailable",true]]),j=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:Ct.get(this.code))??super.retryable}},M=class{#e;constructor(e){this.#e=e;}async invoke(e,t={}){let r=It(e),o;try{o=await this.#e(r,t.signal===void 0?{}:{signal:t.signal});}catch(a){throw a instanceof g?Lt(a):a}return Et(o)}};function It(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 f(`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 f(`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 Et(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 Lt(n){let{details:e,invocationId:t}=re(n),o=e?.untrusted?.message,a=e?.reason;return new j(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 O=n=>typeof n=="string"?n:"",qt=/(?:Z|[+-]\d{2}:?\d{2})$/i;function _e(n){let e=O(n);if(!qt.test(e))return 0;let t=Date.parse(e);return Number.isFinite(t)?Math.floor(t/1e3):0}var Mt=/^[0-9a-f]{1,64}$/,$t=/^[0-9a-f]{16}$/,jt=/^[A-Za-z][A-Za-z0-9_+\-/]{0,63}$/,Bt=/^(?:[01]\d|2[0-3]):[0-5]\d$/;function Ft(n){let e=O(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 Ut=4096,Nt=new TextEncoder;function Dt(n){let e=O(n.challenge_data),t=O(n.challenge_data_hash);return e===""||!$t.test(t)?{}:Nt.encode(e).length>Ut?{}:{data:e,dataHash:t}}function Ht(n){let e=n??{},t=_e(e.period_start_at),r=_e(e.period_ends_at);if(t===0||r===0)return;let o=O(e.slug),a=O(e.seed),i=Ft(e.period_local_date),l=O(e.boundary),u=O(e.reset_time);return {id:O(e.progression_definition_id),...o===""?{}:{slug:o},window:O(e.window),periodStartAt:t,periodEndsAt:r,...i===void 0?{}:{periodLocalDate:i},boundary:jt.test(l)?l:"",resetTime:Bt.test(u)?u:"",seed:Mt.test(a)?a:"",...Dt(e)}}function be(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 Re(n){let e=n??{};return Array.isArray(e.challenges)?e.challenges.map(Ht).filter(t=>t!==void 0):[]}function ve(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().");be(r);let a=await n({player_id:t,...r===void 0?{}:{periods_back:r},...o===void 0?{}:{signal:o}});return Re(a)}}}function Vt(n){let e={};for(let[t,r]of Object.entries(J))if(typeof r=="function"){let o=r;e[t]=(...a)=>o(n,...a);}return e}function V(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=K(n,{clock:t,...e.onAuthStateChange===void 0?{}:{onStateChange:e.onAuthStateChange}}),a=oe({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=Vt({client:i,gameId:()=>l.gameId}),c=l.gameRoomId,p=n.endMatch,_=n.log,R=he({client:i,clock:t,gameId:l.gameId,...typeof _=="function"?{log:y=>_.call(n,y)}:{}});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(y,w)=>{let A=await u.setMatchBackfill(l.matchId,{open:y.open,...y.seats===void 0?{}:{seats:y.seats}},w===void 0?{}:{signal:w});return {open:A.open,seats:A.seats??null}},reportPlayers:async(y,w)=>(await u.reportMatchPlayers(l.matchId,{players:y.map(P=>({player_id:P.playerId,state:P.state}))},w===void 0?{}:{signal:w})).players.map(P=>({playerId:P.player_id,outcome:P.outcome}))},analytics:R,functions:new M(u.invokeFunction),challenges:ve(u.listChallenges),...c===void 0?{}:{room:{get:y=>u.getGameRoomV2(c,y),args:async y=>{let w=await u.getGameRoomV2(c,y?.signal===void 0?{}:{signal:y.signal}),A=w.modified?w.body:void 0;if(A?.room_args==null||A.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:A.room_args,room_args_template:A.room_args_template}}}},dispose:()=>{R.dispose(),o.dispose();}}}var Wt=["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"],zt=new Set(Wt);function Se(n){return typeof n=="string"&&zt.has(n)?n:"unknown"}var ke="[gem: use gem.text.toPlain()]",xe=new Set,we;function Kt(n){try{if(xe.has(n))return;let e=globalThis.location;if(we??=!!e?.port&&ue(e.hostname??""),!we)return;xe.add(n),console.warn(`[gem] ${n} is PlayerText, turned into a string: players see ${ke}. Render text.toPlain(value) (text is in @indiegems/gem-web-sdk/sdk).
2
2
  ${new Error().stack}`);}catch{}}var x=class{#e;#n;constructor(e,t="player text"){this.#e=e,this.#n=t,Object.freeze(this);}toString(){return Kt(this.#n),ke}toJSON(){return this.toString()}get[Symbol.toStringTag](){return "PlayerText"}static unwrap(e){return e.#e}};function B(n,e){return new x(n,e)}var Ae={toPlain(n){return x.unwrap(n)},compare(n,e,t){let r=n instanceof x?x.unwrap(n):n,o=e instanceof x?x.unwrap(e):e;if(typeof Intl>"u"||typeof Intl.Collator!="function")return r<o?-1:r>o?1:0;let a;try{a=new Intl.Collator(t);}catch{a=new Intl.Collator;}return a.compare(r,o)},equals(n,e){let t=n instanceof x?x.unwrap(n):n,r=e instanceof x?x.unwrap(e):e;return t.normalize("NFC")===r.normalize("NFC")}};var Oe="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 X(n,e={}){let t=e.clock??q,r=()=>{let l=n();if(l===null)throw new Error(Oe);return l},o=null,a=()=>{if(o===null)throw new Error(Oe);return o};return {server:{get identity(){return a().identity},get client(){return a().client},get api(){return a().api},get match(){return a().match},get analytics(){return a().analytics},get functions(){return a().functions},get challenges(){return a().challenges},get room(){return a().room},dispose(){o?.dispose();},get sizeClass(){return r().sizeClass},get roomArgs(){return r().roomArgs},get roster(){return r().roster},players(){return r().players()},profile(l){let c=r().profile?.(l);if(!c)return null;let p=c.displayName;return typeof p!="string"||p===""?null:{displayName:B(p,"profile.displayName"),...typeof c.displayTag=="string"&&c.displayTag!==""?{displayTag:B(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=V(r(),{...e,clock:t});}}}function Pe(n,e={}){let{server:t,attach:r}=X(()=>n,e);return r(),t}function Yt(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:Se(e)}}}var Jt=1e4;function Xt(n){let e=false;return t=>{if(e)return;let r;try{r=n.match.reportPlayers([{playerId:t,state:"connected"}],AbortSignal.timeout(Jt));}catch{return}r.catch(o=>{o instanceof g&&o.status>=400&&o.status<500&&(e=o.status!==429);});}}function Ge(n,e={}){return ()=>{let t=null,{server:r,attach:o}=X(()=>t,e),a=n(r),i={async init(u){t=u,o(),await a.init?.();},async shutdown(u){let c=Yt(u);try{await a.shutdown?.(c);}finally{r.dispose();}}},l=Xt(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,_)=>a.message?.(u,c,p,_)),i}}var Qt=new Set(["unlocked","already_unlocked","suppressed"]);function Te(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"||!Qt.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,N as CONDITIONAL_HEADERS,M as FunctionsApi,g as GemApiError,L as GemClient,j as GemFunctionError,x as PlayerText,f as TransportRefusal,Te as achievementReceipts,B as asPlayerText,V as createGemServer,ce as createHostTokenSource,Pe as createMatchServer,Ge as defineServer,q as systemClock,Ae as text,ee as toBase64};//# sourceMappingURL=gem-web-sdk.server.js.map
3
3
  //# sourceMappingURL=gem-web-sdk.server.js.map
package/dist/index.d.ts CHANGED
@@ -590,6 +590,7 @@ interface GemSignalMoment {
590
590
  readonly requestId: string;
591
591
  readonly kind: "level_end" | "run_end" | "match_end" | "menu_return" | "other_break";
592
592
  readonly placement?: string;
593
+ readonly wall?: boolean;
593
594
  }
594
595
  interface GemMomentResult {
595
596
  readonly gem: typeof PROTOCOL;
@@ -1419,7 +1420,7 @@ declare class GemFrame {
1419
1420
  requestAvatar3dPurchase(requestId: string, itemId: string, currencySlug: string): boolean;
1420
1421
  putDeviceSettings(requestId: string, settings: Readonly<Record<string, unknown>>): boolean;
1421
1422
  requestAd(requestId: string, placement: string, format: "interstitial" | "rewarded"): boolean;
1422
- signalMoment(requestId: string, kind: string, placement?: string): boolean;
1423
+ signalMoment(requestId: string, kind: string, placement?: string, wall?: boolean): boolean;
1423
1424
  readyCalled(): boolean;
1424
1425
  requestSignIn(requestId: string): boolean;
1425
1426
  requestFriendChallenge(requestId: string, playerId: string, template: string, params?: Readonly<Record<string, string | number>>): boolean;
package/dist/sdk.d.ts CHANGED
@@ -4750,7 +4750,7 @@ declare class GemFrame {
4750
4750
  requestAvatar3dPurchase(requestId: string, itemId: string, currencySlug: string): boolean;
4751
4751
  putDeviceSettings(requestId: string, settings: Readonly<Record<string, unknown>>): boolean;
4752
4752
  requestAd(requestId: string, placement: string, format: "interstitial" | "rewarded"): boolean;
4753
- signalMoment(requestId: string, kind: string, placement?: string): boolean;
4753
+ signalMoment(requestId: string, kind: string, placement?: string, wall?: boolean): boolean;
4754
4754
  readyCalled(): boolean;
4755
4755
  requestSignIn(requestId: string): boolean;
4756
4756
  requestFriendChallenge(requestId: string, playerId: string, template: string, params?: Readonly<Record<string, string | number>>): boolean;
@@ -4937,6 +4937,7 @@ type MomentKind = "level_end" | "run_end" | "match_end" | "menu_return" | "other
4937
4937
  interface MomentSignal {
4938
4938
  kind: MomentKind;
4939
4939
  placement?: string;
4940
+ wall?: boolean;
4940
4941
  }
4941
4942
  interface MomentResult {
4942
4943
  readonly shown: boolean;
@@ -1,6 +1,6 @@
1
1
  # The function surface — API reference
2
2
 
3
- Generated from `@indiegems/gem-web-sdk/function` v16.0.0, the version of the package this file ships in. Every symbol below carries an explicit anchor, its `anchor` in `reference.json` beside this file.
3
+ Generated from `@indiegems/gem-web-sdk/function` v16.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
 
@@ -1,6 +1,6 @@
1
1
  # The browser surface — API reference
2
2
 
3
- Generated from `@indiegems/gem-web-sdk/sdk` v16.0.0, the version of the package this file ships in. Every symbol below carries an explicit anchor, its `anchor` in `reference.json` beside this file.
3
+ Generated from `@indiegems/gem-web-sdk/sdk` v16.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
 
@@ -12771,6 +12771,22 @@ Optional: your own name for the screen the player is leaving —
12771
12771
  moment to a screen. It is never sent to the platform, never stored, never
12772
12772
  shown to a player and never sent to an ad network.
12773
12773
 
12774
+ <a id="momentsignal-wall"></a>
12775
+
12776
+ ## MomentSignal.wall
12777
+
12778
+ ```ts
12779
+ wall?: boolean
12780
+ ```
12781
+
12782
+ Optional: `true` says your game accepts that the arcade may show its **app
12783
+ wall** at this break — a panel that may leave the player no way on in this
12784
+ browser. Set it only at a break where the player's progress is already
12785
+ saved and stopping there is acceptable. Absent or `false` is an ordinary
12786
+ break. It is an acceptance, not an ask: the arcade still decides, and
12787
+ usually shows nothing. An older arcade ignores it and treats the break as
12788
+ ordinary.
12789
+
12774
12790
  <a id="momentresult"></a>
12775
12791
 
12776
12792
  ## MomentResult
@@ -12823,10 +12839,14 @@ player-opened pause menu (choosing Quit to menu from it is a
12823
12839
  `menu_return`). No press is required by the SDK; the rule is about when a
12824
12840
  break really is one.
12825
12841
 
12842
+ Add `wall: true` only at a break where the player's progress is saved and
12843
+ your game accepts that the arcade may show its app wall there.
12844
+
12826
12845
  NOTHING REJECTS. It resolves `{ shown: false }` without asking for an
12827
12846
  arcade that does not do platform moments, a `kind` or `placement` outside
12828
- the grammar, a call before `gem.frame.ready()`, a call while another is in
12829
- flight, a call within 10 seconds of the last answer, or no answer within
12847
+ the grammar, a `wall` that is not a boolean, a call before
12848
+ `gem.frame.ready()`, a call while another is in flight, a call within 10
12849
+ seconds of the last answer, or no answer within
12830
12850
  three minutes — and each of those, except an arcade that does not do it
12831
12851
  (said once a session), is reported to your `onError` handler with code
12832
12852
  `'internal'` and a message beginning with a stable token:
@@ -12841,7 +12861,7 @@ on it, and never pop your own offer at a break that settled `shown: true`.
12841
12861
 
12842
12862
  | Parameter | Type | Description |
12843
12863
  | --- | --- | --- |
12844
- | `moment` | `MomentSignal` | Which kind of break, and optionally your name for the screen. |
12864
+ | `moment` | `MomentSignal` | Which kind of break, your screen's name, and whether a wall is acceptable. |
12845
12865
 
12846
12866
  **Returns.** Whether the arcade showed anything. Always resolves; never rejects.
12847
12867
 
@@ -1,6 +1,6 @@
1
1
  # The server surface — API reference
2
2
 
3
- Generated from `@indiegems/gem-web-sdk/sdk` v16.0.0, the version of the package this file ships in. Every symbol below carries an explicit anchor, its `anchor` in `reference.json` beside this file.
3
+ Generated from `@indiegems/gem-web-sdk/sdk` v16.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": "16.0.0"
5
+ "version": "16.1.0"
6
6
  },
7
7
  "entries": [
8
8
  {
@@ -14198,6 +14198,22 @@
14198
14198
  "defaultValue": null,
14199
14199
  "guides": []
14200
14200
  },
14201
+ {
14202
+ "id": "MomentSignal.wall",
14203
+ "name": "wall",
14204
+ "anchor": "momentsignal-wall",
14205
+ "group": "moments",
14206
+ "signature": "wall?: boolean",
14207
+ "documented": true,
14208
+ "summary": "Optional: `true` says your game accepts that the arcade may show its **app\nwall** at this break — a panel that may leave the player no way on in this\nbrowser. Set it only at a break where the player's progress is already\nsaved and stopping there is acceptable. Absent or `false` is an ordinary\nbreak. It is an acceptance, not an ask: the arcade still decides, and\nusually shows nothing. An older arcade ignores it and treats the break as\nordinary.",
14209
+ "deprecated": null,
14210
+ "params": [],
14211
+ "returns": null,
14212
+ "throws": null,
14213
+ "example": null,
14214
+ "defaultValue": null,
14215
+ "guides": []
14216
+ },
14201
14217
  {
14202
14218
  "id": "MomentResult",
14203
14219
  "name": "MomentResult",
@@ -14253,14 +14269,14 @@
14253
14269
  "group": "moments",
14254
14270
  "signature": "signal(moment: MomentSignal): Promise<MomentResult>",
14255
14271
  "documented": true,
14256
- "summary": "Signal a platform moment: the player is leaving a natural break in play.\nThe arcade may show one of its own offers over your paused game, and\nusually shows nothing.\n\n**Call it from the player's press that LEAVES the break** — Next, Retry,\nBack to menu — once per break. Start your own transition in parallel, and\nstart play when this settles. **Never** mid-input, during a timed\nsequence, on a timer, on boot or the first arrival at the title, or from a\nplayer-opened pause menu (choosing Quit to menu from it is a\n`menu_return`). No press is required by the SDK; the rule is about when a\nbreak really is one.\n\nNOTHING REJECTS. It resolves `{ shown: false }` without asking for an\narcade that does not do platform moments, a `kind` or `placement` outside\nthe grammar, a call before `gem.frame.ready()`, a call while another is in\nflight, a call within 10 seconds of the last answer, or no answer within\nthree minutes — and each of those, except an arcade that does not do it\n(said once a session), is reported to your `onError` handler with code\n`'internal'` and a message beginning with a stable token:\n`moments_unsupported`, `moments_invalid_argument`, `moments_before_ready`,\n`moments_in_flight`, `moments_called_repeatedly` or `moments_timeout`.\n\nThe arcade pauses and resumes your game through the ordinary\n`gem.pause`, so you do not pause anything yourself.\n\n⚠️ `shown` grants nothing. Never hand out a reward, an unlock or a currency\non it, and never pop your own offer at a break that settled `shown: true`.",
14272
+ "summary": "Signal a platform moment: the player is leaving a natural break in play.\nThe arcade may show one of its own offers over your paused game, and\nusually shows nothing.\n\n**Call it from the player's press that LEAVES the break** — Next, Retry,\nBack to menu — once per break. Start your own transition in parallel, and\nstart play when this settles. **Never** mid-input, during a timed\nsequence, on a timer, on boot or the first arrival at the title, or from a\nplayer-opened pause menu (choosing Quit to menu from it is a\n`menu_return`). No press is required by the SDK; the rule is about when a\nbreak really is one.\n\nAdd `wall: true` only at a break where the player's progress is saved and\nyour game accepts that the arcade may show its app wall there.\n\nNOTHING REJECTS. It resolves `{ shown: false }` without asking for an\narcade that does not do platform moments, a `kind` or `placement` outside\nthe grammar, a `wall` that is not a boolean, a call before\n`gem.frame.ready()`, a call while another is in flight, a call within 10\nseconds of the last answer, or no answer within\nthree minutes — and each of those, except an arcade that does not do it\n(said once a session), is reported to your `onError` handler with code\n`'internal'` and a message beginning with a stable token:\n`moments_unsupported`, `moments_invalid_argument`, `moments_before_ready`,\n`moments_in_flight`, `moments_called_repeatedly` or `moments_timeout`.\n\nThe arcade pauses and resumes your game through the ordinary\n`gem.pause`, so you do not pause anything yourself.\n\n⚠️ `shown` grants nothing. Never hand out a reward, an unlock or a currency\non it, and never pop your own offer at a break that settled `shown: true`.",
14257
14273
  "deprecated": null,
14258
14274
  "params": [
14259
14275
  {
14260
14276
  "name": "moment",
14261
14277
  "type": "MomentSignal",
14262
14278
  "optional": false,
14263
- "summary": "Which kind of break, and optionally your name for the screen."
14279
+ "summary": "Which kind of break, your screen's name, and whether a wall is acceptable."
14264
14280
  }
14265
14281
  ],
14266
14282
  "returns": "Whether the arcade showed anything. Always resolves; never rejects.",
package/docs/changelog.md CHANGED
@@ -16,6 +16,24 @@ Its entries are grouped under up to five headings:
16
16
  - **Rebuild**: a type changed. Recompile against the new version; code that compiles today keeps compiling unless the entry says otherwise.
17
17
  - **New capability**: something a game can now do. Nothing changes unless you use it.
18
18
 
19
+ ## 16.1.0
20
+
21
+ Upgrading from 16.0.1. Impact: required.
22
+
23
+ ### Rebuild
24
+
25
+ - The signalMoment method on the frame now accepts an optional fourth parameter, wall, in the game, root and SDK entry points. Existing calls with three arguments keep working unchanged, so recompiling your game against the new types is enough.
26
+
27
+ ### New capability
28
+
29
+ - A game can now mark a platform moment with wall set to true to say it accepts that the Arcade may show its app wall at that break. Leaving it out or passing false keeps the break ordinary. An older Arcade ignores the field, so it is safe to send everywhere. Only set it where showing the wall at that break is acceptable for your game.
30
+
31
+ ## 16.0.1
32
+
33
+ Upgrading from 16.0.0. Impact: none.
34
+
35
+ Nothing in this release asks anything of a game.
36
+
19
37
  ## 16.0.0
20
38
 
21
39
  Upgrading from 15.3.3. Impact: required.
@@ -50,7 +50,7 @@ either way.
50
50
  ```jsonc
51
51
  // package.json
52
52
  "dependencies": {
53
- "@indiegems/gem-web-sdk": "16.0.0"
53
+ "@indiegems/gem-web-sdk": "16.1.0"
54
54
  }
55
55
  ```
56
56
 
@@ -43,8 +43,8 @@
43
43
  },
44
44
  {
45
45
  "file": "changelog.md",
46
- "sha256": "739709af2b5a0918ea7041f6f3d50142c3182aca892bc388dee51ad1a0f64c41",
47
- "updated": "2026-10-28T21:16:25Z"
46
+ "sha256": "085828e2eb6fdb752c8e2fd65e8110d31cdf1322e210a199f85a2e8bb17ba4d3",
47
+ "updated": "2026-10-29T18:42:12Z"
48
48
  },
49
49
  {
50
50
  "file": "daily-challenges.md",
@@ -73,8 +73,8 @@
73
73
  },
74
74
  {
75
75
  "file": "getting-started.md",
76
- "sha256": "b3c215882b2ea836e79e37553277b97914f6947e8e3bbeb10e2a2e0667d2fb86",
77
- "updated": "2026-10-28T21:16:25Z"
76
+ "sha256": "4344ccdf72a10cf7dddf2323d528240638bc88a14f742840a571ed347df5cb92",
77
+ "updated": "2026-10-29T18:42:12Z"
78
78
  },
79
79
  {
80
80
  "file": "inventory-and-catalogs.md",
@@ -98,8 +98,8 @@
98
98
  },
99
99
  {
100
100
  "file": "platform-moments.md",
101
- "sha256": "c9909452a49fe50bac2266e56e5a44ad6495b8464ce1b5c889d0be39604bbff0",
102
- "updated": "2026-10-14T22:43:26Z"
101
+ "sha256": "2d7a24af647c6820fb6d4b098ce417ca81ceaf131bf4c02a51f3e82e45631e01",
102
+ "updated": "2026-10-29T16:05:50Z"
103
103
  },
104
104
  {
105
105
  "file": "platform-rules.md",
@@ -133,8 +133,8 @@
133
133
  },
134
134
  {
135
135
  "file": "server-bundles.md",
136
- "sha256": "b4a7918f6b10b754976937f216ee8679260166a0377dcb0448fd42d65bdb2f31",
137
- "updated": "2026-10-28T21:16:25Z"
136
+ "sha256": "ec3ce51e73941a55ad4bd66daa832b85a9688f6011493c1347c51e8f0a1dbfd4",
137
+ "updated": "2026-10-29T18:42:12Z"
138
138
  },
139
139
  {
140
140
  "file": "serverless-functions-js.md",
@@ -30,6 +30,7 @@ put the call, where never to, and the few things a game gets wrong when nobody t
30
30
  - [10. Testing it in the dev host](#10-testing-it-in-the-dev-host)
31
31
  - [11. The release requirement](#11-the-release-requirement)
32
32
  - [12. Moving off `format: 'interstitial'`](#12-moving-off-format-interstitial)
33
+ - [13. A break that may be a wall: `wall: true`](#13-a-break-that-may-be-a-wall-wall-true)
33
34
 
34
35
  ## 1. A platform moment is not your own offer
35
36
 
@@ -133,7 +134,7 @@ you find the mistake while you build:
133
134
  | token | when |
134
135
  | --------------------------- | -------------------------------------------------------------------------------------------------- |
135
136
  | `moments_unsupported` | the page your game runs in does not do platform moments. Keep the call; it costs nothing. Said once a session |
136
- | `moments_invalid_argument` | a `kind` outside the five, or a `placement` outside the grammar |
137
+ | `moments_invalid_argument` | a `kind` outside the five, a `placement` outside the grammar, or a `wall` that is not a boolean |
137
138
  | `moments_before_ready` | a signal before `gem.frame.ready()` — play has not started, so there is no break |
138
139
  | `moments_in_flight` | a second signal while the first is still waiting for its answer |
139
140
  | `moments_called_repeatedly` | a signal within 10 seconds of the last moment's answer — one break signalled twice, or a timer |
@@ -264,3 +265,33 @@ await gem.moments.signal({ kind: 'level_end', placement: 'level-complete' });
264
265
 
265
266
  `format: 'rewarded'` is not deprecated and does not change: a button the player presses for a
266
267
  reward is your game's own offer, and [`rewarded-ads.md`](rewarded-ads.md) is its page.
268
+
269
+ ## 13. A break that may be a wall: `wall: true`
270
+
271
+ `wall` is optional. Set it to `true` at a break where your game **accepts that the Arcade may show
272
+ its app wall**: a panel that asks the player to carry on in the Gem Arcade app, and that may leave
273
+ them no way to keep playing in this browser.
274
+
275
+ ```js
276
+ // From the Next press, after the player's progress is saved.
277
+ await saveProgress();
278
+ await gem.moments.signal({ kind: 'level_end', placement: 'chapter-1-end', wall: true });
279
+ startNextLevel();
280
+ ```
281
+
282
+ - **Absent or `false` is an ordinary break**, exactly as before the flag existed. Leave it off
283
+ everywhere you would not want a player to stop.
284
+ - **Only where stopping is acceptable, and only after saving.** The end of a level, a chapter or a
285
+ run, once the player's progress is saved where it follows them
286
+ ([`saving-player-progress.md`](saving-player-progress.md)) — never mid-run, and never at a break
287
+ whose progress is lost if the player does not come back to this tab.
288
+ - **An acceptance, not an ask.** The Arcade still decides, on its own servers and under its own
289
+ settings, whether to show anything at that break, and usually shows nothing. The flag only
290
+ widens what it may show over your game; it never makes anything appear.
291
+ - **Nothing else changes.** Call it from the same press, once per break (§3). The answer is the
292
+ same `{ shown }`, it grants nothing (§6), and the Arcade pauses your game the same way while
293
+ anything is up (§7). If a wall is shown, your game stays paused behind it.
294
+ - **A `wall` that is not a boolean** is refused like any other bad argument: `{ shown: false }`
295
+ and a `moments_invalid_argument` report (§5).
296
+ - **An older Arcade ignores it** and treats the break as ordinary, so the flag is safe to send
297
+ everywhere. The dev host's log line (§10) does not carry it.