@indiegems/gem-web-sdk 10.0.0 → 10.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,3 +1,3 @@
1
- var ve=Object.defineProperty;var Re=(n,e)=>{for(var t in e)ve(n,t,{get:e[t],enumerable:true});};globalThis.__gemWebSdkVersion="[gem-web-sdk:sdkVersion:10.0.0]";function xe(n,e){return e!==void 0?!e:n==="chain_exhausted"}var $=class{constructor(e){this.options=e;}options;grant=null;state="pending";failure=null;generation=0;inFlight=null;rejected=false;get currentState(){return this.state}get lastFailure(){return this.failure}async get(){if(this.state==="lost")throw new _(this.failure??"unavailable","the session cannot be renewed");let e=this.seconds();if(this.grant&&e<this.grant.expiresAt-this.renewBefore())return this.grant.token;if(this.grant&&e>=this.grant.chainEndsAt)throw this.enter("lost","chain_exhausted"),new _("chain_exhausted","the token chain reached its ceiling");return this.refresh(this.nextReason())}nextReason(){return this.rejected?"rejected":this.grant?"expiring":"initial"}invalidate(e){e!==void 0&&this.grant!==null&&this.grant.token!==e||this.rejected&&this.grant===null||(this.grant=null,this.generation+=1,this.inFlight=null,this.rejected=true,this.state!=="lost"&&this.enter("pending"));}accept(e){this.state!=="lost"&&(this.grant=e,this.rejected=false,this.enter("ready"));}close(e="unavailable"){this.grant=null,this.generation+=1,this.inFlight=null,this.enter("lost",e);}refresh(e){if(this.inFlight)return this.inFlight;let t=this.generation;this.enter("pending");let r=this.options.request(e).then(o=>{if(t!==this.generation)throw new _("internal","token arrived for a superseded generation");return this.grant=o,this.rejected=false,this.enter("ready"),o.token}).catch(o=>{let s=Se(o),a=o?.retryable;throw t===this.generation&&this.enter(xe(s,typeof a=="boolean"?a:void 0)?"lost":"degraded",s),o instanceof _?o:new _(s,String(o))}).finally(()=>{this.inFlight===r&&(this.inFlight=null);});return this.inFlight=r,r}enter(e,t){this.failure=t??(e==="ready"?null:this.failure),this.state!==e&&(this.state=e,this.options.onStateChange?.(e,t));}renewBefore(){return this.options.renewBeforeSeconds??60}seconds(){return Math.floor(this.options.clock.now()/1e3)}},_=class n extends Error{constructor(t,r){super(`auth ${t}: ${r}`);this.reason=t;this.name="AuthError";}reason;static isAuthError(t){if(t instanceof n)return true;let r=t;return r?.name==="AuthError"&&typeof r.reason=="string"}};function Se(n){if(n instanceof _)return n.reason;let e=n?.reason;return typeof e=="string"&&["chain_exhausted","unavailable","timeout","internal"].includes(e)?e:"internal"}var p=class n extends Error{retryable=false;constructor(e){super(e),this.name="TransportRefusal";}static isRefusal(e){if(e instanceof n)return true;let t=e;return t?.name==="TransportRefusal"&&t.retryable===false}},j=["if-match","if-none-match"],W=4096;function ke(n){if(!n)return;let e={};for(let[t,r]of Object.entries(n)){let o=t.toLowerCase();if(!j.includes(o)||r===void 0)continue;let s=typeof r=="string"?we(r):r;if(typeof s!="string"||s.length>W||!Ae(s))throw new p(`the ${o} header value cannot be sent \u2014 it is not a string, is longer than ${W} characters, or contains a character outside the range an HTTP header value may carry. This is a malformed request, not a server failure; the value is withheld here rather than written to logs.`);s!==""&&(e[o]=s);}return Object.freeze(e)}function we(n){let e=o=>o===32||o===9||o===10||o===13,t=0,r=n.length;for(;t<r&&e(n.charCodeAt(t));)t++;for(;r>t&&e(n.charCodeAt(r-1));)r--;return n.slice(t,r)}function Ae(n){for(let e=0;e<n.length;e++){let t=n.charCodeAt(e);if(t!==9&&(t<32||t===127||t>255))return false}return true}function Pe(n){let{bytes:e}=n;if(e!==void 0){if(Object.prototype.toString.call(e)!=="[object Uint8Array]")throw new p("the raw body is not a Uint8Array, so it cannot be sent as bytes. This is a malformed request, not a server failure.");if(n.body!==void 0)throw new p("the request carries both a JSON body and a raw body, and only one can be sent. This is a malformed request, not a server failure.");return new Uint8Array(e)}}function z(n,e){let t=e.replayUnauthorizedOnce??true;return {async request(r){let o={...r},s=ke(o.headers),a=Pe(o),l=Object.freeze({...o,headers:s,...a===void 0?{}:{bytes:a}}),d=await e.tokenSource.get(),c=await n(l,d);if(c.status!==401||!t)return c;e.tokenSource.invalidate(d);let g=await e.tokenSource.get(),b=await n(l,g);if(b.status===401)throw e.tokenSource.close("unavailable"),new _("unavailable","the server refused a freshly minted token");return b}}}function K(n){let e=typeof n=="string"?new TextEncoder().encode(n):n;return btoa(Te(e))}function Te(n){let t="";for(let r=0;r<n.length;r+=32768)t+=String.fromCharCode(...n.subarray(r,r+32768));return t}var m=class extends Error{constructor(t,r,o,s,a){super(`${t} (${r}): ${o}`);this.reason=t;this.status=r;this.detail=o;this.retryAfterSeconds=s;this.code=a;this.name="GemApiError";}reason;status;detail;retryAfterSeconds;code;get retryable(){return this.reason==="unavailable"||this.reason==="rate_limited"}},J=new WeakMap;function X(n){return J.get(n)??{}}var Oe=new Set([408,429,500,502,503,504]),Ge=6e4;function Ee(n){if(n===void 0)return 2;if(!Number.isInteger(n)||n<0||n>10)throw new p(`maxRetries must be a whole number between 0 and 10; received ${JSON.stringify(n)}. This is a configuration fault, not a server failure.`);return n}var T=class{constructor(e){this.options=e;}options;async get(e,t){return this.send({method:"GET",path:e,signal:t},true)}async getWithEtag(e,t={}){let r=await this.sendRaw({method:"GET",path:e,...t.signal===void 0?{}:{signal:t.signal},...t.ifNoneMatch===void 0?{}:{headers:{"if-none-match":t.ifNoneMatch}}},true),o=r.etag===void 0?{}:{etag:r.etag};return r.status===304?{modified:false,...o}:{modified:true,body:r.body,...o}}async put(e,t,r,o={}){return this.send({method:"PUT",path:e,body:t,signal:r,...C(o)},o.replaySafe===true)}async post(e,t,r,o={}){return this.send({method:"POST",path:e,body:t,signal:r,...C(o)},o.replaySafe===true)}async postBytes(e,t,r,o={}){let s=await this.sendRaw({method:"POST",path:e,bytes:t,responseType:"bytes",signal:r,...C(o)},o.replaySafe===true);return {bytes:Ce(s.body),...s.invocationId===void 0?{}:{invocationId:s.invocationId}}}async patch(e,t,r,o={}){return this.send({method:"PATCH",path:e,body:t,signal:r,...C(o)},o.replaySafe===true)}async delete(e,t,r={}){return this.send({method:"DELETE",path:e,signal:t,...C(r)},r.replaySafe===true)}async send(e,t){return (await this.sendRaw(e,t)).body}async sendRaw(e,t){let r=t?Ee(this.options.maxRetries)+1:1,o=null;if(e.signal?.aborted)throw Y(e.signal);for(let s=0;s<r;s++){if(s>0&&await this.backoff(s,o,e.signal),e.signal?.aborted)throw Y(e.signal);let a;try{a=await this.options.transport.request(e);}catch(d){if(_.isAuthError(d)||p.isRefusal(d)||e.signal?.aborted||Ie(d))throw d;o=new m("unavailable",0,String(d));continue}if(a.status>=200&&a.status<300||a.status===304)return a;let l=qe(a);if(!Oe.has(a.status))throw l;o=l;}throw o??new m("unavailable",0,"no attempt was made")}backoff(e,t,r){if(r?.aborted)return Promise.resolve();let o=t?.retryAfterSeconds,s=o!==void 0?o*1e3:2**(e-1)*250,a=2**(e-1)*250,l=Math.min(Math.max(s,a),Ge);return new Promise(d=>{let c=this.options.clock,g=false,b=false,x,f=()=>{g||(g=true,b&&c.clearTimeout(x),r?.removeEventListener("abort",f),d());};r?.addEventListener("abort",f,{once:true}),x=c.setTimeout(f,l),b=true,g&&c.clearTimeout(x);})}};function Ce(n){if(n instanceof Uint8Array)return n;if(n==null)return new Uint8Array(0);let e=typeof n=="string"?n:JSON.stringify(n);return new TextEncoder().encode(e)}function C(n){return {...n.keepalive===void 0?{}:{keepalive:n.keepalive},...n.ifMatch===void 0?{}:{headers:{"if-match":n.ifMatch}}}}function Y(n){return n.reason!==void 0?n.reason:new DOMException("The operation was aborted.","AbortError")}function Ie(n){let e=n?.name;return e==="AbortError"||e==="TimeoutError"}function qe(n){let e=$e(n),t=Me(n.body),r={...t===void 0?{}:{details:t},...n.invocationId===void 0?{}:{invocationId:n.invocationId}};return Object.keys(r).length>0&&J.set(e,r),e}var Le=new Map([["insufficient_funds","insufficient_funds"]]);function $e(n){let{status:e,body:t}=n,r=je(t),o=n.retryAfterSeconds??Be(t),s=Fe(t),a=s===void 0?void 0:Le.get(s);if(a!==void 0)return new m(a,e,r,void 0,s);switch(e){case 304:return new m("not_modified",e,r);case 400:case 422:return new m("invalid",e,r,void 0,s);case 403:return new m("forbidden",e,r,void 0,s);case 404:return new m("not_found",e,r,void 0,s);case 402:return new m("insufficient_funds",e,r,void 0,s);case 409:return new m("conflict",e,r,void 0,s);case 412:return new m("precondition_failed",e,r,void 0,s);case 413:return new m("too_large",e,r,void 0,s);case 429:return new m("rate_limited",e,r,o,s);default:return new m("unavailable",e,r,o,s)}}function je(n){if(typeof n=="string")return n;let e=n?.message;if(typeof e=="string")return e;let t=n?.error;if(typeof t=="string")return t;let r=t?.message;return typeof r=="string"?r:"no detail"}function Me(n){let t=n?.error?.details;return t===null?void 0:t}function Fe(n){let t=n?.error?.code;return typeof t=="string"&&t.length>0?t:void 0}function Be(n){let e=n?.retryAfterSeconds;return typeof e=="number"&&Number.isFinite(e)&&e>=0?e:void 0}function Ue(n){let e=n.lastIndexOf("@");return (e===-1?n:`***@${n.slice(e+1)}`).slice(0,200)}var Ne=new Set(j);function De(n){if(!n)return {};let e={};for(let[t,r]of Object.entries(n))Ne.has(t.toLowerCase())&&(e[t.toLowerCase()]=r);return e}function Q(n){let e=n.fetch??globalThis.fetch.bind(globalThis);return z(async(t,r)=>{let o;try{o=new URL(n.baseUrl.replace(/\/+$/,""));}catch{throw new p("the configured baseUrl is not a valid URL. Its value is withheld here rather than written to logs. This is a configuration fault, not a server failure.")}let s;try{s=new URL(o.href.replace(/\/+$/,"")+t.path);}catch{throw new p(`${JSON.stringify(typeof t.path=="string"?Ue(t.path):"(a non-string path)")} does not form a valid URL against ${o.protocol}//${o.host}. This is a malformed request, not a server failure.`)}if(s.protocol!==o.protocol||s.host!==o.host)throw new p(`${JSON.stringify(s.pathname)} resolves to ${s.protocol}//${s.host}, not ${o.protocol}//${o.host}. A request path may not change the request's origin \u2014 it carries the play token.`);if(s.username!==""||s.password!==""){let f=o.username!==""||o.password!=="",v=s.username!==o.username||s.password!==o.password,y=f?v?"baseUrl (and possibly the request path)":"baseUrl":"request path";throw new p(`the ${y} puts credentials in the URL, which cannot be fetched (${t.method} ${s.pathname}). The value is withheld here rather than written to logs. This is a malformed request, not a server failure.`)}for(let[f,v]of Object.entries(n.defaultQuery??{}))s.searchParams.has(f)||s.searchParams.set(f,v);let a=t.bytes,l=t.bytes===void 0?void 0:"application/octet-stream";try{t.body!==void 0&&(a=JSON.stringify(t.body),l="application/json");}catch(f){throw new p(`the body of ${t.method} ${JSON.stringify(s.pathname)} could not be serialised to JSON: ${String(f)}. This is a bug in the request, not a server failure \u2014 retrying sends the same unserialisable value.`)}let d=await e(s.toString(),{method:t.method,headers:{authorization:`Bearer ${r}`,...l===void 0?{}:{"content-type":l},...De(t.headers)},body:a,signal:t.signal,...t.keepalive===void 0?{}:{keepalive:t.keepalive},credentials:"omit",mode:"cors",redirect:"error",cache:"no-store",referrerPolicy:"no-referrer"}),c=null;if(t.responseType==="bytes"&&d.status>=200&&d.status<300)c=new Uint8Array(await d.arrayBuffer());else {let f=await d.text();if(f.length>0)try{c=JSON.parse(f);}catch{c=f;}}let g=d.headers.get("etag"),b=He(d.headers.get("retry-after")),x=d.headers.get("x-gem-invocation-id");return {status:d.status,body:c,...g===null?{}:{etag:g},...b===void 0?{}:{retryAfterSeconds:b},...x===null||x===""?{}:{invocationId:x}}},n)}function He(n){if(n===null)return;let e=n.trim();if(!/^\d+$/.test(e))return;let t=Number(e);return Number.isFinite(t)?t:void 0}var Ve="gem-web-bridge";var O=65536,Z=8,M=5e3,ee=1024;function U(n){return Object.freeze(Object.assign(Object.create(null),n))}U({"gem.handshake":30,"gem.handshake.accept":5,"gem.token":30,"gem.token.denied":30,"gem.player":12,"gem.pause":120,"gem.prefs":60,"gem.cohorts":12,"gem.earnAllowanceChanged":30,"gem.viewport":60,"gem.deviceSettings":12,"gem.willTerminate":10,"gem.roomEvent":120,"gem.socketState":12,"gem.seatedEvent":60,"gem.autoStartFailedEvent":30,"gem.signalEvent":1800,"gem.dedicatedEvent":120,"gem.partyResult":30,"gem.clusterTarget":12,"gem.devtools":30,"gem.screenshot":6,"gem.screenshot.denied":12,"gem.requestContext":12,"gem.gameContext":12,"gem.signal":1200,"gem.dedicatedOffer":60,"gem.partyRequest":12,"gem.ready":5,"gem.engaged":5,"gem.progress":600,"gem.requestToken":12,"gem.requestLocalServer":6,"gem.localServer":30,"gem.localServer.denied":30,"gem.exit":5,"gem.openExternal":6,"gem.requestFullscreen":30,"gem.audioState":120,"gem.rewardCue":60,"gem.walletDisplay":60,"gem.menu":60,"gem.menuSelect":60,"gem.requestShare":6,"gem.vibrate":600,"gem.frameStats":120,"gem.portraitBorders":60,"gem.error":60,"gem.requestPurchase":12,"gem.purchaseResult":30,"gem.deviceSettings.put":30,"gem.deviceSettings.result":30,"gem.requestAd":6,"gem.adResult":12,"gem.requestSignIn":6,"gem.signInResult":12,"gem.requestFriendChallenge":12,"gem.friendChallengeResult":30,__malformed:60});U({"gem.requestAd":"ads","gem.adResult":"ads","gem.requestSignIn":"signIn","gem.signInResult":"signIn","gem.requestPurchase":"purchases","gem.purchaseResult":"purchases","gem.requestFriendChallenge":"friendChallenges","gem.friendChallengeResult":"friendChallenges","gem.devtools":"devtools","gem.screenshot":"screenshot","gem.screenshot.denied":"screenshot","gem.requestContext":"feedbackContext","gem.gameContext":"feedbackContext","gem.roomEvent":"rooms","gem.signal":"p2p","gem.signalEvent":"p2p","gem.dedicatedOffer":"dedicated","gem.dedicatedEvent":"dedicated","gem.clusterTarget":"clusterTarget","gem.partyRequest":"parties","gem.partyResult":"parties","gem.autoStartFailedEvent":"autoStartFailure","gem.seatedEvent":"partySeating","gem.socketState":"socketState","gem.audioState":"audioState","gem.rewardCue":"rewardCue","gem.frameStats":"frameStats","gem.portraitBorders":"portraitBorders","gem.engaged":"engagement","gem.viewport":"viewport","gem.walletDisplay":"walletDisplay","gem.requestLocalServer":"localHost","gem.localServer":"localHost","gem.localServer.denied":"localHost","gem.cohorts":"cohorts","gem.earnAllowanceChanged":"earnAllowance","gem.deviceSettings":"deviceSettings","gem.deviceSettings.put":"deviceSettings","gem.deviceSettings.result":"deviceSettings","gem.requestShare":"share","gem.vibrate":"vibration","gem.menu":"gameMenu","gem.menuSelect":"gameMenu"});function ze(n){let e=/^([a-z][a-z0-9+.-]*):\/\/([a-z0-9.-]+|\[[0-9a-f:.]+\])(:([0-9]{1,5}))?$/i.exec(n);return e===null?false:e[4]===void 0||Number(e[4])<=65535}function Ke(n){let e;try{e=new URL(n);}catch{return false}return e.username!==""||e.password!==""?false:e.protocol==="https:"?true:e.protocol==="http:"&&(e.hostname==="localhost"||e.hostname==="127.0.0.1")}function Ye(n){return /^[a-z]{2,8}(-[a-z0-9]{1,8})*$/i.test(n)}function Je(n){return /^[a-z_]+$/.test(n)}function B(n,e,t){if(e>Z)return `nesting deeper than ${Z}`;if(++t.nodes>M)return `more than ${M} values`;if(t.bytes>O)return `over the ${O} byte limit`;if(n==null)return t.bytes+=4,null;let r=typeof n;if(r==="boolean")return t.bytes+=5,null;if(r==="number")return t.bytes+=8,null;if(r==="string")return t.bytes+=n.length*3+2,null;if(r!=="object")return `${r} is not plain data`;let o=n;if(t.seen.has(o))return "a repeated or cyclic object reference";if(t.seen.add(o),Array.isArray(n)){if(n.length>ee)return `an array of ${n.length} entries, over the ${ee} limit`;t.bytes+=2;for(let l of n){let d=B(l,e+1,t);if(d)return d}return null}let s=Object.getPrototypeOf(n);if(s!==Object.prototype&&s!==null)return "a value that is not a plain object";t.bytes+=2;let a=n;for(let l in a){if(!Object.prototype.hasOwnProperty.call(a,l))continue;if(++t.nodes>M)return `more than ${M} values`;if(t.bytes+=l.length*3+4,t.bytes>O)return `over the ${O} byte limit`;let d=B(a[l],e+1,t);if(d)return d}return null}function Xe(n){let e={nodes:0,bytes:0,seen:new Set},t=B(n,0,e);return t?`message contains ${t}`:e.bytes>O?`message is over the ${O} byte limit`:null}var Qe={origin:[ze,"not a well-formed origin"],url:[Ke,"not a safe absolute http(s) URL"],bcp47:[Ye,"not a well-formed BCP 47 tag"],code:[Je,"not a code of lower-case letters and underscores"]};function ne(n,e,t){for(let r of e){let o=t===""?r.n:`${t}.${r.n}`,s=n[r.n];if(s==null){if(r.o)continue;return `${o}: required`}let a=te(s,r,o);if(a)return a}return null}function te(n,e,t){switch(e.k){case "string":{if(typeof n!="string")return `${t}: expected string`;if(n.length>e.max)return `${t}: exceeds ${e.max} characters`;if(e.f){let[r,o]=Qe[e.f];if(!r(n))return `${t}: ${o}`}return null}case "int":return typeof n!="number"||!Number.isInteger(n)?`${t}: expected integer`:n<e.lo||n>e.hi?`${t}: out of range ${e.lo}..${e.hi}`:null;case "boolean":return typeof n=="boolean"?null:`${t}: expected boolean`;case "enum":{let r=e.v;return r.includes(n)?null:`${t}: not one of ${r.join("|")}`}case "object":return typeof n!="object"||n===null||Array.isArray(n)?`${t}: expected object`:ne(n,e.fs,t);case "json":return typeof n!="object"||n===null||Array.isArray(n)?`${t}: expected a plain object`:null;case "array":{if(!Array.isArray(n))return `${t}: expected array`;if(n.length>e.max)return `${t}: exceeds ${e.max} items`;let r=e.it,o=`${t}[]`;for(let s of n){if(s==null){if(r.o)continue;return `${o}: required`}let a=te(s,r,o);if(a)return a}return null}default:{let r=e.k;return `${t}: unknown kind ${String(r)}`}}}function u(n,e){return t=>{let r=Xe(t);if(r)return r;if(typeof t!="object"||t===null||Array.isArray(t))return "message: expected object";let o=t;return o.gem!==Ve?"gem: wrong protocol marker":o.type!==n?`type: expected ${n}`:ne(o,e,"")}}var Ze=u("gem.handshake",[{n:"versions",k:"object",fs:[{n:"min",k:"int",lo:1,hi:1e3},{n:"max",k:"int",lo:1,hi:1e3}]},{n:"capabilities",k:"array",o:1,max:64,it:{n:"",k:"string",max:64}},{n:"embedder",k:"string",max:2048,f:"origin"},{n:"unbidden",k:"boolean",o:1}]),en=u("gem.handshake.accept",[{n:"v",k:"int",lo:1,hi:1e3},{n:"capabilities",k:"array",o:1,max:64,it:{n:"",k:"string",max:64}}]),nn=u("gem.token",[{n:"token",k:"string",max:4096},{n:"requestId",k:"string",o:1,max:64},{n:"generation",k:"int",lo:0,hi:2147483647},{n:"apiBaseUrl",k:"string",o:1,max:512,f:"url"},{n:"playerId",k:"string",max:64},{n:"gameId",k:"string",max:64},{n:"channel",k:"enum",v:["dev","test","release"]},{n:"gameVersion",k:"string",o:1,max:64},{n:"expiresAt",k:"int",lo:0,hi:4102444800},{n:"chainEndsAt",k:"int",lo:0,hi:4102444800},{n:"allowDevTools",k:"boolean",o:1}]),tn=u("gem.token.denied",[{n:"requestId",k:"string",max:64},{n:"retryable",k:"boolean"},{n:"retryAfterMs",k:"int",o:1,lo:0,hi:36e5},{n:"reason",k:"enum",v:["chain_exhausted","unavailable"]},{n:"correlationId",k:"string",max:64}]),rn=u("gem.player",[{n:"untrusted",k:"object",fs:[{n:"displayName",k:"string",max:64},{n:"displayTag",k:"string",o:1,max:80},{n:"displayHandle",k:"string",max:80}]},{n:"playerId",k:"string",o:1,max:64},{n:"discriminator",k:"string",o:1,max:8},{n:"avatarIconUrl",k:"string",o:1,max:2048,f:"url"},{n:"badges",k:"array",o:1,max:2,it:{n:"",k:"object",fs:[{n:"itemId",k:"string",max:64},{n:"iconUrl",k:"string",max:2048,f:"url"}]}},{n:"displayTag",k:"string",max:8},{n:"avatarUrl",k:"string",o:1,max:2048,f:"url"},{n:"boost",k:"object",o:1,fs:[{n:"multipliers",k:"array",max:8,it:{n:"",k:"object",fs:[{n:"currencyId",k:"string",max:64},{n:"currencySlug",k:"string",max:32},{n:"multiplierBp",k:"int",lo:1e4,hi:1e6}]}},{n:"expiresInDays",k:"int",o:1,lo:1,hi:7}]}]),on=u("gem.pause",[{n:"paused",k:"boolean"}]),sn=u("gem.prefs",[{n:"reducedMotion",k:"boolean"},{n:"muted",k:"boolean"},{n:"showFrameStats",k:"boolean",o:1},{n:"locale",k:"string",max:35,f:"bcp47"}]),an=u("gem.cohorts",[{n:"cohorts",k:"array",max:8,it:{n:"",k:"object",fs:[{n:"experimentId",k:"string",max:36},{n:"variantKey",k:"string",max:32}]}}]),ln=u("gem.earnAllowanceChanged",[]),dn=u("gem.viewport",[{n:"insets",k:"object",fs:[{n:"top",k:"int",lo:0,hi:4096},{n:"right",k:"int",lo:0,hi:4096},{n:"bottom",k:"int",lo:0,hi:4096},{n:"left",k:"int",lo:0,hi:4096}]},{n:"reserved",k:"array",o:1,max:4,it:{n:"",k:"object",fs:[{n:"x",k:"int",lo:0,hi:16384},{n:"y",k:"int",lo:0,hi:16384},{n:"width",k:"int",lo:0,hi:16384},{n:"height",k:"int",lo:0,hi:16384}]}}]),un=u("gem.deviceSettings",[{n:"settings",k:"json",o:1}]),cn=u("gem.willTerminate",[{n:"reason",k:"enum",v:["grant_expiring","session_ended","navigating","kill_switch"]},{n:"graceMs",k:"int",lo:0,hi:6e4}]),gn=u("gem.roomEvent",[{n:"event",k:"enum",v:["updated","match_started","match_ready","match_failed","version_stale"]},{n:"roomId",k:"string",max:64},{n:"matchId",k:"string",o:1,max:64},{n:"version",k:"int",o:1,lo:0,hi:2147483647},{n:"reason",k:"string",o:1,max:64},{n:"platform",k:"enum",o:1,v:["universal","mobile"]}]),mn=u("gem.socketState",[{n:"connected",k:"boolean"},{n:"reason",k:"enum",o:1,v:["connecting","dropped","watchdog","terminal"]}]),pn=u("gem.seatedEvent",[{n:"roomId",k:"string",max:64}]),yn=u("gem.autoStartFailedEvent",[{n:"roomId",k:"string",max:64},{n:"code",k:"string",max:64}]),fn=u("gem.signalEvent",[{n:"event",k:"enum",v:["hello","offer","answer","ice","peerJoined","peerLeft","migration","matchEnded","error"]},{n:"matchId",k:"string",max:64},{n:"data",k:"json"}]),hn=u("gem.dedicatedEvent",[{n:"event",k:"enum",v:["answer","error","matchEnded"]},{n:"matchId",k:"string",max:64},{n:"sdp",k:"string",o:1,max:10240},{n:"sessionId",k:"string",o:1,max:64},{n:"code",k:"string",o:1,max:64},{n:"message",k:"string",o:1,max:256},{n:"reason",k:"string",o:1,max:64}]),_n=u("gem.partyResult",[{n:"requestId",k:"string",max:64},{n:"partyId",k:"string",o:1,max:64}]),bn=u("gem.clusterTarget",[{n:"clusterTargetId",k:"string",max:64},{n:"clusterTargetIds",k:"array",o:1,max:3,it:{n:"",k:"string",max:64}}]),vn=u("gem.devtools",[{n:"action",k:"enum",v:["open","close","toggle"]}]),Rn=u("gem.screenshot",[{n:"maxWidth",k:"int",lo:1,hi:7680},{n:"maxHeight",k:"int",lo:1,hi:4320}]),xn=u("gem.screenshot.denied",[{n:"reason",k:"enum",v:["not_wired","no_source","unsupported","unreadable","tainted","too_large","busy","declined","failed"]},{n:"retryable",k:"boolean"}]),Sn=u("gem.requestContext",[]),kn=u("gem.gameContext",[{n:"context",k:"json"}]),wn=u("gem.signal",[{n:"signal",k:"enum",v:["join","offer","answer","ice","migrationAck","hostUnreachable"]},{n:"matchId",k:"string",max:64},{n:"data",k:"json"}]),An=u("gem.dedicatedOffer",[{n:"matchId",k:"string",max:64},{n:"sdp",k:"string",max:10240},{n:"intent",k:"enum",v:["initial","ice_restart","full_reconnect"]}]),Pn=u("gem.partyRequest",[{n:"requestId",k:"string",max:64}]),Tn=u("gem.ready",[]),On=u("gem.engaged",[]),Gn=u("gem.progress",[{n:"loaded",k:"int",lo:0,hi:1099511627776},{n:"total",k:"int",lo:0,hi:1099511627776}]),En=u("gem.requestToken",[{n:"requestId",k:"string",max:64},{n:"reason",k:"enum",v:["initial","expiring","rejected"]}]),Cn=u("gem.requestLocalServer",[{n:"requestId",k:"string",max:64},{n:"gameRoomId",k:"string",max:64}]),In=u("gem.localServer",[{n:"requestId",k:"string",max:64},{n:"serverId",k:"string",o:1,max:128}]),qn=u("gem.localServer.denied",[{n:"requestId",k:"string",max:64},{n:"retryable",k:"boolean"},{n:"reason",k:"enum",v:["refused","unavailable"]}]),Ln=u("gem.exit",[{n:"reason",k:"string",o:1,max:64}]),$n=u("gem.openExternal",[{n:"url",k:"string",max:2048,f:"url"}]),jn=u("gem.requestFullscreen",[{n:"enabled",k:"boolean"}]),Mn=u("gem.audioState",[{n:"muted",k:"boolean"}]),Fn=u("gem.rewardCue",[{n:"currencySlug",k:"string",max:32},{n:"expected",k:"int",o:1,lo:1,hi:1e9},{n:"origin",k:"object",o:1,fs:[{n:"x",k:"int",lo:0,hi:16384},{n:"y",k:"int",lo:0,hi:16384}]}]),Bn=u("gem.walletDisplay",[{n:"visible",k:"boolean"},{n:"currencies",k:"array",o:1,max:8,it:{n:"",k:"string",max:64}},{n:"score",k:"boolean",o:1}]),Un=u("gem.menu",[{n:"settings",k:"boolean"},{n:"items",k:"array",o:1,max:4,it:{n:"",k:"object",fs:[{n:"id",k:"string",max:32},{n:"label",k:"string",max:40}]}}]),Nn=u("gem.menuSelect",[{n:"entry",k:"enum",v:["settings","item"]},{n:"id",k:"string",o:1,max:32}]),Dn=u("gem.requestShare",[{n:"params",k:"array",max:16,it:{n:"",k:"object",fs:[{n:"key",k:"string",max:64},{n:"value",k:"string",max:512}]}}]),Hn=u("gem.vibrate",[{n:"pattern",k:"array",max:99,it:{n:"",k:"int",lo:0,hi:1e4}}]),Vn=u("gem.frameStats",[{n:"fps",k:"int",lo:0,hi:1e3},{n:"frameTimeP95Ms",k:"int",lo:0,hi:1e5}]),Wn=u("gem.portraitBorders",[{n:"name",k:"string",o:1,max:40}]),zn=u("gem.error",[{n:"code",k:"enum",v:["version_mismatch","handshake_timeout","handshake_duplicate","invalid_message","rate_limited","token_unavailable","unsupported","unsupported_capability","internal"]},{n:"message",k:"string",o:1,max:256}]),Kn=u("gem.requestPurchase",[{n:"requestId",k:"string",max:64},{n:"purchaseKind",k:"enum",v:["item","recipe"]},{n:"targetId",k:"string",max:64},{n:"currencySlug",k:"string",max:32},{n:"quantity",k:"int",o:1,lo:1,hi:10},{n:"catalogId",k:"string",o:1,max:64}]),Yn=u("gem.purchaseResult",[{n:"requestId",k:"string",max:64},{n:"outcome",k:"enum",v:["ok","declined","unavailable"]},{n:"reason",k:"string",o:1,max:64,f:"code"},{n:"purchaseId",k:"string",o:1,max:64}]),Jn=u("gem.deviceSettings.put",[{n:"requestId",k:"string",max:64},{n:"settings",k:"json"}]),Xn=u("gem.deviceSettings.result",[{n:"requestId",k:"string",max:64},{n:"outcome",k:"enum",v:["stored","too_large","unavailable"]}]),Qn=u("gem.requestAd",[{n:"requestId",k:"string",max:64},{n:"placement",k:"string",max:32},{n:"format",k:"enum",v:["interstitial","rewarded"]}]),Zn=u("gem.adResult",[{n:"requestId",k:"string",max:64},{n:"outcome",k:"enum",v:["shown","no_ad","unavailable"]}]),et=u("gem.requestSignIn",[{n:"requestId",k:"string",max:64}]),nt=u("gem.signInResult",[{n:"requestId",k:"string",max:64},{n:"outcome",k:"enum",v:["signed_in","declined","unavailable"]}]),tt=u("gem.requestFriendChallenge",[{n:"requestId",k:"string",max:64},{n:"playerId",k:"string",max:64},{n:"template",k:"string",max:64},{n:"params",k:"json",o:1}]),rt=u("gem.friendChallengeResult",[{n:"requestId",k:"string",max:64},{n:"outcome",k:"enum",v:["accepted","cancelled","refused","unavailable","rate_limited","invalid"]},{n:"code",k:"string",o:1,max:64},{n:"param",k:"string",o:1,max:64},{n:"channel",k:"string",o:1,max:16},{n:"configVersion",k:"int",o:1,lo:0,hi:9007199254740991},{n:"retryAfterMs",k:"int",o:1,lo:0,hi:864e5},{n:"detail",k:"string",o:1,max:300}]);U({"gem.handshake":Ze,"gem.handshake.accept":en,"gem.token":nn,"gem.token.denied":tn,"gem.player":rn,"gem.pause":on,"gem.prefs":sn,"gem.cohorts":an,"gem.earnAllowanceChanged":ln,"gem.viewport":dn,"gem.deviceSettings":un,"gem.willTerminate":cn,"gem.roomEvent":gn,"gem.socketState":mn,"gem.seatedEvent":pn,"gem.autoStartFailedEvent":yn,"gem.signalEvent":fn,"gem.dedicatedEvent":hn,"gem.partyResult":_n,"gem.clusterTarget":bn,"gem.devtools":vn,"gem.screenshot":Rn,"gem.screenshot.denied":xn,"gem.requestContext":Sn,"gem.gameContext":kn,"gem.signal":wn,"gem.dedicatedOffer":An,"gem.partyRequest":Pn,"gem.ready":Tn,"gem.engaged":On,"gem.progress":Gn,"gem.requestToken":En,"gem.requestLocalServer":Cn,"gem.localServer":In,"gem.localServer.denied":qn,"gem.exit":Ln,"gem.openExternal":$n,"gem.requestFullscreen":jn,"gem.audioState":Mn,"gem.rewardCue":Fn,"gem.walletDisplay":Bn,"gem.menu":Un,"gem.menuSelect":Nn,"gem.requestShare":Dn,"gem.vibrate":Hn,"gem.frameStats":Vn,"gem.portraitBorders":Wn,"gem.error":zn,"gem.requestPurchase":Kn,"gem.purchaseResult":Yn,"gem.deviceSettings.put":Jn,"gem.deviceSettings.result":Xn,"gem.requestAd":Qn,"gem.adResult":Zn,"gem.requestSignIn":et,"gem.signInResult":nt,"gem.requestFriendChallenge":tt,"gem.friendChallengeResult":rt});var G={now:()=>Date.now(),setTimeout:(n,e)=>setTimeout(n,e),clearTimeout:n=>clearTimeout(n)};var ot=1e4;function re(n,e){return N(n,e)}function N(n,e){if(typeof n.serverToken!="function"||typeof n.onServerToken!="function")throw new Error("this runtime delivers no game-server token: host.serverToken/onServerToken are missing. The server image running this bundle predates token delivery \u2014 the bundle cannot call gem-api on it.");let t=a=>({token:a.token,expiresAt:a.expiresAt,chainEndsAt:Number.POSITIVE_INFINITY}),r=null,o=new $({clock:e.clock,...e.onStateChange===void 0?{}:{onStateChange:e.onStateChange},request:()=>new Promise((a,l)=>{let d=e.clock.setTimeout(()=>{r=null,l({reason:"unavailable",retryable:true});},e.timeoutMs??ot);r={resolve:c=>{e.clock.clearTimeout(d),a(c);},reject:l,timer:d};})}),s=n.onServerToken(a=>{let l=t(a),d=r;if(d){r=null,d.resolve(l);return}o.accept(l);});return {source:o,dispose(){s(),r&&(e.clock.clearTimeout(r.timer),r.reject({reason:"unavailable",retryable:false}),r=null);}}}var H={};Re(H,{acceptTransfer:()=>st,addEntityProgression:()=>it,adminAction:()=>at,cancelInventoryTransfer:()=>lt,claimEntityProgressionRewards:()=>dt,closeGameRoom:()=>ut,createEntityBatchOrder:()=>ct,createEntityOrder:()=>gt,createSession:()=>mt,deleteEntityGameSetting:()=>pt,deleteEntitySave:()=>yt,deleteSession:()=>ft,deleteShowcaseValue:()=>ht,executeEntityRecipe:()=>_t,finalizeSaveUpload:()=>bt,getChannelAssignment:()=>vt,getDropRates:()=>Rt,getEntityCurrency:()=>xt,getEntityGameSetting:()=>St,getEntityInventory:()=>kt,getEntityInventoryItem:()=>wt,getEntityLeaderboard:()=>At,getEntityOrder:()=>Pt,getEntityProgression:()=>Tt,getEntityRecipeAvailability:()=>Ot,getEntityRecipeUsage:()=>Gt,getEntitySave:()=>Et,getEvent:()=>Ct,getGameRoomV2:()=>It,getLeaderboard:()=>qt,getPlayerGameProfile:()=>Lt,getPurchaseCatalog:()=>$t,getResolvedTemplate:()=>jt,getRoomArgs:()=>Mt,getShowcaseValue:()=>Ft,getTransferDetails:()=>Bt,ingestAnalyticsEvents:()=>D,initiateInventoryTransfer:()=>Ut,invokeFunction:()=>Nt,kickPlayer:()=>Dt,listChallenges:()=>Ht,listEntityGameSettings:()=>Vt,listEntityOrders:()=>Wt,listEntityProgressions:()=>zt,listEntitySaves:()=>Kt,listEvents:()=>Yt,listGameRooms:()=>Jt,listResolvedTemplates:()=>Xt,listTransfers:()=>Qt,maxEntityProgression:()=>Zt,putEntityGameSetting:()=>er,putRoomArgs:()=>nr,putShowcaseValue:()=>tr,rejectTransfer:()=>rr,requestSaveUploadUrl:()=>or,resetEntityProgression:()=>sr,simulateEntityOrder:()=>ir,transferHostV2:()=>ar,updateGameRoomV2:()=>lr});function i(n){let e=String(n);if(!/^[A-Za-z0-9_.-]{1,128}$/.test(e)||e==="."||e==="..")throw new TypeError(`${JSON.stringify(e)} is not a usable path segment \u2014 it is interpolated into a URL`);return encodeURIComponent(e)}async function st(n,e,t){let r=`/v1/inventory/transfers/${i(e)}/accept`;return n.client.post(r,void 0,t?.signal)}async function it(n,e,t,r,o,s){let a=`/v1/inventory/${i(e)}/${i(t)}/progressions/${i(r)}/add`;return n.client.post(a,o,s?.signal)}async function at(n,e,t,r){let o=`/v1/voice/sessions/${i(e)}/admin`;return n.client.post(o,t,r?.signal)}async function lt(n,e,t){let r=`/v1/inventory/transfers/${i(e)}/cancel`;return n.client.post(r,void 0,t?.signal)}async function dt(n,e,t,r,o,s){let a=`/v1/inventory/${i(e)}/${i(t)}/progressions/${i(r)}/claim`;return n.client.post(a,o,s?.signal)}async function ut(n,e,t){let r=`/v1/games/${i(n.gameId())}/game-rooms/${i(e)}`;return n.client.delete(r,t?.signal)}async function ct(n,e,t,r,o){let s=`/v1/inventory/${i(e)}/${i(t)}/orders/batch`;return n.client.post(s,r,o?.signal,{...o?.ifMatch===void 0?{}:{ifMatch:o.ifMatch}})}async function gt(n,e,t,r,o){let s=`/v1/inventory/${i(e)}/${i(t)}/orders`;return n.client.post(s,r,o?.signal,{...o?.ifMatch===void 0?{}:{ifMatch:o.ifMatch}})}async function mt(n,e,t){return n.client.post("/v1/voice/sessions",e,t?.signal)}async function pt(n,e,t,r,o){let s=`/v1/settings/${i(e)}/${i(t)}/${i(r)}`;return n.client.delete(s,o?.signal)}async function yt(n,e,t,r,o){let s=`/v1/saves/${i(e)}/${i(t)}/${i(r)}`;return n.client.delete(s,o?.signal)}async function ft(n,e,t){let r=`/v1/voice/sessions/${i(e)}`;return n.client.delete(r,t?.signal)}async function ht(n,e,t,r){let o=`/v1/showcase/players/${i(e)}/${i(t)}`;return n.client.delete(o,r?.signal)}async function _t(n,e,t,r,o){let s=`/v1/inventory/${i(e)}/${i(t)}/recipes/execute`;return n.client.post(s,r,o?.signal,{...o?.ifMatch===void 0?{}:{ifMatch:o.ifMatch}})}async function bt(n,e,t,r,o,s){let a=`/v1/saves/${i(e)}/${i(t)}/${i(r)}/finalize`;return n.client.post(a,o,s?.signal)}async function vt(n,e,t){let r=`/v1/games/${i(n.gameId())}/config/channels/${i(e)}`;return n.client.getWithEtag(r,{...t?.signal===void 0?{}:{signal:t.signal},...t?.ifNoneMatch===void 0?{}:{ifNoneMatch:t.ifNoneMatch}})}async function Rt(n,e,t){let r=`/v1/inventory/loot-tables/${i(e)}/drop-rates`;return n.client.get(r,t?.signal)}async function xt(n,e,t,r,o){let s=`/v1/inventory/${i(e)}/${i(t)}/currencies/${i(r)}`;return n.client.get(s,o?.signal)}async function St(n,e,t,r,o){let s=`/v1/settings/${i(e)}/${i(t)}/${i(r)}`;return n.client.getWithEtag(s,{...o?.signal===void 0?{}:{signal:o.signal},...o?.ifNoneMatch===void 0?{}:{ifNoneMatch:o.ifNoneMatch}})}async function kt(n,e,t,r){let o=new URLSearchParams;r?.include_buckets!==void 0&&o.set("include_buckets",String(r?.include_buckets)),r?.include_custom_data!==void 0&&o.set("include_custom_data",String(r?.include_custom_data)),r?.currency_limit!==void 0&&o.set("currency_limit",String(r?.currency_limit)),r?.currency_cursor!==void 0&&o.set("currency_cursor",String(r?.currency_cursor)),r?.item_limit!==void 0&&o.set("item_limit",String(r?.item_limit)),r?.item_cursor!==void 0&&o.set("item_cursor",String(r?.item_cursor)),r?.progression_limit!==void 0&&o.set("progression_limit",String(r?.progression_limit)),r?.progression_cursor!==void 0&&o.set("progression_cursor",String(r?.progression_cursor));let s=o.toString(),a=`/v1/inventory/${i(e)}/${i(t)}`+(s?`?${s}`:"");return n.client.get(a,r?.signal)}async function wt(n,e,t,r,o){let s=`/v1/inventory/${i(e)}/${i(t)}/items/${i(r)}`;return n.client.get(s,o?.signal)}async function At(n,e,t,r,o){let s=new URLSearchParams;o?.bucket_1!==void 0&&s.set("bucket_1",String(o?.bucket_1)),o?.bucket_2!==void 0&&s.set("bucket_2",String(o?.bucket_2)),o?.limit!==void 0&&s.set("limit",String(o?.limit)),o?.periods_back!==void 0&&s.set("periods_back",String(o?.periods_back)),o?.period!==void 0&&s.set("period",String(o?.period)),o?.player_id!==void 0&&s.set("player_id",String(o?.player_id));let a=s.toString(),l=`/v1/leaderboards/${i(e)}/${i(t)}/${i(r)}`+(a?`?${a}`:"");return n.client.get(l,o?.signal)}async function Pt(n,e,t,r,o){let s=`/v1/inventory/${i(e)}/${i(t)}/orders/${i(r)}`;return n.client.get(s,o?.signal)}async function Tt(n,e,t,r,o){let s=`/v1/inventory/${i(e)}/${i(t)}/progressions/${i(r)}`;return n.client.get(s,o?.signal)}async function Ot(n,e,t,r,o,s){let a=`/v1/inventory/${i(e)}/${i(t)}/catalogs/${i(r)}/recipes/${i(o)}/availability`;return n.client.get(a,s?.signal)}async function Gt(n,e,t,r){let o=new URLSearchParams;r?.limit!==void 0&&o.set("limit",String(r?.limit));let s=o.toString(),a=`/v1/inventory/${i(e)}/${i(t)}/recipe-usage`+(s?`?${s}`:"");return n.client.get(a,r?.signal)}async function Et(n,e,t,r,o){let s=`/v1/saves/${i(e)}/${i(t)}/${i(r)}`;return n.client.getWithEtag(s,{...o?.signal===void 0?{}:{signal:o.signal},...o?.ifNoneMatch===void 0?{}:{ifNoneMatch:o.ifNoneMatch}})}async function Ct(n,e,t){let r=`/v1/events/${i(e)}`;return n.client.get(r,t?.signal)}async function It(n,e,t){let r=`/v2/games/${i(n.gameId())}/game-rooms/${i(e)}`;return n.client.getWithEtag(r,{...t?.signal===void 0?{}:{signal:t.signal},...t?.ifNoneMatch===void 0?{}:{ifNoneMatch:t.ifNoneMatch}})}async function qt(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(),s=`/v1/leaderboards/${i(e)}`+(o?`?${o}`:"");return n.client.get(s,t?.signal)}async function Lt(n,e,t){let r=`/v1/profiles/players/${i(e)}`;return n.client.get(r,t?.signal)}async function $t(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 jt(n,e,t){let r=`/v1/game-room-templates/${i(e)}`;return n.client.get(r,t?.signal)}async function Mt(n,e,t){let r=`/v1/games/${i(n.gameId())}/game-rooms/${i(e)}/room-args`;return n.client.get(r,t?.signal)}async function Ft(n,e,t,r){let o=`/v1/showcase/players/${i(e)}/${i(t)}`;return n.client.get(o,r?.signal)}async function Bt(n,e,t){let r=`/v1/inventory/transfers/${i(e)}`;return n.client.get(r,t?.signal)}async function D(n,e,t){let r=`/v1/games/${i(n.gameId())}/analytics/events`;return n.client.post(r,e,t?.signal,{replaySafe:true})}async function Ut(n,e,t){return n.client.post("/v1/inventory/transfers",e,t?.signal)}async function Nt(n,e,t){return n.client.postBytes("/v1/functions/invoke",e,t?.signal)}async function Dt(n,e,t,r){let o=`/v1/games/${i(n.gameId())}/game-rooms/${i(e)}/kick/${i(t)}`;return n.client.post(o,void 0,r?.signal)}async function Ht(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 Vt(n,e,t,r){let o=`/v1/settings/${i(e)}/${i(t)}`;return n.client.get(o,r?.signal)}async function Wt(n,e,t,r){let o=new URLSearchParams;r?.limit!==void 0&&o.set("limit",String(r?.limit)),r?.cursor!==void 0&&o.set("cursor",String(r?.cursor));let s=o.toString(),a=`/v1/inventory/${i(e)}/${i(t)}/orders`+(s?`?${s}`:"");return n.client.get(a,r?.signal)}async function zt(n,e,t,r){let o=`/v1/inventory/${i(e)}/${i(t)}/progressions`;return n.client.get(o,r?.signal)}async function Kt(n,e,t,r){let o=new URLSearchParams;r?.limit!==void 0&&o.set("limit",String(r?.limit)),r?.cursor!==void 0&&o.set("cursor",String(r?.cursor));let s=o.toString(),a=`/v1/saves/${i(e)}/${i(t)}`+(s?`?${s}`:"");return n.client.get(a,r?.signal)}async function Yt(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 Jt(n,e){let t=new URLSearchParams;e?.status!==void 0&&t.set("status",String(e?.status)),e?.game_channel!==void 0&&t.set("game_channel",String(e?.game_channel)),e?.game_room_type!==void 0&&t.set("game_room_type",String(e?.game_room_type)),e?.template_id!==void 0&&t.set("template_id",String(e?.template_id)),e?.template_slug!==void 0&&t.set("template_slug",String(e?.template_slug)),e?.limit!==void 0&&t.set("limit",String(e?.limit)),e?.cursor!==void 0&&t.set("cursor",String(e?.cursor));let r=t.toString(),o=`/v1/games/${i(n.gameId())}/game-rooms`+(r?`?${r}`:"");return n.client.get(o,e?.signal)}async function Xt(n,e){return n.client.get("/v1/game-room-templates",e?.signal)}async function Qt(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 Zt(n,e,t,r,o,s){let a=`/v1/inventory/${i(e)}/${i(t)}/progressions/${i(r)}/max`;return n.client.post(a,o,s?.signal)}async function er(n,e,t,r,o,s){let a=`/v1/settings/${i(e)}/${i(t)}/${i(r)}`;return n.client.put(a,o,s?.signal,{...s?.ifMatch===void 0?{}:{ifMatch:s.ifMatch}})}async function nr(n,e,t,r){let o=`/v1/games/${i(n.gameId())}/game-rooms/${i(e)}/room-args`;return n.client.put(o,t,r?.signal)}async function tr(n,e,t,r,o){let s=`/v1/showcase/players/${i(e)}/${i(t)}`;return n.client.put(s,r,o?.signal)}async function rr(n,e,t){let r=`/v1/inventory/transfers/${i(e)}/reject`;return n.client.post(r,void 0,t?.signal)}async function or(n,e,t,r,o,s){let a=`/v1/saves/${i(e)}/${i(t)}/${i(r)}/upload-url`;return n.client.post(a,o,s?.signal,{replaySafe:true})}async function sr(n,e,t,r,o,s){let a=`/v1/inventory/${i(e)}/${i(t)}/progressions/${i(r)}/reset`;return n.client.post(a,o,s?.signal)}async function ir(n,e,t,r,o){let s=`/v1/inventory/${i(e)}/${i(t)}/orders/simulate`;return n.client.post(s,r,o?.signal)}async function ar(n,e,t,r){let o=`/v2/games/${i(n.gameId())}/game-rooms/${i(e)}/transfer/${i(t)}`;return n.client.post(o,void 0,r?.signal)}async function lr(n,e,t,r){let o=`/v2/games/${i(n.gameId())}/game-rooms/${i(e)}`;return n.client.patch(o,t,r?.signal,{...r?.ifMatch===void 0?{}:{ifMatch:r.ifMatch}})}var oe="gem_";var cr=1e4,gr=50,mr=1e3,pr=65536-4*1024,se=n=>typeof n=="number"?n:0,yr=n=>typeof n=="string"?n:"";function ie(){let n=globalThis.crypto;return typeof n?.randomUUID=="function"?n.randomUUID():"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,e=>{let t=Math.floor(Math.random()*16);return (e==="x"?t:t&3|8).toString(16)})}function fr(n){return n?.retryable===true}function hr(n,e){let t=n??{},r=Array.isArray(t.rejected)?t.rejected.map(o=>{let s=o??{};return {index:se(s.index),code:yr(s.code)}}):[];return {accepted:se(t.accepted),rejected:r,dropped:e,duplicate:t.duplicate===true}}function ae(n,e){return {event_uid:n.uid,name:n.name,offset_ms:Math.round(n.atMs)-e,player_id:n.playerId,dimensions:n.dimensions,measures:n.measures}}function le(n){let e=Math.max(1,Math.floor(n.maxQueue??mr)),t={client:n.client,gameId:()=>n.gameId},r=[],o=0,s=null,a=false,l=false,d=false,c=false,g=y=>{n.log?.(y);},b=()=>{s!==null&&(n.clock.clearTimeout(s),s=null);},x=()=>{s!==null||a||l||(s=n.clock.setTimeout(()=>{s=null,v().catch(()=>{});},cr));},f=()=>{let y=Math.min(r.length,100),h=128;for(let w=0;w<y;w+=1){let A=r[w];if(A===void 0)break;if(h+=JSON.stringify(ae(A,0)).length+1,h>pr)return Math.max(1,w)}return y};async function v(y){if(r.length===0)return {accepted:0,rejected:[],dropped:0,duplicate:false};b();let h=r.splice(0,f()),w=o;o=0;let A=Math.round(n.clock.now()),L={batch_id:ie(),sent_at_ms:A,events:h.map(S=>ae(S,A))};l=true;try{let S=await D(t,L,y===void 0?void 0:{signal:y}),P=hr(S,w);for(let be of P.rejected)g(`[gem] analytics: an event was refused (${be.code}). See the analytics_events section of your game config.`);return P}catch(S){if(fr(S))for(r=[...h,...r],o+=w;r.length>e;)r.shift(),o+=1;else g(`[gem] analytics: ${h.length} event(s) were discarded \u2014 the platform refused the batch and will refuse it again: ${String(S)}`);throw S}finally{l=false,r.length>0&&x();}}return {track(y,h,w={}){if(a)return;if(typeof y!="string"||y===""){c||(c=true,g(`[gem] analytics: '${h}' was not recorded \u2014 an event from a server has to name the player it is about. A game-server token names no player, so the platform cannot infer one; pass the id from join() or host.players().`));return}if(h.startsWith(oe)){d||(d=true,g(`[gem] analytics: '${h}' was not recorded \u2014 the gem_ prefix is reserved, and the platform's own events are client-sourced, so a server may not emit one at all. Name your event something else.`));return}let A={},L={};for(let[S,P]of Object.entries(w))typeof P=="string"?A[S]=P:typeof P=="number"&&Number.isFinite(P)&&(L[S]=P);for(;r.length>=e;)r.shift(),o+=1;r.push({uid:ie(),playerId:y,name:h,atMs:n.clock.now(),dimensions:A,measures:L}),r.length>=gr?v().catch(()=>{}):x();},flush:y=>v(y),get pending(){return r.length},dispose(){a=true,b(),r=[],o=0;}}}var _r=new Map([["function_error",false],["function_failed",false],["function_timeout",false],["function_not_published",false],["function_input_too_large",false],["functions_not_configured",false],["forbidden",false],["function_capacity_unavailable",true],["function_host_unreachable",true],["function_host_error",true],["rate_limited",true],["service_unavailable",true]]),I=class extends m{constructor(e,t){super(e.reason,e.status,e.detail,e.retryAfterSeconds,e.code),this.name="GemFunctionError",Object.assign(this,t);}get retryable(){return (this.code===void 0?void 0:_r.get(this.code))??super.retryable}},E=class{#e;constructor(e){this.#e=e;}async invoke(e,t={}){let r=br(e),o;try{o=await this.#e(r,t.signal===void 0?{}:{signal:t.signal});}catch(s){throw s instanceof m?Rr(s):s}return vr(o)}};function br(n){if(n instanceof ArrayBuffer)return new Uint8Array(n);if(ArrayBuffer.isView(n))return new Uint8Array(n.buffer,n.byteOffset,n.byteLength);let e;try{e=JSON.stringify(n);}catch(t){throw new p(`the function input could not be serialised to JSON: ${String(t)}. Pass bytes, or a value JSON can carry. This is a bug in the call, not a server failure.`)}if(e===void 0)throw new p(`the function input is ${typeof n}, which JSON cannot carry. Pass bytes \u2014 an empty Uint8Array for no input \u2014 or a JSON value. This is a bug in the call, not a server failure.`);return new TextEncoder().encode(e)}function vr(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 Rr(n){let{details:e,invocationId:t}=X(n),o=e?.untrusted?.message,s=e?.reason;return new I(n,{...t===void 0?{}:{invocationId:t},...n.code==="function_error"&&typeof o=="string"?{functionMessage:o}:{},...n.code==="function_failed"&&typeof s=="string"?{failure:s}:{}})}var k=n=>typeof n=="string"?n:"",xr=/(?:Z|[+-]\d{2}:?\d{2})$/i;function de(n){let e=k(n);if(!xr.test(e))return 0;let t=Date.parse(e);return Number.isFinite(t)?Math.floor(t/1e3):0}var Sr=/^[0-9a-f]{1,64}$/,kr=/^[0-9a-f]{16}$/,wr=/^[A-Za-z][A-Za-z0-9_+\-/]{0,63}$/,Ar=/^(?:[01]\d|2[0-3]):[0-5]\d$/;function Pr(n){let e=k(n),t=/^(\d{4})-(\d{2})-(\d{2})$/.exec(e);if(!t)return;let[r,o,s]=[Number(t[1]),Number(t[2]),Number(t[3])],a=new Date(Date.UTC(r,o-1,s));return a.getUTCFullYear()===r&&a.getUTCMonth()===o-1&&a.getUTCDate()===s?e:void 0}var Tr=4096,Or=new TextEncoder;function Gr(n){let e=k(n.challenge_data),t=k(n.challenge_data_hash);return e===""||!kr.test(t)?{}:Or.encode(e).length>Tr?{}:{data:e,dataHash:t}}function Er(n){let e=n??{},t=de(e.period_start_at),r=de(e.period_ends_at);if(t===0||r===0)return;let o=k(e.slug),s=k(e.seed),a=Pr(e.period_local_date),l=k(e.boundary),d=k(e.reset_time);return {id:k(e.progression_definition_id),...o===""?{}:{slug:o},window:k(e.window),periodStartAt:t,periodEndsAt:r,...a===void 0?{}:{periodLocalDate:a},boundary:wr.test(l)?l:"",resetTime:Ar.test(d)?d:"",seed:Sr.test(s)?s:"",...Gr(e)}}function ue(n){if(n!==void 0&&(!Number.isInteger(n)||n<0||n>400))throw new TypeError(`periodsBack must be an integer between 0 and 400, got ${String(n)}`)}function ce(n){let e=n??{};return Array.isArray(e.challenges)?e.challenges.map(Er).filter(t=>t!==void 0):[]}function ge(n){return {async list(e){let{playerId:t,periodsBack:r,signal:o}=e??{};if(typeof t!="string"||t==="")throw new TypeError("gem.challenges.list needs { playerId }: a game-server token names no player, so the platform cannot tell whose period you mean. Pass the id from join() or gem.players().");ue(r);let s=await n({player_id:t,...r===void 0?{}:{periods_back:r},...o===void 0?{}:{signal:o}});return ce(s)}}}function Cr(n){let e={};for(let[t,r]of Object.entries(H))if(typeof r=="function"){let o=r;e[t]=(...s)=>o(n,...s);}return e}function F(n,e={}){let t=e.clock??G,r=e.baseUrl??n.apiBaseUrl;if(!r)throw new Error("this runtime names no gem-api host (host.apiBaseUrl is missing). The server image running this bundle predates token delivery \u2014 the bundle cannot call gem-api on it.");let o=N(n,{clock:t,...e.onAuthStateChange===void 0?{}:{onStateChange:e.onAuthStateChange}}),s=Q({baseUrl:r,tokenSource:o.source,defaultQuery:{game_id:n.gameId,channel:n.channel},...e.fetch===void 0?{}:{fetch:e.fetch}}),a=new T({transport:s,clock:t}),l={gameId:n.gameId,channel:n.channel,matchId:n.matchId,...n.gameRoomId===void 0?{}:{gameRoomId:n.gameRoomId}},d=Cr({client:a,gameId:()=>l.gameId}),c=l.gameRoomId,g=n.endMatch,b=n.log,x=le({client:a,clock:t,gameId:l.gameId,...typeof b=="function"?{log:v=>b.call(n,v)}:{}});return {identity:l,client:a,api:d,match:{end:async()=>{if(g===void 0)throw new Error("this runtime cannot end the match: the server image running this bundle predates host.endMatch, and only the platform half holds the allocation proof an end needs.");await g.call(n);}},analytics:x,functions:new E(d.invokeFunction),challenges:ge(d.listChallenges),...c===void 0?{}:{room:{get:v=>d.getGameRoomV2(c,v),args:async v=>{let y=await d.getGameRoomV2(c,v?.signal===void 0?{}:{signal:v.signal}),h=y.modified?y.body:void 0;if(h?.room_args==null||h.room_args_template==null)throw new m("not_found",404,"this room's template declares no room args",void 0,"room_args_not_defined");return {room_args:h.room_args,room_args_template:h.room_args_template}}}},dispose:()=>{x.dispose(),o.dispose();}}}var Ir=["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"],qr=new Set(Ir);function me(n){return typeof n=="string"&&qr.has(n)?n:"unknown"}var R=class{#e;constructor(e){this.#e=e,Object.freeze(this);}toString(){return "[gem: use gem.text.toPlain()]"}toJSON(){return this.toString()}get[Symbol.toStringTag](){return "PlayerText"}static unwrap(e){return e.#e}};function q(n){return new R(n)}var pe={toPlain(n){return R.unwrap(n)},compare(n,e,t){let r=n instanceof R?R.unwrap(n):n,o=e instanceof R?R.unwrap(e):e,s;try{s=new Intl.Collator(t);}catch{s=new Intl.Collator;}return s.compare(r,o)},equals(n,e){let t=n instanceof R?R.unwrap(n):n,r=e instanceof R?R.unwrap(e):e;return t.normalize("NFC")===r.normalize("NFC")}};var ye="the match has not started yet: the runtime hands over the host at `init`, and this was read before that. Read it from `init` or later \u2014 a bundle that needs a value at module scope is reading it one call too early.";function V(n,e={}){let t=e.clock??G,r=()=>{let l=n();if(l===null)throw new Error(ye);return l},o=null,s=()=>{if(o===null)throw new Error(ye);return o};return {server:{get identity(){return s().identity},get client(){return s().client},get api(){return s().api},get match(){return s().match},get analytics(){return s().analytics},get functions(){return s().functions},get challenges(){return s().challenges},get room(){return s().room},dispose(){o?.dispose();},get sizeClass(){return r().sizeClass},get roomArgs(){return r().roomArgs},get roster(){return r().roster},players(){return r().players()},profile(l){let c=r().profile?.(l);if(!c)return null;let g=c.displayName;return typeof g!="string"||g===""?null:{displayName:q(g),...typeof c.displayTag=="string"&&c.displayTag!==""?{displayTag:q(c.displayTag)}:{},...typeof c.discriminator=="string"?{discriminator:c.discriminator}:{}}},playerNumber(l){return r().playerNumber?.(l)},send(l,d,c){c===void 0?r().send(l,d):r().send(l,d,c);},broadcast(l,d){d===void 0?r().broadcast(l):r().broadcast(l,d);},kick(l,d){d===void 0?r().kick(l):r().kick(l,d);},log(l){r().log(l);},warn(l){r().warn(l);}},attach:()=>{o=F(r(),{...e,clock:t});}}}function fe(n,e={}){let{server:t,attach:r}=V(()=>n,e);return r(),t}function Lr(n){if(n===void 0||typeof n.reason!="string"||n.reason==="")return;let e=n.platform_reason??n.endedReason;return {reason:n.reason,...e===void 0?{}:{endedReason:me(e)}}}function he(n,e={}){return ()=>{let t=null,{server:r,attach:o}=V(()=>t,e),s=n(r),a={async init(l){t=l,o(),await s.init?.();},async shutdown(l){let d=Lr(l);try{await s.shutdown?.(d);}finally{r.dispose();}}};return s.join&&(a.join=(l,d)=>s.join?.(l,d)),s.leave&&(a.leave=(l,d)=>s.leave?.(l,d)),s.message&&(a.message=(l,d,c,g)=>s.message?.(l,d,c,g)),a}}var $r=new Set(["unlocked","already_unlocked","suppressed"]);function _e(n){let e=n?.changes;if(!Array.isArray(e))return [];let t=[];for(let r of e){let o=r??{};if(o.type!=="achievement_unlocked"||typeof o.outcome!="string"||!$r.has(o.outcome)||typeof o.achievement_id!="string"||o.achievement_id==="")continue;let s=o.outcome;t.push({achievementId:o.achievement_id,progressionDefinitionId:typeof o.progression_definition_id=="string"?o.progression_definition_id:"",points:s==="unlocked"&&typeof o.points=="number"&&Number.isFinite(o.points)?o.points:0,outcome:s,...typeof o.reason=="string"?{reason:o.reason}:{}});}return t}
2
- export{_ as AuthError,j as CONDITIONAL_HEADERS,E as FunctionsApi,m as GemApiError,T as GemClient,I as GemFunctionError,R as PlayerText,p as TransportRefusal,_e as achievementReceipts,q as asPlayerText,F as createGemServer,re as createHostTokenSource,fe as createMatchServer,he as defineServer,G as systemClock,pe as text,K as toBase64};//# sourceMappingURL=gem-web-sdk.server.js.map
1
+ var ve=Object.defineProperty;var Re=(n,e)=>{for(var t in e)ve(n,t,{get:e[t],enumerable:true});};globalThis.__gemWebSdkVersion="[gem-web-sdk:sdkVersion:10.1.1]";function xe(n,e){return e!==void 0?!e:n==="chain_exhausted"}var $=class{constructor(e){this.options=e;}options;grant=null;state="pending";failure=null;generation=0;inFlight=null;rejected=false;get currentState(){return this.state}get lastFailure(){return this.failure}async get(){if(this.state==="lost")throw new _(this.failure??"unavailable","the session cannot be renewed");let e=this.seconds();if(this.grant&&e<this.grant.expiresAt-this.renewBefore())return this.grant.token;if(this.grant&&e>=this.grant.chainEndsAt)throw this.enter("lost","chain_exhausted"),new _("chain_exhausted","the token chain reached its ceiling");return this.refresh(this.nextReason())}nextReason(){return this.rejected?"rejected":this.grant?"expiring":"initial"}invalidate(e){e!==void 0&&this.grant!==null&&this.grant.token!==e||this.rejected&&this.grant===null||(this.grant=null,this.generation+=1,this.inFlight=null,this.rejected=true,this.state!=="lost"&&this.enter("pending"));}accept(e){this.state!=="lost"&&(this.grant=e,this.rejected=false,this.enter("ready"));}close(e="unavailable"){this.grant=null,this.generation+=1,this.inFlight=null,this.enter("lost",e);}refresh(e){if(this.inFlight)return this.inFlight;let t=this.generation;this.enter("pending");let r=this.options.request(e).then(o=>{if(t!==this.generation)throw new _("internal","token arrived for a superseded generation");return this.grant=o,this.rejected=false,this.enter("ready"),o.token}).catch(o=>{let s=Se(o),i=o?.retryable;throw t===this.generation&&this.enter(xe(s,typeof i=="boolean"?i:void 0)?"lost":"degraded",s),o instanceof _?o:new _(s,String(o))}).finally(()=>{this.inFlight===r&&(this.inFlight=null);});return this.inFlight=r,r}enter(e,t){this.failure=t??(e==="ready"?null:this.failure),this.state!==e&&(this.state=e,this.options.onStateChange?.(e,t));}renewBefore(){return this.options.renewBeforeSeconds??60}seconds(){return Math.floor(this.options.clock.now()/1e3)}},_=class n extends Error{constructor(t,r){super(`auth ${t}: ${r}`);this.reason=t;this.name="AuthError";}reason;static isAuthError(t){if(t instanceof n)return true;let r=t;return r?.name==="AuthError"&&typeof r.reason=="string"}};function Se(n){if(n instanceof _)return n.reason;let e=n?.reason;return typeof e=="string"&&["chain_exhausted","unavailable","timeout","internal"].includes(e)?e:"internal"}var p=class n extends Error{retryable=false;constructor(e){super(e),this.name="TransportRefusal";}static isRefusal(e){if(e instanceof n)return true;let t=e;return t?.name==="TransportRefusal"&&t.retryable===false}},j=["if-match","if-none-match"],W=4096;function ke(n){if(!n)return;let e={};for(let[t,r]of Object.entries(n)){let o=t.toLowerCase();if(!j.includes(o)||r===void 0)continue;let s=typeof r=="string"?we(r):r;if(typeof s!="string"||s.length>W||!Ae(s))throw new p(`the ${o} header value cannot be sent \u2014 it is not a string, is longer than ${W} characters, or contains a character outside the range an HTTP header value may carry. This is a malformed request, not a server failure; the value is withheld here rather than written to logs.`);s!==""&&(e[o]=s);}return Object.freeze(e)}function we(n){let e=o=>o===32||o===9||o===10||o===13,t=0,r=n.length;for(;t<r&&e(n.charCodeAt(t));)t++;for(;r>t&&e(n.charCodeAt(r-1));)r--;return n.slice(t,r)}function Ae(n){for(let e=0;e<n.length;e++){let t=n.charCodeAt(e);if(t!==9&&(t<32||t===127||t>255))return false}return true}function Pe(n){let{bytes:e}=n;if(e!==void 0){if(Object.prototype.toString.call(e)!=="[object Uint8Array]")throw new p("the raw body is not a Uint8Array, so it cannot be sent as bytes. This is a malformed request, not a server failure.");if(n.body!==void 0)throw new p("the request carries both a JSON body and a raw body, and only one can be sent. This is a malformed request, not a server failure.");return new Uint8Array(e)}}function z(n,e){let t=e.replayUnauthorizedOnce??true;return {async request(r){let o={...r},s=ke(o.headers),i=Pe(o),l=Object.freeze({...o,headers:s,...i===void 0?{}:{bytes:i}}),d=await e.tokenSource.get(),c=await n(l,d);if(c.status!==401||!t)return c;e.tokenSource.invalidate(d);let m=await e.tokenSource.get(),b=await n(l,m);if(b.status===401)throw e.tokenSource.close("unavailable"),new _("unavailable","the server refused a freshly minted token");return b}}}function K(n){let e=typeof n=="string"?new TextEncoder().encode(n):n;return btoa(Te(e))}function Te(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,s,i){super(`${t} (${r}): ${o}`);this.reason=t;this.status=r;this.detail=o;this.retryAfterSeconds=s;this.code=i;this.name="GemApiError";}reason;status;detail;retryAfterSeconds;code;get retryable(){return this.reason==="unavailable"||this.reason==="rate_limited"}},J=new WeakMap;function X(n){return J.get(n)??{}}var Oe=new Set([408,429,500,502,503,504]),Ge=6e4;function Ce(n){if(n===void 0)return 2;if(!Number.isInteger(n)||n<0||n>10)throw new p(`maxRetries must be a whole number between 0 and 10; received ${JSON.stringify(n)}. This is a configuration fault, not a server failure.`);return n}var T=class{constructor(e){this.options=e;}options;async get(e,t){return this.send({method:"GET",path:e,signal:t},true)}async getWithEtag(e,t={}){let r=await this.sendRaw({method:"GET",path:e,...t.signal===void 0?{}:{signal:t.signal},...t.ifNoneMatch===void 0?{}:{headers:{"if-none-match":t.ifNoneMatch}}},true),o=r.etag===void 0?{}:{etag:r.etag};return r.status===304?{modified:false,...o}:{modified:true,body:r.body,...o}}async put(e,t,r,o={}){return this.send({method:"PUT",path:e,body:t,signal:r,...E(o)},o.replaySafe===true)}async post(e,t,r,o={}){return this.send({method:"POST",path:e,body:t,signal:r,...E(o)},o.replaySafe===true)}async postBytes(e,t,r,o={}){let s=await this.sendRaw({method:"POST",path:e,bytes:t,responseType:"bytes",signal:r,...E(o)},o.replaySafe===true);return {bytes:Ee(s.body),...s.invocationId===void 0?{}:{invocationId:s.invocationId}}}async patch(e,t,r,o={}){return this.send({method:"PATCH",path:e,body:t,signal:r,...E(o)},o.replaySafe===true)}async delete(e,t,r={}){return this.send({method:"DELETE",path:e,signal:t,...E(r)},r.replaySafe===true)}async send(e,t){return (await this.sendRaw(e,t)).body}async sendRaw(e,t){let r=t?Ce(this.options.maxRetries)+1:1,o=null;if(e.signal?.aborted)throw Y(e.signal);for(let s=0;s<r;s++){if(s>0&&await this.backoff(s,o,e.signal),e.signal?.aborted)throw Y(e.signal);let i;try{i=await this.options.transport.request(e);}catch(d){if(_.isAuthError(d)||p.isRefusal(d)||e.signal?.aborted||Ie(d))throw d;o=new g("unavailable",0,String(d));continue}if(i.status>=200&&i.status<300||i.status===304)return i;let l=qe(i);if(!Oe.has(i.status))throw l;o=l;}throw o??new g("unavailable",0,"no attempt was made")}backoff(e,t,r){if(r?.aborted)return Promise.resolve();let o=t?.retryAfterSeconds,s=o!==void 0?o*1e3:2**(e-1)*250,i=2**(e-1)*250,l=Math.min(Math.max(s,i),Ge);return new Promise(d=>{let c=this.options.clock,m=false,b=false,x,f=()=>{m||(m=true,b&&c.clearTimeout(x),r?.removeEventListener("abort",f),d());};r?.addEventListener("abort",f,{once:true}),x=c.setTimeout(f,l),b=true,m&&c.clearTimeout(x);})}};function Ee(n){if(n instanceof Uint8Array)return n;if(n==null)return new Uint8Array(0);let e=typeof n=="string"?n:JSON.stringify(n);return new TextEncoder().encode(e)}function E(n){return {...n.keepalive===void 0?{}:{keepalive:n.keepalive},...n.ifMatch===void 0?{}:{headers:{"if-match":n.ifMatch}}}}function Y(n){return n.reason!==void 0?n.reason:new DOMException("The operation was aborted.","AbortError")}function Ie(n){let e=n?.name;return e==="AbortError"||e==="TimeoutError"}function qe(n){let e=$e(n),t=Me(n.body),r={...t===void 0?{}:{details:t},...n.invocationId===void 0?{}:{invocationId:n.invocationId}};return Object.keys(r).length>0&&J.set(e,r),e}var Le=new Map([["insufficient_funds","insufficient_funds"]]);function $e(n){let{status:e,body:t}=n,r=je(t),o=n.retryAfterSeconds??Be(t),s=Fe(t),i=s===void 0?void 0:Le.get(s);if(i!==void 0)return new g(i,e,r,void 0,s);switch(e){case 304:return new g("not_modified",e,r);case 400:case 422:return new g("invalid",e,r,void 0,s);case 403:return new g("forbidden",e,r,void 0,s);case 404:return new g("not_found",e,r,void 0,s);case 402:return new g("insufficient_funds",e,r,void 0,s);case 409:return new g("conflict",e,r,void 0,s);case 412:return new g("precondition_failed",e,r,void 0,s);case 413:return new g("too_large",e,r,void 0,s);case 429:return new g("rate_limited",e,r,o,s);default:return new g("unavailable",e,r,o,s)}}function je(n){if(typeof n=="string")return n;let e=n?.message;if(typeof e=="string")return e;let t=n?.error;if(typeof t=="string")return t;let r=t?.message;return typeof r=="string"?r:"no detail"}function Me(n){let t=n?.error?.details;return t===null?void 0:t}function Fe(n){let t=n?.error?.code;return typeof t=="string"&&t.length>0?t:void 0}function Be(n){let e=n?.retryAfterSeconds;return typeof e=="number"&&Number.isFinite(e)&&e>=0?e:void 0}function Ue(n){let e=n.lastIndexOf("@");return (e===-1?n:`***@${n.slice(e+1)}`).slice(0,200)}var Ne=new Set(j);function De(n){if(!n)return {};let e={};for(let[t,r]of Object.entries(n))Ne.has(t.toLowerCase())&&(e[t.toLowerCase()]=r);return e}function Q(n){let e=n.fetch??globalThis.fetch.bind(globalThis);return z(async(t,r)=>{let o;try{o=new URL(n.baseUrl.replace(/\/+$/,""));}catch{throw new p("the configured baseUrl is not a valid URL. Its value is withheld here rather than written to logs. This is a configuration fault, not a server failure.")}let s;try{s=new URL(o.href.replace(/\/+$/,"")+t.path);}catch{throw new p(`${JSON.stringify(typeof t.path=="string"?Ue(t.path):"(a non-string path)")} does not form a valid URL against ${o.protocol}//${o.host}. This is a malformed request, not a server failure.`)}if(s.protocol!==o.protocol||s.host!==o.host)throw new p(`${JSON.stringify(s.pathname)} resolves to ${s.protocol}//${s.host}, not ${o.protocol}//${o.host}. A request path may not change the request's origin \u2014 it carries the play token.`);if(s.username!==""||s.password!==""){let f=o.username!==""||o.password!=="",v=s.username!==o.username||s.password!==o.password,y=f?v?"baseUrl (and possibly the request path)":"baseUrl":"request path";throw new p(`the ${y} puts credentials in the URL, which cannot be fetched (${t.method} ${s.pathname}). The value is withheld here rather than written to logs. This is a malformed request, not a server failure.`)}for(let[f,v]of Object.entries(n.defaultQuery??{}))s.searchParams.has(f)||s.searchParams.set(f,v);let i=t.bytes,l=t.bytes===void 0?void 0:"application/octet-stream";try{t.body!==void 0&&(i=JSON.stringify(t.body),l="application/json");}catch(f){throw new p(`the body of ${t.method} ${JSON.stringify(s.pathname)} could not be serialised to JSON: ${String(f)}. This is a bug in the request, not a server failure \u2014 retrying sends the same unserialisable value.`)}let d=await e(s.toString(),{method:t.method,headers:{authorization:`Bearer ${r}`,...l===void 0?{}:{"content-type":l},...De(t.headers)},body:i,signal:t.signal,...t.keepalive===void 0?{}:{keepalive:t.keepalive},credentials:"omit",mode:"cors",redirect:"error",cache:"no-store",referrerPolicy:"no-referrer"}),c=null;if(t.responseType==="bytes"&&d.status>=200&&d.status<300)c=new Uint8Array(await d.arrayBuffer());else {let f=await d.text();if(f.length>0)try{c=JSON.parse(f);}catch{c=f;}}let m=d.headers.get("etag"),b=He(d.headers.get("retry-after")),x=d.headers.get("x-gem-invocation-id");return {status:d.status,body:c,...m===null?{}:{etag:m},...b===void 0?{}:{retryAfterSeconds:b},...x===null||x===""?{}:{invocationId:x}}},n)}function He(n){if(n===null)return;let e=n.trim();if(!/^\d+$/.test(e))return;let t=Number(e);return Number.isFinite(t)?t:void 0}var Ve="gem-web-bridge";var O=65536,Z=8,M=5e3,ee=1024;function U(n){return Object.freeze(Object.assign(Object.create(null),n))}U({"gem.handshake":30,"gem.handshake.accept":5,"gem.token":30,"gem.token.denied":30,"gem.player":12,"gem.pause":120,"gem.prefs":60,"gem.cohorts":12,"gem.earnAllowanceChanged":30,"gem.viewport":60,"gem.deviceSettings":12,"gem.willTerminate":10,"gem.roomEvent":120,"gem.socketState":12,"gem.seatedEvent":60,"gem.autoStartFailedEvent":30,"gem.signalEvent":1800,"gem.dedicatedEvent":120,"gem.partyResult":30,"gem.clusterTarget":12,"gem.devtools":30,"gem.screenshot":6,"gem.screenshot.denied":12,"gem.requestContext":12,"gem.gameContext":12,"gem.signal":1200,"gem.dedicatedOffer":60,"gem.partyRequest":12,"gem.ready":5,"gem.engaged":5,"gem.progress":600,"gem.requestToken":12,"gem.requestLocalServer":6,"gem.localServer":30,"gem.localServer.denied":30,"gem.exit":5,"gem.openExternal":6,"gem.requestFullscreen":30,"gem.audioState":120,"gem.rewardCue":60,"gem.walletDisplay":60,"gem.menu":60,"gem.menuSelect":60,"gem.requestShare":6,"gem.vibrate":600,"gem.frameStats":120,"gem.portraitBorders":60,"gem.error":60,"gem.requestPurchase":12,"gem.purchaseResult":30,"gem.deviceSettings.put":30,"gem.deviceSettings.result":30,"gem.requestAd":6,"gem.adResult":12,"gem.requestSignIn":6,"gem.signInResult":12,"gem.requestFriendChallenge":12,"gem.friendChallengeResult":30,__malformed:60});U({"gem.requestAd":"ads","gem.adResult":"ads","gem.requestSignIn":"signIn","gem.signInResult":"signIn","gem.requestPurchase":"purchases","gem.purchaseResult":"purchases","gem.requestFriendChallenge":"friendChallenges","gem.friendChallengeResult":"friendChallenges","gem.devtools":"devtools","gem.screenshot":"screenshot","gem.screenshot.denied":"screenshot","gem.requestContext":"feedbackContext","gem.gameContext":"feedbackContext","gem.roomEvent":"rooms","gem.signal":"p2p","gem.signalEvent":"p2p","gem.dedicatedOffer":"dedicated","gem.dedicatedEvent":"dedicated","gem.clusterTarget":"clusterTarget","gem.partyRequest":"parties","gem.partyResult":"parties","gem.autoStartFailedEvent":"autoStartFailure","gem.seatedEvent":"partySeating","gem.socketState":"socketState","gem.audioState":"audioState","gem.rewardCue":"rewardCue","gem.frameStats":"frameStats","gem.portraitBorders":"portraitBorders","gem.engaged":"engagement","gem.viewport":"viewport","gem.walletDisplay":"walletDisplay","gem.requestLocalServer":"localHost","gem.localServer":"localHost","gem.localServer.denied":"localHost","gem.cohorts":"cohorts","gem.earnAllowanceChanged":"earnAllowance","gem.deviceSettings":"deviceSettings","gem.deviceSettings.put":"deviceSettings","gem.deviceSettings.result":"deviceSettings","gem.requestShare":"share","gem.vibrate":"vibration","gem.menu":"gameMenu","gem.menuSelect":"gameMenu"});function ze(n){let e=/^([a-z][a-z0-9+.-]*):\/\/([a-z0-9.-]+|\[[0-9a-f:.]+\])(:([0-9]{1,5}))?$/i.exec(n);return e===null?false:e[4]===void 0||Number(e[4])<=65535}function Ke(n){let e;try{e=new URL(n);}catch{return false}return e.username!==""||e.password!==""?false:e.protocol==="https:"?true:e.protocol==="http:"&&(e.hostname==="localhost"||e.hostname==="127.0.0.1")}function Ye(n){return /^[a-z]{2,8}(-[a-z0-9]{1,8})*$/i.test(n)}function Je(n){return /^[a-z_]+$/.test(n)}function B(n,e,t){if(e>Z)return `nesting deeper than ${Z}`;if(++t.nodes>M)return `more than ${M} values`;if(t.bytes>O)return `over the ${O} byte limit`;if(n==null)return t.bytes+=4,null;let r=typeof n;if(r==="boolean")return t.bytes+=5,null;if(r==="number")return t.bytes+=8,null;if(r==="string")return t.bytes+=n.length*3+2,null;if(r!=="object")return `${r} is not plain data`;let o=n;if(t.seen.has(o))return "a repeated or cyclic object reference";if(t.seen.add(o),Array.isArray(n)){if(n.length>ee)return `an array of ${n.length} entries, over the ${ee} limit`;t.bytes+=2;for(let l of n){let d=B(l,e+1,t);if(d)return d}return null}let s=Object.getPrototypeOf(n);if(s!==Object.prototype&&s!==null)return "a value that is not a plain object";t.bytes+=2;let i=n;for(let l in i){if(!Object.prototype.hasOwnProperty.call(i,l))continue;if(++t.nodes>M)return `more than ${M} values`;if(t.bytes+=l.length*3+4,t.bytes>O)return `over the ${O} byte limit`;let d=B(i[l],e+1,t);if(d)return d}return null}function Xe(n){let e={nodes:0,bytes:0,seen:new Set},t=B(n,0,e);return t?`message contains ${t}`:e.bytes>O?`message is over the ${O} byte limit`:null}var Qe={origin:[ze,"not a well-formed origin"],url:[Ke,"not a safe absolute http(s) URL"],bcp47:[Ye,"not a well-formed BCP 47 tag"],code:[Je,"not a code of lower-case letters and underscores"]};function ne(n,e,t){for(let r of e){let o=t===""?r.n:`${t}.${r.n}`,s=n[r.n];if(s==null){if(r.o)continue;return `${o}: required`}let i=te(s,r,o);if(i)return i}return null}function te(n,e,t){switch(e.k){case "s":{if(typeof n!="string")return `${t}: expected string`;if(n.length>e.max)return `${t}: exceeds ${e.max} characters`;if(e.f){let[r,o]=Qe[e.f];if(!r(n))return `${t}: ${o}`}return null}case "i":return typeof n!="number"||!Number.isInteger(n)?`${t}: expected integer`:n<e.lo||n>e.hi?`${t}: out of range ${e.lo}..${e.hi}`:null;case "b":return typeof n=="boolean"?null:`${t}: expected boolean`;case "e":{let r=e.v;return r.includes(n)?null:`${t}: not one of ${r.join("|")}`}case "o":return typeof n!="object"||n===null||Array.isArray(n)?`${t}: expected object`:ne(n,e.fs,t);case "j":return typeof n!="object"||n===null||Array.isArray(n)?`${t}: expected a plain object`:null;case "a":{if(!Array.isArray(n))return `${t}: expected array`;if(n.length>e.max)return `${t}: exceeds ${e.max} items`;let r=e.it,o=`${t}[]`;for(let s of n){if(s==null){if(r.o)continue;return `${o}: required`}let i=te(s,r,o);if(i)return i}return null}default:{let r=e.k;return `${t}: unknown kind ${String(r)}`}}}function u(n,e){return t=>{let r=Xe(t);if(r)return r;if(typeof t!="object"||t===null||Array.isArray(t))return "message: expected object";let o=t;return o.gem!==Ve?"gem: wrong protocol marker":o.type!==n?`type: expected ${n}`:ne(o,e,"")}}var Ze=u("gem.handshake",[{n:"versions",k:"o",fs:[{n:"min",k:"i",lo:1,hi:1e3},{n:"max",k:"i",lo:1,hi:1e3}]},{n:"capabilities",k:"a",o:1,max:64,it:{n:"",k:"s",max:64}},{n:"embedder",k:"s",max:2048,f:"origin"},{n:"unbidden",k:"b",o:1}]),en=u("gem.handshake.accept",[{n:"v",k:"i",lo:1,hi:1e3},{n:"capabilities",k:"a",o:1,max:64,it:{n:"",k:"s",max:64}}]),nn=u("gem.token",[{n:"token",k:"s",max:4096},{n:"requestId",k:"s",o:1,max:64},{n:"generation",k:"i",lo:0,hi:2147483647},{n:"apiBaseUrl",k:"s",o:1,max:512,f:"url"},{n:"playerId",k:"s",max:64},{n:"gameId",k:"s",max:64},{n:"channel",k:"e",v:["dev","test","release"]},{n:"gameVersion",k:"s",o:1,max:64},{n:"expiresAt",k:"i",lo:0,hi:4102444800},{n:"chainEndsAt",k:"i",lo:0,hi:4102444800},{n:"allowDevTools",k:"b",o:1}]),tn=u("gem.token.denied",[{n:"requestId",k:"s",max:64},{n:"retryable",k:"b"},{n:"retryAfterMs",k:"i",o:1,lo:0,hi:36e5},{n:"reason",k:"e",v:["chain_exhausted","unavailable"]},{n:"correlationId",k:"s",max:64}]),rn=u("gem.player",[{n:"untrusted",k:"o",fs:[{n:"displayName",k:"s",max:64},{n:"displayTag",k:"s",o:1,max:80},{n:"displayHandle",k:"s",max:80}]},{n:"playerId",k:"s",o:1,max:64},{n:"discriminator",k:"s",o:1,max:8},{n:"avatarIconUrl",k:"s",o:1,max:2048,f:"url"},{n:"badges",k:"a",o:1,max:2,it:{n:"",k:"o",fs:[{n:"itemId",k:"s",max:64},{n:"iconUrl",k:"s",max:2048,f:"url"}]}},{n:"displayTag",k:"s",max:8},{n:"avatarUrl",k:"s",o:1,max:2048,f:"url"},{n:"boost",k:"o",o:1,fs:[{n:"multipliers",k:"a",max:8,it:{n:"",k:"o",fs:[{n:"currencyId",k:"s",max:64},{n:"currencySlug",k:"s",max:32},{n:"multiplierBp",k:"i",lo:1e4,hi:1e6}]}},{n:"expiresInDays",k:"i",o:1,lo:1,hi:7}]}]),on=u("gem.pause",[{n:"paused",k:"b"}]),sn=u("gem.prefs",[{n:"reducedMotion",k:"b"},{n:"muted",k:"b"},{n:"showFrameStats",k:"b",o:1},{n:"locale",k:"s",max:35,f:"bcp47"},{n:"recommended",k:"o",o:1,fs:[{n:"volume",k:"i",lo:0,hi:100},{n:"batterySaver",k:"b"},{n:"keyboardLayout",k:"e",v:["wasd","arrows"]},{n:"gamepadConfirm",k:"e",v:["south","east"]},{n:"vibration",k:"b"}]}]),an=u("gem.cohorts",[{n:"cohorts",k:"a",max:8,it:{n:"",k:"o",fs:[{n:"experimentId",k:"s",max:36},{n:"variantKey",k:"s",max:32}]}}]),ln=u("gem.earnAllowanceChanged",[]),dn=u("gem.viewport",[{n:"insets",k:"o",fs:[{n:"top",k:"i",lo:0,hi:4096},{n:"right",k:"i",lo:0,hi:4096},{n:"bottom",k:"i",lo:0,hi:4096},{n:"left",k:"i",lo:0,hi:4096}]},{n:"reserved",k:"a",o:1,max:4,it:{n:"",k:"o",fs:[{n:"x",k:"i",lo:0,hi:16384},{n:"y",k:"i",lo:0,hi:16384},{n:"width",k:"i",lo:0,hi:16384},{n:"height",k:"i",lo:0,hi:16384}]}}]),un=u("gem.deviceSettings",[{n:"settings",k:"j",o:1}]),cn=u("gem.willTerminate",[{n:"reason",k:"e",v:["grant_expiring","session_ended","navigating","kill_switch"]},{n:"graceMs",k:"i",lo:0,hi:6e4}]),mn=u("gem.roomEvent",[{n:"event",k:"e",v:["updated","match_started","match_ready","match_failed","version_stale"]},{n:"roomId",k:"s",max:64},{n:"matchId",k:"s",o:1,max:64},{n:"version",k:"i",o:1,lo:0,hi:2147483647},{n:"reason",k:"s",o:1,max:64},{n:"platform",k:"e",o:1,v:["universal","mobile"]}]),gn=u("gem.socketState",[{n:"connected",k:"b"},{n:"reason",k:"e",o:1,v:["connecting","dropped","watchdog","terminal"]}]),pn=u("gem.seatedEvent",[{n:"roomId",k:"s",max:64}]),yn=u("gem.autoStartFailedEvent",[{n:"roomId",k:"s",max:64},{n:"code",k:"s",max:64}]),fn=u("gem.signalEvent",[{n:"event",k:"e",v:["hello","offer","answer","ice","peerJoined","peerLeft","migration","matchEnded","error"]},{n:"matchId",k:"s",max:64},{n:"data",k:"j"}]),hn=u("gem.dedicatedEvent",[{n:"event",k:"e",v:["answer","error","matchEnded"]},{n:"matchId",k:"s",max:64},{n:"sdp",k:"s",o:1,max:10240},{n:"sessionId",k:"s",o:1,max:64},{n:"code",k:"s",o:1,max:64},{n:"message",k:"s",o:1,max:256},{n:"reason",k:"s",o:1,max:64}]),_n=u("gem.partyResult",[{n:"requestId",k:"s",max:64},{n:"partyId",k:"s",o:1,max:64}]),bn=u("gem.clusterTarget",[{n:"clusterTargetId",k:"s",max:64},{n:"clusterTargetIds",k:"a",o:1,max:3,it:{n:"",k:"s",max:64}}]),vn=u("gem.devtools",[{n:"action",k:"e",v:["open","close","toggle"]}]),Rn=u("gem.screenshot",[{n:"maxWidth",k:"i",lo:1,hi:7680},{n:"maxHeight",k:"i",lo:1,hi:4320}]),xn=u("gem.screenshot.denied",[{n:"reason",k:"e",v:["not_wired","no_source","unsupported","unreadable","tainted","too_large","busy","declined","failed"]},{n:"retryable",k:"b"}]),Sn=u("gem.requestContext",[]),kn=u("gem.gameContext",[{n:"context",k:"j"}]),wn=u("gem.signal",[{n:"signal",k:"e",v:["join","offer","answer","ice","migrationAck","hostUnreachable"]},{n:"matchId",k:"s",max:64},{n:"data",k:"j"}]),An=u("gem.dedicatedOffer",[{n:"matchId",k:"s",max:64},{n:"sdp",k:"s",max:10240},{n:"intent",k:"e",v:["initial","ice_restart","full_reconnect"]}]),Pn=u("gem.partyRequest",[{n:"requestId",k:"s",max:64}]),Tn=u("gem.ready",[]),On=u("gem.engaged",[]),Gn=u("gem.progress",[{n:"loaded",k:"i",lo:0,hi:1099511627776},{n:"total",k:"i",lo:0,hi:1099511627776}]),Cn=u("gem.requestToken",[{n:"requestId",k:"s",max:64},{n:"reason",k:"e",v:["initial","expiring","rejected"]}]),En=u("gem.requestLocalServer",[{n:"requestId",k:"s",max:64},{n:"gameRoomId",k:"s",max:64}]),In=u("gem.localServer",[{n:"requestId",k:"s",max:64},{n:"serverId",k:"s",o:1,max:128}]),qn=u("gem.localServer.denied",[{n:"requestId",k:"s",max:64},{n:"retryable",k:"b"},{n:"reason",k:"e",v:["refused","unavailable"]}]),Ln=u("gem.exit",[{n:"reason",k:"s",o:1,max:64}]),$n=u("gem.openExternal",[{n:"url",k:"s",max:2048,f:"url"}]),jn=u("gem.requestFullscreen",[{n:"enabled",k:"b"}]),Mn=u("gem.audioState",[{n:"muted",k:"b"}]),Fn=u("gem.rewardCue",[{n:"currencySlug",k:"s",max:32},{n:"expected",k:"i",o:1,lo:1,hi:1e9},{n:"origin",k:"o",o:1,fs:[{n:"x",k:"i",lo:0,hi:16384},{n:"y",k:"i",lo:0,hi:16384}]}]),Bn=u("gem.walletDisplay",[{n:"visible",k:"b"},{n:"currencies",k:"a",o:1,max:8,it:{n:"",k:"s",max:64}},{n:"score",k:"b",o:1}]),Un=u("gem.menu",[{n:"settings",k:"b"},{n:"items",k:"a",o:1,max:4,it:{n:"",k:"o",fs:[{n:"id",k:"s",max:32},{n:"label",k:"s",max:40}]}}]),Nn=u("gem.menuSelect",[{n:"entry",k:"e",v:["settings","item"]},{n:"id",k:"s",o:1,max:32}]),Dn=u("gem.requestShare",[{n:"params",k:"a",max:16,it:{n:"",k:"o",fs:[{n:"key",k:"s",max:64},{n:"value",k:"s",max:512}]}}]),Hn=u("gem.vibrate",[{n:"pattern",k:"a",max:99,it:{n:"",k:"i",lo:0,hi:1e4}}]),Vn=u("gem.frameStats",[{n:"fps",k:"i",lo:0,hi:1e3},{n:"frameTimeP95Ms",k:"i",lo:0,hi:1e5}]),Wn=u("gem.portraitBorders",[{n:"name",k:"s",o:1,max:40}]),zn=u("gem.error",[{n:"code",k:"e",v:["version_mismatch","handshake_timeout","handshake_duplicate","invalid_message","rate_limited","token_unavailable","unsupported","unsupported_capability","internal"]},{n:"message",k:"s",o:1,max:256}]),Kn=u("gem.requestPurchase",[{n:"requestId",k:"s",max:64},{n:"purchaseKind",k:"e",v:["item","recipe"]},{n:"targetId",k:"s",max:64},{n:"currencySlug",k:"s",max:32},{n:"quantity",k:"i",o:1,lo:1,hi:10},{n:"catalogId",k:"s",o:1,max:64}]),Yn=u("gem.purchaseResult",[{n:"requestId",k:"s",max:64},{n:"outcome",k:"e",v:["ok","declined","unavailable"]},{n:"reason",k:"s",o:1,max:64,f:"code"},{n:"purchaseId",k:"s",o:1,max:64}]),Jn=u("gem.deviceSettings.put",[{n:"requestId",k:"s",max:64},{n:"settings",k:"j"}]),Xn=u("gem.deviceSettings.result",[{n:"requestId",k:"s",max:64},{n:"outcome",k:"e",v:["stored","too_large","unavailable"]}]),Qn=u("gem.requestAd",[{n:"requestId",k:"s",max:64},{n:"placement",k:"s",max:32},{n:"format",k:"e",v:["interstitial","rewarded"]}]),Zn=u("gem.adResult",[{n:"requestId",k:"s",max:64},{n:"outcome",k:"e",v:["shown","no_ad","unavailable"]}]),et=u("gem.requestSignIn",[{n:"requestId",k:"s",max:64}]),nt=u("gem.signInResult",[{n:"requestId",k:"s",max:64},{n:"outcome",k:"e",v:["signed_in","declined","unavailable"]}]),tt=u("gem.requestFriendChallenge",[{n:"requestId",k:"s",max:64},{n:"playerId",k:"s",max:64},{n:"template",k:"s",max:64},{n:"params",k:"j",o:1}]),rt=u("gem.friendChallengeResult",[{n:"requestId",k:"s",max:64},{n:"outcome",k:"e",v:["accepted","cancelled","refused","unavailable","rate_limited","invalid"]},{n:"code",k:"s",o:1,max:64},{n:"param",k:"s",o:1,max:64},{n:"channel",k:"s",o:1,max:16},{n:"configVersion",k:"i",o:1,lo:0,hi:9007199254740991},{n:"retryAfterMs",k:"i",o:1,lo:0,hi:864e5},{n:"detail",k:"s",o:1,max:300}]);U({"gem.handshake":Ze,"gem.handshake.accept":en,"gem.token":nn,"gem.token.denied":tn,"gem.player":rn,"gem.pause":on,"gem.prefs":sn,"gem.cohorts":an,"gem.earnAllowanceChanged":ln,"gem.viewport":dn,"gem.deviceSettings":un,"gem.willTerminate":cn,"gem.roomEvent":mn,"gem.socketState":gn,"gem.seatedEvent":pn,"gem.autoStartFailedEvent":yn,"gem.signalEvent":fn,"gem.dedicatedEvent":hn,"gem.partyResult":_n,"gem.clusterTarget":bn,"gem.devtools":vn,"gem.screenshot":Rn,"gem.screenshot.denied":xn,"gem.requestContext":Sn,"gem.gameContext":kn,"gem.signal":wn,"gem.dedicatedOffer":An,"gem.partyRequest":Pn,"gem.ready":Tn,"gem.engaged":On,"gem.progress":Gn,"gem.requestToken":Cn,"gem.requestLocalServer":En,"gem.localServer":In,"gem.localServer.denied":qn,"gem.exit":Ln,"gem.openExternal":$n,"gem.requestFullscreen":jn,"gem.audioState":Mn,"gem.rewardCue":Fn,"gem.walletDisplay":Bn,"gem.menu":Un,"gem.menuSelect":Nn,"gem.requestShare":Dn,"gem.vibrate":Hn,"gem.frameStats":Vn,"gem.portraitBorders":Wn,"gem.error":zn,"gem.requestPurchase":Kn,"gem.purchaseResult":Yn,"gem.deviceSettings.put":Jn,"gem.deviceSettings.result":Xn,"gem.requestAd":Qn,"gem.adResult":Zn,"gem.requestSignIn":et,"gem.signInResult":nt,"gem.requestFriendChallenge":tt,"gem.friendChallengeResult":rt});var G={now:()=>Date.now(),setTimeout:(n,e)=>setTimeout(n,e),clearTimeout:n=>clearTimeout(n)};var ot=1e4;function re(n,e){return N(n,e)}function N(n,e){if(typeof n.serverToken!="function"||typeof n.onServerToken!="function")throw new Error("this runtime delivers no game-server token: host.serverToken/onServerToken are missing. The server image running this bundle predates token delivery \u2014 the bundle cannot call gem-api on it.");let t=i=>({token:i.token,expiresAt:i.expiresAt,chainEndsAt:Number.POSITIVE_INFINITY}),r=null,o=new $({clock:e.clock,...e.onStateChange===void 0?{}:{onStateChange:e.onStateChange},request:()=>new Promise((i,l)=>{let d=e.clock.setTimeout(()=>{r=null,l({reason:"unavailable",retryable:true});},e.timeoutMs??ot);r={resolve:c=>{e.clock.clearTimeout(d),i(c);},reject:l,timer:d};})}),s=n.onServerToken(i=>{let l=t(i),d=r;if(d){r=null,d.resolve(l);return}o.accept(l);});return {source:o,dispose(){s(),r&&(e.clock.clearTimeout(r.timer),r.reject({reason:"unavailable",retryable:false}),r=null);}}}var H={};Re(H,{acceptTransfer:()=>st,addEntityProgression:()=>at,adminAction:()=>it,cancelInventoryTransfer:()=>lt,claimEntityProgressionRewards:()=>dt,closeGameRoom:()=>ut,createEntityBatchOrder:()=>ct,createEntityOrder:()=>mt,createSession:()=>gt,deleteEntityGameSetting:()=>pt,deleteEntitySave:()=>yt,deleteSession:()=>ft,deleteShowcaseValue:()=>ht,executeEntityRecipe:()=>_t,finalizeSaveUpload:()=>bt,getChannelAssignment:()=>vt,getDropRates:()=>Rt,getEntityCurrency:()=>xt,getEntityGameSetting:()=>St,getEntityInventory:()=>kt,getEntityInventoryItem:()=>wt,getEntityLeaderboard:()=>At,getEntityOrder:()=>Pt,getEntityProgression:()=>Tt,getEntityRecipeAvailability:()=>Ot,getEntityRecipeUsage:()=>Gt,getEntitySave:()=>Ct,getEvent:()=>Et,getGameRoomV2:()=>It,getLeaderboard:()=>qt,getPlayerGameProfile:()=>Lt,getPurchaseCatalog:()=>$t,getResolvedTemplate:()=>jt,getRoomArgs:()=>Mt,getShowcaseValue:()=>Ft,getTransferDetails:()=>Bt,ingestAnalyticsEvents:()=>D,initiateInventoryTransfer:()=>Ut,invokeFunction:()=>Nt,kickPlayer:()=>Dt,listChallenges:()=>Ht,listEntityGameSettings:()=>Vt,listEntityOrders:()=>Wt,listEntityProgressions:()=>zt,listEntitySaves:()=>Kt,listEvents:()=>Yt,listGameRooms:()=>Jt,listResolvedTemplates:()=>Xt,listTransfers:()=>Qt,maxEntityProgression:()=>Zt,putEntityGameSetting:()=>er,putRoomArgs:()=>nr,putShowcaseValue:()=>tr,rejectTransfer:()=>rr,requestSaveUploadUrl:()=>or,resetEntityProgression:()=>sr,simulateEntityOrder:()=>ar,transferHostV2:()=>ir,updateGameRoomV2:()=>lr});function a(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 st(n,e,t){let r=`/v1/inventory/transfers/${a(e)}/accept`;return n.client.post(r,void 0,t?.signal)}async function at(n,e,t,r,o,s){let i=`/v1/inventory/${a(e)}/${a(t)}/progressions/${a(r)}/add`;return n.client.post(i,o,s?.signal)}async function it(n,e,t,r){let o=`/v1/voice/sessions/${a(e)}/admin`;return n.client.post(o,t,r?.signal)}async function lt(n,e,t){let r=`/v1/inventory/transfers/${a(e)}/cancel`;return n.client.post(r,void 0,t?.signal)}async function dt(n,e,t,r,o,s){let i=`/v1/inventory/${a(e)}/${a(t)}/progressions/${a(r)}/claim`;return n.client.post(i,o,s?.signal)}async function ut(n,e,t){let r=`/v1/games/${a(n.gameId())}/game-rooms/${a(e)}`;return n.client.delete(r,t?.signal)}async function ct(n,e,t,r,o){let s=`/v1/inventory/${a(e)}/${a(t)}/orders/batch`;return n.client.post(s,r,o?.signal,{...o?.ifMatch===void 0?{}:{ifMatch:o.ifMatch}})}async function mt(n,e,t,r,o){let s=`/v1/inventory/${a(e)}/${a(t)}/orders`;return n.client.post(s,r,o?.signal,{...o?.ifMatch===void 0?{}:{ifMatch:o.ifMatch}})}async function gt(n,e,t){return n.client.post("/v1/voice/sessions",e,t?.signal)}async function pt(n,e,t,r,o){let s=`/v1/settings/${a(e)}/${a(t)}/${a(r)}`;return n.client.delete(s,o?.signal)}async function yt(n,e,t,r,o){let s=`/v1/saves/${a(e)}/${a(t)}/${a(r)}`;return n.client.delete(s,o?.signal)}async function ft(n,e,t){let r=`/v1/voice/sessions/${a(e)}`;return n.client.delete(r,t?.signal)}async function ht(n,e,t,r){let o=`/v1/showcase/players/${a(e)}/${a(t)}`;return n.client.delete(o,r?.signal)}async function _t(n,e,t,r,o){let s=`/v1/inventory/${a(e)}/${a(t)}/recipes/execute`;return n.client.post(s,r,o?.signal,{...o?.ifMatch===void 0?{}:{ifMatch:o.ifMatch}})}async function bt(n,e,t,r,o,s){let i=`/v1/saves/${a(e)}/${a(t)}/${a(r)}/finalize`;return n.client.post(i,o,s?.signal)}async function vt(n,e,t){let r=`/v1/games/${a(n.gameId())}/config/channels/${a(e)}`;return n.client.getWithEtag(r,{...t?.signal===void 0?{}:{signal:t.signal},...t?.ifNoneMatch===void 0?{}:{ifNoneMatch:t.ifNoneMatch}})}async function Rt(n,e,t){let r=`/v1/inventory/loot-tables/${a(e)}/drop-rates`;return n.client.get(r,t?.signal)}async function xt(n,e,t,r,o){let s=`/v1/inventory/${a(e)}/${a(t)}/currencies/${a(r)}`;return n.client.get(s,o?.signal)}async function St(n,e,t,r,o){let s=`/v1/settings/${a(e)}/${a(t)}/${a(r)}`;return n.client.getWithEtag(s,{...o?.signal===void 0?{}:{signal:o.signal},...o?.ifNoneMatch===void 0?{}:{ifNoneMatch:o.ifNoneMatch}})}async function kt(n,e,t,r){let o=new URLSearchParams;r?.include_buckets!==void 0&&o.set("include_buckets",String(r?.include_buckets)),r?.include_custom_data!==void 0&&o.set("include_custom_data",String(r?.include_custom_data)),r?.currency_limit!==void 0&&o.set("currency_limit",String(r?.currency_limit)),r?.currency_cursor!==void 0&&o.set("currency_cursor",String(r?.currency_cursor)),r?.item_limit!==void 0&&o.set("item_limit",String(r?.item_limit)),r?.item_cursor!==void 0&&o.set("item_cursor",String(r?.item_cursor)),r?.progression_limit!==void 0&&o.set("progression_limit",String(r?.progression_limit)),r?.progression_cursor!==void 0&&o.set("progression_cursor",String(r?.progression_cursor));let s=o.toString(),i=`/v1/inventory/${a(e)}/${a(t)}`+(s?`?${s}`:"");return n.client.get(i,r?.signal)}async function wt(n,e,t,r,o){let s=`/v1/inventory/${a(e)}/${a(t)}/items/${a(r)}`;return n.client.get(s,o?.signal)}async function At(n,e,t,r,o){let s=new URLSearchParams;o?.bucket_1!==void 0&&s.set("bucket_1",String(o?.bucket_1)),o?.bucket_2!==void 0&&s.set("bucket_2",String(o?.bucket_2)),o?.limit!==void 0&&s.set("limit",String(o?.limit)),o?.periods_back!==void 0&&s.set("periods_back",String(o?.periods_back)),o?.period!==void 0&&s.set("period",String(o?.period)),o?.player_id!==void 0&&s.set("player_id",String(o?.player_id));let i=s.toString(),l=`/v1/leaderboards/${a(e)}/${a(t)}/${a(r)}`+(i?`?${i}`:"");return n.client.get(l,o?.signal)}async function Pt(n,e,t,r,o){let s=`/v1/inventory/${a(e)}/${a(t)}/orders/${a(r)}`;return n.client.get(s,o?.signal)}async function Tt(n,e,t,r,o){let s=`/v1/inventory/${a(e)}/${a(t)}/progressions/${a(r)}`;return n.client.get(s,o?.signal)}async function Ot(n,e,t,r,o,s){let i=`/v1/inventory/${a(e)}/${a(t)}/catalogs/${a(r)}/recipes/${a(o)}/availability`;return n.client.get(i,s?.signal)}async function Gt(n,e,t,r){let o=new URLSearchParams;r?.limit!==void 0&&o.set("limit",String(r?.limit));let s=o.toString(),i=`/v1/inventory/${a(e)}/${a(t)}/recipe-usage`+(s?`?${s}`:"");return n.client.get(i,r?.signal)}async function Ct(n,e,t,r,o){let s=`/v1/saves/${a(e)}/${a(t)}/${a(r)}`;return n.client.getWithEtag(s,{...o?.signal===void 0?{}:{signal:o.signal},...o?.ifNoneMatch===void 0?{}:{ifNoneMatch:o.ifNoneMatch}})}async function Et(n,e,t){let r=`/v1/events/${a(e)}`;return n.client.get(r,t?.signal)}async function It(n,e,t){let r=`/v2/games/${a(n.gameId())}/game-rooms/${a(e)}`;return n.client.getWithEtag(r,{...t?.signal===void 0?{}:{signal:t.signal},...t?.ifNoneMatch===void 0?{}:{ifNoneMatch:t.ifNoneMatch}})}async function qt(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(),s=`/v1/leaderboards/${a(e)}`+(o?`?${o}`:"");return n.client.get(s,t?.signal)}async function Lt(n,e,t){let r=`/v1/profiles/players/${a(e)}`;return n.client.get(r,t?.signal)}async function $t(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 jt(n,e,t){let r=`/v1/game-room-templates/${a(e)}`;return n.client.get(r,t?.signal)}async function Mt(n,e,t){let r=`/v1/games/${a(n.gameId())}/game-rooms/${a(e)}/room-args`;return n.client.get(r,t?.signal)}async function Ft(n,e,t,r){let o=`/v1/showcase/players/${a(e)}/${a(t)}`;return n.client.get(o,r?.signal)}async function Bt(n,e,t){let r=`/v1/inventory/transfers/${a(e)}`;return n.client.get(r,t?.signal)}async function D(n,e,t){let r=`/v1/games/${a(n.gameId())}/analytics/events`;return n.client.post(r,e,t?.signal,{replaySafe:true})}async function Ut(n,e,t){return n.client.post("/v1/inventory/transfers",e,t?.signal)}async function Nt(n,e,t){return n.client.postBytes("/v1/functions/invoke",e,t?.signal)}async function Dt(n,e,t,r){let o=`/v1/games/${a(n.gameId())}/game-rooms/${a(e)}/kick/${a(t)}`;return n.client.post(o,void 0,r?.signal)}async function Ht(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 Vt(n,e,t,r){let o=`/v1/settings/${a(e)}/${a(t)}`;return n.client.get(o,r?.signal)}async function Wt(n,e,t,r){let o=new URLSearchParams;r?.limit!==void 0&&o.set("limit",String(r?.limit)),r?.cursor!==void 0&&o.set("cursor",String(r?.cursor));let s=o.toString(),i=`/v1/inventory/${a(e)}/${a(t)}/orders`+(s?`?${s}`:"");return n.client.get(i,r?.signal)}async function zt(n,e,t,r){let o=`/v1/inventory/${a(e)}/${a(t)}/progressions`;return n.client.get(o,r?.signal)}async function Kt(n,e,t,r){let o=new URLSearchParams;r?.limit!==void 0&&o.set("limit",String(r?.limit)),r?.cursor!==void 0&&o.set("cursor",String(r?.cursor));let s=o.toString(),i=`/v1/saves/${a(e)}/${a(t)}`+(s?`?${s}`:"");return n.client.get(i,r?.signal)}async function Yt(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 Jt(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/${a(n.gameId())}/game-rooms`+(r?`?${r}`:"");return n.client.get(o,e?.signal)}async function Xt(n,e){return n.client.get("/v1/game-room-templates",e?.signal)}async function Qt(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 Zt(n,e,t,r,o,s){let i=`/v1/inventory/${a(e)}/${a(t)}/progressions/${a(r)}/max`;return n.client.post(i,o,s?.signal)}async function er(n,e,t,r,o,s){let i=`/v1/settings/${a(e)}/${a(t)}/${a(r)}`;return n.client.put(i,o,s?.signal,{...s?.ifMatch===void 0?{}:{ifMatch:s.ifMatch}})}async function nr(n,e,t,r){let o=`/v1/games/${a(n.gameId())}/game-rooms/${a(e)}/room-args`;return n.client.put(o,t,r?.signal)}async function tr(n,e,t,r,o){let s=`/v1/showcase/players/${a(e)}/${a(t)}`;return n.client.put(s,r,o?.signal)}async function rr(n,e,t){let r=`/v1/inventory/transfers/${a(e)}/reject`;return n.client.post(r,void 0,t?.signal)}async function or(n,e,t,r,o,s){let i=`/v1/saves/${a(e)}/${a(t)}/${a(r)}/upload-url`;return n.client.post(i,o,s?.signal,{replaySafe:true})}async function sr(n,e,t,r,o,s){let i=`/v1/inventory/${a(e)}/${a(t)}/progressions/${a(r)}/reset`;return n.client.post(i,o,s?.signal)}async function ar(n,e,t,r,o){let s=`/v1/inventory/${a(e)}/${a(t)}/orders/simulate`;return n.client.post(s,r,o?.signal)}async function ir(n,e,t,r){let o=`/v2/games/${a(n.gameId())}/game-rooms/${a(e)}/transfer/${a(t)}`;return n.client.post(o,void 0,r?.signal)}async function lr(n,e,t,r){let o=`/v2/games/${a(n.gameId())}/game-rooms/${a(e)}`;return n.client.patch(o,t,r?.signal,{...r?.ifMatch===void 0?{}:{ifMatch:r.ifMatch}})}var oe="gem_";var cr=1e4,mr=50,gr=1e3,pr=65536-4*1024,se=n=>typeof n=="number"?n:0,yr=n=>typeof n=="string"?n:"";function ae(){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 fr(n){return n?.retryable===true}function hr(n,e){let t=n??{},r=Array.isArray(t.rejected)?t.rejected.map(o=>{let s=o??{};return {index:se(s.index),code:yr(s.code)}}):[];return {accepted:se(t.accepted),rejected:r,dropped:e,duplicate:t.duplicate===true}}function ie(n,e){return {event_uid:n.uid,name:n.name,offset_ms:Math.round(n.atMs)-e,player_id:n.playerId,dimensions:n.dimensions,measures:n.measures}}function le(n){let e=Math.max(1,Math.floor(n.maxQueue??gr)),t={client:n.client,gameId:()=>n.gameId},r=[],o=0,s=null,i=false,l=false,d=false,c=false,m=y=>{n.log?.(y);},b=()=>{s!==null&&(n.clock.clearTimeout(s),s=null);},x=()=>{s!==null||i||l||(s=n.clock.setTimeout(()=>{s=null,v().catch(()=>{});},cr));},f=()=>{let y=Math.min(r.length,100),h=128;for(let w=0;w<y;w+=1){let A=r[w];if(A===void 0)break;if(h+=JSON.stringify(ie(A,0)).length+1,h>pr)return Math.max(1,w)}return y};async function v(y){if(r.length===0)return {accepted:0,rejected:[],dropped:0,duplicate:false};b();let h=r.splice(0,f()),w=o;o=0;let A=Math.round(n.clock.now()),L={batch_id:ae(),sent_at_ms:A,events:h.map(S=>ie(S,A))};l=true;try{let S=await D(t,L,y===void 0?void 0:{signal:y}),P=hr(S,w);for(let be of P.rejected)m(`[gem] analytics: an event was refused (${be.code}). See the analytics_events section of your game config.`);return P}catch(S){if(fr(S))for(r=[...h,...r],o+=w;r.length>e;)r.shift(),o+=1;else m(`[gem] analytics: ${h.length} event(s) were discarded \u2014 the platform refused the batch and will refuse it again: ${String(S)}`);throw S}finally{l=false,r.length>0&&x();}}return {track(y,h,w={}){if(i)return;if(typeof y!="string"||y===""){c||(c=true,m(`[gem] analytics: '${h}' was not recorded \u2014 an event from a server has to name the player it is about. A game-server token names no player, so the platform cannot infer one; pass the id from join() or host.players().`));return}if(h.startsWith(oe)){d||(d=true,m(`[gem] analytics: '${h}' was not recorded \u2014 the gem_ prefix is reserved, and the platform's own events are client-sourced, so a server may not emit one at all. Name your event something else.`));return}let A={},L={};for(let[S,P]of Object.entries(w))typeof P=="string"?A[S]=P:typeof P=="number"&&Number.isFinite(P)&&(L[S]=P);for(;r.length>=e;)r.shift(),o+=1;r.push({uid:ae(),playerId:y,name:h,atMs:n.clock.now(),dimensions:A,measures:L}),r.length>=mr?v().catch(()=>{}):x();},flush:y=>v(y),get pending(){return r.length},dispose(){i=true,b(),r=[],o=0;}}}var _r=new Map([["function_error",false],["function_failed",false],["function_timeout",false],["function_not_published",false],["function_input_too_large",false],["functions_not_configured",false],["forbidden",false],["function_capacity_unavailable",true],["function_host_unreachable",true],["function_host_error",true],["rate_limited",true],["service_unavailable",true]]),I=class extends g{constructor(e,t){super(e.reason,e.status,e.detail,e.retryAfterSeconds,e.code),this.name="GemFunctionError",Object.assign(this,t);}get retryable(){return (this.code===void 0?void 0:_r.get(this.code))??super.retryable}},C=class{#e;constructor(e){this.#e=e;}async invoke(e,t={}){let r=br(e),o;try{o=await this.#e(r,t.signal===void 0?{}:{signal:t.signal});}catch(s){throw s instanceof g?Rr(s):s}return vr(o)}};function br(n){if(n instanceof ArrayBuffer)return new Uint8Array(n);if(ArrayBuffer.isView(n))return new Uint8Array(n.buffer,n.byteOffset,n.byteLength);let e;try{e=JSON.stringify(n);}catch(t){throw new p(`the function input could not be serialised to JSON: ${String(t)}. Pass bytes, or a value JSON can carry. This is a bug in the call, not a server failure.`)}if(e===void 0)throw new p(`the function input is ${typeof n}, which JSON cannot carry. Pass bytes \u2014 an empty Uint8Array for no input \u2014 or a JSON value. This is a bug in the call, not a server failure.`);return new TextEncoder().encode(e)}function vr(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 Rr(n){let{details:e,invocationId:t}=X(n),o=e?.untrusted?.message,s=e?.reason;return new I(n,{...t===void 0?{}:{invocationId:t},...n.code==="function_error"&&typeof o=="string"?{functionMessage:o}:{},...n.code==="function_failed"&&typeof s=="string"?{failure:s}:{}})}var k=n=>typeof n=="string"?n:"",xr=/(?:Z|[+-]\d{2}:?\d{2})$/i;function de(n){let e=k(n);if(!xr.test(e))return 0;let t=Date.parse(e);return Number.isFinite(t)?Math.floor(t/1e3):0}var Sr=/^[0-9a-f]{1,64}$/,kr=/^[0-9a-f]{16}$/,wr=/^[A-Za-z][A-Za-z0-9_+\-/]{0,63}$/,Ar=/^(?:[01]\d|2[0-3]):[0-5]\d$/;function Pr(n){let e=k(n),t=/^(\d{4})-(\d{2})-(\d{2})$/.exec(e);if(!t)return;let[r,o,s]=[Number(t[1]),Number(t[2]),Number(t[3])],i=new Date(Date.UTC(r,o-1,s));return i.getUTCFullYear()===r&&i.getUTCMonth()===o-1&&i.getUTCDate()===s?e:void 0}var Tr=4096,Or=new TextEncoder;function Gr(n){let e=k(n.challenge_data),t=k(n.challenge_data_hash);return e===""||!kr.test(t)?{}:Or.encode(e).length>Tr?{}:{data:e,dataHash:t}}function Cr(n){let e=n??{},t=de(e.period_start_at),r=de(e.period_ends_at);if(t===0||r===0)return;let o=k(e.slug),s=k(e.seed),i=Pr(e.period_local_date),l=k(e.boundary),d=k(e.reset_time);return {id:k(e.progression_definition_id),...o===""?{}:{slug:o},window:k(e.window),periodStartAt:t,periodEndsAt:r,...i===void 0?{}:{periodLocalDate:i},boundary:wr.test(l)?l:"",resetTime:Ar.test(d)?d:"",seed:Sr.test(s)?s:"",...Gr(e)}}function ue(n){if(n!==void 0&&(!Number.isInteger(n)||n<0||n>400))throw new TypeError(`periodsBack must be an integer between 0 and 400, got ${String(n)}`)}function ce(n){let e=n??{};return Array.isArray(e.challenges)?e.challenges.map(Cr).filter(t=>t!==void 0):[]}function me(n){return {async list(e){let{playerId:t,periodsBack:r,signal:o}=e??{};if(typeof t!="string"||t==="")throw new TypeError("gem.challenges.list needs { playerId }: a game-server token names no player, so the platform cannot tell whose period you mean. Pass the id from join() or gem.players().");ue(r);let s=await n({player_id:t,...r===void 0?{}:{periods_back:r},...o===void 0?{}:{signal:o}});return ce(s)}}}function Er(n){let e={};for(let[t,r]of Object.entries(H))if(typeof r=="function"){let o=r;e[t]=(...s)=>o(n,...s);}return e}function F(n,e={}){let t=e.clock??G,r=e.baseUrl??n.apiBaseUrl;if(!r)throw new Error("this runtime names no gem-api host (host.apiBaseUrl is missing). The server image running this bundle predates token delivery \u2014 the bundle cannot call gem-api on it.");let o=N(n,{clock:t,...e.onAuthStateChange===void 0?{}:{onStateChange:e.onAuthStateChange}}),s=Q({baseUrl:r,tokenSource:o.source,defaultQuery:{game_id:n.gameId,channel:n.channel},...e.fetch===void 0?{}:{fetch:e.fetch}}),i=new T({transport:s,clock:t}),l={gameId:n.gameId,channel:n.channel,matchId:n.matchId,...n.gameRoomId===void 0?{}:{gameRoomId:n.gameRoomId}},d=Er({client:i,gameId:()=>l.gameId}),c=l.gameRoomId,m=n.endMatch,b=n.log,x=le({client:i,clock:t,gameId:l.gameId,...typeof b=="function"?{log:v=>b.call(n,v)}:{}});return {identity:l,client:i,api:d,match:{end:async()=>{if(m===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 m.call(n);}},analytics:x,functions:new C(d.invokeFunction),challenges:me(d.listChallenges),...c===void 0?{}:{room:{get:v=>d.getGameRoomV2(c,v),args:async v=>{let y=await d.getGameRoomV2(c,v?.signal===void 0?{}:{signal:v.signal}),h=y.modified?y.body:void 0;if(h?.room_args==null||h.room_args_template==null)throw new g("not_found",404,"this room's template declares no room args",void 0,"room_args_not_defined");return {room_args:h.room_args,room_args_template:h.room_args_template}}}},dispose:()=>{x.dispose(),o.dispose();}}}var Ir=["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"],qr=new Set(Ir);function ge(n){return typeof n=="string"&&qr.has(n)?n:"unknown"}var R=class{#e;constructor(e){this.#e=e,Object.freeze(this);}toString(){return "[gem: use gem.text.toPlain()]"}toJSON(){return this.toString()}get[Symbol.toStringTag](){return "PlayerText"}static unwrap(e){return e.#e}};function q(n){return new R(n)}var pe={toPlain(n){return R.unwrap(n)},compare(n,e,t){let r=n instanceof R?R.unwrap(n):n,o=e instanceof R?R.unwrap(e):e,s;try{s=new Intl.Collator(t);}catch{s=new Intl.Collator;}return s.compare(r,o)},equals(n,e){let t=n instanceof R?R.unwrap(n):n,r=e instanceof R?R.unwrap(e):e;return t.normalize("NFC")===r.normalize("NFC")}};var ye="the match has not started yet: the runtime hands over the host at `init`, and this was read before that. Read it from `init` or later \u2014 a bundle that needs a value at module scope is reading it one call too early.";function V(n,e={}){let t=e.clock??G,r=()=>{let l=n();if(l===null)throw new Error(ye);return l},o=null,s=()=>{if(o===null)throw new Error(ye);return o};return {server:{get identity(){return s().identity},get client(){return s().client},get api(){return s().api},get match(){return s().match},get analytics(){return s().analytics},get functions(){return s().functions},get challenges(){return s().challenges},get room(){return s().room},dispose(){o?.dispose();},get sizeClass(){return r().sizeClass},get roomArgs(){return r().roomArgs},get roster(){return r().roster},players(){return r().players()},profile(l){let c=r().profile?.(l);if(!c)return null;let m=c.displayName;return typeof m!="string"||m===""?null:{displayName:q(m),...typeof c.displayTag=="string"&&c.displayTag!==""?{displayTag:q(c.displayTag)}:{},...typeof c.discriminator=="string"?{discriminator:c.discriminator}:{}}},playerNumber(l){return r().playerNumber?.(l)},send(l,d,c){c===void 0?r().send(l,d):r().send(l,d,c);},broadcast(l,d){d===void 0?r().broadcast(l):r().broadcast(l,d);},kick(l,d){d===void 0?r().kick(l):r().kick(l,d);},log(l){r().log(l);},warn(l){r().warn(l);}},attach:()=>{o=F(r(),{...e,clock:t});}}}function fe(n,e={}){let{server:t,attach:r}=V(()=>n,e);return r(),t}function Lr(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:ge(e)}}}function he(n,e={}){return ()=>{let t=null,{server:r,attach:o}=V(()=>t,e),s=n(r),i={async init(l){t=l,o(),await s.init?.();},async shutdown(l){let d=Lr(l);try{await s.shutdown?.(d);}finally{r.dispose();}}};return s.join&&(i.join=(l,d)=>s.join?.(l,d)),s.leave&&(i.leave=(l,d)=>s.leave?.(l,d)),s.message&&(i.message=(l,d,c,m)=>s.message?.(l,d,c,m)),i}}var $r=new Set(["unlocked","already_unlocked","suppressed"]);function _e(n){let e=n?.changes;if(!Array.isArray(e))return [];let t=[];for(let r of e){let o=r??{};if(o.type!=="achievement_unlocked"||typeof o.outcome!="string"||!$r.has(o.outcome)||typeof o.achievement_id!="string"||o.achievement_id==="")continue;let s=o.outcome;t.push({achievementId:o.achievement_id,progressionDefinitionId:typeof o.progression_definition_id=="string"?o.progression_definition_id:"",points:s==="unlocked"&&typeof o.points=="number"&&Number.isFinite(o.points)?o.points:0,outcome:s,...typeof o.reason=="string"?{reason:o.reason}:{}});}return t}
2
+ export{_ as AuthError,j as CONDITIONAL_HEADERS,C as FunctionsApi,g as GemApiError,T as GemClient,I as GemFunctionError,R as PlayerText,p as TransportRefusal,_e as achievementReceipts,q as asPlayerText,F as createGemServer,re as createHostTokenSource,fe as createMatchServer,he as defineServer,G as systemClock,pe as text,K as toBase64};//# sourceMappingURL=gem-web-sdk.server.js.map
3
3
  //# sourceMappingURL=gem-web-sdk.server.js.map
package/dist/index.d.ts CHANGED
@@ -160,6 +160,13 @@ interface GemPrefs {
160
160
  readonly muted: boolean;
161
161
  readonly showFrameStats?: boolean;
162
162
  readonly locale: string;
163
+ readonly recommended?: {
164
+ volume: number;
165
+ batterySaver: boolean;
166
+ keyboardLayout: "wasd" | "arrows";
167
+ gamepadConfirm: "south" | "east";
168
+ vibration: boolean;
169
+ };
163
170
  }
164
171
  interface GemCohorts {
165
172
  readonly gem: typeof PROTOCOL;
@@ -844,6 +851,13 @@ declare class GemHost {
844
851
  muted: boolean;
845
852
  locale: string;
846
853
  showFrameStats?: boolean;
854
+ recommended?: {
855
+ volume: number;
856
+ batterySaver: boolean;
857
+ keyboardLayout: "wasd" | "arrows";
858
+ gamepadConfirm: "south" | "east";
859
+ vibration: boolean;
860
+ };
847
861
  }): void;
848
862
  sendCohorts(cohorts: ReadonlyArray<{
849
863
  experimentId: string;
package/dist/sdk.d.ts CHANGED
@@ -2024,6 +2024,13 @@ interface GemPrefs$1 {
2024
2024
  readonly muted: boolean;
2025
2025
  readonly showFrameStats?: boolean;
2026
2026
  readonly locale: string;
2027
+ readonly recommended?: {
2028
+ volume: number;
2029
+ batterySaver: boolean;
2030
+ keyboardLayout: "wasd" | "arrows";
2031
+ gamepadConfirm: "south" | "east";
2032
+ vibration: boolean;
2033
+ };
2027
2034
  }
2028
2035
  interface GemCohorts$1 {
2029
2036
  readonly gem: typeof PROTOCOL;
@@ -4436,6 +4443,14 @@ interface GemPrefs {
4436
4443
  readonly muted: boolean;
4437
4444
  readonly showFrameStats: boolean;
4438
4445
  readonly locale: string;
4446
+ readonly recommended: GemRecommendedSettings | null;
4447
+ }
4448
+ interface GemRecommendedSettings {
4449
+ readonly volume: number;
4450
+ readonly batterySaver: boolean;
4451
+ readonly keyboardLayout: "wasd" | "arrows";
4452
+ readonly gamepadConfirm: "south" | "east";
4453
+ readonly vibration: boolean;
4439
4454
  }
4440
4455
  interface GemCohort {
4441
4456
  readonly experimentId: string;
@@ -4538,4 +4553,4 @@ interface ExitAnalytics {
4538
4553
  }
4539
4554
  declare function leaveAndExit(rooms: ExitRooms, bridge: ExitBridge | null, reason?: string, analytics?: ExitAnalytics): Promise<void>;
4540
4555
  declare function createGem(options?: GemOptions): Gem;
4541
- export { ARCADE_EMBEDDERS, type AccountApi, type AdFormat, type AdOutcome, type AdOutcomeKind, type AdRequest, type AdsApi, AnalyticsApi, type AnalyticsFlushOptions, type AnalyticsFlushResult, type AnalyticsOptions, type AnalyticsRejection$1 as AnalyticsRejection, type AnalyticsValue, AuthError, type AuthFailure, type AuthState, type Base64String, type BootMark, type BootTimeline, type BroadcastOptions, type BytesResponse, CONDITIONAL_HEADERS, type Challenge, type ChallengeWindow, ChallengesApi, type ClientOptions, type Clock, type ConditionalRequestHeaders, type ConfiguredPurchasePayment, type ConfiguredPurchaseRequest, type ConfiguredPurchaseResult, DEVICE_SETTINGS_MAX_BYTES, DedicatedServerError, type DedicatedServerFailure, type DedicatedServerSession, type DevToolsOpener, type DeviceSettings, type DeviceSettingsApi, type DeviceSettingsPutOutcome, type DirectPurchaseRequest, type DirectPurchaseResult, type EarnAllowance, type EarnAllowanceEvent, type EarnAllowancePeriod, type EarnAllowanceReadOptions, type EntityLeaderboard, type EntityLeaderboardEntry, type EntityLeaderboardOptions, type EntityType$1 as EntityType, type ExitAnalytics, type ExitBridge, type ExitRooms, type FrameState, type Friend, type FriendChallenge, FriendChallengeError, type FriendChallengeErrorCode, type FriendChallengeOutcome, type FriendChallengeOutcomeKind, type FriendChallengeRequest, type FriendChallengesPage, FriendsApi, type FriendsPage, type FunctionFailure, type FunctionInvokeOptions, type FunctionResult, FunctionsApi, type GameApi, type GameConfig, type GameMenu, type GameMenuItem, type GameServerLink, type Gem, GemApiError, GemClient, type GemCohort, type GemCohorts, GemConfigError, type GemDevTools, type GemErrorReason, GemFrame, GemFunctionError, type GemIdentity, type GemInsets, type GemMatchApi, type GemMatchServer, type GemMatchServerModule, type GemOptions, type GemPlayer, type GemPrefs, type GemReservedArea, GemSaveError, type GemServer, type GemServerBundle, type GemServerFactory, type GemServerHost, type GemServerHostProfile, type GemServerIdentity, type GemServerLifecycle, type GemServerOptions, type GemServerProfile, type GemTerminationNotice, GemUnframedError, type GemViewport, type GetLeaderboardOptions, type HostTokenSource, type HostTokenSourceOptions, type JoinWelcome, type Leaderboard, type LeaderboardEntry, type LeaderboardPeriod, LeaderboardsApi, type ListChallengesOptions, type ListFriendChallengesOptions, type ListFriendsOptions, MAX_PERIODS_BACK, type MatchConnectOptions, type MatchConnection, type MatchHosting, type MatchHostingMode, type MatchServeOptions, type MatchTransport, type MessageMeta, type MultiTransportSession, PLATFORM_EVENTS, type PeriodOptions, PlatformApi, PlatformCurrenciesApi, type PlatformCurrency, type PlatformCurrencyAccess, type PlatformCurrencyPurchasePayment, type PlatformCurrencyPurchaseRequest, type PlatformCurrencyPurchaseResult, type PlatformCurrencyReadOptions, PlatformEarnAllowanceApi, type PlatformEventName, type PlayerBadge$1 as PlayerBadge, type PlayerBoost, type PlayerBoostMultiplier, type PlayerIdentity, type PlayerProfile, PlayerText, type ProfileCallOptions, type ProfileShowcaseEntry$1 as ProfileShowcaseEntry, ProfilesApi, type PurchaseApi, type PurchaseOptions, type PurchaseOutcome, PurchaseRefusal, type PurchaseRefusalCode, type PurchaseRequest, type PutBytesOptions, type PutSaveOptions, type RankedRow, type RecipeAvailability, type RecipeLock, type RequestOptions, type RewardCue, type RewardedStatus, type RoomArgValue, type SavePage, type SaveRecord, type SendOptions$1 as SendOptions, type ServerApi, type ServerBundleHost, type ServerTokenGrant, type SessionEndReason, type ShareApi, type ShareRequest, ShowcaseApi, type ShowcaseCallOptions, type ShowcaseFriendEntry, type ShowcaseFriends, type ShowcaseValue, type SignInOutcome, type SignInOutcomeKind, type SnapshotCurrency, type SnapshotItem, type TokenGrant, type Transport, type TransportAdvert, type TransportKind, TransportRefusal, type TransportRequest, type TransportResponse, UNRELIABLE_CHANNEL_LABEL, type VersionedGetOptions, type VersionedResponse, type VibrationApi, type WalletVisibleOptions, asPlayerText, createBootTimeline, createGem, createGemServer, createHostTokenSource, createMatchServer, defineServer, leaveAndExit, mapIdentity, markOnResolve, platformIconUrl, presentJoinCredential, readTemplateTransports, readTransportAdvert, reportOnResolve, systemClock, text, toBase64, webTransportAvailable };
4556
+ export { ARCADE_EMBEDDERS, type AccountApi, type AdFormat, type AdOutcome, type AdOutcomeKind, type AdRequest, type AdsApi, AnalyticsApi, type AnalyticsFlushOptions, type AnalyticsFlushResult, type AnalyticsOptions, type AnalyticsRejection$1 as AnalyticsRejection, type AnalyticsValue, AuthError, type AuthFailure, type AuthState, type Base64String, type BootMark, type BootTimeline, type BroadcastOptions, type BytesResponse, CONDITIONAL_HEADERS, type Challenge, type ChallengeWindow, ChallengesApi, type ClientOptions, type Clock, type ConditionalRequestHeaders, type ConfiguredPurchasePayment, type ConfiguredPurchaseRequest, type ConfiguredPurchaseResult, DEVICE_SETTINGS_MAX_BYTES, DedicatedServerError, type DedicatedServerFailure, type DedicatedServerSession, type DevToolsOpener, type DeviceSettings, type DeviceSettingsApi, type DeviceSettingsPutOutcome, type DirectPurchaseRequest, type DirectPurchaseResult, type EarnAllowance, type EarnAllowanceEvent, type EarnAllowancePeriod, type EarnAllowanceReadOptions, type EntityLeaderboard, type EntityLeaderboardEntry, type EntityLeaderboardOptions, type EntityType$1 as EntityType, type ExitAnalytics, type ExitBridge, type ExitRooms, type FrameState, type Friend, type FriendChallenge, FriendChallengeError, type FriendChallengeErrorCode, type FriendChallengeOutcome, type FriendChallengeOutcomeKind, type FriendChallengeRequest, type FriendChallengesPage, FriendsApi, type FriendsPage, type FunctionFailure, type FunctionInvokeOptions, type FunctionResult, FunctionsApi, type GameApi, type GameConfig, type GameMenu, type GameMenuItem, type GameServerLink, type Gem, GemApiError, GemClient, type GemCohort, type GemCohorts, GemConfigError, type GemDevTools, type GemErrorReason, GemFrame, GemFunctionError, type GemIdentity, type GemInsets, type GemMatchApi, type GemMatchServer, type GemMatchServerModule, type GemOptions, type GemPlayer, type GemPrefs, type GemRecommendedSettings, type GemReservedArea, GemSaveError, type GemServer, type GemServerBundle, type GemServerFactory, type GemServerHost, type GemServerHostProfile, type GemServerIdentity, type GemServerLifecycle, type GemServerOptions, type GemServerProfile, type GemTerminationNotice, GemUnframedError, type GemViewport, type GetLeaderboardOptions, type HostTokenSource, type HostTokenSourceOptions, type JoinWelcome, type Leaderboard, type LeaderboardEntry, type LeaderboardPeriod, LeaderboardsApi, type ListChallengesOptions, type ListFriendChallengesOptions, type ListFriendsOptions, MAX_PERIODS_BACK, type MatchConnectOptions, type MatchConnection, type MatchHosting, type MatchHostingMode, type MatchServeOptions, type MatchTransport, type MessageMeta, type MultiTransportSession, PLATFORM_EVENTS, type PeriodOptions, PlatformApi, PlatformCurrenciesApi, type PlatformCurrency, type PlatformCurrencyAccess, type PlatformCurrencyPurchasePayment, type PlatformCurrencyPurchaseRequest, type PlatformCurrencyPurchaseResult, type PlatformCurrencyReadOptions, PlatformEarnAllowanceApi, type PlatformEventName, type PlayerBadge$1 as PlayerBadge, type PlayerBoost, type PlayerBoostMultiplier, type PlayerIdentity, type PlayerProfile, PlayerText, type ProfileCallOptions, type ProfileShowcaseEntry$1 as ProfileShowcaseEntry, ProfilesApi, type PurchaseApi, type PurchaseOptions, type PurchaseOutcome, PurchaseRefusal, type PurchaseRefusalCode, type PurchaseRequest, type PutBytesOptions, type PutSaveOptions, type RankedRow, type RecipeAvailability, type RecipeLock, type RequestOptions, type RewardCue, type RewardedStatus, type RoomArgValue, type SavePage, type SaveRecord, type SendOptions$1 as SendOptions, type ServerApi, type ServerBundleHost, type ServerTokenGrant, type SessionEndReason, type ShareApi, type ShareRequest, ShowcaseApi, type ShowcaseCallOptions, type ShowcaseFriendEntry, type ShowcaseFriends, type ShowcaseValue, type SignInOutcome, type SignInOutcomeKind, type SnapshotCurrency, type SnapshotItem, type TokenGrant, type Transport, type TransportAdvert, type TransportKind, TransportRefusal, type TransportRequest, type TransportResponse, UNRELIABLE_CHANNEL_LABEL, type VersionedGetOptions, type VersionedResponse, type VibrationApi, type WalletVisibleOptions, asPlayerText, createBootTimeline, createGem, createGemServer, createHostTokenSource, createMatchServer, defineServer, leaveAndExit, mapIdentity, markOnResolve, platformIconUrl, presentJoinCredential, readTemplateTransports, readTransportAdvert, reportOnResolve, systemClock, text, toBase64, webTransportAvailable };
@@ -1,6 +1,6 @@
1
1
  # The browser surface — API reference
2
2
 
3
- Generated from `@indiegems/gem-web-sdk/sdk` v10.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` v10.1.1, the version of the package this file ships in. Every symbol below carries an explicit anchor, its `anchor` in `reference.json` beside this file.
4
4
 
5
5
  `@indiegems/gem-web-sdk/sdk` is the one import a game writes, wherever its code runs. `@indiegems/gem-web-sdk/game` exports exactly the symbols on this page and nothing else, for a build that wants only this half.
6
6
 
@@ -6733,6 +6733,10 @@ checklist.
6733
6733
  here so the two agree, and see [Gem.reportMuted](#gem-reportmuted) for the other
6734
6734
  direction.
6735
6735
 
6736
+ **`recommended` changing is advice changing.** Apply it only to a setting
6737
+ the player has not chosen in your game; never overwrite their own choice
6738
+ with it.
6739
+
6736
6740
  <a id="gemoptions-oncohorts"></a>
6737
6741
 
6738
6742
  ## GemOptions.onCohorts
@@ -7175,6 +7179,10 @@ not for your game — respecting them is part of what a game must do.
7175
7179
  They can change mid-session, so read them when you need them rather than
7176
7180
  caching at boot.
7177
7181
 
7182
+ `recommended` is the exception: the player's Arcade-wide defaults, which
7183
+ your game may start its own settings from or ignore — never a reason to
7184
+ overwrite a choice the player made in your game.
7185
+
7178
7186
  **Guides.** [what-a-game-must-do](../what-a-game-must-do.md)
7179
7187
 
7180
7188
  <a id="gemprefs-reducedmotion"></a>
@@ -7227,6 +7235,100 @@ Use it to pick your game's language, and pass it to
7227
7235
  [text.compare](#text-compare) when sorting names — that call has no other way to
7228
7236
  learn a locale.
7229
7237
 
7238
+ <a id="gemprefs-recommended"></a>
7239
+
7240
+ ## GemPrefs.recommended
7241
+
7242
+ ```ts
7243
+ readonly recommended: GemRecommendedSettings | null
7244
+ ```
7245
+
7246
+ The player's Arcade-wide defaults for this device — a volume, battery
7247
+ saver, a keyboard layout, the gamepad's confirm button and vibration — or
7248
+ `null` when the Arcade did not send them.
7249
+
7250
+ **Recommendations only; the player's own choice in your game wins.** Start
7251
+ a setting from here while the player has made no choice of their own for
7252
+ it, and never overwrite one they made because this changed:
7253
+
7254
+ ```js
7255
+ const saved = gem.deviceSettings.current ?? {};
7256
+ const volume = saved.volume ?? gem.prefs?.recommended?.volume ?? 100;
7257
+ ```
7258
+
7259
+ Unlike `muted` and `reducedMotion`, nothing here is applied for you, and
7260
+ nothing obliges you to use it. See the guide's "Game settings" section.
7261
+
7262
+ <a id="gemrecommendedsettings"></a>
7263
+
7264
+ ## GemRecommendedSettings
7265
+
7266
+ ```ts
7267
+ interface GemRecommendedSettings
7268
+ ```
7269
+
7270
+ The player's Arcade-wide defaults for this device, as `gem.prefs.recommended`.
7271
+
7272
+ The player sets these once in the Arcade's Settings, and every game that
7273
+ reads them starts in the right place. They are advice: a game may ignore
7274
+ them, and a choice the player made in your game always beats them.
7275
+
7276
+ **Guides.** [what-a-game-must-do](../what-a-game-must-do.md)
7277
+
7278
+ <a id="gemrecommendedsettings-volume"></a>
7279
+
7280
+ ## GemRecommendedSettings.volume
7281
+
7282
+ ```ts
7283
+ readonly volume: number
7284
+ ```
7285
+
7286
+ The volume the player wants, as a percentage from 0 to 100. A level, not a
7287
+ mute — `gem.prefs.muted` is the mute.
7288
+
7289
+ <a id="gemrecommendedsettings-batterysaver"></a>
7290
+
7291
+ ## GemRecommendedSettings.batterySaver
7292
+
7293
+ ```ts
7294
+ readonly batterySaver: boolean
7295
+ ```
7296
+
7297
+ The player asked games to save power on this device: a lower frame rate,
7298
+ fewer effects, a lower resolution.
7299
+
7300
+ <a id="gemrecommendedsettings-keyboardlayout"></a>
7301
+
7302
+ ## GemRecommendedSettings.keyboardLayout
7303
+
7304
+ ```ts
7305
+ readonly keyboardLayout: "wasd" | "arrows"
7306
+ ```
7307
+
7308
+ Which keys the player expects to move with: `'wasd'` or `'arrows'`.
7309
+
7310
+ <a id="gemrecommendedsettings-gamepadconfirm"></a>
7311
+
7312
+ ## GemRecommendedSettings.gamepadConfirm
7313
+
7314
+ ```ts
7315
+ readonly gamepadConfirm: "south" | "east"
7316
+ ```
7317
+
7318
+ Which gamepad face button the player expects to confirm with, by position:
7319
+ `'south'` (the bottom button, A on an Xbox controller) or `'east'` (the
7320
+ right one, B on an Xbox controller). The other one goes back.
7321
+
7322
+ <a id="gemrecommendedsettings-vibration"></a>
7323
+
7324
+ ## GemRecommendedSettings.vibration
7325
+
7326
+ ```ts
7327
+ readonly vibration: boolean
7328
+ ```
7329
+
7330
+ Whether the player wants vibration and controller rumble.
7331
+
7230
7332
  <a id="gemcohort"></a>
7231
7333
 
7232
7334
  ## GemCohort
@@ -7536,8 +7638,10 @@ What your game adds to the arcade's menu — see `gem.setMenu`.
7536
7638
  readonly onSettings?: () => void
7537
7639
  ```
7538
7640
 
7539
- Open your settings screen. Give this and the arcade's menu gains a
7540
- Settings entry that calls it; leave it out and there is no such entry.
7641
+ Open your settings screen. Another embedder may show a Settings entry that
7642
+ calls it, but **the Gem Arcade no longer does**: draw a settings button of
7643
+ your own, always (top-right is the recommendation). Passing this is still
7644
+ accepted and harmless.
7541
7645
 
7542
7646
  <a id="gamemenu-items"></a>
7543
7647
 
@@ -8484,25 +8588,21 @@ for one: the arcade takes every figure from the platform. If this returns
8484
8588
  setMenu(menu: GameMenu): boolean
8485
8589
  ```
8486
8590
 
8487
- Put your settings, and up to four entries of your own, in the arcade's
8488
- menu. The arcade keeps one menu button over your game, in the top-right
8489
- corner: it is how a player leaves, mutes, goes fullscreen and reports a
8490
- problem — and, once you call this, how they open **your** settings.
8591
+ Put up to four entries of your own in the arcade's menu. The arcade keeps
8592
+ one menu button over your game: it is how a player leaves, mutes, goes
8593
+ fullscreen, reports a problem and changes their Arcade-wide settings.
8491
8594
 
8492
8595
  ```js
8493
- const inArcadeMenu = gem.setMenu({
8494
- onSettings: () => settingsScreen.open(),
8596
+ gem.setMenu({
8495
8597
  items: [{ id: 'how-to-play', label: t('How to play'), onSelect: () => help.open() }],
8496
8598
  });
8497
- ownSettingsButton.hidden = inArcadeMenu;
8498
8599
  ```
8499
8600
 
8500
- **Do not draw a settings button of your own while this returns `true`** —
8501
- the arcade's menu is the one place a player looks, in every game. Draw
8502
- your own only when it returns `false` once the bridge has settled
8503
- (`await gem.awaitBridge()`): an embedder with no menu, or no embedder at
8504
- all. The top-left corner is yours, for a back or home button that moves
8505
- around inside your game.
8601
+ **Your settings are not in it: draw your own settings button, always** —
8602
+ top-right is the recommendation. `onSettings` is still accepted, and
8603
+ another embedder may show an entry for it, but the Gem Arcade no longer
8604
+ shows a Settings entry, so a game whose settings open only from there has
8605
+ none a player can reach.
8506
8606
 
8507
8607
  **It is screen state, not a toggle.** Each call is the whole answer and
8508
8608
  replaces the last, so call it again when the entries change — a new
@@ -1,6 +1,6 @@
1
1
  # The server surface — API reference
2
2
 
3
- Generated from `@indiegems/gem-web-sdk/sdk` v10.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` v10.1.1, the version of the package this file ships in. Every symbol below carries an explicit anchor, its `anchor` in `reference.json` beside this file.
4
4
 
5
5
  `@indiegems/gem-web-sdk/sdk` is the one import a game writes, wherever its code runs. `@indiegems/gem-web-sdk/server` exports exactly the symbols on this page and nothing else, for a build that wants only this half.
6
6