@indiegems/gem-web-sdk 7.7.0 → 7.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,3 +1,3 @@
1
- var ve=Object.defineProperty;var Re=(n,e)=>{for(var t in e)ve(n,t,{get:e[t],enumerable:true});};globalThis.__gemWebSdkVersion="[gem-web-sdk:sdkVersion:7.7.0]";function xe(n,e){return e!==void 0?!e:n==="chain_exhausted"}var $=class{constructor(e){this.options=e;}options;grant=null;state="pending";failure=null;generation=0;inFlight=null;rejected=false;get currentState(){return this.state}get lastFailure(){return this.failure}async get(){if(this.state==="lost")throw new _(this.failure??"unavailable","the session cannot be renewed");let e=this.seconds();if(this.grant&&e<this.grant.expiresAt-this.renewBefore())return this.grant.token;if(this.grant&&e>=this.grant.chainEndsAt)throw this.enter("lost","chain_exhausted"),new _("chain_exhausted","the token chain reached its ceiling");return this.refresh(this.nextReason())}nextReason(){return this.rejected?"rejected":this.grant?"expiring":"initial"}invalidate(e){e!==void 0&&this.grant!==null&&this.grant.token!==e||this.rejected&&this.grant===null||(this.grant=null,this.generation+=1,this.inFlight=null,this.rejected=true,this.state!=="lost"&&this.enter("pending"));}accept(e){this.state!=="lost"&&(this.grant=e,this.rejected=false,this.enter("ready"));}close(e="unavailable"){this.grant=null,this.generation+=1,this.inFlight=null,this.enter("lost",e);}refresh(e){if(this.inFlight)return this.inFlight;let t=this.generation;this.enter("pending");let r=this.options.request(e).then(o=>{if(t!==this.generation)throw new _("internal","token arrived for a superseded generation");return this.grant=o,this.rejected=false,this.enter("ready"),o.token}).catch(o=>{let s=Se(o),a=o?.retryable;throw t===this.generation&&this.enter(xe(s,typeof a=="boolean"?a:void 0)?"lost":"degraded",s),o instanceof _?o:new _(s,String(o))}).finally(()=>{this.inFlight===r&&(this.inFlight=null);});return this.inFlight=r,r}enter(e,t){this.failure=t??(e==="ready"?null:this.failure),this.state!==e&&(this.state=e,this.options.onStateChange?.(e,t));}renewBefore(){return this.options.renewBeforeSeconds??60}seconds(){return Math.floor(this.options.clock.now()/1e3)}},_=class n extends Error{constructor(t,r){super(`auth ${t}: ${r}`);this.reason=t;this.name="AuthError";}reason;static isAuthError(t){if(t instanceof n)return true;let r=t;return r?.name==="AuthError"&&typeof r.reason=="string"}};function Se(n){if(n instanceof _)return n.reason;let e=n?.reason;return typeof e=="string"&&["chain_exhausted","unavailable","timeout","internal"].includes(e)?e:"internal"}var p=class n extends Error{retryable=false;constructor(e){super(e),this.name="TransportRefusal";}static isRefusal(e){if(e instanceof n)return true;let t=e;return t?.name==="TransportRefusal"&&t.retryable===false}},j=["if-match","if-none-match"],W=4096;function ke(n){if(!n)return;let e={};for(let[t,r]of Object.entries(n)){let o=t.toLowerCase();if(!j.includes(o)||r===void 0)continue;let s=typeof r=="string"?we(r):r;if(typeof s!="string"||s.length>W||!Ae(s))throw new p(`the ${o} header value cannot be sent \u2014 it is not a string, is longer than ${W} characters, or contains a character outside the range an HTTP header value may carry. This is a malformed request, not a server failure; the value is withheld here rather than written to logs.`);s!==""&&(e[o]=s);}return Object.freeze(e)}function we(n){let e=o=>o===32||o===9||o===10||o===13,t=0,r=n.length;for(;t<r&&e(n.charCodeAt(t));)t++;for(;r>t&&e(n.charCodeAt(r-1));)r--;return n.slice(t,r)}function Ae(n){for(let e=0;e<n.length;e++){let t=n.charCodeAt(e);if(t!==9&&(t<32||t===127||t>255))return false}return true}function Te(n){let{bytes:e}=n;if(e!==void 0){if(Object.prototype.toString.call(e)!=="[object Uint8Array]")throw new p("the raw body is not a Uint8Array, so it cannot be sent as bytes. This is a malformed request, not a server failure.");if(n.body!==void 0)throw new p("the request carries both a JSON body and a raw body, and only one can be sent. This is a malformed request, not a server failure.");return new Uint8Array(e)}}function z(n,e){let t=e.replayUnauthorizedOnce??true;return {async request(r){let o={...r},s=ke(o.headers),a=Te(o),l=Object.freeze({...o,headers:s,...a===void 0?{}:{bytes:a}}),d=await e.tokenSource.get(),c=await n(l,d);if(c.status!==401||!t)return c;e.tokenSource.invalidate(d);let g=await e.tokenSource.get(),b=await n(l,g);if(b.status===401)throw e.tokenSource.close("unavailable"),new _("unavailable","the server refused a freshly minted token");return b}}}function K(n){let e=typeof n=="string"?new TextEncoder().encode(n):n;return btoa(Pe(e))}function Pe(n){let t="";for(let r=0;r<n.length;r+=32768)t+=String.fromCharCode(...n.subarray(r,r+32768));return t}var m=class extends Error{constructor(t,r,o,s,a){super(`${t} (${r}): ${o}`);this.reason=t;this.status=r;this.detail=o;this.retryAfterSeconds=s;this.code=a;this.name="GemApiError";}reason;status;detail;retryAfterSeconds;code;get retryable(){return this.reason==="unavailable"||this.reason==="rate_limited"}},J=new WeakMap;function X(n){return J.get(n)??{}}var Oe=new Set([408,429,500,502,503,504]),Ge=6e4;function Ee(n){if(n===void 0)return 2;if(!Number.isInteger(n)||n<0||n>10)throw new p(`maxRetries must be a whole number between 0 and 10; received ${JSON.stringify(n)}. This is a configuration fault, not a server failure.`);return n}var P=class{constructor(e){this.options=e;}options;async get(e,t){return this.send({method:"GET",path:e,signal:t},true)}async getWithEtag(e,t={}){let r=await this.sendRaw({method:"GET",path:e,...t.signal===void 0?{}:{signal:t.signal},...t.ifNoneMatch===void 0?{}:{headers:{"if-none-match":t.ifNoneMatch}}},true),o=r.etag===void 0?{}:{etag:r.etag};return r.status===304?{modified:false,...o}:{modified:true,body:r.body,...o}}async put(e,t,r,o={}){return this.send({method:"PUT",path:e,body:t,signal:r,...C(o)},o.replaySafe===true)}async post(e,t,r,o={}){return this.send({method:"POST",path:e,body:t,signal:r,...C(o)},o.replaySafe===true)}async postBytes(e,t,r,o={}){let s=await this.sendRaw({method:"POST",path:e,bytes:t,responseType:"bytes",signal:r,...C(o)},o.replaySafe===true);return {bytes:Ce(s.body),...s.invocationId===void 0?{}:{invocationId:s.invocationId}}}async patch(e,t,r,o={}){return this.send({method:"PATCH",path:e,body:t,signal:r,...C(o)},o.replaySafe===true)}async delete(e,t,r={}){return this.send({method:"DELETE",path:e,signal:t,...C(r)},r.replaySafe===true)}async send(e,t){return (await this.sendRaw(e,t)).body}async sendRaw(e,t){let r=t?Ee(this.options.maxRetries)+1:1,o=null;if(e.signal?.aborted)throw Y(e.signal);for(let s=0;s<r;s++){if(s>0&&await this.backoff(s,o,e.signal),e.signal?.aborted)throw Y(e.signal);let a;try{a=await this.options.transport.request(e);}catch(d){if(_.isAuthError(d)||p.isRefusal(d)||e.signal?.aborted||Ie(d))throw d;o=new m("unavailable",0,String(d));continue}if(a.status>=200&&a.status<300||a.status===304)return a;let l=qe(a);if(!Oe.has(a.status))throw l;o=l;}throw o??new m("unavailable",0,"no attempt was made")}backoff(e,t,r){if(r?.aborted)return Promise.resolve();let o=t?.retryAfterSeconds,s=o!==void 0?o*1e3:2**(e-1)*250,a=2**(e-1)*250,l=Math.min(Math.max(s,a),Ge);return new Promise(d=>{let c=this.options.clock,g=false,b=false,x,f=()=>{g||(g=true,b&&c.clearTimeout(x),r?.removeEventListener("abort",f),d());};r?.addEventListener("abort",f,{once:true}),x=c.setTimeout(f,l),b=true,g&&c.clearTimeout(x);})}};function Ce(n){if(n instanceof Uint8Array)return n;if(n==null)return new Uint8Array(0);let e=typeof n=="string"?n:JSON.stringify(n);return new TextEncoder().encode(e)}function C(n){return {...n.keepalive===void 0?{}:{keepalive:n.keepalive},...n.ifMatch===void 0?{}:{headers:{"if-match":n.ifMatch}}}}function Y(n){return n.reason!==void 0?n.reason:new DOMException("The operation was aborted.","AbortError")}function Ie(n){let e=n?.name;return e==="AbortError"||e==="TimeoutError"}function qe(n){let e=$e(n),t=Fe(n.body),r={...t===void 0?{}:{details:t},...n.invocationId===void 0?{}:{invocationId:n.invocationId}};return Object.keys(r).length>0&&J.set(e,r),e}var Le=new Map([["insufficient_funds","insufficient_funds"]]);function $e(n){let{status:e,body:t}=n,r=je(t),o=n.retryAfterSeconds??Ue(t),s=Me(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 Fe(n){let t=n?.error?.details;return t===null?void 0:t}function Me(n){let t=n?.error?.code;return typeof t=="string"&&t.length>0?t:void 0}function Ue(n){let e=n?.retryAfterSeconds;return typeof e=="number"&&Number.isFinite(e)&&e>=0?e:void 0}function Be(n){let e=n.lastIndexOf("@");return (e===-1?n:`***@${n.slice(e+1)}`).slice(0,200)}var Ne=new Set(j);function De(n){if(!n)return {};let e={};for(let[t,r]of Object.entries(n))Ne.has(t.toLowerCase())&&(e[t.toLowerCase()]=r);return e}function Q(n){let e=n.fetch??globalThis.fetch.bind(globalThis);return z(async(t,r)=>{let o;try{o=new URL(n.baseUrl.replace(/\/+$/,""));}catch{throw new p("the configured baseUrl is not a valid URL. Its value is withheld here rather than written to logs. This is a configuration fault, not a server failure.")}let s;try{s=new URL(o.href.replace(/\/+$/,"")+t.path);}catch{throw new p(`${JSON.stringify(typeof t.path=="string"?Be(t.path):"(a non-string path)")} does not form a valid URL against ${o.protocol}//${o.host}. This is a malformed request, not a server failure.`)}if(s.protocol!==o.protocol||s.host!==o.host)throw new p(`${JSON.stringify(s.pathname)} resolves to ${s.protocol}//${s.host}, not ${o.protocol}//${o.host}. A request path may not change the request's origin \u2014 it carries the play token.`);if(s.username!==""||s.password!==""){let f=o.username!==""||o.password!=="",v=s.username!==o.username||s.password!==o.password,y=f?v?"baseUrl (and possibly the request path)":"baseUrl":"request path";throw new p(`the ${y} puts credentials in the URL, which cannot be fetched (${t.method} ${s.pathname}). The value is withheld here rather than written to logs. This is a malformed request, not a server failure.`)}for(let[f,v]of Object.entries(n.defaultQuery??{}))s.searchParams.has(f)||s.searchParams.set(f,v);let a=t.bytes,l=t.bytes===void 0?void 0:"application/octet-stream";try{t.body!==void 0&&(a=JSON.stringify(t.body),l="application/json");}catch(f){throw new p(`the body of ${t.method} ${JSON.stringify(s.pathname)} could not be serialised to JSON: ${String(f)}. This is a bug in the request, not a server failure \u2014 retrying sends the same unserialisable value.`)}let d=await e(s.toString(),{method:t.method,headers:{authorization:`Bearer ${r}`,...l===void 0?{}:{"content-type":l},...De(t.headers)},body:a,signal:t.signal,...t.keepalive===void 0?{}:{keepalive:t.keepalive},credentials:"omit",mode:"cors",redirect:"error",cache:"no-store",referrerPolicy:"no-referrer"}),c=null;if(t.responseType==="bytes"&&d.status>=200&&d.status<300)c=new Uint8Array(await d.arrayBuffer());else {let f=await d.text();if(f.length>0)try{c=JSON.parse(f);}catch{c=f;}}let g=d.headers.get("etag"),b=He(d.headers.get("retry-after")),x=d.headers.get("x-gem-invocation-id");return {status:d.status,body:c,...g===null?{}:{etag:g},...b===void 0?{}:{retryAfterSeconds:b},...x===null||x===""?{}:{invocationId:x}}},n)}function He(n){if(n===null)return;let e=n.trim();if(!/^\d+$/.test(e))return;let t=Number(e);return Number.isFinite(t)?t:void 0}var Ve="gem-web-bridge";var O=65536,Z=8,F=5e3,ee=1024;function B(n){return Object.freeze(Object.assign(Object.create(null),n))}B({"gem.handshake":30,"gem.handshake.accept":5,"gem.token":30,"gem.token.denied":30,"gem.player":12,"gem.pause":120,"gem.prefs":60,"gem.cohorts":12,"gem.earnAllowanceChanged":30,"gem.viewport":60,"gem.deviceSettings":12,"gem.willTerminate":10,"gem.roomEvent":120,"gem.socketState":12,"gem.seatedEvent":60,"gem.autoStartFailedEvent":30,"gem.signalEvent":1800,"gem.dedicatedEvent":120,"gem.partyResult":30,"gem.clusterTarget":12,"gem.devtools":30,"gem.screenshot":6,"gem.screenshot.denied":12,"gem.requestContext":12,"gem.gameContext":12,"gem.signal":1200,"gem.dedicatedOffer":60,"gem.partyRequest":12,"gem.ready":5,"gem.engaged":5,"gem.progress":600,"gem.requestToken":12,"gem.requestLocalServer":6,"gem.localServer":30,"gem.localServer.denied":30,"gem.exit":5,"gem.openExternal":6,"gem.requestFullscreen":30,"gem.audioState":120,"gem.rewardCue":60,"gem.walletDisplay":60,"gem.requestShare":6,"gem.frameStats":120,"gem.error":60,"gem.requestPurchase":12,"gem.purchaseResult":30,"gem.deviceSettings.put":30,"gem.deviceSettings.result":30,"gem.requestAd":6,"gem.adResult":12,"gem.requestSignIn":6,"gem.signInResult":12,"gem.requestFriendChallenge":12,"gem.friendChallengeResult":30,__malformed:60});B({"gem.requestAd":"ads","gem.adResult":"ads","gem.requestSignIn":"signIn","gem.signInResult":"signIn","gem.requestPurchase":"purchases","gem.purchaseResult":"purchases","gem.requestFriendChallenge":"friendChallenges","gem.friendChallengeResult":"friendChallenges","gem.devtools":"devtools","gem.screenshot":"screenshot","gem.screenshot.denied":"screenshot","gem.requestContext":"feedbackContext","gem.gameContext":"feedbackContext","gem.roomEvent":"rooms","gem.signal":"p2p","gem.signalEvent":"p2p","gem.dedicatedOffer":"dedicated","gem.dedicatedEvent":"dedicated","gem.clusterTarget":"clusterTarget","gem.partyRequest":"parties","gem.partyResult":"parties","gem.autoStartFailedEvent":"autoStartFailure","gem.seatedEvent":"partySeating","gem.socketState":"socketState","gem.audioState":"audioState","gem.rewardCue":"rewardCue","gem.frameStats":"frameStats","gem.engaged":"engagement","gem.viewport":"viewport","gem.walletDisplay":"walletDisplay","gem.requestLocalServer":"localHost","gem.localServer":"localHost","gem.localServer.denied":"localHost","gem.cohorts":"cohorts","gem.earnAllowanceChanged":"earnAllowance","gem.deviceSettings":"deviceSettings","gem.deviceSettings.put":"deviceSettings","gem.deviceSettings.result":"deviceSettings","gem.requestShare":"share"});function ze(n){let e=/^([a-z][a-z0-9+.-]*):\/\/([a-z0-9.-]+|\[[0-9a-f:.]+\])(:([0-9]{1,5}))?$/i.exec(n);return e===null?false:e[4]===void 0||Number(e[4])<=65535}function Ke(n){let e;try{e=new URL(n);}catch{return false}return e.username!==""||e.password!==""?false:e.protocol==="https:"?true:e.protocol==="http:"&&(e.hostname==="localhost"||e.hostname==="127.0.0.1")}function Ye(n){return /^[a-z]{2,8}(-[a-z0-9]{1,8})*$/i.test(n)}function Je(n){return /^[a-z_]+$/.test(n)}function U(n,e,t){if(e>Z)return `nesting deeper than ${Z}`;if(++t.nodes>F)return `more than ${F} values`;if(t.bytes>O)return `over the ${O} byte limit`;if(n==null)return t.bytes+=4,null;let r=typeof n;if(r==="boolean")return t.bytes+=5,null;if(r==="number")return t.bytes+=8,null;if(r==="string")return t.bytes+=n.length*3+2,null;if(r!=="object")return `${r} is not plain data`;let o=n;if(t.seen.has(o))return "a repeated or cyclic object reference";if(t.seen.add(o),Array.isArray(n)){if(n.length>ee)return `an array of ${n.length} entries, over the ${ee} limit`;t.bytes+=2;for(let l of n){let d=U(l,e+1,t);if(d)return d}return null}let s=Object.getPrototypeOf(n);if(s!==Object.prototype&&s!==null)return "a value that is not a plain object";t.bytes+=2;let a=n;for(let l in a){if(!Object.prototype.hasOwnProperty.call(a,l))continue;if(++t.nodes>F)return `more than ${F} values`;if(t.bytes+=l.length*3+4,t.bytes>O)return `over the ${O} byte limit`;let d=U(a[l],e+1,t);if(d)return d}return null}function Xe(n){let e={nodes:0,bytes:0,seen:new Set},t=U(n,0,e);return t?`message contains ${t}`:e.bytes>O?`message is over the ${O} byte limit`:null}var Qe={origin:[ze,"not a well-formed origin"],url:[Ke,"not a safe absolute http(s) URL"],bcp47:[Ye,"not a well-formed BCP 47 tag"],code:[Je,"not a code of lower-case letters and underscores"]};function ne(n,e,t){for(let r of e){let o=t===""?r.n:`${t}.${r.n}`,s=n[r.n];if(s==null){if(r.o)continue;return `${o}: required`}let a=te(s,r,o);if(a)return a}return null}function te(n,e,t){switch(e.k){case "string":{if(typeof n!="string")return `${t}: expected string`;if(n.length>e.max)return `${t}: exceeds ${e.max} characters`;if(e.f){let[r,o]=Qe[e.f];if(!r(n))return `${t}: ${o}`}return null}case "int":return typeof n!="number"||!Number.isInteger(n)?`${t}: expected integer`:n<e.lo||n>e.hi?`${t}: out of range ${e.lo}..${e.hi}`:null;case "boolean":return typeof n=="boolean"?null:`${t}: expected boolean`;case "enum":{let r=e.v;return r.includes(n)?null:`${t}: not one of ${r.join("|")}`}case "object":return typeof n!="object"||n===null||Array.isArray(n)?`${t}: expected object`:ne(n,e.fs,t);case "json":return typeof n!="object"||n===null||Array.isArray(n)?`${t}: expected a plain object`:null;case "array":{if(!Array.isArray(n))return `${t}: expected array`;if(n.length>e.max)return `${t}: exceeds ${e.max} items`;let r=e.it,o=`${t}[]`;for(let s of n){if(s==null){if(r.o)continue;return `${o}: required`}let a=te(s,r,o);if(a)return a}return null}default:{let r=e.k;return `${t}: unknown kind ${String(r)}`}}}function u(n,e){return t=>{let r=Xe(t);if(r)return r;if(typeof t!="object"||t===null||Array.isArray(t))return "message: expected object";let o=t;return o.gem!==Ve?"gem: wrong protocol marker":o.type!==n?`type: expected ${n}`:ne(o,e,"")}}var Ze=u("gem.handshake",[{n:"versions",k:"object",fs:[{n:"min",k:"int",lo:1,hi:1e3},{n:"max",k:"int",lo:1,hi:1e3}]},{n:"capabilities",k:"array",o:1,max:64,it:{n:"",k:"string",max:64}},{n:"embedder",k:"string",max:2048,f:"origin"},{n:"unbidden",k:"boolean",o:1}]),en=u("gem.handshake.accept",[{n:"v",k:"int",lo:1,hi:1e3},{n:"capabilities",k:"array",o:1,max:64,it:{n:"",k:"string",max:64}}]),nn=u("gem.token",[{n:"token",k:"string",max:4096},{n:"requestId",k:"string",o:1,max:64},{n:"generation",k:"int",lo:0,hi:2147483647},{n:"apiBaseUrl",k:"string",o:1,max:512,f:"url"},{n:"playerId",k:"string",max:64},{n:"gameId",k:"string",max:64},{n:"channel",k:"enum",v:["dev","test","release"]},{n:"gameVersion",k:"string",o:1,max:64},{n:"expiresAt",k:"int",lo:0,hi:4102444800},{n:"chainEndsAt",k:"int",lo:0,hi:4102444800},{n:"allowDevTools",k:"boolean",o:1}]),tn=u("gem.token.denied",[{n:"requestId",k:"string",max:64},{n:"retryable",k:"boolean"},{n:"retryAfterMs",k:"int",o:1,lo:0,hi:36e5},{n:"reason",k:"enum",v:["chain_exhausted","unavailable"]},{n:"correlationId",k:"string",max:64}]),rn=u("gem.player",[{n:"untrusted",k:"object",fs:[{n:"displayName",k:"string",max:64},{n:"displayTag",k:"string",o:1,max:80},{n:"displayHandle",k:"string",max:80}]},{n:"playerId",k:"string",o:1,max:64},{n:"discriminator",k:"string",o:1,max:8},{n:"avatarIconUrl",k:"string",o:1,max:2048,f:"url"},{n:"badges",k:"array",o:1,max:2,it:{n:"",k:"object",fs:[{n:"itemId",k:"string",max:64},{n:"iconUrl",k:"string",max:2048,f:"url"}]}},{n:"displayTag",k:"string",max:8},{n:"avatarUrl",k:"string",o:1,max:2048,f:"url"},{n:"boost",k:"object",o:1,fs:[{n:"multipliers",k:"array",max:8,it:{n:"",k:"object",fs:[{n:"currencyId",k:"string",max:64},{n:"currencySlug",k:"string",max:32},{n:"multiplierBp",k:"int",lo:1e4,hi:1e6}]}},{n:"expiresInDays",k:"int",o:1,lo:1,hi:7}]}]),on=u("gem.pause",[{n:"paused",k:"boolean"}]),sn=u("gem.prefs",[{n:"reducedMotion",k:"boolean"},{n:"muted",k:"boolean"},{n:"showFrameStats",k:"boolean",o:1},{n:"locale",k:"string",max:35,f:"bcp47"}]),an=u("gem.cohorts",[{n:"cohorts",k:"array",max:8,it:{n:"",k:"object",fs:[{n:"experimentId",k:"string",max:36},{n:"variantKey",k:"string",max:32}]}}]),ln=u("gem.earnAllowanceChanged",[]),dn=u("gem.viewport",[{n:"insets",k:"object",fs:[{n:"top",k:"int",lo:0,hi:4096},{n:"right",k:"int",lo:0,hi:4096},{n:"bottom",k:"int",lo:0,hi:4096},{n:"left",k:"int",lo:0,hi:4096}]},{n:"reserved",k:"array",o:1,max:4,it:{n:"",k:"object",fs:[{n:"x",k:"int",lo:0,hi:16384},{n:"y",k:"int",lo:0,hi:16384},{n:"width",k:"int",lo:0,hi:16384},{n:"height",k:"int",lo:0,hi:16384}]}}]),un=u("gem.deviceSettings",[{n:"settings",k:"json",o:1}]),cn=u("gem.willTerminate",[{n:"reason",k:"enum",v:["grant_expiring","session_ended","navigating","kill_switch"]},{n:"graceMs",k:"int",lo:0,hi:6e4}]),gn=u("gem.roomEvent",[{n:"event",k:"enum",v:["updated","match_started","match_ready","match_failed","version_stale"]},{n:"roomId",k:"string",max:64},{n:"matchId",k:"string",o:1,max:64},{n:"version",k:"int",o:1,lo:0,hi:2147483647},{n:"reason",k:"string",o:1,max:64},{n:"platform",k:"enum",o:1,v:["universal","mobile"]}]),mn=u("gem.socketState",[{n:"connected",k:"boolean"},{n:"reason",k:"enum",o:1,v:["connecting","dropped","watchdog","terminal"]}]),pn=u("gem.seatedEvent",[{n:"roomId",k:"string",max:64}]),yn=u("gem.autoStartFailedEvent",[{n:"roomId",k:"string",max:64},{n:"code",k:"string",max:64}]),fn=u("gem.signalEvent",[{n:"event",k:"enum",v:["hello","offer","answer","ice","peerJoined","peerLeft","migration","matchEnded","error"]},{n:"matchId",k:"string",max:64},{n:"data",k:"json"}]),hn=u("gem.dedicatedEvent",[{n:"event",k:"enum",v:["answer","error","matchEnded"]},{n:"matchId",k:"string",max:64},{n:"sdp",k:"string",o:1,max:10240},{n:"sessionId",k:"string",o:1,max:64},{n:"code",k:"string",o:1,max:64},{n:"message",k:"string",o:1,max:256},{n:"reason",k:"string",o:1,max:64}]),_n=u("gem.partyResult",[{n:"requestId",k:"string",max:64},{n:"partyId",k:"string",o:1,max:64}]),bn=u("gem.clusterTarget",[{n:"clusterTargetId",k:"string",max:64},{n:"clusterTargetIds",k:"array",o:1,max:3,it:{n:"",k:"string",max:64}}]),vn=u("gem.devtools",[{n:"action",k:"enum",v:["open","close","toggle"]}]),Rn=u("gem.screenshot",[{n:"maxWidth",k:"int",lo:1,hi:7680},{n:"maxHeight",k:"int",lo:1,hi:4320}]),xn=u("gem.screenshot.denied",[{n:"reason",k:"enum",v:["not_wired","no_source","unsupported","unreadable","tainted","too_large","busy","declined","failed"]},{n:"retryable",k:"boolean"}]),Sn=u("gem.requestContext",[]),kn=u("gem.gameContext",[{n:"context",k:"json"}]),wn=u("gem.signal",[{n:"signal",k:"enum",v:["join","offer","answer","ice","migrationAck","hostUnreachable"]},{n:"matchId",k:"string",max:64},{n:"data",k:"json"}]),An=u("gem.dedicatedOffer",[{n:"matchId",k:"string",max:64},{n:"sdp",k:"string",max:10240},{n:"intent",k:"enum",v:["initial","ice_restart","full_reconnect"]}]),Tn=u("gem.partyRequest",[{n:"requestId",k:"string",max:64}]),Pn=u("gem.ready",[]),On=u("gem.engaged",[]),Gn=u("gem.progress",[{n:"loaded",k:"int",lo:0,hi:1099511627776},{n:"total",k:"int",lo:0,hi:1099511627776}]),En=u("gem.requestToken",[{n:"requestId",k:"string",max:64},{n:"reason",k:"enum",v:["initial","expiring","rejected"]}]),Cn=u("gem.requestLocalServer",[{n:"requestId",k:"string",max:64},{n:"gameRoomId",k:"string",max:64}]),In=u("gem.localServer",[{n:"requestId",k:"string",max:64},{n:"serverId",k:"string",o:1,max:128}]),qn=u("gem.localServer.denied",[{n:"requestId",k:"string",max:64},{n:"retryable",k:"boolean"},{n:"reason",k:"enum",v:["refused","unavailable"]}]),Ln=u("gem.exit",[{n:"reason",k:"string",o:1,max:64}]),$n=u("gem.openExternal",[{n:"url",k:"string",max:2048,f:"url"}]),jn=u("gem.requestFullscreen",[{n:"enabled",k:"boolean"}]),Fn=u("gem.audioState",[{n:"muted",k:"boolean"}]),Mn=u("gem.rewardCue",[{n:"currencySlug",k:"string",max:32},{n:"expected",k:"int",o:1,lo:1,hi:1e9},{n:"origin",k:"object",o:1,fs:[{n:"x",k:"int",lo:0,hi:16384},{n:"y",k:"int",lo:0,hi:16384}]}]),Un=u("gem.walletDisplay",[{n:"visible",k:"boolean"},{n:"currencies",k:"array",o:1,max:8,it:{n:"",k:"string",max:64}},{n:"score",k:"boolean",o:1}]),Bn=u("gem.requestShare",[{n:"params",k:"array",max:16,it:{n:"",k:"object",fs:[{n:"key",k:"string",max:64},{n:"value",k:"string",max:512}]}}]),Nn=u("gem.frameStats",[{n:"fps",k:"int",lo:0,hi:1e3},{n:"frameTimeP95Ms",k:"int",lo:0,hi:1e5}]),Dn=u("gem.error",[{n:"code",k:"enum",v:["version_mismatch","handshake_timeout","handshake_duplicate","invalid_message","rate_limited","token_unavailable","unsupported","unsupported_capability","internal"]},{n:"message",k:"string",o:1,max:256}]),Hn=u("gem.requestPurchase",[{n:"requestId",k:"string",max:64},{n:"purchaseKind",k:"enum",v:["item","recipe"]},{n:"targetId",k:"string",max:64},{n:"currencySlug",k:"string",max:32},{n:"quantity",k:"int",o:1,lo:1,hi:10},{n:"catalogId",k:"string",o:1,max:64}]),Vn=u("gem.purchaseResult",[{n:"requestId",k:"string",max:64},{n:"outcome",k:"enum",v:["ok","declined","unavailable"]},{n:"reason",k:"string",o:1,max:64,f:"code"},{n:"purchaseId",k:"string",o:1,max:64}]),Wn=u("gem.deviceSettings.put",[{n:"requestId",k:"string",max:64},{n:"settings",k:"json"}]),zn=u("gem.deviceSettings.result",[{n:"requestId",k:"string",max:64},{n:"outcome",k:"enum",v:["stored","too_large","unavailable"]}]),Kn=u("gem.requestAd",[{n:"requestId",k:"string",max:64},{n:"placement",k:"string",max:32},{n:"format",k:"enum",v:["interstitial","rewarded"]}]),Yn=u("gem.adResult",[{n:"requestId",k:"string",max:64},{n:"outcome",k:"enum",v:["shown","no_ad","unavailable"]}]),Jn=u("gem.requestSignIn",[{n:"requestId",k:"string",max:64}]),Xn=u("gem.signInResult",[{n:"requestId",k:"string",max:64},{n:"outcome",k:"enum",v:["signed_in","declined","unavailable"]}]),Qn=u("gem.requestFriendChallenge",[{n:"requestId",k:"string",max:64},{n:"playerId",k:"string",max:64},{n:"template",k:"string",max:64},{n:"params",k:"json",o:1}]),Zn=u("gem.friendChallengeResult",[{n:"requestId",k:"string",max:64},{n:"outcome",k:"enum",v:["accepted","cancelled","refused","unavailable","rate_limited","invalid"]},{n:"code",k:"string",o:1,max:64},{n:"param",k:"string",o:1,max:64},{n:"channel",k:"string",o:1,max:16},{n:"configVersion",k:"int",o:1,lo:0,hi:9007199254740991},{n:"retryAfterMs",k:"int",o:1,lo:0,hi:864e5},{n:"detail",k:"string",o:1,max:300}]);B({"gem.handshake":Ze,"gem.handshake.accept":en,"gem.token":nn,"gem.token.denied":tn,"gem.player":rn,"gem.pause":on,"gem.prefs":sn,"gem.cohorts":an,"gem.earnAllowanceChanged":ln,"gem.viewport":dn,"gem.deviceSettings":un,"gem.willTerminate":cn,"gem.roomEvent":gn,"gem.socketState":mn,"gem.seatedEvent":pn,"gem.autoStartFailedEvent":yn,"gem.signalEvent":fn,"gem.dedicatedEvent":hn,"gem.partyResult":_n,"gem.clusterTarget":bn,"gem.devtools":vn,"gem.screenshot":Rn,"gem.screenshot.denied":xn,"gem.requestContext":Sn,"gem.gameContext":kn,"gem.signal":wn,"gem.dedicatedOffer":An,"gem.partyRequest":Tn,"gem.ready":Pn,"gem.engaged":On,"gem.progress":Gn,"gem.requestToken":En,"gem.requestLocalServer":Cn,"gem.localServer":In,"gem.localServer.denied":qn,"gem.exit":Ln,"gem.openExternal":$n,"gem.requestFullscreen":jn,"gem.audioState":Fn,"gem.rewardCue":Mn,"gem.walletDisplay":Un,"gem.requestShare":Bn,"gem.frameStats":Nn,"gem.error":Dn,"gem.requestPurchase":Hn,"gem.purchaseResult":Vn,"gem.deviceSettings.put":Wn,"gem.deviceSettings.result":zn,"gem.requestAd":Kn,"gem.adResult":Yn,"gem.requestSignIn":Jn,"gem.signInResult":Xn,"gem.requestFriendChallenge":Qn,"gem.friendChallengeResult":Zn});var G={now:()=>Date.now(),setTimeout:(n,e)=>setTimeout(n,e),clearTimeout:n=>clearTimeout(n)};var et=1e4;function re(n,e){return N(n,e)}function N(n,e){if(typeof n.serverToken!="function"||typeof n.onServerToken!="function")throw new Error("this runtime delivers no game-server token: host.serverToken/onServerToken are missing. The server image running this bundle predates token delivery \u2014 the bundle cannot call gem-api on it.");let t=a=>({token:a.token,expiresAt:a.expiresAt,chainEndsAt:Number.POSITIVE_INFINITY}),r=null,o=new $({clock:e.clock,...e.onStateChange===void 0?{}:{onStateChange:e.onStateChange},request:()=>new Promise((a,l)=>{let d=e.clock.setTimeout(()=>{r=null,l({reason:"unavailable",retryable:true});},e.timeoutMs??et);r={resolve:c=>{e.clock.clearTimeout(d),a(c);},reject:l,timer:d};})}),s=n.onServerToken(a=>{let l=t(a),d=r;if(d){r=null,d.resolve(l);return}o.accept(l);});return {source:o,dispose(){s(),r&&(e.clock.clearTimeout(r.timer),r.reject({reason:"unavailable",retryable:false}),r=null);}}}var H={};Re(H,{acceptTransfer:()=>nt,addEntityProgression:()=>tt,adminAction:()=>rt,cancelInventoryTransfer:()=>ot,claimEntityProgressionRewards:()=>st,closeGameRoom:()=>it,createEntityBatchOrder:()=>at,createEntityOrder:()=>lt,createSession:()=>dt,deleteEntityGameSetting:()=>ut,deleteEntitySave:()=>ct,deleteSession:()=>gt,deleteShowcaseValue:()=>mt,executeEntityRecipe:()=>pt,finalizeSaveUpload:()=>yt,getChannelAssignment:()=>ft,getDropRates:()=>ht,getEntityCurrency:()=>_t,getEntityGameSetting:()=>bt,getEntityInventory:()=>vt,getEntityInventoryItem:()=>Rt,getEntityLeaderboard:()=>xt,getEntityOrder:()=>St,getEntityProgression:()=>kt,getEntityRecipeAvailability:()=>wt,getEntityRecipeUsage:()=>At,getEntitySave:()=>Tt,getEvent:()=>Pt,getGameRoomV2:()=>Ot,getLeaderboard:()=>Gt,getPlayerGameProfile:()=>Et,getPurchaseCatalog:()=>Ct,getResolvedTemplate:()=>It,getRoomArgs:()=>qt,getShowcaseValue:()=>Lt,getTransferDetails:()=>$t,ingestAnalyticsEvents:()=>D,initiateInventoryTransfer:()=>jt,invokeFunction:()=>Ft,kickPlayer:()=>Mt,listChallenges:()=>Ut,listEntityGameSettings:()=>Bt,listEntityOrders:()=>Nt,listEntityProgressions:()=>Dt,listEntitySaves:()=>Ht,listEvents:()=>Vt,listGameRooms:()=>Wt,listResolvedTemplates:()=>zt,listTransfers:()=>Kt,maxEntityProgression:()=>Yt,putEntityGameSetting:()=>Jt,putRoomArgs:()=>Xt,putShowcaseValue:()=>Qt,rejectTransfer:()=>Zt,requestSaveUploadUrl:()=>er,resetEntityProgression:()=>nr,simulateEntityOrder:()=>tr,transferHostV2:()=>rr,updateGameRoomV2:()=>or});function i(n){let e=String(n);if(!/^[A-Za-z0-9_.-]{1,128}$/.test(e)||e==="."||e==="..")throw new TypeError(`${JSON.stringify(e)} is not a usable path segment \u2014 it is interpolated into a URL`);return encodeURIComponent(e)}async function nt(n,e,t){let r=`/v1/inventory/transfers/${i(e)}/accept`;return n.client.post(r,void 0,t?.signal)}async function tt(n,e,t,r,o,s){let a=`/v1/inventory/${i(e)}/${i(t)}/progressions/${i(r)}/add`;return n.client.post(a,o,s?.signal)}async function rt(n,e,t,r){let o=`/v1/voice/sessions/${i(e)}/admin`;return n.client.post(o,t,r?.signal)}async function ot(n,e,t){let r=`/v1/inventory/transfers/${i(e)}/cancel`;return n.client.post(r,void 0,t?.signal)}async function st(n,e,t,r,o,s){let a=`/v1/inventory/${i(e)}/${i(t)}/progressions/${i(r)}/claim`;return n.client.post(a,o,s?.signal)}async function it(n,e,t){let r=`/v1/games/${i(n.gameId())}/game-rooms/${i(e)}`;return n.client.delete(r,t?.signal)}async function at(n,e,t,r,o){let s=`/v1/inventory/${i(e)}/${i(t)}/orders/batch`;return n.client.post(s,r,o?.signal,{...o?.ifMatch===void 0?{}:{ifMatch:o.ifMatch}})}async function lt(n,e,t,r,o){let s=`/v1/inventory/${i(e)}/${i(t)}/orders`;return n.client.post(s,r,o?.signal,{...o?.ifMatch===void 0?{}:{ifMatch:o.ifMatch}})}async function dt(n,e,t){return n.client.post("/v1/voice/sessions",e,t?.signal)}async function ut(n,e,t,r,o){let s=`/v1/settings/${i(e)}/${i(t)}/${i(r)}`;return n.client.delete(s,o?.signal)}async function ct(n,e,t,r,o){let s=`/v1/saves/${i(e)}/${i(t)}/${i(r)}`;return n.client.delete(s,o?.signal)}async function gt(n,e,t){let r=`/v1/voice/sessions/${i(e)}`;return n.client.delete(r,t?.signal)}async function mt(n,e,t,r){let o=`/v1/showcase/players/${i(e)}/${i(t)}`;return n.client.delete(o,r?.signal)}async function pt(n,e,t,r,o){let s=`/v1/inventory/${i(e)}/${i(t)}/recipes/execute`;return n.client.post(s,r,o?.signal,{...o?.ifMatch===void 0?{}:{ifMatch:o.ifMatch}})}async function yt(n,e,t,r,o,s){let a=`/v1/saves/${i(e)}/${i(t)}/${i(r)}/finalize`;return n.client.post(a,o,s?.signal)}async function ft(n,e,t){let r=`/v1/games/${i(n.gameId())}/config/channels/${i(e)}`;return n.client.getWithEtag(r,{...t?.signal===void 0?{}:{signal:t.signal},...t?.ifNoneMatch===void 0?{}:{ifNoneMatch:t.ifNoneMatch}})}async function ht(n,e,t){let r=`/v1/inventory/loot-tables/${i(e)}/drop-rates`;return n.client.get(r,t?.signal)}async function _t(n,e,t,r,o){let s=`/v1/inventory/${i(e)}/${i(t)}/currencies/${i(r)}`;return n.client.get(s,o?.signal)}async function bt(n,e,t,r,o){let s=`/v1/settings/${i(e)}/${i(t)}/${i(r)}`;return n.client.getWithEtag(s,{...o?.signal===void 0?{}:{signal:o.signal},...o?.ifNoneMatch===void 0?{}:{ifNoneMatch:o.ifNoneMatch}})}async function vt(n,e,t,r){let o=new URLSearchParams;r?.include_buckets!==void 0&&o.set("include_buckets",String(r?.include_buckets)),r?.include_custom_data!==void 0&&o.set("include_custom_data",String(r?.include_custom_data)),r?.currency_limit!==void 0&&o.set("currency_limit",String(r?.currency_limit)),r?.currency_cursor!==void 0&&o.set("currency_cursor",String(r?.currency_cursor)),r?.item_limit!==void 0&&o.set("item_limit",String(r?.item_limit)),r?.item_cursor!==void 0&&o.set("item_cursor",String(r?.item_cursor)),r?.progression_limit!==void 0&&o.set("progression_limit",String(r?.progression_limit)),r?.progression_cursor!==void 0&&o.set("progression_cursor",String(r?.progression_cursor));let s=o.toString(),a=`/v1/inventory/${i(e)}/${i(t)}`+(s?`?${s}`:"");return n.client.get(a,r?.signal)}async function Rt(n,e,t,r,o){let s=`/v1/inventory/${i(e)}/${i(t)}/items/${i(r)}`;return n.client.get(s,o?.signal)}async function xt(n,e,t,r,o){let s=new URLSearchParams;o?.bucket_1!==void 0&&s.set("bucket_1",String(o?.bucket_1)),o?.bucket_2!==void 0&&s.set("bucket_2",String(o?.bucket_2)),o?.limit!==void 0&&s.set("limit",String(o?.limit)),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 St(n,e,t,r,o){let s=`/v1/inventory/${i(e)}/${i(t)}/orders/${i(r)}`;return n.client.get(s,o?.signal)}async function kt(n,e,t,r,o){let s=`/v1/inventory/${i(e)}/${i(t)}/progressions/${i(r)}`;return n.client.get(s,o?.signal)}async function wt(n,e,t,r,o,s){let a=`/v1/inventory/${i(e)}/${i(t)}/catalogs/${i(r)}/recipes/${i(o)}/availability`;return n.client.get(a,s?.signal)}async function At(n,e,t,r){let o=new URLSearchParams;r?.limit!==void 0&&o.set("limit",String(r?.limit));let s=o.toString(),a=`/v1/inventory/${i(e)}/${i(t)}/recipe-usage`+(s?`?${s}`:"");return n.client.get(a,r?.signal)}async function Tt(n,e,t,r,o){let s=`/v1/saves/${i(e)}/${i(t)}/${i(r)}`;return n.client.getWithEtag(s,{...o?.signal===void 0?{}:{signal:o.signal},...o?.ifNoneMatch===void 0?{}:{ifNoneMatch:o.ifNoneMatch}})}async function Pt(n,e,t){let r=`/v1/events/${i(e)}`;return n.client.get(r,t?.signal)}async function Ot(n,e,t){let r=`/v2/games/${i(n.gameId())}/game-rooms/${i(e)}`;return n.client.getWithEtag(r,{...t?.signal===void 0?{}:{signal:t.signal},...t?.ifNoneMatch===void 0?{}:{ifNoneMatch:t.ifNoneMatch}})}async function Gt(n,e,t){let r=new URLSearchParams;t?.bucket_1!==void 0&&r.set("bucket_1",String(t?.bucket_1)),t?.bucket_2!==void 0&&r.set("bucket_2",String(t?.bucket_2)),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 Et(n,e,t){let r=`/v1/profiles/players/${i(e)}`;return n.client.get(r,t?.signal)}async function Ct(n,e){let t=new URLSearchParams;e?.config_version!==void 0&&t.set("config_version",String(e?.config_version));let r=t.toString(),o="/v1/inventory/platform-funded-game-inventory-purchase-catalog"+(r?`?${r}`:"");return n.client.get(o,e?.signal)}async function It(n,e,t){let r=`/v1/game-room-templates/${i(e)}`;return n.client.get(r,t?.signal)}async function qt(n,e,t){let r=`/v1/games/${i(n.gameId())}/game-rooms/${i(e)}/room-args`;return n.client.get(r,t?.signal)}async function Lt(n,e,t,r){let o=`/v1/showcase/players/${i(e)}/${i(t)}`;return n.client.get(o,r?.signal)}async function $t(n,e,t){let r=`/v1/inventory/transfers/${i(e)}`;return n.client.get(r,t?.signal)}async function D(n,e,t){let r=`/v1/games/${i(n.gameId())}/analytics/events`;return n.client.post(r,e,t?.signal,{replaySafe:true})}async function jt(n,e,t){return n.client.post("/v1/inventory/transfers",e,t?.signal)}async function Ft(n,e,t){return n.client.postBytes("/v1/functions/invoke",e,t?.signal)}async function Mt(n,e,t,r){let o=`/v1/games/${i(n.gameId())}/game-rooms/${i(e)}/kick/${i(t)}`;return n.client.post(o,void 0,r?.signal)}async function Ut(n,e){let t=new URLSearchParams;e?.periods_back!==void 0&&t.set("periods_back",String(e?.periods_back)),e?.player_id!==void 0&&t.set("player_id",String(e?.player_id));let r=t.toString(),o="/v1/challenges"+(r?`?${r}`:"");return n.client.get(o,e?.signal)}async function Bt(n,e,t,r){let o=`/v1/settings/${i(e)}/${i(t)}`;return n.client.get(o,r?.signal)}async function Nt(n,e,t,r){let o=new URLSearchParams;r?.limit!==void 0&&o.set("limit",String(r?.limit)),r?.cursor!==void 0&&o.set("cursor",String(r?.cursor));let s=o.toString(),a=`/v1/inventory/${i(e)}/${i(t)}/orders`+(s?`?${s}`:"");return n.client.get(a,r?.signal)}async function Dt(n,e,t,r){let o=`/v1/inventory/${i(e)}/${i(t)}/progressions`;return n.client.get(o,r?.signal)}async function Ht(n,e,t,r){let o=new URLSearchParams;r?.limit!==void 0&&o.set("limit",String(r?.limit)),r?.cursor!==void 0&&o.set("cursor",String(r?.cursor));let s=o.toString(),a=`/v1/saves/${i(e)}/${i(t)}`+(s?`?${s}`:"");return n.client.get(a,r?.signal)}async function Vt(n,e){let t=new URLSearchParams;e?.include_inactive!==void 0&&t.set("include_inactive",String(e?.include_inactive)),e?.limit!==void 0&&t.set("limit",String(e?.limit)),e?.offset!==void 0&&t.set("offset",String(e?.offset));let r=t.toString(),o="/v1/events"+(r?`?${r}`:"");return n.client.get(o,e?.signal)}async function Wt(n,e){let t=new URLSearchParams;e?.status!==void 0&&t.set("status",String(e?.status)),e?.game_channel!==void 0&&t.set("game_channel",String(e?.game_channel)),e?.game_room_type!==void 0&&t.set("game_room_type",String(e?.game_room_type)),e?.template_id!==void 0&&t.set("template_id",String(e?.template_id)),e?.template_slug!==void 0&&t.set("template_slug",String(e?.template_slug)),e?.limit!==void 0&&t.set("limit",String(e?.limit)),e?.cursor!==void 0&&t.set("cursor",String(e?.cursor));let r=t.toString(),o=`/v1/games/${i(n.gameId())}/game-rooms`+(r?`?${r}`:"");return n.client.get(o,e?.signal)}async function zt(n,e){return n.client.get("/v1/game-room-templates",e?.signal)}async function Kt(n,e){let t=new URLSearchParams;e.entity_type!==void 0&&t.set("entity_type",String(e.entity_type)),e.entity_id!==void 0&&t.set("entity_id",String(e.entity_id)),e?.direction!==void 0&&t.set("direction",String(e?.direction)),e?.status!==void 0&&t.set("status",String(e?.status)),e?.cursor!==void 0&&t.set("cursor",String(e?.cursor)),e?.limit!==void 0&&t.set("limit",String(e?.limit));let r=t.toString(),o="/v1/inventory/transfers"+(r?`?${r}`:"");return n.client.get(o,e?.signal)}async function Yt(n,e,t,r,o,s){let a=`/v1/inventory/${i(e)}/${i(t)}/progressions/${i(r)}/max`;return n.client.post(a,o,s?.signal)}async function Jt(n,e,t,r,o,s){let a=`/v1/settings/${i(e)}/${i(t)}/${i(r)}`;return n.client.put(a,o,s?.signal,{...s?.ifMatch===void 0?{}:{ifMatch:s.ifMatch}})}async function Xt(n,e,t,r){let o=`/v1/games/${i(n.gameId())}/game-rooms/${i(e)}/room-args`;return n.client.put(o,t,r?.signal)}async function Qt(n,e,t,r,o){let s=`/v1/showcase/players/${i(e)}/${i(t)}`;return n.client.put(s,r,o?.signal)}async function Zt(n,e,t){let r=`/v1/inventory/transfers/${i(e)}/reject`;return n.client.post(r,void 0,t?.signal)}async function er(n,e,t,r,o,s){let a=`/v1/saves/${i(e)}/${i(t)}/${i(r)}/upload-url`;return n.client.post(a,o,s?.signal,{replaySafe:true})}async function nr(n,e,t,r,o,s){let a=`/v1/inventory/${i(e)}/${i(t)}/progressions/${i(r)}/reset`;return n.client.post(a,o,s?.signal)}async function tr(n,e,t,r,o){let s=`/v1/inventory/${i(e)}/${i(t)}/orders/simulate`;return n.client.post(s,r,o?.signal)}async function rr(n,e,t,r){let o=`/v2/games/${i(n.gameId())}/game-rooms/${i(e)}/transfer/${i(t)}`;return n.client.post(o,void 0,r?.signal)}async function or(n,e,t,r){let o=`/v2/games/${i(n.gameId())}/game-rooms/${i(e)}`;return n.client.patch(o,t,r?.signal,{...r?.ifMatch===void 0?{}:{ifMatch:r.ifMatch}})}var oe="gem_";var ar=1e4,lr=50,dr=1e3,ur=65536-4*1024,se=n=>typeof n=="number"?n:0,cr=n=>typeof n=="string"?n:"";function ie(){let n=globalThis.crypto;return typeof n?.randomUUID=="function"?n.randomUUID():"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,e=>{let t=Math.floor(Math.random()*16);return (e==="x"?t:t&3|8).toString(16)})}function gr(n){return n?.retryable===true}function mr(n,e){let t=n??{},r=Array.isArray(t.rejected)?t.rejected.map(o=>{let s=o??{};return {index:se(s.index),code:cr(s.code)}}):[];return {accepted:se(t.accepted),rejected:r,dropped:e,duplicate:t.duplicate===true}}function ae(n,e){return {event_uid:n.uid,name:n.name,offset_ms:Math.round(n.atMs)-e,player_id:n.playerId,dimensions:n.dimensions,measures:n.measures}}function le(n){let e=Math.max(1,Math.floor(n.maxQueue??dr)),t={client:n.client,gameId:()=>n.gameId},r=[],o=0,s=null,a=false,l=false,d=false,c=false,g=y=>{n.log?.(y);},b=()=>{s!==null&&(n.clock.clearTimeout(s),s=null);},x=()=>{s!==null||a||l||(s=n.clock.setTimeout(()=>{s=null,v().catch(()=>{});},ar));},f=()=>{let y=Math.min(r.length,100),h=128;for(let w=0;w<y;w+=1){let A=r[w];if(A===void 0)break;if(h+=JSON.stringify(ae(A,0)).length+1,h>ur)return Math.max(1,w)}return y};async function v(y){if(r.length===0)return {accepted:0,rejected:[],dropped:0,duplicate:false};b();let h=r.splice(0,f()),w=o;o=0;let A=Math.round(n.clock.now()),L={batch_id:ie(),sent_at_ms:A,events:h.map(S=>ae(S,A))};l=true;try{let S=await D(t,L,y===void 0?void 0:{signal:y}),T=mr(S,w);for(let be of T.rejected)g(`[gem] analytics: an event was refused (${be.code}). See the analytics_events section of your game config.`);return T}catch(S){if(gr(S))for(r=[...h,...r],o+=w;r.length>e;)r.shift(),o+=1;else g(`[gem] analytics: ${h.length} event(s) were discarded \u2014 the platform refused the batch and will refuse it again: ${String(S)}`);throw S}finally{l=false,r.length>0&&x();}}return {track(y,h,w={}){if(a)return;if(typeof y!="string"||y===""){c||(c=true,g(`[gem] analytics: '${h}' was not recorded \u2014 an event from a server has to name the player it is about. A game-server token names no player, so the platform cannot infer one; pass the id from join() or host.players().`));return}if(h.startsWith(oe)){d||(d=true,g(`[gem] analytics: '${h}' was not recorded \u2014 the gem_ prefix is reserved, and the platform's own events are client-sourced, so a server may not emit one at all. Name your event something else.`));return}let A={},L={};for(let[S,T]of Object.entries(w))typeof T=="string"?A[S]=T:typeof T=="number"&&Number.isFinite(T)&&(L[S]=T);for(;r.length>=e;)r.shift(),o+=1;r.push({uid:ie(),playerId:y,name:h,atMs:n.clock.now(),dimensions:A,measures:L}),r.length>=lr?v().catch(()=>{}):x();},flush:y=>v(y),get pending(){return r.length},dispose(){a=true,b(),r=[],o=0;}}}var pr=new Map([["function_error",false],["function_failed",false],["function_timeout",false],["function_not_published",false],["function_input_too_large",false],["functions_not_configured",false],["forbidden",false],["function_capacity_unavailable",true],["function_host_unreachable",true],["function_host_error",true],["rate_limited",true],["service_unavailable",true]]),I=class extends m{constructor(e,t){super(e.reason,e.status,e.detail,e.retryAfterSeconds,e.code),this.name="GemFunctionError",Object.assign(this,t);}get retryable(){return (this.code===void 0?void 0:pr.get(this.code))??super.retryable}},E=class{#e;constructor(e){this.#e=e;}async invoke(e,t={}){let r=yr(e),o;try{o=await this.#e(r,t.signal===void 0?{}:{signal:t.signal});}catch(s){throw s instanceof m?hr(s):s}return fr(o)}};function yr(n){if(n instanceof ArrayBuffer)return new Uint8Array(n);if(ArrayBuffer.isView(n))return new Uint8Array(n.buffer,n.byteOffset,n.byteLength);let e;try{e=JSON.stringify(n);}catch(t){throw new p(`the function input could not be serialised to JSON: ${String(t)}. Pass bytes, or a value JSON can carry. This is a bug in the call, not a server failure.`)}if(e===void 0)throw new p(`the function input is ${typeof n}, which JSON cannot carry. Pass bytes \u2014 an empty Uint8Array for no input \u2014 or a JSON value. This is a bug in the call, not a server failure.`);return new TextEncoder().encode(e)}function fr(n){let{bytes:e}=n,t=()=>new TextDecoder("utf-8",{fatal:true}).decode(e);return {bytes:e,...n.invocationId===void 0?{}:{invocationId:n.invocationId},text:t,json:()=>JSON.parse(t())}}function hr(n){let{details:e,invocationId:t}=X(n),o=e?.untrusted?.message,s=e?.reason;return new I(n,{...t===void 0?{}:{invocationId:t},...n.code==="function_error"&&typeof o=="string"?{functionMessage:o}:{},...n.code==="function_failed"&&typeof s=="string"?{failure:s}:{}})}var k=n=>typeof n=="string"?n:"",_r=/(?:Z|[+-]\d{2}:?\d{2})$/i;function de(n){let e=k(n);if(!_r.test(e))return 0;let t=Date.parse(e);return Number.isFinite(t)?Math.floor(t/1e3):0}var br=/^[0-9a-f]{1,64}$/,vr=/^[0-9a-f]{16}$/,Rr=/^[A-Za-z][A-Za-z0-9_+\-/]{0,63}$/,xr=/^(?:[01]\d|2[0-3]):[0-5]\d$/;function Sr(n){let e=k(n),t=/^(\d{4})-(\d{2})-(\d{2})$/.exec(e);if(!t)return;let[r,o,s]=[Number(t[1]),Number(t[2]),Number(t[3])],a=new Date(Date.UTC(r,o-1,s));return a.getUTCFullYear()===r&&a.getUTCMonth()===o-1&&a.getUTCDate()===s?e:void 0}var kr=4096,wr=new TextEncoder;function Ar(n){let e=k(n.challenge_data),t=k(n.challenge_data_hash);return e===""||!vr.test(t)?{}:wr.encode(e).length>kr?{}:{data:e,dataHash:t}}function Tr(n){let e=n??{},t=de(e.period_start_at),r=de(e.period_ends_at);if(t===0||r===0)return;let o=k(e.slug),s=k(e.seed),a=Sr(e.period_local_date),l=k(e.boundary),d=k(e.reset_time);return {id:k(e.progression_definition_id),...o===""?{}:{slug:o},window:k(e.window),periodStartAt:t,periodEndsAt:r,...a===void 0?{}:{periodLocalDate:a},boundary:Rr.test(l)?l:"",resetTime:xr.test(d)?d:"",seed:br.test(s)?s:"",...Ar(e)}}function ue(n){if(n!==void 0&&(!Number.isInteger(n)||n<0||n>400))throw new TypeError(`periodsBack must be an integer between 0 and 400, got ${String(n)}`)}function ce(n){let e=n??{};return Array.isArray(e.challenges)?e.challenges.map(Tr).filter(t=>t!==void 0):[]}function ge(n){return {async list(e){let{playerId:t,periodsBack:r,signal:o}=e??{};if(typeof t!="string"||t==="")throw new TypeError("gem.challenges.list needs { playerId }: a game-server token names no player, so the platform cannot tell whose period you mean. Pass the id from join() or gem.players().");ue(r);let s=await n({player_id:t,...r===void 0?{}:{periods_back:r},...o===void 0?{}:{signal:o}});return ce(s)}}}function Pr(n){let e={};for(let[t,r]of Object.entries(H))if(typeof r=="function"){let o=r;e[t]=(...s)=>o(n,...s);}return e}function M(n,e={}){let t=e.clock??G,r=e.baseUrl??n.apiBaseUrl;if(!r)throw new Error("this runtime names no gem-api host (host.apiBaseUrl is missing). The server image running this bundle predates token delivery \u2014 the bundle cannot call gem-api on it.");let o=N(n,{clock:t,...e.onAuthStateChange===void 0?{}:{onStateChange:e.onAuthStateChange}}),s=Q({baseUrl:r,tokenSource:o.source,defaultQuery:{game_id:n.gameId,channel:n.channel},...e.fetch===void 0?{}:{fetch:e.fetch}}),a=new P({transport:s,clock:t}),l={gameId:n.gameId,channel:n.channel,matchId:n.matchId,...n.gameRoomId===void 0?{}:{gameRoomId:n.gameRoomId}},d=Pr({client:a,gameId:()=>l.gameId}),c=l.gameRoomId,g=n.endMatch,b=n.log,x=le({client:a,clock:t,gameId:l.gameId,...typeof b=="function"?{log:v=>b.call(n,v)}:{}});return {identity:l,client:a,api:d,match:{end:async()=>{if(g===void 0)throw new Error("this runtime cannot end the match: the server image running this bundle predates host.endMatch, and only the platform half holds the allocation proof an end needs.");await g.call(n);}},analytics:x,functions:new E(d.invokeFunction),challenges:ge(d.listChallenges),...c===void 0?{}:{room:{get:v=>d.getGameRoomV2(c,v),args:async v=>{let y=await d.getGameRoomV2(c,v?.signal===void 0?{}:{signal:v.signal}),h=y.modified?y.body:void 0;if(h?.room_args==null||h.room_args_template==null)throw new m("not_found",404,"this room's template declares no room args",void 0,"room_args_not_defined");return {room_args:h.room_args,room_args_template:h.room_args_template}}}},dispose:()=>{x.dispose(),o.dispose();}}}var Or=["explicit","stale_cleanup","game_room_closed","replaced","migration_failed","host_left","insufficient_players","all_left","expired","migration_rate_exceeded","game_room_gone","failed","idle","reclaimed"],Gr=new Set(Or);function me(n){return typeof n=="string"&&Gr.has(n)?n:"unknown"}var R=class{#e;constructor(e){this.#e=e,Object.freeze(this);}toString(){return "[gem: use gem.text.toPlain()]"}toJSON(){return this.toString()}get[Symbol.toStringTag](){return "PlayerText"}static unwrap(e){return e.#e}};function q(n){return new R(n)}var pe={toPlain(n){return R.unwrap(n)},compare(n,e,t){let r=n instanceof R?R.unwrap(n):n,o=e instanceof R?R.unwrap(e):e,s;try{s=new Intl.Collator(t);}catch{s=new Intl.Collator;}return s.compare(r,o)},equals(n,e){let t=n instanceof R?R.unwrap(n):n,r=e instanceof R?R.unwrap(e):e;return t.normalize("NFC")===r.normalize("NFC")}};var ye="the match has not started yet: the runtime hands over the host at `init`, and this was read before that. Read it from `init` or later \u2014 a bundle that needs a value at module scope is reading it one call too early.";function V(n,e={}){let t=e.clock??G,r=()=>{let l=n();if(l===null)throw new Error(ye);return l},o=null,s=()=>{if(o===null)throw new Error(ye);return o};return {server:{get identity(){return s().identity},get client(){return s().client},get api(){return s().api},get match(){return s().match},get analytics(){return s().analytics},get functions(){return s().functions},get challenges(){return s().challenges},get room(){return s().room},dispose(){o?.dispose();},get sizeClass(){return r().sizeClass},get roomArgs(){return r().roomArgs},get roster(){return r().roster},players(){return r().players()},profile(l){let c=r().profile?.(l);if(!c)return null;let g=c.displayName;return typeof g!="string"||g===""?null:{displayName:q(g),...typeof c.displayTag=="string"&&c.displayTag!==""?{displayTag:q(c.displayTag)}:{},...typeof c.discriminator=="string"?{discriminator:c.discriminator}:{}}},playerNumber(l){return r().playerNumber?.(l)},send(l,d,c){c===void 0?r().send(l,d):r().send(l,d,c);},broadcast(l,d){d===void 0?r().broadcast(l):r().broadcast(l,d);},kick(l,d){d===void 0?r().kick(l):r().kick(l,d);},log(l){r().log(l);},warn(l){r().warn(l);}},attach:()=>{o=M(r(),{...e,clock:t});}}}function fe(n,e={}){let{server:t,attach:r}=V(()=>n,e);return r(),t}function Er(n){if(n===void 0||typeof n.reason!="string"||n.reason==="")return;let e=n.platform_reason??n.endedReason;return {reason:n.reason,...e===void 0?{}:{endedReason:me(e)}}}function he(n,e={}){return ()=>{let t=null,{server:r,attach:o}=V(()=>t,e),s=n(r),a={async init(l){t=l,o(),await s.init?.();},async shutdown(l){let d=Er(l);try{await s.shutdown?.(d);}finally{r.dispose();}}};return s.join&&(a.join=(l,d)=>s.join?.(l,d)),s.leave&&(a.leave=(l,d)=>s.leave?.(l,d)),s.message&&(a.message=(l,d,c,g)=>s.message?.(l,d,c,g)),a}}var Cr=new Set(["unlocked","already_unlocked","suppressed"]);function _e(n){let e=n?.changes;if(!Array.isArray(e))return [];let t=[];for(let r of e){let o=r??{};if(o.type!=="achievement_unlocked"||typeof o.outcome!="string"||!Cr.has(o.outcome)||typeof o.achievement_id!="string"||o.achievement_id==="")continue;let s=o.outcome;t.push({achievementId:o.achievement_id,progressionDefinitionId:typeof o.progression_definition_id=="string"?o.progression_definition_id:"",points:s==="unlocked"&&typeof o.points=="number"&&Number.isFinite(o.points)?o.points:0,outcome:s,...typeof o.reason=="string"?{reason:o.reason}:{}});}return t}
1
+ var ve=Object.defineProperty;var Re=(n,e)=>{for(var t in e)ve(n,t,{get:e[t],enumerable:true});};globalThis.__gemWebSdkVersion="[gem-web-sdk:sdkVersion:7.8.0]";function xe(n,e){return e!==void 0?!e:n==="chain_exhausted"}var $=class{constructor(e){this.options=e;}options;grant=null;state="pending";failure=null;generation=0;inFlight=null;rejected=false;get currentState(){return this.state}get lastFailure(){return this.failure}async get(){if(this.state==="lost")throw new _(this.failure??"unavailable","the session cannot be renewed");let e=this.seconds();if(this.grant&&e<this.grant.expiresAt-this.renewBefore())return this.grant.token;if(this.grant&&e>=this.grant.chainEndsAt)throw this.enter("lost","chain_exhausted"),new _("chain_exhausted","the token chain reached its ceiling");return this.refresh(this.nextReason())}nextReason(){return this.rejected?"rejected":this.grant?"expiring":"initial"}invalidate(e){e!==void 0&&this.grant!==null&&this.grant.token!==e||this.rejected&&this.grant===null||(this.grant=null,this.generation+=1,this.inFlight=null,this.rejected=true,this.state!=="lost"&&this.enter("pending"));}accept(e){this.state!=="lost"&&(this.grant=e,this.rejected=false,this.enter("ready"));}close(e="unavailable"){this.grant=null,this.generation+=1,this.inFlight=null,this.enter("lost",e);}refresh(e){if(this.inFlight)return this.inFlight;let t=this.generation;this.enter("pending");let r=this.options.request(e).then(o=>{if(t!==this.generation)throw new _("internal","token arrived for a superseded generation");return this.grant=o,this.rejected=false,this.enter("ready"),o.token}).catch(o=>{let s=Se(o),a=o?.retryable;throw t===this.generation&&this.enter(xe(s,typeof a=="boolean"?a:void 0)?"lost":"degraded",s),o instanceof _?o:new _(s,String(o))}).finally(()=>{this.inFlight===r&&(this.inFlight=null);});return this.inFlight=r,r}enter(e,t){this.failure=t??(e==="ready"?null:this.failure),this.state!==e&&(this.state=e,this.options.onStateChange?.(e,t));}renewBefore(){return this.options.renewBeforeSeconds??60}seconds(){return Math.floor(this.options.clock.now()/1e3)}},_=class n extends Error{constructor(t,r){super(`auth ${t}: ${r}`);this.reason=t;this.name="AuthError";}reason;static isAuthError(t){if(t instanceof n)return true;let r=t;return r?.name==="AuthError"&&typeof r.reason=="string"}};function Se(n){if(n instanceof _)return n.reason;let e=n?.reason;return typeof e=="string"&&["chain_exhausted","unavailable","timeout","internal"].includes(e)?e:"internal"}var p=class n extends Error{retryable=false;constructor(e){super(e),this.name="TransportRefusal";}static isRefusal(e){if(e instanceof n)return true;let t=e;return t?.name==="TransportRefusal"&&t.retryable===false}},j=["if-match","if-none-match"],W=4096;function ke(n){if(!n)return;let e={};for(let[t,r]of Object.entries(n)){let o=t.toLowerCase();if(!j.includes(o)||r===void 0)continue;let s=typeof r=="string"?we(r):r;if(typeof s!="string"||s.length>W||!Ae(s))throw new p(`the ${o} header value cannot be sent \u2014 it is not a string, is longer than ${W} characters, or contains a character outside the range an HTTP header value may carry. This is a malformed request, not a server failure; the value is withheld here rather than written to logs.`);s!==""&&(e[o]=s);}return Object.freeze(e)}function we(n){let e=o=>o===32||o===9||o===10||o===13,t=0,r=n.length;for(;t<r&&e(n.charCodeAt(t));)t++;for(;r>t&&e(n.charCodeAt(r-1));)r--;return n.slice(t,r)}function Ae(n){for(let e=0;e<n.length;e++){let t=n.charCodeAt(e);if(t!==9&&(t<32||t===127||t>255))return false}return true}function Te(n){let{bytes:e}=n;if(e!==void 0){if(Object.prototype.toString.call(e)!=="[object Uint8Array]")throw new p("the raw body is not a Uint8Array, so it cannot be sent as bytes. This is a malformed request, not a server failure.");if(n.body!==void 0)throw new p("the request carries both a JSON body and a raw body, and only one can be sent. This is a malformed request, not a server failure.");return new Uint8Array(e)}}function z(n,e){let t=e.replayUnauthorizedOnce??true;return {async request(r){let o={...r},s=ke(o.headers),a=Te(o),l=Object.freeze({...o,headers:s,...a===void 0?{}:{bytes:a}}),d=await e.tokenSource.get(),c=await n(l,d);if(c.status!==401||!t)return c;e.tokenSource.invalidate(d);let g=await e.tokenSource.get(),b=await n(l,g);if(b.status===401)throw e.tokenSource.close("unavailable"),new _("unavailable","the server refused a freshly minted token");return b}}}function K(n){let e=typeof n=="string"?new TextEncoder().encode(n):n;return btoa(Pe(e))}function Pe(n){let t="";for(let r=0;r<n.length;r+=32768)t+=String.fromCharCode(...n.subarray(r,r+32768));return t}var m=class extends Error{constructor(t,r,o,s,a){super(`${t} (${r}): ${o}`);this.reason=t;this.status=r;this.detail=o;this.retryAfterSeconds=s;this.code=a;this.name="GemApiError";}reason;status;detail;retryAfterSeconds;code;get retryable(){return this.reason==="unavailable"||this.reason==="rate_limited"}},J=new WeakMap;function X(n){return J.get(n)??{}}var Oe=new Set([408,429,500,502,503,504]),Ge=6e4;function Ee(n){if(n===void 0)return 2;if(!Number.isInteger(n)||n<0||n>10)throw new p(`maxRetries must be a whole number between 0 and 10; received ${JSON.stringify(n)}. This is a configuration fault, not a server failure.`);return n}var P=class{constructor(e){this.options=e;}options;async get(e,t){return this.send({method:"GET",path:e,signal:t},true)}async getWithEtag(e,t={}){let r=await this.sendRaw({method:"GET",path:e,...t.signal===void 0?{}:{signal:t.signal},...t.ifNoneMatch===void 0?{}:{headers:{"if-none-match":t.ifNoneMatch}}},true),o=r.etag===void 0?{}:{etag:r.etag};return r.status===304?{modified:false,...o}:{modified:true,body:r.body,...o}}async put(e,t,r,o={}){return this.send({method:"PUT",path:e,body:t,signal:r,...C(o)},o.replaySafe===true)}async post(e,t,r,o={}){return this.send({method:"POST",path:e,body:t,signal:r,...C(o)},o.replaySafe===true)}async postBytes(e,t,r,o={}){let s=await this.sendRaw({method:"POST",path:e,bytes:t,responseType:"bytes",signal:r,...C(o)},o.replaySafe===true);return {bytes:Ce(s.body),...s.invocationId===void 0?{}:{invocationId:s.invocationId}}}async patch(e,t,r,o={}){return this.send({method:"PATCH",path:e,body:t,signal:r,...C(o)},o.replaySafe===true)}async delete(e,t,r={}){return this.send({method:"DELETE",path:e,signal:t,...C(r)},r.replaySafe===true)}async send(e,t){return (await this.sendRaw(e,t)).body}async sendRaw(e,t){let r=t?Ee(this.options.maxRetries)+1:1,o=null;if(e.signal?.aborted)throw Y(e.signal);for(let s=0;s<r;s++){if(s>0&&await this.backoff(s,o,e.signal),e.signal?.aborted)throw Y(e.signal);let a;try{a=await this.options.transport.request(e);}catch(d){if(_.isAuthError(d)||p.isRefusal(d)||e.signal?.aborted||Ie(d))throw d;o=new m("unavailable",0,String(d));continue}if(a.status>=200&&a.status<300||a.status===304)return a;let l=qe(a);if(!Oe.has(a.status))throw l;o=l;}throw o??new m("unavailable",0,"no attempt was made")}backoff(e,t,r){if(r?.aborted)return Promise.resolve();let o=t?.retryAfterSeconds,s=o!==void 0?o*1e3:2**(e-1)*250,a=2**(e-1)*250,l=Math.min(Math.max(s,a),Ge);return new Promise(d=>{let c=this.options.clock,g=false,b=false,x,f=()=>{g||(g=true,b&&c.clearTimeout(x),r?.removeEventListener("abort",f),d());};r?.addEventListener("abort",f,{once:true}),x=c.setTimeout(f,l),b=true,g&&c.clearTimeout(x);})}};function Ce(n){if(n instanceof Uint8Array)return n;if(n==null)return new Uint8Array(0);let e=typeof n=="string"?n:JSON.stringify(n);return new TextEncoder().encode(e)}function C(n){return {...n.keepalive===void 0?{}:{keepalive:n.keepalive},...n.ifMatch===void 0?{}:{headers:{"if-match":n.ifMatch}}}}function Y(n){return n.reason!==void 0?n.reason:new DOMException("The operation was aborted.","AbortError")}function Ie(n){let e=n?.name;return e==="AbortError"||e==="TimeoutError"}function qe(n){let e=$e(n),t=Fe(n.body),r={...t===void 0?{}:{details:t},...n.invocationId===void 0?{}:{invocationId:n.invocationId}};return Object.keys(r).length>0&&J.set(e,r),e}var Le=new Map([["insufficient_funds","insufficient_funds"]]);function $e(n){let{status:e,body:t}=n,r=je(t),o=n.retryAfterSeconds??Ue(t),s=Me(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 Fe(n){let t=n?.error?.details;return t===null?void 0:t}function Me(n){let t=n?.error?.code;return typeof t=="string"&&t.length>0?t:void 0}function Ue(n){let e=n?.retryAfterSeconds;return typeof e=="number"&&Number.isFinite(e)&&e>=0?e:void 0}function Be(n){let e=n.lastIndexOf("@");return (e===-1?n:`***@${n.slice(e+1)}`).slice(0,200)}var Ne=new Set(j);function De(n){if(!n)return {};let e={};for(let[t,r]of Object.entries(n))Ne.has(t.toLowerCase())&&(e[t.toLowerCase()]=r);return e}function Q(n){let e=n.fetch??globalThis.fetch.bind(globalThis);return z(async(t,r)=>{let o;try{o=new URL(n.baseUrl.replace(/\/+$/,""));}catch{throw new p("the configured baseUrl is not a valid URL. Its value is withheld here rather than written to logs. This is a configuration fault, not a server failure.")}let s;try{s=new URL(o.href.replace(/\/+$/,"")+t.path);}catch{throw new p(`${JSON.stringify(typeof t.path=="string"?Be(t.path):"(a non-string path)")} does not form a valid URL against ${o.protocol}//${o.host}. This is a malformed request, not a server failure.`)}if(s.protocol!==o.protocol||s.host!==o.host)throw new p(`${JSON.stringify(s.pathname)} resolves to ${s.protocol}//${s.host}, not ${o.protocol}//${o.host}. A request path may not change the request's origin \u2014 it carries the play token.`);if(s.username!==""||s.password!==""){let f=o.username!==""||o.password!=="",v=s.username!==o.username||s.password!==o.password,y=f?v?"baseUrl (and possibly the request path)":"baseUrl":"request path";throw new p(`the ${y} puts credentials in the URL, which cannot be fetched (${t.method} ${s.pathname}). The value is withheld here rather than written to logs. This is a malformed request, not a server failure.`)}for(let[f,v]of Object.entries(n.defaultQuery??{}))s.searchParams.has(f)||s.searchParams.set(f,v);let a=t.bytes,l=t.bytes===void 0?void 0:"application/octet-stream";try{t.body!==void 0&&(a=JSON.stringify(t.body),l="application/json");}catch(f){throw new p(`the body of ${t.method} ${JSON.stringify(s.pathname)} could not be serialised to JSON: ${String(f)}. This is a bug in the request, not a server failure \u2014 retrying sends the same unserialisable value.`)}let d=await e(s.toString(),{method:t.method,headers:{authorization:`Bearer ${r}`,...l===void 0?{}:{"content-type":l},...De(t.headers)},body:a,signal:t.signal,...t.keepalive===void 0?{}:{keepalive:t.keepalive},credentials:"omit",mode:"cors",redirect:"error",cache:"no-store",referrerPolicy:"no-referrer"}),c=null;if(t.responseType==="bytes"&&d.status>=200&&d.status<300)c=new Uint8Array(await d.arrayBuffer());else {let f=await d.text();if(f.length>0)try{c=JSON.parse(f);}catch{c=f;}}let g=d.headers.get("etag"),b=He(d.headers.get("retry-after")),x=d.headers.get("x-gem-invocation-id");return {status:d.status,body:c,...g===null?{}:{etag:g},...b===void 0?{}:{retryAfterSeconds:b},...x===null||x===""?{}:{invocationId:x}}},n)}function He(n){if(n===null)return;let e=n.trim();if(!/^\d+$/.test(e))return;let t=Number(e);return Number.isFinite(t)?t:void 0}var Ve="gem-web-bridge";var O=65536,Z=8,F=5e3,ee=1024;function B(n){return Object.freeze(Object.assign(Object.create(null),n))}B({"gem.handshake":30,"gem.handshake.accept":5,"gem.token":30,"gem.token.denied":30,"gem.player":12,"gem.pause":120,"gem.prefs":60,"gem.cohorts":12,"gem.earnAllowanceChanged":30,"gem.viewport":60,"gem.deviceSettings":12,"gem.willTerminate":10,"gem.roomEvent":120,"gem.socketState":12,"gem.seatedEvent":60,"gem.autoStartFailedEvent":30,"gem.signalEvent":1800,"gem.dedicatedEvent":120,"gem.partyResult":30,"gem.clusterTarget":12,"gem.devtools":30,"gem.screenshot":6,"gem.screenshot.denied":12,"gem.requestContext":12,"gem.gameContext":12,"gem.signal":1200,"gem.dedicatedOffer":60,"gem.partyRequest":12,"gem.ready":5,"gem.engaged":5,"gem.progress":600,"gem.requestToken":12,"gem.requestLocalServer":6,"gem.localServer":30,"gem.localServer.denied":30,"gem.exit":5,"gem.openExternal":6,"gem.requestFullscreen":30,"gem.audioState":120,"gem.rewardCue":60,"gem.walletDisplay":60,"gem.requestShare":6,"gem.frameStats":120,"gem.error":60,"gem.requestPurchase":12,"gem.purchaseResult":30,"gem.deviceSettings.put":30,"gem.deviceSettings.result":30,"gem.requestAd":6,"gem.adResult":12,"gem.requestSignIn":6,"gem.signInResult":12,"gem.requestFriendChallenge":12,"gem.friendChallengeResult":30,__malformed:60});B({"gem.requestAd":"ads","gem.adResult":"ads","gem.requestSignIn":"signIn","gem.signInResult":"signIn","gem.requestPurchase":"purchases","gem.purchaseResult":"purchases","gem.requestFriendChallenge":"friendChallenges","gem.friendChallengeResult":"friendChallenges","gem.devtools":"devtools","gem.screenshot":"screenshot","gem.screenshot.denied":"screenshot","gem.requestContext":"feedbackContext","gem.gameContext":"feedbackContext","gem.roomEvent":"rooms","gem.signal":"p2p","gem.signalEvent":"p2p","gem.dedicatedOffer":"dedicated","gem.dedicatedEvent":"dedicated","gem.clusterTarget":"clusterTarget","gem.partyRequest":"parties","gem.partyResult":"parties","gem.autoStartFailedEvent":"autoStartFailure","gem.seatedEvent":"partySeating","gem.socketState":"socketState","gem.audioState":"audioState","gem.rewardCue":"rewardCue","gem.frameStats":"frameStats","gem.engaged":"engagement","gem.viewport":"viewport","gem.walletDisplay":"walletDisplay","gem.requestLocalServer":"localHost","gem.localServer":"localHost","gem.localServer.denied":"localHost","gem.cohorts":"cohorts","gem.earnAllowanceChanged":"earnAllowance","gem.deviceSettings":"deviceSettings","gem.deviceSettings.put":"deviceSettings","gem.deviceSettings.result":"deviceSettings","gem.requestShare":"share"});function ze(n){let e=/^([a-z][a-z0-9+.-]*):\/\/([a-z0-9.-]+|\[[0-9a-f:.]+\])(:([0-9]{1,5}))?$/i.exec(n);return e===null?false:e[4]===void 0||Number(e[4])<=65535}function Ke(n){let e;try{e=new URL(n);}catch{return false}return e.username!==""||e.password!==""?false:e.protocol==="https:"?true:e.protocol==="http:"&&(e.hostname==="localhost"||e.hostname==="127.0.0.1")}function Ye(n){return /^[a-z]{2,8}(-[a-z0-9]{1,8})*$/i.test(n)}function Je(n){return /^[a-z_]+$/.test(n)}function U(n,e,t){if(e>Z)return `nesting deeper than ${Z}`;if(++t.nodes>F)return `more than ${F} values`;if(t.bytes>O)return `over the ${O} byte limit`;if(n==null)return t.bytes+=4,null;let r=typeof n;if(r==="boolean")return t.bytes+=5,null;if(r==="number")return t.bytes+=8,null;if(r==="string")return t.bytes+=n.length*3+2,null;if(r!=="object")return `${r} is not plain data`;let o=n;if(t.seen.has(o))return "a repeated or cyclic object reference";if(t.seen.add(o),Array.isArray(n)){if(n.length>ee)return `an array of ${n.length} entries, over the ${ee} limit`;t.bytes+=2;for(let l of n){let d=U(l,e+1,t);if(d)return d}return null}let s=Object.getPrototypeOf(n);if(s!==Object.prototype&&s!==null)return "a value that is not a plain object";t.bytes+=2;let a=n;for(let l in a){if(!Object.prototype.hasOwnProperty.call(a,l))continue;if(++t.nodes>F)return `more than ${F} values`;if(t.bytes+=l.length*3+4,t.bytes>O)return `over the ${O} byte limit`;let d=U(a[l],e+1,t);if(d)return d}return null}function Xe(n){let e={nodes:0,bytes:0,seen:new Set},t=U(n,0,e);return t?`message contains ${t}`:e.bytes>O?`message is over the ${O} byte limit`:null}var Qe={origin:[ze,"not a well-formed origin"],url:[Ke,"not a safe absolute http(s) URL"],bcp47:[Ye,"not a well-formed BCP 47 tag"],code:[Je,"not a code of lower-case letters and underscores"]};function ne(n,e,t){for(let r of e){let o=t===""?r.n:`${t}.${r.n}`,s=n[r.n];if(s==null){if(r.o)continue;return `${o}: required`}let a=te(s,r,o);if(a)return a}return null}function te(n,e,t){switch(e.k){case "string":{if(typeof n!="string")return `${t}: expected string`;if(n.length>e.max)return `${t}: exceeds ${e.max} characters`;if(e.f){let[r,o]=Qe[e.f];if(!r(n))return `${t}: ${o}`}return null}case "int":return typeof n!="number"||!Number.isInteger(n)?`${t}: expected integer`:n<e.lo||n>e.hi?`${t}: out of range ${e.lo}..${e.hi}`:null;case "boolean":return typeof n=="boolean"?null:`${t}: expected boolean`;case "enum":{let r=e.v;return r.includes(n)?null:`${t}: not one of ${r.join("|")}`}case "object":return typeof n!="object"||n===null||Array.isArray(n)?`${t}: expected object`:ne(n,e.fs,t);case "json":return typeof n!="object"||n===null||Array.isArray(n)?`${t}: expected a plain object`:null;case "array":{if(!Array.isArray(n))return `${t}: expected array`;if(n.length>e.max)return `${t}: exceeds ${e.max} items`;let r=e.it,o=`${t}[]`;for(let s of n){if(s==null){if(r.o)continue;return `${o}: required`}let a=te(s,r,o);if(a)return a}return null}default:{let r=e.k;return `${t}: unknown kind ${String(r)}`}}}function u(n,e){return t=>{let r=Xe(t);if(r)return r;if(typeof t!="object"||t===null||Array.isArray(t))return "message: expected object";let o=t;return o.gem!==Ve?"gem: wrong protocol marker":o.type!==n?`type: expected ${n}`:ne(o,e,"")}}var Ze=u("gem.handshake",[{n:"versions",k:"object",fs:[{n:"min",k:"int",lo:1,hi:1e3},{n:"max",k:"int",lo:1,hi:1e3}]},{n:"capabilities",k:"array",o:1,max:64,it:{n:"",k:"string",max:64}},{n:"embedder",k:"string",max:2048,f:"origin"},{n:"unbidden",k:"boolean",o:1}]),en=u("gem.handshake.accept",[{n:"v",k:"int",lo:1,hi:1e3},{n:"capabilities",k:"array",o:1,max:64,it:{n:"",k:"string",max:64}}]),nn=u("gem.token",[{n:"token",k:"string",max:4096},{n:"requestId",k:"string",o:1,max:64},{n:"generation",k:"int",lo:0,hi:2147483647},{n:"apiBaseUrl",k:"string",o:1,max:512,f:"url"},{n:"playerId",k:"string",max:64},{n:"gameId",k:"string",max:64},{n:"channel",k:"enum",v:["dev","test","release"]},{n:"gameVersion",k:"string",o:1,max:64},{n:"expiresAt",k:"int",lo:0,hi:4102444800},{n:"chainEndsAt",k:"int",lo:0,hi:4102444800},{n:"allowDevTools",k:"boolean",o:1}]),tn=u("gem.token.denied",[{n:"requestId",k:"string",max:64},{n:"retryable",k:"boolean"},{n:"retryAfterMs",k:"int",o:1,lo:0,hi:36e5},{n:"reason",k:"enum",v:["chain_exhausted","unavailable"]},{n:"correlationId",k:"string",max:64}]),rn=u("gem.player",[{n:"untrusted",k:"object",fs:[{n:"displayName",k:"string",max:64},{n:"displayTag",k:"string",o:1,max:80},{n:"displayHandle",k:"string",max:80}]},{n:"playerId",k:"string",o:1,max:64},{n:"discriminator",k:"string",o:1,max:8},{n:"avatarIconUrl",k:"string",o:1,max:2048,f:"url"},{n:"badges",k:"array",o:1,max:2,it:{n:"",k:"object",fs:[{n:"itemId",k:"string",max:64},{n:"iconUrl",k:"string",max:2048,f:"url"}]}},{n:"displayTag",k:"string",max:8},{n:"avatarUrl",k:"string",o:1,max:2048,f:"url"},{n:"boost",k:"object",o:1,fs:[{n:"multipliers",k:"array",max:8,it:{n:"",k:"object",fs:[{n:"currencyId",k:"string",max:64},{n:"currencySlug",k:"string",max:32},{n:"multiplierBp",k:"int",lo:1e4,hi:1e6}]}},{n:"expiresInDays",k:"int",o:1,lo:1,hi:7}]}]),on=u("gem.pause",[{n:"paused",k:"boolean"}]),sn=u("gem.prefs",[{n:"reducedMotion",k:"boolean"},{n:"muted",k:"boolean"},{n:"showFrameStats",k:"boolean",o:1},{n:"locale",k:"string",max:35,f:"bcp47"}]),an=u("gem.cohorts",[{n:"cohorts",k:"array",max:8,it:{n:"",k:"object",fs:[{n:"experimentId",k:"string",max:36},{n:"variantKey",k:"string",max:32}]}}]),ln=u("gem.earnAllowanceChanged",[]),dn=u("gem.viewport",[{n:"insets",k:"object",fs:[{n:"top",k:"int",lo:0,hi:4096},{n:"right",k:"int",lo:0,hi:4096},{n:"bottom",k:"int",lo:0,hi:4096},{n:"left",k:"int",lo:0,hi:4096}]},{n:"reserved",k:"array",o:1,max:4,it:{n:"",k:"object",fs:[{n:"x",k:"int",lo:0,hi:16384},{n:"y",k:"int",lo:0,hi:16384},{n:"width",k:"int",lo:0,hi:16384},{n:"height",k:"int",lo:0,hi:16384}]}}]),un=u("gem.deviceSettings",[{n:"settings",k:"json",o:1}]),cn=u("gem.willTerminate",[{n:"reason",k:"enum",v:["grant_expiring","session_ended","navigating","kill_switch"]},{n:"graceMs",k:"int",lo:0,hi:6e4}]),gn=u("gem.roomEvent",[{n:"event",k:"enum",v:["updated","match_started","match_ready","match_failed","version_stale"]},{n:"roomId",k:"string",max:64},{n:"matchId",k:"string",o:1,max:64},{n:"version",k:"int",o:1,lo:0,hi:2147483647},{n:"reason",k:"string",o:1,max:64},{n:"platform",k:"enum",o:1,v:["universal","mobile"]}]),mn=u("gem.socketState",[{n:"connected",k:"boolean"},{n:"reason",k:"enum",o:1,v:["connecting","dropped","watchdog","terminal"]}]),pn=u("gem.seatedEvent",[{n:"roomId",k:"string",max:64}]),yn=u("gem.autoStartFailedEvent",[{n:"roomId",k:"string",max:64},{n:"code",k:"string",max:64}]),fn=u("gem.signalEvent",[{n:"event",k:"enum",v:["hello","offer","answer","ice","peerJoined","peerLeft","migration","matchEnded","error"]},{n:"matchId",k:"string",max:64},{n:"data",k:"json"}]),hn=u("gem.dedicatedEvent",[{n:"event",k:"enum",v:["answer","error","matchEnded"]},{n:"matchId",k:"string",max:64},{n:"sdp",k:"string",o:1,max:10240},{n:"sessionId",k:"string",o:1,max:64},{n:"code",k:"string",o:1,max:64},{n:"message",k:"string",o:1,max:256},{n:"reason",k:"string",o:1,max:64}]),_n=u("gem.partyResult",[{n:"requestId",k:"string",max:64},{n:"partyId",k:"string",o:1,max:64}]),bn=u("gem.clusterTarget",[{n:"clusterTargetId",k:"string",max:64},{n:"clusterTargetIds",k:"array",o:1,max:3,it:{n:"",k:"string",max:64}}]),vn=u("gem.devtools",[{n:"action",k:"enum",v:["open","close","toggle"]}]),Rn=u("gem.screenshot",[{n:"maxWidth",k:"int",lo:1,hi:7680},{n:"maxHeight",k:"int",lo:1,hi:4320}]),xn=u("gem.screenshot.denied",[{n:"reason",k:"enum",v:["not_wired","no_source","unsupported","unreadable","tainted","too_large","busy","declined","failed"]},{n:"retryable",k:"boolean"}]),Sn=u("gem.requestContext",[]),kn=u("gem.gameContext",[{n:"context",k:"json"}]),wn=u("gem.signal",[{n:"signal",k:"enum",v:["join","offer","answer","ice","migrationAck","hostUnreachable"]},{n:"matchId",k:"string",max:64},{n:"data",k:"json"}]),An=u("gem.dedicatedOffer",[{n:"matchId",k:"string",max:64},{n:"sdp",k:"string",max:10240},{n:"intent",k:"enum",v:["initial","ice_restart","full_reconnect"]}]),Tn=u("gem.partyRequest",[{n:"requestId",k:"string",max:64}]),Pn=u("gem.ready",[]),On=u("gem.engaged",[]),Gn=u("gem.progress",[{n:"loaded",k:"int",lo:0,hi:1099511627776},{n:"total",k:"int",lo:0,hi:1099511627776}]),En=u("gem.requestToken",[{n:"requestId",k:"string",max:64},{n:"reason",k:"enum",v:["initial","expiring","rejected"]}]),Cn=u("gem.requestLocalServer",[{n:"requestId",k:"string",max:64},{n:"gameRoomId",k:"string",max:64}]),In=u("gem.localServer",[{n:"requestId",k:"string",max:64},{n:"serverId",k:"string",o:1,max:128}]),qn=u("gem.localServer.denied",[{n:"requestId",k:"string",max:64},{n:"retryable",k:"boolean"},{n:"reason",k:"enum",v:["refused","unavailable"]}]),Ln=u("gem.exit",[{n:"reason",k:"string",o:1,max:64}]),$n=u("gem.openExternal",[{n:"url",k:"string",max:2048,f:"url"}]),jn=u("gem.requestFullscreen",[{n:"enabled",k:"boolean"}]),Fn=u("gem.audioState",[{n:"muted",k:"boolean"}]),Mn=u("gem.rewardCue",[{n:"currencySlug",k:"string",max:32},{n:"expected",k:"int",o:1,lo:1,hi:1e9},{n:"origin",k:"object",o:1,fs:[{n:"x",k:"int",lo:0,hi:16384},{n:"y",k:"int",lo:0,hi:16384}]}]),Un=u("gem.walletDisplay",[{n:"visible",k:"boolean"},{n:"currencies",k:"array",o:1,max:8,it:{n:"",k:"string",max:64}},{n:"score",k:"boolean",o:1}]),Bn=u("gem.requestShare",[{n:"params",k:"array",max:16,it:{n:"",k:"object",fs:[{n:"key",k:"string",max:64},{n:"value",k:"string",max:512}]}}]),Nn=u("gem.frameStats",[{n:"fps",k:"int",lo:0,hi:1e3},{n:"frameTimeP95Ms",k:"int",lo:0,hi:1e5}]),Dn=u("gem.error",[{n:"code",k:"enum",v:["version_mismatch","handshake_timeout","handshake_duplicate","invalid_message","rate_limited","token_unavailable","unsupported","unsupported_capability","internal"]},{n:"message",k:"string",o:1,max:256}]),Hn=u("gem.requestPurchase",[{n:"requestId",k:"string",max:64},{n:"purchaseKind",k:"enum",v:["item","recipe"]},{n:"targetId",k:"string",max:64},{n:"currencySlug",k:"string",max:32},{n:"quantity",k:"int",o:1,lo:1,hi:10},{n:"catalogId",k:"string",o:1,max:64}]),Vn=u("gem.purchaseResult",[{n:"requestId",k:"string",max:64},{n:"outcome",k:"enum",v:["ok","declined","unavailable"]},{n:"reason",k:"string",o:1,max:64,f:"code"},{n:"purchaseId",k:"string",o:1,max:64}]),Wn=u("gem.deviceSettings.put",[{n:"requestId",k:"string",max:64},{n:"settings",k:"json"}]),zn=u("gem.deviceSettings.result",[{n:"requestId",k:"string",max:64},{n:"outcome",k:"enum",v:["stored","too_large","unavailable"]}]),Kn=u("gem.requestAd",[{n:"requestId",k:"string",max:64},{n:"placement",k:"string",max:32},{n:"format",k:"enum",v:["interstitial","rewarded"]}]),Yn=u("gem.adResult",[{n:"requestId",k:"string",max:64},{n:"outcome",k:"enum",v:["shown","no_ad","unavailable"]}]),Jn=u("gem.requestSignIn",[{n:"requestId",k:"string",max:64}]),Xn=u("gem.signInResult",[{n:"requestId",k:"string",max:64},{n:"outcome",k:"enum",v:["signed_in","declined","unavailable"]}]),Qn=u("gem.requestFriendChallenge",[{n:"requestId",k:"string",max:64},{n:"playerId",k:"string",max:64},{n:"template",k:"string",max:64},{n:"params",k:"json",o:1}]),Zn=u("gem.friendChallengeResult",[{n:"requestId",k:"string",max:64},{n:"outcome",k:"enum",v:["accepted","cancelled","refused","unavailable","rate_limited","invalid"]},{n:"code",k:"string",o:1,max:64},{n:"param",k:"string",o:1,max:64},{n:"channel",k:"string",o:1,max:16},{n:"configVersion",k:"int",o:1,lo:0,hi:9007199254740991},{n:"retryAfterMs",k:"int",o:1,lo:0,hi:864e5},{n:"detail",k:"string",o:1,max:300}]);B({"gem.handshake":Ze,"gem.handshake.accept":en,"gem.token":nn,"gem.token.denied":tn,"gem.player":rn,"gem.pause":on,"gem.prefs":sn,"gem.cohorts":an,"gem.earnAllowanceChanged":ln,"gem.viewport":dn,"gem.deviceSettings":un,"gem.willTerminate":cn,"gem.roomEvent":gn,"gem.socketState":mn,"gem.seatedEvent":pn,"gem.autoStartFailedEvent":yn,"gem.signalEvent":fn,"gem.dedicatedEvent":hn,"gem.partyResult":_n,"gem.clusterTarget":bn,"gem.devtools":vn,"gem.screenshot":Rn,"gem.screenshot.denied":xn,"gem.requestContext":Sn,"gem.gameContext":kn,"gem.signal":wn,"gem.dedicatedOffer":An,"gem.partyRequest":Tn,"gem.ready":Pn,"gem.engaged":On,"gem.progress":Gn,"gem.requestToken":En,"gem.requestLocalServer":Cn,"gem.localServer":In,"gem.localServer.denied":qn,"gem.exit":Ln,"gem.openExternal":$n,"gem.requestFullscreen":jn,"gem.audioState":Fn,"gem.rewardCue":Mn,"gem.walletDisplay":Un,"gem.requestShare":Bn,"gem.frameStats":Nn,"gem.error":Dn,"gem.requestPurchase":Hn,"gem.purchaseResult":Vn,"gem.deviceSettings.put":Wn,"gem.deviceSettings.result":zn,"gem.requestAd":Kn,"gem.adResult":Yn,"gem.requestSignIn":Jn,"gem.signInResult":Xn,"gem.requestFriendChallenge":Qn,"gem.friendChallengeResult":Zn});var G={now:()=>Date.now(),setTimeout:(n,e)=>setTimeout(n,e),clearTimeout:n=>clearTimeout(n)};var et=1e4;function re(n,e){return N(n,e)}function N(n,e){if(typeof n.serverToken!="function"||typeof n.onServerToken!="function")throw new Error("this runtime delivers no game-server token: host.serverToken/onServerToken are missing. The server image running this bundle predates token delivery \u2014 the bundle cannot call gem-api on it.");let t=a=>({token:a.token,expiresAt:a.expiresAt,chainEndsAt:Number.POSITIVE_INFINITY}),r=null,o=new $({clock:e.clock,...e.onStateChange===void 0?{}:{onStateChange:e.onStateChange},request:()=>new Promise((a,l)=>{let d=e.clock.setTimeout(()=>{r=null,l({reason:"unavailable",retryable:true});},e.timeoutMs??et);r={resolve:c=>{e.clock.clearTimeout(d),a(c);},reject:l,timer:d};})}),s=n.onServerToken(a=>{let l=t(a),d=r;if(d){r=null,d.resolve(l);return}o.accept(l);});return {source:o,dispose(){s(),r&&(e.clock.clearTimeout(r.timer),r.reject({reason:"unavailable",retryable:false}),r=null);}}}var H={};Re(H,{acceptTransfer:()=>nt,addEntityProgression:()=>tt,adminAction:()=>rt,cancelInventoryTransfer:()=>ot,claimEntityProgressionRewards:()=>st,closeGameRoom:()=>it,createEntityBatchOrder:()=>at,createEntityOrder:()=>lt,createSession:()=>dt,deleteEntityGameSetting:()=>ut,deleteEntitySave:()=>ct,deleteSession:()=>gt,deleteShowcaseValue:()=>mt,executeEntityRecipe:()=>pt,finalizeSaveUpload:()=>yt,getChannelAssignment:()=>ft,getDropRates:()=>ht,getEntityCurrency:()=>_t,getEntityGameSetting:()=>bt,getEntityInventory:()=>vt,getEntityInventoryItem:()=>Rt,getEntityLeaderboard:()=>xt,getEntityOrder:()=>St,getEntityProgression:()=>kt,getEntityRecipeAvailability:()=>wt,getEntityRecipeUsage:()=>At,getEntitySave:()=>Tt,getEvent:()=>Pt,getGameRoomV2:()=>Ot,getLeaderboard:()=>Gt,getPlayerGameProfile:()=>Et,getPurchaseCatalog:()=>Ct,getResolvedTemplate:()=>It,getRoomArgs:()=>qt,getShowcaseValue:()=>Lt,getTransferDetails:()=>$t,ingestAnalyticsEvents:()=>D,initiateInventoryTransfer:()=>jt,invokeFunction:()=>Ft,kickPlayer:()=>Mt,listChallenges:()=>Ut,listEntityGameSettings:()=>Bt,listEntityOrders:()=>Nt,listEntityProgressions:()=>Dt,listEntitySaves:()=>Ht,listEvents:()=>Vt,listGameRooms:()=>Wt,listResolvedTemplates:()=>zt,listTransfers:()=>Kt,maxEntityProgression:()=>Yt,putEntityGameSetting:()=>Jt,putRoomArgs:()=>Xt,putShowcaseValue:()=>Qt,rejectTransfer:()=>Zt,requestSaveUploadUrl:()=>er,resetEntityProgression:()=>nr,simulateEntityOrder:()=>tr,transferHostV2:()=>rr,updateGameRoomV2:()=>or});function i(n){let e=String(n);if(!/^[A-Za-z0-9_.-]{1,128}$/.test(e)||e==="."||e==="..")throw new TypeError(`${JSON.stringify(e)} is not a usable path segment \u2014 it is interpolated into a URL`);return encodeURIComponent(e)}async function nt(n,e,t){let r=`/v1/inventory/transfers/${i(e)}/accept`;return n.client.post(r,void 0,t?.signal)}async function tt(n,e,t,r,o,s){let a=`/v1/inventory/${i(e)}/${i(t)}/progressions/${i(r)}/add`;return n.client.post(a,o,s?.signal)}async function rt(n,e,t,r){let o=`/v1/voice/sessions/${i(e)}/admin`;return n.client.post(o,t,r?.signal)}async function ot(n,e,t){let r=`/v1/inventory/transfers/${i(e)}/cancel`;return n.client.post(r,void 0,t?.signal)}async function st(n,e,t,r,o,s){let a=`/v1/inventory/${i(e)}/${i(t)}/progressions/${i(r)}/claim`;return n.client.post(a,o,s?.signal)}async function it(n,e,t){let r=`/v1/games/${i(n.gameId())}/game-rooms/${i(e)}`;return n.client.delete(r,t?.signal)}async function at(n,e,t,r,o){let s=`/v1/inventory/${i(e)}/${i(t)}/orders/batch`;return n.client.post(s,r,o?.signal,{...o?.ifMatch===void 0?{}:{ifMatch:o.ifMatch}})}async function lt(n,e,t,r,o){let s=`/v1/inventory/${i(e)}/${i(t)}/orders`;return n.client.post(s,r,o?.signal,{...o?.ifMatch===void 0?{}:{ifMatch:o.ifMatch}})}async function dt(n,e,t){return n.client.post("/v1/voice/sessions",e,t?.signal)}async function ut(n,e,t,r,o){let s=`/v1/settings/${i(e)}/${i(t)}/${i(r)}`;return n.client.delete(s,o?.signal)}async function ct(n,e,t,r,o){let s=`/v1/saves/${i(e)}/${i(t)}/${i(r)}`;return n.client.delete(s,o?.signal)}async function gt(n,e,t){let r=`/v1/voice/sessions/${i(e)}`;return n.client.delete(r,t?.signal)}async function mt(n,e,t,r){let o=`/v1/showcase/players/${i(e)}/${i(t)}`;return n.client.delete(o,r?.signal)}async function pt(n,e,t,r,o){let s=`/v1/inventory/${i(e)}/${i(t)}/recipes/execute`;return n.client.post(s,r,o?.signal,{...o?.ifMatch===void 0?{}:{ifMatch:o.ifMatch}})}async function yt(n,e,t,r,o,s){let a=`/v1/saves/${i(e)}/${i(t)}/${i(r)}/finalize`;return n.client.post(a,o,s?.signal)}async function ft(n,e,t){let r=`/v1/games/${i(n.gameId())}/config/channels/${i(e)}`;return n.client.getWithEtag(r,{...t?.signal===void 0?{}:{signal:t.signal},...t?.ifNoneMatch===void 0?{}:{ifNoneMatch:t.ifNoneMatch}})}async function ht(n,e,t){let r=`/v1/inventory/loot-tables/${i(e)}/drop-rates`;return n.client.get(r,t?.signal)}async function _t(n,e,t,r,o){let s=`/v1/inventory/${i(e)}/${i(t)}/currencies/${i(r)}`;return n.client.get(s,o?.signal)}async function bt(n,e,t,r,o){let s=`/v1/settings/${i(e)}/${i(t)}/${i(r)}`;return n.client.getWithEtag(s,{...o?.signal===void 0?{}:{signal:o.signal},...o?.ifNoneMatch===void 0?{}:{ifNoneMatch:o.ifNoneMatch}})}async function vt(n,e,t,r){let o=new URLSearchParams;r?.include_buckets!==void 0&&o.set("include_buckets",String(r?.include_buckets)),r?.include_custom_data!==void 0&&o.set("include_custom_data",String(r?.include_custom_data)),r?.currency_limit!==void 0&&o.set("currency_limit",String(r?.currency_limit)),r?.currency_cursor!==void 0&&o.set("currency_cursor",String(r?.currency_cursor)),r?.item_limit!==void 0&&o.set("item_limit",String(r?.item_limit)),r?.item_cursor!==void 0&&o.set("item_cursor",String(r?.item_cursor)),r?.progression_limit!==void 0&&o.set("progression_limit",String(r?.progression_limit)),r?.progression_cursor!==void 0&&o.set("progression_cursor",String(r?.progression_cursor));let s=o.toString(),a=`/v1/inventory/${i(e)}/${i(t)}`+(s?`?${s}`:"");return n.client.get(a,r?.signal)}async function Rt(n,e,t,r,o){let s=`/v1/inventory/${i(e)}/${i(t)}/items/${i(r)}`;return n.client.get(s,o?.signal)}async function xt(n,e,t,r,o){let s=new URLSearchParams;o?.bucket_1!==void 0&&s.set("bucket_1",String(o?.bucket_1)),o?.bucket_2!==void 0&&s.set("bucket_2",String(o?.bucket_2)),o?.limit!==void 0&&s.set("limit",String(o?.limit)),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 St(n,e,t,r,o){let s=`/v1/inventory/${i(e)}/${i(t)}/orders/${i(r)}`;return n.client.get(s,o?.signal)}async function kt(n,e,t,r,o){let s=`/v1/inventory/${i(e)}/${i(t)}/progressions/${i(r)}`;return n.client.get(s,o?.signal)}async function wt(n,e,t,r,o,s){let a=`/v1/inventory/${i(e)}/${i(t)}/catalogs/${i(r)}/recipes/${i(o)}/availability`;return n.client.get(a,s?.signal)}async function At(n,e,t,r){let o=new URLSearchParams;r?.limit!==void 0&&o.set("limit",String(r?.limit));let s=o.toString(),a=`/v1/inventory/${i(e)}/${i(t)}/recipe-usage`+(s?`?${s}`:"");return n.client.get(a,r?.signal)}async function Tt(n,e,t,r,o){let s=`/v1/saves/${i(e)}/${i(t)}/${i(r)}`;return n.client.getWithEtag(s,{...o?.signal===void 0?{}:{signal:o.signal},...o?.ifNoneMatch===void 0?{}:{ifNoneMatch:o.ifNoneMatch}})}async function Pt(n,e,t){let r=`/v1/events/${i(e)}`;return n.client.get(r,t?.signal)}async function Ot(n,e,t){let r=`/v2/games/${i(n.gameId())}/game-rooms/${i(e)}`;return n.client.getWithEtag(r,{...t?.signal===void 0?{}:{signal:t.signal},...t?.ifNoneMatch===void 0?{}:{ifNoneMatch:t.ifNoneMatch}})}async function Gt(n,e,t){let r=new URLSearchParams;t?.bucket_1!==void 0&&r.set("bucket_1",String(t?.bucket_1)),t?.bucket_2!==void 0&&r.set("bucket_2",String(t?.bucket_2)),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 Et(n,e,t){let r=`/v1/profiles/players/${i(e)}`;return n.client.get(r,t?.signal)}async function Ct(n,e){let t=new URLSearchParams;e?.config_version!==void 0&&t.set("config_version",String(e?.config_version));let r=t.toString(),o="/v1/inventory/platform-funded-game-inventory-purchase-catalog"+(r?`?${r}`:"");return n.client.get(o,e?.signal)}async function It(n,e,t){let r=`/v1/game-room-templates/${i(e)}`;return n.client.get(r,t?.signal)}async function qt(n,e,t){let r=`/v1/games/${i(n.gameId())}/game-rooms/${i(e)}/room-args`;return n.client.get(r,t?.signal)}async function Lt(n,e,t,r){let o=`/v1/showcase/players/${i(e)}/${i(t)}`;return n.client.get(o,r?.signal)}async function $t(n,e,t){let r=`/v1/inventory/transfers/${i(e)}`;return n.client.get(r,t?.signal)}async function D(n,e,t){let r=`/v1/games/${i(n.gameId())}/analytics/events`;return n.client.post(r,e,t?.signal,{replaySafe:true})}async function jt(n,e,t){return n.client.post("/v1/inventory/transfers",e,t?.signal)}async function Ft(n,e,t){return n.client.postBytes("/v1/functions/invoke",e,t?.signal)}async function Mt(n,e,t,r){let o=`/v1/games/${i(n.gameId())}/game-rooms/${i(e)}/kick/${i(t)}`;return n.client.post(o,void 0,r?.signal)}async function Ut(n,e){let t=new URLSearchParams;e?.periods_back!==void 0&&t.set("periods_back",String(e?.periods_back)),e?.player_id!==void 0&&t.set("player_id",String(e?.player_id));let r=t.toString(),o="/v1/challenges"+(r?`?${r}`:"");return n.client.get(o,e?.signal)}async function Bt(n,e,t,r){let o=`/v1/settings/${i(e)}/${i(t)}`;return n.client.get(o,r?.signal)}async function Nt(n,e,t,r){let o=new URLSearchParams;r?.limit!==void 0&&o.set("limit",String(r?.limit)),r?.cursor!==void 0&&o.set("cursor",String(r?.cursor));let s=o.toString(),a=`/v1/inventory/${i(e)}/${i(t)}/orders`+(s?`?${s}`:"");return n.client.get(a,r?.signal)}async function Dt(n,e,t,r){let o=`/v1/inventory/${i(e)}/${i(t)}/progressions`;return n.client.get(o,r?.signal)}async function Ht(n,e,t,r){let o=new URLSearchParams;r?.limit!==void 0&&o.set("limit",String(r?.limit)),r?.cursor!==void 0&&o.set("cursor",String(r?.cursor));let s=o.toString(),a=`/v1/saves/${i(e)}/${i(t)}`+(s?`?${s}`:"");return n.client.get(a,r?.signal)}async function Vt(n,e){let t=new URLSearchParams;e?.include_inactive!==void 0&&t.set("include_inactive",String(e?.include_inactive)),e?.limit!==void 0&&t.set("limit",String(e?.limit)),e?.offset!==void 0&&t.set("offset",String(e?.offset));let r=t.toString(),o="/v1/events"+(r?`?${r}`:"");return n.client.get(o,e?.signal)}async function Wt(n,e){let t=new URLSearchParams;e?.status!==void 0&&t.set("status",String(e?.status)),e?.game_channel!==void 0&&t.set("game_channel",String(e?.game_channel)),e?.game_room_type!==void 0&&t.set("game_room_type",String(e?.game_room_type)),e?.template_id!==void 0&&t.set("template_id",String(e?.template_id)),e?.template_slug!==void 0&&t.set("template_slug",String(e?.template_slug)),e?.limit!==void 0&&t.set("limit",String(e?.limit)),e?.cursor!==void 0&&t.set("cursor",String(e?.cursor));let r=t.toString(),o=`/v1/games/${i(n.gameId())}/game-rooms`+(r?`?${r}`:"");return n.client.get(o,e?.signal)}async function zt(n,e){return n.client.get("/v1/game-room-templates",e?.signal)}async function Kt(n,e){let t=new URLSearchParams;e.entity_type!==void 0&&t.set("entity_type",String(e.entity_type)),e.entity_id!==void 0&&t.set("entity_id",String(e.entity_id)),e?.direction!==void 0&&t.set("direction",String(e?.direction)),e?.status!==void 0&&t.set("status",String(e?.status)),e?.cursor!==void 0&&t.set("cursor",String(e?.cursor)),e?.limit!==void 0&&t.set("limit",String(e?.limit));let r=t.toString(),o="/v1/inventory/transfers"+(r?`?${r}`:"");return n.client.get(o,e?.signal)}async function Yt(n,e,t,r,o,s){let a=`/v1/inventory/${i(e)}/${i(t)}/progressions/${i(r)}/max`;return n.client.post(a,o,s?.signal)}async function Jt(n,e,t,r,o,s){let a=`/v1/settings/${i(e)}/${i(t)}/${i(r)}`;return n.client.put(a,o,s?.signal,{...s?.ifMatch===void 0?{}:{ifMatch:s.ifMatch}})}async function Xt(n,e,t,r){let o=`/v1/games/${i(n.gameId())}/game-rooms/${i(e)}/room-args`;return n.client.put(o,t,r?.signal)}async function Qt(n,e,t,r,o){let s=`/v1/showcase/players/${i(e)}/${i(t)}`;return n.client.put(s,r,o?.signal)}async function Zt(n,e,t){let r=`/v1/inventory/transfers/${i(e)}/reject`;return n.client.post(r,void 0,t?.signal)}async function er(n,e,t,r,o,s){let a=`/v1/saves/${i(e)}/${i(t)}/${i(r)}/upload-url`;return n.client.post(a,o,s?.signal,{replaySafe:true})}async function nr(n,e,t,r,o,s){let a=`/v1/inventory/${i(e)}/${i(t)}/progressions/${i(r)}/reset`;return n.client.post(a,o,s?.signal)}async function tr(n,e,t,r,o){let s=`/v1/inventory/${i(e)}/${i(t)}/orders/simulate`;return n.client.post(s,r,o?.signal)}async function rr(n,e,t,r){let o=`/v2/games/${i(n.gameId())}/game-rooms/${i(e)}/transfer/${i(t)}`;return n.client.post(o,void 0,r?.signal)}async function or(n,e,t,r){let o=`/v2/games/${i(n.gameId())}/game-rooms/${i(e)}`;return n.client.patch(o,t,r?.signal,{...r?.ifMatch===void 0?{}:{ifMatch:r.ifMatch}})}var oe="gem_";var ar=1e4,lr=50,dr=1e3,ur=65536-4*1024,se=n=>typeof n=="number"?n:0,cr=n=>typeof n=="string"?n:"";function ie(){let n=globalThis.crypto;return typeof n?.randomUUID=="function"?n.randomUUID():"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,e=>{let t=Math.floor(Math.random()*16);return (e==="x"?t:t&3|8).toString(16)})}function gr(n){return n?.retryable===true}function mr(n,e){let t=n??{},r=Array.isArray(t.rejected)?t.rejected.map(o=>{let s=o??{};return {index:se(s.index),code:cr(s.code)}}):[];return {accepted:se(t.accepted),rejected:r,dropped:e,duplicate:t.duplicate===true}}function ae(n,e){return {event_uid:n.uid,name:n.name,offset_ms:Math.round(n.atMs)-e,player_id:n.playerId,dimensions:n.dimensions,measures:n.measures}}function le(n){let e=Math.max(1,Math.floor(n.maxQueue??dr)),t={client:n.client,gameId:()=>n.gameId},r=[],o=0,s=null,a=false,l=false,d=false,c=false,g=y=>{n.log?.(y);},b=()=>{s!==null&&(n.clock.clearTimeout(s),s=null);},x=()=>{s!==null||a||l||(s=n.clock.setTimeout(()=>{s=null,v().catch(()=>{});},ar));},f=()=>{let y=Math.min(r.length,100),h=128;for(let w=0;w<y;w+=1){let A=r[w];if(A===void 0)break;if(h+=JSON.stringify(ae(A,0)).length+1,h>ur)return Math.max(1,w)}return y};async function v(y){if(r.length===0)return {accepted:0,rejected:[],dropped:0,duplicate:false};b();let h=r.splice(0,f()),w=o;o=0;let A=Math.round(n.clock.now()),L={batch_id:ie(),sent_at_ms:A,events:h.map(S=>ae(S,A))};l=true;try{let S=await D(t,L,y===void 0?void 0:{signal:y}),T=mr(S,w);for(let be of T.rejected)g(`[gem] analytics: an event was refused (${be.code}). See the analytics_events section of your game config.`);return T}catch(S){if(gr(S))for(r=[...h,...r],o+=w;r.length>e;)r.shift(),o+=1;else g(`[gem] analytics: ${h.length} event(s) were discarded \u2014 the platform refused the batch and will refuse it again: ${String(S)}`);throw S}finally{l=false,r.length>0&&x();}}return {track(y,h,w={}){if(a)return;if(typeof y!="string"||y===""){c||(c=true,g(`[gem] analytics: '${h}' was not recorded \u2014 an event from a server has to name the player it is about. A game-server token names no player, so the platform cannot infer one; pass the id from join() or host.players().`));return}if(h.startsWith(oe)){d||(d=true,g(`[gem] analytics: '${h}' was not recorded \u2014 the gem_ prefix is reserved, and the platform's own events are client-sourced, so a server may not emit one at all. Name your event something else.`));return}let A={},L={};for(let[S,T]of Object.entries(w))typeof T=="string"?A[S]=T:typeof T=="number"&&Number.isFinite(T)&&(L[S]=T);for(;r.length>=e;)r.shift(),o+=1;r.push({uid:ie(),playerId:y,name:h,atMs:n.clock.now(),dimensions:A,measures:L}),r.length>=lr?v().catch(()=>{}):x();},flush:y=>v(y),get pending(){return r.length},dispose(){a=true,b(),r=[],o=0;}}}var pr=new Map([["function_error",false],["function_failed",false],["function_timeout",false],["function_not_published",false],["function_input_too_large",false],["functions_not_configured",false],["forbidden",false],["function_capacity_unavailable",true],["function_host_unreachable",true],["function_host_error",true],["rate_limited",true],["service_unavailable",true]]),I=class extends m{constructor(e,t){super(e.reason,e.status,e.detail,e.retryAfterSeconds,e.code),this.name="GemFunctionError",Object.assign(this,t);}get retryable(){return (this.code===void 0?void 0:pr.get(this.code))??super.retryable}},E=class{#e;constructor(e){this.#e=e;}async invoke(e,t={}){let r=yr(e),o;try{o=await this.#e(r,t.signal===void 0?{}:{signal:t.signal});}catch(s){throw s instanceof m?hr(s):s}return fr(o)}};function yr(n){if(n instanceof ArrayBuffer)return new Uint8Array(n);if(ArrayBuffer.isView(n))return new Uint8Array(n.buffer,n.byteOffset,n.byteLength);let e;try{e=JSON.stringify(n);}catch(t){throw new p(`the function input could not be serialised to JSON: ${String(t)}. Pass bytes, or a value JSON can carry. This is a bug in the call, not a server failure.`)}if(e===void 0)throw new p(`the function input is ${typeof n}, which JSON cannot carry. Pass bytes \u2014 an empty Uint8Array for no input \u2014 or a JSON value. This is a bug in the call, not a server failure.`);return new TextEncoder().encode(e)}function fr(n){let{bytes:e}=n,t=()=>new TextDecoder("utf-8",{fatal:true}).decode(e);return {bytes:e,...n.invocationId===void 0?{}:{invocationId:n.invocationId},text:t,json:()=>JSON.parse(t())}}function hr(n){let{details:e,invocationId:t}=X(n),o=e?.untrusted?.message,s=e?.reason;return new I(n,{...t===void 0?{}:{invocationId:t},...n.code==="function_error"&&typeof o=="string"?{functionMessage:o}:{},...n.code==="function_failed"&&typeof s=="string"?{failure:s}:{}})}var k=n=>typeof n=="string"?n:"",_r=/(?:Z|[+-]\d{2}:?\d{2})$/i;function de(n){let e=k(n);if(!_r.test(e))return 0;let t=Date.parse(e);return Number.isFinite(t)?Math.floor(t/1e3):0}var br=/^[0-9a-f]{1,64}$/,vr=/^[0-9a-f]{16}$/,Rr=/^[A-Za-z][A-Za-z0-9_+\-/]{0,63}$/,xr=/^(?:[01]\d|2[0-3]):[0-5]\d$/;function Sr(n){let e=k(n),t=/^(\d{4})-(\d{2})-(\d{2})$/.exec(e);if(!t)return;let[r,o,s]=[Number(t[1]),Number(t[2]),Number(t[3])],a=new Date(Date.UTC(r,o-1,s));return a.getUTCFullYear()===r&&a.getUTCMonth()===o-1&&a.getUTCDate()===s?e:void 0}var kr=4096,wr=new TextEncoder;function Ar(n){let e=k(n.challenge_data),t=k(n.challenge_data_hash);return e===""||!vr.test(t)?{}:wr.encode(e).length>kr?{}:{data:e,dataHash:t}}function Tr(n){let e=n??{},t=de(e.period_start_at),r=de(e.period_ends_at);if(t===0||r===0)return;let o=k(e.slug),s=k(e.seed),a=Sr(e.period_local_date),l=k(e.boundary),d=k(e.reset_time);return {id:k(e.progression_definition_id),...o===""?{}:{slug:o},window:k(e.window),periodStartAt:t,periodEndsAt:r,...a===void 0?{}:{periodLocalDate:a},boundary:Rr.test(l)?l:"",resetTime:xr.test(d)?d:"",seed:br.test(s)?s:"",...Ar(e)}}function ue(n){if(n!==void 0&&(!Number.isInteger(n)||n<0||n>400))throw new TypeError(`periodsBack must be an integer between 0 and 400, got ${String(n)}`)}function ce(n){let e=n??{};return Array.isArray(e.challenges)?e.challenges.map(Tr).filter(t=>t!==void 0):[]}function ge(n){return {async list(e){let{playerId:t,periodsBack:r,signal:o}=e??{};if(typeof t!="string"||t==="")throw new TypeError("gem.challenges.list needs { playerId }: a game-server token names no player, so the platform cannot tell whose period you mean. Pass the id from join() or gem.players().");ue(r);let s=await n({player_id:t,...r===void 0?{}:{periods_back:r},...o===void 0?{}:{signal:o}});return ce(s)}}}function Pr(n){let e={};for(let[t,r]of Object.entries(H))if(typeof r=="function"){let o=r;e[t]=(...s)=>o(n,...s);}return e}function M(n,e={}){let t=e.clock??G,r=e.baseUrl??n.apiBaseUrl;if(!r)throw new Error("this runtime names no gem-api host (host.apiBaseUrl is missing). The server image running this bundle predates token delivery \u2014 the bundle cannot call gem-api on it.");let o=N(n,{clock:t,...e.onAuthStateChange===void 0?{}:{onStateChange:e.onAuthStateChange}}),s=Q({baseUrl:r,tokenSource:o.source,defaultQuery:{game_id:n.gameId,channel:n.channel},...e.fetch===void 0?{}:{fetch:e.fetch}}),a=new P({transport:s,clock:t}),l={gameId:n.gameId,channel:n.channel,matchId:n.matchId,...n.gameRoomId===void 0?{}:{gameRoomId:n.gameRoomId}},d=Pr({client:a,gameId:()=>l.gameId}),c=l.gameRoomId,g=n.endMatch,b=n.log,x=le({client:a,clock:t,gameId:l.gameId,...typeof b=="function"?{log:v=>b.call(n,v)}:{}});return {identity:l,client:a,api:d,match:{end:async()=>{if(g===void 0)throw new Error("this runtime cannot end the match: the server image running this bundle predates host.endMatch, and only the platform half holds the allocation proof an end needs.");await g.call(n);}},analytics:x,functions:new E(d.invokeFunction),challenges:ge(d.listChallenges),...c===void 0?{}:{room:{get:v=>d.getGameRoomV2(c,v),args:async v=>{let y=await d.getGameRoomV2(c,v?.signal===void 0?{}:{signal:v.signal}),h=y.modified?y.body:void 0;if(h?.room_args==null||h.room_args_template==null)throw new m("not_found",404,"this room's template declares no room args",void 0,"room_args_not_defined");return {room_args:h.room_args,room_args_template:h.room_args_template}}}},dispose:()=>{x.dispose(),o.dispose();}}}var Or=["explicit","stale_cleanup","game_room_closed","replaced","migration_failed","host_left","insufficient_players","all_left","expired","migration_rate_exceeded","game_room_gone","failed","idle","reclaimed"],Gr=new Set(Or);function me(n){return typeof n=="string"&&Gr.has(n)?n:"unknown"}var R=class{#e;constructor(e){this.#e=e,Object.freeze(this);}toString(){return "[gem: use gem.text.toPlain()]"}toJSON(){return this.toString()}get[Symbol.toStringTag](){return "PlayerText"}static unwrap(e){return e.#e}};function q(n){return new R(n)}var pe={toPlain(n){return R.unwrap(n)},compare(n,e,t){let r=n instanceof R?R.unwrap(n):n,o=e instanceof R?R.unwrap(e):e,s;try{s=new Intl.Collator(t);}catch{s=new Intl.Collator;}return s.compare(r,o)},equals(n,e){let t=n instanceof R?R.unwrap(n):n,r=e instanceof R?R.unwrap(e):e;return t.normalize("NFC")===r.normalize("NFC")}};var ye="the match has not started yet: the runtime hands over the host at `init`, and this was read before that. Read it from `init` or later \u2014 a bundle that needs a value at module scope is reading it one call too early.";function V(n,e={}){let t=e.clock??G,r=()=>{let l=n();if(l===null)throw new Error(ye);return l},o=null,s=()=>{if(o===null)throw new Error(ye);return o};return {server:{get identity(){return s().identity},get client(){return s().client},get api(){return s().api},get match(){return s().match},get analytics(){return s().analytics},get functions(){return s().functions},get challenges(){return s().challenges},get room(){return s().room},dispose(){o?.dispose();},get sizeClass(){return r().sizeClass},get roomArgs(){return r().roomArgs},get roster(){return r().roster},players(){return r().players()},profile(l){let c=r().profile?.(l);if(!c)return null;let g=c.displayName;return typeof g!="string"||g===""?null:{displayName:q(g),...typeof c.displayTag=="string"&&c.displayTag!==""?{displayTag:q(c.displayTag)}:{},...typeof c.discriminator=="string"?{discriminator:c.discriminator}:{}}},playerNumber(l){return r().playerNumber?.(l)},send(l,d,c){c===void 0?r().send(l,d):r().send(l,d,c);},broadcast(l,d){d===void 0?r().broadcast(l):r().broadcast(l,d);},kick(l,d){d===void 0?r().kick(l):r().kick(l,d);},log(l){r().log(l);},warn(l){r().warn(l);}},attach:()=>{o=M(r(),{...e,clock:t});}}}function fe(n,e={}){let{server:t,attach:r}=V(()=>n,e);return r(),t}function Er(n){if(n===void 0||typeof n.reason!="string"||n.reason==="")return;let e=n.platform_reason??n.endedReason;return {reason:n.reason,...e===void 0?{}:{endedReason:me(e)}}}function he(n,e={}){return ()=>{let t=null,{server:r,attach:o}=V(()=>t,e),s=n(r),a={async init(l){t=l,o(),await s.init?.();},async shutdown(l){let d=Er(l);try{await s.shutdown?.(d);}finally{r.dispose();}}};return s.join&&(a.join=(l,d)=>s.join?.(l,d)),s.leave&&(a.leave=(l,d)=>s.leave?.(l,d)),s.message&&(a.message=(l,d,c,g)=>s.message?.(l,d,c,g)),a}}var Cr=new Set(["unlocked","already_unlocked","suppressed"]);function _e(n){let e=n?.changes;if(!Array.isArray(e))return [];let t=[];for(let r of e){let o=r??{};if(o.type!=="achievement_unlocked"||typeof o.outcome!="string"||!Cr.has(o.outcome)||typeof o.achievement_id!="string"||o.achievement_id==="")continue;let s=o.outcome;t.push({achievementId:o.achievement_id,progressionDefinitionId:typeof o.progression_definition_id=="string"?o.progression_definition_id:"",points:s==="unlocked"&&typeof o.points=="number"&&Number.isFinite(o.points)?o.points:0,outcome:s,...typeof o.reason=="string"?{reason:o.reason}:{}});}return t}
2
2
  export{_ as AuthError,j as CONDITIONAL_HEADERS,E as FunctionsApi,m as GemApiError,P as GemClient,I as GemFunctionError,R as PlayerText,p as TransportRefusal,_e as achievementReceipts,q as asPlayerText,M 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
@@ -1384,6 +1384,7 @@ interface Room {
1384
1384
  readonly gameChannel: string;
1385
1385
  readonly region?: string;
1386
1386
  readonly clusterTargetId?: string;
1387
+ readonly selfHosted: boolean;
1387
1388
  readonly matchId?: string;
1388
1389
  readonly version: number;
1389
1390
  readonly templateId?: string;
@@ -1428,6 +1429,7 @@ declare function summaryFromWire(body: unknown): RoomSummary;
1428
1429
  interface RoomsApiOptions {
1429
1430
  readonly client: GemClient;
1430
1431
  readonly gameId: () => string;
1432
+ readonly selfHosted?: () => boolean;
1431
1433
  }
1432
1434
  interface CreateRoomOptions {
1433
1435
  readonly name: string;
@@ -1477,6 +1479,7 @@ declare class RoomsApi {
1477
1479
  joinByCode(code: string, options: JoinRoomOptions, version: ResolvedClientVersion): Promise<Room>;
1478
1480
  quickJoin(options: QuickJoinOptions, version: ResolvedClientVersion, clusterTargetIds?: readonly string[]): Promise<Room>;
1479
1481
  leave(roomId: string, asGroup: boolean, signal?: AbortSignal, keepalive?: boolean): Promise<void>;
1482
+ private asksSelfHosted;
1480
1483
  close(roomId: string, signal?: AbortSignal): Promise<void>;
1481
1484
  update(roomId: string, options: UpdateRoomOptions): Promise<Room>;
1482
1485
  setReady(roomId: string, isReady: boolean, signal?: AbortSignal): Promise<Room>;
@@ -1627,6 +1630,7 @@ interface RoomManagerOptions {
1627
1630
  readonly resolveClusterTargets?: ClusterTargetListResolver;
1628
1631
  readonly refreshClusterTargets?: ClusterTargetRefresher;
1629
1632
  readonly ensureLocalServer?: (gameRoomId: string) => Promise<void>;
1633
+ readonly localHostAvailable?: () => boolean;
1630
1634
  readonly autoReconnect?: AutoReconnectWiring;
1631
1635
  readonly recoverStaleMembership?: boolean;
1632
1636
  readonly retryAutoStart?: boolean;
package/dist/sdk.d.ts CHANGED
@@ -1684,6 +1684,7 @@ interface Room {
1684
1684
  readonly gameChannel: string;
1685
1685
  readonly region?: string;
1686
1686
  readonly clusterTargetId?: string;
1687
+ readonly selfHosted: boolean;
1687
1688
  readonly matchId?: string;
1688
1689
  readonly version: number;
1689
1690
  readonly templateId?: string;
@@ -4310,6 +4311,7 @@ interface GemOptions {
4310
4311
  readonly onDeviceSettings?: (settings: DeviceSettings | null) => void;
4311
4312
  readonly onViewport?: (viewport: GemViewport) => void;
4312
4313
  readonly manageAudio?: boolean;
4314
+ readonly selectableText?: boolean;
4313
4315
  readonly onPause?: (paused: boolean) => void;
4314
4316
  readonly onWillTerminate?: (notice: GemTerminationNotice) => void;
4315
4317
  readonly analytics?: AnalyticsOptions;
@@ -1,6 +1,6 @@
1
1
  # The browser surface — API reference
2
2
 
3
- Generated from `@indiegems/gem-web-sdk/sdk` v7.7.0. Every symbol below links to its page on the Gem Arcade developer site.
3
+ Generated from `@indiegems/gem-web-sdk/sdk` v7.8.0. Every symbol below links to its page on the Gem Arcade developer site.
4
4
 
5
5
  `@indiegems/gem-web-sdk/sdk` is the one import a game writes, wherever its code runs. `@indiegems/gem-web-sdk/game` exports exactly the symbols on this page and nothing else, for a build that wants only this half.
6
6
 
@@ -6194,6 +6194,25 @@ rather than cut it, say. The arcade shows its mute button for your game
6194
6194
  either way where it shows one, so `false` is a promise that your handler goes quiet on
6195
6195
  `muted: true`, and the release checklist holds you to it.
6196
6196
 
6197
+ ## GemOptions.selectableText
6198
+
6199
+ [GemOptions.selectableText](https://gemarcade.com/developer/api/game#gemoptions-selectabletext)
6200
+
6201
+ ```ts
6202
+ readonly selectableText?: boolean
6203
+ ```
6204
+
6205
+ Leave your page's text selectable. Default `false`: the SDK stops
6206
+ accidental text selection, the long-press copy menu and the tap highlight
6207
+ across your document, because in a game every one of them is a press the
6208
+ player did not mean.
6209
+
6210
+ Your own CSS always wins — the SDK's rule has zero specificity — so to make
6211
+ one element copyable, give it `user-select: text` (and
6212
+ `-webkit-user-select: text`). Inputs, text areas and editable content stay
6213
+ typeable and selectable without anything from you. Set this to `true` only
6214
+ if your game is mostly text a player should be able to copy.
6215
+
6197
6216
  ## GemOptions.onPause
6198
6217
 
6199
6218
  [GemOptions.onPause](https://gemarcade.com/developer/api/game#gemoptions-onpause)
@@ -14998,6 +15017,24 @@ Arcade measured for them, and a host moves it by naming another cluster on
14998
15017
  [RoomManager.startMatch](https://gemarcade.com/developer/api/game#roommanager-startmatch). Absent on a room created without one, such
14999
15018
  as by an older client or outside the Arcade.
15000
15019
 
15020
+ ## Room.selfHosted
15021
+
15022
+ [Room.selfHosted](https://gemarcade.com/developer/api/game#room-selfhosted)
15023
+
15024
+ ```ts
15025
+ readonly selfHosted: boolean
15026
+ ```
15027
+
15028
+ Whether this room's matches are served from the developer's own machine
15029
+ rather than by the platform.
15030
+
15031
+ True only inside a development tool that runs your game's server locally
15032
+ (the Gem Editor's play surface). The SDK asks for such a room on your
15033
+ behalf — there is no option for a game to set — and the platform keeps it
15034
+ to its host: no other player can join it, quick-join never matches into
15035
+ it, and the server browser never lists it. False on every room a player in
15036
+ the Arcade is in.
15037
+
15001
15038
  ## Room.matchId
15002
15039
 
15003
15040
  [Room.matchId](https://gemarcade.com/developer/api/game#room-matchid)
@@ -1,6 +1,6 @@
1
1
  # The server surface — API reference
2
2
 
3
- Generated from `@indiegems/gem-web-sdk/sdk` v7.7.0. Every symbol below links to its page on the Gem Arcade developer site.
3
+ Generated from `@indiegems/gem-web-sdk/sdk` v7.8.0. Every symbol below links to its page on the Gem Arcade developer site.
4
4
 
5
5
  `@indiegems/gem-web-sdk/sdk` is the one import a game writes, wherever its code runs. `@indiegems/gem-web-sdk/server` exports exactly the symbols on this page and nothing else, for a build that wants only this half.
6
6
 
@@ -2,7 +2,7 @@
2
2
  "schema_version": 1,
3
3
  "source": {
4
4
  "repo": "IndieGems/gem-web-sdk",
5
- "version": "7.7.0"
5
+ "version": "7.8.0"
6
6
  },
7
7
  "entries": [
8
8
  {
@@ -7572,6 +7572,23 @@
7572
7572
  "defaultValue": null,
7573
7573
  "guides": []
7574
7574
  },
7575
+ {
7576
+ "id": "GemOptions.selectableText",
7577
+ "name": "selectableText",
7578
+ "anchor": "gemoptions-selectabletext",
7579
+ "group": "start",
7580
+ "url": "https://gemarcade.com/developer/api/game#gemoptions-selectabletext",
7581
+ "signature": "readonly selectableText?: boolean",
7582
+ "documented": true,
7583
+ "summary": "Leave your page's text selectable. Default `false`: the SDK stops\naccidental text selection, the long-press copy menu and the tap highlight\nacross your document, because in a game every one of them is a press the\nplayer did not mean.\n\nYour own CSS always wins — the SDK's rule has zero specificity — so to make\none element copyable, give it `user-select: text` (and\n`-webkit-user-select: text`). Inputs, text areas and editable content stay\ntypeable and selectable without anything from you. Set this to `true` only\nif your game is mostly text a player should be able to copy.",
7584
+ "deprecated": null,
7585
+ "params": [],
7586
+ "returns": null,
7587
+ "throws": null,
7588
+ "example": null,
7589
+ "defaultValue": null,
7590
+ "guides": []
7591
+ },
7575
7592
  {
7576
7593
  "id": "GemOptions.onPause",
7577
7594
  "name": "onPause",
@@ -18240,6 +18257,23 @@
18240
18257
  "defaultValue": null,
18241
18258
  "guides": []
18242
18259
  },
18260
+ {
18261
+ "id": "Room.selfHosted",
18262
+ "name": "selfHosted",
18263
+ "anchor": "room-selfhosted",
18264
+ "group": "rooms",
18265
+ "url": "https://gemarcade.com/developer/api/game#room-selfhosted",
18266
+ "signature": "readonly selfHosted: boolean",
18267
+ "documented": true,
18268
+ "summary": "Whether this room's matches are served from the developer's own machine\nrather than by the platform.\n\nTrue only inside a development tool that runs your game's server locally\n(the Gem Editor's play surface). The SDK asks for such a room on your\nbehalf — there is no option for a game to set — and the platform keeps it\nto its host: no other player can join it, quick-join never matches into\nit, and the server browser never lists it. False on every room a player in\nthe Arcade is in.",
18269
+ "deprecated": null,
18270
+ "params": [],
18271
+ "returns": null,
18272
+ "throws": null,
18273
+ "example": null,
18274
+ "defaultValue": null,
18275
+ "guides": []
18276
+ },
18243
18277
  {
18244
18278
  "id": "Room.matchId",
18245
18279
  "name": "matchId",
@@ -849,20 +849,29 @@ the same thing and a regression on either would be silent.
849
849
  Inside a development tool that can host — it advertises the `localHost` capability, which no
850
850
  player-facing embedder carries — the platform can dispatch a dedicated match to a server running
851
851
  on the developer's own machine instead of allocating one from the fleet. **Your game's source does
852
- not participate.** Immediately before starting a match, the SDK asks the embedder for a server for
853
- the room; the tool spawns your game's own server bundle, registers it with the platform, and the
854
- match that follows is dispatched to it. A game published to players never runs inside such an
855
- embedder, so there is nothing to gate and nothing to remove before shipping.
856
-
857
- Three things are worth knowing while you develop this way:
858
-
859
- - **The ask happens before the match starts, and a refusal arrives as `startMatch()` rejecting —
860
- never as a hang.** The two failure shapes are deliberately different. A platform refusal (you are
861
- not signed in as a developer on this game, or the room is not on a development channel) is
862
- terminal, and retrying sends the same request to the same refusal. A machine that merely could
863
- not start the process is retryable, and your tool has the log. Silence is bounded too: an
864
- embedder that never answers is given thirty seconds, then the rejection says so. However many
865
- times a racing Start button asks, one server is started per room.
852
+ not participate.** Every room the SDK creates there — by `create()` or `quickJoin()` — is a
853
+ *self-hosted* room (`room.selfHosted` is `true`), and the moment the SDK holds one it asks the
854
+ embedder for a server for it; the tool spawns your game's own server bundle and registers it with
855
+ the platform. A self-hosted room's match is dispatched to that server and never to the fleet: a
856
+ template with `auto_start_host` waits for the registration and then starts by itself, and a start
857
+ your game makes waits for the server first. A game published to players never runs inside such
858
+ an embedder, so there is nothing to gate and nothing to remove before shipping.
859
+
860
+ Four things are worth knowing while you develop this way:
861
+
862
+ - **A self-hosted room is yours alone.** Nobody else can join it, `quickJoin()` makes a fresh one
863
+ rather than joining another player's room, and the server browser never lists it. The build you
864
+ are running does not need to be published on the channel: the platform skips its published-build
865
+ check for these rooms, though a blacklisted build is still refused. A room created with a party
866
+ is an ordinary room.
867
+
868
+ - **A refusal arrives as `startMatch()` rejecting — never as a hang.** The two failure shapes are
869
+ deliberately different. A platform refusal (you are not signed in as a developer on this game,
870
+ or the room is not on a development channel) is terminal, and retrying sends the same request
871
+ to the same refusal. A machine that merely could not start the process is retryable, and your
872
+ tool has the log. Silence is bounded too: an embedder that never answers is given thirty
873
+ seconds, then the rejection says so. However many times a racing Start button asks, one server
874
+ is started per room.
866
875
 
867
876
  - **The winning transport is usually WebSocket, so take the negotiated path.** A locally run server
868
877
  typically offers no WebTransport certificate chain and no WebRTC signaling; the ladder works
@@ -50,7 +50,7 @@ either way.
50
50
  ```jsonc
51
51
  // package.json
52
52
  "dependencies": {
53
- "@indiegems/gem-web-sdk": "7.7.0"
53
+ "@indiegems/gem-web-sdk": "7.8.0"
54
54
  }
55
55
  ```
56
56
 
@@ -48,8 +48,8 @@
48
48
  },
49
49
  {
50
50
  "file": "dedicated-server-flow.md",
51
- "sha256": "06dfa9341e924628f67d33e8751f523ea27a3bc91eb07f1f52aadc5e2aa62de7",
52
- "updated": "2026-09-24T19:20:12Z"
51
+ "sha256": "6da1bfc820ab2cf79180f69f9fec4d9f377ddde690f53923e749a88ec6307e22",
52
+ "updated": "2026-10-02T19:04:21Z"
53
53
  },
54
54
  {
55
55
  "file": "deprecation-policy.md",
@@ -68,8 +68,8 @@
68
68
  },
69
69
  {
70
70
  "file": "getting-started.md",
71
- "sha256": "4a3c179022bbc7143b190a27a78c6fac8f7f92d8964b2dc6aec7342b052f40e1",
72
- "updated": "2026-10-02T19:06:36Z"
71
+ "sha256": "d2179480be49085d828c9afbd89d1d72c00914c5607105831503f0652e521285",
72
+ "updated": "2026-10-02T21:18:29Z"
73
73
  },
74
74
  {
75
75
  "file": "inventory-and-catalogs.md",
@@ -118,8 +118,8 @@
118
118
  },
119
119
  {
120
120
  "file": "server-bundles.md",
121
- "sha256": "7d48bdbc026a03c78d26c24bf217fab1aa8df9d358fbe54c64fa53f18aa0d77b",
122
- "updated": "2026-10-02T19:06:36Z"
121
+ "sha256": "fed144c0d7b9f8be10fc3896a7325ab19aa660441c24038f39bc02b5fdf60cb3",
122
+ "updated": "2026-10-02T21:18:29Z"
123
123
  },
124
124
  {
125
125
  "file": "serverless-functions-js.md",
@@ -138,8 +138,8 @@
138
138
  },
139
139
  {
140
140
  "file": "what-a-game-must-do.md",
141
- "sha256": "a0a2952a2b16b43b0af831ff58ad8fabe47b414f57fccd2cb2d866861a65465e",
142
- "updated": "2026-10-02T14:04:37Z"
141
+ "sha256": "d7b66e2c04f5cea169ae4cecd3926e350e272232af32752e60a7a388dfd8c461",
142
+ "updated": "2026-10-02T21:01:44Z"
143
143
  }
144
144
  ]
145
145
  }
@@ -80,8 +80,8 @@ To check the download yourself: the package npm serves is, byte for byte, the fi
80
80
  also publishes on its download host, with the hash beside it:
81
81
 
82
82
  ```bash
83
- curl -fsSL -O https://downloads.gemarcade.com/sdk/v7.7.0/gem-web-sdk.tgz
84
- curl -fsSL https://downloads.gemarcade.com/sdk/v7.7.0/gem-web-sdk.tgz.sri
83
+ curl -fsSL -O https://downloads.gemarcade.com/sdk/v7.8.0/gem-web-sdk.tgz
84
+ curl -fsSL https://downloads.gemarcade.com/sdk/v7.8.0/gem-web-sdk.tgz.sri
85
85
  openssl dgst -sha384 -binary gem-web-sdk.tgz | openssl base64 -A
86
86
  ```
87
87