@onceworlds/cli 0.10.0 → 0.12.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.
package/dist/sdk.js CHANGED
@@ -1,5 +1,5 @@
1
- "use strict";(()=>{var Vt=Object.defineProperty;var Ft=(n,e,t)=>e in n?Vt(n,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):n[e]=t;var u=(n,e,t)=>Ft(n,typeof e!="symbol"?e+"":e,t);var qt=["#ffe0c4","#f3c59c","#d9a174","#b57a4f","#8a5836","#5c3a24","#5fd4b9","#8bd46e","#5ec8f2","#a98bff","#ff8fc0","#b9c2cf"],Ne=["#e53935","#fb8c00","#fdd835","#7cb342","#2e7d32","#00897b","#00acc1","#1e88e5","#283593","#8e24aa","#ec407a","#f5f5f5","#9e9e9e","#424242","#1b1b1b","#6d4c41"],Wt=["Happy","Grin","Shades","Wink","Surprised","Determined","Joyful","Shy"],Jt=["None","Sprout","Cap","Beanie","Crown","Headphones","Horns","Antenna","Bow","Halo","Party hat","Cat ears","Short hair","Tuft","Bob","Spikes","Bun","Curls"];var Yt=["Plain","Band","Spots","Stripes","Star"];var Xt={skin:qt.length,shirt:Ne.length,pants:Ne.length,face:Wt.length,hat:Jt.length,top:Yt.length};function Be(n){if(!n||typeof n!="object")return null;let e=n,t={};for(let[r,o]of Object.entries(Xt)){let s=e[r],i=typeof s=="number"?s:typeof s=="string"&&/^[0-9]{1,3}$/.test(s)?Number(s):NaN;if(!Number.isInteger(i)||i<0||i>=o)return null;t[r]=i}return t}var b={roomMaxPlayersDefault:16,roomMaxPlayersCap:30,teamsMax:8,messageBytes:16*1024,presenceBytes:1024,stateKeyLength:64,stateValueBytes:16*1024,stateKeys:256,privateKeys:16,privateValueBytes:4*1024,privateBytesPerPlayer:8*1024,messagesPerSecond:60,messagesPerSecondMin:10,roomBytesPerSecond:128*1024,roomBytesPerSecondMin:16*1024,presenceHz:20,presenceHzMin:5,roomMessagesPerSecond:900,roomBytesPerSecondTotal:2*1024*1024,matchCountdownMs:3e3,matchCountdownMaxMs:1e4,matchIdleMs:45e3,matchAbandonMs:12e4,idleAfterMs:3e4,idleAbandonMs:5*6e4,rankedPairMatchesPerDay:5,chatLength:200,chatIntervalMs:750,chatHistory:50,chatChannelsPerPlayer:10,saveValueBytes:64*1024,saveKeysPerGame:100,saveBytesPerGame:1024*1024,guestSaveBytesPerGame:128*1024,serverDataKeys:128,serverDataBytes:512*1024,serverDataServersPerGame:5e3,serverDataBytesPerGame:64*1024*1024,serverDataIdleDays:120,gameDataKeys:32,gameDataListMax:100,gameDataItemBytes:1024,gameDataValueBytes:8*1024,gameDataMapFields:1e3,gameDataMapPerPlayer:100,gameDataNumberMax:1e15,gameDataWritesPerMinute:30,deployFiles:2e3,deployFileBytes:25*1024*1024,deployHtmlBytes:10*1024*1024,deployPathLength:200,deployTotalBytes:100*1024*1024,envVars:50,envValueBytes:4*1024,envTotalBytes:16*1024,proxyRequestBytes:1024*1024,proxyTextRequestBytes:256*1024,proxySpeechRequestBytes:16*1024,proxyResponseBytes:10*1024*1024,proxyMaxOutputTokens:4096,proxyCallsPerDay:2e3,proxyCallsPerDayMax:1e5,proxyCallsPerPlayerPerDay:100,proxyCallsPerNetworkPerDay:1e3,proxyMediaCallsPerDay:100,proxyMediaCallsPerDayMax:1e4,proxyMediaCallsPerPlayerPerDay:20,proxyMediaCallsPerNetworkPerDay:25,proxyUnitsPerDay:2e6,proxyUnitsPerDayMax:1e8,proxyUnitsPerPlayerPerDay:25e4,proxyUnitsPerGuestPerDay:1e5,proxyUnitsPerNetworkPerDay:5e5,errorReportsPerPage:10,consoleLineLength:2e3,consoleLinesPerSecond:50,gameNameLength:60,gameDescriptionLength:1e3,galleryItems:5,mediaImageBytes:5*1024*1024,mediaVideoBytes:30*1024*1024,mediaGifBytes:1024*1024,mediaGifSide:512,mediaUploadsPerDay:200,mediaBytesPerDay:500*1024*1024,badgesPerGame:50,controlHints:12,controlHintKeys:4,controlKeyLength:12,controlActionLength:40,helpLength:400,badgeNameLength:50,badgeDescriptionLength:200,leaderboardsPerGame:25,leaderboardTop:100,gamesPerOwner:50,gamesCreatedPerCreatorPerDay:3,uploadAccountAgeMs:10080*6e4,deploysPerOwnerPerDay:100,draftsPerOwnerPerDay:1e3,draftsKeptPerGame:3,cliTokensPerAccount:10,cliDeviceCodeSeconds:600,deploymentsKeptPerGame:10,deployBytesPerOwnerPerDay:2*1024*1024*1024,deployEntriesPerOwnerPerDay:1e5,bioLength:500,exportRows:2e3,exportSaveChars:4*1024*1024,exportEveryMs:60*6e4,friendsMax:200,friendRequestsMax:100,friendRequestsIncomingMax:50,friendRequestsPerDay:20,friendRequestsPerNetworkPerDay:120,friendRequestPushesPerDay:5,passwordMinLength:8,passwordMaxLength:72,signupsPerNetworkPerDay:100,signupsPerWidePerDay:300,guestsPerNetworkPerDay:300,guestsPerWidePerDay:1500,visitsPerNetworkPerDay:10,visitSeconds:10,errorsPerDeployment:100,controlButtons:4,controlLabelLength:12,partySize:6,partyChatHistory:50,messageLength:500,messagesPerPage:50,groupChatMembers:20,groupChatNameLength:40,conversationsListed:50,notificationsListed:50,invitesPerRequest:10,inviteLiveMs:30*6e4,partyInviteMs:60*6e4};var Zt="host:",N="data:";function V(n){return n.startsWith(Zt)||n.startsWith(N)}var Ge=/^(?!__proto__$)[A-Za-z0-9_.:-]{1,59}$/;function fe(n){return n.startsWith(N)}function ge(n){return N+n}function je(n){return n.startsWith("private:")||n.startsWith("room:")}function he(n){let e=n.length;for(let t=0;t<n.length;t++){let r=n.charCodeAt(t);r<128||(r<2048?e+=1:r>=55296&&r<=56319&&t+1<n.length&&(n.charCodeAt(t+1)&64512)===56320?(e+=2,t++):e+=2)}return e}var ye=/^[A-Za-z][A-Za-z0-9_.-]{0,31}$/;var Qt={counter:["add"],list:["push"],record:["best"],map:["claim","release"],value:["set"]},en={add:"add(key, n)",push:"push(key, item)",best:"best(key, n)",claim:"claim(key, field)",release:"release(key, field)",set:"set(key, value)"};function tn(n){return Qt[n].map(e=>`ow.data.game.${en[e]}`).join(" or ")}function be(n,e){let r=Math.floor(e/864e5);if(n==="daily")return{start:r*864e5,next:(r+1)*864e5};let o=r-(r+3)%7;return{start:o*864e5,next:(o+7)*864e5}}function nn(n,e){switch(n.type){case"counter":return{type:"counter",value:n.min,...n.reset?{resetsAt:be(n.reset,e).next}:{}};case"list":return{type:"list",items:[]};case"record":return{type:"record",value:null,by:null,at:null};case"map":return{type:"map",fields:{}};case"value":return{type:"value",value:null,at:null}}}function rn(n,e,t){if(!e||e.type!==n.type)return nn(n,t);if(e.type==="counter"&&n.type==="counter"){if(!n.reset)return{type:"counter",value:e.value};let s=be(n.reset,t);return{type:"counter",value:(e.period??0)>=s.start?e.value:n.min,resetsAt:s.next}}let{period:r,...o}=e;return o}function ze(n,e,t,r,o){if(r.guest&&!n.guests)return{code:"sign_in",message:`Log in to change '${t.key}': guests can't (a ${n.type} is for signed-in players unless onceworlds.json says "guests": true).`};let s={id:r.id,name:r.name},i=rn(n,e,o);switch(i.type){case"counter":{if(t.op!=="add"||n.type!=="counter")break;let l=Math.min(n.max,Math.max(n.min,i.value+t.n)),d=n.reset?be(n.reset,o):null;return{next:{type:"counter",value:l,...d?{resetsAt:d.next,period:d.start}:{}},result:{type:"counter",value:l}}}case"list":{if(t.op!=="push"||n.type!=="list")break;return{next:{type:"list",items:[{value:t.item,by:s,at:o},...i.items].slice(0,n.max)},result:{type:"list",ok:!0}}}case"record":{if(t.op!=="best"||n.type!=="record")break;return i.value!==null&&i.by&&i.at!==null&&!(n.order==="max"?t.n>i.value:t.n<i.value)?{next:i,result:{type:"record",value:i.value,by:i.by,at:i.at,record:!1}}:{next:{type:"record",value:t.n,by:s,at:o},result:{type:"record",value:t.n,by:s,at:o,record:!0}}}case"map":{if(t.op!=="claim"&&t.op!=="release"||n.type!=="map")break;let l={...i.fields},d=Object.hasOwn(l,t.field)?l[t.field]:void 0;return t.op==="release"?!d||d.by.id!==r.id?{next:i,result:{type:"map",ok:!1,...d?{holder:d.by}:{}}}:(delete l[t.field],{next:{type:"map",fields:l},result:{type:"map",ok:!0}}):d?{next:i,result:{type:"map",ok:d.by.id===r.id,holder:d.by}}:Object.values(l).filter(f=>f.by.id===r.id).length>=n.perPlayer?{code:"limit",message:`claim('${t.key}'): a player holds at most ${n.perPlayer} (onceworlds.json's "perPlayer"). Release one first.`}:Object.keys(l).length>=n.fields?{code:"full",message:`claim('${t.key}'): all ${n.fields} fields are taken (onceworlds.json's "fields").`}:(l[t.field]={by:s,at:o},{next:{type:"map",fields:l},result:{type:"map",ok:!0}})}case"value":{if(t.op!=="set"||n.type!=="value")break;return r.host?{next:{type:"value",value:t.value,at:o},result:{type:"value",ok:!0}}:{code:"not_host",message:`set('${t.key}'): only the host of one of the game's rooms sets a value. Join a room, and set it from the host's page (room.isHost).`}}}return{code:"wrong_op",message:`'${t.key}' is a ${n.type}: use ${tn(n.type)}.`}}var Ie=n=>n.replace(/[\u0000-\u001f\u007f]/g," ").replace(/\s+/g," ").trim();var on=/^[a-z0-9][a-z0-9-]{0,19}$/;function He(n){if(!n||typeof n!="object")return null;let e=n,t=[];for(let o of Array.isArray(e.buttons)?e.buttons:[]){if(t.length>=b.controlButtons)break;let{id:s,label:i}=o??{};if(typeof s!="string"||!on.test(s)||t.some(d=>d.id===s))continue;let l=typeof i=="string"?i.replace(/[\u0000-\u001f\u007f]/g,"").replace(/\s+/g," ").trim().slice(0,b.controlLabelLength).trim():"";t.push({id:s,label:l||s})}let r=e.stick===!0;return r||t.length>0?{stick:r,zone:e.zone==="corner"?"corner":"wide",buttons:t}:null}var F="host:ow.settings",sn=/^[a-z][a-zA-Z0-9]{0,15}$/;function we(n){if(!Array.isArray(n))return[];let e=[];for(let t of n){if(e.length>=6)break;let{id:r,label:o,options:s,default:i}=t??{};if(typeof r!="string"||!sn.test(r)||e.some(f=>f.id===r)||!Array.isArray(s))continue;let l=[];for(let f of s){let p=typeof f=="object"&&f!==null?f.value:f;if(typeof p!="string"&&typeof p!="number"||typeof p=="number"&&!Number.isFinite(p)||l.length>=8||l.some(D=>D.value===p))continue;let S=typeof f=="object"&&f!==null&&typeof f.label=="string"?f.label:String(p);l.push({value:p,label:Ie(S).slice(0,20)||String(p)})}if(l.length<2)continue;let d=typeof o=="string"?Ie(o).slice(0,24):"";e.push({id:r,label:d||r,options:l,default:l.some(f=>f.value===i)?i:l[0].value})}return e}function Ue(n,e){let t=e!==null&&typeof e=="object"?e[n.id]:void 0;return n.options.some(r=>r.value===t)?t:n.default}var Ke="onceworlds:hello",Ve="onceworlds:connect",Fe=/^[a-z0-9]{1,32}~(?:(?:0|[1-9]\d{0,3})\.(?:0|[1-9]\d{0,4})\.(?:0|[1-9]\d{0,5}))?~[0-9a-z]{1,11}~[lp]~[A-Za-z0-9_-]{43}$/;var qe=["log","info","warn","error"],We="onceworlds-console";var Je=/^[A-Za-z0-9-]{1,64}$/;function Ye(){let n=1,e=!1,t=()=>e?0:n,r=new Map;if(typeof AudioNode<"u"&&typeof AudioDestinationNode<"u"){let f=AudioNode.prototype.connect,p=AudioNode.prototype.disconnect,S=v=>typeof OfflineAudioContext>"u"||!(v instanceof OfflineAudioContext),D=v=>{let h=r.get(v);return h||(h=v.createGain(),h.gain.value=t(),f.call(h,v.destination),r.set(v,h)),h};AudioNode.prototype.connect=function(v,...h){return v instanceof AudioDestinationNode&&S(v.context)&&r.get(v.context)!==this?(f.call(this,D(v.context),...h),v):f.call(this,v,...h)},AudioNode.prototype.disconnect=function(...v){let h=v[0];if(h instanceof AudioDestinationNode){let R=r.get(h.context);R&&R!==this&&(v[0]=R)}return p.apply(this,v)}}let o=new WeakMap,s=new Set,i=typeof HTMLMediaElement<"u"?Object.getOwnPropertyDescriptor(HTMLMediaElement.prototype,"volume"):void 0,l=f=>i?.set?.call(f,ke((o.get(f)??1)*t())),d=f=>{o.has(f)||!i?.get||(o.set(f,i.get.call(f)),s.add(new WeakRef(f)))};if(i?.get&&i.set){Object.defineProperty(HTMLMediaElement.prototype,"volume",{configurable:!0,enumerable:i.enumerable,get(){return o.has(this)?o.get(this):i.get.call(this)},set(p){d(this),o.set(this,ke(Number(p))),l(this)}});let f=HTMLMediaElement.prototype.play;HTMLMediaElement.prototype.play=function(){return d(this),l(this),f.call(this)}}return{get volume(){return n},get muted(){return e},apply(f){n=ke(f.volume),e=f.muted;for(let[p,S]of r)S.gain.setTargetAtTime(t(),p.currentTime,.02);for(let p of s){let S=p.deref();S?l(S):s.delete(p)}}}}function ke(n){return Number.isFinite(n)?Math.min(1,Math.max(0,n)):1}function Xe(n){try{let e=n?.getAttribute("data-build");return e&&Fe.test(e)?e:null}catch{return null}}var an=200,Ze=2,j=20,Qe=200;function et(n){try{return new URLSearchParams(n).get(We)==="1"}catch{return!1}}function tt(n){return typeof n=="object"&&n!==null&&n.solo===!0?"standalone":"platform"}function nt(n,e,t=Date.now,r=setTimeout){let o=null,s=[],i=-1/0,l=0,d=0,f=!1,p=!1,S=h=>{o?o(h):s.length<an&&s.push(h)},D=()=>{let h=t();return h-i>=1e3&&(i=h,l=0),l<b.consoleLinesPerSecond?(l++,!0):(d++,f||(f=!0,r(()=>{f=!1;let R=d;d=0,R>0&&D()&&S({level:"warn",text:`${R} more ${R===1?"line":"lines"} left out`,at:t()})},Math.max(0,1e3-(h-i)))),!1)},v=(h,R,$)=>{if(!D())return;let G=rt(e?R.split(`${e}/`).join(""):R);S({level:h,text:G,at:t(),...$?{source:$.source.slice(0,300),line:$.line,column:$.column}:{}})};for(let h of qe){let R=n[h];typeof R=="function"&&(n[h]=function(...$){if(R.apply(n,$),!p){p=!0;try{v(h,ln($))}catch{}finally{p=!1}}})}return{error(h,R){if(!p){p=!0;try{v("error",h,R)}catch{}finally{p=!1}}},connect(h){o=h;for(let R of s.splice(0))h(R)}}}function ln(n){let e="",t=n;if(typeof n[0]=="string"){let r=1;e=n[0].replace(/%[sdifoOc%]/g,o=>{if(o==="%%")return"%";if(r>=n.length)return o;let s=n[r++];return o==="%c"?"":o==="%d"||o==="%i"?String(typeof s=="number"?Math.trunc(s):parseInt(q(s),10)):o==="%f"?String(typeof s=="number"?s:parseFloat(q(s))):o==="%s"?q(s):z(s)}),t=n.slice(r)}for(let r of t)e+=e?` ${q(r)}`:q(r);return rt(e)}function q(n){return typeof n=="string"?n:z(n)}function z(n,e=0){try{switch(typeof n){case"string":return JSON.stringify(n.length>Qe?`${n.slice(0,Qe)}\u2026`:n);case"bigint":return`${n}n`;case"symbol":return n.toString();case"function":return`\u0192 ${n.name||"anonymous"}()`;case"object":break;default:return String(n)}if(n===null)return"null";if(n instanceof Error)return te(n);if(n instanceof Date)return Number.isNaN(n.getTime())?"Invalid Date":n.toISOString();if(n instanceof RegExp)return String(n);if(n instanceof Map||n instanceof Set)return`${n.constructor.name}(${n.size})`;if(ArrayBuffer.isView(n))return`${n.constructor.name}(${"length"in n?n.length:n.byteLength})`;if(typeof Element<"u"&&n instanceof Element)return`<${n.tagName.toLowerCase()}>`;if(Array.isArray(n))return e>=Ze?`Array(${n.length})`:`[${n.slice(0,j).map(i=>z(i,e+1)).join(", ")}${n.length>j?`, \u2026${n.length-j} more`:""}]`;let t=typeof n.constructor=="function"&&n.constructor!==Object?`${n.constructor.name} `:"";if(e>=Ze)return`${t}{\u2026}`;let r=Object.keys(n),o=r.slice(0,j).map(s=>`${/^[A-Za-z_$][\w$]*$/.test(s)?s:JSON.stringify(s)}: ${z(n[s],e+1)}`);return`${t}{${o.join(", ")}${r.length>j?`, \u2026${r.length-j} more`:""}}`}catch{return Object.prototype.toString.call(n)}}function te(n){try{let e=`${n.name||"Error"}: ${n.message}`,t=typeof n.stack=="string"?n.stack:"";return t?t.startsWith(e)?t:`${e}
2
- ${t}`:e}catch{return"Error"}}function rt(n){return n.length>b.consoleLineLength?`${n.slice(0,b.consoleLineLength-1)}\u2026`:n}var cn={wasd:{up:"w",down:"s",left:"a",right:"d"},arrows:{up:"ArrowUp",down:"ArrowDown",left:"ArrowLeft",right:"ArrowRight"}},un=.45,dn=.3,ve={" ":["Space",32],Enter:["Enter",13],Shift:["ShiftLeft",16],Control:["ControlLeft",17],Alt:["AltLeft",18],Escape:["Escape",27],Tab:["Tab",9],Backspace:["Backspace",8],ArrowLeft:["ArrowLeft",37],ArrowUp:["ArrowUp",38],ArrowRight:["ArrowRight",39],ArrowDown:["ArrowDown",40]},ne=class{constructor(e,t){u(this,"touch");u(this,"stick",{x:0,y:0});u(this,"held",new Set);u(this,"downs",new Map);u(this,"stickMode");u(this,"buttonKeys",new Map);u(this,"down",new Map);u(this,"show");u(this,"reportTouch");this.show=e,this.reportTouch=t,this.touch=typeof matchMedia=="function"&&matchMedia("(pointer: coarse)").matches,window.addEventListener("pointerdown",r=>r.isTrusted&&this.setTouch(r.pointerType!=="mouse"),!0),window.addEventListener("keydown",r=>r.isTrusted&&this.setTouch(!1),!0),window.addEventListener("blur",()=>this.release()),document.addEventListener("visibilitychange",()=>document.hidden&&this.release())}set(e){let t=e??{};this.stickMode=t.stick==="wasd"||t.stick==="arrows"||t.stick==="analog"?t.stick:void 0;let r=Array.isArray(t.buttons)?t.buttons:[],o=e?He({stick:this.stickMode!==void 0,zone:t.zone,buttons:r}):null;this.buttonKeys=new Map;for(let s of o?.buttons??[]){let i=r.find(l=>l?.id===s.id)?.key;typeof i=="string"&&i&&this.buttonKeys.set(s.id,i)}this.show(o),o?this.update():this.release()}receive(e){let t=o=>typeof o=="number"&&Number.isFinite(o)?Math.max(-1,Math.min(1,o)):0;this.stick.x=t(e?.x),this.stick.y=t(e?.y);let r=new Set(Array.isArray(e?.buttons)?e.buttons.filter(o=>typeof o=="string"):[]);for(let o of r)this.held.has(o)||this.downs.set(o,(this.downs.get(o)??0)+1);this.held=r,this.update()}pressed(e){return this.held.has(e)}presses(e){return this.downs.get(e)??0}update(){let e=new Map;if(this.stickMode==="wasd"||this.stickMode==="arrows"){let t=cn[this.stickMode],r=(o,s)=>{s>(this.down.has(o)?dn:un)&&e.set(o,ot(o))};r(t.up,-this.stick.y),r(t.down,this.stick.y),r(t.left,-this.stick.x),r(t.right,this.stick.x)}for(let t of this.held){let r=this.buttonKeys.get(t);r&&e.set(r,ot(r))}for(let[t,r]of this.down)e.has(t)||(this.down.delete(t),st(r,!1));for(let[t,r]of e)this.down.has(t)||(this.down.set(t,r),st(r,!0))}release(){this.stick.x=0,this.stick.y=0,this.held.clear(),this.update()}setTouch(e){e!==this.touch&&(this.touch=e,e||this.release(),this.reportTouch(e))}};function ot(n){let e=n==="Space"?" ":n;return Object.prototype.hasOwnProperty.call(ve,e)?{key:e,code:ve[e][0],keyCode:ve[e][1]}:/^[a-z]$/i.test(e)?{key:e.toLowerCase(),code:`Key${e.toUpperCase()}`,keyCode:e.toUpperCase().charCodeAt(0)}:/^[0-9]$/.test(e)?{key:e,code:`Digit${e}`,keyCode:48+Number(e)}:{key:e,code:"",keyCode:0}}function st(n,e){try{let t={key:n.key,code:n.code,keyCode:n.keyCode,which:n.keyCode,bubbles:!0,cancelable:!0},r=new KeyboardEvent(e?"keydown":"keyup",t);r.keyCode!==n.keyCode&&(Object.defineProperty(r,"keyCode",{get:()=>n.keyCode}),Object.defineProperty(r,"which",{get:()=>n.keyCode})),(document.activeElement??document.body??document).dispatchEvent(r)}catch{}}function pn(n){switch(n.type){case"counter":return n.value;case"list":return n.items;case"record":return n.value===null?null:{value:n.value,by:n.by,at:n.at};case"map":return n.fields;case"value":return n.value}}function it(n=e=>console.warn(`[onceworlds] ${e}`)){let e=new Map;return t=>{let r=Date.now();r-(e.get(t)??-1/0)<5e3||(e.size>200&&e.clear(),e.set(t,r),n(t))}}function at(n,e){let t=new Set,r=async(o,s)=>{let i=`onceworlds.data.server.${s===null?"delete":"set"}('${String(o).slice(0,40)}')`,l=n();if(typeof o!="string"||!Ge.test(o))return e(`${i} did nothing: a key is 1-59 letters, digits or _ . : -`),!1;if(!l||l.closed)return e(`${i} did nothing: you're not in a room. Join one first (await onceworlds.rooms.join({ private: true })): server data belongs to a server.`),!1;if(!l.connected)return e(`${i} did nothing: the connection is down and the platform is reconnecting. Write it again after room.on('reconnect').`),!1;if(!l.isHost)return e(`${i} did nothing: only the room's host writes server data. Check onceworlds.data.server.canWrite, or send the change to the host (room.send) and let it write.`),!1;let d;try{d=JSON.stringify(s??null)}catch{d=void 0}return d===void 0?(e(`${i} did nothing: the value must be plain JSON data (numbers, text, lists, objects).`),!1):he(d)>b.stateValueBytes-128?(e(`${i} did nothing: the value is ${Math.ceil(he(d)/1024)} KB, and a key holds 16 KB. Split it into keys by area or chunk (a server keeps ${b.serverDataKeys} keys, ${b.serverDataBytes/1024} KB), or let the engine's Persist() save the world for you.`),!1):await l._writeAcked(ge(o),s??null)};return{get(o){let s=n();if(!s||typeof o!="string")return null;let i=s.state[ge(o)];return i===void 0?null:i},all(){let o=n(),s={};if(!o)return s;for(let[i,l]of Object.entries(o.state))i.startsWith("data:")&&(s[i.slice(5)]=l);return s},set:(o,s)=>r(o,s??null),delete:o=>r(o,null),get kept(){return n()?.kept??!1},get canWrite(){let o=n();return!!(o&&!o.closed&&o.isHost)},async reset(){let o=n();return o?o.owner!==o.me.id&&o.kind!=="solo"?(e("onceworlds.data.server.reset() did nothing: only a private server's owner starts its world over (room.owner)."),!1):o._resetData():(e("onceworlds.data.server.reset() did nothing: you're not in a room."),!1)},on(o,s){return o!=="change"||typeof s!="function"?()=>{}:(t.add(s),()=>t.delete(s))},_changed(o,s,i){for(let l of t)try{l(o,s??null,i)}catch(d){console.error('[onceworlds] error in data.server "change" listener',d)}}}}function lt(n,e){let t=async(o,s,i,l)=>{if(typeof o.key!="string"||!ye.test(o.key))return e(`${s} did nothing: '${String(o.key).slice(0,40)}' isn't a game data key (1-32 letters, digits, _ . or -, declared in onceworlds.json's "data").`),l;try{return i(await(await n()).op(o))}catch(d){return e(`${s} did nothing: ${d instanceof Error?d.message:String(d)}`),l}},r=(o,s)=>`onceworlds.data.game.${o}('${String(s).slice(0,40)}')`;return{async get(o){if(typeof o!="string"||!ye.test(o))return e(`${r("get",o)}: '${String(o).slice(0,40)}' isn't a game data key (1-32 letters, digits, _ . or -).`),null;try{return pn(await(await n()).read(o))}catch(s){return e(`${r("get",o)} read nothing: ${s instanceof Error?s.message:String(s)}`),null}},add:(o,s)=>t({key:o,op:"add",n:Number(s)},r("add",o),i=>i.type==="counter"?i.value:null,null),push:(o,s)=>t({key:o,op:"push",item:s},r("push",o),i=>i.type==="list",!1),best:(o,s)=>t({key:o,op:"best",n:Number(s)},r("best",o),i=>i.type==="record"?{value:i.value,by:i.by,at:i.at,record:i.record}:null,null),claim:(o,s)=>t({key:o,op:"claim",field:String(s)},r("claim",o),i=>i.type==="map"&&i.ok,!1),release:(o,s)=>t({key:o,op:"release",field:String(s)},r("release",o),i=>i.type==="map"&&i.ok,!1),set:(o,s)=>t({key:o,op:"set",value:s},r("set",o),i=>i.type==="value",!1)}}function ct(n,e){let t=b.gameDataNumberMax,r=s=>{switch(s.op){case"add":return{type:"counter",min:0,max:t,add:[-t,t],guests:!0};case"push":return{type:"list",max:b.gameDataListMax,bytes:b.gameDataItemBytes,guests:!0};case"best":return{type:"record",order:"max",min:-t,max:t,guests:!0};case"claim":case"release":return{type:"map",fields:b.gameDataMapFields,perPlayer:b.gameDataMapPerPlayer,guests:!0};case"set":return{type:"value",bytes:b.gameDataValueBytes,guests:!0}}},o=s=>{try{let i=e.get(`onceworlds:game:${s}`);return i?JSON.parse(i):null}catch{return null}};return{async read(s){let i=o(s);if(!i)throw new Error(`nothing is stored under '${s}' on this page yet (on its own, game data lives in this browser).`);return i},async op(s){let i=await n(),l=o(s.key),d=r(s);if(l&&l.type!==d.type)throw new Error(`'${s.key}' holds a ${l.type} on this page: it was first used that way.`);let f=ze(d,l,JSON.parse(JSON.stringify(s??null)),{id:i.id,name:i.name,host:!0},Date.now());if("code"in f)throw new Error(f.message);return e.set(`onceworlds:game:${s.key}`,JSON.stringify(f.next)),f.result}}}function ut(n){return{messagesPerSecond:n.messagesPerSecond*.85,messageBurst:n.messagesPerSecond*2*.85,bytesPerSecond:n.bytesPerSecond*.85,byteBurst:n.bytesPerSecond*4*.85}}var mn=60,fn=100,gn=5e3,re=class{constructor(e={}){u(this,"queue",[]);u(this,"rates",ut({messagesPerSecond:b.messagesPerSecond,bytesPerSecond:b.roomBytesPerSecond}));u(this,"messages",this.rates.messageBurst);u(this,"bytes",this.rates.byteBurst);u(this,"budget",{messagesPerSecond:b.messagesPerSecond,bytesPerSecond:b.roomBytesPerSecond});u(this,"refilledAt");u(this,"timer",null);u(this,"warnedAt",-1/0);u(this,"dropped",0);u(this,"now");u(this,"setTimer");u(this,"clearTimer");u(this,"warn");this.now=e.now??Date.now,this.setTimer=e.setTimer??((t,r)=>setTimeout(t,r)),this.clearTimer=e.clearTimer??(t=>clearTimeout(t)),this.warn=e.warn??(t=>console.warn(`[onceworlds] ${t}`)),this.refilledAt=this.now(),e.budget&&this.setBudget(e.budget)}setBudget(e){this.refill(),this.budget={messagesPerSecond:e.messagesPerSecond,bytesPerSecond:e.bytesPerSecond},this.rates=ut(this.budget),this.messages=Math.min(this.messages,this.rates.messageBurst),this.bytes=Math.min(this.bytes,this.rates.byteBurst),this.drain(!1)}get waiting(){return this.queue.length}event(e,t){this.queue.push({kind:"event",size:e,send:t}),this.settle()}urgent(e,t){this.queue.push({kind:"event",size:e,send:t}),this.drain(!0)}state(e,t,r){for(let o=this.queue.length-1;o>=0;o--){let s=this.queue[o];if(s.kind!=="state")break;if(s.key===e)return s.size=t,s.send=r,this.settle()}this.queue.push({kind:"state",key:e,size:t,send:r}),this.settle()}spend(e){this.refill(),this.bytes-=e}clear(){this.queue=[],this.timer!==null&&this.clearTimer(this.timer),this.timer=null}settle(){this.queue.length>this.waitingLimit(mn,12)&&(this.squeeze(),this.tell(`${this.queue.length} messages are waiting: a room takes about ${this.budget.messagesPerSecond} messages and ${Math.round(this.budget.bytesPerSecond/1024)} KB a second from each player. State is sent at its newest value and other messages in order. Send less: batch events, write state at 10-20 Hz, and only what changed.`)),this.drain(!1)}waitingLimit(e,t){return Math.max(t,Math.round(e*this.rates.messagesPerSecond/(b.messagesPerSecond*.85)))}refill(){let e=this.now(),t=Math.max(0,(e-this.refilledAt)/1e3);this.refilledAt=e,this.messages=Math.min(this.rates.messageBurst,this.messages+t*this.rates.messagesPerSecond),this.bytes=Math.min(this.rates.byteBurst,this.bytes+t*this.rates.bytesPerSecond)}drain(e){for(this.timer!==null&&(this.clearTimer(this.timer),this.timer=null),this.refill();this.queue.length>0;){let i=this.queue[0],l=Math.min(i.size(),this.rates.byteBurst);if(!e&&(this.messages<1||this.bytes<l))break;this.queue.shift(),this.messages-=1,this.bytes-=l;try{i.send()}catch(d){console.error("[onceworlds] a message could not be sent",d)}}if(this.queue.length===0)return;let t=Math.min(this.queue[0].size(),this.rates.byteBurst),r=Math.max(0,1-this.messages)/this.rates.messagesPerSecond,o=Math.max(0,t-this.bytes)/this.rates.bytesPerSecond,s=Math.min(250,Math.max(8,Math.ceil(Math.max(r,o)*1e3)));this.timer=this.setTimer(()=>{this.timer=null,this.drain(!1)},s)}squeeze(){let e=new Set;for(let o=this.queue.length-1;o>=0;o--){let s=this.queue[o];s.kind==="state"&&(e.has(s.key)?this.queue.splice(o,1):e.add(s.key))}let t=this.queue.filter(o=>o.kind==="event").length,r=this.waitingLimit(fn,20);for(let o=0;t>r&&o<this.queue.length;)this.queue[o].kind==="event"?(this.queue.splice(o,1),t--,this.dropped++):o++;this.dropped>0&&this.tell(`${this.dropped} messages were dropped so the rest arrive fresh: the game sends much more than a room takes (${this.budget.messagesPerSecond} messages, ${Math.round(this.budget.bytesPerSecond/1024)} KB a second per player). Send less.`)}tell(e){let t=this.now();t-this.warnedAt<gn||(this.warnedAt=t,this.warn(e))}};function B(n){try{let e=JSON.stringify(n)??"null",t=0;for(let r=0;r<e.length;r++)e.charCodeAt(r)>127&&(t+=2);return e.length+t+32}catch{return 1024}}var xe=Math.PI*2;function Se(n,e,t,r={},o=""){if(typeof n=="number"&&typeof e=="number"){if(r.angles?.includes(o)){let s=((e-n)%xe+xe+Math.PI)%xe-Math.PI;return n+s*t}return n+(e-n)*t}if(Array.isArray(n)&&Array.isArray(e)&&n.length===e.length)return e.map((s,i)=>Se(n[i],s,t,r,o));if(n&&e&&typeof n=="object"&&typeof e=="object"&&!Array.isArray(n)&&!Array.isArray(e)){let s={};for(let i of Object.keys(e))s[i]=i in n?Se(n[i],e[i],t,r,i):e[i];return s}return t<.5?n:e}function hn(n,e,t){if(t===void 0||!n||!e||typeof n!="object"||typeof e!="object")return!1;for(let[r,o]of Object.entries(e)){let s=n[r];if(typeof o=="number"&&typeof s=="number"&&Math.abs(o-s)>t)return!0}return!1}function dt(n,e,t={}){if(n.length===0)return;let r=n[0],o=n[n.length-1];if(e<=r.at)return r.d;if(e>=o.at)return o.d;let s=n.length-2;for(;s>0&&n[s].at>e;)s--;let i=n[s],l=n[s+1];return hn(i.d,l.d,t.snap)?l.d:Se(i.d,l.d,(e-i.at)/Math.max(1,l.at-i.at),t)}var pt=8,mt=2e3;var yn=3e3,bn=15e3,wn=5e3;function ft(n){let e={};for(let t of Object.keys(n))V(t)&&(e[t]=n[t]);return e}var O=()=>48,W=class{constructor(e,t,r=Date.now,o=[]){u(this,"id");u(this,"kind");u(this,"invite");u(this,"teams");u(this,"open");u(this,"ranked");u(this,"kept");u(this,"me");u(this,"owner");u(this,"players",new Map);u(this,"state",{});u(this,"host");u(this,"closed",!1);u(this,"connected",!0);u(this,"match");u(this,"listeners",new Map);u(this,"transport");u(this,"outbox",new re);u(this,"samples",new Map);u(this,"presenceTimer",null);u(this,"pendingPresence",null);u(this,"writes",0);u(this,"written",new Map);u(this,"confirmed",{});u(this,"shares",{messagesPerSecond:b.messagesPerSecond,presenceHz:b.presenceHz,bytesPerSecond:b.roomBytesPerSecond});u(this,"clock");u(this,"schema");u(this,"frozenSettings",null);u(this,"secrets",new Map);u(this,"offlineReady");u(this,"complained",new Map);u(this,"acks",new Map);this.transport=t,this.clock=r,this.schema=o,this.match=e.match??{phase:"lobby",n:0,min:1},this.applyBudget(e.budget),this.id=e.room,this.kind=e.room==="solo"?"solo":e.room.startsWith("private:")?"private":e.room.startsWith("room:")?"named":"public",this.invite=e.invite??null,this.teams=e.teams??0,this.open=e.open??!0,this.ranked=e.ranked??!1,this.kept=e.kept??je(e.room),this.owner=e.owner??null,this.host=e.host;for(let s of e.players)this.players.set(s.id,{...s}),s.presence!==null&&s.presence!==void 0&&this.samples.set(s.id,[{at:e.now??this.clock(),d:s.presence}]);this.me=this.players.get(e.you)??{id:e.you,name:"You",presence:null,team:0},this.players.set(this.me.id,this.me),this.state={...e.state},this.confirmed=ft(e.state);for(let[s,i]of Object.entries(e.private??{}))this.secrets.set(s,{...i});this.match.phase!=="lobby"&&(this.frozenSettings=this.chosenSettings())}get budget(){return this.shares}get settings(){return this.frozenSettings??this.chosenSettings()}setSetting(e,t){if(this.closed||!this.isHost||this.match.phase!=="lobby")return;let r=this.schema.find(s=>s.id===e);if(!r||!r.options.some(s=>s.value===t)||this.chosenSettings()[e]===t)return;let o=this.state[F];this.setState(F,{...o!==null&&typeof o=="object"?o:{},[e]:t}),this.clearReady(),this.emit("settings",this.settings)}chosenSettings(){let e=this.state[F];return Object.fromEntries(this.schema.map(t=>[t.id,Ue(t,e)]))}get isHost(){return this.connected&&this.host===this.me.id}get online(){return[...this.players.values()].filter(e=>e.connected!==!1)}get participants(){let e=this.match.participants;return this.match.phase==="lobby"||!e?[]:e.map(t=>this.players.get(t)).filter(t=>!!t)}get spectators(){let e=this.match.participants;return this.match.phase==="lobby"||!e?[]:this.online.filter(t=>!e.includes(t.id))}get leftOut(){let e=this.match.left;return this.match.phase==="lobby"||!e?.length?[]:this.spectators.filter(t=>e.includes(t.id))}get private(){return this.secrets.get(this.me.id)??{}}privateOf(e){return e===this.me.id||this.isHost?this.secrets.get(e)??{}:{}}setPrivate(e,t){this.closed||(this.setSecret(this.me.id,e,t??null),this.outbox.event(()=>B(t),()=>this.transport.private(e,t??null)))}setPrivateFor(e,t,r){if(!this.closed){if(e===this.me.id)return this.setPrivate(t,r);this.outbox.event(()=>B(r),()=>this.transport.private(t,r??null,String(e)))}}presenceAt(e,t={}){if(e===this.me.id)return this.me.presence;let r=this.samples.get(e);return!r||r.length===0?this.players.get(e)?.presence??null:dt(r,this.clock()-(t.delay??100),t)}keep(e,t,r){let o=this.samples.get(e)??[],s=o.length;for(;s>0&&o[s-1].at>t;)s--;for(o.splice(s,0,{at:t,d:r});o.length>pt||o.length>2&&o[0].at<t-mt;)o.shift();this.samples.set(e,o)}isParticipant(e=this.me.id){return this.match.phase!=="lobby"&&!!this.match.participants?.includes(e)}get spectating(){return this.match.phase!=="lobby"&&!this.isParticipant()}get running(){return this.match.phase==="playing"&&!this.match.paused}matchNow(){let e=this.match;if(e.phase!=="playing"||e.startedAt===void 0)return 0;let t=this.clock(),r=(e.pausedMs??0)+(e.paused?Math.max(0,t-e.paused.since):0);return Math.max(0,t-e.startedAt-r)}get canStart(){return this.isHost&&this.kind!=="public"&&this.match.phase==="lobby"&&this.online.length>=this.match.min&&this.allReady}get allReady(){return this.notReady.length===0}get notReady(){return this.online.filter(e=>e.id!==this.host&&!e.ready)}setReady(e=!0){this.closed||!!this.me.ready===e||(e?this.me.ready=!0:delete this.me.ready,this.connected||(this.offlineReady=e),this.outbox.urgent(O,()=>this.transport.ready(e)))}startMatch(e={}){if(!this.reachable("startMatch"))return;let t=Number(e.countdown),r={...Number.isFinite(t)?{countdown:Math.round(t*1e3)}:{},...e.open===!0?{open:!0}:{}};this.outbox.urgent(O,()=>this.transport.start(r))}endMatch(){this.reachable("endMatch")&&this.outbox.urgent(O,()=>this.transport.end())}pauseMatch(e=!0){this.reachable("pauseMatch")&&this.outbox.urgent(O,()=>this.transport.pause(e))}admit(e){let t=(Array.isArray(e)?e:[e]).map(String);t.length&&this.reachable("admit")&&this.outbox.urgent(O,()=>this.transport.admit(t))}reachable(e){let[t,r]=this.closed?["closed","this room is closed (you left it, were removed, or moved to another one)"]:this.connected?["",""]:["disconnected","the connection to the room is down and the platform is reconnecting: call it again after room.on('reconnect')"];return t?(this.complain(e,t,r),!1):!0}dropHostWrites(){for(let e of[...this.written.keys()]){if(!V(e))continue;this.written.delete(e);let t=this.confirmed[e]??null;JSON.stringify(this.state[e]??null)!==JSON.stringify(t)&&(t===null?delete this.state[e]:this.state[e]=t,this.emit("state",e,t,""))}}complain(e,t,r){let o=this.clock(),s=`${e}:${t}`;if(o-(this.complained.get(s)??-1/0)<wn)return;this.complained.set(s,o);let i=`${e}() did nothing: ${r}.`;console.warn(`[onceworlds] ${i} (${t})`),this.emit("error",{code:t,message:i})}transferHost(e){this.closed||this.outbox.urgent(O,()=>this.transport.transfer(String(e)))}hideLobby(e=!0){this.closed||this.transport.hideLobby?.(!!e)}clearReady(){if(!(this.closed||!this.isHost)){for(let e of this.players.values())delete e.ready;this.outbox.urgent(O,()=>this.transport.unready())}}send(e,t={}){this.closed||this.outbox.event(()=>B(e),()=>this.transport.send(e,t.to))}setPresence(e){if(!this.closed){if(this.me.presence=e,this.presenceTimer){this.pendingPresence={value:e};return}this.transport.presence(e),this.outbox.spend(B(e)),this.presenceTimer=setTimeout(()=>this.flushPresence(),1e3/this.shares.presenceHz)}}setState(e,t){this.writeState(e,t)}writeState(e,t){if(this.closed)return 0;if(V(e)&&this.connected&&this.host!==this.me.id)return this.complain("setState","not_host",`only the host writes ${e}`),0;t==null?delete this.state[e]:this.state[e]=t;let r=++this.writes;return this.written.set(e,{w:r,at:this.clock()}),this.outbox.state(e,()=>B(t)+e.length,()=>this.transport.state(e,t??null,r)),r}_writeAcked(e,t){if(this.closed||!this.connected)return Promise.resolve(!1);let r=this.writeState(e,t);return r?this.kind==="solo"?Promise.resolve(!0):new Promise(o=>{let s={w:r,done:l=>{clearTimeout(i),o(l)}},i=setTimeout(()=>this.settleAcks(e,l=>l===s,!1),bn);this.acks.set(e,[...this.acks.get(e)??[],s])}):Promise.resolve(!1)}_resetData(){return this.closed||!this.connected||!this.transport.dataReset?!1:(this.outbox.urgent(O,()=>this.transport.dataReset()),!0)}settleAcks(e,t,r){let o=this.acks.get(e);if(!o)return;let s=o.filter(i=>!t(i));s.length>0?this.acks.set(e,s):this.acks.delete(e);for(let i of o)t(i)&&i.done(r)}failAcks(){for(let e of[...this.acks.keys()])this.settleAcks(e,()=>!0,!1)}setTeam(e,t){this.closed||this.outbox.urgent(O,()=>this.transport.team(e,t))}setOpen(e){this.closed||this.outbox.urgent(O,()=>this.transport.open(e))}reportResult(e){this.closed||this.outbox.urgent(()=>B(e),()=>this.transport.result(e))}kick(e){this.closed||this.outbox.urgent(O,()=>this.transport.kick(String(e)))}voteKick(e){this.closed||this.outbox.urgent(O,()=>this.transport.voteKick(String(e)))}on(e,t){let r=this.listeners.get(e);return r||this.listeners.set(e,r=new Set),r.add(t),()=>r.delete(t)}leave(){this.closed||(this.transport.leave(),this.close("left"))}_receive(e){switch(e.t){case"welcome":return this.resync(e);case"away":{let t=this.players.get(e.id);return!t||t===this.me?void 0:(t.connected=!1,this.emit("away",t))}case"back":{let t=this.players.get(e.id);return!t||t===this.me?void 0:(delete t.connected,this.emit("back",t,e.fresh===!0))}case"ready":{let t=this.players.get(e.id);return!t||!!t.ready==(e.ready===!0)?void 0:(e.ready===!0?t.ready=!0:delete t.ready,this.emit("ready",t))}case"match":return this.applyMatch(e.match);case"idle":{let t=this.players.get(e.id);return!t||t===this.me||!!t.idle==(e.idle===!0)?void 0:(e.idle===!0?t.idle=!0:delete t.idle,this.emit("idle",t))}case"private":{let t=JSON.stringify(this.secrets.get(e.id)?.[e.k]??null);this.setSecret(e.id,e.k,e.v??null),t!==JSON.stringify(e.v??null)&&this.emit("private",e.k,e.v??null,e.id);return}case"privates":return this.applySecrets(e.all??{});case"unready":{for(let t of this.players.values())t.ready&&(delete t.ready,this.emit("ready",t));return}case"join":{let t={...e.player};return this.players.set(t.id,t),this.emit("join",t)}case"leave":{let t=this.players.get(e.id);return!t||t===this.me?void 0:(this.players.delete(e.id),this.samples.delete(e.id),this.emit("leave",t,e.kicked===!0))}case"votekick":{let t=this.players.get(e.id);t&&this.emit("votekick",t,e.votes,e.needed);return}case"host":if(this.host=e.id,e.id!==this.me.id)for(let t of[...this.secrets.keys()])t!==this.me.id&&this.secrets.delete(t);return e.id!==this.me.id&&(this.dropHostWrites(),this.failAcks()),this.emit("host",e.id);case"msg":return this.emit("message",e.d,this.players.get(e.from)??{id:e.from,name:"Unknown",presence:null,team:0},typeof e.at=="number"?e.at:this.clock(),typeof e.mt=="number"?e.mt:void 0);case"team":{let t=this.players.get(e.id);return t?(t.team=e.team,this.emit("team",t)):void 0}case"name":{let t=e.id===this.me.id?this.me:this.players.get(e.id);return!t||typeof e.name!="string"||t.name===e.name?void 0:(t.name=e.name,this.emit("rename",t))}case"open":return this.open=e.open,this.emit("open",e.open);case"rated":for(let t of e.changes){let r=this.players.get(t.id);r&&(r.rating=t.rating)}return this.emit("rated",e.changes,e.disputed,e.capped===!0);case"presence":{let t=this.players.get(e.id);return!t||t===this.me?void 0:(t.presence=e.d,this.keep(e.id,typeof e.at=="number"?e.at:this.clock(),e.d),this.emit("presence",t))}case"state":{e.from===this.me.id&&typeof e.w=="number"&&this.settleAcks(e.k,o=>o.w<=e.w,!0),V(e.k)&&(e.v===null?delete this.confirmed[e.k]:this.confirmed[e.k]=e.v);let t=this.written.get(e.k);if(t)if(e.from===this.me.id)if(typeof e.w!="number")this.written.delete(e.k);else{if(e.w<t.w)return;e.w===t.w&&this.written.delete(e.k)}else{if(this.clock()-t.at<yn)return;this.written.delete(e.k)}let r=JSON.stringify(this.state[e.k]??null);e.v===null?delete this.state[e.k]:this.state[e.k]=e.v,(e.from!==this.me.id||r!==JSON.stringify(e.v??null))&&this.emit("state",e.k,e.v,e.from),e.k===F&&this.schema.length>0&&this.frozenSettings===null&&r!==JSON.stringify(e.v??null)&&e.from!==this.me.id&&this.emit("settings",this.settings);return}case"chat":return this.emit("chat",e.entry);case"error":return typeof e.k=="string"&&typeof e.w=="number"&&this.settleAcks(e.k,t=>t.w===e.w,!1),e.code==="cooldown"&&this.me.ready&&(delete this.me.ready,this.emit("ready",this.me)),console.warn(`[onceworlds] ${e.message} (${e.code})`),this.emit("error",{code:e.code,message:e.message})}}_closed(e){this.close(e)}_disconnected(){this.closed||!this.connected||(this.connected=!1,this.outbox.clear(),this.failAcks(),this.emit("disconnect"))}close(e){this.closed||(this.closed=!0,this.outbox.clear(),this.failAcks(),this.presenceTimer&&clearTimeout(this.presenceTimer),this.emit("close",e))}flushPresence(){if(this.presenceTimer=null,!this.pendingPresence||this.closed)return;let{value:e}=this.pendingPresence;this.pendingPresence=null,this.transport.presence(e),this.outbox.spend(B(e)),this.presenceTimer=setTimeout(()=>this.flushPresence(),1e3/this.shares.presenceHz)}applyBudget(e){if(!e)return;let t=(r,o)=>typeof r=="number"&&Number.isFinite(r)&&r>0&&r<=o;t(e.presenceHz,b.presenceHz)&&(this.shares={...this.shares,presenceHz:e.presenceHz}),t(e.messagesPerSecond,b.messagesPerSecond)&&t(e.bytesPerSecond,b.roomBytesPerSecond)&&(this.shares={...this.shares,messagesPerSecond:e.messagesPerSecond,bytesPerSecond:e.bytesPerSecond},this.outbox.setBudget({messagesPerSecond:e.messagesPerSecond,bytesPerSecond:e.bytesPerSecond}))}setSecret(e,t,r){let o={...this.secrets.get(e)??{}};r===null?delete o[t]:o[t]=r,Object.keys(o).length>0?this.secrets.set(e,o):this.secrets.delete(e)}applySecrets(e){let t=[];for(let[r,o]of Object.entries(e))for(let[s,i]of Object.entries(o))JSON.stringify(this.secrets.get(r)?.[s]??null)!==JSON.stringify(i)&&t.push([r,s,i]);for(let[r,o]of this.secrets)for(let s of Object.keys(o))s in(e[r]??{})||t.push([r,s,null]);this.secrets=new Map(Object.entries(e).map(([r,o])=>[r,{...o}]));for(let[r,o,s]of t)this.emit("private",o,s,r)}applyMatch(e){let t=this.match;if(!(!e||JSON.stringify(t)===JSON.stringify(e))){if(this.match=e,e.phase!=="lobby"&&this.frozenSettings===null)this.frozenSettings=this.chosenSettings();else if(e.phase==="lobby"&&this.frozenSettings!==null){let r=JSON.stringify(this.frozenSettings);this.frozenSettings=null,r!==JSON.stringify(this.chosenSettings())&&queueMicrotask(()=>this.emit("settings",this.settings))}this.emit("match",e,t),t.phase!=="starting"&&e.phase==="starting"&&this.emit("starting",e),t.phase!=="playing"&&e.phase==="playing"&&this.emit("matchstart",e),t.phase!=="lobby"&&e.phase==="lobby"&&this.emit("matchend",e,t),t.phase==="playing"&&e.phase==="playing"&&(!t.paused&&e.paused?this.emit("matchpause",e):t.paused&&!e.paused&&this.emit("matchresume",e))}}resync(e){let t=this.connected,r=this.host!==e.host;this.connected=!0,this.host=e.host,this.written.clear(),this.confirmed=ft(e.state),this.applyBudget(e.budget);let o=new Set;for(let i of e.players){if(o.add(i.id),i.id===this.me.id){this.offlineReady===void 0&&!!this.me.ready!=!!i.ready&&(i.ready?this.me.ready=!0:delete this.me.ready,this.emit("ready",this.me));continue}let l=this.players.get(i.id);if(l)l.presence=i.presence,i.presence!==null&&i.presence!==void 0&&this.keep(i.id,e.now??this.clock(),i.presence),l.team=i.team,l.name!==i.name&&(l.name=i.name,this.emit("rename",l)),!!l.ready!=!!i.ready&&(i.ready?l.ready=!0:delete l.ready,this.emit("ready",l)),!!l.idle!=!!i.idle&&(i.idle?l.idle=!0:delete l.idle,this.emit("idle",l)),l.connected===!1!=(i.connected===!1)&&(i.connected===!1?l.connected=!1:delete l.connected,i.connected===!1?this.emit("away",l):this.emit("back",l,!1));else{let d={...i};this.players.set(i.id,d),this.emit("join",d)}}for(let[i,l]of this.players)o.has(i)||l===this.me||(this.players.delete(i),this.emit("leave",l));let s=new Set([...Object.keys(this.state),...Object.keys(e.state)]);for(let i of s){let l=e.state[i]??null;JSON.stringify(this.state[i]??null)!==JSON.stringify(l)&&(l===null?delete this.state[i]:this.state[i]=l,this.emit("state",i,l,""))}r&&this.emit("host",e.host),this.teams=e.teams??this.teams,this.kept=e.kept??this.kept,e.open!==void 0&&e.open!==this.open&&(this.open=e.open,this.emit("open",e.open)),this.applyMatch(e.match??{phase:"lobby",n:0,min:1}),this.applySecrets(e.private??{}),this.me.presence!==null&&this.transport.presence(this.me.presence),this.offlineReady!==void 0&&!!e.players.find(i=>i.id===this.me.id)?.ready!==this.offlineReady&&this.transport.ready(this.offlineReady),this.offlineReady=void 0,t||this.emit("reconnect")}emit(e,...t){for(let r of this.listeners.get(e)??[])try{r(...t)}catch(o){console.error(`[onceworlds] error in room "${e}" listener`,o)}}};function gt(n){let e=null,t=o=>n()._receive({t:"match",match:o}),r=()=>{let s=n().match;if(s.phase!=="starting")return;let{startsAt:i,...l}=s;t({...l,phase:"playing",startedAt:Date.now(),pausedMs:0})};return{send(){},presence(){},state(){},team(){},open(){},result(){},kick(){},voteKick(){},ready(){},unready(){},transfer(){},start(o){let s=n();if(s.match.phase!=="lobby")return;let i=Math.min(b.matchCountdownMaxMs,Math.max(0,o.countdown??b.matchCountdownMs));t({phase:"starting",n:s.match.n+1,min:s.match.min,id:`solo${s.match.n+1}`,seed:Math.floor(Math.random()*2**32),participants:[s.me.id],startsAt:Date.now()+i}),i===0?r():e=setTimeout(r,i)},end(){let o=n();e&&clearTimeout(e),e=null,o.match.phase!=="lobby"&&t({phase:"lobby",n:o.match.n,min:o.match.min})},pause(o){let s=n().match;if(s.phase!=="playing")return;let i=Date.now();if(o&&!s.paused)t({...s,paused:{since:i,reason:"host"}});else if(!o&&s.paused){let{paused:l,...d}=s;t({...d,pausedMs:(s.pausedMs??0)+Math.max(0,i-l.since)})}},admit(){},private(){},leave(){e&&clearTimeout(e),e=null}}}var ht=["pointerdown","pointermove","keydown","wheel","touchstart","touchmove","devicemotion","visibilitychange"],kn=5e3;function yt(n,e=b.idleAfterMs){let t=Date.now(),r=!1,o=()=>{t=Date.now(),r&&(r=!1,n(!1))},s=()=>{try{for(let l of navigator.getGamepads?.()??[])if(l&&(l.buttons.some(d=>d.pressed)||l.axes.some(d=>Math.abs(d)>.25)))return!0}catch{}return!1};for(let l of ht)window.addEventListener(l,o,{capture:!0,passive:!0});let i=setInterval(()=>{if(s())return o();!r&&Date.now()-t>e&&(r=!0,n(!0))},kn);return{get idle(){return r},stop(){clearInterval(i);for(let l of ht)window.removeEventListener(l,o,{capture:!0})}}}var bt=["pointerdown","keydown","touchstart","gamepadconnected"];function wt(n,e){let t=r=>{if(!(!r.isTrusted||!n())){for(let o of bt)window.removeEventListener(o,t,{capture:!0});e()}};for(let r of bt)window.addEventListener(r,t,{capture:!0,passive:!0})}var vt=["low","medium","high"],vn={low:.6,medium:.8,high:1},xn=24,Sn=18.5,Rn=26,Re=6e3,kt=2e4,En=5*6e4,Ee=class{constructor(e=2){u(this,"level",2);u(this,"slow",0);u(this,"smoothSince",0);u(this,"holdUntil",0);u(this,"probeAfter",kt);u(this,"steppedUpAt",-1/0);this.level=e}window(e,t,r){return t>xn?(this.smoothSince=0,++this.slow>=2&&e>=this.holdUntil&&this.level>0&&(e-this.steppedUpAt<Re+kt/2&&(this.probeAfter=Math.min(En,this.probeAfter*2)),this.level--,this.slow=0,this.holdUntil=e+Re)):t<=Sn&&r<=Rn?(this.slow=0,this.smoothSince||(this.smoothSince=e),this.level<vt.length-1&&e>=this.holdUntil&&e-this.smoothSince>=this.probeAfter&&(this.level++,this.steppedUpAt=e,this.smoothSince=0,this.holdUntil=e+Re)):(this.slow=0,this.smoothSince=0),this.level}};function xt(n){let e="auto",t=typeof matchMedia=="function"&&matchMedia("(prefers-reduced-motion: reduce)").matches,r=!1,o=new Ee(Mn()?1:2),s=new Set,i=!1,l=!1,d=0,f=[],p=0,S=0,D=k=>{if(i){if(d&&!document.hidden){let E=k-d;E<250&&f.push(E)}if(d=document.hidden?0:k,p||(p=k),k-p>=1e3){if(f.length>=10){let E=[...f].sort((H,U)=>H-U),M=f.reduce((H,U)=>H+U,0)/f.length,Z=E[Math.min(E.length-1,Math.floor(E.length*.95))],Q=$();e==="auto"&&o.window(k,M,Z),r&&k-S>=500&&(S=k,n.stats({fps:Math.round(1e3/M),frameMs:Math.round(M*10)/10,worstMs:Math.round(E[E.length-1]*10)/10})),$()!==Q&&G()}f=[],p=k}v()}},v=()=>{l||!i||(l=!0,requestAnimationFrame(k=>{l=!1,D(k)}))},h=()=>{i||typeof requestAnimationFrame!="function"||(i=!0,d=0,p=0,v())},R=()=>{!r&&e!=="auto"&&i&&(i=!1)},$=()=>e==="auto"?vt[o.level]:e,G=()=>{for(let k of s)try{k(T)}catch(E){console.error('[onceworlds] error in settings "change" listener',E)}},T={get choice(){return e},get quality(){return e==="auto"&&h(),$()},get scale(){return vn[T.quality]},get reducedMotion(){return t},pixelRatio(k=2){let E=typeof devicePixelRatio=="number"&&devicePixelRatio>0?devicePixelRatio:1;return Math.max(.5,Math.min(E,k)*T.scale)},on(k,E){return k!=="change"?()=>{}:(s.add(E),e==="auto"&&h(),()=>s.delete(E))}};return{settings:T,apply(k){let E=`${$()}|${t}`;e=k.quality,t=k.reducedMotion,r=k.showStats,r||e==="auto"&&s.size>0?h():R(),`${$()}|${t}`!==E&&G()}}}function Mn(){return typeof matchMedia=="function"&&matchMedia("(pointer: coarse)").matches}var St=(n,e)=>Object.prototype.hasOwnProperty.call(n,e);function Me(n){try{return n(),!0}catch{return!1}}function Pn(){let n=new Map,e={getItem:t=>n.has(String(t))?n.get(String(t)):null,setItem:(t,r)=>{n.set(String(t),String(r))},removeItem:t=>{n.delete(String(t))},clear:()=>n.clear(),key:t=>[...n.keys()][Number(t)]??null};return new Proxy(e,{get(t,r){if(r==="length")return n.size;if(r===Symbol.toStringTag)return"Storage";if(typeof r=="string")return St(e,r)?t[r]:n.get(r)},set(t,r,o){return typeof r=="string"&&n.set(r,String(o)),!0},has:(t,r)=>typeof r=="string"&&(St(e,r)||n.has(r)),deleteProperty(t,r){return typeof r=="string"&&n.delete(r),!0},ownKeys:()=>[...n.keys()],getOwnPropertyDescriptor:(t,r)=>typeof r=="string"&&n.has(r)?{value:n.get(r),writable:!0,enumerable:!0,configurable:!0}:void 0})}function An(n=Date.now){let e=new Map;return{read:()=>[...e].map(([t,r])=>`${t}=${r}`).join("; "),write(t){let[r,...o]=String(t).split(";"),s=r.indexOf("="),i=(s<0?"":r.slice(0,s)).trim(),l=(s<0?r:r.slice(s+1)).trim();if(!i&&!l)return;let d=!1;for(let f of o){let[p,...S]=f.split("="),D=S.join("=").trim();p.trim().toLowerCase()==="max-age"&&Number(D)<=0&&(d=!0),p.trim().toLowerCase()==="expires"&&Date.parse(D)<=n()&&(d=!0)}d?e.delete(i):e.set(i,l)}}}function J(n,e,t){try{Object.defineProperty(n,e,{configurable:!0,...t})}catch{}}function $n(){if(typeof HTMLImageElement!="function")return;let n=Object.getOwnPropertyDescriptor(HTMLImageElement.prototype,"src");if(!n?.get||!n.set)return;let{get:e,set:t}=n;J(HTMLImageElement.prototype,"src",{enumerable:n.enumerable,get(){return e.call(this)},set(r){try{this.crossOrigin===null&&new URL(String(r),document.baseURI).origin===location.origin&&(this.crossOrigin="anonymous")}catch{}t.call(this,r)}})}function Dn(){let n=window.Worker;if(typeof n!="function")return;let e=function(t,r){try{return new n(t,r)}catch(o){if(!(o instanceof DOMException&&o.name==="SecurityError")||r?.type==="module")throw o;let s;try{s=new URL(String(t),document.baseURI)}catch{throw o}if(s.origin!==location.origin)throw o;let l=`const base = ${JSON.stringify(s.href)};
1
+ "use strict";(()=>{var zn=Object.defineProperty;var Fn=(n,e,t)=>e in n?zn(n,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):n[e]=t;var c=(n,e,t)=>Fn(n,typeof e!="symbol"?e+"":e,t);var Vn=["#f6dcc5","#ebc29f","#d4a07a","#b07a55","#875839","#5e3d29","#93c9bb","#a8c595","#94bcd3","#ab9bd9","#dca3ad","#b3bccb"],vt=["#c95f56","#dc8a4f","#e2bd52","#9cc27a","#5a8a5e","#4f9a8e","#6fb7c8","#5b87c5","#465089","#8b68a8","#dc8fae","#f2eee6","#a9a8ad","#5d5c63","#2b2a30","#80604d"],Wn=["Happy","Grin","Shades","Wink","Surprised","Determined","Joyful","Shy"],Jn=["None","Sprout","Cap","Beanie","Crown","Headphones","Horns","Antenna","Bow","Halo","Party hat","Cat ears","Short hair","Tuft","Bob","Spikes","Bun","Curls","Long","Mop"];var Yn=["Plain","Band","Spots","Stripes","Star"];var Qn={skin:Vn.length,shirt:vt.length,pants:vt.length,face:Wn.length,hat:Jn.length,top:Yn.length};function St(n){if(!n||typeof n!="object")return null;let e=n,t={};for(let[r,o]of Object.entries(Qn)){let s=e[r],i=typeof s=="number"?s:typeof s=="string"&&/^[0-9]{1,3}$/.test(s)?Number(s):NaN;if(!Number.isInteger(i)||i<0||i>=o)return null;t[r]=i}return t}var S={roomMaxPlayersDefault:16,roomMaxPlayersCap:30,teamsMax:8,messageBytes:16*1024,presenceBytes:1024,stateKeyLength:64,stateValueBytes:16*1024,stateKeys:256,privateKeys:16,privateValueBytes:4*1024,privateBytesPerPlayer:8*1024,messagesPerSecond:60,messagesPerSecondMin:10,roomBytesPerSecond:128*1024,roomBytesPerSecondMin:16*1024,presenceHz:20,presenceHzMin:5,roomMessagesPerSecond:900,roomBytesPerSecondTotal:2*1024*1024,matchCountdownMs:3e3,matchCountdownMaxMs:1e4,matchIdleMs:45e3,matchAbandonMs:12e4,idleAfterMs:3e4,idleAbandonMs:5*6e4,rankedPairMatchesPerDay:5,chatLength:200,chatIntervalMs:750,chatHistory:50,chatChannelsPerPlayer:10,saveValueBytes:64*1024,saveKeysPerGame:100,saveBytesPerGame:1024*1024,guestSaveBytesPerGame:128*1024,serverDataKeys:128,serverDataBytes:512*1024,serverDataServersPerGame:5e3,serverDataBytesPerGame:64*1024*1024,serverDataIdleDays:120,gameDataKeys:32,gameDataListMax:100,gameDataItemBytes:1024,gameDataValueBytes:8*1024,gameDataMapFields:1e3,gameDataMapPerPlayer:100,gameDataNumberMax:1e15,gameDataWritesPerMinute:30,deployFiles:2e3,deployFileBytes:25*1024*1024,deployHtmlBytes:10*1024*1024,deployPathLength:200,deployTotalBytes:100*1024*1024,envVars:50,envValueBytes:4*1024,envTotalBytes:16*1024,proxyRequestBytes:1024*1024,proxyTextRequestBytes:256*1024,proxySpeechRequestBytes:16*1024,proxyResponseBytes:10*1024*1024,proxyMaxOutputTokens:4096,proxyCallsPerDay:2e3,proxyCallsPerDayMax:1e5,proxyCallsPerPlayerPerDay:100,proxyCallsPerNetworkPerDay:1e3,proxyMediaCallsPerDay:100,proxyMediaCallsPerDayMax:1e4,proxyMediaCallsPerPlayerPerDay:20,proxyMediaCallsPerNetworkPerDay:25,proxyUnitsPerDay:2e6,proxyUnitsPerDayMax:1e8,proxyUnitsPerPlayerPerDay:25e4,proxyUnitsPerGuestPerDay:1e5,proxyUnitsPerNetworkPerDay:5e5,errorReportsPerPage:10,consoleLineLength:2e3,consoleLinesPerSecond:50,gameNameLength:60,gameDescriptionLength:1e3,galleryItems:5,mediaImageBytes:5*1024*1024,mediaVideoBytes:30*1024*1024,mediaGifBytes:1024*1024,mediaGifSide:512,mediaUploadsPerDay:200,mediaBytesPerDay:500*1024*1024,badgesPerGame:50,controlHints:12,controlHintKeys:4,controlKeyLength:12,controlActionLength:40,helpLength:400,badgeNameLength:50,badgeDescriptionLength:200,leaderboardsPerGame:25,leaderboardTop:100,gamesPerOwner:50,gamesCreatedPerCreatorPerDay:3,uploadAccountAgeMs:10080*6e4,deploysPerOwnerPerDay:100,draftsPerOwnerPerDay:1e3,draftsKeptPerGame:3,cliTokensPerAccount:10,cliDeviceCodeSeconds:600,deploymentsKeptPerGame:10,deployBytesPerOwnerPerDay:2*1024*1024*1024,deployEntriesPerOwnerPerDay:1e5,bioLength:500,exportRows:2e3,exportSaveChars:4*1024*1024,exportEveryMs:60*6e4,friendsMax:200,friendRequestsMax:100,friendRequestsIncomingMax:50,friendRequestsPerDay:20,friendRequestsPerNetworkPerDay:120,friendRequestPushesPerDay:5,passwordMinLength:8,passwordMaxLength:72,signupsPerNetworkPerDay:100,signupsPerWidePerDay:300,guestsPerNetworkPerDay:300,guestsPerWidePerDay:1500,visitsPerNetworkPerDay:10,visitSeconds:10,errorsPerDeployment:100,controlButtons:4,controlLabelLength:12,partySize:6,partyChatHistory:50,messageLength:500,messagesPerPage:50,groupChatMembers:20,groupChatNameLength:40,conversationsListed:50,notificationsListed:50,invitesPerRequest:10,inviteLiveMs:30*6e4,partyInviteMs:60*6e4};var Zn="host:",z="data:";function te(n){return n.startsWith(Zn)||n.startsWith(z)}var Mt=/^(?!__proto__$)[A-Za-z0-9_.:-]{1,59}$/;function He(n){return n.startsWith(z)}function Ke(n){return z+n}function Et(n){return n.startsWith("private:")||n.startsWith("room:")}function qe(n){let e=n.length;for(let t=0;t<n.length;t++){let r=n.charCodeAt(t);r<128||(r<2048?e+=1:r>=55296&&r<=56319&&t+1<n.length&&(n.charCodeAt(t+1)&64512)===56320?(e+=2,t++):e+=2)}return e}var Ue=/^[A-Za-z][A-Za-z0-9_.-]{0,31}$/;var Xn={counter:["add"],list:["push"],record:["best"],map:["claim","release"],value:["set"]},er={add:"add(key, n)",push:"push(key, item)",best:"best(key, n)",claim:"claim(key, field)",release:"release(key, field)",set:"set(key, value)"};function tr(n){return Xn[n].map(e=>`ow.data.game.${er[e]}`).join(" or ")}function ze(n,e){let r=Math.floor(e/864e5);if(n==="daily")return{start:r*864e5,next:(r+1)*864e5};let o=r-(r+3)%7;return{start:o*864e5,next:(o+7)*864e5}}function nr(n,e){switch(n.type){case"counter":return{type:"counter",value:n.min,...n.reset?{resetsAt:ze(n.reset,e).next}:{}};case"list":return{type:"list",items:[]};case"record":return{type:"record",value:null,by:null,at:null};case"map":return{type:"map",fields:{}};case"value":return{type:"value",value:null,at:null}}}function rr(n,e,t){if(!e||e.type!==n.type)return nr(n,t);if(e.type==="counter"&&n.type==="counter"){if(!n.reset)return{type:"counter",value:e.value};let s=ze(n.reset,t);return{type:"counter",value:(e.period??0)>=s.start?e.value:n.min,resetsAt:s.next}}let{period:r,...o}=e;return o}function Rt(n,e,t,r,o){if(r.guest&&!n.guests)return{code:"sign_in",message:`Log in to change '${t.key}': guests can't (a ${n.type} is for signed-in players unless onceworlds.json says "guests": true).`};let s={id:r.id,name:r.name},i=rr(n,e,o);switch(i.type){case"counter":{if(t.op!=="add"||n.type!=="counter")break;let a=Math.min(n.max,Math.max(n.min,i.value+t.n)),u=n.reset?ze(n.reset,o):null;return{next:{type:"counter",value:a,...u?{resetsAt:u.next,period:u.start}:{}},result:{type:"counter",value:a}}}case"list":{if(t.op!=="push"||n.type!=="list")break;return{next:{type:"list",items:[{value:t.item,by:s,at:o},...i.items].slice(0,n.max)},result:{type:"list",ok:!0}}}case"record":{if(t.op!=="best"||n.type!=="record")break;return i.value!==null&&i.by&&i.at!==null&&!(n.order==="max"?t.n>i.value:t.n<i.value)?{next:i,result:{type:"record",value:i.value,by:i.by,at:i.at,record:!1}}:{next:{type:"record",value:t.n,by:s,at:o},result:{type:"record",value:t.n,by:s,at:o,record:!0}}}case"map":{if(t.op!=="claim"&&t.op!=="release"||n.type!=="map")break;let a={...i.fields},u=Object.hasOwn(a,t.field)?a[t.field]:void 0;return t.op==="release"?!u||u.by.id!==r.id?{next:i,result:{type:"map",ok:!1,...u?{holder:u.by}:{}}}:(delete a[t.field],{next:{type:"map",fields:a},result:{type:"map",ok:!0}}):u?{next:i,result:{type:"map",ok:u.by.id===r.id,holder:u.by}}:Object.values(a).filter(d=>d.by.id===r.id).length>=n.perPlayer?{code:"limit",message:`claim('${t.key}'): a player holds at most ${n.perPlayer} (onceworlds.json's "perPlayer"). Release one first.`}:Object.keys(a).length>=n.fields?{code:"full",message:`claim('${t.key}'): all ${n.fields} fields are taken (onceworlds.json's "fields").`}:(a[t.field]={by:s,at:o},{next:{type:"map",fields:a},result:{type:"map",ok:!0}})}case"value":{if(t.op!=="set"||n.type!=="value")break;return r.host?{next:{type:"value",value:t.value,at:o},result:{type:"value",ok:!0}}:{code:"not_host",message:`set('${t.key}'): only the host of one of the game's rooms sets a value. Join a room, and set it from the host's page (room.isHost).`}}}return{code:"wrong_op",message:`'${t.key}' is a ${n.type}: use ${tr(n.type)}.`}}var xt=n=>n.replace(/[\u0000-\u001f\u007f]/g," ").replace(/\s+/g," ").trim();var or=/^[a-z0-9][a-z0-9-]{0,19}$/;function Pt(n){if(!n||typeof n!="object")return null;let e=n,t=[];for(let o of Array.isArray(e.buttons)?e.buttons:[]){if(t.length>=S.controlButtons)break;let{id:s,label:i}=o??{};if(typeof s!="string"||!or.test(s)||t.some(u=>u.id===s))continue;let a=typeof i=="string"?i.replace(/[\u0000-\u001f\u007f]/g,"").replace(/\s+/g," ").trim().slice(0,S.controlLabelLength).trim():"";t.push({id:s,label:a||s})}let r=e.stick===!0;return r||t.length>0?{stick:r,zone:e.zone==="corner"?"corner":"wide",buttons:t}:null}var ne="host:ow.settings",sr=/^[a-z][a-zA-Z0-9]{0,15}$/;function Fe(n){if(!Array.isArray(n))return[];let e=[];for(let t of n){if(e.length>=6)break;let{id:r,label:o,options:s,default:i}=t??{};if(typeof r!="string"||!sr.test(r)||e.some(d=>d.id===r)||!Array.isArray(s))continue;let a=[];for(let d of s){let f=typeof d=="object"&&d!==null?d.value:d;if(typeof f!="string"&&typeof f!="number"||typeof f=="number"&&!Number.isFinite(f)||a.length>=8||a.some(m=>m.value===f))continue;let h=typeof d=="object"&&d!==null&&typeof d.label=="string"?d.label:String(f);a.push({value:f,label:xt(h).slice(0,20)||String(f)})}if(a.length<2)continue;let u=typeof o=="string"?xt(o).slice(0,24):"";e.push({id:r,label:u||r,options:a,default:a.some(d=>d.value===i)?i:a[0].value})}return e}function At(n,e){let t=e!==null&&typeof e=="object"?e[n.id]:void 0;return n.options.some(r=>r.value===t)?t:n.default}var Dt="onceworlds:hello",Ct="onceworlds:connect",$t=/^[a-z0-9]{1,32}~(?:(?:0|[1-9]\d{0,3})\.(?:0|[1-9]\d{0,4})\.(?:0|[1-9]\d{0,5}))?~[0-9a-z]{1,11}~[lp]~[A-Za-z0-9_-]{43}$/;var It=["log","info","warn","error"],Tt="onceworlds-console";var Ot=/^[A-Za-z0-9-]{1,64}$/;function Lt(){let n=1,e=!1,t=()=>e?0:n,r=new Map;if(typeof AudioNode<"u"&&typeof AudioDestinationNode<"u"){let d=AudioNode.prototype.connect,f=AudioNode.prototype.disconnect,h=w=>typeof OfflineAudioContext>"u"||!(w instanceof OfflineAudioContext),m=w=>{let y=r.get(w);return y||(y=w.createGain(),y.gain.value=t(),d.call(y,w.destination),r.set(w,y)),y};AudioNode.prototype.connect=function(w,...y){return w instanceof AudioDestinationNode&&h(w.context)&&r.get(w.context)!==this?(d.call(this,m(w.context),...y),w):d.call(this,w,...y)},AudioNode.prototype.disconnect=function(...w){let y=w[0];if(y instanceof AudioDestinationNode){let k=r.get(y.context);k&&k!==this&&(w[0]=k)}return f.apply(this,w)}}let o=new WeakMap,s=new Set,i=typeof HTMLMediaElement<"u"?Object.getOwnPropertyDescriptor(HTMLMediaElement.prototype,"volume"):void 0,a=d=>i?.set?.call(d,Ve((o.get(d)??1)*t())),u=d=>{o.has(d)||!i?.get||(o.set(d,i.get.call(d)),s.add(new WeakRef(d)))};if(i?.get&&i.set){Object.defineProperty(HTMLMediaElement.prototype,"volume",{configurable:!0,enumerable:i.enumerable,get(){return o.has(this)?o.get(this):i.get.call(this)},set(f){u(this),o.set(this,Ve(Number(f))),a(this)}});let d=HTMLMediaElement.prototype.play;HTMLMediaElement.prototype.play=function(){return u(this),a(this),d.call(this)}}return{get volume(){return n},get muted(){return e},apply(d){n=Ve(d.volume),e=d.muted;for(let[f,h]of r)h.gain.setTargetAtTime(t(),f.currentTime,.02);for(let f of s){let h=f.deref();h?a(h):s.delete(f)}}}}function Ve(n){return Number.isFinite(n)?Math.min(1,Math.max(0,n)):1}function _t(n){try{let e=n?.getAttribute("data-build");return e&&$t.test(e)?e:null}catch{return null}}var _={ms:9e3,warmupMs:1e3,flowSettleMs:1500,playSettleMs:2e3,motionGraceMs:5e3,ceilingMs:25e3,graceMs:12e3,maxBytes:6*1024*1024,posterBytes:1024*1024,long:1280,short:720,fps:30,bitsPerSecond:25e5};var ar=["video/webm;codecs=vp9","video/webm;codecs=vp8","video/webm","video/mp4;codecs=avc1","video/mp4"],lr=3e3,Bt=250,ur="host:ow.flow";function Nt(n){let e=n?.[ur],t=e&&typeof e=="object"?e.phase:void 0;return typeof t=="string"?t:void 0}var We=250,ye=32,be=18,cr=.02,Je={needed:6,of:8};function dr(){return typeof window>"u"||typeof document>"u"?null:{document,MediaRecorder:globalThis.MediaRecorder,requestAnimationFrame:n=>window.requestAnimationFrame(n),setTimeout:(n,e)=>window.setTimeout(n,e),clearTimeout:n=>window.clearTimeout(n)}}var Q=(n,e,t,r)=>typeof n=="number"&&Number.isFinite(n)?Math.min(t,Math.max(e,Math.round(n))):r;function pr(n){if(!n||typeof n!="object")return null;let e=n;return e.t==="stop"?{t:"stop"}:e.t!=="start"?null:{t:"start",ms:Q(e.ms,1e3,15e3,_.ms),long:Q(e.long,160,1920,_.long),short:Q(e.short,90,1080,_.short),fps:Q(e.fps,5,60,_.fps),bitsPerSecond:Q(e.bitsPerSecond,25e4,8e6,_.bitsPerSecond),maxBytes:Q(e.maxBytes,64*1024,_.maxBytes,_.maxBytes)}}function we(n){let e=null,t=0;for(let r of Array.from(n))try{if(r.isConnected===!1||r.width<64||r.height<64)continue;let o=typeof r.getBoundingClientRect=="function"?r.getBoundingClientRect():null;if(o&&(o.width<32||o.height<32))continue;let s=o?o.width*o.height:r.width*r.height;s>t&&(e=r,t=s)}catch{}return e}function fr(n,e,t,r){let o=n>=e,s=Math.min(1,(o?t:r)/n,(o?r:t)/e);if(s>=1)return{width:n,height:e,scale:1};let i=a=>Math.max(2,Math.floor(a*s/2)*2);return{width:i(n),height:i(e),scale:s}}function mr(n,e){return new Promise(t=>{e.requestAnimationFrame(()=>{try{let r=n.width,o=n.height,s=Math.min(_.long,Math.max(480,r)),i=Math.round(s*9/16),a=e.document.createElement("canvas");a.width=s,a.height=i;let u=a.getContext("2d");if(!u)return t(null);u.fillStyle="#000",u.fillRect(0,0,s,i);let d=r/o,f=d>=1.25&&d<=2.4?Math.max(s/r,i/o):Math.min(s/r,i/o);u.drawImage(n,(s-r*f)/2,(i-o*f)/2,r*f,o*f),a.toBlob(h=>h?h.arrayBuffer().then(t,()=>t(null)):t(null),"image/jpeg",.85)}catch{t(null)}})})}function hr(n,e){let t=null,r=null;return o=>{e.requestAnimationFrame(()=>{try{if(!t){let u=e.document.createElement("canvas");u.width=ye,u.height=be,t=u.getContext("2d",{willReadFrequently:!0})}if(!t)return o(null);t.drawImage(n,0,0,ye,be);let s=t.getImageData(0,0,ye,be).data,i=r;if(r=new Uint8ClampedArray(s),!i)return o(null);let a=0;for(let u=0;u+2<s.length;u+=4){let d=s[u]*2+s[u+1]*5+s[u+2],f=i[u]*2+i[u+1]*5+i[u+2];Math.abs(d-f)>128&&a++}o(a/(ye*be))}catch{o(null)}})}}function gr(n,e,t,r){return new Promise(o=>{let s=hr(n,e),i=[],a=0,u=0,d=!1,f=()=>{if(r()||a>=_.ceilingMs)return o(!1);let h=null;try{h=t()}catch{}h&&h.phase!=="lobby"&&(d=!0);let m=h?.flow;if(h?.phase==="playing"&&h.paused!==!0&&(m===void 0||m==="playing")){if(u+=We,u>(m===void 0?_.playSettleMs:_.flowSettleMs))return o(!0)}else u=0;if(!d){if(a>=_.motionGraceMs&&i.length>=Je.of&&i.filter(Boolean).length>=Je.needed)return o(!0);s(w=>{i.push(w!==null&&w>=cr),i.length>Je.of&&i.shift()})}a+=We,e.setTimeout(f,We)};f()})}function jt(n,e){let t=e.MediaRecorder;return typeof n.captureStream!="function"||typeof t!="function"?null:ar.find(r=>{try{return t.isTypeSupported(r)}catch{return!1}})??null}function Gt(n,e=dr(),t=()=>null){let r=null,o=a=>{try{n(a)}catch{}},s=a=>o({t:"none",reason:a});function i(a){if(r)return;if(!e)return s("unsupported");let u=e,d=!1,f=null;r={cancel(){d=!0,f!==null&&u.clearTimeout(f)}};let h=y=>{r=null,!d&&y&&o(y)},m=0,w=()=>{if(d)return h(null);let y=we(u.document.querySelectorAll("canvas"));if(y){if(f=null,!jt(y,u))return h({t:"none",reason:"unsupported"});gr(y,u,t,()=>d).then(k=>{if(d)return null;if(!k)return{t:"none",reason:"not-playing"};let P=we(u.document.querySelectorAll("canvas"))??y;return yr(P,a,u,()=>d,()=>!d&&o({t:"started"}))}).then(h,()=>h({t:"none",reason:"failed"}))}else++m>lr/Bt?h({t:"none",reason:"no-canvas"}):f=u.setTimeout(w,Bt)};w()}return{receive(a){try{let u=pr(a);if(!u)return;if(u.t==="stop"){r?.cancel(),r=null;return}i(u)}catch{r=null,s("failed")}}}}function yr(n,e,t,r,o){let s=t.MediaRecorder,i=jt(n,t);if(!s||!i)return Promise.resolve({t:"none",reason:"unsupported"});let a=fr(n.width,n.height,e.long,e.short),u=!1,d=n;if(a.scale<1){let m=t.document.createElement("canvas");m.width=a.width,m.height=a.height;let w=m.getContext("2d");if(!w)return Promise.resolve({t:"none",reason:"unsupported"});u=!0;let y=()=>{if(u){try{w.drawImage(n,0,0,a.width,a.height)}catch{}t.requestAnimationFrame(y)}};y(),d=m}let f,h;try{f=d.captureStream(e.fps),h=new s(f,{mimeType:i,videoBitsPerSecond:e.bitsPerSecond})}catch{return u=!1,Promise.resolve({t:"none",reason:"failed"})}return new Promise(m=>{let w=[],y=0,k=Promise.resolve(null),P=t.setTimeout(()=>{k=mr(n,t)},Math.round(e.ms/2)),O=null,B=()=>{try{h.state!=="inactive"&&h.stop()}catch{}},R=()=>{u=!1,t.clearTimeout(P),O!==null&&t.clearTimeout(O);try{for(let I of f.getTracks())I.stop()}catch{}};h.ondataavailable=I=>{!I.data||I.data.size===0||(w.push(I.data),y+=I.data.size,y>e.maxBytes*.85&&B())},h.onerror=()=>{R(),m(r()?null:{t:"none",reason:"failed"})},h.onstop=()=>{if(R(),r())return m(null);let I=new Blob(w,{type:h.mimeType||i});Promise.all([I.arrayBuffer(),k.catch(()=>null)]).then(([W,K])=>{if(W.byteLength===0)return m({t:"none",reason:"failed"});if(W.byteLength>e.maxBytes)return m({t:"none",reason:"too-large"});m({t:"done",type:I.type||i,video:W,poster:K,width:a.width,height:a.height})}).catch(()=>m({t:"none",reason:"failed"}))};try{h.start(1e3)}catch{return R(),m({t:"none",reason:"failed"})}o(),O=t.setTimeout(()=>{O=null,B()},e.ms);let A=()=>{if(h.state!=="inactive"){if(r())return B();t.setTimeout(A,200)}};t.setTimeout(A,200)})}var br=200,Ht=2,Z=20,Kt=200;function qt(n){try{return new URLSearchParams(n).get(Tt)==="1"}catch{return!1}}function Ut(n){return typeof n=="object"&&n!==null&&n.solo===!0?"standalone":"platform"}function zt(n){return typeof n=="object"&&n!==null&&n.demo===!0}function Ft(n){try{let e=new URLSearchParams(n).get("demo");return e!==null&&e!=="0"&&e!=="false"}catch{return!1}}function Vt(n,e,t=Date.now,r=setTimeout){let o=null,s=[],i=-1/0,a=0,u=0,d=!1,f=!1,h=y=>{o?o(y):s.length<br&&s.push(y)},m=()=>{let y=t();return y-i>=1e3&&(i=y,a=0),a<S.consoleLinesPerSecond?(a++,!0):(u++,d||(d=!0,r(()=>{d=!1;let k=u;u=0,k>0&&m()&&h({level:"warn",text:`${k} more ${k===1?"line":"lines"} left out`,at:t()})},Math.max(0,1e3-(y-i)))),!1)},w=(y,k,P)=>{if(!m())return;let O=Wt(e?k.split(`${e}/`).join(""):k);h({level:y,text:O,at:t(),...P?{source:P.source.slice(0,300),line:P.line,column:P.column}:{}})};for(let y of It){let k=n[y];typeof k=="function"&&(n[y]=function(...P){if(k.apply(n,P),!f){f=!0;try{w(y,wr(P))}catch{}finally{f=!1}}})}return{error(y,k){if(!f){f=!0;try{w("error",y,k)}catch{}finally{f=!1}}},connect(y){o=y;for(let k of s.splice(0))y(k)}}}function wr(n){let e="",t=n;if(typeof n[0]=="string"){let r=1;e=n[0].replace(/%[sdifoOc%]/g,o=>{if(o==="%%")return"%";if(r>=n.length)return o;let s=n[r++];return o==="%c"?"":o==="%d"||o==="%i"?String(typeof s=="number"?Math.trunc(s):parseInt(re(s),10)):o==="%f"?String(typeof s=="number"?s:parseFloat(re(s))):o==="%s"?re(s):X(s)}),t=n.slice(r)}for(let r of t)e+=e?` ${re(r)}`:re(r);return Wt(e)}function re(n){return typeof n=="string"?n:X(n)}function X(n,e=0){try{switch(typeof n){case"string":return JSON.stringify(n.length>Kt?`${n.slice(0,Kt)}\u2026`:n);case"bigint":return`${n}n`;case"symbol":return n.toString();case"function":return`\u0192 ${n.name||"anonymous"}()`;case"object":break;default:return String(n)}if(n===null)return"null";if(n instanceof Error)return ke(n);if(n instanceof Date)return Number.isNaN(n.getTime())?"Invalid Date":n.toISOString();if(n instanceof RegExp)return String(n);if(n instanceof Map||n instanceof Set)return`${n.constructor.name}(${n.size})`;if(ArrayBuffer.isView(n))return`${n.constructor.name}(${"length"in n?n.length:n.byteLength})`;if(typeof Element<"u"&&n instanceof Element)return`<${n.tagName.toLowerCase()}>`;if(Array.isArray(n))return e>=Ht?`Array(${n.length})`:`[${n.slice(0,Z).map(i=>X(i,e+1)).join(", ")}${n.length>Z?`, \u2026${n.length-Z} more`:""}]`;let t=typeof n.constructor=="function"&&n.constructor!==Object?`${n.constructor.name} `:"";if(e>=Ht)return`${t}{\u2026}`;let r=Object.keys(n),o=r.slice(0,Z).map(s=>`${/^[A-Za-z_$][\w$]*$/.test(s)?s:JSON.stringify(s)}: ${X(n[s],e+1)}`);return`${t}{${o.join(", ")}${r.length>Z?`, \u2026${r.length-Z} more`:""}}`}catch{return Object.prototype.toString.call(n)}}function ke(n){try{let e=`${n.name||"Error"}: ${n.message}`,t=typeof n.stack=="string"?n.stack:"";return t?t.startsWith(e)?t:`${e}
2
+ ${t}`:e}catch{return"Error"}}function Wt(n){return n.length>S.consoleLineLength?`${n.slice(0,S.consoleLineLength-1)}\u2026`:n}var kr={wasd:{up:"w",down:"s",left:"a",right:"d"},arrows:{up:"ArrowUp",down:"ArrowDown",left:"ArrowLeft",right:"ArrowRight"}},vr=.45,Sr=.3,Ye={" ":["Space",32],Enter:["Enter",13],Shift:["ShiftLeft",16],Control:["ControlLeft",17],Alt:["AltLeft",18],Escape:["Escape",27],Tab:["Tab",9],Backspace:["Backspace",8],ArrowLeft:["ArrowLeft",37],ArrowUp:["ArrowUp",38],ArrowRight:["ArrowRight",39],ArrowDown:["ArrowDown",40]},ve=class{constructor(e,t){c(this,"touch");c(this,"stick",{x:0,y:0});c(this,"held",new Set);c(this,"downs",new Map);c(this,"stickMode");c(this,"buttonKeys",new Map);c(this,"down",new Map);c(this,"show");c(this,"reportTouch");this.show=e,this.reportTouch=t,this.touch=typeof matchMedia=="function"&&matchMedia("(pointer: coarse)").matches,window.addEventListener("pointerdown",r=>r.isTrusted&&this.setTouch(r.pointerType!=="mouse"),!0),window.addEventListener("keydown",r=>r.isTrusted&&this.setTouch(!1),!0),window.addEventListener("blur",()=>this.release()),document.addEventListener("visibilitychange",()=>document.hidden&&this.release())}set(e){let t=e??{};this.stickMode=t.stick==="wasd"||t.stick==="arrows"||t.stick==="analog"?t.stick:void 0;let r=Array.isArray(t.buttons)?t.buttons:[],o=e?Pt({stick:this.stickMode!==void 0,zone:t.zone,buttons:r}):null;this.buttonKeys=new Map;for(let s of o?.buttons??[]){let i=r.find(a=>a?.id===s.id)?.key;typeof i=="string"&&i&&this.buttonKeys.set(s.id,i)}this.show(o),o?this.update():this.release()}receive(e){let t=o=>typeof o=="number"&&Number.isFinite(o)?Math.max(-1,Math.min(1,o)):0;this.stick.x=t(e?.x),this.stick.y=t(e?.y);let r=new Set(Array.isArray(e?.buttons)?e.buttons.filter(o=>typeof o=="string"):[]);for(let o of r)this.held.has(o)||this.downs.set(o,(this.downs.get(o)??0)+1);this.held=r,this.update()}pressed(e){return this.held.has(e)}presses(e){return this.downs.get(e)??0}update(){let e=new Map;if(this.stickMode==="wasd"||this.stickMode==="arrows"){let t=kr[this.stickMode],r=(o,s)=>{s>(this.down.has(o)?Sr:vr)&&e.set(o,Jt(o))};r(t.up,-this.stick.y),r(t.down,this.stick.y),r(t.left,-this.stick.x),r(t.right,this.stick.x)}for(let t of this.held){let r=this.buttonKeys.get(t);r&&e.set(r,Jt(r))}for(let[t,r]of this.down)e.has(t)||(this.down.delete(t),Yt(r,!1));for(let[t,r]of e)this.down.has(t)||(this.down.set(t,r),Yt(r,!0))}release(){this.stick.x=0,this.stick.y=0,this.held.clear(),this.update()}setTouch(e){e!==this.touch&&(this.touch=e,e||this.release(),this.reportTouch(e))}};function Jt(n){let e=n==="Space"?" ":n;return Object.prototype.hasOwnProperty.call(Ye,e)?{key:e,code:Ye[e][0],keyCode:Ye[e][1]}:/^[a-z]$/i.test(e)?{key:e.toLowerCase(),code:`Key${e.toUpperCase()}`,keyCode:e.toUpperCase().charCodeAt(0)}:/^[0-9]$/.test(e)?{key:e,code:`Digit${e}`,keyCode:48+Number(e)}:{key:e,code:"",keyCode:0}}function Yt(n,e){try{let t={key:n.key,code:n.code,keyCode:n.keyCode,which:n.keyCode,bubbles:!0,cancelable:!0},r=new KeyboardEvent(e?"keydown":"keyup",t);r.keyCode!==n.keyCode&&(Object.defineProperty(r,"keyCode",{get:()=>n.keyCode}),Object.defineProperty(r,"which",{get:()=>n.keyCode})),(document.activeElement??document.body??document).dispatchEvent(r)}catch{}}function xr(n){switch(n.type){case"counter":return n.value;case"list":return n.items;case"record":return n.value===null?null:{value:n.value,by:n.by,at:n.at};case"map":return n.fields;case"value":return n.value}}function Qt(n=e=>console.warn(`[onceworlds] ${e}`)){let e=new Map;return t=>{let r=Date.now();r-(e.get(t)??-1/0)<5e3||(e.size>200&&e.clear(),e.set(t,r),n(t))}}function Zt(n,e){let t=new Set,r=async(o,s)=>{let i=`onceworlds.data.server.${s===null?"delete":"set"}('${String(o).slice(0,40)}')`,a=n();if(typeof o!="string"||!Mt.test(o))return e(`${i} did nothing: a key is 1-59 letters, digits or _ . : -`),!1;if(!a||a.closed)return e(`${i} did nothing: you're not in a room. Join one first (await onceworlds.rooms.join({ private: true })): server data belongs to a server.`),!1;if(!a.connected)return e(`${i} did nothing: the connection is down and the platform is reconnecting. Write it again after room.on('reconnect').`),!1;if(!a.isHost)return e(`${i} did nothing: only the room's host writes server data. Check onceworlds.data.server.canWrite, or send the change to the host (room.send) and let it write.`),!1;let u;try{u=JSON.stringify(s??null)}catch{u=void 0}return u===void 0?(e(`${i} did nothing: the value must be plain JSON data (numbers, text, lists, objects).`),!1):qe(u)>S.stateValueBytes-128?(e(`${i} did nothing: the value is ${Math.ceil(qe(u)/1024)} KB, and a key holds 16 KB. Split it into keys by area or chunk (a server keeps ${S.serverDataKeys} keys, ${S.serverDataBytes/1024} KB), or let the engine's Persist() save the world for you.`),!1):await a._writeAcked(Ke(o),s??null)};return{get(o){let s=n();if(!s||typeof o!="string")return null;let i=s.state[Ke(o)];return i===void 0?null:i},all(){let o=n(),s={};if(!o)return s;for(let[i,a]of Object.entries(o.state))i.startsWith("data:")&&(s[i.slice(5)]=a);return s},set:(o,s)=>r(o,s??null),delete:o=>r(o,null),get kept(){return n()?.kept??!1},get canWrite(){let o=n();return!!(o&&!o.closed&&o.isHost)},async reset(){let o=n();return o?o.owner!==o.me.id&&o.kind!=="solo"?(e("onceworlds.data.server.reset() did nothing: only a private server's owner starts its world over (room.owner)."),!1):o._resetData():(e("onceworlds.data.server.reset() did nothing: you're not in a room."),!1)},on(o,s){return o!=="change"||typeof s!="function"?()=>{}:(t.add(s),()=>t.delete(s))},_changed(o,s,i){for(let a of t)try{a(o,s??null,i)}catch(u){console.error('[onceworlds] error in data.server "change" listener',u)}}}}function Xt(n,e){let t=async(o,s,i,a)=>{if(typeof o.key!="string"||!Ue.test(o.key))return e(`${s} did nothing: '${String(o.key).slice(0,40)}' isn't a game data key (1-32 letters, digits, _ . or -, declared in onceworlds.json's "data").`),a;try{return i(await(await n()).op(o))}catch(u){return e(`${s} did nothing: ${u instanceof Error?u.message:String(u)}`),a}},r=(o,s)=>`onceworlds.data.game.${o}('${String(s).slice(0,40)}')`;return{async get(o){if(typeof o!="string"||!Ue.test(o))return e(`${r("get",o)}: '${String(o).slice(0,40)}' isn't a game data key (1-32 letters, digits, _ . or -).`),null;try{return xr(await(await n()).read(o))}catch(s){return e(`${r("get",o)} read nothing: ${s instanceof Error?s.message:String(s)}`),null}},add:(o,s)=>t({key:o,op:"add",n:Number(s)},r("add",o),i=>i.type==="counter"?i.value:null,null),push:(o,s)=>t({key:o,op:"push",item:s},r("push",o),i=>i.type==="list",!1),best:(o,s)=>t({key:o,op:"best",n:Number(s)},r("best",o),i=>i.type==="record"?{value:i.value,by:i.by,at:i.at,record:i.record}:null,null),claim:(o,s)=>t({key:o,op:"claim",field:String(s)},r("claim",o),i=>i.type==="map"&&i.ok,!1),release:(o,s)=>t({key:o,op:"release",field:String(s)},r("release",o),i=>i.type==="map"&&i.ok,!1),set:(o,s)=>t({key:o,op:"set",value:s},r("set",o),i=>i.type==="value",!1)}}function en(n,e){let t=S.gameDataNumberMax,r=s=>{switch(s.op){case"add":return{type:"counter",min:0,max:t,add:[-t,t],guests:!0};case"push":return{type:"list",max:S.gameDataListMax,bytes:S.gameDataItemBytes,guests:!0};case"best":return{type:"record",order:"max",min:-t,max:t,guests:!0};case"claim":case"release":return{type:"map",fields:S.gameDataMapFields,perPlayer:S.gameDataMapPerPlayer,guests:!0};case"set":return{type:"value",bytes:S.gameDataValueBytes,guests:!0}}},o=s=>{try{let i=e.get(`onceworlds:game:${s}`);return i?JSON.parse(i):null}catch{return null}};return{async read(s){let i=o(s);if(!i)throw new Error(`nothing is stored under '${s}' on this page yet (on its own, game data lives in this browser).`);return i},async op(s){let i=await n(),a=o(s.key),u=r(s);if(a&&a.type!==u.type)throw new Error(`'${s.key}' holds a ${a.type} on this page: it was first used that way.`);let d=Rt(u,a,JSON.parse(JSON.stringify(s??null)),{id:i.id,name:i.name,host:!0},Date.now());if("code"in d)throw new Error(d.message);return e.set(`onceworlds:game:${s.key}`,JSON.stringify(d.next)),d.result}}}function tn(n){return{messagesPerSecond:n.messagesPerSecond*.85,messageBurst:n.messagesPerSecond*2*.85,bytesPerSecond:n.bytesPerSecond*.85,byteBurst:n.bytesPerSecond*4*.85}}var Mr=60,Er=100,Rr=5e3,Se=class{constructor(e={}){c(this,"queue",[]);c(this,"rates",tn({messagesPerSecond:S.messagesPerSecond,bytesPerSecond:S.roomBytesPerSecond}));c(this,"messages",this.rates.messageBurst);c(this,"bytes",this.rates.byteBurst);c(this,"budget",{messagesPerSecond:S.messagesPerSecond,bytesPerSecond:S.roomBytesPerSecond});c(this,"refilledAt");c(this,"timer",null);c(this,"warnedAt",-1/0);c(this,"dropped",0);c(this,"now");c(this,"setTimer");c(this,"clearTimer");c(this,"warn");this.now=e.now??Date.now,this.setTimer=e.setTimer??((t,r)=>setTimeout(t,r)),this.clearTimer=e.clearTimer??(t=>clearTimeout(t)),this.warn=e.warn??(t=>console.warn(`[onceworlds] ${t}`)),this.refilledAt=this.now(),e.budget&&this.setBudget(e.budget)}setBudget(e){this.refill(),this.budget={messagesPerSecond:e.messagesPerSecond,bytesPerSecond:e.bytesPerSecond},this.rates=tn(this.budget),this.messages=Math.min(this.messages,this.rates.messageBurst),this.bytes=Math.min(this.bytes,this.rates.byteBurst),this.drain(!1)}get waiting(){return this.queue.length}event(e,t){this.queue.push({kind:"event",size:e,send:t}),this.settle()}urgent(e,t){this.queue.push({kind:"event",size:e,send:t}),this.drain(!0)}state(e,t,r){for(let o=this.queue.length-1;o>=0;o--){let s=this.queue[o];if(s.kind!=="state")break;if(s.key===e)return s.size=t,s.send=r,this.settle()}this.queue.push({kind:"state",key:e,size:t,send:r}),this.settle()}spend(e){this.refill(),this.bytes-=e}clear(){this.queue=[],this.timer!==null&&this.clearTimer(this.timer),this.timer=null}settle(){this.queue.length>this.waitingLimit(Mr,12)&&(this.squeeze(),this.tell(`${this.queue.length} messages are waiting: a room takes about ${this.budget.messagesPerSecond} messages and ${Math.round(this.budget.bytesPerSecond/1024)} KB a second from each player. State is sent at its newest value and other messages in order. Send less: batch events, write state at 10-20 Hz, and only what changed.`)),this.drain(!1)}waitingLimit(e,t){return Math.max(t,Math.round(e*this.rates.messagesPerSecond/(S.messagesPerSecond*.85)))}refill(){let e=this.now(),t=Math.max(0,(e-this.refilledAt)/1e3);this.refilledAt=e,this.messages=Math.min(this.rates.messageBurst,this.messages+t*this.rates.messagesPerSecond),this.bytes=Math.min(this.rates.byteBurst,this.bytes+t*this.rates.bytesPerSecond)}drain(e){for(this.timer!==null&&(this.clearTimer(this.timer),this.timer=null),this.refill();this.queue.length>0;){let i=this.queue[0],a=Math.min(i.size(),this.rates.byteBurst);if(!e&&(this.messages<1||this.bytes<a))break;this.queue.shift(),this.messages-=1,this.bytes-=a;try{i.send()}catch(u){console.error("[onceworlds] a message could not be sent",u)}}if(this.queue.length===0)return;let t=Math.min(this.queue[0].size(),this.rates.byteBurst),r=Math.max(0,1-this.messages)/this.rates.messagesPerSecond,o=Math.max(0,t-this.bytes)/this.rates.bytesPerSecond,s=Math.min(250,Math.max(8,Math.ceil(Math.max(r,o)*1e3)));this.timer=this.setTimer(()=>{this.timer=null,this.drain(!1)},s)}squeeze(){let e=new Set;for(let o=this.queue.length-1;o>=0;o--){let s=this.queue[o];s.kind==="state"&&(e.has(s.key)?this.queue.splice(o,1):e.add(s.key))}let t=this.queue.filter(o=>o.kind==="event").length,r=this.waitingLimit(Er,20);for(let o=0;t>r&&o<this.queue.length;)this.queue[o].kind==="event"?(this.queue.splice(o,1),t--,this.dropped++):o++;this.dropped>0&&this.tell(`${this.dropped} messages were dropped so the rest arrive fresh: the game sends much more than a room takes (${this.budget.messagesPerSecond} messages, ${Math.round(this.budget.bytesPerSecond/1024)} KB a second per player). Send less.`)}tell(e){let t=this.now();t-this.warnedAt<Rr||(this.warnedAt=t,this.warn(e))}};function F(n){try{let e=JSON.stringify(n)??"null",t=0;for(let r=0;r<e.length;r++)e.charCodeAt(r)>127&&(t+=2);return e.length+t+32}catch{return 1024}}var Qe=Math.PI*2;function Ze(n,e,t,r={},o=""){if(typeof n=="number"&&typeof e=="number"){if(r.angles?.includes(o)){let s=((e-n)%Qe+Qe+Math.PI)%Qe-Math.PI;return n+s*t}return n+(e-n)*t}if(Array.isArray(n)&&Array.isArray(e)&&n.length===e.length)return e.map((s,i)=>Ze(n[i],s,t,r,o));if(n&&e&&typeof n=="object"&&typeof e=="object"&&!Array.isArray(n)&&!Array.isArray(e)){let s={};for(let i of Object.keys(e))s[i]=i in n?Ze(n[i],e[i],t,r,i):e[i];return s}return t<.5?n:e}function Pr(n,e,t){if(t===void 0||!n||!e||typeof n!="object"||typeof e!="object")return!1;for(let[r,o]of Object.entries(e)){let s=n[r];if(typeof o=="number"&&typeof s=="number"&&Math.abs(o-s)>t)return!0}return!1}function nn(n,e,t={}){if(n.length===0)return;let r=n[0],o=n[n.length-1];if(e<=r.at)return r.d;if(e>=o.at)return o.d;let s=n.length-2;for(;s>0&&n[s].at>e;)s--;let i=n[s],a=n[s+1];return Pr(i.d,a.d,t.snap)?a.d:Ze(i.d,a.d,(e-i.at)/Math.max(1,a.at-i.at),t)}var rn=8,on=2e3;var Ar=3e3,Dr=15e3,Cr=5e3;function sn(n){let e={};for(let t of Object.keys(n))te(t)&&(e[t]=n[t]);return e}var N=()=>48,oe=class{constructor(e,t,r=Date.now,o=[]){c(this,"id");c(this,"kind");c(this,"invite");c(this,"teams");c(this,"open");c(this,"ranked");c(this,"kept");c(this,"me");c(this,"owner");c(this,"players",new Map);c(this,"state",{});c(this,"host");c(this,"closed",!1);c(this,"connected",!0);c(this,"match");c(this,"listeners",new Map);c(this,"transport");c(this,"outbox",new Se);c(this,"samples",new Map);c(this,"presenceTimer",null);c(this,"pendingPresence",null);c(this,"writes",0);c(this,"written",new Map);c(this,"confirmed",{});c(this,"shares",{messagesPerSecond:S.messagesPerSecond,presenceHz:S.presenceHz,bytesPerSecond:S.roomBytesPerSecond});c(this,"clock");c(this,"schema");c(this,"frozenSettings",null);c(this,"secrets",new Map);c(this,"offlineReady");c(this,"complained",new Map);c(this,"acks",new Map);this.transport=t,this.clock=r,this.schema=o,this.match=e.match??{phase:"lobby",n:0,min:1},this.applyBudget(e.budget),this.id=e.room,this.kind=e.room==="solo"?"solo":e.room.startsWith("private:")?"private":e.room.startsWith("room:")?"named":"public",this.invite=e.invite??null,this.teams=e.teams??0,this.open=e.open??!0,this.ranked=e.ranked??!1,this.kept=e.kept??Et(e.room),this.owner=e.owner??null,this.host=e.host;for(let s of e.players)this.players.set(s.id,{...s}),s.presence!==null&&s.presence!==void 0&&this.samples.set(s.id,[{at:e.now??this.clock(),d:s.presence}]);this.me=this.players.get(e.you)??{id:e.you,name:"You",presence:null,team:0},this.players.set(this.me.id,this.me),this.state={...e.state},this.confirmed=sn(e.state);for(let[s,i]of Object.entries(e.private??{}))this.secrets.set(s,{...i});this.match.phase!=="lobby"&&(this.frozenSettings=this.chosenSettings())}get budget(){return this.shares}get settings(){return this.frozenSettings??this.chosenSettings()}setSetting(e,t){if(this.closed||!this.isHost||this.match.phase!=="lobby")return;let r=this.schema.find(s=>s.id===e);if(!r||!r.options.some(s=>s.value===t)||this.chosenSettings()[e]===t)return;let o=this.state[ne];this.setState(ne,{...o!==null&&typeof o=="object"?o:{},[e]:t}),this.clearReady(),this.emit("settings",this.settings)}chosenSettings(){let e=this.state[ne];return Object.fromEntries(this.schema.map(t=>[t.id,At(t,e)]))}get isHost(){return this.connected&&this.host===this.me.id}get online(){return[...this.players.values()].filter(e=>e.connected!==!1)}get participants(){let e=this.match.participants;return this.match.phase==="lobby"||!e?[]:e.map(t=>this.players.get(t)).filter(t=>!!t)}get spectators(){let e=this.match.participants;return this.match.phase==="lobby"||!e?[]:this.online.filter(t=>!e.includes(t.id))}get leftOut(){let e=this.match.left;return this.match.phase==="lobby"||!e?.length?[]:this.spectators.filter(t=>e.includes(t.id))}get private(){return this.secrets.get(this.me.id)??{}}privateOf(e){return e===this.me.id||this.isHost?this.secrets.get(e)??{}:{}}setPrivate(e,t){this.closed||(this.setSecret(this.me.id,e,t??null),this.outbox.event(()=>F(t),()=>this.transport.private(e,t??null)))}setPrivateFor(e,t,r){if(!this.closed){if(e===this.me.id)return this.setPrivate(t,r);this.outbox.event(()=>F(r),()=>this.transport.private(t,r??null,String(e)))}}presenceAt(e,t={}){if(e===this.me.id)return this.me.presence;let r=this.samples.get(e);return!r||r.length===0?this.players.get(e)?.presence??null:nn(r,this.clock()-(t.delay??100),t)}keep(e,t,r){let o=this.samples.get(e)??[],s=o.length;for(;s>0&&o[s-1].at>t;)s--;for(o.splice(s,0,{at:t,d:r});o.length>rn||o.length>2&&o[0].at<t-on;)o.shift();this.samples.set(e,o)}isParticipant(e=this.me.id){return this.match.phase!=="lobby"&&!!this.match.participants?.includes(e)}get spectating(){return this.match.phase!=="lobby"&&!this.isParticipant()}get running(){return this.match.phase==="playing"&&!this.match.paused}matchNow(){let e=this.match;if(e.phase!=="playing"||e.startedAt===void 0)return 0;let t=this.clock(),r=(e.pausedMs??0)+(e.paused?Math.max(0,t-e.paused.since):0);return Math.max(0,t-e.startedAt-r)}get canStart(){return this.isHost&&this.kind!=="public"&&this.match.phase==="lobby"&&this.online.length>=this.match.min&&this.allReady}get allReady(){return this.notReady.length===0}get notReady(){return this.online.filter(e=>e.id!==this.host&&!e.ready)}setReady(e=!0){this.closed||!!this.me.ready===e||(e?this.me.ready=!0:delete this.me.ready,this.connected||(this.offlineReady=e),this.outbox.urgent(N,()=>this.transport.ready(e)))}startMatch(e={}){if(!this.reachable("startMatch"))return;let t=Number(e.countdown),r={...Number.isFinite(t)?{countdown:Math.round(t*1e3)}:{},...e.open===!0?{open:!0}:{}};this.outbox.urgent(N,()=>this.transport.start(r))}endMatch(){this.reachable("endMatch")&&this.outbox.urgent(N,()=>this.transport.end())}pauseMatch(e=!0){this.reachable("pauseMatch")&&this.outbox.urgent(N,()=>this.transport.pause(e))}admit(e){let t=(Array.isArray(e)?e:[e]).map(String);t.length&&this.reachable("admit")&&this.outbox.urgent(N,()=>this.transport.admit(t))}reachable(e){let[t,r]=this.closed?["closed","this room is closed (you left it, were removed, or moved to another one)"]:this.connected?["",""]:["disconnected","the connection to the room is down and the platform is reconnecting: call it again after room.on('reconnect')"];return t?(this.complain(e,t,r),!1):!0}dropHostWrites(){for(let e of[...this.written.keys()]){if(!te(e))continue;this.written.delete(e);let t=this.confirmed[e]??null;JSON.stringify(this.state[e]??null)!==JSON.stringify(t)&&(t===null?delete this.state[e]:this.state[e]=t,this.emit("state",e,t,""))}}complain(e,t,r){let o=this.clock(),s=`${e}:${t}`;if(o-(this.complained.get(s)??-1/0)<Cr)return;this.complained.set(s,o);let i=`${e}() did nothing: ${r}.`;console.warn(`[onceworlds] ${i} (${t})`),this.emit("error",{code:t,message:i})}transferHost(e){this.closed||this.outbox.urgent(N,()=>this.transport.transfer(String(e)))}hideLobby(e=!0){this.closed||this.transport.hideLobby?.(!!e)}clearReady(){if(!(this.closed||!this.isHost)){for(let e of this.players.values())delete e.ready;this.outbox.urgent(N,()=>this.transport.unready())}}send(e,t={}){this.closed||this.outbox.event(()=>F(e),()=>this.transport.send(e,t.to))}setPresence(e){if(!this.closed){if(this.me.presence=e,this.presenceTimer){this.pendingPresence={value:e};return}this.transport.presence(e),this.outbox.spend(F(e)),this.presenceTimer=setTimeout(()=>this.flushPresence(),1e3/this.shares.presenceHz)}}setState(e,t){this.writeState(e,t)}writeState(e,t){if(this.closed)return 0;if(te(e)&&this.connected&&this.host!==this.me.id)return this.complain("setState","not_host",`only the host writes ${e}`),0;t==null?delete this.state[e]:this.state[e]=t;let r=++this.writes;return this.written.set(e,{w:r,at:this.clock()}),this.outbox.state(e,()=>F(t)+e.length,()=>this.transport.state(e,t??null,r)),r}_writeAcked(e,t){if(this.closed||!this.connected)return Promise.resolve(!1);let r=this.writeState(e,t);return r?this.kind==="solo"?Promise.resolve(!0):new Promise(o=>{let s={w:r,done:a=>{clearTimeout(i),o(a)}},i=setTimeout(()=>this.settleAcks(e,a=>a===s,!1),Dr);this.acks.set(e,[...this.acks.get(e)??[],s])}):Promise.resolve(!1)}_resetData(){return this.closed||!this.connected||!this.transport.dataReset?!1:(this.outbox.urgent(N,()=>this.transport.dataReset()),!0)}settleAcks(e,t,r){let o=this.acks.get(e);if(!o)return;let s=o.filter(i=>!t(i));s.length>0?this.acks.set(e,s):this.acks.delete(e);for(let i of o)t(i)&&i.done(r)}failAcks(){for(let e of[...this.acks.keys()])this.settleAcks(e,()=>!0,!1)}setTeam(e,t){this.closed||this.outbox.urgent(N,()=>this.transport.team(e,t))}setOpen(e){this.closed||this.outbox.urgent(N,()=>this.transport.open(e))}reportResult(e){this.closed||this.outbox.urgent(()=>F(e),()=>this.transport.result(e))}kick(e){this.closed||this.outbox.urgent(N,()=>this.transport.kick(String(e)))}voteKick(e){this.closed||this.outbox.urgent(N,()=>this.transport.voteKick(String(e)))}on(e,t){let r=this.listeners.get(e);return r||this.listeners.set(e,r=new Set),r.add(t),()=>r.delete(t)}leave(){this.closed||(this.transport.leave(),this.close("left"))}_receive(e){switch(e.t){case"welcome":return this.resync(e);case"away":{let t=this.players.get(e.id);return!t||t===this.me?void 0:(t.connected=!1,this.emit("away",t))}case"back":{let t=this.players.get(e.id);return!t||t===this.me?void 0:(delete t.connected,this.emit("back",t,e.fresh===!0))}case"ready":{let t=this.players.get(e.id);return!t||!!t.ready==(e.ready===!0)?void 0:(e.ready===!0?t.ready=!0:delete t.ready,this.emit("ready",t))}case"match":return this.applyMatch(e.match);case"idle":{let t=this.players.get(e.id);return!t||t===this.me||!!t.idle==(e.idle===!0)?void 0:(e.idle===!0?t.idle=!0:delete t.idle,this.emit("idle",t))}case"private":{let t=JSON.stringify(this.secrets.get(e.id)?.[e.k]??null);this.setSecret(e.id,e.k,e.v??null),t!==JSON.stringify(e.v??null)&&this.emit("private",e.k,e.v??null,e.id);return}case"privates":return this.applySecrets(e.all??{});case"unready":{for(let t of this.players.values())t.ready&&(delete t.ready,this.emit("ready",t));return}case"join":{let t={...e.player};return this.players.set(t.id,t),this.emit("join",t)}case"leave":{let t=this.players.get(e.id);return!t||t===this.me?void 0:(this.players.delete(e.id),this.samples.delete(e.id),this.emit("leave",t,e.kicked===!0))}case"votekick":{let t=this.players.get(e.id);t&&this.emit("votekick",t,e.votes,e.needed);return}case"host":if(this.host=e.id,e.id!==this.me.id)for(let t of[...this.secrets.keys()])t!==this.me.id&&this.secrets.delete(t);return e.id!==this.me.id&&(this.dropHostWrites(),this.failAcks()),this.emit("host",e.id);case"msg":return this.emit("message",e.d,this.players.get(e.from)??{id:e.from,name:"Unknown",presence:null,team:0},typeof e.at=="number"?e.at:this.clock(),typeof e.mt=="number"?e.mt:void 0);case"team":{let t=this.players.get(e.id);return t?(t.team=e.team,this.emit("team",t)):void 0}case"name":{let t=e.id===this.me.id?this.me:this.players.get(e.id);return!t||typeof e.name!="string"||t.name===e.name?void 0:(t.name=e.name,this.emit("rename",t))}case"open":return this.open=e.open,this.emit("open",e.open);case"rated":for(let t of e.changes){let r=this.players.get(t.id);r&&(r.rating=t.rating)}return this.emit("rated",e.changes,e.disputed,e.capped===!0);case"presence":{let t=this.players.get(e.id);return!t||t===this.me?void 0:(t.presence=e.d,this.keep(e.id,typeof e.at=="number"?e.at:this.clock(),e.d),this.emit("presence",t))}case"state":{e.from===this.me.id&&typeof e.w=="number"&&this.settleAcks(e.k,o=>o.w<=e.w,!0),te(e.k)&&(e.v===null?delete this.confirmed[e.k]:this.confirmed[e.k]=e.v);let t=this.written.get(e.k);if(t)if(e.from===this.me.id)if(typeof e.w!="number")this.written.delete(e.k);else{if(e.w<t.w)return;e.w===t.w&&this.written.delete(e.k)}else{if(this.clock()-t.at<Ar)return;this.written.delete(e.k)}let r=JSON.stringify(this.state[e.k]??null);e.v===null?delete this.state[e.k]:this.state[e.k]=e.v,(e.from!==this.me.id||r!==JSON.stringify(e.v??null))&&this.emit("state",e.k,e.v,e.from),e.k===ne&&this.schema.length>0&&this.frozenSettings===null&&r!==JSON.stringify(e.v??null)&&e.from!==this.me.id&&this.emit("settings",this.settings);return}case"chat":return this.emit("chat",e.entry);case"error":return typeof e.k=="string"&&typeof e.w=="number"&&this.settleAcks(e.k,t=>t.w===e.w,!1),e.code==="cooldown"&&this.me.ready&&(delete this.me.ready,this.emit("ready",this.me)),console.warn(`[onceworlds] ${e.message} (${e.code})`),this.emit("error",{code:e.code,message:e.message})}}_closed(e){this.close(e)}_disconnected(){this.closed||!this.connected||(this.connected=!1,this.outbox.clear(),this.failAcks(),this.emit("disconnect"))}close(e){this.closed||(this.closed=!0,this.outbox.clear(),this.failAcks(),this.presenceTimer&&clearTimeout(this.presenceTimer),this.emit("close",e))}flushPresence(){if(this.presenceTimer=null,!this.pendingPresence||this.closed)return;let{value:e}=this.pendingPresence;this.pendingPresence=null,this.transport.presence(e),this.outbox.spend(F(e)),this.presenceTimer=setTimeout(()=>this.flushPresence(),1e3/this.shares.presenceHz)}applyBudget(e){if(!e)return;let t=(r,o)=>typeof r=="number"&&Number.isFinite(r)&&r>0&&r<=o;t(e.presenceHz,S.presenceHz)&&(this.shares={...this.shares,presenceHz:e.presenceHz}),t(e.messagesPerSecond,S.messagesPerSecond)&&t(e.bytesPerSecond,S.roomBytesPerSecond)&&(this.shares={...this.shares,messagesPerSecond:e.messagesPerSecond,bytesPerSecond:e.bytesPerSecond},this.outbox.setBudget({messagesPerSecond:e.messagesPerSecond,bytesPerSecond:e.bytesPerSecond}))}setSecret(e,t,r){let o={...this.secrets.get(e)??{}};r===null?delete o[t]:o[t]=r,Object.keys(o).length>0?this.secrets.set(e,o):this.secrets.delete(e)}applySecrets(e){let t=[];for(let[r,o]of Object.entries(e))for(let[s,i]of Object.entries(o))JSON.stringify(this.secrets.get(r)?.[s]??null)!==JSON.stringify(i)&&t.push([r,s,i]);for(let[r,o]of this.secrets)for(let s of Object.keys(o))s in(e[r]??{})||t.push([r,s,null]);this.secrets=new Map(Object.entries(e).map(([r,o])=>[r,{...o}]));for(let[r,o,s]of t)this.emit("private",o,s,r)}applyMatch(e){let t=this.match;if(!(!e||JSON.stringify(t)===JSON.stringify(e))){if(this.match=e,e.phase!=="lobby"&&this.frozenSettings===null)this.frozenSettings=this.chosenSettings();else if(e.phase==="lobby"&&this.frozenSettings!==null){let r=JSON.stringify(this.frozenSettings);this.frozenSettings=null,r!==JSON.stringify(this.chosenSettings())&&queueMicrotask(()=>this.emit("settings",this.settings))}this.emit("match",e,t),t.phase!=="starting"&&e.phase==="starting"&&this.emit("starting",e),t.phase!=="playing"&&e.phase==="playing"&&this.emit("matchstart",e),t.phase!=="lobby"&&e.phase==="lobby"&&this.emit("matchend",e,t),t.phase==="playing"&&e.phase==="playing"&&(!t.paused&&e.paused?this.emit("matchpause",e):t.paused&&!e.paused&&this.emit("matchresume",e))}}resync(e){let t=this.connected,r=this.host!==e.host;this.connected=!0,this.host=e.host,this.written.clear(),this.confirmed=sn(e.state),this.applyBudget(e.budget);let o=new Set;for(let i of e.players){if(o.add(i.id),i.id===this.me.id){this.offlineReady===void 0&&!!this.me.ready!=!!i.ready&&(i.ready?this.me.ready=!0:delete this.me.ready,this.emit("ready",this.me));continue}let a=this.players.get(i.id);if(a)a.presence=i.presence,i.presence!==null&&i.presence!==void 0&&this.keep(i.id,e.now??this.clock(),i.presence),a.team=i.team,a.name!==i.name&&(a.name=i.name,this.emit("rename",a)),!!a.ready!=!!i.ready&&(i.ready?a.ready=!0:delete a.ready,this.emit("ready",a)),!!a.idle!=!!i.idle&&(i.idle?a.idle=!0:delete a.idle,this.emit("idle",a)),a.connected===!1!=(i.connected===!1)&&(i.connected===!1?a.connected=!1:delete a.connected,i.connected===!1?this.emit("away",a):this.emit("back",a,!1));else{let u={...i};this.players.set(i.id,u),this.emit("join",u)}}for(let[i,a]of this.players)o.has(i)||a===this.me||(this.players.delete(i),this.emit("leave",a));let s=new Set([...Object.keys(this.state),...Object.keys(e.state)]);for(let i of s){let a=e.state[i]??null;JSON.stringify(this.state[i]??null)!==JSON.stringify(a)&&(a===null?delete this.state[i]:this.state[i]=a,this.emit("state",i,a,""))}r&&this.emit("host",e.host),this.teams=e.teams??this.teams,this.kept=e.kept??this.kept,e.open!==void 0&&e.open!==this.open&&(this.open=e.open,this.emit("open",e.open)),this.applyMatch(e.match??{phase:"lobby",n:0,min:1}),this.applySecrets(e.private??{}),this.me.presence!==null&&this.transport.presence(this.me.presence),this.offlineReady!==void 0&&!!e.players.find(i=>i.id===this.me.id)?.ready!==this.offlineReady&&this.transport.ready(this.offlineReady),this.offlineReady=void 0,t||this.emit("reconnect")}emit(e,...t){for(let r of this.listeners.get(e)??[])try{r(...t)}catch(o){console.error(`[onceworlds] error in room "${e}" listener`,o)}}};function an(n){let e=null,t=o=>n()._receive({t:"match",match:o}),r=()=>{let s=n().match;if(s.phase!=="starting")return;let{startsAt:i,...a}=s;t({...a,phase:"playing",startedAt:Date.now(),pausedMs:0})};return{send(){},presence(){},state(){},team(){},open(){},result(){},kick(){},voteKick(){},ready(){},unready(){},transfer(){},start(o){let s=n();if(s.match.phase!=="lobby")return;let i=Math.min(S.matchCountdownMaxMs,Math.max(0,o.countdown??S.matchCountdownMs));t({phase:"starting",n:s.match.n+1,min:s.match.min,id:`solo${s.match.n+1}`,seed:Math.floor(Math.random()*2**32),participants:[s.me.id],startsAt:Date.now()+i}),i===0?r():e=setTimeout(r,i)},end(){let o=n();e&&clearTimeout(e),e=null,o.match.phase!=="lobby"&&t({phase:"lobby",n:o.match.n,min:o.match.min})},pause(o){let s=n().match;if(s.phase!=="playing")return;let i=Date.now();if(o&&!s.paused)t({...s,paused:{since:i,reason:"host"}});else if(!o&&s.paused){let{paused:a,...u}=s;t({...u,pausedMs:(s.pausedMs??0)+Math.max(0,i-a.since)})}},admit(){},private(){},leave(){e&&clearTimeout(e),e=null}}}var ln=["pointerdown","pointermove","keydown","wheel","touchstart","touchmove","devicemotion","visibilitychange"],$r=5e3;function un(n,e=S.idleAfterMs){let t=Date.now(),r=!1,o=()=>{t=Date.now(),r&&(r=!1,n(!1))},s=()=>{try{for(let a of navigator.getGamepads?.()??[])if(a&&(a.buttons.some(u=>u.pressed)||a.axes.some(u=>Math.abs(u)>.25)))return!0}catch{}return!1};for(let a of ln)window.addEventListener(a,o,{capture:!0,passive:!0});let i=setInterval(()=>{if(s())return o();!r&&Date.now()-t>e&&(r=!0,n(!0))},$r);return{get idle(){return r},stop(){clearInterval(i);for(let a of ln)window.removeEventListener(a,o,{capture:!0})}}}var cn=["pointerdown","keydown","touchstart","gamepadconnected"];function dn(n,e){let t=r=>{if(!(!r.isTrusted||!n())){for(let o of cn)window.removeEventListener(o,t,{capture:!0});e()}};for(let r of cn)window.addEventListener(r,t,{capture:!0,passive:!0})}var fn=["low","medium","high"],Ir={low:.6,medium:.8,high:1},Tr=24,Or=18.5,Lr=26,Xe=6e3,pn=2e4,_r=5*6e4,et=class{constructor(e=2){c(this,"level",2);c(this,"slow",0);c(this,"smoothSince",0);c(this,"holdUntil",0);c(this,"probeAfter",pn);c(this,"steppedUpAt",-1/0);this.level=e}window(e,t,r){return t>Tr?(this.smoothSince=0,++this.slow>=2&&e>=this.holdUntil&&this.level>0&&(e-this.steppedUpAt<Xe+pn/2&&(this.probeAfter=Math.min(_r,this.probeAfter*2)),this.level--,this.slow=0,this.holdUntil=e+Xe)):t<=Or&&r<=Lr?(this.slow=0,this.smoothSince||(this.smoothSince=e),this.level<fn.length-1&&e>=this.holdUntil&&e-this.smoothSince>=this.probeAfter&&(this.level++,this.steppedUpAt=e,this.smoothSince=0,this.holdUntil=e+Xe)):(this.slow=0,this.smoothSince=0),this.level}};function mn(n){let e="auto",t=typeof matchMedia=="function"&&matchMedia("(prefers-reduced-motion: reduce)").matches,r=!1,o=new et(Br()?1:2),s=new Set,i=!1,a=!1,u=0,d=[],f=0,h=0,m=R=>{if(i){if(u&&!document.hidden){let A=R-u;A<250&&d.push(A)}if(u=document.hidden?0:R,f||(f=R),R-f>=1e3){if(d.length>=10){let A=[...d].sort((U,D)=>U-D),I=d.reduce((U,D)=>U+D,0)/d.length,W=A[Math.min(A.length-1,Math.floor(A.length*.95))],K=P();e==="auto"&&o.window(R,I,W),r&&R-h>=500&&(h=R,n.stats({fps:Math.round(1e3/I),frameMs:Math.round(I*10)/10,worstMs:Math.round(A[A.length-1]*10)/10})),P()!==K&&O()}d=[],f=R}w()}},w=()=>{a||!i||(a=!0,requestAnimationFrame(R=>{a=!1,m(R)}))},y=()=>{i||typeof requestAnimationFrame!="function"||(i=!0,u=0,f=0,w())},k=()=>{!r&&e!=="auto"&&i&&(i=!1)},P=()=>e==="auto"?fn[o.level]:e,O=()=>{for(let R of s)try{R(B)}catch(A){console.error('[onceworlds] error in settings "change" listener',A)}},B={get choice(){return e},get quality(){return e==="auto"&&y(),P()},get scale(){return Ir[B.quality]},get reducedMotion(){return t},pixelRatio(R=2){let A=typeof devicePixelRatio=="number"&&devicePixelRatio>0?devicePixelRatio:1;return Math.max(.5,Math.min(A,R)*B.scale)},on(R,A){return R!=="change"?()=>{}:(s.add(A),e==="auto"&&y(),()=>s.delete(A))}};return{settings:B,apply(R){let A=`${P()}|${t}`;e=R.quality,t=R.reducedMotion,r=R.showStats,r||e==="auto"&&s.size>0?y():k(),`${P()}|${t}`!==A&&O()}}}function Br(){return typeof matchMedia=="function"&&matchMedia("(pointer: coarse)").matches}var se={maxSide:1280,quality:.85,maxBytes:15e5,answerMs:2500,waitMs:3e3,perSecond:3};var Nr=4,jr=250,Gr=1e3;function Hr(){return typeof window>"u"||typeof document>"u"?null:{document,requestAnimationFrame:n=>window.requestAnimationFrame(n),setTimeout:(n,e)=>window.setTimeout(n,e),clearTimeout:n=>window.clearTimeout(n),background:n=>window.getComputedStyle(n).backgroundColor,hidden:()=>document.visibilityState==="hidden"}}function Kr(n){if(!n||typeof n!="object")return null;let e=n;if(typeof e.id!="number"||!Number.isSafeInteger(e.id)||e.id<0)return null;let t=typeof e.maxSide=="number"&&Number.isFinite(e.maxSide)?Math.min(se.maxSide,Math.max(64,Math.round(e.maxSide))):se.maxSide,r=typeof e.quality=="number"&&Number.isFinite(e.quality)?Math.min(.95,Math.max(.5,e.quality)):se.quality;return{id:e.id,maxSide:t,quality:r}}function qr(n,e,t){let r=Math.min(1,t/Math.max(n,e,1)),o=s=>Math.max(1,Math.min(t,Math.round(s*r)));return{width:o(n),height:o(e)}}function Ur(n){for(let e=0;e+2<n.length;e+=4)if(n[e]!==0||n[e+1]!==0||n[e+2]!==0)return!1;return!0}var zr=/^(?:transparent|rgba\(.*,\s*0(?:\.0*)?\))$/;function Fr(n,e){try{for(let t=n;t;t=t.parentElement){let r=e.background?.(t)?.trim();if(r&&!zr.test(r))return r}}catch{}return"#000"}function tt(n,e,t,r,o){try{let s=r.document.createElement("canvas");s.width=e.width,s.height=e.height;let i=s.getContext("2d");if(!i)return{miss:"unsupported"};if(i.drawImage(n,0,0,e.width,e.height),Ur(i.getImageData(0,0,e.width,e.height).data))return{miss:"blank"};i.globalCompositeOperation="destination-over",i.fillStyle=o(),i.fillRect(0,0,e.width,e.height);for(let a of[t.quality,.6]){let u=s.toDataURL("image/jpeg",a);if(!u.startsWith("data:image/jpeg;base64,"))return{miss:"unsupported"};if((u.length-23)*.75<=se.maxBytes)return{image:u}}return{miss:"failed"}}catch(s){return{miss:s?.name==="SecurityError"?"tainted":"failed"}}}function hn(n,e){let t=!1,r=()=>{t||(t=!0,e())};n.requestAnimationFrame(r),n.setTimeout(r,jr)}function Vr(n,e,t){return new Promise(r=>{let o,s;try{if(typeof n.captureStream!="function")return r(null);o=n.captureStream(),s=e.document.createElement("video"),s.muted=!0,s.playsInline=!0,s.srcObject=o}catch{return r(null)}let i=!1,a=f=>{if(!i){i=!0,e.clearTimeout(u);try{s.srcObject=null;for(let h of o.getTracks())h.stop()}catch{}r(f)}},u=e.setTimeout(()=>a(null),Gr),d=()=>{!i&&s.videoWidth>0&&s.videoHeight>0&&a(t(s))};try{s.addEventListener("loadeddata",d),s.addEventListener("playing",d),s.play()?.catch(()=>{})}catch{a(null)}})}function gn(n,e=Hr()){let t=!1,r=s=>{try{n(s)}catch{}};function o(s){let i=s.id;if(!e)return r({id:i,t:"none",reason:"unsupported"});if(t)return r({id:i,t:"none",reason:"busy"});let a=e,u=we(a.document.querySelectorAll("canvas"));if(!u)return r({id:i,t:"none",reason:"no-canvas"});t=!0;let d=k=>{t=!1,r("image"in k?{id:i,t:"done",image:k.image}:{id:i,t:"none",reason:k.miss})},f=qr(u.width,u.height,s.maxSide),h=null,m=()=>h??(h=Fr(u,a));if(a.hidden?.()){let k=tt(u,f,s,a,m);return d("miss"in k&&k.miss==="blank"?{miss:"hidden"}:k)}let w=0,y=()=>{try{let k=tt(u,f,s,a,m);if(!("miss"in k)||k.miss!=="blank")return d(k);if(++w<Nr)return hn(a,y);Vr(u,a,P=>tt(P,f,s,a,m)).then(P=>d(P??{miss:"blank"}),()=>d({miss:"blank"}))}catch{d({miss:"failed"})}};hn(a,y)}return{receive(s){let i=null;try{i=Kr(s),i&&o(i)}catch{t=!1,i&&r({id:i.id,t:"none",reason:"failed"})}}}}var M=(n,e)=>new DOMException(e,n);function G(n,e=[]){if(typeof n=="number"&&!Number.isNaN(n)||typeof n=="string")return n;if(n instanceof Date&&!Number.isNaN(n.getTime()))return new Date(n.getTime());if(n instanceof ArrayBuffer)return n.slice(0);if(ArrayBuffer.isView(n))return n.buffer.slice(n.byteOffset,n.byteOffset+n.byteLength);if(Array.isArray(n)&&!e.includes(n))return n.map(t=>G(t,[...e,n]));throw M("DataError","The value is not a valid key.")}function st(n){try{return G(n)}catch{return}}var xe=n=>typeof n=="number"?1:n instanceof Date?2:typeof n=="string"?3:n instanceof ArrayBuffer?4:5;function T(n,e){if(xe(n)!==xe(e))return xe(n)<xe(e)?-1:1;if(n instanceof ArrayBuffer||Array.isArray(n)){let o=n instanceof ArrayBuffer?[...new Uint8Array(n)]:n,s=e instanceof ArrayBuffer?[...new Uint8Array(e)]:e;for(let i=0;i<Math.min(o.length,s.length);i++){let a=T(o[i],s[i]);if(a)return a}return o.length===s.length?0:o.length<s.length?-1:1}let t=n instanceof Date?n.getTime():n,r=e instanceof Date?e.getTime():e;return t<r?-1:t>r?1:0}function J(n){return typeof n=="number"?`n${n}`:typeof n=="string"?`s${n}`:n instanceof Date?`d${n.getTime()}`:n instanceof ArrayBuffer?`b${new Uint8Array(n).join()}`:`a${JSON.stringify(n.map(J))}`}function wn(n,e){let t=n;if(e==="")return t;for(let r of e.split(".")){if(t==null)return;t=t[r]}return t}function it(n,e){if(typeof e=="string")return st(wn(n,e));let t=e.map(r=>it(n,r));return t.includes(void 0)?void 0:t}function Wr(n,e,t){let r=e.split("."),o=n;for(let s of r.slice(0,-1))o=o[s]??(o[s]={});o[r[r.length-1]]=t}var Y=n=>typeof structuredClone=="function"?structuredClone(n):n;function at(n){let e=[...n].sort();return e.item=t=>e[t]??null,e.contains=t=>e.includes(t),e}var nt=(()=>{if(typeof MessageChannel!="function")return t=>{setTimeout(t)};let n=[],e=new MessageChannel;return e.port1.onmessage=()=>n.shift()?.(),e.port1.unref?.(),t=>{n.push(t),e.port2.postMessage(0)}})(),ie=class{constructor(){c(this,"listeners",new Map)}addEventListener(e,t){if(!t)return;let r=this.listeners.get(e)??[];r.includes(t)||r.push(t),this.listeners.set(e,r)}removeEventListener(e,t){let r=this.listeners.get(e);r&&t&&r.includes(t)&&r.splice(r.indexOf(t),1)}dispatchEvent(e){return j(e,[this]),!e.defaultPrevented}run(e){let t=!1,r=this[`on${e.type}`];for(let o of[r,...this.listeners.get(e.type)??[]])try{typeof o=="function"?o.call(this,e):o?.handleEvent?.(e)}catch(s){t=!0,setTimeout(()=>{throw s})}return t}};function j(n,e){Object.defineProperty(n,"target",{configurable:!0,value:e[0]}),Object.defineProperty(n,"srcElement",{configurable:!0,value:e[0]});let t=!1;for(let r of e)if(Object.defineProperty(n,"currentTarget",{configurable:!0,value:r}),t=r.run(n)||t,n.cancelBubble)break;return t}function Me(n,e,t){return typeof IDBVersionChangeEvent=="function"?new IDBVersionChangeEvent(n,{oldVersion:e,newVersion:t}):Object.assign(new Event(n),{oldVersion:e,newVersion:t})}var Ee=class{constructor(e,t,r){c(this,"name",e);c(this,"keyPath",t);c(this,"autoIncrement",r);c(this,"records",new Map);c(this,"indexes",new Map);c(this,"nextKey",1)}schema(){return{keyPath:this.keyPath,autoIncrement:this.autoIncrement,nextKey:this.nextKey,indexes:[...this.indexes.values()]}}},Re=class{constructor(e,t,r){c(this,"name",e);c(this,"backend",t);c(this,"version",0);c(this,"stores",new Map);c(this,"connections",new Set);c(this,"queue",[]);c(this,"running",null);if(r){this.version=r.version;for(let[o,s]of Object.entries(r.stores)){let i=new Ee(o,s.keyPath,s.autoIncrement);i.nextKey=s.nextKey;for(let a of s.indexes)i.indexes.set(a.name,a);this.stores.set(o,i)}for(let{store:o,key:s,value:i}of r.records){let a=st(s);a!==void 0&&this.stores.get(o)?.records.set(J(a),{key:a,value:i})}}}enqueue(e,t){this.queue.push({transaction:e,started:t}),nt(()=>this.next())}next(){if(this.running)return;let e=this.queue.shift();e&&(this.running=e.transaction,e.transaction.begin(e.started))}finished(){this.running=null,this.next()}drop(e){this.queue=this.queue.filter(t=>t.transaction!==e)}},ae=class extends ie{constructor(t,r){super();c(this,"source",t);c(this,"transaction",r);c(this,"result");c(this,"error",null);c(this,"readyState","pending");c(this,"onsuccess",null);c(this,"onerror",null)}},le=class extends ae{constructor(){super(...arguments);c(this,"onupgradeneeded",null);c(this,"onblocked",null)}},ue=class extends ie{constructor(t,r,o){super();c(this,"db",t);c(this,"scope",r);c(this,"mode",o);c(this,"error",null);c(this,"oncomplete",null);c(this,"onerror",null);c(this,"onabort",null);c(this,"ended",null);c(this,"undo",[]);c(this,"ops",[]);c(this,"schemaChanged",!1);c(this,"state","waiting");c(this,"work",[]);c(this,"stores",new Map);c(this,"scheduled",!1)}get objectStoreNames(){return at(this.scope)}widen(t){this.scope.includes(t)||this.scope.push(t)}forget(t){this.scope=this.scope.filter(r=>r!==t),this.stores.delete(t)}objectStore(t){if(this.state==="done")throw M("InvalidStateError","The transaction has finished.");let r=this.db.data.stores.get(t);if(!r||!this.scope.includes(t))throw M("NotFoundError",`No object store named ${t} in this transaction.`);let o=this.stores.get(t);return o||this.stores.set(t,o=new de(this,r)),o}begin(t){this.state="active",t?.(),this.schedule()}schedule(){this.scheduled||this.state!=="active"||(this.scheduled=!0,nt(()=>{if(this.scheduled=!1,this.state!=="active")return;let t=this.work.shift();t?(this.perform(t.request,t.run),this.schedule()):this.finish()}))}check(t=!1){if(this.state!=="active"&&this.state!=="waiting")throw M("TransactionInactiveError","The transaction has finished.");if(t&&this.mode==="readonly")throw M("ReadOnlyError","The transaction is read-only.")}request(t,r){this.check();let o=new ae(t,this);return this.work.push({request:o,run:r}),this.schedule(),o}again(t,r){this.check(),t.readyState="pending",this.work.push({request:t,run:r}),this.schedule()}path(t){return[t,this,this.db]}perform(t,r){let o;try{o=r()}catch(s){let i=s instanceof DOMException?s:M("UnknownError",String(s));t.readyState="done",t.error=i;let a=new Event("error",{bubbles:!0,cancelable:!0}),u=j(a,this.path(t));(u||!a.defaultPrevented)&&this.stop(u?M("AbortError","A handler threw."):i);return}t.readyState="done",t.result=o,j(new Event("success"),[t])&&this.stop(M("AbortError","A handler threw."))}async finish(){this.state="committing";let t=this.db.data;if((this.ops.length>0||this.schemaChanged)&&t.backend){let o=this.schemaChanged?Object.fromEntries([...t.stores].map(([s,i])=>[s,i.schema()])):void 0;try{await t.backend.commit({db:t.name,version:t.version,stores:o,ops:this.ops})}catch(s){let i=s instanceof Error?s.message:String(s);this.state="active",this.stop(i.includes("QuotaExceededError")?M("QuotaExceededError","This game has used its storage in this browser."):M("UnknownError",i));return}}this.state="done",j(new Event("complete"),[this]),this.ended?.(!0),t.finished()}stop(t){if(this.state==="done")return;let r=this.state==="waiting";this.state="done",this.error=t;for(let i of this.undo.reverse())i();let o=this.work;this.work=[];let s=this.db.data;r&&s.drop(this),nt(()=>{for(let{request:i}of o)i.readyState="done",i.error=M("AbortError","The transaction was aborted."),j(new Event("error",{bubbles:!0,cancelable:!0}),this.path(i));j(new Event("abort",{bubbles:!0}),[this,this.db]),this.ended?.(!1),r||s.finished()})}abort(){if(this.state==="done"||this.state==="committing")throw M("InvalidStateError","The transaction has finished.");this.stop(null)}commit(){this.check()}},Pe=class{constructor(e){c(this,"transaction",e)}select(e,t="next"){let r=lt(e),o=this.entries().filter(s=>r(s.key));return t.endsWith("unique")&&(o=o.filter((s,i)=>i===0||T(o[i-1].key,s.key)!==0)),t.startsWith("prev")&&(o=o.reverse()),o}value(e){return Y(this.storeData().records.get(J(e.primaryKey))?.value)}get(e){return rt(e),this.transaction.request(this,()=>{let[t]=this.select(e);return t?this.value(t):void 0})}getKey(e){return rt(e),this.transaction.request(this,()=>Y(this.select(e)[0]?.primaryKey))}getAll(e,t){return this.transaction.request(this,()=>yn(this.select(e),t).map(r=>this.value(r)))}getAllKeys(e,t){return this.transaction.request(this,()=>yn(this.select(e),t).map(r=>Y(r.primaryKey)))}count(e){return this.transaction.request(this,()=>this.select(e).length)}openCursor(e,t){return bn(this,e,t,!0)}openKeyCursor(e,t){return bn(this,e,t,!1)}};function rt(n){if(n==null)throw M("DataError","A key or key range is required.")}var yn=(n,e)=>e===void 0?n:n.slice(0,e);function lt(n){if(n==null)return()=>!0;if(typeof n=="object"&&"lowerOpen"in n){let t=n,r=t.lower===void 0?void 0:G(t.lower),o=t.upper===void 0?void 0:G(t.upper);return s=>{let i=r===void 0?1:T(s,r),a=o===void 0?-1:T(s,o);return(t.lowerOpen?i>0:i>=0)&&(t.upperOpen?a<0:a<=0)}}let e=G(n);return t=>T(t,e)===0}function bn(n,e,t="next",r){let o=e??void 0;lt(o);let s=n.transaction.request(n,()=>new(r?Ae:ce)(n,s,n.select(o,t),t).move());return s}var ce=class{constructor(e,t,r,o){c(this,"source",e);c(this,"request",t);c(this,"list",r);c(this,"direction",o);c(this,"key");c(this,"primaryKey");c(this,"at",-1);c(this,"ready",!0)}move(e=()=>!0){let t=this.source.storeData().records;for(this.ready=!0,this.at++;this.at<this.list.length;this.at++){let r=this.list[this.at];if(!(!t.has(J(r.primaryKey))||!e(r)))return this.key=Y(r.key),this.primaryKey=Y(r.primaryKey),this.show(r),this}return null}show(e){}step(e){if(this.source.transaction.check(),!this.ready)throw M("InvalidStateError","The cursor is already moving.");this.ready=!1,this.source.transaction.again(this.request,()=>this.move(e))}continue(e){if(e==null)return this.step();let t=G(e),r=this.direction.startsWith("prev");this.step(o=>r?T(o.key,t)<=0:T(o.key,t)>=0)}continuePrimaryKey(e,t){let r=G(e),o=G(t),s=this.direction.startsWith("prev");this.step(i=>{let a=T(i.key,r)||T(i.primaryKey,o);return s?a<=0:a>=0})}advance(e){if(!(e>0))throw new TypeError("advance needs a positive count.");let t=e;this.step(()=>--t===0)}store(){let e=this.source;return e instanceof de?e:e.objectStore}update(e){let t=this.store();return t.keyPath===null?t.put(e,this.primaryKey):t.put(e)}delete(){return this.store().delete(this.primaryKey)}},Ae=class extends ce{constructor(){super(...arguments);c(this,"value")}show(t){this.value=this.source.value(t)}},de=class extends Pe{constructor(t,r){super(t);c(this,"data",r)}get name(){return this.data.name}get keyPath(){return this.data.keyPath}get autoIncrement(){return this.data.autoIncrement}get indexNames(){return at(this.data.indexes.keys())}storeData(){return this.data}entries(){return[...this.data.records.values()].map(t=>({key:t.key,primaryKey:t.key})).sort((t,r)=>T(t.key,r.key))}select(t,r){if(t==null||typeof t=="object"&&"lowerOpen"in t)return super.select(t,r);let o=this.data.records.get(J(G(t)));return o?[{key:o.key,primaryKey:o.key}]:[]}put(t,r){return this.write(t,r,!1)}add(t,r){return this.write(t,r,!0)}write(t,r,o){let{transaction:s,data:i}=this;s.check(!0);let a=Y(t),u;if(i.keyPath!==null){if(r!==void 0)throw M("DataError","This store takes its keys from its values.");u=it(a,i.keyPath)}else r!==void 0&&(u=G(r));if(u===void 0&&!i.autoIncrement)throw M("DataError","The value has no key.");return s.request(this,()=>{let d=u,f=i.nextKey;d===void 0?(d=i.nextKey++,typeof i.keyPath=="string"&&Wr(a,i.keyPath,d),s.schemaChanged=!0):i.autoIncrement&&typeof d=="number"&&d>=i.nextKey&&(i.nextKey=Math.floor(d)+1,s.schemaChanged=!0);let h=J(d),m=i.records.get(h);if(o&&m)throw M("ConstraintError","A record with this key already exists.");return this.checkUnique(h,a),i.records.set(h,{key:d,value:a}),s.undo.push(()=>{i.nextKey=f,m?i.records.set(h,m):i.records.delete(h)}),s.ops.push({store:i.name,put:d,value:a}),Y(d)})}checkUnique(t,r){for(let o of this.data.indexes.values())if(o.unique){for(let s of ot(o,r))for(let[i,a]of this.data.records)if(i!==t&&ot(o,a.value).some(u=>T(u,s)===0))throw M("ConstraintError",`Another record has this ${o.name}.`)}}delete(t){let{transaction:r,data:o}=this;return r.check(!0),rt(t),lt(t),r.request(this,()=>{for(let{primaryKey:s}of this.select(t)){let i=J(s),a=o.records.get(i);a&&(o.records.delete(i),r.undo.push(()=>o.records.set(i,a)),r.ops.push({store:o.name,remove:a.key}))}})}clear(){let{transaction:t,data:r}=this;return t.check(!0),t.request(this,()=>{let o=r.records;r.records=new Map,t.undo.push(()=>r.records=o),t.ops.push({store:r.name,clear:!0})})}upgrading(){if(this.transaction.mode!=="versionchange")throw M("InvalidStateError","Indexes change only while a database upgrades.");this.transaction.check(),this.transaction.schemaChanged=!0}createIndex(t,r,o){if(this.upgrading(),this.data.indexes.has(t))throw M("ConstraintError",`An index named ${t} already exists.`);let s=r;return this.data.indexes.set(t,{name:t,keyPath:Array.isArray(s)?[...s]:String(s),unique:o?.unique===!0,multiEntry:o?.multiEntry===!0}),this.transaction.undo.push(()=>this.data.indexes.delete(t)),this.index(t)}deleteIndex(t){this.upgrading();let r=this.data.indexes.get(t);if(!r)throw M("NotFoundError",`No index named ${t}.`);this.data.indexes.delete(t),this.transaction.undo.push(()=>this.data.indexes.set(t,r))}index(t){this.transaction.check();let r=this.data.indexes.get(t);if(!r)throw M("NotFoundError",`No index named ${t}.`);return new De(this,r)}};function ot(n,e){if(n.multiEntry&&typeof n.keyPath=="string"){let r=wn(e,n.keyPath);if(Array.isArray(r)){let o=r.map(s=>st(s)).filter(s=>s!==void 0);return o.filter((s,i)=>o.findIndex(a=>T(a,s)===0)===i)}}let t=it(e,n.keyPath);return t===void 0?[]:[t]}var De=class extends Pe{constructor(t,r){super(t.transaction);c(this,"objectStore",t);c(this,"index",r)}get name(){return this.index.name}get keyPath(){return this.index.keyPath}get unique(){return this.index.unique}get multiEntry(){return this.index.multiEntry}storeData(){return this.objectStore.data}entries(){let t=[];for(let r of this.objectStore.data.records.values())for(let o of ot(this.index,r.value))t.push({key:o,primaryKey:r.key});return t.sort((r,o)=>T(r.key,o.key)||T(r.primaryKey,o.primaryKey))}},pe=class extends ie{constructor(t){super();c(this,"data",t);c(this,"onversionchange",null);c(this,"onclose",null);c(this,"onerror",null);c(this,"onabort",null);c(this,"upgrade",null);c(this,"closed",!1);t.connections.add(this)}get name(){return this.data.name}get version(){return this.data.version}get objectStoreNames(){return at(this.data.stores.keys())}transaction(t,r="readonly"){if(this.closed)throw M("InvalidStateError","The database connection is closed.");if(this.upgrade)throw M("InvalidStateError","The database is upgrading.");if(r!=="readonly"&&r!=="readwrite")throw new TypeError(`Bad transaction mode: ${String(r)}`);let o=typeof t=="string"?[t]:[...t];if(o.length===0)throw M("InvalidAccessError","A transaction needs an object store.");for(let i of o)if(!this.data.stores.has(i))throw M("NotFoundError",`No object store named ${i}.`);let s=new ue(this,[...new Set(o)],r);return this.data.enqueue(s),s}createObjectStore(t,r){let o=this.upgrading();if(this.data.stores.has(t))throw M("ConstraintError",`An object store named ${t} already exists.`);let s=r?.keyPath??null;if(r?.autoIncrement&&(s===""||Array.isArray(s)))throw M("InvalidAccessError","A key generator needs a single key path.");let i=new Ee(t,Array.isArray(s)?[...s]:s,r?.autoIncrement===!0);return this.data.stores.set(t,i),o.widen(t),o.undo.push(()=>{this.data.stores.delete(t),o.forget(t)}),o.objectStore(t)}deleteObjectStore(t){let r=this.upgrading(),o=this.data.stores.get(t);if(!o)throw M("NotFoundError",`No object store named ${t}.`);this.data.stores.delete(t),r.forget(t),r.ops.push({store:t,clear:!0}),r.undo.push(()=>{this.data.stores.set(t,o),r.widen(t)})}upgrading(){if(!this.upgrade)throw M("InvalidStateError","Object stores change only while a database upgrades.");return this.upgrade.check(),this.upgrade.schemaChanged=!0,this.upgrade}close(){this.closed=!0,this.data.connections.delete(this)}},Ce=class{constructor(e){c(this,"backend",e);c(this,"loading",new Map)}load(e){let t=this.loading.get(e);return t||(t=Jr(this.backend.open(e)).then(r=>new Re(e,this.backend,r),()=>new Re(e,null,null)),this.loading.set(e,t)),t}open(e,t){if(t!==void 0&&!(Math.floor(t)>=1))throw new TypeError("The version must be at least 1.");let r=new le(null,null);return this.load(String(e)).then(o=>this.connect(r,o,t===void 0?void 0:Math.floor(t))),r}connect(e,t,r){let o=r??(t.version||1),s=f=>{e.readyState="done",e.result=void 0,e.error=f,j(new Event("error",{bubbles:!0,cancelable:!0}),[e])},i=f=>{e.readyState="done",e.result=f,j(new Event("success"),[e])};if(o<t.version)return s(M("VersionError",`The database is at version ${t.version}.`));if(o===t.version)return i(new pe(t));let a=t.version;for(let f of[...t.connections])j(Me("versionchange",a,o),[f]);let u=new pe(t),d=new ue(u,[...t.stores.keys()],"versionchange");d.schemaChanged=!0,u.upgrade=d,d.ended=f=>{if(u.upgrade=null,e.transaction=null,f)return i(u);u.close(),s(M("AbortError","The upgrade was aborted."))},t.enqueue(d,()=>{t.version=o,d.undo.push(()=>t.version=a),e.readyState="done",e.result=u,e.transaction=d,j(Me("upgradeneeded",a,o),[e])&&d.abort()})}deleteDatabase(e){let t=new le(null,null);return this.load(String(e)).then(async r=>{let o=r.version;for(let s of[...r.connections])j(Me("versionchange",o,null),[s]),s.close();await r.backend?.remove(r.name).catch(()=>{}),this.loading.delete(r.name),t.readyState="done",j(Me("success",o,null),[t])}),t}async databases(){return this.backend.list().catch(()=>[])}cmp(e,t){return T(G(e),G(t))}};function Jr(n){return new Promise((e,t)=>{let r=setTimeout(()=>t(new Error("Timed out")),8e3);n.then(e,t).finally(()=>clearTimeout(r))})}function Yr(n){return new Ce(n)}function kn(n){try{if(window.origin!=="null")return;let e={indexedDB:Yr(n),IDBFactory:Ce,IDBDatabase:pe,IDBTransaction:ue,IDBObjectStore:de,IDBIndex:De,IDBCursor:ce,IDBCursorWithValue:Ae,IDBRequest:ae,IDBOpenDBRequest:le};for(let[t,r]of Object.entries(e))Object.defineProperty(window,t,{configurable:!0,writable:!0,value:r})}catch{}}var vn=(n,e)=>Object.prototype.hasOwnProperty.call(n,e);function ut(n){try{return n(),!0}catch{return!1}}function Qr(){let n=new Map,e={getItem:t=>n.has(String(t))?n.get(String(t)):null,setItem:(t,r)=>{n.set(String(t),String(r))},removeItem:t=>{n.delete(String(t))},clear:()=>n.clear(),key:t=>[...n.keys()][Number(t)]??null};return new Proxy(e,{get(t,r){if(r==="length")return n.size;if(r===Symbol.toStringTag)return"Storage";if(typeof r=="string")return vn(e,r)?t[r]:n.get(r)},set(t,r,o){return typeof r=="string"&&n.set(r,String(o)),!0},has:(t,r)=>typeof r=="string"&&(vn(e,r)||n.has(r)),deleteProperty(t,r){return typeof r=="string"&&n.delete(r),!0},ownKeys:()=>[...n.keys()],getOwnPropertyDescriptor:(t,r)=>typeof r=="string"&&n.has(r)?{value:n.get(r),writable:!0,enumerable:!0,configurable:!0}:void 0})}function Zr(n=Date.now){let e=new Map;return{read:()=>[...e].map(([t,r])=>`${t}=${r}`).join("; "),write(t){let[r,...o]=String(t).split(";"),s=r.indexOf("="),i=(s<0?"":r.slice(0,s)).trim(),a=(s<0?r:r.slice(s+1)).trim();if(!i&&!a)return;let u=!1;for(let d of o){let[f,...h]=d.split("="),m=h.join("=").trim();f.trim().toLowerCase()==="max-age"&&Number(m)<=0&&(u=!0),f.trim().toLowerCase()==="expires"&&Date.parse(m)<=n()&&(u=!0)}u?e.delete(i):e.set(i,a)}}}function fe(n,e,t){try{Object.defineProperty(n,e,{configurable:!0,...t})}catch{}}function Xr(){if(typeof HTMLImageElement!="function")return;let n=Object.getOwnPropertyDescriptor(HTMLImageElement.prototype,"src");if(!n?.get||!n.set)return;let{get:e,set:t}=n;fe(HTMLImageElement.prototype,"src",{enumerable:n.enumerable,get(){return e.call(this)},set(r){try{this.crossOrigin===null&&new URL(String(r),document.baseURI).origin===location.origin&&(this.crossOrigin="anonymous")}catch{}t.call(this,r)}})}function eo(){let n=window.Worker;if(typeof n!="function")return;let e=function(t,r){try{return new n(t,r)}catch(o){if(!(o instanceof DOMException&&o.name==="SecurityError")||r?.type==="module")throw o;let s;try{s=new URL(String(t),document.baseURI)}catch{throw o}if(s.origin!==location.origin)throw o;let a=`const base = ${JSON.stringify(s.href)};
3
3
  const resolve = (input) => new URL(String(input), base).href;
4
4
  const importScripts_ = self.importScripts.bind(self);
5
5
  self.importScripts = (...urls) => importScripts_(...urls.map(resolve));
@@ -9,4 +9,4 @@ if (typeof XMLHttpRequest === 'function') {
9
9
  const open_ = XMLHttpRequest.prototype.open;
10
10
  XMLHttpRequest.prototype.open = function (method, url, ...rest) { return open_.call(this, method, resolve(url), ...rest); };
11
11
  }
12
- importScripts(base);`;return new n(URL.createObjectURL(new Blob([l],{type:"text/javascript"})),r)}};e.prototype=n.prototype,J(window,"Worker",{value:e,writable:!0})}function Rt(){try{for(let n of["localStorage","sessionStorage"])Me(()=>window[n].length)||J(window,n,{value:Pn()});if(!Me(()=>document.cookie)){let n=An();J(document,"cookie",{get:()=>n.read(),set:e=>n.write(e)})}if(window.origin==="null"&&(Dn(),$n()),window.origin==="null"||!Me(()=>history.replaceState(history.state,"",location.href)))for(let n of["pushState","replaceState"]){let e=history[n];J(history,n,{value:function(...t){try{return e.apply(this,t)}catch(r){if(!(r instanceof DOMException&&r.name==="SecurityError"))throw r}}})}}catch{}}var _n=["menu","lobby","stick","buttons"];function Mt(n){if(!Array.isArray(n)||n.length>16)return null;let e=[];for(let t of n){if(!t||typeof t!="object")continue;let{kind:r,x:o,y:s,w:i,h:l}=t;_n.includes(r)&&(!oe(o)||!oe(s)||!oe(i)||!oe(l)||i<0||l<0||e.push({kind:r,x:o,y:s,w:i,h:l}))}return e}var oe=n=>typeof n=="number"&&Number.isFinite(n),Pe={entries:10,entryMs:1e3,totalMs:2e3};function Pt(n){let e=typeof n=="number"?[n]:Array.isArray(n)?n.slice(0,Pe.entries):null;if(!e||!e.every(o=>typeof o=="number"&&Number.isFinite(o)&&o>=0))return null;let t=[],r=Pe.totalMs;for(let o of e){let s=Math.min(Math.round(o),Pe.entryMs,r);if(t.push(s),r-=s,r<=0)break}return t.some((o,s)=>s%2===0&&o>0)?t:[]}var On=/^#(?:[0-9a-f]{3}){1,2}$/i,Y={panel:"#111216",text:"#f7f7f8",accent:"#d33e00"},$e=4.5,Ae=3,se=["#4ade80","#15803d"];function At(n){let e=[];if(n==null)return{look:null,notes:e};if(typeof n!="object")return{look:null,notes:["a look is { accent, panel, text } or null"]};let t=n,r=p=>{let S=t[p];return S==null?null:typeof S=="string"&&On.test(S)?$t(S):(e.push(`${p} is not #rgb or #rrggbb`),null)},o=r("panel"),s=r("text"),i=r("accent");if(o||s){let p=I(s??Y.text,o??Y.panel);p<$e&&(e.push(`text on panel is ${p.toFixed(1)}:1, under ${$e}:1: the platform's are used`),o=s=null)}let l=o??Y.panel,d=s??Y.text;if(i){let p=I(i,l);p<Ae&&(e.push(`accent on panel is ${p.toFixed(1)}:1, under ${Ae}:1: the platform's is used`),i=null)}if(!i&&o&&I(Y.accent,o)<Ae&&(i=d),!o&&!s&&!i)return{look:null,notes:e};let f=i?Ln(i):null;return{look:{panel:o,text:s,muted:o||s?Cn(d,l):null,accent:i,accentHover:i?Dt(i,f==="#ffffff"?"#000000":"#ffffff",.14):null,onAccent:f,ok:o?I(se[0],o)>=I(se[1],o)?se[0]:se[1]:null},notes:e}}function $t(n){let e=n.slice(1).toLowerCase();return`#${e.length===3?[...e].map(t=>t+t).join(""):e}`}function De(n){let e=$t(n);return[parseInt(e.slice(1,3),16),parseInt(e.slice(3,5),16),parseInt(e.slice(5,7),16)]}function Et(n){let[e,t,r]=De(n).map(o=>{let s=o/255;return s<=.04045?s/12.92:((s+.055)/1.055)**2.4});return .2126*e+.7152*t+.0722*r}function I(n,e){let[t,r]=[Et(n),Et(e)].sort((o,s)=>s-o);return(t+.05)/(r+.05)}function Ln(n){return I(n,"#000000")>I(n,"#ffffff")?"#000000":"#ffffff"}function Dt(n,e,t){let[r,o]=[De(n),De(e)];return`#${r.map((s,i)=>Math.round(s+(o[i]-s)*t).toString(16).padStart(2,"0")).join("")}`}function Cn(n,e){for(let t=.3;t>.001;t-=.05){let r=Dt(n,e,t);if(I(r,e)>=$e)return r}return n}var ie=class{constructor(){u(this,"areas",null);u(this,"key","")}receive(e){let t=Mt(e);if(!t)return!1;let r=JSON.stringify(t);return this.areas&&r===this.key?!1:(this.key=r,this.areas=Object.freeze(t.map(o=>Object.freeze(o))),!0)}};function _t(n){let e={look:null,notes:["a look is { accent, panel, text } or null"]};if(n==null)return{look:null,notes:[]};if(typeof n!="object")return e;let t={};try{for(let r of["accent","panel","text"]){let o=n[r];o!=null&&(t[r]=typeof o=="string"?o.slice(0,16):"")}}catch{return e}return{look:t,notes:At(t).notes}}function Ot(n,e,t){let r=typeof n.vibrate=="function"?n.vibrate.bind(n):null,o=s=>{try{if(!e())return r?r(s):!1;if(!r)return!1;let i=Pt(Array.isArray(s)?Array.from(s):s);return i?(t(i),!0):!1}catch{return!1}};try{Object.defineProperty(n,"vibrate",{value:o,configurable:!0,writable:!0})}catch{}}var Tn=["RTCPeerConnection","webkitRTCPeerConnection","mozRTCPeerConnection"];function Lt(n){if(n)for(let e of Tn)try{Object.defineProperty(n,e,{value:void 0,writable:!1,enumerable:!1,configurable:!1})}catch{}}function Ct(n,e){if(Lt(n),!!e)for(let t of["contentWindow","contentDocument"])try{let r=Object.getOwnPropertyDescriptor(e.prototype,t),o=r?.get;if(!r||!o)continue;Object.defineProperty(e.prototype,t,{...r,get(){let s=o.call(this);return Lt(t==="contentWindow"?s:s?.defaultView),s}})}catch{}}var Tt="0.1.0";function Gt(){let n=globalThis;return n.onceworlds?.__onceworlds||(n.onceworlds=Nn()),n.onceworlds}function Nn(){let n=Xe(document.currentScript);Rt(),Ct(window,typeof HTMLIFrameElement>"u"?void 0:HTMLIFrameElement);let e=Ye(),t=xt({stats:a=>w("stats",a)}),r=window.parent!==window,o=r&&et(location.search)?nt(console,location.origin):null,s="connecting",i=null,l=1,d=new Map,f=new Map,p=null,S=[],D,v=null,h=0,R=new Set,$=new ie,G=new Set,T=new Set,k=new ne(a=>{s!=="standalone"&&x("ui.controls",a).catch(()=>{})},a=>w("input",{touch:a})),E,M=new Promise(a=>E=a),Z=it(),Q=at(()=>p,Z),H={read:a=>x("data.game.get",{key:a}),op:a=>x("data.game.op",a)},U=ct(()=>C().then(a=>a.player),L),jt=lt(async()=>(await M,s==="platform"?H:U),Z),pe=new Set,me=[],_e=a=>{let c=`${a.message}|${a.source}|${a.line}`;pe.has(c)||pe.size>=b.errorReportsPerPage||(pe.add(c),s==="platform"?w("error",a):s==="connecting"&&me.push(a))};if(window.addEventListener("error",a=>{if(!(a instanceof ErrorEvent))return;let c=String(a.message||"Error");if(_e({message:c,source:Nt(a.filename),line:a.lineno||0,column:a.colno||0,stack:a.error instanceof Error?String(a.error.stack??""):""}),o){let m=a.error instanceof Error?`Uncaught ${te(a.error)}`:/^Uncaught\b/.test(c)?c:`Uncaught ${c}`;o.error(m,{source:Nt(a.filename),line:a.lineno||0,column:a.colno||0})}}),window.addEventListener("unhandledrejection",a=>{let c=a.reason;o?.error(`Uncaught (in promise) ${c instanceof Error?te(c):z(c)}`),_e({message:`Unhandled promise rejection: ${c instanceof Error?c.message:String(c)}`,source:"",line:0,column:0,stack:c instanceof Error?String(c.stack??""):""})}),r){window.addEventListener("message",c=>{if(!(c.source!==window.parent||c.data?.type!==Ve||!c.ports[0])&&s!=="standalone"){if(i?.close(),i=c.ports[0],i.onmessage=m=>zt(m.data),s=tt(c.data),E(),s==="platform")for(let m of me.splice(0))w("error",m);else me.length=0;o?.connect(m=>w("console",m)),D||(w("alive",{}),D=setInterval(()=>w("alive",{}),2e3)),s==="platform"&&C().then(m=>{e.apply(m.audio),m.settings&&t.apply(m.settings)}).catch(()=>{})}});let a={type:Ke,version:Tt,...n?{build:n}:{}};window.parent.postMessage(a,"*"),setTimeout(()=>{s==="connecting"&&(s="standalone",E())},5e3)}else s="standalone",E();if(window.addEventListener("keydown",a=>{a.key!=="/"||s!=="platform"||!p||Gn(a.target)||(a.preventDefault(),a.stopImmediatePropagation(),w("hotkey",{key:"/"}))},!0),r){try{document.documentElement.style.touchAction="pan-x pan-y"}catch{}for(let a of["gesturestart","gesturechange","gestureend"])document.addEventListener(a,c=>c.preventDefault(),{passive:!1})}if(r){let a=c=>{c.pointerType==="mouse"||s!=="platform"||(window.removeEventListener("pointerup",a,!0),x("ui.tapped",void 0).catch(()=>{}))};window.addEventListener("pointerup",a,!0)}if(r&&wt(()=>s==="platform",()=>w("input.first",{})),r&&Ot(navigator,()=>s==="platform",a=>w("vibrate",{pattern:a})),r){let a=Element.prototype.requestFullscreen;Element.prototype.requestFullscreen=function(c){return s!=="platform"?a.call(this,c):(x("ui.fullscreen",void 0).catch(()=>{}),Promise.resolve())}}function zt(a){if(a.kind==="res"){let m=d.get(a.id);if(!m)return;d.delete(a.id),a.ok?m.resolve(a.result):m.reject(new Error(a.error));return}if(a.kind!=="event")return;let c=a.name;if(c==="room")p?._receive(a.data);else if(c==="room.connection")a.data?.connected===!1&&p?._disconnected();else if(c==="room.closed"){let m=p;p=null,m?._closed(a.data.reason)}else if(c==="room.moved"){let m=p;p=Oe(a.data),m?._closed("moved");for(let y of R)try{y(p)}catch(_){console.error('[onceworlds] error in rooms "moved" listener',_)}}else if(c==="audio")e.apply(a.data),ee("audio",a.data);else if(c==="settings")t.apply(a.data);else if(c==="pause"||c==="resume")ee(c);else if(c==="controls")k.receive(a.data);else if(c==="input")k.touch=a.data?.touch===!0;else if(c==="reserved")$.receive(a.data)&&ee("reserved",$.areas);else if(c==="debug")for(let m of T)try{m(a.data)}catch(y){console.error("[onceworlds] error in the debugger link",y)}else if(c==="player"){let m=a.data;C().then(y=>{m?.id!==y.player.id||typeof m.name!="string"||(y.player.name=m.name,ee("player",y.player))}).catch(()=>{})}}async function x(a,c){await M;let m=i;if(!m)throw new Error("Not connected to Onceworlds");return new Promise((y,_)=>{let g=l++;d.set(g,{resolve:y,reject:_}),m.postMessage({kind:"req",id:g,method:a,params:c})})}function w(a,c){i?.postMessage({kind:"event",name:a,data:c})}function ee(a,...c){for(let m of f.get(a)??[])try{m(...c)}catch(y){console.error(`[onceworlds] error in "${a}" listener`,y)}}function Oe(a,c=S){let m={send:(g,P)=>w("room.send",{d:g,to:P}),presence:g=>w("room.presence",{d:g}),state:(g,P,A)=>w("room.state",{k:g,v:P,w:A}),hideLobby:g=>w("room.hideLobby",{hidden:g}),team:(g,P)=>w("room.team",{id:g,team:P}),open:g=>w("room.open",{open:g}),result:g=>w("room.result",{result:g}),kick:g=>w("room.kick",{id:g}),voteKick:g=>w("room.votekick",{id:g}),ready:g=>w("room.ready",{ready:g}),unready:()=>w("room.unready",{}),transfer:g=>w("room.transfer",{id:g}),start:g=>w("room.start",g),end:()=>w("room.end",{}),pause:g=>w("room.pause",{paused:g}),admit:g=>w("room.admit",{ids:g}),private:(g,P,A)=>w("room.private",{k:g,v:P,...A?{id:A}:{}}),dataReset:()=>w("room.datareset",{}),leave:()=>{p===y&&(p=null),x("room.leave",void 0).catch(()=>{})}};S=c;let y=new W(a,m,()=>Date.now()+h,c);Le(y);let _=yt(g=>w("room.idle",{idle:g}));return y.on("reconnect",()=>_.idle&&w("room.idle",{idle:!0})),y.on("close",()=>_.stop()),y}function Le(a){a.on("state",(c,m,y)=>{p===a&&fe(c)&&Q._changed(c.slice(N.length),m,y)})}function Ht(a,c){let m={};for(let[A,K]of Object.entries(ce.all()))m[N+A]=K;let y={room:"solo",you:a.id,host:a.id,players:[{...a,presence:null,team:c.teams?1:0}],state:m,chat:[],teams:c.teams??0,open:!0,now:Date.now(),ranked:!1,kept:!0,owner:a.id},g={...gt(()=>P),state(A,K){fe(A)&&ce.set(A.slice(N.length),K)},dataReset(){for(let A of Object.keys(ce.all()))ce.set(A,null),P._receive({t:"state",k:N+A,v:null,from:""})}},P=new W(y,g,()=>Date.now()+h,we(c.settings));return Le(P),P}function C(){return v??(v=M.then(()=>s==="platform"?x("session.get",void 0):jn()).then(a=>(h=Number(a.timeOffset)||0,a))),v}C().catch(()=>{});let Ce={async get(a){return await M,s==="platform"?await x("save.get",{key:a}):ae.get(a)},async set(a,c){await M,s==="platform"?await x("save.set",{key:a,value:c}):ae.set(a,c)},async delete(a){await M,s==="platform"?await x("save.delete",{key:a}):ae.delete(a)},async list(){return await M,s==="platform"?x("save.list",void 0):ae.list()}},Te={__onceworlds:!0,_debug:o?{send:a=>{i&&w("debug",a)},on:a=>(T.add(a),()=>T.delete(a))}:null,version:Tt,get mode(){return s},ready:()=>M,player:{get:()=>C().then(a=>a.player),async avatarUrl(a,c="full"){let m=await C().catch(()=>null);if(!m?.platformOrigin)return null;let y=typeof a=="string"&&a?a:m.player.id;return`${m.platformOrigin}/avatar/${encodeURIComponent(y)}${c==="head"?"/head":""}.svg`},async avatar(a){if(await M,s!=="platform")return null;let c=typeof a=="string"&&a?a:(await C()).player.id;return Je.test(c)?Be(await x("player.avatar",{id:c}).catch(()=>null)):null},async rename(){return await M,s!=="platform"?null:await x("player.rename",void 0).catch(()=>null)?(await C()).player:null}},game:{info:()=>C().then(a=>a.game)},save:Ce,data:{player:Ce,server:Q,game:jt},rooms:{async join(a={}){await M;let c=a.party===!0&&p!==null&&s==="platform";if(c||(p?.leave(),p=null),s!=="platform"){let{player:_}=await C();return p=Ht(_,a),p}let m=await x("room.join",{name:a.name,maxPlayers:a.maxPlayers,mode:a.mode,teams:a.teams,private:a.private,ranked:a.ranked,party:a.party,minPlayers:a.minPlayers,minPlayersPrivate:a.minPlayersPrivate,settings:a.settings,countdown:a.countdown,lobby:a.lobby,...a.ownCountdown===!0?{ownCountdown:!0}:{}}),y=p;return p=Oe(m,we(a.settings)),c&&y?._closed("moved"),p},get current(){return p},on(a,c){return a!=="moved"?()=>{}:(R.add(c),()=>R.delete(c))}},ratings:{async get(a){return await M,s==="platform"?x("ratings.get",{mode:String(a)}):null},async top(a,c={}){return await M,s==="platform"?x("ratings.top",{mode:String(a),limit:c.limit}):[]}},ui:{setMenuPosition(a){x("ui.menuPosition",{position:a}).catch(()=>{})},get reserved(){return $.areas},setLook(a){let{look:c,notes:m}=_t(a);for(let y of m)G.has(y)||(G.add(y),console.warn(`[onceworlds] ui.setLook: ${y}`));s!=="standalone"&&x("ui.look",c).catch(()=>{})},requestFullscreen(){s==="platform"?x("ui.fullscreen",void 0).catch(()=>{}):document.documentElement.requestFullscreen?.().catch(()=>{})},showInvite(){s==="platform"&&x("ui.invite",void 0).catch(()=>{})},setOrientation(a){a!=="any"&&a!=="landscape"&&a!=="portrait"||s!=="standalone"&&x("ui.orientation",{orientation:a}).catch(()=>{})}},controls:{set(a){k.set(a)},get stick(){return k.stick},pressed(a){return k.pressed(String(a))},presses(a){return k.presses(String(a))},get touch(){return k.touch}},now:()=>Date.now()+h,leaderboards:{async submit(a,c,m={}){if(await M,s!=="platform")return ue.submit(String(a),Number(c),m.lowerIsBetter===!0);try{return await x("leaderboards.submit",{board:String(a),score:Number(c),lowerIsBetter:m.lowerIsBetter===!0})}catch(y){return console.warn(`[onceworlds] score for "${a}" was not saved: ${y instanceof Error?y.message:y}`),null}},async top(a,c={}){return await M,s!=="platform"?ue.top(String(a)):x("leaderboards.top",{board:String(a),limit:c.limit,lowerIsBetter:c.lowerIsBetter===!0})}},settings:t.settings,audio:{get volume(){return e.volume},get muted(){return e.muted}},badges:{async award(a){if(await M,s!=="platform")return de.add(String(a));try{return(await x("badges.award",{key:String(a)})).awarded}catch(c){return console.warn(`[onceworlds] badge "${a}" was not awarded: ${c instanceof Error?c.message:c}`),!1}},async list(){return await M,s==="platform"?x("badges.list",void 0):de.list()},async has(a){return(await Te.badges.list()).some(c=>c.key===a&&c.earned)}},env:Bn(),async fetch(a,c={}){if(await M,s!=="platform")throw new Error("onceworlds.fetch only works on Onceworlds, where your secrets are stored. Run the game with `onceworlds dev`.");let m=a instanceof Request?a:null,y=new URL(m?m.url:String(a),location.href).href,_=(c.method??m?.method??"GET").toUpperCase(),g={};new Headers(c.headers??m?.headers).forEach((Ut,Kt)=>{g[Kt]=Ut});let P=c.body??null;P===null&&m&&_!=="GET"&&_!=="HEAD"&&(P=await m.arrayBuffer()),P instanceof URLSearchParams&&(g["content-type"]??(g["content-type"]="application/x-www-form-urlencoded;charset=UTF-8"),P=P.toString());let A=await x("net.fetch",{url:y,method:_,headers:g,body:await In(P)}),K=[101,204,205,304].includes(A.status);return new Response(K?null:A.body,{status:A.status,statusText:A.statusText,headers:A.headers})},on(a,c){let m=f.get(a);return m||f.set(a,m=new Set),m.add(c),()=>m.delete(c)}};return Te}function Bn(){let n=globalThis.__ONCEWORLDS_ENV__,e={};if(n&&typeof n=="object")for(let[t,r]of Object.entries(n))typeof r=="string"&&(e[t]=r);return Object.freeze(e)}async function In(n){if(n==null)return null;if(typeof n=="string"||n instanceof ArrayBuffer)return n;if(ArrayBuffer.isView(n))return new Uint8Array(n.buffer,n.byteOffset,n.byteLength).slice().buffer;if(n instanceof Blob)return n.arrayBuffer();throw new TypeError("onceworlds.fetch bodies must be a string (e.g. JSON.stringify(...)), bytes or a Blob.")}function Nt(n){if(!n)return"";try{let e=new URL(n);return e.origin===location.origin?e.pathname.slice(1)||"index.html":e.href}catch{return n}}function Gn(n){return n instanceof HTMLElement?n.isContentEditable||["INPUT","TEXTAREA","SELECT"].includes(n.tagName):!1}function jn(){let n=L.get("onceworlds:player-id");return n||(n=`local-${Math.random().toString(36).slice(2,10)}`,L.set("onceworlds:player-id",n)),{player:{id:n,name:"Player"},game:{slug:location.hostname.split(".")[0]||"local",name:document.title||"Game",owner:"local"},audio:{volume:1,muted:!1},timeOffset:0}}var Bt="onceworlds:scores",ue={all(){try{let n=JSON.parse(L.get(Bt)??"{}");return n&&typeof n=="object"?n:{}}catch{return{}}},submit(n,e,t){let r=ue.all(),o=r[n],s=o===void 0?e:t?Math.min(o,e):Math.max(o,e);return r[n]=s,L.set(Bt,JSON.stringify(r)),{best:s,rank:1}},top(n){let e=ue.all()[n];if(e===void 0)return{entries:[],me:null};let t={rank:1,player:{id:"local",name:"You"},score:e};return{entries:[t],me:t}}},X="onceworlds:save:",It="onceworlds:badges",de={earned(){try{let n=JSON.parse(L.get(It)??"{}");return n&&typeof n=="object"?n:{}}catch{return{}}},add(n){let e=de.earned();return e[n]?!1:(e[n]=Date.now(),L.set(It,JSON.stringify(e)),!0)},list(){return Object.entries(de.earned()).map(([n,e])=>({key:n,name:n,description:"",icon:null,earned:!0,earnedAt:e}))}},ae={get(n){let e=L.get(X+n);if(e===null)return null;try{return JSON.parse(e)}catch{return null}},set(n,e){L.set(X+n,JSON.stringify(e??null))},delete(n){L.remove(X+n)},list(){let n=[];try{for(let e=0;e<localStorage.length;e++){let t=localStorage.key(e);t?.startsWith(X)&&n.push(t.slice(X.length))}}catch{}return n.sort()}},le="onceworlds:server:",ce={all(){let n={};try{for(let e=0;e<localStorage.length;e++){let t=localStorage.key(e);if(t?.startsWith(le))try{n[t.slice(le.length)]=JSON.parse(localStorage.getItem(t)??"null")}catch{}}}catch{}return n},set(n,e){e==null?L.remove(le+n):L.set(le+n,JSON.stringify(e))}},L={get(n){try{return localStorage.getItem(n)}catch{return null}},set(n,e){try{localStorage.setItem(n,e)}catch{}},remove(n){try{localStorage.removeItem(n)}catch{}}};Gt();})();
12
+ importScripts(base);`;return new n(URL.createObjectURL(new Blob([a],{type:"text/javascript"})),r)}};e.prototype=n.prototype,fe(window,"Worker",{value:e,writable:!0})}function Sn(){try{for(let n of["localStorage","sessionStorage"])ut(()=>window[n].length)||fe(window,n,{value:Qr()});if(!ut(()=>document.cookie)){let n=Zr();fe(document,"cookie",{get:()=>n.read(),set:e=>n.write(e)})}if(window.origin==="null"&&(eo(),Xr(),Reflect.deleteProperty(Navigator.prototype,"serviceWorker")),window.origin==="null"||!ut(()=>history.replaceState(history.state,"",location.href)))for(let n of["pushState","replaceState"]){let e=history[n];fe(history,n,{value:function(...t){try{return e.apply(this,t)}catch(r){if(!(r instanceof DOMException&&r.name==="SecurityError"))throw r}}})}}catch{}}var to=["menu","lobby","stick","buttons"];function Mn(n){if(!Array.isArray(n)||n.length>16)return null;let e=[];for(let t of n){if(!t||typeof t!="object")continue;let{kind:r,x:o,y:s,w:i,h:a}=t;to.includes(r)&&(!$e(o)||!$e(s)||!$e(i)||!$e(a)||i<0||a<0||e.push({kind:r,x:o,y:s,w:i,h:a}))}return e}var $e=n=>typeof n=="number"&&Number.isFinite(n),ct={entries:10,entryMs:1e3,totalMs:2e3};function En(n){let e=typeof n=="number"?[n]:Array.isArray(n)?n.slice(0,ct.entries):null;if(!e||!e.every(o=>typeof o=="number"&&Number.isFinite(o)&&o>=0))return null;let t=[],r=ct.totalMs;for(let o of e){let s=Math.min(Math.round(o),ct.entryMs,r);if(t.push(s),r-=s,r<=0)break}return t.some((o,s)=>s%2===0&&o>0)?t:[]}var no=/^#(?:[0-9a-f]{3}){1,2}$/i,me={panel:"#111216",text:"#f7f7f8",accent:"#d33e00"},pt=4.5,dt=3,Ie=["#4ade80","#15803d"];function Rn(n){let e=[];if(n==null)return{look:null,notes:e};if(typeof n!="object")return{look:null,notes:["a look is { accent, panel, text } or null"]};let t=n,r=f=>{let h=t[f];return h==null?null:typeof h=="string"&&no.test(h)?Pn(h):(e.push(`${f} is not #rgb or #rrggbb`),null)},o=r("panel"),s=r("text"),i=r("accent");if(o||s){let f=V(s??me.text,o??me.panel);f<pt&&(e.push(`text on panel is ${f.toFixed(1)}:1, under ${pt}:1: the platform's are used`),o=s=null)}let a=o??me.panel,u=s??me.text;if(i){let f=V(i,a);f<dt&&(e.push(`accent on panel is ${f.toFixed(1)}:1, under ${dt}:1: the platform's is used`),i=null)}if(!i&&o&&V(me.accent,o)<dt&&(i=u),!o&&!s&&!i)return{look:null,notes:e};let d=i?ro(i):null;return{look:{panel:o,text:s,muted:o||s?oo(u,a):null,accent:i,accentHover:i?An(i,d==="#ffffff"?"#000000":"#ffffff",.14):null,onAccent:d,ok:o?V(Ie[0],o)>=V(Ie[1],o)?Ie[0]:Ie[1]:null},notes:e}}function Pn(n){let e=n.slice(1).toLowerCase();return`#${e.length===3?[...e].map(t=>t+t).join(""):e}`}function ft(n){let e=Pn(n);return[parseInt(e.slice(1,3),16),parseInt(e.slice(3,5),16),parseInt(e.slice(5,7),16)]}function xn(n){let[e,t,r]=ft(n).map(o=>{let s=o/255;return s<=.04045?s/12.92:((s+.055)/1.055)**2.4});return .2126*e+.7152*t+.0722*r}function V(n,e){let[t,r]=[xn(n),xn(e)].sort((o,s)=>s-o);return(t+.05)/(r+.05)}function ro(n){return V(n,"#000000")>V(n,"#ffffff")?"#000000":"#ffffff"}function An(n,e,t){let[r,o]=[ft(n),ft(e)];return`#${r.map((s,i)=>Math.round(s+(o[i]-s)*t).toString(16).padStart(2,"0")).join("")}`}function oo(n,e){for(let t=.3;t>.001;t-=.05){let r=An(n,e,t);if(V(r,e)>=pt)return r}return n}var Te=class{constructor(){c(this,"areas",null);c(this,"key","")}receive(e){let t=Mn(e);if(!t)return!1;let r=JSON.stringify(t);return this.areas&&r===this.key?!1:(this.key=r,this.areas=Object.freeze(t.map(o=>Object.freeze(o))),!0)}};function Dn(n){let e={look:null,notes:["a look is { accent, panel, text } or null"]};if(n==null)return{look:null,notes:[]};if(typeof n!="object")return e;let t={};try{for(let r of["accent","panel","text"]){let o=n[r];o!=null&&(t[r]=typeof o=="string"?o.slice(0,16):"")}}catch{return e}return{look:t,notes:Rn(t).notes}}function Cn(n,e,t){let r=typeof n.vibrate=="function"?n.vibrate.bind(n):null,o=s=>{try{if(!e())return r?r(s):!1;if(!r)return!1;let i=En(Array.isArray(s)?Array.from(s):s);return i?(t(i),!0):!1}catch{return!1}};try{Object.defineProperty(n,"vibrate",{value:o,configurable:!0,writable:!0})}catch{}}var so=["RTCPeerConnection","webkitRTCPeerConnection","mozRTCPeerConnection"];function $n(n){if(n)for(let e of so)try{Object.defineProperty(n,e,{value:void 0,writable:!1,enumerable:!1,configurable:!1})}catch{}}function In(n,e){if($n(n),!!e)for(let t of["contentWindow","contentDocument"])try{let r=Object.getOwnPropertyDescriptor(e.prototype,t),o=r?.get;if(!r||!o)continue;Object.defineProperty(e.prototype,t,{...r,get(){let s=o.call(this);return $n(t==="contentWindow"?s:s?.defaultView),s}})}catch{}}var Tn="0.1.0";function Bn(){let n=globalThis;return n.onceworlds?.__onceworlds||(n.onceworlds=io()),n.onceworlds}function io(){let n=_t(document.currentScript);Sn(),kn({open:l=>E("storage.open",{db:l}),commit:l=>E("storage.commit",l),remove:l=>E("storage.delete",{db:l}),list:()=>E("storage.list",void 0)}),In(window,typeof HTMLIFrameElement>"u"?void 0:HTMLIFrameElement);let e=Lt(),t=mn({stats:l=>x("stats",l)}),r=window.parent!==window,o=r&&qt(location.search)?Vt(console,location.origin):null,s="connecting",i=!r&&Ft(location.search),a=null,u=null,d=1,f=new Map,h=new Map,m=null,w=[],y,k=null,P=0,O=new Set,B=new Te,R=new Set,A=new Set,I=r?Gt(l=>x("clip",l),void 0,()=>m?{phase:m.match.phase,paused:!!m.match.paused,flow:Nt(m.state)}:null):null,W=o?gn(l=>x("snapshot",l)):null,K=new ve(l=>{s!=="standalone"&&E("ui.controls",l).catch(()=>{})},l=>x("input",{touch:l})),U,D=new Promise(l=>U=l),mt=Qt(),ht=Zt(()=>m,mt),Nn={read:l=>E("data.game.get",{key:l}),op:l=>E("data.game.op",l)},jn=en(()=>q().then(l=>l.player),H),Gn=Xt(async()=>(await D,s==="platform"?Nn:jn),mt),je=new Set,Ge=[],gt=l=>{let p=`${l.message}|${l.source}|${l.line}`;je.has(p)||je.size>=S.errorReportsPerPage||(je.add(p),s==="platform"?x("error",l):s==="connecting"&&Ge.push(l))};if(window.addEventListener("error",l=>{if(!(l instanceof ErrorEvent))return;let p=String(l.message||"Error");if(gt({message:p,source:On(l.filename),line:l.lineno||0,column:l.colno||0,stack:l.error instanceof Error?String(l.error.stack??""):""}),o){let g=l.error instanceof Error?`Uncaught ${ke(l.error)}`:/^Uncaught\b/.test(p)?p:`Uncaught ${p}`;o.error(g,{source:On(l.filename),line:l.lineno||0,column:l.colno||0})}}),window.addEventListener("unhandledrejection",l=>{let p=l.reason;o?.error(`Uncaught (in promise) ${p instanceof Error?ke(p):X(p)}`),gt({message:`Unhandled promise rejection: ${p instanceof Error?p.message:String(p)}`,source:"",line:0,column:0,stack:p instanceof Error?String(p.stack??""):""})}),r){window.addEventListener("message",p=>{if(!(p.source!==window.parent||p.data?.type!==Ct||!p.ports[0])&&s!=="standalone"){if(u?.close(),u=p.ports[0],u.onmessage=g=>Hn(g.data),s=Ut(p.data),i=s==="platform"&&zt(p.data),U(),s==="platform")for(let g of Ge.splice(0))x("error",g);else Ge.length=0;o?.connect(g=>x("console",g)),y||(x("alive",{}),y=setInterval(()=>x("alive",{}),2e3)),s==="platform"&&q().then(g=>{e.apply(g.audio),g.settings&&t.apply(g.settings)}).catch(()=>{})}});let l={type:Dt,version:Tn,...n?{build:n}:{}};window.parent.postMessage(l,"*"),setTimeout(()=>{s==="connecting"&&(s="standalone",U())},5e3)}else s="standalone",U();if(window.addEventListener("keydown",l=>{l.key!=="/"||s!=="platform"||!m||uo(l.target)||(l.preventDefault(),l.stopImmediatePropagation(),x("hotkey",{key:"/"}))},!0),r){try{document.documentElement.style.touchAction="pan-x pan-y"}catch{}for(let l of["gesturestart","gesturechange","gestureend"])document.addEventListener(l,p=>p.preventDefault(),{passive:!1})}if(r){let l=p=>{p.pointerType==="mouse"||s!=="platform"||(window.removeEventListener("pointerup",l,!0),E("ui.tapped",void 0).catch(()=>{}))};window.addEventListener("pointerup",l,!0)}if(r&&dn(()=>s==="platform",()=>x("input.first",{})),r&&Cn(navigator,()=>s==="platform",l=>x("vibrate",{pattern:l})),r){let l=Element.prototype.requestFullscreen;Element.prototype.requestFullscreen=function(p){return s!=="platform"?l.call(this,p):(E("ui.fullscreen",void 0).catch(()=>{}),Promise.resolve())}}function Hn(l){if(l.kind==="res"){let g=f.get(l.id);if(!g)return;f.delete(l.id),l.ok?g.resolve(l.result):g.reject(new Error(l.error));return}if(l.kind!=="event")return;let p=l.name;if(p==="room")m?._receive(l.data);else if(p==="room.connection")l.data?.connected===!1&&m?._disconnected();else if(p==="room.closed"){let g=m;m=null,g?._closed(l.data.reason)}else if(p==="room.moved"){let g=m;m=yt(l.data),g?._closed("moved");for(let v of O)try{v(m)}catch(L){console.error('[onceworlds] error in rooms "moved" listener',L)}}else if(p==="audio")e.apply(l.data),ge("audio",l.data);else if(p==="settings")t.apply(l.data);else if(p==="pause"||p==="resume")ge(p);else if(p==="controls")K.receive(l.data);else if(p==="input")K.touch=l.data?.touch===!0;else if(p==="reserved")B.receive(l.data)&&ge("reserved",B.areas);else if(p==="clip")I?.receive(l.data);else if(p==="snapshot")W?.receive(l.data);else if(p==="debug")for(let g of A)try{g(l.data)}catch(v){console.error("[onceworlds] error in the debugger link",v)}else if(p==="player"){let g=l.data;q().then(v=>{g?.id!==v.player.id||typeof g.name!="string"||(v.player.name=g.name,ge("player",v.player))}).catch(()=>{})}}async function E(l,p){await D;let g=u;if(!g)throw new Error("Not connected to Onceworlds");return new Promise((v,L)=>{let b=d++;f.set(b,{resolve:v,reject:L}),g.postMessage({kind:"req",id:b,method:l,params:p})})}function x(l,p){u?.postMessage({kind:"event",name:l,data:p})}function ge(l,...p){for(let g of h.get(l)??[])try{g(...p)}catch(v){console.error(`[onceworlds] error in "${l}" listener`,v)}}function yt(l,p=w){let g={send:(b,C)=>x("room.send",{d:b,to:C}),presence:b=>x("room.presence",{d:b}),state:(b,C,$)=>x("room.state",{k:b,v:C,w:$}),hideLobby:b=>x("room.hideLobby",{hidden:b}),team:(b,C)=>x("room.team",{id:b,team:C}),open:b=>x("room.open",{open:b}),result:b=>x("room.result",{result:b}),kick:b=>x("room.kick",{id:b}),voteKick:b=>x("room.votekick",{id:b}),ready:b=>x("room.ready",{ready:b}),unready:()=>x("room.unready",{}),transfer:b=>x("room.transfer",{id:b}),start:b=>x("room.start",b),end:()=>x("room.end",{}),pause:b=>x("room.pause",{paused:b}),admit:b=>x("room.admit",{ids:b}),private:(b,C,$)=>x("room.private",{k:b,v:C,...$?{id:$}:{}}),dataReset:()=>x("room.datareset",{}),leave:()=>{m===v&&(m=null),E("room.leave",void 0).catch(()=>{})}};w=p;let v=new oe(l,g,()=>Date.now()+P,p);bt(v);let L=un(b=>x("room.idle",{idle:b}));return v.on("reconnect",()=>L.idle&&x("room.idle",{idle:!0})),v.on("close",()=>L.stop()),v}function bt(l){l.on("state",(p,g,v)=>{m===l&&He(p)&&ht._changed(p.slice(z.length),g,v)})}function Kn(l,p){let g={};for(let[$,ee]of Object.entries(_e.all()))g[z+$]=ee;let v={room:"solo",you:l.id,host:l.id,players:[{...l,presence:null,team:p.teams?1:0}],state:g,chat:[],teams:p.teams??0,open:!0,now:Date.now(),ranked:!1,kept:!0,owner:l.id},b={...an(()=>C),state($,ee){He($)&&_e.set($.slice(z.length),ee)},dataReset(){for(let $ of Object.keys(_e.all()))_e.set($,null),C._receive({t:"state",k:z+$,v:null,from:""})}},C=new oe(v,b,()=>Date.now()+P,Fe(p.settings));return bt(C),C}function q(){return k??(k=D.then(()=>s==="platform"?E("session.get",void 0):co()).then(l=>(P=Number(l.timeOffset)||0,l))),k}q().catch(()=>{});let wt={async get(l){return await D,s==="platform"?await E("save.get",{key:l}):Oe.get(l)},async set(l,p){await D,s==="platform"?await E("save.set",{key:l,value:p}):Oe.set(l,p)},async delete(l){await D,s==="platform"?await E("save.delete",{key:l}):Oe.delete(l)},async list(){return await D,s==="platform"?E("save.list",void 0):Oe.list()}},kt={__onceworlds:!0,_debug:o?{send:l=>{u&&x("debug",l)},on:l=>(A.add(l),()=>A.delete(l))}:null,version:Tn,get mode(){return s},ready:()=>D,player:{get:()=>q().then(l=>l.player),async avatarUrl(l,p="full"){let g=await q().catch(()=>null);if(!g?.platformOrigin)return null;let v=typeof l=="string"&&l?l:g.player.id;return`${g.platformOrigin}/avatar/${encodeURIComponent(v)}${p==="head"?"/head":""}.svg`},async avatar(l){if(await D,s!=="platform")return null;let p=typeof l=="string"&&l?l:(await q()).player.id;return Ot.test(p)?St(await E("player.avatar",{id:p}).catch(()=>null)):null},async rename(){return await D,s!=="platform"?null:await E("player.rename",void 0).catch(()=>null)?(await q()).player:null}},game:{info:()=>q().then(l=>l.game)},save:wt,data:{player:wt,server:ht,game:Gn},rooms:{async join(l={}){await D;let p=l.party===!0&&m!==null&&s==="platform";if(p||(m?.leave(),m=null),s!=="platform"){let{player:L}=await q();return m=Kn(L,l),m}let g=await E("room.join",{name:l.name,maxPlayers:l.maxPlayers,mode:l.mode,teams:l.teams,private:l.private,ranked:l.ranked,party:l.party,minPlayers:l.minPlayers,minPlayersPrivate:l.minPlayersPrivate,settings:l.settings,countdown:l.countdown,lobby:l.lobby,...l.ownCountdown===!0?{ownCountdown:!0}:{}}),v=m;return m=yt(g,Fe(l.settings)),p&&v?._closed("moved"),m},get current(){return m},on(l,p){return l!=="moved"?()=>{}:(O.add(p),()=>O.delete(p))}},ratings:{async get(l){return await D,s==="platform"?E("ratings.get",{mode:String(l)}):null},async top(l,p={}){return await D,s==="platform"?E("ratings.top",{mode:String(l),limit:p.limit}):[]}},ui:{setMenuPosition(l){E("ui.menuPosition",{position:l}).catch(()=>{})},get reserved(){return B.areas},setLook(l){let{look:p,notes:g}=Dn(l);for(let v of g)R.has(v)||(R.add(v),console.warn(`[onceworlds] ui.setLook: ${v}`));s!=="standalone"&&E("ui.look",p).catch(()=>{})},requestFullscreen(){s==="platform"?E("ui.fullscreen",void 0).catch(()=>{}):document.documentElement.requestFullscreen?.().catch(()=>{})},showInvite(){s==="platform"&&E("ui.invite",void 0).catch(()=>{})},setOrientation(l){l!=="any"&&l!=="landscape"&&l!=="portrait"||s!=="standalone"&&E("ui.orientation",{orientation:l}).catch(()=>{})}},controls:{set(l){K.set(l)},get stick(){return K.stick},pressed(l){return K.pressed(String(l))},presses(l){return K.presses(String(l))},get touch(){return K.touch}},now:()=>Date.now()+P,leaderboards:{async submit(l,p,g={}){if(await D,s!=="platform")return Be.submit(String(l),Number(p),g.lowerIsBetter===!0);try{return await E("leaderboards.submit",{board:String(l),score:Number(p),lowerIsBetter:g.lowerIsBetter===!0})}catch(v){return console.warn(`[onceworlds] score for "${l}" was not saved: ${v instanceof Error?v.message:v}`),null}},async top(l,p={}){return await D,s!=="platform"?Be.top(String(l)):E("leaderboards.top",{board:String(l),limit:p.limit,lowerIsBetter:p.lowerIsBetter===!0})}},settings:t.settings,audio:{get volume(){return e.volume},get muted(){return e.muted}},badges:{async award(l){if(await D,s!=="platform")return Ne.add(String(l));try{return(await E("badges.award",{key:String(l)})).awarded}catch(p){return console.warn(`[onceworlds] badge "${l}" was not awarded: ${p instanceof Error?p.message:p}`),!1}},async list(){return await D,s==="platform"?E("badges.list",void 0):Ne.list()},async has(l){return(await kt.badges.list()).some(p=>p.key===l&&p.earned)}},demo:{get active(){return i},end(){return a??(a=(async()=>(await D,i?s!=="platform"?(console.info("[onceworlds] demo.end(): the end of the demo. On Onceworlds the platform shows its end-of-demo card here."),!0):E("demo.end",void 0).then(l=>l!==!1,()=>!0):!1))().finally(()=>a=null)),a}},env:ao(),async fetch(l,p={}){if(await D,s!=="platform")throw new Error("onceworlds.fetch only works on Onceworlds, where your secrets are stored. Run the game with `onceworlds dev`.");let g=l instanceof Request?l:null,v=new URL(g?g.url:String(l),location.href).href,L=(p.method??g?.method??"GET").toUpperCase(),b={};new Headers(p.headers??g?.headers).forEach((qn,Un)=>{b[Un]=qn});let C=p.body??null;C===null&&g&&L!=="GET"&&L!=="HEAD"&&(C=await g.arrayBuffer()),C instanceof URLSearchParams&&(b["content-type"]??(b["content-type"]="application/x-www-form-urlencoded;charset=UTF-8"),C=C.toString());let $=await E("net.fetch",{url:v,method:L,headers:b,body:await lo(C)}),ee=[101,204,205,304].includes($.status);return new Response(ee?null:$.body,{status:$.status,statusText:$.statusText,headers:$.headers})},on(l,p){let g=h.get(l);return g||h.set(l,g=new Set),g.add(p),()=>g.delete(p)}};return kt}function ao(){let n=globalThis.__ONCEWORLDS_ENV__,e={};if(n&&typeof n=="object")for(let[t,r]of Object.entries(n))typeof r=="string"&&(e[t]=r);return Object.freeze(e)}async function lo(n){if(n==null)return null;if(typeof n=="string"||n instanceof ArrayBuffer)return n;if(ArrayBuffer.isView(n))return new Uint8Array(n.buffer,n.byteOffset,n.byteLength).slice().buffer;if(n instanceof Blob)return n.arrayBuffer();throw new TypeError("onceworlds.fetch bodies must be a string (e.g. JSON.stringify(...)), bytes or a Blob.")}function On(n){if(!n)return"";try{let e=new URL(n);return e.origin===location.origin?e.pathname.slice(1)||"index.html":e.href}catch{return n}}function uo(n){return n instanceof HTMLElement?n.isContentEditable||["INPUT","TEXTAREA","SELECT"].includes(n.tagName):!1}function co(){let n=H.get("onceworlds:player-id");return n||(n=`local-${Math.random().toString(36).slice(2,10)}`,H.set("onceworlds:player-id",n)),{player:{id:n,name:"Player"},game:{slug:location.hostname.split(".")[0]||"local",name:document.title||"Game",owner:"local"},audio:{volume:1,muted:!1},timeOffset:0}}var Ln="onceworlds:scores",Be={all(){try{let n=JSON.parse(H.get(Ln)??"{}");return n&&typeof n=="object"?n:{}}catch{return{}}},submit(n,e,t){let r=Be.all(),o=r[n],s=o===void 0?e:t?Math.min(o,e):Math.max(o,e);return r[n]=s,H.set(Ln,JSON.stringify(r)),{best:s,rank:1}},top(n){let e=Be.all()[n];if(e===void 0)return{entries:[],me:null};let t={rank:1,player:{id:"local",name:"You"},score:e};return{entries:[t],me:t}}},he="onceworlds:save:",_n="onceworlds:badges",Ne={earned(){try{let n=JSON.parse(H.get(_n)??"{}");return n&&typeof n=="object"?n:{}}catch{return{}}},add(n){let e=Ne.earned();return e[n]?!1:(e[n]=Date.now(),H.set(_n,JSON.stringify(e)),!0)},list(){return Object.entries(Ne.earned()).map(([n,e])=>({key:n,name:n,description:"",icon:null,earned:!0,earnedAt:e}))}},Oe={get(n){let e=H.get(he+n);if(e===null)return null;try{return JSON.parse(e)}catch{return null}},set(n,e){H.set(he+n,JSON.stringify(e??null))},delete(n){H.remove(he+n)},list(){let n=[];try{for(let e=0;e<localStorage.length;e++){let t=localStorage.key(e);t?.startsWith(he)&&n.push(t.slice(he.length))}}catch{}return n.sort()}},Le="onceworlds:server:",_e={all(){let n={};try{for(let e=0;e<localStorage.length;e++){let t=localStorage.key(e);if(t?.startsWith(Le))try{n[t.slice(Le.length)]=JSON.parse(localStorage.getItem(t)??"null")}catch{}}}catch{}return n},set(n,e){e==null?H.remove(Le+n):H.set(Le+n,JSON.stringify(e))}},H={get(n){try{return localStorage.getItem(n)}catch{return null}},set(n,e){try{localStorage.setItem(n,e)}catch{}},remove(n){try{localStorage.removeItem(n)}catch{}}};Bn();})();
package/dist/v1/match.js CHANGED
@@ -661,6 +661,7 @@ function createMatch(room, rules = {}) {
661
661
  let cache = { raw: void 0, rec: null };
662
662
  let lastGood = null;
663
663
  let adoptSince = 0;
664
+ let adopted = false;
664
665
  let confirmed = void 0;
665
666
  let lastTick = null;
666
667
  let ended = "";
@@ -731,7 +732,7 @@ function createMatch(room, rules = {}) {
731
732
  }
732
733
  function acting() {
733
734
  const m = room.match;
734
- return !disposed && room.isHost && m.phase === "playing" && room.running && !!mem && mem.mid === m.id && mem.by === me() && adoptSince === 0;
735
+ return !disposed && room.isHost && m.phase === "playing" && room.running && !!mem && mem.mid === m.id && mem.by === me() && adopted && adoptSince === 0;
735
736
  }
736
737
  function requestTick() {
737
738
  if (tickQueued) return;
@@ -747,6 +748,7 @@ function createMatch(room, rules = {}) {
747
748
  if (!room.isHost || m.phase !== "playing" || !room.running) {
748
749
  adoptSince = 0;
749
750
  lastTick = null;
751
+ if (!room.isHost) adopted = false;
750
752
  return;
751
753
  }
752
754
  let rec = record();
@@ -755,12 +757,13 @@ function createMatch(room, rules = {}) {
755
757
  if (mem && mem.mid === m.id && mem.by === me()) rec = mem;
756
758
  else return beginMatch(m);
757
759
  }
758
- if (!mem || mem.mid !== rec.mid || rec.by !== me()) {
760
+ if (!adopted || !mem || mem.mid !== rec.mid || rec.by !== me()) {
759
761
  const now = Date.now();
760
762
  adoptSince || (adoptSince = now);
761
763
  mem = rec;
762
764
  if (now - adoptSince < ADOPT_MS) return;
763
765
  adoptSince = 0;
766
+ adopted = true;
764
767
  write({});
765
768
  awaySince = /* @__PURE__ */ new Map();
766
769
  guard("match resume", () => rules.resume?.(api), void 0);
@@ -804,6 +807,7 @@ function createMatch(room, rules = {}) {
804
807
  };
805
808
  ended = "";
806
809
  adoptSince = 0;
810
+ adopted = true;
807
811
  beginRound(1);
808
812
  }
809
813
  function beginRound(round) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@onceworlds/cli",
3
- "version": "0.10.0",
3
+ "version": "0.12.0",
4
4
  "description": "Deploy games to Onceworlds.",
5
5
  "homepage": "https://onceworlds.com",
6
6
  "type": "module",