@indiegems/gem-web-sdk 5.10.0 → 5.11.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 ue=Object.defineProperty;var ce=(n,e)=>{for(var t in e)ue(n,t,{get:e[t],enumerable:true});};globalThis.__gemWebSdkVersion="[gem-web-sdk:sdkVersion:5.10.0]";function me(n,e){return e!==void 0?!e:n==="chain_exhausted"}var P=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=ge(o),a=o?.retryable;throw t===this.generation&&this.enter(me(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 ge(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 v=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}},E=["if-match","if-none-match"],N=4096;function pe(n){if(!n)return;let e={};for(let[t,r]of Object.entries(n)){let o=t.toLowerCase();if(!E.includes(o)||r===void 0)continue;let s=typeof r=="string"?ye(r):r;if(typeof s!="string"||s.length>N||!fe(s))throw new v(`the ${o} header value cannot be sent \u2014 it is not a string, is longer than ${N} 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 ye(n){let e=o=>o===32||o===9||o===10||o===13,t=0,r=n.length;for(;t<r&&e(n.charCodeAt(t));)t++;for(;r>t&&e(n.charCodeAt(r-1));)r--;return n.slice(t,r)}function fe(n){for(let e=0;e<n.length;e++){let t=n.charCodeAt(e);if(t!==9&&(t<32||t===127||t>255))return false}return true}function B(n,e){let t=e.replayUnauthorizedOnce??true;return {async request(r){let o={...r},s=pe(o.headers),a=Object.freeze({...o,headers:s}),l=await e.tokenSource.get(),d=await n(a,l);if(d.status!==401||!t)return d;e.tokenSource.invalidate(l);let c=await e.tokenSource.get(),m=await n(a,c);if(m.status===401)throw e.tokenSource.close("unavailable"),new _("unavailable","the server refused a freshly minted token");return m}}}function D(n){let e=typeof n=="string"?new TextEncoder().encode(n):n;return btoa(he(e))}function he(n){let t="";for(let r=0;r<n.length;r+=32768)t+=String.fromCharCode(...n.subarray(r,r+32768));return t}var p=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"}},_e=new Set([408,429,500,502,503,504]),ve=6e4;function be(n){if(n===void 0)return 2;if(!Number.isInteger(n)||n<0||n>10)throw new v(`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 A=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,...I(o)},o.replaySafe===true)}async post(e,t,r,o={}){return this.send({method:"POST",path:e,body:t,signal:r,...I(o)},o.replaySafe===true)}async patch(e,t,r,o={}){return this.send({method:"PATCH",path:e,body:t,signal:r,...I(o)},o.replaySafe===true)}async delete(e,t,r={}){return this.send({method:"DELETE",path:e,signal:t,...I(r)},r.replaySafe===true)}async send(e,t){return (await this.sendRaw(e,t)).body}async sendRaw(e,t){let r=t?be(this.options.maxRetries)+1:1,o=null;if(e.signal?.aborted)throw V(e.signal);for(let s=0;s<r;s++){if(s>0&&await this.backoff(s,o,e.signal),e.signal?.aborted)throw V(e.signal);let a;try{a=await this.options.transport.request(e);}catch(d){if(_.isAuthError(d)||v.isRefusal(d)||e.signal?.aborted||Re(d))throw d;o=new p("unavailable",0,String(d));continue}if(a.status>=200&&a.status<300||a.status===304)return a;let l=Se(a);if(!_e.has(a.status))throw l;o=l;}throw o??new p("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),ve);return new Promise(d=>{let c=this.options.clock,m=false,R=false,h,f=()=>{m||(m=true,R&&c.clearTimeout(h),r?.removeEventListener("abort",f),d());};r?.addEventListener("abort",f,{once:true}),h=c.setTimeout(f,l),R=true,m&&c.clearTimeout(h);})}};function I(n){return {...n.keepalive===void 0?{}:{keepalive:n.keepalive},...n.ifMatch===void 0?{}:{headers:{"if-match":n.ifMatch}}}}function V(n){return n.reason!==void 0?n.reason:new DOMException("The operation was aborted.","AbortError")}function Re(n){let e=n?.name;return e==="AbortError"||e==="TimeoutError"}function Se(n){let{status:e,body:t}=n,r=xe(t),o=n.retryAfterSeconds??we(t),s=ke(t);switch(e){case 304:return new p("not_modified",e,r);case 400:case 422:return new p("invalid",e,r,void 0,s);case 403:return new p("forbidden",e,r,void 0,s);case 404:return new p("not_found",e,r,void 0,s);case 402:return new p("insufficient_funds",e,r,void 0,s);case 409:return new p("conflict",e,r,void 0,s);case 412:return new p("precondition_failed",e,r,void 0,s);case 413:return new p("too_large",e,r,void 0,s);case 429:return new p("rate_limited",e,r,o,s);default:return new p("unavailable",e,r,o,s)}}function xe(n){if(typeof n=="string")return n;let e=n?.message;if(typeof e=="string")return e;let t=n?.error;if(typeof t=="string")return t;let r=t?.message;return typeof r=="string"?r:"no detail"}function ke(n){let t=n?.error?.code;return typeof t=="string"&&t.length>0?t:void 0}function we(n){let e=n?.retryAfterSeconds;return typeof e=="number"&&Number.isFinite(e)&&e>=0?e:void 0}function Ae(n){let e=n.lastIndexOf("@");return (e===-1?n:`***@${n.slice(e+1)}`).slice(0,200)}var Te=new Set(E);function Ge(n){if(!n)return {};let e={};for(let[t,r]of Object.entries(n))Te.has(t.toLowerCase())&&(e[t.toLowerCase()]=r);return e}function z(n){let e=n.fetch??globalThis.fetch.bind(globalThis);return B(async(t,r)=>{let o;try{o=new URL(n.baseUrl.replace(/\/+$/,""));}catch{throw new v("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 v(`${JSON.stringify(typeof t.path=="string"?Ae(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 v(`${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 h=o.username!==""||o.password!=="",f=s.username!==o.username||s.password!==o.password,g=h?f?"baseUrl (and possibly the request path)":"baseUrl":"request path";throw new v(`the ${g} 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[h,f]of Object.entries(n.defaultQuery??{}))s.searchParams.has(h)||s.searchParams.set(h,f);let a;try{a=t.body===void 0?void 0:JSON.stringify(t.body);}catch(h){throw new v(`the body of ${t.method} ${JSON.stringify(s.pathname)} could not be serialised to JSON: ${String(h)}. This is a bug in the request, not a server failure \u2014 retrying sends the same unserialisable value.`)}let l=await e(s.toString(),{method:t.method,headers:{authorization:`Bearer ${r}`,...t.body===void 0?{}:{"content-type":"application/json"},...Ge(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"}),d=await l.text(),c=null;if(d.length>0)try{c=JSON.parse(d);}catch{c=d;}let m=l.headers.get("etag"),R=Oe(l.headers.get("retry-after"));return {status:l.status,body:c,...m===null?{}:{etag:m},...R===void 0?{}:{retryAfterSeconds:R}}},n)}function Oe(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 Pe="gem-web-bridge";var T=65536,W=8,C=5e3,K=1024;function M(n){return Object.freeze(Object.assign(Object.create(null),n))}M({"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.viewport":60,"gem.deviceSettings":12,"gem.willTerminate":10,"gem.roomEvent":120,"gem.socketState":12,"gem.seatedEvent":60,"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.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.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,__malformed:60});M({"gem.requestAd":"ads","gem.adResult":"ads","gem.requestSignIn":"signIn","gem.signInResult":"signIn","gem.requestPurchase":"purchases","gem.purchaseResult":"purchases","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.seatedEvent":"partySeating","gem.socketState":"socketState","gem.audioState":"audioState","gem.rewardCue":"rewardCue","gem.frameStats":"frameStats","gem.viewport":"viewport","gem.requestLocalServer":"localHost","gem.localServer":"localHost","gem.localServer.denied":"localHost","gem.cohorts":"cohorts","gem.deviceSettings":"deviceSettings","gem.deviceSettings.put":"deviceSettings","gem.deviceSettings.result":"deviceSettings"});function Ie(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 Ce(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 qe(n){return /^[a-z]{2,8}(-[a-z0-9]{1,8})*$/i.test(n)}function j(n,e,t){if(e>W)return `nesting deeper than ${W}`;if(++t.nodes>C)return `more than ${C} values`;if(t.bytes>T)return `over the ${T} 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>K)return `an array of ${n.length} entries, over the ${K} limit`;t.bytes+=2;for(let l of n){let d=j(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>C)return `more than ${C} values`;if(t.bytes+=l.length*3+4,t.bytes>T)return `over the ${T} byte limit`;let d=j(a[l],e+1,t);if(d)return d}return null}function $e(n){let e={nodes:0,bytes:0,seen:new Set},t=j(n,0,e);return t?`message contains ${t}`:e.bytes>T?`message is over the ${T} byte limit`:null}var Le={origin:[Ie,"not a well-formed origin"],url:[Ce,"not a safe absolute http(s) URL"],bcp47:[qe,"not a well-formed BCP 47 tag"]};function Y(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=J(s,r,o);if(a)return a}return null}function J(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]=Le[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`:Y(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=J(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=$e(t);if(r)return r;if(typeof t!="object"||t===null||Array.isArray(t))return "message: expected object";let o=t;return o.gem!==Pe?"gem: wrong protocol marker":o.type!==n?`type: expected ${n}`:Y(o,e,"")}}var je=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"}]),Me=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}}]),He=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}]),Ue=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}]),Fe=u("gem.player",[{n:"untrusted",k:"object",fs:[{n:"displayName",k:"string",max:64},{n:"displayHandle",k:"string",max:80}]},{n:"displayTag",k:"string",max:8},{n:"avatarUrl",k:"string",o:1,max:2048,f:"url"}]),Ne=u("gem.pause",[{n:"paused",k:"boolean"}]),Be=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"}]),De=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}]}}]),Ve=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}]}]),ze=u("gem.deviceSettings",[{n:"settings",k:"json",o:1}]),We=u("gem.willTerminate",[{n:"reason",k:"enum",v:["grant_expiring","session_ended","navigating","kill_switch"]},{n:"graceMs",k:"int",lo:0,hi:6e4}]),Ke=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"]}]),Ye=u("gem.socketState",[{n:"connected",k:"boolean"},{n:"reason",k:"enum",o:1,v:["connecting","dropped","watchdog","terminal"]}]),Je=u("gem.seatedEvent",[{n:"roomId",k:"string",max:64}]),Xe=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"}]),Qe=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}]),Ze=u("gem.partyResult",[{n:"requestId",k:"string",max:64},{n:"partyId",k:"string",o:1,max:64}]),en=u("gem.clusterTarget",[{n:"clusterTargetId",k:"string",max:64}]),nn=u("gem.devtools",[{n:"action",k:"enum",v:["open","close","toggle"]}]),tn=u("gem.screenshot",[{n:"maxWidth",k:"int",lo:1,hi:7680},{n:"maxHeight",k:"int",lo:1,hi:4320}]),rn=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"}]),on=u("gem.requestContext",[]),sn=u("gem.gameContext",[{n:"context",k:"json"}]),an=u("gem.signal",[{n:"signal",k:"enum",v:["join","offer","answer","ice","migrationAck","hostUnreachable"]},{n:"matchId",k:"string",max:64},{n:"data",k:"json"}]),ln=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"]}]),dn=u("gem.partyRequest",[{n:"requestId",k:"string",max:64}]),un=u("gem.ready",[]),cn=u("gem.progress",[{n:"loaded",k:"int",lo:0,hi:1099511627776},{n:"total",k:"int",lo:0,hi:1099511627776}]),mn=u("gem.requestToken",[{n:"requestId",k:"string",max:64},{n:"reason",k:"enum",v:["initial","expiring","rejected"]}]),gn=u("gem.requestLocalServer",[{n:"requestId",k:"string",max:64},{n:"gameRoomId",k:"string",max:64}]),pn=u("gem.localServer",[{n:"requestId",k:"string",max:64},{n:"serverId",k:"string",o:1,max:128}]),yn=u("gem.localServer.denied",[{n:"requestId",k:"string",max:64},{n:"retryable",k:"boolean"},{n:"reason",k:"enum",v:["refused","unavailable"]}]),fn=u("gem.exit",[{n:"reason",k:"string",o:1,max:64}]),hn=u("gem.openExternal",[{n:"url",k:"string",max:2048,f:"url"}]),_n=u("gem.requestFullscreen",[{n:"enabled",k:"boolean"}]),vn=u("gem.audioState",[{n:"muted",k:"boolean"}]),bn=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}]}]),Rn=u("gem.frameStats",[{n:"fps",k:"int",lo:0,hi:1e3},{n:"frameTimeP95Ms",k:"int",lo:0,hi:1e5}]),Sn=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}]),xn=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}]),kn=u("gem.purchaseResult",[{n:"requestId",k:"string",max:64},{n:"outcome",k:"enum",v:["ok","declined","unavailable"]},{n:"purchaseId",k:"string",o:1,max:64}]),wn=u("gem.deviceSettings.put",[{n:"requestId",k:"string",max:64},{n:"settings",k:"json"}]),An=u("gem.deviceSettings.result",[{n:"requestId",k:"string",max:64},{n:"outcome",k:"enum",v:["stored","too_large","unavailable"]}]),Tn=u("gem.requestAd",[{n:"requestId",k:"string",max:64},{n:"placement",k:"string",max:32},{n:"format",k:"enum",v:["interstitial","rewarded"]}]),Gn=u("gem.adResult",[{n:"requestId",k:"string",max:64},{n:"outcome",k:"enum",v:["shown","no_ad","unavailable"]}]),On=u("gem.requestSignIn",[{n:"requestId",k:"string",max:64}]),Pn=u("gem.signInResult",[{n:"requestId",k:"string",max:64},{n:"outcome",k:"enum",v:["signed_in","declined","unavailable"]}]);M({"gem.handshake":je,"gem.handshake.accept":Me,"gem.token":He,"gem.token.denied":Ue,"gem.player":Fe,"gem.pause":Ne,"gem.prefs":Be,"gem.cohorts":De,"gem.viewport":Ve,"gem.deviceSettings":ze,"gem.willTerminate":We,"gem.roomEvent":Ke,"gem.socketState":Ye,"gem.seatedEvent":Je,"gem.signalEvent":Xe,"gem.dedicatedEvent":Qe,"gem.partyResult":Ze,"gem.clusterTarget":en,"gem.devtools":nn,"gem.screenshot":tn,"gem.screenshot.denied":rn,"gem.requestContext":on,"gem.gameContext":sn,"gem.signal":an,"gem.dedicatedOffer":ln,"gem.partyRequest":dn,"gem.ready":un,"gem.progress":cn,"gem.requestToken":mn,"gem.requestLocalServer":gn,"gem.localServer":pn,"gem.localServer.denied":yn,"gem.exit":fn,"gem.openExternal":hn,"gem.requestFullscreen":_n,"gem.audioState":vn,"gem.rewardCue":bn,"gem.frameStats":Rn,"gem.error":Sn,"gem.requestPurchase":xn,"gem.purchaseResult":kn,"gem.deviceSettings.put":wn,"gem.deviceSettings.result":An,"gem.requestAd":Tn,"gem.adResult":Gn,"gem.requestSignIn":On,"gem.signInResult":Pn});var G={now:()=>Date.now(),setTimeout:(n,e)=>setTimeout(n,e),clearTimeout:n=>clearTimeout(n)};var En=1e4;function X(n,e){return H(n,e)}function H(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 P({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??En);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 U={};ce(U,{acceptTransfer:()=>In,addEntityProgression:()=>Cn,adminAction:()=>qn,cancelInventoryTransfer:()=>$n,claimEntityProgressionRewards:()=>Ln,closeGameRoom:()=>jn,createEntityBatchOrder:()=>Mn,createEntityOrder:()=>Hn,createSession:()=>Un,deleteEntityGameSetting:()=>Fn,deleteEntitySave:()=>Nn,deleteSession:()=>Bn,executeEntityRecipe:()=>Dn,finalizeSaveUpload:()=>Vn,getDropRates:()=>zn,getEntityCurrency:()=>Wn,getEntityGameSetting:()=>Kn,getEntityInventory:()=>Yn,getEntityInventoryItem:()=>Jn,getEntityLeaderboard:()=>Xn,getEntityOrder:()=>Qn,getEntityProgression:()=>Zn,getEntityRecipeAvailability:()=>et,getEntityRecipeUsage:()=>nt,getEntitySave:()=>tt,getEvent:()=>rt,getGameRoomV2:()=>ot,getLeaderboard:()=>st,getPurchaseCatalog:()=>it,getResolvedTemplate:()=>at,getRoomArgs:()=>lt,getTransferDetails:()=>dt,initiateInventoryTransfer:()=>ut,kickPlayer:()=>ct,listEntityGameSettings:()=>mt,listEntityOrders:()=>gt,listEntityProgressions:()=>pt,listEntitySaves:()=>yt,listEvents:()=>ft,listGameRooms:()=>ht,listResolvedTemplates:()=>_t,listTransfers:()=>vt,matchEnd:()=>bt,putEntityGameSetting:()=>Rt,putRoomArgs:()=>St,rejectTransfer:()=>xt,requestSaveUploadUrl:()=>kt,resetEntityProgression:()=>wt,simulateEntityOrder:()=>At,transferHostV2:()=>Tt,updateGameRoomV2:()=>Gt});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 In(n,e,t){let r=`/v1/inventory/transfers/${i(e)}/accept`;return n.client.post(r,void 0,t?.signal)}async function Cn(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 qn(n,e,t,r){let o=`/v1/voice/sessions/${i(e)}/admin`;return n.client.post(o,t,r?.signal)}async function $n(n,e,t){let r=`/v1/inventory/transfers/${i(e)}/cancel`;return n.client.post(r,void 0,t?.signal)}async function Ln(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 jn(n,e,t){let r=`/v1/games/${i(n.gameId())}/game-rooms/${i(e)}`;return n.client.delete(r,t?.signal)}async function Mn(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 Hn(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 Un(n,e,t){return n.client.post("/v1/voice/sessions",e,t?.signal)}async function Fn(n,e,t,r,o){let s=`/v1/settings/${i(e)}/${i(t)}/${i(r)}`;return n.client.delete(s,o?.signal)}async function Nn(n,e,t,r,o){let s=`/v1/saves/${i(e)}/${i(t)}/${i(r)}`;return n.client.delete(s,o?.signal)}async function Bn(n,e,t){let r=`/v1/voice/sessions/${i(e)}`;return n.client.delete(r,t?.signal)}async function Dn(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 Vn(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 zn(n,e,t){let r=`/v1/inventory/loot-tables/${i(e)}/drop-rates`;return n.client.get(r,t?.signal)}async function Wn(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 Kn(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 Yn(n,e,t,r){let o=new URLSearchParams;r?.include_buckets!==void 0&&o.set("include_buckets",String(r?.include_buckets)),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 Jn(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 Xn(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));let a=s.toString(),l=`/v1/leaderboards/${i(e)}/${i(t)}/${i(r)}`+(a?`?${a}`:"");return n.client.get(l,o?.signal)}async function Qn(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 Zn(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 et(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 nt(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 rt(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 st(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));let o=r.toString(),s=`/v1/leaderboards/${i(e)}`+(o?`?${o}`:"");return n.client.get(s,t?.signal)}async function it(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 at(n,e,t){let r=`/v1/game-room-templates/${i(e)}`;return n.client.get(r,t?.signal)}async function lt(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 dt(n,e,t){let r=`/v1/inventory/transfers/${i(e)}`;return n.client.get(r,t?.signal)}async function ut(n,e,t){return n.client.post("/v1/inventory/transfers",e,t?.signal)}async function ct(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 mt(n,e,t,r){let o=`/v1/settings/${i(e)}/${i(t)}`;return n.client.get(o,r?.signal)}async function gt(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 pt(n,e,t,r){let o=`/v1/inventory/${i(e)}/${i(t)}/progressions`;return n.client.get(o,r?.signal)}async function yt(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 ft(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 ht(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 _t(n,e){return n.client.get("/v1/game-room-templates",e?.signal)}async function vt(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 bt(n,e,t){let r=`/v1/games/${i(n.gameId())}/matches/${i(e)}/end`;return n.client.post(r,void 0,t?.signal)}async function Rt(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 St(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 xt(n,e,t){let r=`/v1/inventory/transfers/${i(e)}/reject`;return n.client.post(r,void 0,t?.signal)}async function kt(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 wt(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 At(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 Tt(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 Gt(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 Q="gem_";var Et=1e4,It=50,Ct=1e3,qt=65536-4*1024,Z=n=>typeof n=="number"?n:0,$t=n=>typeof n=="string"?n:"";function ee(){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 Lt(n){return n?.retryable===true}function jt(n,e){let t=n??{},r=Array.isArray(t.rejected)?t.rejected.map(o=>{let s=o??{};return {index:Z(s.index),code:$t(s.code)}}):[];return {accepted:Z(t.accepted),rejected:r,dropped:e,duplicate:t.duplicate===true}}function ne(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 te(n){let e=Math.max(1,Math.floor(n.maxQueue??Ct)),t=[],r=0,o=null,s=false,a=false,l=false,d=false,c=g=>{n.log?.(g);},m=()=>{o!==null&&(n.clock.clearTimeout(o),o=null);},R=()=>{o!==null||s||a||(o=n.clock.setTimeout(()=>{o=null,f().catch(()=>{});},Et));},h=()=>{let g=Math.min(t.length,100),y=128;for(let x=0;x<g;x+=1){let k=t[x];if(k===void 0)break;if(y+=JSON.stringify(ne(k,0)).length+1,y>qt)return Math.max(1,x)}return g};async function f(g){if(t.length===0)return {accepted:0,rejected:[],dropped:0,duplicate:false};m();let y=t.splice(0,h()),x=r;r=0;let k=Math.round(n.clock.now()),O={batch_id:ee(),sent_at_ms:k,events:y.map(S=>ne(S,k))};a=true;try{let S=await n.client.post(`/v1/games/${encodeURIComponent(n.gameId)}/analytics/events`,O,g,{replaySafe:!0}),w=jt(S,x);for(let de of w.rejected)c(`[gem] analytics: an event was refused (${de.code}). See the analytics_events section of your game config.`);return w}catch(S){if(Lt(S))for(t=[...y,...t],r+=x;t.length>e;)t.shift(),r+=1;else c(`[gem] analytics: ${y.length} event(s) were discarded \u2014 the platform refused the batch and will refuse it again: ${String(S)}`);throw S}finally{a=false,t.length>0&&R();}}return {track(g,y,x={}){if(s)return;if(typeof g!="string"||g===""){d||(d=true,c(`[gem] analytics: '${y}' 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(y.startsWith(Q)){l||(l=true,c(`[gem] analytics: '${y}' 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 k={},O={};for(let[S,w]of Object.entries(x))typeof w=="string"?k[S]=w:typeof w=="number"&&Number.isFinite(w)&&(O[S]=w);for(;t.length>=e;)t.shift(),r+=1;t.push({uid:ee(),playerId:g,name:y,atMs:n.clock.now(),dimensions:k,measures:O}),t.length>=It?f().catch(()=>{}):R();},flush:g=>f(g),get pending(){return t.length},dispose(){s=true,m(),t=[],r=0;}}}function Mt(n){let e={};for(let[t,r]of Object.entries(U))if(typeof r=="function"){let o=r;e[t]=(...s)=>o(n,...s);}return e}function $(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=H(n,{clock:t,...e.onAuthStateChange===void 0?{}:{onStateChange:e.onAuthStateChange}}),s=z({baseUrl:r,tokenSource:o.source,defaultQuery:{game_id:n.gameId,channel:n.channel},...e.fetch===void 0?{}:{fetch:e.fetch}}),a=new A({transport:s,clock:t}),l={gameId:n.gameId,channel:n.channel,matchId:n.matchId,...n.gameRoomId===void 0?{}:{gameRoomId:n.gameRoomId}},d=Mt({client:a,gameId:()=>l.gameId}),c=l.gameRoomId,m=n.endMatch,R=n.log,h=te({client:a,clock:t,gameId:l.gameId,...typeof R=="function"?{log:g=>R.call(n,g)}:{}}),f={identity:l,client:a,api:d,match:{end:async g=>{if(m!==void 0){let y=await m.call(n);(y==="ok"||y==="already_ended")&&q.add(f);return}try{await d.matchEnd(l.matchId,g===void 0?void 0:{signal:g});}catch(y){if(y instanceof p&&y.reason==="not_found"){q.add(f);return}throw y}q.add(f);}},analytics:h,...c===void 0?{}:{room:{get:g=>d.getGameRoomV2(c,g),args:g=>d.getRoomArgs(c,g)}},dispose:()=>{h.dispose(),o.dispose();}};return f}var q=new WeakSet;function re(n){return q.has(n)}var Ht=["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"],Ut=new Set(Ht);function oe(n){return typeof n=="string"&&Ut.has(n)?n:"unknown"}var b=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 L(n){return new b(n)}var se={toPlain(n){return b.unwrap(n)},compare(n,e,t){let r=n instanceof b?b.unwrap(n):n,o=e instanceof b?b.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 b?b.unwrap(n):n,r=e instanceof b?b.unwrap(e):e;return t.normalize("NFC")===r.normalize("NFC")}};var ie="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 F(n,e={}){let t=e.clock??G,r=()=>{let l=n();if(l===null)throw new Error(ie);return l},o=null,s=()=>{if(o===null)throw new Error(ie);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 room(){return s().room},dispose(){o?.dispose();},get sizeClass(){return r().sizeClass},get roomArgs(){return r().roomArgs},get roster(){return r().roster},players(){return r().players()},profile(l){let c=r().profile?.(l);if(!c)return null;let m=c.displayName;return typeof m!="string"||m===""?null:{displayName:L(m),displayTag:typeof c.displayTag=="string"?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=$(r(),{...e,clock:t});},ended:()=>o!==null&&re(o)}}function ae(n,e={}){let{server:t,attach:r}=F(()=>n,e);return r(),t}var Ft=5e3;function Nt(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:oe(e)}}}function Bt(n,e,t){return t||e?.endMatch!==void 0?false:n===void 0?true:n.reason==="idle_timeout"}function Dt(n){return n instanceof Error?n.message:String(n)}function le(n,e={}){return ()=>{let t=null,{server:r,attach:o,ended:s}=F(()=>t,e),a=n(r),l={async init(d){t=d,o(),await a.init?.();},async shutdown(d){let c=Nt(d);try{await a.shutdown?.(c);}finally{try{Bt(c,t,s())&&await r.match.end(AbortSignal.timeout(Ft)).catch(m=>{m instanceof p&&m.reason==="not_found"||t?.warn?.(`ending the match after shutdown failed: ${Dt(m)}`);});}finally{r.dispose();}}}};return a.join&&(l.join=(d,c)=>a.join?.(d,c)),a.leave&&(l.leave=(d,c)=>a.leave?.(d,c)),a.message&&(l.message=(d,c,m,R)=>a.message?.(d,c,m,R)),l}}
2
- export{_ as AuthError,E as CONDITIONAL_HEADERS,p as GemApiError,A as GemClient,b as PlayerText,v as TransportRefusal,L as asPlayerText,$ as createGemServer,X as createHostTokenSource,ae as createMatchServer,le as defineServer,G as systemClock,se as text,D as toBase64};//# sourceMappingURL=gem-web-sdk.server.js.map
1
+ var ce=Object.defineProperty;var me=(n,e)=>{for(var t in e)ce(n,t,{get:e[t],enumerable:true});};globalThis.__gemWebSdkVersion="[gem-web-sdk:sdkVersion:5.11.0]";function ge(n,e){return e!==void 0?!e:n==="chain_exhausted"}var E=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 v(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 v("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 v("internal","token arrived for a superseded generation");return this.grant=o,this.rejected=false,this.enter("ready"),o.token}).catch(o=>{let s=pe(o),a=o?.retryable;throw t===this.generation&&this.enter(ge(s,typeof a=="boolean"?a:void 0)?"lost":"degraded",s),o instanceof v?o:new v(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)}},v=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 pe(n){if(n instanceof v)return n.reason;let e=n?.reason;return typeof e=="string"&&["chain_exhausted","unavailable","timeout","internal"].includes(e)?e:"internal"}var _=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}},I=["if-match","if-none-match"],N=4096;function ye(n){if(!n)return;let e={};for(let[t,r]of Object.entries(n)){let o=t.toLowerCase();if(!I.includes(o)||r===void 0)continue;let s=typeof r=="string"?fe(r):r;if(typeof s!="string"||s.length>N||!he(s))throw new _(`the ${o} header value cannot be sent \u2014 it is not a string, is longer than ${N} 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 fe(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 he(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 B(n,e){let t=e.replayUnauthorizedOnce??true;return {async request(r){let o={...r},s=ye(o.headers),a=Object.freeze({...o,headers:s}),l=await e.tokenSource.get(),d=await n(a,l);if(d.status!==401||!t)return d;e.tokenSource.invalidate(l);let c=await e.tokenSource.get(),m=await n(a,c);if(m.status===401)throw e.tokenSource.close("unavailable"),new v("unavailable","the server refused a freshly minted token");return m}}}function D(n){let e=typeof n=="string"?new TextEncoder().encode(n):n;return btoa(ve(e))}function ve(n){let t="";for(let r=0;r<n.length;r+=32768)t+=String.fromCharCode(...n.subarray(r,r+32768));return t}var p=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"}},_e=new Set([408,429,500,502,503,504]),be=6e4;function Re(n){if(n===void 0)return 2;if(!Number.isInteger(n)||n<0||n>10)throw new _(`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 A=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 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?Re(this.options.maxRetries)+1:1,o=null;if(e.signal?.aborted)throw V(e.signal);for(let s=0;s<r;s++){if(s>0&&await this.backoff(s,o,e.signal),e.signal?.aborted)throw V(e.signal);let a;try{a=await this.options.transport.request(e);}catch(d){if(v.isAuthError(d)||_.isRefusal(d)||e.signal?.aborted||Se(d))throw d;o=new p("unavailable",0,String(d));continue}if(a.status>=200&&a.status<300||a.status===304)return a;let l=xe(a);if(!_e.has(a.status))throw l;o=l;}throw o??new p("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),be);return new Promise(d=>{let c=this.options.clock,m=false,R=false,h,f=()=>{m||(m=true,R&&c.clearTimeout(h),r?.removeEventListener("abort",f),d());};r?.addEventListener("abort",f,{once:true}),h=c.setTimeout(f,l),R=true,m&&c.clearTimeout(h);})}};function C(n){return {...n.keepalive===void 0?{}:{keepalive:n.keepalive},...n.ifMatch===void 0?{}:{headers:{"if-match":n.ifMatch}}}}function V(n){return n.reason!==void 0?n.reason:new DOMException("The operation was aborted.","AbortError")}function Se(n){let e=n?.name;return e==="AbortError"||e==="TimeoutError"}function xe(n){let{status:e,body:t}=n,r=ke(t),o=n.retryAfterSeconds??Ae(t),s=we(t);switch(e){case 304:return new p("not_modified",e,r);case 400:case 422:return new p("invalid",e,r,void 0,s);case 403:return new p("forbidden",e,r,void 0,s);case 404:return new p("not_found",e,r,void 0,s);case 402:return new p("insufficient_funds",e,r,void 0,s);case 409:return new p("conflict",e,r,void 0,s);case 412:return new p("precondition_failed",e,r,void 0,s);case 413:return new p("too_large",e,r,void 0,s);case 429:return new p("rate_limited",e,r,o,s);default:return new p("unavailable",e,r,o,s)}}function ke(n){if(typeof n=="string")return n;let e=n?.message;if(typeof e=="string")return e;let t=n?.error;if(typeof t=="string")return t;let r=t?.message;return typeof r=="string"?r:"no detail"}function we(n){let t=n?.error?.code;return typeof t=="string"&&t.length>0?t:void 0}function Ae(n){let e=n?.retryAfterSeconds;return typeof e=="number"&&Number.isFinite(e)&&e>=0?e:void 0}function Te(n){let e=n.lastIndexOf("@");return (e===-1?n:`***@${n.slice(e+1)}`).slice(0,200)}var Oe=new Set(I);function Ge(n){if(!n)return {};let e={};for(let[t,r]of Object.entries(n))Oe.has(t.toLowerCase())&&(e[t.toLowerCase()]=r);return e}function z(n){let e=n.fetch??globalThis.fetch.bind(globalThis);return B(async(t,r)=>{let o;try{o=new URL(n.baseUrl.replace(/\/+$/,""));}catch{throw new _("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 _(`${JSON.stringify(typeof t.path=="string"?Te(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 _(`${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 h=o.username!==""||o.password!=="",f=s.username!==o.username||s.password!==o.password,g=h?f?"baseUrl (and possibly the request path)":"baseUrl":"request path";throw new _(`the ${g} 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[h,f]of Object.entries(n.defaultQuery??{}))s.searchParams.has(h)||s.searchParams.set(h,f);let a;try{a=t.body===void 0?void 0:JSON.stringify(t.body);}catch(h){throw new _(`the body of ${t.method} ${JSON.stringify(s.pathname)} could not be serialised to JSON: ${String(h)}. This is a bug in the request, not a server failure \u2014 retrying sends the same unserialisable value.`)}let l=await e(s.toString(),{method:t.method,headers:{authorization:`Bearer ${r}`,...t.body===void 0?{}:{"content-type":"application/json"},...Ge(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"}),d=await l.text(),c=null;if(d.length>0)try{c=JSON.parse(d);}catch{c=d;}let m=l.headers.get("etag"),R=Pe(l.headers.get("retry-after"));return {status:l.status,body:c,...m===null?{}:{etag:m},...R===void 0?{}:{retryAfterSeconds:R}}},n)}function Pe(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 Ee="gem-web-bridge";var T=65536,W=8,q=5e3,K=1024;function M(n){return Object.freeze(Object.assign(Object.create(null),n))}M({"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.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.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.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,__malformed:60});M({"gem.requestAd":"ads","gem.adResult":"ads","gem.requestSignIn":"signIn","gem.signInResult":"signIn","gem.requestPurchase":"purchases","gem.purchaseResult":"purchases","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.viewport":"viewport","gem.requestLocalServer":"localHost","gem.localServer":"localHost","gem.localServer.denied":"localHost","gem.cohorts":"cohorts","gem.deviceSettings":"deviceSettings","gem.deviceSettings.put":"deviceSettings","gem.deviceSettings.result":"deviceSettings"});function Ce(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 qe(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 $e(n){return /^[a-z]{2,8}(-[a-z0-9]{1,8})*$/i.test(n)}function j(n,e,t){if(e>W)return `nesting deeper than ${W}`;if(++t.nodes>q)return `more than ${q} values`;if(t.bytes>T)return `over the ${T} 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>K)return `an array of ${n.length} entries, over the ${K} limit`;t.bytes+=2;for(let l of n){let d=j(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>q)return `more than ${q} values`;if(t.bytes+=l.length*3+4,t.bytes>T)return `over the ${T} byte limit`;let d=j(a[l],e+1,t);if(d)return d}return null}function Le(n){let e={nodes:0,bytes:0,seen:new Set},t=j(n,0,e);return t?`message contains ${t}`:e.bytes>T?`message is over the ${T} byte limit`:null}var je={origin:[Ce,"not a well-formed origin"],url:[qe,"not a safe absolute http(s) URL"],bcp47:[$e,"not a well-formed BCP 47 tag"]};function Y(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=J(s,r,o);if(a)return a}return null}function J(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]=je[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`:Y(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=J(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=Le(t);if(r)return r;if(typeof t!="object"||t===null||Array.isArray(t))return "message: expected object";let o=t;return o.gem!==Ee?"gem: wrong protocol marker":o.type!==n?`type: expected ${n}`:Y(o,e,"")}}var Me=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"}]),Ue=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}}]),He=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}]),Fe=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}]),Ne=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"}]),Be=u("gem.pause",[{n:"paused",k:"boolean"}]),De=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"}]),Ve=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}]}}]),ze=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}]}]),We=u("gem.deviceSettings",[{n:"settings",k:"json",o:1}]),Ke=u("gem.willTerminate",[{n:"reason",k:"enum",v:["grant_expiring","session_ended","navigating","kill_switch"]},{n:"graceMs",k:"int",lo:0,hi:6e4}]),Ye=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"]}]),Je=u("gem.socketState",[{n:"connected",k:"boolean"},{n:"reason",k:"enum",o:1,v:["connecting","dropped","watchdog","terminal"]}]),Xe=u("gem.seatedEvent",[{n:"roomId",k:"string",max:64}]),Qe=u("gem.autoStartFailedEvent",[{n:"roomId",k:"string",max:64},{n:"code",k:"string",max:64}]),Ze=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"}]),en=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}]),nn=u("gem.partyResult",[{n:"requestId",k:"string",max:64},{n:"partyId",k:"string",o:1,max:64}]),tn=u("gem.clusterTarget",[{n:"clusterTargetId",k:"string",max:64},{n:"clusterTargetIds",k:"array",o:1,max:3,it:{n:"",k:"string",max:64}}]),rn=u("gem.devtools",[{n:"action",k:"enum",v:["open","close","toggle"]}]),on=u("gem.screenshot",[{n:"maxWidth",k:"int",lo:1,hi:7680},{n:"maxHeight",k:"int",lo:1,hi:4320}]),sn=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"}]),an=u("gem.requestContext",[]),ln=u("gem.gameContext",[{n:"context",k:"json"}]),dn=u("gem.signal",[{n:"signal",k:"enum",v:["join","offer","answer","ice","migrationAck","hostUnreachable"]},{n:"matchId",k:"string",max:64},{n:"data",k:"json"}]),un=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"]}]),cn=u("gem.partyRequest",[{n:"requestId",k:"string",max:64}]),mn=u("gem.ready",[]),gn=u("gem.progress",[{n:"loaded",k:"int",lo:0,hi:1099511627776},{n:"total",k:"int",lo:0,hi:1099511627776}]),pn=u("gem.requestToken",[{n:"requestId",k:"string",max:64},{n:"reason",k:"enum",v:["initial","expiring","rejected"]}]),yn=u("gem.requestLocalServer",[{n:"requestId",k:"string",max:64},{n:"gameRoomId",k:"string",max:64}]),fn=u("gem.localServer",[{n:"requestId",k:"string",max:64},{n:"serverId",k:"string",o:1,max:128}]),hn=u("gem.localServer.denied",[{n:"requestId",k:"string",max:64},{n:"retryable",k:"boolean"},{n:"reason",k:"enum",v:["refused","unavailable"]}]),vn=u("gem.exit",[{n:"reason",k:"string",o:1,max:64}]),_n=u("gem.openExternal",[{n:"url",k:"string",max:2048,f:"url"}]),bn=u("gem.requestFullscreen",[{n:"enabled",k:"boolean"}]),Rn=u("gem.audioState",[{n:"muted",k:"boolean"}]),Sn=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}]}]),xn=u("gem.frameStats",[{n:"fps",k:"int",lo:0,hi:1e3},{n:"frameTimeP95Ms",k:"int",lo:0,hi:1e5}]),kn=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}]),wn=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}]),An=u("gem.purchaseResult",[{n:"requestId",k:"string",max:64},{n:"outcome",k:"enum",v:["ok","declined","unavailable"]},{n:"purchaseId",k:"string",o:1,max:64}]),Tn=u("gem.deviceSettings.put",[{n:"requestId",k:"string",max:64},{n:"settings",k:"json"}]),On=u("gem.deviceSettings.result",[{n:"requestId",k:"string",max:64},{n:"outcome",k:"enum",v:["stored","too_large","unavailable"]}]),Gn=u("gem.requestAd",[{n:"requestId",k:"string",max:64},{n:"placement",k:"string",max:32},{n:"format",k:"enum",v:["interstitial","rewarded"]}]),Pn=u("gem.adResult",[{n:"requestId",k:"string",max:64},{n:"outcome",k:"enum",v:["shown","no_ad","unavailable"]}]),En=u("gem.requestSignIn",[{n:"requestId",k:"string",max:64}]),In=u("gem.signInResult",[{n:"requestId",k:"string",max:64},{n:"outcome",k:"enum",v:["signed_in","declined","unavailable"]}]);M({"gem.handshake":Me,"gem.handshake.accept":Ue,"gem.token":He,"gem.token.denied":Fe,"gem.player":Ne,"gem.pause":Be,"gem.prefs":De,"gem.cohorts":Ve,"gem.viewport":ze,"gem.deviceSettings":We,"gem.willTerminate":Ke,"gem.roomEvent":Ye,"gem.socketState":Je,"gem.seatedEvent":Xe,"gem.autoStartFailedEvent":Qe,"gem.signalEvent":Ze,"gem.dedicatedEvent":en,"gem.partyResult":nn,"gem.clusterTarget":tn,"gem.devtools":rn,"gem.screenshot":on,"gem.screenshot.denied":sn,"gem.requestContext":an,"gem.gameContext":ln,"gem.signal":dn,"gem.dedicatedOffer":un,"gem.partyRequest":cn,"gem.ready":mn,"gem.progress":gn,"gem.requestToken":pn,"gem.requestLocalServer":yn,"gem.localServer":fn,"gem.localServer.denied":hn,"gem.exit":vn,"gem.openExternal":_n,"gem.requestFullscreen":bn,"gem.audioState":Rn,"gem.rewardCue":Sn,"gem.frameStats":xn,"gem.error":kn,"gem.requestPurchase":wn,"gem.purchaseResult":An,"gem.deviceSettings.put":Tn,"gem.deviceSettings.result":On,"gem.requestAd":Gn,"gem.adResult":Pn,"gem.requestSignIn":En,"gem.signInResult":In});var O={now:()=>Date.now(),setTimeout:(n,e)=>setTimeout(n,e),clearTimeout:n=>clearTimeout(n)};var Cn=1e4;function X(n,e){return U(n,e)}function U(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 E({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??Cn);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={};me(H,{acceptTransfer:()=>qn,addEntityProgression:()=>$n,adminAction:()=>Ln,cancelInventoryTransfer:()=>jn,claimEntityProgressionRewards:()=>Mn,closeGameRoom:()=>Un,createEntityBatchOrder:()=>Hn,createEntityOrder:()=>Fn,createSession:()=>Nn,deleteEntityGameSetting:()=>Bn,deleteEntitySave:()=>Dn,deleteSession:()=>Vn,executeEntityRecipe:()=>zn,finalizeSaveUpload:()=>Wn,getDropRates:()=>Kn,getEntityCurrency:()=>Yn,getEntityGameSetting:()=>Jn,getEntityInventory:()=>Xn,getEntityInventoryItem:()=>Qn,getEntityLeaderboard:()=>Zn,getEntityOrder:()=>et,getEntityProgression:()=>nt,getEntityRecipeAvailability:()=>tt,getEntityRecipeUsage:()=>rt,getEntitySave:()=>ot,getEvent:()=>st,getGameRoomV2:()=>it,getLeaderboard:()=>at,getPurchaseCatalog:()=>lt,getResolvedTemplate:()=>dt,getRoomArgs:()=>ut,getTransferDetails:()=>ct,initiateInventoryTransfer:()=>mt,kickPlayer:()=>gt,listEntityGameSettings:()=>pt,listEntityOrders:()=>yt,listEntityProgressions:()=>ft,listEntitySaves:()=>ht,listEvents:()=>vt,listGameRooms:()=>_t,listResolvedTemplates:()=>bt,listTransfers:()=>Rt,matchEnd:()=>St,putEntityGameSetting:()=>xt,putRoomArgs:()=>kt,rejectTransfer:()=>wt,requestSaveUploadUrl:()=>At,resetEntityProgression:()=>Tt,simulateEntityOrder:()=>Ot,transferHostV2:()=>Gt,updateGameRoomV2:()=>Pt});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 qn(n,e,t){let r=`/v1/inventory/transfers/${i(e)}/accept`;return n.client.post(r,void 0,t?.signal)}async function $n(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 Ln(n,e,t,r){let o=`/v1/voice/sessions/${i(e)}/admin`;return n.client.post(o,t,r?.signal)}async function jn(n,e,t){let r=`/v1/inventory/transfers/${i(e)}/cancel`;return n.client.post(r,void 0,t?.signal)}async function Mn(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 Un(n,e,t){let r=`/v1/games/${i(n.gameId())}/game-rooms/${i(e)}`;return n.client.delete(r,t?.signal)}async function Hn(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 Fn(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 Nn(n,e,t){return n.client.post("/v1/voice/sessions",e,t?.signal)}async function Bn(n,e,t,r,o){let s=`/v1/settings/${i(e)}/${i(t)}/${i(r)}`;return n.client.delete(s,o?.signal)}async function Dn(n,e,t,r,o){let s=`/v1/saves/${i(e)}/${i(t)}/${i(r)}`;return n.client.delete(s,o?.signal)}async function Vn(n,e,t){let r=`/v1/voice/sessions/${i(e)}`;return n.client.delete(r,t?.signal)}async function zn(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 Wn(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 Kn(n,e,t){let r=`/v1/inventory/loot-tables/${i(e)}/drop-rates`;return n.client.get(r,t?.signal)}async function Yn(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 Jn(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 Xn(n,e,t,r){let o=new URLSearchParams;r?.include_buckets!==void 0&&o.set("include_buckets",String(r?.include_buckets)),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 Qn(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 Zn(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));let a=s.toString(),l=`/v1/leaderboards/${i(e)}/${i(t)}/${i(r)}`+(a?`?${a}`:"");return n.client.get(l,o?.signal)}async function et(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 nt(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 tt(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 rt(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 ot(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 st(n,e,t){let r=`/v1/events/${i(e)}`;return n.client.get(r,t?.signal)}async function it(n,e,t){let r=`/v2/games/${i(n.gameId())}/game-rooms/${i(e)}`;return n.client.getWithEtag(r,{...t?.signal===void 0?{}:{signal:t.signal},...t?.ifNoneMatch===void 0?{}:{ifNoneMatch:t.ifNoneMatch}})}async function at(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));let o=r.toString(),s=`/v1/leaderboards/${i(e)}`+(o?`?${o}`:"");return n.client.get(s,t?.signal)}async function lt(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 dt(n,e,t){let r=`/v1/game-room-templates/${i(e)}`;return n.client.get(r,t?.signal)}async function ut(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 ct(n,e,t){let r=`/v1/inventory/transfers/${i(e)}`;return n.client.get(r,t?.signal)}async function mt(n,e,t){return n.client.post("/v1/inventory/transfers",e,t?.signal)}async function gt(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 pt(n,e,t,r){let o=`/v1/settings/${i(e)}/${i(t)}`;return n.client.get(o,r?.signal)}async function yt(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 ft(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 _t(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 bt(n,e){return n.client.get("/v1/game-room-templates",e?.signal)}async function Rt(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 St(n,e,t){let r=`/v1/games/${i(n.gameId())}/matches/${i(e)}/end`;return n.client.post(r,void 0,t?.signal)}async function xt(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 kt(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 wt(n,e,t){let r=`/v1/inventory/transfers/${i(e)}/reject`;return n.client.post(r,void 0,t?.signal)}async function At(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 Tt(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 Ot(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 Gt(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 Pt(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 Q="gem_";var Ct=1e4,qt=50,$t=1e3,Lt=65536-4*1024,Z=n=>typeof n=="number"?n:0,jt=n=>typeof n=="string"?n:"";function ee(){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 Mt(n){return n?.retryable===true}function Ut(n,e){let t=n??{},r=Array.isArray(t.rejected)?t.rejected.map(o=>{let s=o??{};return {index:Z(s.index),code:jt(s.code)}}):[];return {accepted:Z(t.accepted),rejected:r,dropped:e,duplicate:t.duplicate===true}}function ne(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 te(n){let e=Math.max(1,Math.floor(n.maxQueue??$t)),t=[],r=0,o=null,s=false,a=false,l=false,d=false,c=g=>{n.log?.(g);},m=()=>{o!==null&&(n.clock.clearTimeout(o),o=null);},R=()=>{o!==null||s||a||(o=n.clock.setTimeout(()=>{o=null,f().catch(()=>{});},Ct));},h=()=>{let g=Math.min(t.length,100),y=128;for(let x=0;x<g;x+=1){let k=t[x];if(k===void 0)break;if(y+=JSON.stringify(ne(k,0)).length+1,y>Lt)return Math.max(1,x)}return g};async function f(g){if(t.length===0)return {accepted:0,rejected:[],dropped:0,duplicate:false};m();let y=t.splice(0,h()),x=r;r=0;let k=Math.round(n.clock.now()),P={batch_id:ee(),sent_at_ms:k,events:y.map(S=>ne(S,k))};a=true;try{let S=await n.client.post(`/v1/games/${encodeURIComponent(n.gameId)}/analytics/events`,P,g,{replaySafe:!0}),w=Ut(S,x);for(let ue of w.rejected)c(`[gem] analytics: an event was refused (${ue.code}). See the analytics_events section of your game config.`);return w}catch(S){if(Mt(S))for(t=[...y,...t],r+=x;t.length>e;)t.shift(),r+=1;else c(`[gem] analytics: ${y.length} event(s) were discarded \u2014 the platform refused the batch and will refuse it again: ${String(S)}`);throw S}finally{a=false,t.length>0&&R();}}return {track(g,y,x={}){if(s)return;if(typeof g!="string"||g===""){d||(d=true,c(`[gem] analytics: '${y}' 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(y.startsWith(Q)){l||(l=true,c(`[gem] analytics: '${y}' 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 k={},P={};for(let[S,w]of Object.entries(x))typeof w=="string"?k[S]=w:typeof w=="number"&&Number.isFinite(w)&&(P[S]=w);for(;t.length>=e;)t.shift(),r+=1;t.push({uid:ee(),playerId:g,name:y,atMs:n.clock.now(),dimensions:k,measures:P}),t.length>=qt?f().catch(()=>{}):R();},flush:g=>f(g),get pending(){return t.length},dispose(){s=true,m(),t=[],r=0;}}}function Ht(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 L(n,e={}){let t=e.clock??O,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=U(n,{clock:t,...e.onAuthStateChange===void 0?{}:{onStateChange:e.onAuthStateChange}}),s=z({baseUrl:r,tokenSource:o.source,defaultQuery:{game_id:n.gameId,channel:n.channel},...e.fetch===void 0?{}:{fetch:e.fetch}}),a=new A({transport:s,clock:t}),l={gameId:n.gameId,channel:n.channel,matchId:n.matchId,...n.gameRoomId===void 0?{}:{gameRoomId:n.gameRoomId}},d=Ht({client:a,gameId:()=>l.gameId}),c=l.gameRoomId,m=n.endMatch,R=n.log,h=te({client:a,clock:t,gameId:l.gameId,...typeof R=="function"?{log:g=>R.call(n,g)}:{}}),f={identity:l,client:a,api:d,match:{end:async g=>{if(m!==void 0){let y=await m.call(n);(y==="ok"||y==="already_ended")&&$.add(f);return}try{await d.matchEnd(l.matchId,g===void 0?void 0:{signal:g});}catch(y){if(y instanceof p&&y.reason==="not_found"){$.add(f);return}throw y}$.add(f);}},analytics:h,...c===void 0?{}:{room:{get:g=>d.getGameRoomV2(c,g),args:g=>d.getRoomArgs(c,g)}},dispose:()=>{h.dispose(),o.dispose();}};return f}var $=new WeakSet;function re(n){return $.has(n)}var Ft=["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"],Nt=new Set(Ft);function oe(n){return typeof n=="string"&&Nt.has(n)?n:"unknown"}var b=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 G(n){return new b(n)}var se={toPlain(n){return b.unwrap(n)},compare(n,e,t){let r=n instanceof b?b.unwrap(n):n,o=e instanceof b?b.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 b?b.unwrap(n):n,r=e instanceof b?b.unwrap(e):e;return t.normalize("NFC")===r.normalize("NFC")}};var ie="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 F(n,e={}){let t=e.clock??O,r=()=>{let l=n();if(l===null)throw new Error(ie);return l},o=null,s=()=>{if(o===null)throw new Error(ie);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 room(){return s().room},dispose(){o?.dispose();},get sizeClass(){return r().sizeClass},get roomArgs(){return r().roomArgs},get roster(){return r().roster},players(){return r().players()},profile(l){let c=r().profile?.(l);if(!c)return null;let m=c.displayName;return typeof m!="string"||m===""?null:{displayName:G(m),...typeof c.displayTag=="string"&&c.displayTag!==""?{displayTag:G(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=L(r(),{...e,clock:t});},ended:()=>o!==null&&re(o)}}function ae(n,e={}){let{server:t,attach:r}=F(()=>n,e);return r(),t}var Bt=5e3;function Dt(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:oe(e)}}}function Vt(n,e,t){return t||e?.endMatch!==void 0?false:n===void 0?true:n.reason==="idle_timeout"}function zt(n){return n instanceof Error?n.message:String(n)}function le(n,e={}){return ()=>{let t=null,{server:r,attach:o,ended:s}=F(()=>t,e),a=n(r),l={async init(d){t=d,o(),await a.init?.();},async shutdown(d){let c=Dt(d);try{await a.shutdown?.(c);}finally{try{Vt(c,t,s())&&await r.match.end(AbortSignal.timeout(Bt)).catch(m=>{m instanceof p&&m.reason==="not_found"||t?.warn?.(`ending the match after shutdown failed: ${zt(m)}`);});}finally{r.dispose();}}}};return a.join&&(l.join=(d,c)=>a.join?.(d,c)),a.leave&&(l.leave=(d,c)=>a.leave?.(d,c)),a.message&&(l.message=(d,c,m,R)=>a.message?.(d,c,m,R)),l}}var Wt=new Set(["unlocked","already_unlocked","suppressed"]);function de(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"||!Wt.has(o.outcome)||typeof o.achievement_id!="string"||o.achievement_id==="")continue;let s=o.outcome;t.push({achievementId:o.achievement_id,progressionDefinitionId:typeof o.progression_definition_id=="string"?o.progression_definition_id:"",points:s==="unlocked"&&typeof o.points=="number"&&Number.isFinite(o.points)?o.points:0,outcome:s,...typeof o.reason=="string"?{reason:o.reason}:{}});}return t}
2
+ export{v as AuthError,I as CONDITIONAL_HEADERS,p as GemApiError,A as GemClient,b as PlayerText,_ as TransportRefusal,de as achievementReceipts,G as asPlayerText,L as createGemServer,X as createHostTokenSource,ae as createMatchServer,le as defineServer,O as systemClock,se as text,D as toBase64};//# sourceMappingURL=gem-web-sdk.server.js.map
3
3
  //# sourceMappingURL=gem-web-sdk.server.js.map
package/dist/index.d.ts CHANGED
@@ -24,6 +24,7 @@ declare const PARENT_TO_FRAME: readonly [
24
24
  "gem.roomEvent",
25
25
  "gem.socketState",
26
26
  "gem.seatedEvent",
27
+ "gem.autoStartFailedEvent",
27
28
  "gem.signalEvent",
28
29
  "gem.dedicatedEvent",
29
30
  "gem.partyResult",
@@ -62,7 +63,7 @@ declare const FRAME_TO_PARENT: readonly [
62
63
  "gem.requestAd",
63
64
  "gem.requestSignIn"
64
65
  ];
65
- type GemCapability = "ads" | "signIn" | "purchases" | "devtools" | "screenshot" | "feedbackContext" | "rooms" | "p2p" | "dedicated" | "clusterTarget" | "parties" | "partySeating" | "socketState" | "audioState" | "rewardCue" | "frameStats" | "viewport" | "localHost" | "cohorts" | "deviceSettings" | "asyncOpponents";
66
+ type GemCapability = "ads" | "signIn" | "purchases" | "devtools" | "screenshot" | "feedbackContext" | "rooms" | "p2p" | "dedicated" | "clusterTarget" | "parties" | "autoStartFailure" | "partySeating" | "socketState" | "audioState" | "rewardCue" | "frameStats" | "viewport" | "localHost" | "cohorts" | "deviceSettings" | "asyncOpponents";
66
67
  declare const CAPABILITY_GATES: Readonly<Record<string, string>>;
67
68
  declare const CAPABILITY_NAMESPACE_GATES: ReadonlyArray<readonly [
68
69
  string,
@@ -115,8 +116,16 @@ interface GemPlayer {
115
116
  readonly type: "gem.player";
116
117
  readonly untrusted: {
117
118
  displayName: string;
119
+ displayTag?: string;
118
120
  displayHandle: string;
119
121
  };
122
+ readonly playerId?: string;
123
+ readonly discriminator?: string;
124
+ readonly avatarIconUrl?: string;
125
+ readonly badges?: {
126
+ itemId: string;
127
+ iconUrl: string;
128
+ }[];
120
129
  readonly displayTag: string;
121
130
  readonly avatarUrl?: string;
122
131
  }
@@ -183,6 +192,12 @@ interface GemSeatedEvent {
183
192
  readonly type: "gem.seatedEvent";
184
193
  readonly roomId: string;
185
194
  }
195
+ interface GemAutoStartFailedEvent {
196
+ readonly gem: typeof PROTOCOL;
197
+ readonly type: "gem.autoStartFailedEvent";
198
+ readonly roomId: string;
199
+ readonly code: string;
200
+ }
186
201
  interface GemSignalEvent {
187
202
  readonly gem: typeof PROTOCOL;
188
203
  readonly type: "gem.signalEvent";
@@ -211,6 +226,7 @@ interface GemClusterTarget {
211
226
  readonly gem: typeof PROTOCOL;
212
227
  readonly type: "gem.clusterTarget";
213
228
  readonly clusterTargetId: string;
229
+ readonly clusterTargetIds?: string[];
214
230
  }
215
231
  interface GemDevtools {
216
232
  readonly gem: typeof PROTOCOL;
@@ -387,7 +403,7 @@ interface GemSignInResult {
387
403
  readonly requestId: string;
388
404
  readonly outcome: "signed_in" | "declined" | "unavailable";
389
405
  }
390
- type ParentMessage = GemHandshake | GemToken | GemTokenDenied | GemPlayer | GemPause | GemPrefs | GemCohorts | GemViewport | GemDeviceSettings | GemWillTerminate | GemRoomEvent | GemSocketState | GemSeatedEvent | GemSignalEvent | GemDedicatedEvent | GemPartyResult | GemClusterTarget | GemDevtools | GemScreenshot | GemRequestContext | GemLocalServer | GemLocalServerDenied | GemError | GemPurchaseResult | GemDeviceSettingsResult | GemAdResult | GemSignInResult;
406
+ type ParentMessage = GemHandshake | GemToken | GemTokenDenied | GemPlayer | GemPause | GemPrefs | GemCohorts | GemViewport | GemDeviceSettings | GemWillTerminate | GemRoomEvent | GemSocketState | GemSeatedEvent | GemAutoStartFailedEvent | GemSignalEvent | GemDedicatedEvent | GemPartyResult | GemClusterTarget | GemDevtools | GemScreenshot | GemRequestContext | GemLocalServer | GemLocalServerDenied | GemError | GemPurchaseResult | GemDeviceSettingsResult | GemAdResult | GemSignInResult;
391
407
  type FrameMessage = GemHandshakeAccept | GemScreenshotDenied | GemGameContext | GemSignal | GemDedicatedOffer | GemPartyRequest | GemReady | GemProgress | GemRequestToken | GemRequestLocalServer | GemExit | GemOpenExternal | GemRequestFullscreen | GemAudioState | GemRewardCue | GemFrameStats | GemError | GemRequestPurchase | GemDeviceSettingsPut | GemRequestAd | GemRequestSignIn;
392
408
  type GemMessage = ParentMessage | FrameMessage;
393
409
  type Rejection = string | null;
@@ -407,6 +423,7 @@ declare const validateGemWillTerminate: (raw: unknown) => Rejection;
407
423
  declare const validateGemRoomEvent: (raw: unknown) => Rejection;
408
424
  declare const validateGemSocketState: (raw: unknown) => Rejection;
409
425
  declare const validateGemSeatedEvent: (raw: unknown) => Rejection;
426
+ declare const validateGemAutoStartFailedEvent: (raw: unknown) => Rejection;
410
427
  declare const validateGemSignalEvent: (raw: unknown) => Rejection;
411
428
  declare const validateGemDedicatedEvent: (raw: unknown) => Rejection;
412
429
  declare const validateGemPartyResult: (raw: unknown) => Rejection;
@@ -555,13 +572,18 @@ interface LocalServerDenial {
555
572
  readonly retryable: boolean;
556
573
  readonly reason: "refused" | "unavailable";
557
574
  }
558
- interface PlayerIdentity {
575
+ interface SendPlayerInput {
559
576
  readonly untrusted: {
560
577
  readonly displayName: string;
561
- readonly displayHandle: string;
578
+ readonly displayTag?: string;
562
579
  };
563
- readonly displayTag: string;
564
- readonly avatarUrl?: string;
580
+ readonly playerId?: string;
581
+ readonly discriminator?: string;
582
+ readonly avatarIconUrl?: string;
583
+ readonly badges?: readonly {
584
+ readonly itemId: string;
585
+ readonly iconUrl: string;
586
+ }[];
565
587
  }
566
588
  interface RoomEventRelay {
567
589
  readonly event: "updated" | "match_started" | "match_ready" | "match_failed" | "version_stale";
@@ -652,6 +674,11 @@ declare class GemHost {
652
674
  }): boolean;
653
675
  sendSeatedEvent(roomId: string): boolean;
654
676
  relaySeatedEvent(raw: unknown): boolean;
677
+ sendAutoStartFailedEvent(failure: {
678
+ roomId: string;
679
+ code: string;
680
+ }): boolean;
681
+ relayAutoStartFailedEvent(raw: unknown): boolean;
655
682
  relaySocketEvent(raw: unknown): readonly RelayDestination[];
656
683
  relaySignalEvent(raw: unknown): boolean;
657
684
  sendSignalEvent(relay: RelayedSignal): boolean;
@@ -669,8 +696,8 @@ declare class GemHost {
669
696
  denyToken(denial: TokenDenial): void;
670
697
  grantLocalServer(grant: LocalServerGrant): boolean;
671
698
  denyLocalServer(denial: LocalServerDenial): boolean;
672
- sendClusterTarget(clusterTargetId: string): boolean;
673
- sendPlayer(player: PlayerIdentity): void;
699
+ sendClusterTarget(clusterTargets: string | readonly string[]): boolean;
700
+ sendPlayer(player: SendPlayerInput): void;
674
701
  private chainExpired;
675
702
  private localCorrelationId;
676
703
  sendPause(paused: boolean): void;
@@ -727,7 +754,11 @@ declare const text: {
727
754
  };
728
755
  type ClusterTargetLike = string | null | undefined;
729
756
  type ClusterTargetResolver = () => Promise<ClusterTargetLike>;
757
+ type ClusterTargetListResolver = () => Promise<readonly string[]>;
758
+ type ClusterTargetRefresher = (refused: readonly string[]) => Promise<readonly string[]>;
759
+ declare const MAX_CLUSTER_TARGETS = 3;
730
760
  declare function normaliseClusterTarget(value: ClusterTargetLike): string | undefined;
761
+ declare function normaliseClusterTargets(values: unknown): string[];
731
762
  interface ClusterTargetBridge {
732
763
  parentSupports(capability: string): boolean;
733
764
  }
@@ -735,12 +766,28 @@ interface ClusterTargetSourceOptions {
735
766
  readonly bridge: ClusterTargetBridge;
736
767
  readonly clock: Clock;
737
768
  readonly timeoutMs?: number;
769
+ readonly refreshTimeoutMs?: number;
738
770
  }
739
771
  interface ClusterTargetSource {
740
772
  resolve: ClusterTargetResolver;
741
- accept(clusterTargetId: ClusterTargetLike): void;
773
+ resolveList: ClusterTargetListResolver;
774
+ refresh: ClusterTargetRefresher;
775
+ accept(clusterTargetId: ClusterTargetLike, clusterTargetIds?: unknown): void;
742
776
  }
743
777
  declare function createClusterTargetSource(options: ClusterTargetSourceOptions): ClusterTargetSource;
778
+ interface PlayerBadge {
779
+ readonly itemId: string;
780
+ readonly iconUrl: string;
781
+ }
782
+ interface PlayerIdentity {
783
+ readonly playerId?: string;
784
+ readonly displayName?: PlayerText;
785
+ readonly discriminator?: string;
786
+ readonly displayTag?: PlayerText;
787
+ readonly avatarIconId?: string;
788
+ readonly avatarIconUrl?: string;
789
+ readonly badges: readonly PlayerBadge[];
790
+ }
744
791
  interface RewardCue {
745
792
  currencySlug: string;
746
793
  expected?: number;
@@ -750,6 +797,11 @@ interface RewardCue {
750
797
  };
751
798
  }
752
799
  type FrameState = "waiting" | "connected" | "refused" | "closed";
800
+ interface FramePlayer extends PlayerIdentity {
801
+ readonly displayName: PlayerText;
802
+ readonly displayHandle: PlayerText;
803
+ readonly avatarUrl?: string;
804
+ }
753
805
  interface FrameCallbacks {
754
806
  onToken?(msg: GemToken): void;
755
807
  onPause?(msg: GemPause): void;
@@ -766,14 +818,10 @@ interface FrameCallbacks {
766
818
  onTokenDenied?(msg: GemTokenDenied): void;
767
819
  onLocalServer?(msg: GemLocalServer): void;
768
820
  onLocalServerDenied?(msg: GemLocalServerDenied): void;
769
- onPlayer?(player: {
770
- displayName: PlayerText;
771
- displayHandle: PlayerText;
772
- displayTag: string;
773
- avatarUrl?: string;
774
- }): void;
821
+ onPlayer?(player: FramePlayer): void;
775
822
  onRoomEvent?(msg: GemRoomEvent): void;
776
823
  onSeatedEvent?(msg: GemSeatedEvent): void;
824
+ onAutoStartFailedEvent?(msg: GemAutoStartFailedEvent): void;
777
825
  onSocketState?(msg: GemSocketState): void;
778
826
  onSignalEvent?(msg: GemSignalEvent): void;
779
827
  onDedicatedEvent?(msg: GemDedicatedEvent): void;
@@ -975,6 +1023,7 @@ interface AllocationTarget {
975
1023
  }
976
1024
  interface StartMatchOptions$1 extends AllocationTarget {
977
1025
  readonly clusterTargetId?: ClusterTargetLike;
1026
+ readonly nextClusterTarget?: () => Promise<string | undefined>;
978
1027
  readonly clock?: Clock;
979
1028
  readonly retry?: StartMatchRetryOptions;
980
1029
  readonly signal?: AbortSignal;
@@ -1177,16 +1226,13 @@ interface AutoReconnectOptions {
1177
1226
  readonly attempts?: number;
1178
1227
  readonly maxDelayMs?: number;
1179
1228
  }
1180
- interface RoomMember {
1229
+ interface RoomMember extends PlayerIdentity {
1181
1230
  readonly playerId: string;
1182
1231
  readonly isReady: boolean;
1183
1232
  readonly role: string;
1184
1233
  readonly joinedAt: number;
1185
1234
  readonly groupId?: string;
1186
1235
  readonly platform?: string;
1187
- readonly displayName?: PlayerText;
1188
- readonly displayTag?: PlayerText;
1189
- readonly discriminator?: string;
1190
1236
  }
1191
1237
  interface Room {
1192
1238
  readonly id: string;
@@ -1204,6 +1250,7 @@ interface Room {
1204
1250
  readonly roomArgsTemplate?: readonly RoomArgEntry[];
1205
1251
  readonly gameChannel: string;
1206
1252
  readonly region?: string;
1253
+ readonly clusterTargetId?: string;
1207
1254
  readonly matchId?: string;
1208
1255
  readonly version: number;
1209
1256
  readonly templateId?: string;
@@ -1213,6 +1260,10 @@ interface Room {
1213
1260
  readonly updatedAt: number;
1214
1261
  readonly startedAt?: number;
1215
1262
  }
1263
+ interface MatchAutoStartFailed {
1264
+ readonly roomId: string;
1265
+ readonly code: string;
1266
+ }
1216
1267
  interface RoomSummary {
1217
1268
  readonly id: string;
1218
1269
  readonly gameId: string;
@@ -1286,11 +1337,11 @@ declare class RoomsApi {
1286
1337
  constructor(options: RoomsApiOptions);
1287
1338
  list(options: ListRoomsOptions): Promise<RoomPage>;
1288
1339
  myRooms(signal?: AbortSignal): Promise<RoomPage>;
1289
- create(options: CreateRoomOptions, version: ResolvedClientVersion): Promise<Room>;
1340
+ create(options: CreateRoomOptions, version: ResolvedClientVersion, clusterTargetId?: string): Promise<Room>;
1290
1341
  get(roomId: string, signal?: AbortSignal): Promise<Room>;
1291
1342
  join(roomId: string, options: JoinRoomOptions, version: ResolvedClientVersion): Promise<Room>;
1292
1343
  joinByCode(code: string, options: JoinRoomOptions, version: ResolvedClientVersion): Promise<Room>;
1293
- quickJoin(options: QuickJoinOptions, version: ResolvedClientVersion): Promise<Room>;
1344
+ quickJoin(options: QuickJoinOptions, version: ResolvedClientVersion, clusterTargetIds?: readonly string[]): Promise<Room>;
1294
1345
  leave(roomId: string, asGroup: boolean, signal?: AbortSignal, keepalive?: boolean): Promise<void>;
1295
1346
  close(roomId: string, signal?: AbortSignal): Promise<void>;
1296
1347
  update(roomId: string, options: UpdateRoomOptions): Promise<Room>;
@@ -1344,6 +1395,9 @@ interface RoomEventMap {
1344
1395
  matchStartWaiting: [
1345
1396
  StartMatchWaiting
1346
1397
  ];
1398
+ matchAutoStartFailed: [
1399
+ MatchAutoStartFailed
1400
+ ];
1347
1401
  matchAllocationStarted: [
1348
1402
  string
1349
1403
  ];
@@ -1436,6 +1490,8 @@ interface RoomManagerOptions {
1436
1490
  readonly followMatch?: boolean;
1437
1491
  readonly resolveParty?: PartyResolver;
1438
1492
  readonly resolveClusterTarget?: ClusterTargetResolver;
1493
+ readonly resolveClusterTargets?: ClusterTargetListResolver;
1494
+ readonly refreshClusterTargets?: ClusterTargetRefresher;
1439
1495
  readonly ensureLocalServer?: (gameRoomId: string) => Promise<void>;
1440
1496
  readonly autoReconnect?: AutoReconnectWiring;
1441
1497
  readonly recoverStaleMembership?: boolean;
@@ -1497,6 +1553,7 @@ interface RoomManager {
1497
1553
  once<K extends RoomEventName>(event: K, listener: (...args: RoomEventMap[K]) => void): () => void;
1498
1554
  handleRoomEvent(event: RelayedRoomEvent): void;
1499
1555
  handleSeated(roomId: string): void;
1556
+ handleAutoStartFailed(roomId: string, code: string): void;
1500
1557
  reconcileSeats(): Promise<void>;
1501
1558
  reconcile(hint?: MatchEndHint): Promise<void>;
1502
1559
  startPolling(intervalMs?: number): void;
@@ -1978,4 +2035,4 @@ interface P2pMatchApi {
1978
2035
  session(matchId: string): P2pSession | null;
1979
2036
  }
1980
2037
  declare function createP2pApi(options: P2pApiOptions): P2pMatchApi;
1981
- export { type AutoReconnectOptions, type AwaitMatchOptions, CAPABILITY_GATES, CAPABILITY_NAMESPACE_GATES, CHANNELS, CHANNEL_KINDS, type ChannelKind, type ClientPlatform, ClientTelemetry, type ClientTelemetryOptions, type ClientVersion, type Clock, type ClusterTarget, type ClusterTargetBridge, type ClusterTargetLike, type ClusterTargetResolver, type ClusterTargetSource, type ClusterTargetSourceOptions, type ConnectOptions, type CreateRoomOptions, INBOUND_EVENTS as DEDICATED_INBOUND_EVENTS, DEFAULT_WELCOME_CEILING_MS, DEVICE_SETTINGS_MAX_BYTES, type DataChannelLike$1 as DataChannelLike, type DedicatedServerApi, type DedicatedServerApiOptions, DedicatedServerError, type DedicatedServerFailure, type DedicatedServerSession, type DedicatedSignalTransport, DedicatedSignalingHub, type DedicatedSignalingOptions, type EstablishOptions, FRAME_TO_PARENT, type FailedMatch, type FrameCallbacks, type FrameMessage, type FrameOptions, type FrameState, type GemAdResult, type GemAudioState, type GemCapability, type GemClusterTarget, type GemCohorts, type GemDedicatedEvent, type GemDedicatedOffer, type GemDeviceSettings, type GemDeviceSettingsPut, type GemDeviceSettingsResult, type GemDevtools, type GemError, type GemErrorCode, type GemExit, GemFrame, type GemFrameStats, type GemGameContext, type GemHandshake, type GemHandshakeAccept, GemHost, type GemLocalServer, type GemLocalServerDenied, type GemMessage, type GemOpenExternal, type GemPartyRequest, type GemPartyResult, type GemPause, type GemPlayer, type GemPrefs, type GemProgress, type GemPurchaseResult, type GemReady, type GemRequestAd, type GemRequestContext, type GemRequestFullscreen, type GemRequestLocalServer, type GemRequestPurchase, type GemRequestSignIn, type GemRequestToken, type GemRewardCue, type GemRoomEvent, type GemScreenshot, type GemScreenshotDenied, type GemSeatedEvent, type GemSignInResult, type GemSignal, type GemSignalEvent, type GemSocketState, type GemToken, type GemTokenDenied, type GemViewport, type GemWillTerminate, HANDSHAKE_TIMEOUT_MS, type HandshakeEvent, type HostCallbacks, HostMigration, type HostOptions, type HostState, type JoinCredential, type JoinExchange, type JoinRoomOptions, type JoinWelcome, type KeySource, type ListRoomsOptions, MALFORMED_INBOUND_KEY, MAX_ARRAY_LENGTH, MAX_MESSAGE_BYTES, MAX_MESSAGE_DEPTH, MAX_MESSAGE_NODES, MAX_SIGNALS_PER_SECOND, MAX_SOCKET_FRAME_BYTES, MIGRATION_TIMEOUT_MS, type MatchConnectionState, type MatchEnded, type MatchOutcome, type MatchOutcomeWaitOptions, type MatchReconnected, type MatchReconnecting, type MatchSession, type MatchSessionPhase, type MatchSuspended, type MigrationState, type OfferRefusal, type OfferRequest, P2pApi, type P2pConnectOptions, P2pError, type P2pEventMap, type P2pEventName, type P2pFailure, type P2pMatchApi, type P2pPeer, P2pSession, PARENT_TO_FRAME, PROTOCOL, type ParentMessage, type PartyBridge, type PartyEventRelay, type PartyResolver, type PartyResolverOptions, type PeerConnectionLike$1 as PeerConnectionLike, type PlayerIdentity, PlayerText, type PortLike, type PortMessageHandler, type PresentCredentialOptions, type QuickJoinOptions, RATE_LIMITS, RateLimiter, type ReadyMatch, type Rejection, type RelayedDedicatedEvent, type RelayedRoomEvent, type RelayedSignal, type ResolvedClientVersion, type Room, type RoomArgEntry, type RoomArgScalar, type RoomArgType, type RoomArgValue, type RoomArgs, RoomEmitter, type RoomEventMap, type RoomEventName, type RoomManager, type RoomManagerOptions, type RoomMember, type RoomOperationError, type RoomPage, type RoomStatus, type RoomSummary, RoomsApi, type RoomsApiOptions, SUPPORTED_VERSIONS, type SdpType$1 as SdpType, type SessionDescriptionLike$1 as SessionDescriptionLike, type SignalTransport, type SignalingAnswer, type SignalingChannel, SignalingClient, type SignalingIntent, type StartMatchOptions, type StartedMatch$1 as StartedMatch, TELEMETRY_EVENTS, TRANSPORT_LABELS, type TelemetrySample, type TokenDenial, type TokenGrant, type TransportLabel, type TurnLease, type UpdateRoomOptions, VALIDATORS, type VerifiedCredential, WEBRTC_DEDICATED, WEBRTC_P2P, WEB_ENGINE_VERSION, WEB_PROTOCOL_VERSION, type WindowLike, asPlayerText, awaitMatchOutcome, browserPeerConnection, buildDedicatedOfferFrame, buildSocketFrame, capabilityFor, createClusterTargetSource, createDedicatedServerApi, createKeySource, createP2pApi, createPartyResolver, createRoomManager, deviceSettingsByteLength, establishDataChannel, fingerprintOf, fingerprintsMatch, generateCertificate, isOrigin, listClusterTargets, memberFromWire, negotiateVersion, normaliseClusterTarget, normaliseFingerprint, originsEqual, presentJoinCredential, projectDedicatedEvent, projectPartyEvent, projectSignal, roomArgValuesFromWire, roomArgsTemplateFromWire, roomFromWire, startMatch, summaryFromWire, systemClock, text, unavailableSignaling, validateGemAdResult, validateGemAudioState, validateGemClusterTarget, validateGemCohorts, validateGemDedicatedEvent, validateGemDedicatedOffer, validateGemDeviceSettings, validateGemDeviceSettingsPut, validateGemDeviceSettingsResult, validateGemDevtools, validateGemError, validateGemExit, validateGemFrameStats, validateGemGameContext, validateGemHandshake, validateGemHandshakeAccept, validateGemLocalServer, validateGemLocalServerDenied, validateGemOpenExternal, validateGemPartyRequest, validateGemPartyResult, validateGemPause, validateGemPlayer, validateGemPrefs, validateGemProgress, validateGemPurchaseResult, validateGemReady, validateGemRequestAd, validateGemRequestContext, validateGemRequestFullscreen, validateGemRequestLocalServer, validateGemRequestPurchase, validateGemRequestSignIn, validateGemRequestToken, validateGemRewardCue, validateGemRoomEvent, validateGemScreenshot, validateGemScreenshotDenied, validateGemSeatedEvent, validateGemSignInResult, validateGemSignal, validateGemSignalEvent, validateGemSocketState, validateGemToken, validateGemTokenDenied, validateGemViewport, validateGemWillTerminate, validateSize, verifyCredential };
2038
+ export { type AutoReconnectOptions, type AwaitMatchOptions, CAPABILITY_GATES, CAPABILITY_NAMESPACE_GATES, CHANNELS, CHANNEL_KINDS, type ChannelKind, type ClientPlatform, ClientTelemetry, type ClientTelemetryOptions, type ClientVersion, type Clock, type ClusterTarget, type ClusterTargetBridge, type ClusterTargetLike, type ClusterTargetListResolver, type ClusterTargetRefresher, type ClusterTargetResolver, type ClusterTargetSource, type ClusterTargetSourceOptions, type ConnectOptions, type CreateRoomOptions, INBOUND_EVENTS as DEDICATED_INBOUND_EVENTS, DEFAULT_WELCOME_CEILING_MS, DEVICE_SETTINGS_MAX_BYTES, type DataChannelLike$1 as DataChannelLike, type DedicatedServerApi, type DedicatedServerApiOptions, DedicatedServerError, type DedicatedServerFailure, type DedicatedServerSession, type DedicatedSignalTransport, DedicatedSignalingHub, type DedicatedSignalingOptions, type EstablishOptions, FRAME_TO_PARENT, type FailedMatch, type FrameCallbacks, type FrameMessage, type FrameOptions, type FrameState, type GemAdResult, type GemAudioState, type GemAutoStartFailedEvent, type GemCapability, type GemClusterTarget, type GemCohorts, type GemDedicatedEvent, type GemDedicatedOffer, type GemDeviceSettings, type GemDeviceSettingsPut, type GemDeviceSettingsResult, type GemDevtools, type GemError, type GemErrorCode, type GemExit, GemFrame, type GemFrameStats, type GemGameContext, type GemHandshake, type GemHandshakeAccept, GemHost, type GemLocalServer, type GemLocalServerDenied, type GemMessage, type GemOpenExternal, type GemPartyRequest, type GemPartyResult, type GemPause, type GemPlayer, type GemPrefs, type GemProgress, type GemPurchaseResult, type GemReady, type GemRequestAd, type GemRequestContext, type GemRequestFullscreen, type GemRequestLocalServer, type GemRequestPurchase, type GemRequestSignIn, type GemRequestToken, type GemRewardCue, type GemRoomEvent, type GemScreenshot, type GemScreenshotDenied, type GemSeatedEvent, type GemSignInResult, type GemSignal, type GemSignalEvent, type GemSocketState, type GemToken, type GemTokenDenied, type GemViewport, type GemWillTerminate, HANDSHAKE_TIMEOUT_MS, type HandshakeEvent, type HostCallbacks, HostMigration, type HostOptions, type HostState, type JoinCredential, type JoinExchange, type JoinRoomOptions, type JoinWelcome, type KeySource, type ListRoomsOptions, MALFORMED_INBOUND_KEY, MAX_ARRAY_LENGTH, MAX_CLUSTER_TARGETS, MAX_MESSAGE_BYTES, MAX_MESSAGE_DEPTH, MAX_MESSAGE_NODES, MAX_SIGNALS_PER_SECOND, MAX_SOCKET_FRAME_BYTES, MIGRATION_TIMEOUT_MS, type MatchAutoStartFailed, type MatchConnectionState, type MatchEnded, type MatchOutcome, type MatchOutcomeWaitOptions, type MatchReconnected, type MatchReconnecting, type MatchSession, type MatchSessionPhase, type MatchSuspended, type MigrationState, type OfferRefusal, type OfferRequest, P2pApi, type P2pConnectOptions, P2pError, type P2pEventMap, type P2pEventName, type P2pFailure, type P2pMatchApi, type P2pPeer, P2pSession, PARENT_TO_FRAME, PROTOCOL, type ParentMessage, type PartyBridge, type PartyEventRelay, type PartyResolver, type PartyResolverOptions, type PeerConnectionLike$1 as PeerConnectionLike, PlayerText, type PortLike, type PortMessageHandler, type PresentCredentialOptions, type QuickJoinOptions, RATE_LIMITS, RateLimiter, type ReadyMatch, type Rejection, type RelayedDedicatedEvent, type RelayedRoomEvent, type RelayedSignal, type ResolvedClientVersion, type Room, type RoomArgEntry, type RoomArgScalar, type RoomArgType, type RoomArgValue, type RoomArgs, RoomEmitter, type RoomEventMap, type RoomEventName, type RoomManager, type RoomManagerOptions, type RoomMember, type RoomOperationError, type RoomPage, type RoomStatus, type RoomSummary, RoomsApi, type RoomsApiOptions, SUPPORTED_VERSIONS, type SdpType$1 as SdpType, type SendPlayerInput, type SessionDescriptionLike$1 as SessionDescriptionLike, type SignalTransport, type SignalingAnswer, type SignalingChannel, SignalingClient, type SignalingIntent, type StartMatchOptions, type StartedMatch$1 as StartedMatch, TELEMETRY_EVENTS, TRANSPORT_LABELS, type TelemetrySample, type TokenDenial, type TokenGrant, type TransportLabel, type TurnLease, type UpdateRoomOptions, VALIDATORS, type VerifiedCredential, WEBRTC_DEDICATED, WEBRTC_P2P, WEB_ENGINE_VERSION, WEB_PROTOCOL_VERSION, type WindowLike, asPlayerText, awaitMatchOutcome, browserPeerConnection, buildDedicatedOfferFrame, buildSocketFrame, capabilityFor, createClusterTargetSource, createDedicatedServerApi, createKeySource, createP2pApi, createPartyResolver, createRoomManager, deviceSettingsByteLength, establishDataChannel, fingerprintOf, fingerprintsMatch, generateCertificate, isOrigin, listClusterTargets, memberFromWire, negotiateVersion, normaliseClusterTarget, normaliseClusterTargets, normaliseFingerprint, originsEqual, presentJoinCredential, projectDedicatedEvent, projectPartyEvent, projectSignal, roomArgValuesFromWire, roomArgsTemplateFromWire, roomFromWire, startMatch, summaryFromWire, systemClock, text, unavailableSignaling, validateGemAdResult, validateGemAudioState, validateGemAutoStartFailedEvent, validateGemClusterTarget, validateGemCohorts, validateGemDedicatedEvent, validateGemDedicatedOffer, validateGemDeviceSettings, validateGemDeviceSettingsPut, validateGemDeviceSettingsResult, validateGemDevtools, validateGemError, validateGemExit, validateGemFrameStats, validateGemGameContext, validateGemHandshake, validateGemHandshakeAccept, validateGemLocalServer, validateGemLocalServerDenied, validateGemOpenExternal, validateGemPartyRequest, validateGemPartyResult, validateGemPause, validateGemPlayer, validateGemPrefs, validateGemProgress, validateGemPurchaseResult, validateGemReady, validateGemRequestAd, validateGemRequestContext, validateGemRequestFullscreen, validateGemRequestLocalServer, validateGemRequestPurchase, validateGemRequestSignIn, validateGemRequestToken, validateGemRewardCue, validateGemRoomEvent, validateGemScreenshot, validateGemScreenshotDenied, validateGemSeatedEvent, validateGemSignInResult, validateGemSignal, validateGemSignalEvent, validateGemSocketState, validateGemToken, validateGemTokenDenied, validateGemViewport, validateGemWillTerminate, validateSize, verifyCredential };