@onceworlds/cli 0.11.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/cli.js CHANGED
@@ -615,6 +615,8 @@ var CONTENT_TYPES = {
615
615
  wgsl: "text/plain; charset=utf-8",
616
616
  pck: "application/octet-stream",
617
617
  data: "application/octet-stream",
618
+ // Ren'Py's web build loads its game from a game.zip.
619
+ zip: "application/zip",
618
620
  woff: "font/woff",
619
621
  woff2: "font/woff2",
620
622
  ttf: "font/ttf",
@@ -6513,6 +6515,7 @@ import { extname, join as join10, resolve as resolve6, sep } from "node:path";
6513
6515
  // ../protocol/src/hosting.ts
6514
6516
  var GAME_FRAME_SANDBOX = "allow-scripts allow-pointer-lock allow-forms allow-orientation-lock";
6515
6517
  var GAME_FRAME_ALLOW = ["autoplay", "gamepad", "screen-wake-lock", "accelerometer", "gyroscope"].map((feature) => `${feature} *`).join("; ");
6518
+ var GAME_STORAGE_BYTES = 100 * 1024 * 1024;
6516
6519
  var GAME_CDNS = ["https://cdn.jsdelivr.net", "https://cdnjs.cloudflare.com", "https://unpkg.com", "https://esm.sh", "https://ga.jspm.io"];
6517
6520
  var GOOGLE_FONTS = { styles: "https://fonts.googleapis.com", files: "https://fonts.gstatic.com" };
6518
6521
  function gameContentSecurityPolicy(options) {
@@ -6542,6 +6545,9 @@ function gameContentSecurityPolicy(options) {
6542
6545
  `sandbox ${GAME_FRAME_SANDBOX}`
6543
6546
  ].join("; ");
6544
6547
  }
6548
+ var BRIDGE_PAGE = "onceworlds:page";
6549
+ var PAGE_WATCH_SCRIPT = `(function(){var n=0,s=function(w,d){if(n++<12)try{parent.postMessage({type:${JSON.stringify(BRIDGE_PAGE)},what:w,detail:String(d).slice(0,200)},"*")}catch(e){}};s("ran",document.readyState);addEventListener("securitypolicyviolation",function(e){s("blocked",e.effectiveDirective+" "+e.blockedURI)});addEventListener("error",function(e){var t=e.target;t&&t.tagName?s("failed",t.tagName+" "+(t.src||t.href)):s("threw",e.message+" "+e.filename+":"+e.lineno)},true);addEventListener("load",function(){s("loaded",typeof onceworlds)})})();`;
6550
+ var PAGE_WATCH_TAG = `<script>${PAGE_WATCH_SCRIPT}</script>`;
6545
6551
  function gameMayReach(url, kind) {
6546
6552
  let parsed;
6547
6553
  try {
@@ -12363,8 +12369,15 @@ function checkProjectConfig(config) {
12363
12369
  return out;
12364
12370
  }
12365
12371
 
12372
+ // ../protocol/src/deploy-files.ts
12373
+ var LARGE_FILE_EXTENSIONS = ["wasm", "pck", "data", "zip"];
12374
+ var DEPLOY_LARGE_FILE_BYTES = 95 * 1024 * 1024;
12375
+ function deployFileLimit(path) {
12376
+ return LARGE_FILE_EXTENSIONS.includes(extensionOf(path)) ? DEPLOY_LARGE_FILE_BYTES : LIMITS.deployFileBytes;
12377
+ }
12378
+
12366
12379
  // src/index.ts
12367
- var CLI_VERSION = "0.11.0";
12380
+ var CLI_VERSION = "0.12.0";
12368
12381
  var PRODUCTION_API = "https://onceworlds.com";
12369
12382
  var LOCAL_API = "http://localhost:8787";
12370
12383
  var USAGE = `Usage:
@@ -12462,7 +12475,7 @@ The project directory needs an onceworlds.json:
12462
12475
  var QUIET_SKIPS = /* @__PURE__ */ new Set(["node_modules", "onceworlds.json", "package.json", "package-lock.json", "tsconfig.json", "jsconfig.json", "LICENSE"]);
12463
12476
  var TEST_FILE = /(?:\.(?:test|spec)\.[cm]?[jt]sx?|^vitest\.config\.[cm]?[jt]s)$/;
12464
12477
  var DEV_FOLDERS = /* @__PURE__ */ new Set(["test", "tests", "__tests__", "coverage"]);
12465
- var QUIET_EXTENSIONS = /* @__PURE__ */ new Set(["md", "ts", "tsx", "jsx", "lock", "lockb", "log", "yml", "yaml", "sh"]);
12478
+ var QUIET_EXTENSIONS = /* @__PURE__ */ new Set(["md", "ts", "tsx", "jsx", "lock", "lockb", "log", "yml", "yaml", "sh", "symbols"]);
12466
12479
  async function main() {
12467
12480
  const { values, positionals } = parseArgs({
12468
12481
  allowPositionals: true,
@@ -12675,8 +12688,9 @@ async function kitPrintOf(projectDir) {
12675
12688
  }
12676
12689
  async function readSources(files) {
12677
12690
  const sources = [];
12691
+ const wasm = new Set(files.filter((f) => /\.wasm$/i.test(f.path)).map((f) => f.path.slice(0, -".wasm".length)));
12678
12692
  for (const file of files) {
12679
- if (!/\.(html?|m?js|css)$/i.test(file.path) || file.size > 15e5) continue;
12693
+ if (!/\.(html?|m?js|css)$/i.test(file.path) || file.size > 15e5 || wasm.has(file.path.replace(/\.m?js$/i, ""))) continue;
12680
12694
  sources.push({ path: file.path, text: await readFile9(file.abs, "utf8") });
12681
12695
  }
12682
12696
  return sources;
@@ -13027,8 +13041,8 @@ async function collectFiles(root) {
13027
13041
  continue;
13028
13042
  }
13029
13043
  const data = await readFile9(abs);
13030
- if (data.byteLength > LIMITS.deployFileBytes) {
13031
- throw new CliError(`${path} is ${formatBytes(data.byteLength)}; files can be at most ${formatBytes(LIMITS.deployFileBytes)}.`);
13044
+ if (data.byteLength > deployFileLimit(path)) {
13045
+ throw new CliError(`${path} is ${formatBytes(data.byteLength)}; files like it can be at most ${formatBytes(deployFileLimit(path))}.`);
13032
13046
  }
13033
13047
  files.push({ path, abs, hash: createHash5("sha256").update(data).digest("hex"), size: data.byteLength });
13034
13048
  }
package/dist/emulator.js CHANGED
@@ -1,4 +1,6 @@
1
- "use strict";(()=>{var Te=["#f6dcc5","#ebc29f","#d4a07a","#b07a55","#875839","#5e3d29","#93c9bb","#a8c595","#94bcd3","#ab9bd9","#dca3ad","#b3bccb"],ce=["#c95f56","#dc8a4f","#e2bd52","#9cc27a","#5a8a5e","#4f9a8e","#6fb7c8","#5b87c5","#465089","#8b68a8","#dc8fae","#f2eee6","#a9a8ad","#5d5c63","#2b2a30","#80604d"],De=["Happy","Grin","Shades","Wink","Surprised","Determined","Joyful","Shy"],Oe=["None","Sprout","Cap","Beanie","Crown","Headphones","Horns","Antenna","Bow","Halo","Party hat","Cat ears","Short hair","Tuft","Bob","Spikes","Bun","Curls","Long","Mop"];var _e=["Plain","Band","Spots","Stripes","Star"];var wo={skin:Te.length,shirt:ce.length,pants:ce.length,face:De.length,hat:Oe.length,top:_e.length},jt=[[5,6],[3,4],[6,7],[9,8],[10,0],[12,13]];function je(t){let e=2166136261;for(let h of t)e=Math.imul(e^h.charCodeAt(0),16777619)>>>0;let o=h=>(e=Math.imul(e^e>>>13,2654435761)>>>0,e%h),r=o(Te.length),n=r>=6?jt[r-6][o(2)]:o(ce.length),a=o(2)===0?n:[8,13,14,15][o(4)],i=o(5)===0?1:12+o(Oe.length-12),s=o(2)===0?0:o(_e.length);return{skin:r,shirt:n,pants:a,face:o(De.length),hat:i,top:s}}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 Be=/^[a-z0-9]{12}$/,V=2;function ge(t){return`${t.mode}.${t.max}.${t.teams}.${t.ranked?1:0}${t.min!==V?`.${t.min}`:""}`}var It=/^pub:([a-z0-9-]+)\.(\d+)\.(\d)\.([01])(?:\.(\d+))?:(\d+)$/;function Ne(t){let e=It.exec(t);if(!e)return null;let o={mode:e[1],max:Number(e[2]),teams:Number(e[3]),ranked:e[4]==="1",min:e[5]===void 0?V:Number(e[5])};return{...o,name:ge(o),n:Number(e[6])}}function Ge(t,e,o){let r=typeof t=="string"?Number(t):t;return typeof r!="number"||!Number.isInteger(r)?Math.min(o,e):Math.min(e,Math.max(1,r))}var Ie=t=>t.replace(/[\u0000-\u001f\u007f]/g," ").replace(/\s+/g," ").trim();var Bt=/^[a-z0-9][a-z0-9-]{0,19}$/;function Ue(t){if(!t||typeof t!="object")return null;let e=t,o=[];for(let n of Array.isArray(e.buttons)?e.buttons:[]){if(o.length>=S.controlButtons)break;let{id:a,label:i}=n??{};if(typeof a!="string"||!Bt.test(a)||o.some(h=>h.id===a))continue;let s=typeof i=="string"?i.replace(/[\u0000-\u001f\u007f]/g,"").replace(/\s+/g," ").trim().slice(0,S.controlLabelLength).trim():"";o.push({id:a,label:s||a})}let r=e.stick===!0;return r||o.length>0?{stick:r,zone:e.zone==="corner"?"corner":"wide",buttons:o}:null}var U="host:ow.settings",Nt=/^[a-z][a-zA-Z0-9]{0,15}$/;function He(t){if(!Array.isArray(t))return[];let e=[];for(let o of t){if(e.length>=6)break;let{id:r,label:n,options:a,default:i}=o??{};if(typeof r!="string"||!Nt.test(r)||e.some(g=>g.id===r)||!Array.isArray(a))continue;let s=[];for(let g of a){let l=typeof g=="object"&&g!==null?g.value:g;if(typeof l!="string"&&typeof l!="number"||typeof l=="number"&&!Number.isFinite(l)||s.length>=8||s.some(m=>m.value===l))continue;let y=typeof g=="object"&&g!==null&&typeof g.label=="string"?g.label:String(l);s.push({value:l,label:Ie(y).slice(0,20)||String(l)})}if(s.length<2)continue;let h=typeof n=="string"?Ie(n).slice(0,24):"";e.push({id:r,label:h||r,options:s,default:s.some(g=>g.value===i)?i:s[0].value})}return e}function Fe(t,e){let o=e!==null&&typeof e=="object"?e[t.id]:void 0;return t.options.some(r=>r.value===o)?o:t.default}var he='{"t":"ping"}';var qe=4001,Ke=4003,Ve=4008,We=4006;var Ye="onceworlds:hello",Je="onceworlds:connect",Gt=/^[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}$/;function Xe(t){let e=t!==null&&typeof t=="object"?t.build:void 0;return typeof e=="string"&&Gt.test(e)?e:null}var Ze="onceworlds-console";var Qe="allow-scripts allow-pointer-lock allow-forms allow-orientation-lock",et=["autoplay","gamepad","screen-wake-lock","accelerometer","gyroscope"].map(t=>`${t} *`).join("; ");var tt=new Set(["server","join","deploy","watch","player","embed","k","console","tester","live","demo",Ze]);function ot(t){return t?.ownCountdown!==!0}var Ut=/^#(?:[0-9a-f]{3}){1,2}$/i,$={panel:"#111216",text:"#f7f7f8",accent:"#d33e00"},ue=4.5,me=3,W=["#4ade80","#15803d"];function nt(t){let e=[];if(t==null)return{look:null,notes:e};if(typeof t!="object")return{look:null,notes:["a look is { accent, panel, text } or null"]};let o=t,r=l=>{let y=o[l];return y==null?null:typeof y=="string"&&Ut.test(y)?at(y):(e.push(`${l} is not #rgb or #rrggbb`),null)},n=r("panel"),a=r("text"),i=r("accent");if(n||a){let l=E(a??$.text,n??$.panel);l<ue&&(e.push(`text on panel is ${l.toFixed(1)}:1, under ${ue}:1: the platform's are used`),n=a=null)}let s=n??$.panel,h=a??$.text;if(i){let l=E(i,s);l<me&&(e.push(`accent on panel is ${l.toFixed(1)}:1, under ${me}:1: the platform's is used`),i=null)}if(!i&&n&&E($.accent,n)<me&&(i=h),!n&&!a&&!i)return{look:null,notes:e};let g=i?Ht(i):null;return{look:{panel:n,text:a,muted:n||a?Ft(h,s):null,accent:i,accentHover:i?it(i,g==="#ffffff"?"#000000":"#ffffff",.14):null,onAccent:g,ok:n?E(W[0],n)>=E(W[1],n)?W[0]:W[1]:null},notes:e}}function at(t){let e=t.slice(1).toLowerCase();return`#${e.length===3?[...e].map(o=>o+o).join(""):e}`}function H(t){let e=at(t);return[parseInt(e.slice(1,3),16),parseInt(e.slice(3,5),16),parseInt(e.slice(5,7),16)]}function rt(t){let[e,o,r]=H(t).map(n=>{let a=n/255;return a<=.04045?a/12.92:((a+.055)/1.055)**2.4});return .2126*e+.7152*o+.0722*r}function E(t,e){let[o,r]=[rt(t),rt(e)].sort((n,a)=>a-n);return(o+.05)/(r+.05)}function Ht(t){return E(t,"#000000")>E(t,"#ffffff")?"#000000":"#ffffff"}function it(t,e,o){let[r,n]=[H(t),H(e)];return`#${r.map((a,i)=>Math.round(a+(n[i]-a)*o).toString(16).padStart(2,"0")).join("")}`}function Ft(t,e){for(let o=.3;o>.001;o-=.05){let r=it(t,e,o);if(E(r,e)>=ue)return r}return t}var Y=class{port=null;handlers;events;onConnect;solo;demo;onActivity;constructor(e,o,r,n,a={}){this.handlers=o,this.events=r,this.onConnect=n,this.solo=a.solo===!0,this.demo=a.demo===!0,this.onActivity=a.onActivity??null,window.addEventListener("message",i=>{i.source!==e.contentWindow||i.origin!=="null"||i.data?.type===Ye&&this.connect(i.source,Xe(i.data))})}activity(e,o){try{this.onActivity?.(e,o)}catch{}}emit(e,o){this.port?.postMessage({kind:"event",name:e,data:o})}connect(e,o){this.port?.close();let r=new MessageChannel,n=r.port1;this.port=n,n.onmessage=i=>this.receive(n,i.data);let a={type:Je,...this.solo?{solo:!0}:{},...this.demo?{demo:!0}:{}};e.postMessage(a,"*",[r.port2]),this.onConnect(o)}async receive(e,o){if(!(e!==this.port||!o||typeof o!="object")){if(o.kind==="event"){Object.hasOwn(this.events,o.name)&&(this.events[o.name](o.data),this.activity(String(o.name),null));return}if(o.kind==="req")try{if(!Object.hasOwn(this.handlers,o.method))throw new Error(`Unknown method: ${String(o.method)}`);let r=this.handlers[o.method],n=await r(o.params);e.postMessage({kind:"res",id:o.id,ok:!0,result:n??null}),this.activity(String(o.method),null)}catch(r){let n=r instanceof Error?r.message:String(r);e.postMessage({kind:"res",id:o.id,ok:!1,error:n}),this.activity(String(o.method),n)}}}};var J=class{pressed=new Set;press(e){this.pressed.add(e)}take(e){let o=new Set(e),r=!1;for(let n of this.pressed)o.has(n)||(o.add(n),r=!0);return this.pressed.clear(),{buttons:[...o],owed:r}}};var st=["--ow-panel","--ow-face-edge","--ow-hover","--ow-on-accent","--text","--muted","--line","--line-strong","--fill","--fill-strong","--ok","--accent-fill","--accent-fill-hover","--accent-hover"],lt=["--ow-ctl-edge","--ow-ctl-fill","--ow-ctl-stick","--ow-ctl-knob","--ow-ctl-label","--ow-ctl-shadow","--ow-ctl-held","--ow-ctl-main","--ow-ctl-main-edge","--ow-ctl-main-label","--ow-ctl-main-shadow","--ow-ctl-main-held"];function x(t,e){return`rgba(${H(t).join(", ")}, ${e})`}function pt(t){let e={};if(!t)return e;if(t.panel&&(e["--ow-panel"]=t.panel,e["--ow-face-edge"]=t.panel),t.ok&&(e["--ok"]=t.ok),t.panel||t.text){let o=t.text??$.text;t.text&&(e["--text"]=t.text),t.muted&&(e["--muted"]=t.muted),e["--line"]=x(o,.09),e["--line-strong"]=x(o,.16),e["--fill"]=x(o,.06),e["--fill-strong"]=x(o,.1),e["--ow-hover"]=x(o,.16)}return t.accent&&t.accentHover&&t.onAccent&&(e["--accent-fill"]=t.accent,e["--accent-fill-hover"]=t.accentHover,e["--accent-hover"]=t.accent,e["--ow-on-accent"]=t.onAccent),e}function dt(t){let e={};return t&&(t.text&&(e["--ow-ctl-edge"]=x(t.text,.4),e["--ow-ctl-knob"]=x(t.text,.9),e["--ow-ctl-label"]=t.text,e["--ow-ctl-held"]=x(t.text,.35)),t.panel&&(e["--ow-ctl-fill"]=x(t.panel,.4),e["--ow-ctl-stick"]=x(t.panel,.3),e["--ow-ctl-shadow"]=x(t.panel,.5)),t.accent&&t.accentHover&&t.onAccent&&(e["--ow-ctl-main"]=x(t.accent,.85),e["--ow-ctl-main-edge"]=t.accent,e["--ow-ctl-main-label"]=t.onAccent,e["--ow-ctl-main-shadow"]="none",e["--ow-ctl-main-held"]=t.accentHover)),e}function X(t,e,o){for(let r of e)Object.hasOwn(o,r)?t.style.setProperty(r,o[r]):t.style.removeProperty(r);t.toggleAttribute("data-look",e.some(r=>Object.hasOwn(o,r)))}var M=52,xe=.12,fe=96,qt=400,Kt=2e4,Z=class{parent;root;zone;base;knob;buttonBox;send;onLayout;layout=null;touch;blocked=!1;keyboard=!1;stickPointer=null;center={x:0,y:0};x=0;y=0;buttons=new Map;held=new Map;fingers=new Map;report=new J;queued=0;sent="";placed={stick:null,buttons:null};constructor(e,o,r=()=>{}){this.send=o,this.onLayout=r,this.parent=e,this.touch=matchMedia("(pointer: coarse)").matches,this.root=L("div","ow-controls"),this.root.hidden=!0,this.zone=L("div","ow-stick-zone"),this.base=L("div","ow-stick"),this.knob=L("div","ow-stick-knob"),this.base.append(this.knob),this.zone.append(this.base),this.buttonBox=L("div","ow-control-buttons"),this.root.append(this.zone,this.buttonBox),e.append(this.root),this.zone.addEventListener("pointerdown",n=>this.stickDown(n)),this.zone.addEventListener("pointermove",n=>this.stickMove(n));for(let n of["pointerup","pointercancel","lostpointercapture"])this.zone.addEventListener(n,a=>this.stickUp(a));this.root.addEventListener("contextmenu",n=>n.preventDefault())}setLayout(e){this.layout=Ue(e);let o=this.buttons;this.buttons=new Map,(this.layout?.buttons??[]).forEach((r,n)=>{let a=o.get(r.id)??this.button(r.id);o.delete(r.id),a.className=`ow-control-btn ow-control-btn-${n}`,a.classList.toggle("ow-held",[...this.held.values()].includes(r.id)),a.textContent=r.label,a.isConnected||this.buttonBox.append(a),this.buttons.set(r.id,a)});for(let[r,n]of o){for(let[a,i]of this.held)i===r&&this.letGo(a);n.remove()}this.zone.hidden=!this.layout?.stick,this.zone.classList.toggle("ow-stick-corner",this.layout?.zone==="corner"),this.zone.hidden&&this.stickPointer!==null&&this.letGo(this.stickPointer),this.render(),this.onLayout()}setLook(e){X(this.root,lt,e)}reservedBoxes(){if(this.root.hidden)return this.blocked&&this.layout&&this.touch&&!this.keyboard?this.placed:{stick:null,buttons:null};let e=this.zone.hidden?null:gt(this.base),o=null;for(let r of this.buttons.values()){let n=gt(r);!n.width||!n.height||(o=o?Wt(o,n):n)}return this.placed={stick:e,buttons:o},this.placed}setTouch(e){this.touch=e,this.render()}setKeyboard(e){this.keyboard=e,this.render()}setBlocked(e){this.blocked=e,this.render()}render(){let e=!!this.layout&&this.touch&&!this.blocked&&!this.keyboard;this.root.hidden!==!e&&(e||this.reset(),this.root.hidden=!e,this.onLayout())}reset(){for(let e of[...this.held.keys()])this.letGo(e);this.stickPointer!==null&&this.letGo(this.stickPointer),this.endStick()}letGo(e){e===this.stickPointer&&this.endStick();let o=this.held.get(e);this.held.delete(e),o!==void 0&&![...this.held.values()].includes(o)&&this.buttons.get(o)?.classList.remove("ow-held");let r=this.fingers.get(e);this.fingers.delete(e),r&&Vt(this.parent,e,r),this.changed()}button(e){let o=L("button","ow-control-btn");o.type="button",o.tabIndex=-1,o.addEventListener("pointerdown",n=>{n.preventDefault(),ct(o,n.pointerId),o.classList.add("ow-held"),this.held.set(n.pointerId,e),this.report.press(e),this.fingers.set(n.pointerId,{x:n.clientX,y:n.clientY}),this.changed()}),o.addEventListener("pointermove",n=>{this.held.get(n.pointerId)===e&&this.fingers.set(n.pointerId,{x:n.clientX,y:n.clientY})});let r=n=>{this.held.get(n.pointerId)===e&&(this.held.delete(n.pointerId),this.fingers.delete(n.pointerId),[...this.held.values()].includes(e)||o.classList.remove("ow-held"),this.changed())};for(let n of["pointerup","pointercancel","lostpointercapture"])o.addEventListener(n,a=>r(a));return o}stickDown(e){if(this.stickPointer!==null)return;e.preventDefault(),ct(this.zone,e.pointerId),this.stickPointer=e.pointerId,this.fingers.set(e.pointerId,{x:e.clientX,y:e.clientY});let o=this.zone.getBoundingClientRect(),r=this.base.getBoundingClientRect(),n=M+8;this.center={x:Math.min(Math.max(e.clientX,o.left+n),o.right-n),y:Math.min(Math.max(e.clientY,o.top+n),o.bottom-n)},this.base.style.transform=`translate(${this.center.x-(r.left+r.width/2)}px, ${this.center.y-(r.top+r.height/2)}px)`,this.base.classList.add("ow-active"),this.stickMove(e)}stickMove(e){if(e.pointerId!==this.stickPointer)return;this.fingers.set(e.pointerId,{x:e.clientX,y:e.clientY});let o=e.clientX-this.center.x,r=e.clientY-this.center.y,n=Math.hypot(o,r);n>M&&(o=o/n*M,r=r/n*M),this.knob.style.transform=`translate(${o}px, ${r}px)`;let a=Math.min(n,M)/M,i=a<xe?0:(a-xe)/(1-xe)/(a||1);this.x=ht(o/M*i),this.y=ht(r/M*i),this.changed()}stickUp(e){e.pointerId===this.stickPointer&&(this.fingers.delete(e.pointerId),this.endStick())}endStick(){this.stickPointer=null,this.x=0,this.y=0,this.base.classList.remove("ow-active"),this.base.style.transform="",this.knob.style.transform="",this.changed()}changed(){this.queued||(this.queued=requestAnimationFrame(()=>{this.queued=0;let{buttons:e,owed:o}=this.report.take(this.held.values()),r={x:this.x,y:this.y,buttons:e};o&&this.changed();let n=JSON.stringify(r);n!==this.sent&&(this.sent=n,this.send(r))}))}};function Vt(t,e,o){let r=L("div","ow-tap-shield");r.style.left=`${o.x-fe/2}px`,r.style.top=`${o.y-fe/2}px`,r.style.width=r.style.height=`${fe}px`,t.append(r);let n=setTimeout(()=>r.remove(),Kt),a=()=>{clearTimeout(n),n=setTimeout(()=>r.remove(),qt)};for(let i of["pointerup","pointercancel","lostpointercapture"])r.addEventListener(i,s=>s.pointerId===e&&a());r.addEventListener("contextmenu",i=>i.preventDefault());try{r.setPointerCapture(e)}catch{a()}}function ct(t,e){try{t.setPointerCapture(e)}catch{}}function gt(t){let e=t.getBoundingClientRect(),o=getComputedStyle(t).transform;if(!o||o==="none")return e;let r=new DOMMatrixReadOnly(o);if(r.b||r.c||!r.a||!r.d)return e;let n=e.width/Math.abs(r.a),a=e.height/Math.abs(r.d),i=e.left+e.width/2-r.e,s=e.top+e.height/2-r.f;return{left:i-n/2,top:s-a/2,width:n,height:a}}function Wt(t,e){let o=Math.min(t.left,e.left),r=Math.min(t.top,e.top);return{left:o,top:r,width:Math.max(t.left+t.width,e.left+e.width)-o,height:Math.max(t.top+t.height,e.top+e.height)-r}}function ht(t){return Math.round(t*1e3)/1e3}function L(t,e,o){let r=document.createElement(t);return r.className=e,o!==void 0&&(r.textContent=o),r}function Yt(t,e){return t!=="lobby"?{surface:t,hidden:!1}:{surface:e?"none":"lobby",hidden:e}}var be=t=>Math.max(0,Math.ceil(t/1e3)),we=t=>{let e=t.slice(0,2).map(o=>o.name);return t.length>2?`${e.join(", ")} +${t.length-2}`:e.join(", ")};function Jt(t){let{you:e,host:o,kind:r,match:n,now:a}=t,i=[...t.players].sort((p,k)=>p.id===e?-1:k.id===e?1:p.id===o?-1:k.id===o?1:p.name.localeCompare(k.name)).map(p=>({id:p.id,name:p.name,ready:!!p.ready,host:p.id===o,you:p.id===e,away:p.connected===!1,idle:p.connected!==!1&&!!p.idle})),s=t.players.filter(p=>p.connected!==!1),h=t.players.find(p=>p.id===e),g=o===e&&n.phase==="lobby",l=t.schema.map(p=>({id:p.id,label:p.label,value:Fe(p,t.written),options:p.options,editable:g})),y={n:s.filter(p=>p.ready||r!=="public"&&p.id===o).length,of:s.length},m={surface:"none",rows:i,count:`${t.players.length} / ${t.max}`,ready:y,status:"",action:{kind:"none",label:"",disabled:!0},settings:l,seconds:null},Ce=n.participants?.includes(e)??!1,Ae=o===e&&r!=="public";if(n.phase==="starting"){if(!Ce)return{...m,surface:"watching",status:"Watching"};let p=Ae?{kind:"stop",label:"Stop",disabled:!1}:{kind:"unready",label:"Not ready",disabled:!1};return t.ownCountdown?{...m,surface:"countdown",action:p,seconds:null,status:"Get ready"}:{...m,surface:"countdown",action:p,seconds:Math.max(1,be((n.startsAt??a)-a)),status:"Get ready"}}if(n.phase==="playing"){if(n.paused){let p=s.filter(k=>n.participants?.includes(k.id)).length;return n.paused.reason==="host"?{...m,surface:"paused",status:"Paused"}:{...m,surface:"paused",seconds:be(n.paused.since+S.matchAbandonMs-a),status:`Waiting for players \xB7 ${p} / ${n.min}`}}return Ce?m:{...m,surface:"watching",status:"Watching"}}let P=s.filter(p=>!p.ready&&(r==="public"||p.id!==o));if(m.surface="lobby",Ae){let p=s.length<n.min;return m.action={kind:"start",label:"Start",disabled:p||P.length>0},m.status=p?`Need ${n.min} players`:P.length?`Waiting for ${we(P)}`:"",m}if(m.action={kind:h?.ready?"unready":"ready",label:h?.ready?"Not ready":"Ready",disabled:!1},r==="public")s.length<n.min?m.status=`Need ${n.min} players`:n.waitUntil!==void 0&&P.length?(m.seconds=be(n.waitUntil-a),m.status=`${we(P)} \xB7 ${m.seconds}s`):m.status=`${s.length-P.length} / ${s.length} ready`;else{let p=P.filter(k=>k.id!==e);m.status=h?.ready?p.length?`Waiting for ${we(p)}`:`Waiting for ${t.players.find(k=>k.id===o)?.name??"the host"}`:""}return m}function c(t,e="",o){let r=document.createElement(t);return e&&(r.className=e),o!==void 0&&(r.textContent=o),r}var Q=class{mode=null;ownCountdown=!1;hiddenByGame=!1;state=null;schema=[];timer=0;opts;root;card;title;count;list;settingsBox;status;action;invite;bar;barFaces;barStatus;barAction;countdown;numeral;cancel;pause;pauseStatus;pauseTimer;chip;last=null;lastNumeral=-1;listSignature="";settingsSignature="";faceSignature="";constructor(e,o){this.opts=o,this.root=c("div","ow-lobby"),this.root.hidden=!0,this.card=c("section","ow-lobby-card"),this.card.setAttribute("aria-label","Lobby");let r=c("header","ow-lobby-head");this.title=c("h2","","Lobby"),this.count=c("span","ow-lobby-count"),r.append(this.title,this.count),this.list=c("ul","ow-lobby-players"),this.settingsBox=c("div","ow-lobby-settings"),this.status=c("p","ow-lobby-status"),this.status.setAttribute("role","status"),this.action=this.button("ow-btn ow-btn-primary ow-lobby-action",()=>this.press()),this.invite=this.button("ow-btn ow-lobby-invite",()=>this.opts.onInvite()),this.invite.textContent="Invite";let n=c("div","ow-lobby-actions");n.append(this.action,this.invite),this.card.append(r,this.list,this.settingsBox,this.status,n),this.bar=c("div","ow-lobby-bar"),this.barFaces=c("span","ow-lobby-faces"),this.barStatus=c("span","ow-lobby-bar-status"),this.barStatus.setAttribute("role","status"),this.barAction=this.button("ow-btn ow-btn-primary ow-lobby-action",()=>this.press()),this.bar.append(this.barFaces,this.barStatus,this.barAction),this.countdown=c("div","ow-lobby-countdown"),this.numeral=c("b"),this.numeral.setAttribute("aria-hidden","true");let a=c("span","","Get ready");a.setAttribute("aria-hidden","true"),this.cancel=this.button("ow-btn ow-lobby-cancel",()=>this.press()),this.countdown.append(this.numeral,a,this.cancel),this.pause=c("div","ow-lobby-pause");let i=c("div","ow-lobby-pause-box");this.pauseStatus=c("p","ow-lobby-pause-status"),this.pauseStatus.setAttribute("role","status"),this.pauseTimer=c("p","ow-lobby-pause-timer"),i.append(this.pauseStatus,this.pauseTimer),this.pause.append(i),this.chip=c("div","ow-lobby-chip"),this.chip.setAttribute("role","status"),this.root.append(this.card,this.bar,this.countdown,this.pause,this.chip),e.append(this.root)}setSchema(e){this.schema=e,this.render()}enable(e,o={}){this.mode=e,this.ownCountdown=o.ownCountdown===!0,this.root.dataset.mode=e??"",e||this.reset(),this.render()}setLook(e){X(this.root,st,e)}reservedBox(){if(this.root.hidden)return null;let e=!this.countdown.hidden&&this.countdown.classList.contains("ow-lobby-countdown-bare"),o=this.bar.hidden?e&&!this.cancel.hidden?this.cancel:null:this.bar;return o?o.getBoundingClientRect():null}setHidden(e){this.hiddenByGame=e,this.render()}setRoom(e,o=0){if(!e)return this.reset();this.state={you:e.you,host:e.host,kind:e.room.startsWith("private:")?"private":e.room.startsWith("room:")?"named":"public",max:Math.max(o,e.players.length),players:e.players.map(r=>({...r})),match:e.match??{phase:"lobby",n:0,min:1},written:e.state?.[U]},this.render()}handle(e){let o=this.state;if(o){switch(e.t){case"join":o.players=[...o.players.filter(r=>r.id!==e.player.id),{...e.player}];break;case"leave":o.players=o.players.filter(r=>r.id!==e.id);break;case"away":o.players=o.players.map(r=>r.id===e.id?{...r,connected:!1}:r);break;case"back":o.players=o.players.map(r=>{if(r.id!==e.id)return r;let{connected:n,...a}=r;return a});break;case"ready":o.players=o.players.map(r=>{if(r.id!==e.id)return r;let{ready:n,...a}=r;return e.ready?{...a,ready:!0}:a});break;case"unready":o.players=o.players.map(({ready:r,...n})=>n);break;case"host":o.host=e.id;break;case"idle":o.players=o.players.map(r=>{if(r.id!==e.id)return r;let{idle:n,...a}=r;return e.idle?{...a,idle:!0}:a});break;case"name":o.players=o.players.map(r=>r.id===e.id?{...r,name:e.name}:r);break;case"match":o.match=e.match;break;case"state":if(e.k!==U)return;o.written=e.v;break;default:return}this.render()}}chooseSetting(e,o){let r=this.state,n=this.schema.find(i=>i.id===e);if(!r||!n||!n.options.some(i=>i.value===o))return null;let a={...r.written!==null&&typeof r.written=="object"?r.written:{},[e]:o};return r.written=a,this.render(),a}setReadyLocal(e){let o=this.state?.players.find(r=>r.id===this.state?.you);o&&(e?o.ready=!0:delete o.ready,this.render())}button(e,o){let r=c("button",e);return r.type="button",r.addEventListener("pointerdown",n=>n.preventDefault()),r.addEventListener("click",o),r}press(){let e=this.last?.action.kind;e==="start"?this.opts.onStart():e==="stop"?this.opts.onStop():e==="ready"?(this.setReadyLocal(!0),this.opts.onReady(!0)):e==="unready"&&(this.setReadyLocal(!1),this.opts.onReady(!1))}reset(){this.state=null,this.last=null,this.hiddenByGame=!1,window.clearInterval(this.timer),this.timer=0,this.root.hidden=!0,this.opts.onLayout?.()}render(){this.draw(),this.opts.onLayout?.()}draw(){if(!this.mode||!this.state){this.root.hidden=!0;return}let e=Jt({...this.state,schema:this.schema,now:this.opts.now(),ownCountdown:this.ownCountdown});this.last=e;let o=Yt(e.surface,this.hiddenByGame);this.hiddenByGame=o.hidden;let r=o.surface==="lobby";if(this.root.hidden=o.surface==="none",this.card.hidden=!(r&&this.mode==="card"),this.bar.hidden=!(r&&this.mode==="bar"),this.countdown.hidden=e.surface!=="countdown",this.countdown.classList.toggle("ow-lobby-countdown-bare",e.surface==="countdown"&&e.seconds===null),this.pause.hidden=e.surface!=="paused",this.chip.hidden=e.surface!=="watching",this.root.classList.toggle("ow-lobby-dim",r&&this.mode==="card"),r&&this.mode==="card"&&this.renderCard(e),r&&this.mode==="bar"&&this.renderBar(e),e.surface==="countdown"&&e.seconds!==null&&e.seconds!==this.lastNumeral&&(this.lastNumeral=e.seconds,this.numeral.textContent=String(e.seconds),this.numeral.style.animation="none",this.numeral.offsetWidth,this.numeral.style.animation=""),e.surface==="countdown"&&(this.cancel.textContent=e.action.label),e.surface!=="countdown"&&(this.lastNumeral=-1),e.surface==="paused"&&(this.pauseStatus.textContent=e.status,this.pauseTimer.textContent=e.seconds!==null?`Ends in ${Xt(e.seconds)}`:""),e.surface==="watching"){let[a,...i]=e.status.split(" \xB7 "),s=c("span","ow-lobby-chip-more",i.length?` \xB7 ${i.join(" \xB7 ")}`:"");this.chip.replaceChildren(a,s)}let n=e.seconds!==null;n&&!this.timer?this.timer=window.setInterval(()=>this.render(),250):!n&&this.timer&&(window.clearInterval(this.timer),this.timer=0)}renderCard(e){this.count.textContent=e.count,this.settingsBox.hidden=e.settings.length===0,this.status.textContent=e.status,this.status.hidden=e.status==="",this.setAction(this.action,e);let o=JSON.stringify(e.settings);o!==this.settingsSignature&&(this.settingsSignature=o,this.settingsBox.replaceChildren(...e.settings.map(n=>this.settingRow(n))));let r=JSON.stringify(e.rows);r!==this.listSignature&&(this.listSignature=r,this.list.replaceChildren(...e.rows.map(n=>{let a=c("li",n.away||n.idle?"ow-lobby-away":n.ready?"ow-lobby-ready":""),i=c("img","ow-headshot");i.src=`/avatar/${encodeURIComponent(n.id)}/head.svg`,i.alt="";let s=c("span","ow-lobby-name",n.name),h=[n.away?"Reconnecting":n.idle?"Idle":"",n.you?"You":"",n.host?"Host":""].filter(Boolean).join(" \xB7 ");return a.append(i,s),h&&a.append(c("span","ow-player-notes",h)),a.append(c("span",`ow-lobby-check${n.ready?" ow-lobby-check-on":""}`,n.ready?"Ready":"")),a})))}settingRow(e){let o=c("div","ow-lobby-setting");if(o.append(c("span","ow-lobby-setting-label",e.label)),!e.editable)return o.append(c("span","ow-lobby-setting-value",e.options.find(n=>n.value===e.value)?.label??String(e.value))),o;let r=c("div","ow-segments");r.setAttribute("role","radiogroup"),r.setAttribute("aria-label",e.label);for(let n of e.options){let a=this.button(`ow-segment${n.value===e.value?" ow-segment-on":""}`,()=>this.opts.onSetting(e.id,n.value));a.textContent=n.label,a.setAttribute("role","radio"),a.setAttribute("aria-checked",String(n.value===e.value)),r.append(a)}return o.append(r),o}renderBar(e){this.barStatus.textContent=e.status||`${e.ready.n} / ${e.ready.of} ready`,this.setAction(this.barAction,e);let o=JSON.stringify(e.rows.slice(0,5).map(r=>[r.id,r.ready]));o!==this.faceSignature&&(this.faceSignature=o,this.barFaces.replaceChildren(...e.rows.slice(0,5).map(r=>{let n=c("img",`ow-headshot${r.ready?" ow-lobby-face-ready":""}`);return n.src=`/avatar/${encodeURIComponent(r.id)}/head.svg`,n.alt="",n})))}setAction(e,o){e.hidden=o.action.kind==="none",e.textContent=o.action.label,e.disabled=o.action.disabled,e.classList.toggle("ow-btn-primary",o.action.kind!=="unready")}};function Xt(t){return`${Math.floor(t/60)}:${String(t%60).padStart(2,"0")}`}function mt(t,e){let o=[];for(let{kind:r,box:n}of e){if(!n||!(n.width>0)||!(n.height>0))continue;let a=Math.max(0,n.left-t.left),i=Math.max(0,n.top-t.top),s=Math.min(t.width,n.left+n.width-t.left),h=Math.min(t.height,n.top+n.height-t.top);if(!(s-a>.01&&h-i>.01))continue;let g=Math.floor(a+.01),l=Math.floor(i+.01);o.push({kind:r,x:g,y:l,w:Math.ceil(s-.01)-g,h:Math.ceil(h-.01)-l})}return o}var ee=class{measure;send;nextFrame;queued=!1;sent=null;constructor(e,o,r=n=>requestAnimationFrame(n)){this.measure=e,this.send=o,this.nextFrame=r}changed(){this.queued||(this.queued=!0,this.nextFrame(()=>{this.queued=!1;let e=this.measure();if(!e)return;let o=JSON.stringify(e);o!==this.sent&&(this.sent=o,this.send(e))}))}resend(){this.sent=null,this.changed()}};var ve=t=>`ow:resume:${t}`;function T(t,e){try{e?sessionStorage.setItem(ve(t),JSON.stringify({...e,at:Date.now()})):sessionStorage.removeItem(ve(t))}catch{}}function ut(t){try{let e=sessionStorage.getItem(ve(t));if(!e)return null;let o=performance.getEntriesByType("navigation")[0];if(o&&o.type!=="reload"&&o.type!=="back_forward")return te(t);let r=JSON.parse(e);return typeof r.key!="string"||typeof r.rejoin!="string"||typeof r.at!="number"||Date.now()-r.at>18e4||Number(r.rejoin.split(".")[0])*1e3<Date.now()?te(t):{key:r.key,rejoin:r.rejoin}}catch{return null}}var Zt=t=>`ow:own-server:${t}`;function xt(t,e){try{sessionStorage.setItem(Zt(t),e)}catch{}}function te(t){return T(t,null),null}var oe=class extends Error{constructor(o,r=0,n=0,a=""){super(o);this.status=r;this.retryAfterMs=n;this.code=a;this.name="RequestError"}status;retryAfterMs;code;get retryable(){return this.status===0||this.status===408||this.status===429||this.status>=500}};var re=class{constructor(e=48*1024){this.max=e}max;used=0;async run(e,o){let r=new TextEncoder().encode(e).byteLength;if(this.used+r>this.max)throw new oe("Progress is waiting to sync when you return to the game.");this.used+=r;try{return await o()}finally{this.used-=r}}};var ye=/^[2-9]$/.test(new URLSearchParams(location.search).get("player")??"")?new URLSearchParams(location.search).get("player"):null;var Qt=null;function ft(){return Qt?.n??null}var Zo=new re;var bt=[300,700,1500,3e3,5e3,8e3],eo=9e4,to=1e4,vt=()=>Array.from(crypto.getRandomValues(new Uint8Array(10)),t=>"abcdefghijklmnopqrstuvwxyz0123456789"[t%36]).join(""),yt=vt();function kt(){yt=vt()}var wt=null;var St=!1;function zt(t){St=t}var oo=5e4,ro=4e3,ne=class{ws=null;key=null;rejoin=null;you="";closed=!1;attempt=0;droppedAt=0;sleeping=!1;lastHeard=0;heardCount=0;pingAt=0;hintedHidden=!1;pingTimer=0;watchTimer=0;retryTimer=0;page=yt;slug;options;callbacks;onVisible=()=>{this.hint(),document.visibilityState==="visible"&&this.wake()};onOnline=()=>this.wake();onShow=e=>e.persisted&&this.wake();onHide=()=>this.hint();constructor(e,o,r){this.slug=e,this.options=o,this.callbacks=r,this.key=o.key??null,this.rejoin=o.rejoin??null,document.addEventListener("visibilitychange",this.onVisible),addEventListener("online",this.onOnline),addEventListener("pageshow",this.onShow),addEventListener("pagehide",this.onHide)}join(){return new Promise((e,o)=>this.open(e,o))}send(e){this.ws?.readyState===WebSocket.OPEN&&this.ws.send(JSON.stringify(e))}hint(){let e=document.visibilityState==="hidden";e===this.hintedHidden||this.ws?.readyState!==WebSocket.OPEN||(this.hintedHidden=e,this.send({t:"vis",hidden:e}))}ping(){let e=this.ws;e?.readyState===WebSocket.OPEN&&(this.pingAt&&Date.now()-this.pingAt<5e3||(this.pingAt=Date.now(),e.send(he)))}close(){this.closed=!0,T(this.slug,null),this.dispose(),this.ws?.close(1e3)}reload(){return this.closed=!0,this.dispose(),this.ws?.close(We,"Updating"),this.key?.startsWith("pub:")&&this.rejoin?{key:this.key,rejoin:this.rejoin}:null}open(e,o){this.retryTimer=0;let r=new URL(`/api/games/${this.slug}/rooms/connect`,location.href);r.protocol=location.protocol==="https:"?"wss:":"ws:",this.key?(r.searchParams.set("key",this.key),this.rejoin&&r.searchParams.set("rejoin",this.rejoin)):this.options.server?(r.searchParams.set("server",this.options.server),this.options.private&&r.searchParams.set("own","1")):this.options.name?r.searchParams.set("name",this.options.name):(this.options.mode&&r.searchParams.set("mode",this.options.mode),this.options.follow&&r.searchParams.set("follow",this.options.follow)),this.options.maxPlayers&&r.searchParams.set("max",String(this.options.maxPlayers)),this.options.minPlayers&&r.searchParams.set("min",String(this.options.minPlayers)),this.options.countdown!==void 0&&r.searchParams.set("countdown",String(this.options.countdown)),this.options.teams&&r.searchParams.set("teams",String(this.options.teams)),this.options.ranked&&r.searchParams.set("ranked","1"),ye&&r.searchParams.set("devplayer",ye);let n=ft();n&&r.searchParams.set("tester",n),r.searchParams.set("page",this.page),this.options.build&&r.searchParams.set("build",this.options.build),wt&&r.searchParams.set("pass",wt),St&&r.searchParams.set("demo","1");let a=new WebSocket(r);this.ws=a,this.lastHeard=Date.now();let i=!1;a.onopen=()=>{this.lastHeard=Date.now(),window.clearInterval(this.pingTimer),window.clearInterval(this.watchTimer),this.pingTimer=window.setInterval(()=>a.readyState===WebSocket.OPEN&&this.ping(),to),this.watchTimer=window.setInterval(()=>{a===this.ws&&a.readyState===WebSocket.OPEN&&Date.now()-this.lastHeard>oo&&this.lost(a)},5e3)},a.onmessage=g=>{this.lastHeard=Date.now(),this.heardCount++;let l;try{l=JSON.parse(g.data)}catch{return}if(l.t==="pong"){this.pingAt&&this.callbacks.onRtt?.(Date.now()-this.pingAt),this.pingAt=0;return}if(l.t==="welcome"&&(l.rejoin&&(this.rejoin=l.rejoin),delete l.rejoin,l.room.startsWith("pub:")&&this.rejoin&&T(this.slug,{key:l.room,rejoin:this.rejoin})),l.t==="leave"&&l.kicked&&l.id===this.you){this.close(),this.finish("kicked");return}if(l.t==="welcome"&&(this.hintedHidden=!1,this.hint()),l.t==="welcome"&&!i&&(i=!0,this.key=l.room,this.you=l.you,this.attempt=0,this.droppedAt&&(this.droppedAt=0,this.callbacks.onConnection?.(!0)),e)){let{t:y,...m}=l;e(m),e=void 0;return}this.callbacks.onMessage(l)};let s=!1,h=g=>{if(!s&&(s=!0,window.clearInterval(this.pingTimer),window.clearInterval(this.watchTimer),!(this.closed||a!==this.ws))){if(g.code===qe)return this.finish("replaced");if(g.code===Ve&&i&&document.visibilityState==="hidden"){this.sleeping=!0,this.droppedAt||(this.droppedAt=Date.now(),this.callbacks.onConnection?.(!1));return}if(g.code===Ke){if(i||!o)return this.finish("kicked");this.closed=!0,this.dispose(),T(this.slug,null),o(Object.assign(new Error("You were removed from this server."),{kicked:!0}));return}if(!i&&o){this.closed=!0,this.dispose(),o(new Error(this.options.name||this.options.server?"Could not join that server. It may be full.":"Could not join a server. Try again soon."));return}this.retry()}};a.onclose=h,a.onerror=()=>{window.setTimeout(()=>{a.readyState===WebSocket.CLOSED&&h({code:1006})},1e3)}}retry(){if(this.closed)return;let e=Date.now();if(this.droppedAt||(this.droppedAt=e,this.callbacks.onConnection?.(!1)),e-this.droppedAt>eo)return this.finish("disconnected");if(this.retryTimer)return;let o=bt[Math.min(this.attempt++,bt.length-1)]*(.5+Math.random());this.retryTimer=window.setTimeout(()=>{this.retryTimer=0,this.closed||this.open()},o)}lost(e){if(!(e!==this.ws||this.closed)){e.onopen=e.onmessage=e.onclose=e.onerror=null,window.clearInterval(this.pingTimer),window.clearInterval(this.watchTimer);try{e.close()}catch{}this.retry()}}wake(){if(this.closed)return;if(this.sleeping){this.sleeping=!1,this.droppedAt=Date.now(),this.attempt=0,this.open();return}let e=this.ws;if(!e||e.readyState===WebSocket.CLOSING||e.readyState===WebSocket.CLOSED){this.retryTimer&&(window.clearTimeout(this.retryTimer),this.retryTimer=0,this.open());return}if(e.readyState!==WebSocket.OPEN)return;let o=this.heardCount;try{e.send(he)}catch{return this.lost(e)}window.setTimeout(()=>e===this.ws&&!this.closed&&this.heardCount===o&&this.lost(e),ro)}dispose(){window.clearInterval(this.pingTimer),window.clearInterval(this.watchTimer),window.clearTimeout(this.retryTimer),this.retryTimer=0,document.removeEventListener("visibilitychange",this.onVisible),removeEventListener("online",this.onOnline),removeEventListener("pageshow",this.onShow),removeEventListener("pagehide",this.onHide)}finish(e){this.closed=!0,this.dispose(),T(this.slug,null),this.callbacks.onClose(e)}};var Rt=`:root {
1
+ "use strict";(()=>{var He=["#f6dcc5","#ebc29f","#d4a07a","#b07a55","#875839","#5e3d29","#93c9bb","#a8c595","#94bcd3","#ab9bd9","#dca3ad","#b3bccb"],be=["#c95f56","#dc8a4f","#e2bd52","#9cc27a","#5a8a5e","#4f9a8e","#6fb7c8","#5b87c5","#465089","#8b68a8","#dc8fae","#f2eee6","#a9a8ad","#5d5c63","#2b2a30","#80604d"],Fe=["Happy","Grin","Shades","Wink","Surprised","Determined","Joyful","Shy"],qe=["None","Sprout","Cap","Beanie","Crown","Headphones","Horns","Antenna","Bow","Halo","Party hat","Cat ears","Short hair","Tuft","Bob","Spikes","Bun","Curls","Long","Mop"];var Ke=["Plain","Band","Spots","Stripes","Star"];var jo={skin:He.length,shirt:be.length,pants:be.length,face:Fe.length,hat:qe.length,top:Ke.length},Xt=[[5,6],[3,4],[6,7],[9,8],[10,0],[12,13]];function Ve(t){let e=2166136261;for(let c of t)e=Math.imul(e^c.charCodeAt(0),16777619)>>>0;let o=c=>(e=Math.imul(e^e>>>13,2654435761)>>>0,e%c),r=o(He.length),n=r>=6?Xt[r-6][o(2)]:o(be.length),a=o(2)===0?n:[8,13,14,15][o(4)],i=o(5)===0?1:12+o(qe.length-12),s=o(2)===0?0:o(Ke.length);return{skin:r,shirt:n,pants:a,face:o(Fe.length),hat:i,top:s}}var E={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 Ye=/^[a-z0-9]{12}$/,Z=2;function we(t){return`${t.mode}.${t.max}.${t.teams}.${t.ranked?1:0}${t.min!==Z?`.${t.min}`:""}`}var Zt=/^pub:([a-z0-9-]+)\.(\d+)\.(\d)\.([01])(?:\.(\d+))?:(\d+)$/;function Je(t){let e=Zt.exec(t);if(!e)return null;let o={mode:e[1],max:Number(e[2]),teams:Number(e[3]),ranked:e[4]==="1",min:e[5]===void 0?Z:Number(e[5])};return{...o,name:we(o),n:Number(e[6])}}function Xe(t,e,o){let r=typeof t=="string"?Number(t):t;return typeof r!="number"||!Number.isInteger(r)?Math.min(o,e):Math.min(e,Math.max(1,r))}var We=t=>t.replace(/[\u0000-\u001f\u007f]/g," ").replace(/\s+/g," ").trim();var Qt=/^[a-z0-9][a-z0-9-]{0,19}$/;function Ze(t){if(!t||typeof t!="object")return null;let e=t,o=[];for(let n of Array.isArray(e.buttons)?e.buttons:[]){if(o.length>=E.controlButtons)break;let{id:a,label:i}=n??{};if(typeof a!="string"||!Qt.test(a)||o.some(c=>c.id===a))continue;let s=typeof i=="string"?i.replace(/[\u0000-\u001f\u007f]/g,"").replace(/\s+/g," ").trim().slice(0,E.controlLabelLength).trim():"";o.push({id:a,label:s||a})}let r=e.stick===!0;return r||o.length>0?{stick:r,zone:e.zone==="corner"?"corner":"wide",buttons:o}:null}var K="host:ow.settings",eo=/^[a-z][a-zA-Z0-9]{0,15}$/;function Qe(t){if(!Array.isArray(t))return[];let e=[];for(let o of t){if(e.length>=6)break;let{id:r,label:n,options:a,default:i}=o??{};if(typeof r!="string"||!eo.test(r)||e.some(d=>d.id===r)||!Array.isArray(a))continue;let s=[];for(let d of a){let p=typeof d=="object"&&d!==null?d.value:d;if(typeof p!="string"&&typeof p!="number"||typeof p=="number"&&!Number.isFinite(p)||s.length>=8||s.some(u=>u.value===p))continue;let m=typeof d=="object"&&d!==null&&typeof d.label=="string"?d.label:String(p);s.push({value:p,label:We(m).slice(0,20)||String(p)})}if(s.length<2)continue;let c=typeof n=="string"?We(n).slice(0,24):"";e.push({id:r,label:c||r,options:s,default:s.some(d=>d.value===i)?i:s[0].value})}return e}function et(t,e){let o=e!==null&&typeof e=="object"?e[t.id]:void 0;return t.options.some(r=>r.value===o)?o:t.default}var ve='{"t":"ping"}';var tt=4001,ot=4003,rt=4008,nt=4006;var at="onceworlds:hello",it="onceworlds:connect",to=/^[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}$/;function st(t){let e=t!==null&&typeof t=="object"?t.build:void 0;return typeof e=="string"&&to.test(e)?e:null}var lt="onceworlds-console";var pt="allow-scripts allow-pointer-lock allow-forms allow-orientation-lock",dt=["autoplay","gamepad","screen-wake-lock","accelerometer","gyroscope"].map(t=>`${t} *`).join("; "),ct=100*1024*1024;var gt=new Set(["server","join","deploy","watch","player","embed","k","console","tester","live","demo",lt]);var ye="onceworlds:page",oo=["ran","blocked","failed","threw","loaded"];function ht(t){if(t===null||typeof t!="object")return null;let{what:e,detail:o}=t;return typeof e!="string"||!oo.includes(e)?null:{what:e,detail:typeof o=="string"?o.slice(0,200):""}}var ro=`(function(){var n=0,s=function(w,d){if(n++<12)try{parent.postMessage({type:${JSON.stringify(ye)},what:w,detail:String(d).slice(0,200)},"*")}catch(e){}};s("ran",document.readyState);addEventListener("securitypolicyviolation",function(e){s("blocked",e.effectiveDirective+" "+e.blockedURI)});addEventListener("error",function(e){var t=e.target;t&&t.tagName?s("failed",t.tagName+" "+(t.src||t.href)):s("threw",e.message+" "+e.filename+":"+e.lineno)},true);addEventListener("load",function(){s("loaded",typeof onceworlds)})})();`,Fo=`<script>${ro}<\/script>`;function ut(t){return t?.ownCountdown!==!0}var no=/^#(?:[0-9a-f]{3}){1,2}$/i,C={panel:"#111216",text:"#f7f7f8",accent:"#d33e00"},Se=4.5,ke=3,Q=["#4ade80","#15803d"];function xt(t){let e=[];if(t==null)return{look:null,notes:e};if(typeof t!="object")return{look:null,notes:["a look is { accent, panel, text } or null"]};let o=t,r=p=>{let m=o[p];return m==null?null:typeof m=="string"&&no.test(m)?ft(m):(e.push(`${p} is not #rgb or #rrggbb`),null)},n=r("panel"),a=r("text"),i=r("accent");if(n||a){let p=A(a??C.text,n??C.panel);p<Se&&(e.push(`text on panel is ${p.toFixed(1)}:1, under ${Se}:1: the platform's are used`),n=a=null)}let s=n??C.panel,c=a??C.text;if(i){let p=A(i,s);p<ke&&(e.push(`accent on panel is ${p.toFixed(1)}:1, under ${ke}:1: the platform's is used`),i=null)}if(!i&&n&&A(C.accent,n)<ke&&(i=c),!n&&!a&&!i)return{look:null,notes:e};let d=i?ao(i):null;return{look:{panel:n,text:a,muted:n||a?io(c,s):null,accent:i,accentHover:i?bt(i,d==="#ffffff"?"#000000":"#ffffff",.14):null,onAccent:d,ok:n?A(Q[0],n)>=A(Q[1],n)?Q[0]:Q[1]:null},notes:e}}function ft(t){let e=t.slice(1).toLowerCase();return`#${e.length===3?[...e].map(o=>o+o).join(""):e}`}function V(t){let e=ft(t);return[parseInt(e.slice(1,3),16),parseInt(e.slice(3,5),16),parseInt(e.slice(5,7),16)]}function mt(t){let[e,o,r]=V(t).map(n=>{let a=n/255;return a<=.04045?a/12.92:((a+.055)/1.055)**2.4});return .2126*e+.7152*o+.0722*r}function A(t,e){let[o,r]=[mt(t),mt(e)].sort((n,a)=>a-n);return(o+.05)/(r+.05)}function ao(t){return A(t,"#000000")>A(t,"#ffffff")?"#000000":"#ffffff"}function bt(t,e,o){let[r,n]=[V(t),V(e)];return`#${r.map((a,i)=>Math.round(a+(n[i]-a)*o).toString(16).padStart(2,"0")).join("")}`}function io(t,e){for(let o=.3;o>.001;o-=.05){let r=bt(t,e,o);if(A(r,e)>=Se)return r}return t}var ee=class{port=null;handlers;events;onConnect;solo;demo;onActivity;onPage;constructor(e,o,r,n,a={}){this.handlers=o,this.events=r,this.onConnect=n,this.solo=a.solo===!0,this.demo=a.demo===!0,this.onActivity=a.onActivity??null,this.onPage=a.onPage??null,window.addEventListener("message",i=>{if(!(i.source!==e.contentWindow||i.origin!=="null")&&(i.data?.type===at&&this.connect(i.source,st(i.data)),i.data?.type===ye)){let s=ht(i.data);s&&this.onPage?.(s)}})}activity(e,o){try{this.onActivity?.(e,o)}catch{}}emit(e,o){this.port?.postMessage({kind:"event",name:e,data:o})}connect(e,o){this.port?.close();let r=new MessageChannel,n=r.port1;this.port=n,n.onmessage=i=>this.receive(n,i.data);let a={type:it,...this.solo?{solo:!0}:{},...this.demo?{demo:!0}:{}};e.postMessage(a,"*",[r.port2]),this.onConnect(o)}async receive(e,o){if(!(e!==this.port||!o||typeof o!="object")){if(o.kind==="event"){Object.hasOwn(this.events,o.name)&&(this.events[o.name](o.data),this.activity(String(o.name),null));return}if(o.kind==="req")try{if(!Object.hasOwn(this.handlers,o.method))throw new Error(`Unknown method: ${String(o.method)}`);let r=this.handlers[o.method],n=await r(o.params);e.postMessage({kind:"res",id:o.id,ok:!0,result:n??null}),this.activity(String(o.method),null)}catch(r){let n=r instanceof Error?r.message:String(r);e.postMessage({kind:"res",id:o.id,ok:!1,error:n}),this.activity(String(o.method),n)}}}};var so="ow-game-storage",lo=256,wt="guest";function ze(t){let e=0,o=new Set,r=[t];for(;r.length;){let n=r.pop();if(typeof n=="string")e+=n.length*2;else if(typeof n!="object"||n===null)e+=8;else{if(o.has(n))continue;if(o.add(n),n instanceof ArrayBuffer)e+=n.byteLength;else if(ArrayBuffer.isView(n))e+=n.buffer.byteLength;else if(typeof Blob=="function"&&n instanceof Blob)e+=n.size;else if(n instanceof Map)for(let[a,i]of n)r.push(a,i);else if(n instanceof Set)for(let a of n)r.push(a);else if(Array.isArray(n))r.push(...n.slice(0,1e5),...n.length>1e5?[n.slice(1e5)]:[]);else for(let[a,i]of Object.entries(n))r.push(a,i)}}return e}function $(t){if(typeof t!="string"||t.length>lo)throw new Error("Bad name");return t}function vt(t){if(t===null)return null;if(typeof t=="string")return $(t);if(Array.isArray(t)&&t.length<=32)return t.map($);throw new Error("Bad key path")}function po(t){if(typeof t!="object"||t===null)throw new Error("Bad stores");let e=Object.keys(t);if(e.length>1e3)throw new Error("Too many stores");let o={};for(let r of e){let n=t[$(r)];if(typeof n!="object"||n===null||!Array.isArray(n.indexes)||n.indexes.length>1e3)throw new Error("Bad store");let a=Number(n.nextKey),i=n.indexes.map(s=>{let c=vt(s?.keyPath);if(c===null)throw new Error("Bad index");return{name:$(s.name),keyPath:c,unique:s.unique===!0,multiEntry:s.multiEntry===!0}});o[r]={keyPath:vt(n.keyPath),autoIncrement:n.autoIncrement===!0,nextKey:Number.isFinite(a)?a:1,indexes:i}}return o}function y(t){return new Promise((e,o)=>{t.onsuccess=()=>e(t.result),t.onerror=()=>o(t.error??new Error("Storage failed"))})}function Re(t){return new Promise((e,o)=>{t.oncomplete=()=>e(),t.onabort=t.onerror=()=>o(t.error??new Error("Storage failed"))})}var te=class{database=null;named=null;owner;factory;limit;constructor(e,o={}){this.owner=e,this.factory=o.factory??(()=>indexedDB),this.limit=o.limit??ct}open(){return this.database??=new Promise((e,o)=>{let r=this.factory().open(so,1);r.onupgradeneeded=()=>{r.result.createObjectStore("dbs",{keyPath:["owner","db"]}),r.result.createObjectStore("records")},r.onsuccess=()=>e(r.result),r.onerror=()=>o(r.error??new Error("No storage in this browser"))}),this.database}who(){return this.named??=this.owner().then(async({game:e,player:o})=>{let r=`${e}
2
+ ${o??wt}`;return o!==null&&await this.adopt(`${e}
3
+ ${wt}`,r),r}),this.named}async adopt(e,o){let n=(await this.open()).transaction(["dbs","records"],"readwrite"),a=Re(n),i=n.objectStore("dbs"),s=n.objectStore("records"),c=await y(i.getAll(this.ownerRange(e)));for(let d of c){let p=this.dbRange(e,d.db);if(!await y(i.getKey([o,d.db]))){let m=await y(s.getAllKeys(p));for(let u of m){let R=await y(s.get(u));s.put(R,[o,...u.slice(1)])}i.put({...d,owner:o})}s.delete(p),i.delete([e,d.db])}await a}ownerRange(e){return IDBKeyRange.bound([e],[`${e}\0`],!1,!0)}dbRange(e,o){return IDBKeyRange.bound([e,o],[e,`${o}\0`],!1,!0)}storeRange(e,o,r){return IDBKeyRange.bound([e,o,r],[e,o,`${r}\0`],!1,!0)}async read({db:e}){$(e);let o=await this.who(),n=(await this.open()).transaction(["dbs","records"]),a=await y(n.objectStore("dbs").get([o,e]));if(!a)return null;let i=n.objectStore("records"),s=this.dbRange(o,e),[c,d]=await Promise.all([y(i.getAllKeys(s)),y(i.getAll(s))]);return{version:a.version,stores:a.stores,records:c.map((p,m)=>({store:p[2],key:p[3],value:d[m].value}))}}async commit(e){let o=$(e?.db),r=Number(e.version);if(!Number.isFinite(r)||r<0)throw new Error("Bad version");let n=e.ops;if(!Array.isArray(n))throw new Error("Bad changes");let a=e.stores===void 0?void 0:po(e.stores),i=await this.who(),c=(await this.open()).transaction(["dbs","records"],"readwrite"),d=Re(c),p=c.objectStore("dbs"),m=c.objectStore("records");try{let u=await y(p.getAll(this.ownerRange(i))),R=u.find(l=>l.db===o)??{owner:i,db:o,version:r,stores:{},bytes:0},q=u.reduce((l,x)=>l+(x===R?0:x.bytes),0),b=R.bytes;for(let l of n){let x=$(l?.store);if("clear"in l){b-=await this.sum(m,this.storeRange(i,o,x)),m.delete(this.storeRange(i,o,x));continue}let fe=[i,o,x,"put"in l?l.put:l.remove],Ge=await y(m.get(fe));if(Ge&&(b-=Ge.bytes),"put"in l){let Ue=ze(l.value)+ze(l.put)+64;b+=Ue,m.put({value:l.value,bytes:Ue},fe)}else m.delete(fe)}if(a)for(let l of Object.keys(R.stores))Object.hasOwn(a,l)||(b-=await this.sum(m,this.storeRange(i,o,l)),m.delete(this.storeRange(i,o,l)));if(q+=ze(a??R.stores),q+b>this.limit)throw new Error("QuotaExceededError");p.put({owner:i,db:o,version:r,stores:a??R.stores,bytes:Math.max(0,b)})}catch(u){try{c.abort()}catch{}throw d.catch(()=>{}),u}return await d,null}async sum(e,o){return(await y(e.getAll(o))).reduce((n,a)=>n+a.bytes,0)}async remove({db:e}){$(e);let o=await this.who(),n=(await this.open()).transaction(["dbs","records"],"readwrite"),a=Re(n);return n.objectStore("records").delete(this.dbRange(o,e)),n.objectStore("dbs").delete([o,e]),await a,null}async list(){let e=await this.who(),o=await this.open();return(await y(o.transaction("dbs").objectStore("dbs").getAll(this.ownerRange(e)))).map(n=>({name:n.db,version:n.version}))}};var oe=class{pressed=new Set;press(e){this.pressed.add(e)}take(e){let o=new Set(e),r=!1;for(let n of this.pressed)o.has(n)||(o.add(n),r=!0);return this.pressed.clear(),{buttons:[...o],owed:r}}};var yt=["--ow-panel","--ow-face-edge","--ow-hover","--ow-on-accent","--text","--muted","--line","--line-strong","--fill","--fill-strong","--ok","--accent-fill","--accent-fill-hover","--accent-hover"],kt=["--ow-ctl-edge","--ow-ctl-fill","--ow-ctl-stick","--ow-ctl-knob","--ow-ctl-label","--ow-ctl-shadow","--ow-ctl-held","--ow-ctl-main","--ow-ctl-main-edge","--ow-ctl-main-label","--ow-ctl-main-shadow","--ow-ctl-main-held"];function w(t,e){return`rgba(${V(t).join(", ")}, ${e})`}function St(t){let e={};if(!t)return e;if(t.panel&&(e["--ow-panel"]=t.panel,e["--ow-face-edge"]=t.panel),t.ok&&(e["--ok"]=t.ok),t.panel||t.text){let o=t.text??C.text;t.text&&(e["--text"]=t.text),t.muted&&(e["--muted"]=t.muted),e["--line"]=w(o,.09),e["--line-strong"]=w(o,.16),e["--fill"]=w(o,.06),e["--fill-strong"]=w(o,.1),e["--ow-hover"]=w(o,.16)}return t.accent&&t.accentHover&&t.onAccent&&(e["--accent-fill"]=t.accent,e["--accent-fill-hover"]=t.accentHover,e["--accent-hover"]=t.accent,e["--ow-on-accent"]=t.onAccent),e}function zt(t){let e={};return t&&(t.text&&(e["--ow-ctl-edge"]=w(t.text,.4),e["--ow-ctl-knob"]=w(t.text,.9),e["--ow-ctl-label"]=t.text,e["--ow-ctl-held"]=w(t.text,.35)),t.panel&&(e["--ow-ctl-fill"]=w(t.panel,.4),e["--ow-ctl-stick"]=w(t.panel,.3),e["--ow-ctl-shadow"]=w(t.panel,.5)),t.accent&&t.accentHover&&t.onAccent&&(e["--ow-ctl-main"]=w(t.accent,.85),e["--ow-ctl-main-edge"]=t.accent,e["--ow-ctl-main-label"]=t.onAccent,e["--ow-ctl-main-shadow"]="none",e["--ow-ctl-main-held"]=t.accentHover)),e}function re(t,e,o){for(let r of e)Object.hasOwn(o,r)?t.style.setProperty(r,o[r]):t.style.removeProperty(r);t.toggleAttribute("data-look",e.some(r=>Object.hasOwn(o,r)))}var L=52,Ee=.12,Pe=96,co=400,go=2e4,ne=class{parent;root;zone;base;knob;buttonBox;send;onLayout;layout=null;touch;blocked=!1;keyboard=!1;stickPointer=null;center={x:0,y:0};x=0;y=0;buttons=new Map;held=new Map;fingers=new Map;report=new oe;queued=0;sent="";placed={stick:null,buttons:null};constructor(e,o,r=()=>{}){this.send=o,this.onLayout=r,this.parent=e,this.touch=matchMedia("(pointer: coarse)").matches,this.root=T("div","ow-controls"),this.root.hidden=!0,this.zone=T("div","ow-stick-zone"),this.base=T("div","ow-stick"),this.knob=T("div","ow-stick-knob"),this.base.append(this.knob),this.zone.append(this.base),this.buttonBox=T("div","ow-control-buttons"),this.root.append(this.zone,this.buttonBox),e.append(this.root),this.zone.addEventListener("pointerdown",n=>this.stickDown(n)),this.zone.addEventListener("pointermove",n=>this.stickMove(n));for(let n of["pointerup","pointercancel","lostpointercapture"])this.zone.addEventListener(n,a=>this.stickUp(a));this.root.addEventListener("contextmenu",n=>n.preventDefault())}setLayout(e){this.layout=Ze(e);let o=this.buttons;this.buttons=new Map,(this.layout?.buttons??[]).forEach((r,n)=>{let a=o.get(r.id)??this.button(r.id);o.delete(r.id),a.className=`ow-control-btn ow-control-btn-${n}`,a.classList.toggle("ow-held",[...this.held.values()].includes(r.id)),a.textContent=r.label,a.isConnected||this.buttonBox.append(a),this.buttons.set(r.id,a)});for(let[r,n]of o){for(let[a,i]of this.held)i===r&&this.letGo(a);n.remove()}this.zone.hidden=!this.layout?.stick,this.zone.classList.toggle("ow-stick-corner",this.layout?.zone==="corner"),this.zone.hidden&&this.stickPointer!==null&&this.letGo(this.stickPointer),this.render(),this.onLayout()}setLook(e){re(this.root,kt,e)}reservedBoxes(){if(this.root.hidden)return this.blocked&&this.layout&&this.touch&&!this.keyboard?this.placed:{stick:null,buttons:null};let e=this.zone.hidden?null:Et(this.base),o=null;for(let r of this.buttons.values()){let n=Et(r);!n.width||!n.height||(o=o?uo(o,n):n)}return this.placed={stick:e,buttons:o},this.placed}setTouch(e){this.touch=e,this.render()}setKeyboard(e){this.keyboard=e,this.render()}setBlocked(e){this.blocked=e,this.render()}render(){let e=!!this.layout&&this.touch&&!this.blocked&&!this.keyboard;this.root.hidden!==!e&&(e||this.reset(),this.root.hidden=!e,this.onLayout())}reset(){for(let e of[...this.held.keys()])this.letGo(e);this.stickPointer!==null&&this.letGo(this.stickPointer),this.endStick()}letGo(e){e===this.stickPointer&&this.endStick();let o=this.held.get(e);this.held.delete(e),o!==void 0&&![...this.held.values()].includes(o)&&this.buttons.get(o)?.classList.remove("ow-held");let r=this.fingers.get(e);this.fingers.delete(e),r&&ho(this.parent,e,r),this.changed()}button(e){let o=T("button","ow-control-btn");o.type="button",o.tabIndex=-1,o.addEventListener("pointerdown",n=>{n.preventDefault(),Rt(o,n.pointerId),o.classList.add("ow-held"),this.held.set(n.pointerId,e),this.report.press(e),this.fingers.set(n.pointerId,{x:n.clientX,y:n.clientY}),this.changed()}),o.addEventListener("pointermove",n=>{this.held.get(n.pointerId)===e&&this.fingers.set(n.pointerId,{x:n.clientX,y:n.clientY})});let r=n=>{this.held.get(n.pointerId)===e&&(this.held.delete(n.pointerId),this.fingers.delete(n.pointerId),[...this.held.values()].includes(e)||o.classList.remove("ow-held"),this.changed())};for(let n of["pointerup","pointercancel","lostpointercapture"])o.addEventListener(n,a=>r(a));return o}stickDown(e){if(this.stickPointer!==null)return;e.preventDefault(),Rt(this.zone,e.pointerId),this.stickPointer=e.pointerId,this.fingers.set(e.pointerId,{x:e.clientX,y:e.clientY});let o=this.zone.getBoundingClientRect(),r=this.base.getBoundingClientRect(),n=L+8;this.center={x:Math.min(Math.max(e.clientX,o.left+n),o.right-n),y:Math.min(Math.max(e.clientY,o.top+n),o.bottom-n)},this.base.style.transform=`translate(${this.center.x-(r.left+r.width/2)}px, ${this.center.y-(r.top+r.height/2)}px)`,this.base.classList.add("ow-active"),this.stickMove(e)}stickMove(e){if(e.pointerId!==this.stickPointer)return;this.fingers.set(e.pointerId,{x:e.clientX,y:e.clientY});let o=e.clientX-this.center.x,r=e.clientY-this.center.y,n=Math.hypot(o,r);n>L&&(o=o/n*L,r=r/n*L),this.knob.style.transform=`translate(${o}px, ${r}px)`;let a=Math.min(n,L)/L,i=a<Ee?0:(a-Ee)/(1-Ee)/(a||1);this.x=Pt(o/L*i),this.y=Pt(r/L*i),this.changed()}stickUp(e){e.pointerId===this.stickPointer&&(this.fingers.delete(e.pointerId),this.endStick())}endStick(){this.stickPointer=null,this.x=0,this.y=0,this.base.classList.remove("ow-active"),this.base.style.transform="",this.knob.style.transform="",this.changed()}changed(){this.queued||(this.queued=requestAnimationFrame(()=>{this.queued=0;let{buttons:e,owed:o}=this.report.take(this.held.values()),r={x:this.x,y:this.y,buttons:e};o&&this.changed();let n=JSON.stringify(r);n!==this.sent&&(this.sent=n,this.send(r))}))}};function ho(t,e,o){let r=T("div","ow-tap-shield");r.style.left=`${o.x-Pe/2}px`,r.style.top=`${o.y-Pe/2}px`,r.style.width=r.style.height=`${Pe}px`,t.append(r);let n=setTimeout(()=>r.remove(),go),a=()=>{clearTimeout(n),n=setTimeout(()=>r.remove(),co)};for(let i of["pointerup","pointercancel","lostpointercapture"])r.addEventListener(i,s=>s.pointerId===e&&a());r.addEventListener("contextmenu",i=>i.preventDefault());try{r.setPointerCapture(e)}catch{a()}}function Rt(t,e){try{t.setPointerCapture(e)}catch{}}function Et(t){let e=t.getBoundingClientRect(),o=getComputedStyle(t).transform;if(!o||o==="none")return e;let r=new DOMMatrixReadOnly(o);if(r.b||r.c||!r.a||!r.d)return e;let n=e.width/Math.abs(r.a),a=e.height/Math.abs(r.d),i=e.left+e.width/2-r.e,s=e.top+e.height/2-r.f;return{left:i-n/2,top:s-a/2,width:n,height:a}}function uo(t,e){let o=Math.min(t.left,e.left),r=Math.min(t.top,e.top);return{left:o,top:r,width:Math.max(t.left+t.width,e.left+e.width)-o,height:Math.max(t.top+t.height,e.top+e.height)-r}}function Pt(t){return Math.round(t*1e3)/1e3}function T(t,e,o){let r=document.createElement(t);return r.className=e,o!==void 0&&(r.textContent=o),r}function mo(t,e){return t!=="lobby"?{surface:t,hidden:!1}:{surface:e?"none":"lobby",hidden:e}}var Me=t=>Math.max(0,Math.ceil(t/1e3)),Ae=t=>{let e=t.slice(0,2).map(o=>o.name);return t.length>2?`${e.join(", ")} +${t.length-2}`:e.join(", ")};function xo(t){let{you:e,host:o,kind:r,match:n,now:a}=t,i=[...t.players].sort((l,x)=>l.id===e?-1:x.id===e?1:l.id===o?-1:x.id===o?1:l.name.localeCompare(x.name)).map(l=>({id:l.id,name:l.name,ready:!!l.ready,host:l.id===o,you:l.id===e,away:l.connected===!1,idle:l.connected!==!1&&!!l.idle})),s=t.players.filter(l=>l.connected!==!1),c=t.players.find(l=>l.id===e),d=o===e&&n.phase==="lobby",p=t.schema.map(l=>({id:l.id,label:l.label,value:et(l,t.written),options:l.options,editable:d})),m={n:s.filter(l=>l.ready||r!=="public"&&l.id===o).length,of:s.length},u={surface:"none",rows:i,count:`${t.players.length} / ${t.max}`,ready:m,status:"",action:{kind:"none",label:"",disabled:!0},settings:p,seconds:null},R=n.participants?.includes(e)??!1,q=o===e&&r!=="public";if(n.phase==="starting"){if(!R)return{...u,surface:"watching",status:"Watching"};let l=q?{kind:"stop",label:"Stop",disabled:!1}:{kind:"unready",label:"Not ready",disabled:!1};return t.ownCountdown?{...u,surface:"countdown",action:l,seconds:null,status:"Get ready"}:{...u,surface:"countdown",action:l,seconds:Math.max(1,Me((n.startsAt??a)-a)),status:"Get ready"}}if(n.phase==="playing"){if(n.paused){let l=s.filter(x=>n.participants?.includes(x.id)).length;return n.paused.reason==="host"?{...u,surface:"paused",status:"Paused"}:{...u,surface:"paused",seconds:Me(n.paused.since+E.matchAbandonMs-a),status:`Waiting for players \xB7 ${l} / ${n.min}`}}return R?u:{...u,surface:"watching",status:"Watching"}}let b=s.filter(l=>!l.ready&&(r==="public"||l.id!==o));if(u.surface="lobby",q){let l=s.length<n.min;return u.action={kind:"start",label:"Start",disabled:l||b.length>0},u.status=l?`Need ${n.min} players`:b.length?`Waiting for ${Ae(b)}`:"",u}if(u.action={kind:c?.ready?"unready":"ready",label:c?.ready?"Not ready":"Ready",disabled:!1},r==="public")s.length<n.min?u.status=`Need ${n.min} players`:n.waitUntil!==void 0&&b.length?(u.seconds=Me(n.waitUntil-a),u.status=`${Ae(b)} \xB7 ${u.seconds}s`):u.status=`${s.length-b.length} / ${s.length} ready`;else{let l=b.filter(x=>x.id!==e);u.status=c?.ready?l.length?`Waiting for ${Ae(l)}`:`Waiting for ${t.players.find(x=>x.id===o)?.name??"the host"}`:""}return u}function h(t,e="",o){let r=document.createElement(t);return e&&(r.className=e),o!==void 0&&(r.textContent=o),r}var ae=class{mode=null;ownCountdown=!1;hiddenByGame=!1;state=null;schema=[];timer=0;opts;root;card;title;count;list;settingsBox;status;action;invite;bar;barFaces;barStatus;barAction;countdown;numeral;cancel;pause;pauseStatus;pauseTimer;chip;last=null;lastNumeral=-1;listSignature="";settingsSignature="";faceSignature="";constructor(e,o){this.opts=o,this.root=h("div","ow-lobby"),this.root.hidden=!0,this.card=h("section","ow-lobby-card"),this.card.setAttribute("aria-label","Lobby");let r=h("header","ow-lobby-head");this.title=h("h2","","Lobby"),this.count=h("span","ow-lobby-count"),r.append(this.title,this.count),this.list=h("ul","ow-lobby-players"),this.settingsBox=h("div","ow-lobby-settings"),this.status=h("p","ow-lobby-status"),this.status.setAttribute("role","status"),this.action=this.button("ow-btn ow-btn-primary ow-lobby-action",()=>this.press()),this.invite=this.button("ow-btn ow-lobby-invite",()=>this.opts.onInvite()),this.invite.textContent="Invite";let n=h("div","ow-lobby-actions");n.append(this.action,this.invite),this.card.append(r,this.list,this.settingsBox,this.status,n),this.bar=h("div","ow-lobby-bar"),this.barFaces=h("span","ow-lobby-faces"),this.barStatus=h("span","ow-lobby-bar-status"),this.barStatus.setAttribute("role","status"),this.barAction=this.button("ow-btn ow-btn-primary ow-lobby-action",()=>this.press()),this.bar.append(this.barFaces,this.barStatus,this.barAction),this.countdown=h("div","ow-lobby-countdown"),this.numeral=h("b"),this.numeral.setAttribute("aria-hidden","true");let a=h("span","","Get ready");a.setAttribute("aria-hidden","true"),this.cancel=this.button("ow-btn ow-lobby-cancel",()=>this.press()),this.countdown.append(this.numeral,a,this.cancel),this.pause=h("div","ow-lobby-pause");let i=h("div","ow-lobby-pause-box");this.pauseStatus=h("p","ow-lobby-pause-status"),this.pauseStatus.setAttribute("role","status"),this.pauseTimer=h("p","ow-lobby-pause-timer"),i.append(this.pauseStatus,this.pauseTimer),this.pause.append(i),this.chip=h("div","ow-lobby-chip"),this.chip.setAttribute("role","status"),this.root.append(this.card,this.bar,this.countdown,this.pause,this.chip),e.append(this.root)}setSchema(e){this.schema=e,this.render()}enable(e,o={}){this.mode=e,this.ownCountdown=o.ownCountdown===!0,this.root.dataset.mode=e??"",e||this.reset(),this.render()}setLook(e){re(this.root,yt,e)}reservedBox(){if(this.root.hidden)return null;let e=!this.countdown.hidden&&this.countdown.classList.contains("ow-lobby-countdown-bare"),o=this.bar.hidden?e&&!this.cancel.hidden?this.cancel:null:this.bar;return o?o.getBoundingClientRect():null}setHidden(e){this.hiddenByGame=e,this.render()}setRoom(e,o=0){if(!e)return this.reset();this.state={you:e.you,host:e.host,kind:e.room.startsWith("private:")?"private":e.room.startsWith("room:")?"named":"public",max:Math.max(o,e.players.length),players:e.players.map(r=>({...r})),match:e.match??{phase:"lobby",n:0,min:1},written:e.state?.[K]},this.render()}handle(e){let o=this.state;if(o){switch(e.t){case"join":o.players=[...o.players.filter(r=>r.id!==e.player.id),{...e.player}];break;case"leave":o.players=o.players.filter(r=>r.id!==e.id);break;case"away":o.players=o.players.map(r=>r.id===e.id?{...r,connected:!1}:r);break;case"back":o.players=o.players.map(r=>{if(r.id!==e.id)return r;let{connected:n,...a}=r;return a});break;case"ready":o.players=o.players.map(r=>{if(r.id!==e.id)return r;let{ready:n,...a}=r;return e.ready?{...a,ready:!0}:a});break;case"unready":o.players=o.players.map(({ready:r,...n})=>n);break;case"host":o.host=e.id;break;case"idle":o.players=o.players.map(r=>{if(r.id!==e.id)return r;let{idle:n,...a}=r;return e.idle?{...a,idle:!0}:a});break;case"name":o.players=o.players.map(r=>r.id===e.id?{...r,name:e.name}:r);break;case"match":o.match=e.match;break;case"state":if(e.k!==K)return;o.written=e.v;break;default:return}this.render()}}chooseSetting(e,o){let r=this.state,n=this.schema.find(i=>i.id===e);if(!r||!n||!n.options.some(i=>i.value===o))return null;let a={...r.written!==null&&typeof r.written=="object"?r.written:{},[e]:o};return r.written=a,this.render(),a}setReadyLocal(e){let o=this.state?.players.find(r=>r.id===this.state?.you);o&&(e?o.ready=!0:delete o.ready,this.render())}button(e,o){let r=h("button",e);return r.type="button",r.addEventListener("pointerdown",n=>n.preventDefault()),r.addEventListener("click",o),r}press(){let e=this.last?.action.kind;e==="start"?this.opts.onStart():e==="stop"?this.opts.onStop():e==="ready"?(this.setReadyLocal(!0),this.opts.onReady(!0)):e==="unready"&&(this.setReadyLocal(!1),this.opts.onReady(!1))}reset(){this.state=null,this.last=null,this.hiddenByGame=!1,window.clearInterval(this.timer),this.timer=0,this.root.hidden=!0,this.opts.onLayout?.()}render(){this.draw(),this.opts.onLayout?.()}draw(){if(!this.mode||!this.state){this.root.hidden=!0;return}let e=xo({...this.state,schema:this.schema,now:this.opts.now(),ownCountdown:this.ownCountdown});this.last=e;let o=mo(e.surface,this.hiddenByGame);this.hiddenByGame=o.hidden;let r=o.surface==="lobby";if(this.root.hidden=o.surface==="none",this.card.hidden=!(r&&this.mode==="card"),this.bar.hidden=!(r&&this.mode==="bar"),this.countdown.hidden=e.surface!=="countdown",this.countdown.classList.toggle("ow-lobby-countdown-bare",e.surface==="countdown"&&e.seconds===null),this.pause.hidden=e.surface!=="paused",this.chip.hidden=e.surface!=="watching",this.root.classList.toggle("ow-lobby-dim",r&&this.mode==="card"),r&&this.mode==="card"&&this.renderCard(e),r&&this.mode==="bar"&&this.renderBar(e),e.surface==="countdown"&&e.seconds!==null&&e.seconds!==this.lastNumeral&&(this.lastNumeral=e.seconds,this.numeral.textContent=String(e.seconds),this.numeral.style.animation="none",this.numeral.offsetWidth,this.numeral.style.animation=""),e.surface==="countdown"&&(this.cancel.textContent=e.action.label),e.surface!=="countdown"&&(this.lastNumeral=-1),e.surface==="paused"&&(this.pauseStatus.textContent=e.status,this.pauseTimer.textContent=e.seconds!==null?`Ends in ${fo(e.seconds)}`:""),e.surface==="watching"){let[a,...i]=e.status.split(" \xB7 "),s=h("span","ow-lobby-chip-more",i.length?` \xB7 ${i.join(" \xB7 ")}`:"");this.chip.replaceChildren(a,s)}let n=e.seconds!==null;n&&!this.timer?this.timer=window.setInterval(()=>this.render(),250):!n&&this.timer&&(window.clearInterval(this.timer),this.timer=0)}renderCard(e){this.count.textContent=e.count,this.settingsBox.hidden=e.settings.length===0,this.status.textContent=e.status,this.status.hidden=e.status==="",this.setAction(this.action,e);let o=JSON.stringify(e.settings);o!==this.settingsSignature&&(this.settingsSignature=o,this.settingsBox.replaceChildren(...e.settings.map(n=>this.settingRow(n))));let r=JSON.stringify(e.rows);r!==this.listSignature&&(this.listSignature=r,this.list.replaceChildren(...e.rows.map(n=>{let a=h("li",n.away||n.idle?"ow-lobby-away":n.ready?"ow-lobby-ready":""),i=h("img","ow-headshot");i.src=`/avatar/${encodeURIComponent(n.id)}/head.svg`,i.alt="";let s=h("span","ow-lobby-name",n.name),c=[n.away?"Reconnecting":n.idle?"Idle":"",n.you?"You":"",n.host?"Host":""].filter(Boolean).join(" \xB7 ");return a.append(i,s),c&&a.append(h("span","ow-player-notes",c)),a.append(h("span",`ow-lobby-check${n.ready?" ow-lobby-check-on":""}`,n.ready?"Ready":"")),a})))}settingRow(e){let o=h("div","ow-lobby-setting");if(o.append(h("span","ow-lobby-setting-label",e.label)),!e.editable)return o.append(h("span","ow-lobby-setting-value",e.options.find(n=>n.value===e.value)?.label??String(e.value))),o;let r=h("div","ow-segments");r.setAttribute("role","radiogroup"),r.setAttribute("aria-label",e.label);for(let n of e.options){let a=this.button(`ow-segment${n.value===e.value?" ow-segment-on":""}`,()=>this.opts.onSetting(e.id,n.value));a.textContent=n.label,a.setAttribute("role","radio"),a.setAttribute("aria-checked",String(n.value===e.value)),r.append(a)}return o.append(r),o}renderBar(e){this.barStatus.textContent=e.status||`${e.ready.n} / ${e.ready.of} ready`,this.setAction(this.barAction,e);let o=JSON.stringify(e.rows.slice(0,5).map(r=>[r.id,r.ready]));o!==this.faceSignature&&(this.faceSignature=o,this.barFaces.replaceChildren(...e.rows.slice(0,5).map(r=>{let n=h("img",`ow-headshot${r.ready?" ow-lobby-face-ready":""}`);return n.src=`/avatar/${encodeURIComponent(r.id)}/head.svg`,n.alt="",n})))}setAction(e,o){e.hidden=o.action.kind==="none",e.textContent=o.action.label,e.disabled=o.action.disabled,e.classList.toggle("ow-btn-primary",o.action.kind!=="unready")}};function fo(t){return`${Math.floor(t/60)}:${String(t%60).padStart(2,"0")}`}function Mt(t,e){let o=[];for(let{kind:r,box:n}of e){if(!n||!(n.width>0)||!(n.height>0))continue;let a=Math.max(0,n.left-t.left),i=Math.max(0,n.top-t.top),s=Math.min(t.width,n.left+n.width-t.left),c=Math.min(t.height,n.top+n.height-t.top);if(!(s-a>.01&&c-i>.01))continue;let d=Math.floor(a+.01),p=Math.floor(i+.01);o.push({kind:r,x:d,y:p,w:Math.ceil(s-.01)-d,h:Math.ceil(c-.01)-p})}return o}var ie=class{measure;send;nextFrame;queued=!1;sent=null;constructor(e,o,r=n=>requestAnimationFrame(n)){this.measure=e,this.send=o,this.nextFrame=r}changed(){this.queued||(this.queued=!0,this.nextFrame(()=>{this.queued=!1;let e=this.measure();if(!e)return;let o=JSON.stringify(e);o!==this.sent&&(this.sent=o,this.send(e))}))}resend(){this.sent=null,this.changed()}};var $e=t=>`ow:resume:${t}`;function _(t,e){try{e?sessionStorage.setItem($e(t),JSON.stringify({...e,at:Date.now()})):sessionStorage.removeItem($e(t))}catch{}}function At(t){try{let e=sessionStorage.getItem($e(t));if(!e)return null;let o=performance.getEntriesByType("navigation")[0];if(o&&o.type!=="reload"&&o.type!=="back_forward")return se(t);let r=JSON.parse(e);return typeof r.key!="string"||typeof r.rejoin!="string"||typeof r.at!="number"||Date.now()-r.at>18e4||Number(r.rejoin.split(".")[0])*1e3<Date.now()?se(t):{key:r.key,rejoin:r.rejoin}}catch{return null}}var bo=t=>`ow:own-server:${t}`;function $t(t,e){try{sessionStorage.setItem(bo(t),e)}catch{}}function se(t){return _(t,null),null}var le=class extends Error{constructor(o,r=0,n=0,a=""){super(o);this.status=r;this.retryAfterMs=n;this.code=a;this.name="RequestError"}status;retryAfterMs;code;get retryable(){return this.status===0||this.status===408||this.status===429||this.status>=500}};var pe=class{constructor(e=48*1024){this.max=e}max;used=0;async run(e,o){let r=new TextEncoder().encode(e).byteLength;if(this.used+r>this.max)throw new le("Progress is waiting to sync when you return to the game.");this.used+=r;try{return await o()}finally{this.used-=r}}};var Le=/^[2-9]$/.test(new URLSearchParams(location.search).get("player")??"")?new URLSearchParams(location.search).get("player"):null;var wo=null;function Lt(){return wo?.n??null}var yr=new pe;var Ct=[300,700,1500,3e3,5e3,8e3],vo=9e4,yo=1e4,Dt=()=>Array.from(crypto.getRandomValues(new Uint8Array(10)),t=>"abcdefghijklmnopqrstuvwxyz0123456789"[t%36]).join(""),Ot=Dt();function _t(){Ot=Dt()}var Tt=null;var It=!1;function jt(t){It=t}var ko=5e4,So=4e3,de=class{ws=null;key=null;rejoin=null;you="";closed=!1;attempt=0;droppedAt=0;sleeping=!1;lastHeard=0;heardCount=0;pingAt=0;hintedHidden=!1;pingTimer=0;watchTimer=0;retryTimer=0;page=Ot;slug;options;callbacks;onVisible=()=>{this.hint(),document.visibilityState==="visible"&&this.wake()};onOnline=()=>this.wake();onShow=e=>e.persisted&&this.wake();onHide=()=>this.hint();constructor(e,o,r){this.slug=e,this.options=o,this.callbacks=r,this.key=o.key??null,this.rejoin=o.rejoin??null,document.addEventListener("visibilitychange",this.onVisible),addEventListener("online",this.onOnline),addEventListener("pageshow",this.onShow),addEventListener("pagehide",this.onHide)}join(){return new Promise((e,o)=>this.open(e,o))}send(e){this.ws?.readyState===WebSocket.OPEN&&this.ws.send(JSON.stringify(e))}hint(){let e=document.visibilityState==="hidden";e===this.hintedHidden||this.ws?.readyState!==WebSocket.OPEN||(this.hintedHidden=e,this.send({t:"vis",hidden:e}))}ping(){let e=this.ws;e?.readyState===WebSocket.OPEN&&(this.pingAt&&Date.now()-this.pingAt<5e3||(this.pingAt=Date.now(),e.send(ve)))}close(){this.closed=!0,_(this.slug,null),this.dispose(),this.ws?.close(1e3)}reload(){return this.closed=!0,this.dispose(),this.ws?.close(nt,"Updating"),this.key?.startsWith("pub:")&&this.rejoin?{key:this.key,rejoin:this.rejoin}:null}open(e,o){this.retryTimer=0;let r=new URL(`/api/games/${this.slug}/rooms/connect`,location.href);r.protocol=location.protocol==="https:"?"wss:":"ws:",this.key?(r.searchParams.set("key",this.key),this.rejoin&&r.searchParams.set("rejoin",this.rejoin)):this.options.server?(r.searchParams.set("server",this.options.server),this.options.private&&r.searchParams.set("own","1")):this.options.name?r.searchParams.set("name",this.options.name):(this.options.mode&&r.searchParams.set("mode",this.options.mode),this.options.follow&&r.searchParams.set("follow",this.options.follow)),this.options.maxPlayers&&r.searchParams.set("max",String(this.options.maxPlayers)),this.options.minPlayers&&r.searchParams.set("min",String(this.options.minPlayers)),this.options.countdown!==void 0&&r.searchParams.set("countdown",String(this.options.countdown)),this.options.teams&&r.searchParams.set("teams",String(this.options.teams)),this.options.ranked&&r.searchParams.set("ranked","1"),Le&&r.searchParams.set("devplayer",Le);let n=Lt();n&&r.searchParams.set("tester",n),r.searchParams.set("page",this.page),this.options.build&&r.searchParams.set("build",this.options.build),Tt&&r.searchParams.set("pass",Tt),It&&r.searchParams.set("demo","1");let a=new WebSocket(r);this.ws=a,this.lastHeard=Date.now();let i=!1;a.onopen=()=>{this.lastHeard=Date.now(),window.clearInterval(this.pingTimer),window.clearInterval(this.watchTimer),this.pingTimer=window.setInterval(()=>a.readyState===WebSocket.OPEN&&this.ping(),yo),this.watchTimer=window.setInterval(()=>{a===this.ws&&a.readyState===WebSocket.OPEN&&Date.now()-this.lastHeard>ko&&this.lost(a)},5e3)},a.onmessage=d=>{this.lastHeard=Date.now(),this.heardCount++;let p;try{p=JSON.parse(d.data)}catch{return}if(p.t==="pong"){this.pingAt&&this.callbacks.onRtt?.(Date.now()-this.pingAt),this.pingAt=0;return}if(p.t==="welcome"&&(p.rejoin&&(this.rejoin=p.rejoin),delete p.rejoin,p.room.startsWith("pub:")&&this.rejoin&&_(this.slug,{key:p.room,rejoin:this.rejoin})),p.t==="leave"&&p.kicked&&p.id===this.you){this.close(),this.finish("kicked");return}if(p.t==="welcome"&&(this.hintedHidden=!1,this.hint()),p.t==="welcome"&&!i&&(i=!0,this.key=p.room,this.you=p.you,this.attempt=0,this.droppedAt&&(this.droppedAt=0,this.callbacks.onConnection?.(!0)),e)){let{t:m,...u}=p;e(u),e=void 0;return}this.callbacks.onMessage(p)};let s=!1,c=d=>{if(!s&&(s=!0,window.clearInterval(this.pingTimer),window.clearInterval(this.watchTimer),!(this.closed||a!==this.ws))){if(d.code===tt)return this.finish("replaced");if(d.code===rt&&i&&document.visibilityState==="hidden"){this.sleeping=!0,this.droppedAt||(this.droppedAt=Date.now(),this.callbacks.onConnection?.(!1));return}if(d.code===ot){if(i||!o)return this.finish("kicked");this.closed=!0,this.dispose(),_(this.slug,null),o(Object.assign(new Error("You were removed from this server."),{kicked:!0}));return}if(!i&&o){this.closed=!0,this.dispose(),o(new Error(this.options.name||this.options.server?"Could not join that server. It may be full.":"Could not join a server. Try again soon."));return}this.retry()}};a.onclose=c,a.onerror=()=>{window.setTimeout(()=>{a.readyState===WebSocket.CLOSED&&c({code:1006})},1e3)}}retry(){if(this.closed)return;let e=Date.now();if(this.droppedAt||(this.droppedAt=e,this.callbacks.onConnection?.(!1)),e-this.droppedAt>vo)return this.finish("disconnected");if(this.retryTimer)return;let o=Ct[Math.min(this.attempt++,Ct.length-1)]*(.5+Math.random());this.retryTimer=window.setTimeout(()=>{this.retryTimer=0,this.closed||this.open()},o)}lost(e){if(!(e!==this.ws||this.closed)){e.onopen=e.onmessage=e.onclose=e.onerror=null,window.clearInterval(this.pingTimer),window.clearInterval(this.watchTimer);try{e.close()}catch{}this.retry()}}wake(){if(this.closed)return;if(this.sleeping){this.sleeping=!1,this.droppedAt=Date.now(),this.attempt=0,this.open();return}let e=this.ws;if(!e||e.readyState===WebSocket.CLOSING||e.readyState===WebSocket.CLOSED){this.retryTimer&&(window.clearTimeout(this.retryTimer),this.retryTimer=0,this.open());return}if(e.readyState!==WebSocket.OPEN)return;let o=this.heardCount;try{e.send(ve)}catch{return this.lost(e)}window.setTimeout(()=>e===this.ws&&!this.closed&&this.heardCount===o&&this.lost(e),So)}dispose(){window.clearInterval(this.pingTimer),window.clearInterval(this.watchTimer),window.clearTimeout(this.retryTimer),this.retryTimer=0,document.removeEventListener("visibilitychange",this.onVisible),removeEventListener("online",this.onOnline),removeEventListener("pageshow",this.onShow),removeEventListener("pagehide",this.onHide)}finish(e){this.closed=!0,this.dispose(),_(this.slug,null),this.callbacks.onClose(e)}};var Bt=`:root {
2
4
  color-scheme: light;
3
5
  /* Site pages: as wide as this at most, with gutters that grow with the window. */
4
6
  --page: 1440px;
@@ -8402,6 +8404,39 @@ button.ow-setting-icon:hover {
8402
8404
  transition: opacity 0.35s ease, visibility 0s linear 0.35s;
8403
8405
  }
8404
8406
 
8407
+ /* A page that never ran: what's in the frame (a device's filter page, an error) stays in view and can be tapped, the card below it. */
8408
+ .ow-loading.ow-loading-clear {
8409
+ align-items: end;
8410
+ background: none;
8411
+ pointer-events: none;
8412
+ }
8413
+
8414
+ .ow-loading-clear .ow-loading-cover,
8415
+ .ow-loading-clear .ow-loading-icon {
8416
+ display: none;
8417
+ }
8418
+
8419
+ .ow-loading-clear .ow-loading-inner {
8420
+ gap: 10px;
8421
+ margin-bottom: calc(16px + env(safe-area-inset-bottom));
8422
+ padding: 16px 20px;
8423
+ border-radius: 16px;
8424
+ background: #0e0f12;
8425
+ pointer-events: auto;
8426
+ }
8427
+
8428
+ .ow-loading-clear .ow-loading-name {
8429
+ font-size: 16px;
8430
+ }
8431
+
8432
+ /* On the right: the play page's own buttons show on the left now that the card doesn't cover them. */
8433
+ .ow-loading.ow-loading-clear .ow-loading-close {
8434
+ right: calc(20px + env(safe-area-inset-right));
8435
+ left: auto;
8436
+ background: #0e0f12;
8437
+ pointer-events: auto;
8438
+ }
8439
+
8405
8440
  /* The game's cover, full-bleed, blurred and darkened (a blur hides the small size it is fetched at). */
8406
8441
  .ow-loading-cover {
8407
8442
  position: absolute;
@@ -13742,7 +13777,7 @@ body.share-frame {
13742
13777
  gap: 16px;
13743
13778
  margin-top: 12px;
13744
13779
  }
13745
- `;var q=JSON.parse(document.getElementById("ow-data").textContent),pe=q.game.slug,O=new URL(location.href).searchParams,ze=/^[2-9]$/.test(O.get("player")??"")?O.get("player"):null,ke=O.get("demo"),D=ke===null||ke==="0"?null:{paid:ke!=="free"};zt(D!==null);var $t=document.createElement("style");$t.textContent=`${Rt}
13780
+ `;var Y=JSON.parse(document.getElementById("ow-data").textContent),J=Y.game.slug,j=new URL(location.href).searchParams,De=/^[2-9]$/.test(j.get("player")??"")?j.get("player"):null,Ce=j.get("demo"),I=Ce===null||Ce==="0"?null:{paid:Ce!=="free"};jt(I!==null);var Ht=document.createElement("style");Ht.textContent=`${Bt}
13746
13781
  .ow-local-panel { position: fixed; z-index: 30; top: 64px; left: 10px; max-width: min(340px, calc(100vw - 20px)); padding: 12px 14px; border-radius: 12px; background: var(--glass); border: 1px solid var(--line); color: var(--text); font: 14px/1.45 var(--font); backdrop-filter: blur(12px); }
13747
13782
  .ow-local-panel[hidden] { display: none; }
13748
13783
  .ow-local-panel b { font-weight: 650; }
@@ -13750,4 +13785,4 @@ body.share-frame {
13750
13785
  .ow-local-panel p { margin: 0 0 6px; }
13751
13786
  .ow-local-toast { position: fixed; z-index: 40; left: 50%; bottom: 24px; transform: translateX(-50%); max-width: calc(100vw - 32px); padding: 10px 14px; border-radius: 10px; background: var(--glass); color: var(--text); font: 14px/1.4 var(--font); border: 1px solid var(--line); }
13752
13787
  .ow-local-toast[hidden] { display: none; }
13753
- `;document.head.append($t);document.body.classList.add("play");var R=document.getElementById("ow-game");R.setAttribute("sandbox",Qe);R.setAttribute("allow",et);var G=document.getElementById("ow-root");function ao(){let t=new URLSearchParams;for(let[o,r]of O)tt.has(o)||t.append(o,r);let e=t.toString();return e&&e.length<=400?`?${e}`:""}var _=w("div","ow-hud ow-pos-top-left"),Ee=w("div","ow-bar"),io='<svg viewBox="0 0 24 24" aria-hidden="true"><circle cx="12" cy="12" r="8" fill="none" stroke="currentColor" stroke-width="2"/><circle cx="12" cy="12" r="3" fill="currentColor"/></svg>',so='<svg viewBox="0 0 24 24" aria-hidden="true"><path d="M4 5.5A2.5 2.5 0 0 1 6.5 3h11A2.5 2.5 0 0 1 20 5.5v8a2.5 2.5 0 0 1-2.5 2.5H10l-4.2 3.4c-.5.4-1.3 0-1.3-.6V16A2.5 2.5 0 0 1 4 13.5z" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linejoin="round"/></svg>',lo='<svg viewBox="0 0 24 24" aria-hidden="true"><circle cx="10" cy="8" r="3.5" fill="none" stroke="currentColor" stroke-width="1.8"/><path d="M3.5 19.5c.8-3.4 3.3-5.5 6.5-5.5s5.7 2.1 6.5 5.5" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"/><path d="M19 7.5v6M16 10.5h6" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"/></svg>',Lt=Me("Local platform",io),Ct=Me("Chat (not on this computer)",so),At=Me("Another player",lo);Ee.append(Lt,Ct,At);_.append(Ee);var C=w("div","ow-local-panel");C.hidden=!0;G.append(_,C);var F=w("div","ow-local-toast");F.hidden=!0;G.append(F);var Et=0;function j(t){F.textContent=t,F.hidden=!1,window.clearTimeout(Et),Et=window.setTimeout(()=>F.hidden=!0,4e3)}Lt.addEventListener("click",()=>{C.hidden=!C.hidden,C.hidden||po()});Ct.addEventListener("click",()=>j("Chat is the platform\u2019s: it isn\u2019t on this computer."));At.addEventListener("click",()=>{window.open(K(),"_blank")});function K(){let t=new URL(location.href),e=Math.min(9,Number(ze??1)+1);return t.searchParams.set("player",String(e)),z&&t.searchParams.set("server",z),t.href}function po(){C.replaceChildren();let t=e=>{let o=document.createElement("p");o.innerHTML=e,C.append(o)};t(`<b>${ae(q.game.name)}</b> on this computer`),t(`You are <b>${ae(Tt?.name??"\u2026")}</b>${I?` in <code>${ae(I)}</code>`:""}`),t(`<a href="${ae(K())}" target="_blank">Open another player</a> (up to 9: <code>?player=2</code>\u2026)`),t("Saves, badges and scores are kept by <code>onceworlds serve</code> while it runs.")}function w(t,e=""){let o=document.createElement(t);return e&&(o.className=e),o}function Me(t,e){let o=w("button","ow-icon-btn");return o.type="button",o.title=t,o.setAttribute("aria-label",t),o.innerHTML=e,o}function ae(t){return t.replace(/[&<>"']/g,e=>`&#${e.charCodeAt(0)};`)}async function b(t,e={}){let o=new URL(`/__emulator/api/${t}`,location.href);ze&&o.searchParams.set("player",ze);let r=await fetch(o,{...e,headers:e.body?{"Content-Type":"application/json"}:void 0}),n=await r.json().catch(()=>null);if(!r.ok)throw new Error(n?.message??`The local platform answered ${r.status}`);return n}var co=Date.now(),le=b("me").then(({player:t,now:e})=>({player:t,timeOffset:Math.round(e-(co+Date.now())/2)})),Tt=null;le.then(t=>Tt=t.player).catch(()=>{});var d=null,I=null,B=null,de="",Pe=null,$e=!1,Re=0,Dt=0;le.then(t=>Dt=t.timeOffset).catch(()=>{});var z=Be.test(O.get("server")??"")?O.get("server"):null,ie={value:ut(pe)},v={hellos:0,joins:0,errors:[],lastAlive:0,closed:null},u=new Q(G,{now:()=>Date.now()+Dt,onSetting:(t,e)=>{let o=u.chooseSetting(t,e);o&&(d?.send({t:"state",k:U,v:o}),d?.send({t:"unready"}),u.handle({t:"unready"}),f.emit("room",{t:"unready"}))},onReady:t=>Ot(t),onStart:()=>d?.send({t:"start"}),onStop:()=>d?.send({t:"end"}),onInvite:()=>window.open(K(),"_blank"),onLayout:()=>N.changed()}),A=new Z(G,t=>f.emit("controls",t),()=>N.changed());function Ot(t){d?.send({t:"ready",ready:t}),u.setReadyLocal(t),f.emit("room",{t:"ready",id:de,ready:t})}function Le(t,e=!1){A.touch!==t&&(A.setTouch(t),e||f.emit("input",{touch:t}))}addEventListener("pointerdown",t=>t.isTrusted&&Le(t.pointerType!=="mouse"),!0);addEventListener("keydown",t=>t.isTrusted&&Le(!1),!0);var N=new ee(_t,t=>f.emit("reserved",t)),f=new Y(R,{async"session.get"(){let{player:t,timeOffset:e}=await le;return{player:t,game:{slug:pe,name:q.game.name,owner:"local"},audio:{volume:1,muted:!1},settings:{quality:"auto",reducedMotion:!1,showStats:!1},timeOffset:e,platformOrigin:location.origin}},"save.get":({key:t})=>b(`save?key=${encodeURIComponent(String(t))}`),"save.set":({key:t,value:e})=>b(`save?key=${encodeURIComponent(String(t))}`,{method:"PUT",body:JSON.stringify({value:e??null})}).then(()=>null),"save.delete":({key:t})=>b(`save?key=${encodeURIComponent(String(t))}`,{method:"DELETE"}).then(()=>null),"save.list":()=>b("saves"),async"room.join"(t){await le;let e=t??{};if(Pe=e.lobby==="card"||e.lobby==="bar"?e.lobby:null,$e=!ot(e),u.setSchema(He(e.settings)),e.party&&d)throw new Error("Parties go into matchmaking on onceworlds.com: the local platform keeps everyone where they are.");se();let o=!e.name&&!z&&!e.private&&ie.value&&mo(ie.value.key,e)?ie.value:null;if(ie.value=null,o){let r=await Pt({key:o.key,rejoin:o.rejoin,maxPlayers:e.maxPlayers,minPlayers:e.minPlayers,countdown:e.countdown,teams:e.teams,ranked:e.ranked}).catch(()=>null);if(r)return r;se()}return Pt(xo(e))},"room.leave"(){return se(),null},"net.fetch":()=>{throw new Error("onceworlds.fetch fills in secrets on onceworlds.com: it does nothing on this computer. Push a draft (onceworlds deploy) to try it.")},"badges.list":()=>b("badges"),"badges.award":({key:t})=>D?.paid?{awarded:!1}:b("badges",{method:"POST",body:JSON.stringify({key:String(t)})}).then(e=>(e.awarded&&j(`Badge earned: ${e.badge?.name??t}`),{awarded:e.awarded})),"leaderboards.submit":({board:t,score:e,lowerIsBetter:o})=>D?.paid?null:b("leaderboards",{method:"POST",body:JSON.stringify({board:String(t),score:Number(e),lowerIsBetter:o===!0})}),"leaderboards.top":({board:t,limit:e,lowerIsBetter:o})=>b(`leaderboards?board=${encodeURIComponent(String(t))}&limit=${Number(e)||10}&lower=${o===!0?1:0}`),"ratings.get":()=>null,"ratings.top":()=>[],"ui.invite"(){return window.open(K(),"_blank"),null},"ui.fullscreen"(){return document.documentElement.requestFullscreen?.().catch(()=>{}),null},"ui.tapped":()=>null,"ui.controls"(t){return A.setLayout(t),null},"ui.orientation":()=>null,"ui.menuPosition"(t){let e=t?.position;return(e==="top-left"||e==="top-right"||e==="bottom-left"||e==="bottom-right")&&(_.className=`ow-hud ow-pos-${e}`,N.changed()),null},"ui.look"(t){return Mt(t),null},"player.rename":()=>null,"demo.end":()=>D?go(D.paid):!1,"data.game.get":({key:t})=>b(`gamedata?key=${encodeURIComponent(String(t))}`),"data.game.op":t=>b("gamedata",{method:"POST",body:JSON.stringify(t)}),"player.avatar":t=>{let e=t?.id;return typeof e=="string"&&/^[A-Za-z0-9-]{1,64}$/.test(e)?je(e):null}},{"room.send":({d:t,to:e})=>d?.send({t:"msg",d:t,to:e}),"room.presence":({d:t})=>d?.send({t:"presence",d:t}),"room.hideLobby":({hidden:t})=>u.setHidden(t===!0),"room.state":({k:t,v:e,w:o})=>d?.send({t:"state",k:t,v:e,...typeof o=="number"&&Number.isSafeInteger(o)&&o>0&&o<=2147483647?{w:o}:{}}),"room.team":({id:t,team:e})=>d?.send({t:"team",id:String(t),team:Number(e)}),"room.open":({open:t})=>d?.send({t:"open",open:t===!0}),"room.result":({result:t})=>d?.send({t:"result",result:t}),"room.kick":({id:t})=>d?.send({t:"kick",id:String(t)}),"room.votekick":({id:t})=>d?.send({t:"votekick",id:String(t)}),"room.ready":({ready:t})=>{d?.send({t:"ready",ready:t===!0}),u.setReadyLocal(t===!0)},"room.unready":()=>{d?.send({t:"unready"}),u.handle({t:"unready"})},"room.transfer":({id:t})=>d?.send({t:"transfer",id:String(t)}),"room.start":({countdown:t,open:e})=>d?.send({t:"start",...Number.isFinite(t)?{countdown:Number(t)}:{},...e===!0?{open:!0}:{}}),"room.end":()=>d?.send({t:"end"}),"room.pause":({paused:t})=>d?.send({t:"pause",paused:t===!0}),"room.idle":({idle:t})=>d?.send({t:"idle",idle:t===!0}),"room.private":({k:t,v:e,id:o})=>typeof t=="string"&&d?.send({t:"private",k:t,v:e,...typeof o=="string"?{id:o}:{}}),"room.datareset":()=>d?.send({t:"datareset"}),"room.admit":({ids:t})=>d?.send({t:"admit",ids:Array.isArray(t)?t.filter(e=>typeof e=="string").slice(0,50):[]}),alive:()=>{v.lastAlive=Date.now()},stats:()=>{},hotkey:()=>{},vibrate:()=>{},input:t=>Le(t?.touch===!0,!0),error:t=>{v.errors.length<20&&v.errors.push(String(t?.message??t).slice(0,300))},"input.first":()=>{},console:()=>{},debug:()=>{}},()=>{v.hellos++,kt(),se(),_.className="ow-hud ow-pos-top-left",A.setLayout(null),Mt(null),f.emit("input",{touch:A.touch}),N.resend()},{demo:D!==null}),Se=null;function go(t){return Se??=new Promise(e=>{f.emit("pause",null);let o=w("div","ow-name ow-demo-end"),r=w("div","ow-name-form ow-demo-box"),n=w("h2");n.textContent="End of demo";let a=w("p","ow-demo-name");a.textContent=q.game.name;let i=w("button","ow-btn ow-btn-primary");i.type="button",i.textContent=t?"Buy":"Favorite",i.addEventListener("click",()=>j(t?"On onceworlds.com, Buy opens the game\u2019s store page.":"On onceworlds.com, Favorite follows the game."));let s=w("button","ow-text-btn ow-name-login");s.type="button",s.textContent="Back to game",s.addEventListener("click",()=>{o.remove(),Se=null,f.emit("resume",null),R.focus(),e(!0)}),r.append(n,a,i,s),o.append(r),G.append(o),i.focus()}),Se}function Mt(t){let{look:e}=nt(t);u.setLook(pt(e)),A.setLook(dt(e))}function _t(){let t=R.getBoundingClientRect();if(!t.width||!t.height)return null;let{stick:e,buttons:o}=A.reservedBoxes(),r=Ee.getBoundingClientRect(),n=parseFloat(getComputedStyle(_).paddingTop)||0,a=r.width&&r.height?{left:r.left-n,top:r.top-n,width:r.width+2*n,height:r.height+2*n}:null;return mt(t,[{kind:"menu",box:_.hidden?null:a},{kind:"lobby",box:u.reservedBox()},{kind:"stick",box:e},{kind:"buttons",box:o}])}for(let t of["resize","orientationchange"])addEventListener(t,()=>N.changed());typeof ResizeObserver=="function"&&new ResizeObserver(()=>N.changed()).observe(R);function ho(t){return t.slice(0,t.lastIndexOf(":"))}function mo(t,e){let o=(e.teams??0)>=2?e.teams:0,r=Math.min(S.roomMaxPlayersCap,Math.max(2,e.maxPlayers??16)),n=Ge(e.minPlayers,r,V);return ho(t)===`pub:${ge({mode:e.mode||"default",max:r,teams:o,ranked:e.ranked===!0,min:n})}`}function uo(){let t="abcdefghijklmnopqrstuvwxyz0123456789";return Array.from(crypto.getRandomValues(new Uint8Array(12)),e=>t[e%t.length]).join("")}function xo(t){let{name:e,maxPlayers:o,minPlayers:r,countdown:n,mode:a,teams:i,ranked:s}=t,h=t.minPlayersPrivate??r;if(e)return{name:e,maxPlayers:o,minPlayers:h,countdown:n,teams:i};if(t.private&&!z){z=uo(),xt(pe,z);let g=new URL(location.href);g.searchParams.set("server",z),history.replaceState(null,"",g.href)}return z?{server:z,maxPlayers:o,minPlayers:h,countdown:n,teams:i,private:t.private}:{mode:a,maxPlayers:o,minPlayers:r,countdown:n,teams:i,ranked:s}}async function Pt(t){let e=new ne(pe,t,{onMessage:n=>e===d&&fo(n),onClose:n=>e===d&&bo(n),onConnection:n=>{e===d&&(n||f.emit("room.connection",{connected:!1}))}});d=e;let o=await e.join();if(e!==d)throw new Error("Left the server while joining");let r=o.room.startsWith("private:")?{...o,invite:K()}:o;return de=o.you,B=o.match??null,I=o.room,v.joins++,Re=Ne(o.room)?.max??Math.min(t.maxPlayers??S.roomMaxPlayersDefault,S.roomMaxPlayersCap),u.enable(Pe,{ownCountdown:$e}),u.setRoom(r,Re),r}function fo(t){if(t.t==="update"||t.t==="move")return;if(t.t==="datareset"){j("This server\u2019s world was started over."),R.src=R.src;return}t.t==="chat"&&(t.entry.to||t.entry.channel)||t.t==="channel"||f.emit("room",t),t.t!=="welcome"&&u.handle(t),t.t==="welcome"?(u.setRoom(t,Re),B=t.match??null):t.t==="match"?B=t.match:t.t==="error"&&t.code==="cooldown"&&(j(t.message),u.setReadyLocal(!1),f.emit("room",{t:"ready",id:de,ready:!1}))}function bo(t){d=null,I=null,B=null,v.closed=t,u.setRoom(null),j(t==="replaced"?"You opened this game in another tab, so multiplayer moved there.":t==="kicked"?"You were removed from the server.":"Disconnected from the server."),f.emit("room.closed",{reason:t})}function se(){d&&(d.close(),d=null,I=null,B=null,u.setRoom(null))}window.__owLocal={get you(){return de},get room(){return I},get match(){return B},get lobby(){return Pe},get ownCountdown(){return $e},get hellos(){return v.hellos},get joins(){return v.joins},get errors(){return v.errors},get lastAlive(){return v.lastAlive},get closed(){return v.closed},get reserved(){return _t()},ready(t){return d?(Ot(t),!0):!1},start(t){return d?(d.send({t:"start",...Number.isFinite(t)?{countdown:Number(t)}:{}}),!0):!1},chrome(t){G.style.visibility=t?"":"hidden"}};R.src=`${q.gameOrigin}/${ao()}`;})();
13788
+ `;document.head.append(Ht);document.body.classList.add("play");var M=document.getElementById("ow-game");M.setAttribute("sandbox",pt);M.setAttribute("allow",dt);var F=document.getElementById("ow-root");function Ro(){let t=new URLSearchParams;for(let[o,r]of j)gt.has(o)||t.append(o,r);let e=t.toString();return e&&e.length<=400?`?${e}`:""}var B=S("div","ow-hud ow-pos-top-left"),_e=S("div","ow-bar"),Eo='<svg viewBox="0 0 24 24" aria-hidden="true"><circle cx="12" cy="12" r="8" fill="none" stroke="currentColor" stroke-width="2"/><circle cx="12" cy="12" r="3" fill="currentColor"/></svg>',Po='<svg viewBox="0 0 24 24" aria-hidden="true"><path d="M4 5.5A2.5 2.5 0 0 1 6.5 3h11A2.5 2.5 0 0 1 20 5.5v8a2.5 2.5 0 0 1-2.5 2.5H10l-4.2 3.4c-.5.4-1.3 0-1.3-.6V16A2.5 2.5 0 0 1 4 13.5z" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linejoin="round"/></svg>',Mo='<svg viewBox="0 0 24 24" aria-hidden="true"><circle cx="10" cy="8" r="3.5" fill="none" stroke="currentColor" stroke-width="1.8"/><path d="M3.5 19.5c.8-3.4 3.3-5.5 6.5-5.5s5.7 2.1 6.5 5.5" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"/><path d="M19 7.5v6M16 10.5h6" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"/></svg>',Ft=Ie("Local platform",Eo),qt=Ie("Chat (not on this computer)",Po),Kt=Ie("Another player",Mo);_e.append(Ft,qt,Kt);B.append(_e);var D=S("div","ow-local-panel");D.hidden=!0;F.append(B,D);var W=S("div","ow-local-toast");W.hidden=!0;F.append(W);var Nt=0;function N(t){W.textContent=t,W.hidden=!1,window.clearTimeout(Nt),Nt=window.setTimeout(()=>W.hidden=!0,4e3)}Ft.addEventListener("click",()=>{D.hidden=!D.hidden,D.hidden||Ao()});qt.addEventListener("click",()=>N("Chat is the platform\u2019s: it isn\u2019t on this computer."));Kt.addEventListener("click",()=>{window.open(X(),"_blank")});function X(){let t=new URL(location.href),e=Math.min(9,Number(De??1)+1);return t.searchParams.set("player",String(e)),P&&t.searchParams.set("server",P),t.href}function Ao(){D.replaceChildren();let t=e=>{let o=document.createElement("p");o.innerHTML=e,D.append(o)};t(`<b>${ce(Y.game.name)}</b> on this computer`),t(`You are <b>${ce(Vt?.name??"\u2026")}</b>${G?` in <code>${ce(G)}</code>`:""}`),t(`<a href="${ce(X())}" target="_blank">Open another player</a> (up to 9: <code>?player=2</code>\u2026)`),t("Saves, badges and scores are kept by <code>onceworlds serve</code> while it runs.")}function S(t,e=""){let o=document.createElement(t);return e&&(o.className=e),o}function Ie(t,e){let o=S("button","ow-icon-btn");return o.type="button",o.title=t,o.setAttribute("aria-label",t),o.innerHTML=e,o}function ce(t){return t.replace(/[&<>"']/g,e=>`&#${e.charCodeAt(0)};`)}async function k(t,e={}){let o=new URL(`/__emulator/api/${t}`,location.href);De&&o.searchParams.set("player",De);let r=await fetch(o,{...e,headers:e.body?{"Content-Type":"application/json"}:void 0}),n=await r.json().catch(()=>null);if(!r.ok)throw new Error(n?.message??`The local platform answered ${r.status}`);return n}var $o=Date.now(),me=k("me").then(({player:t,now:e})=>({player:t,timeOffset:Math.round(e-($o+Date.now())/2)})),Vt=null;me.then(t=>Vt=t.player).catch(()=>{});var g=null,G=null,U=null,xe="",je=null,Be=!1,Oe=0,Wt=0;me.then(t=>Wt=t.timeOffset).catch(()=>{});var P=Ye.test(j.get("server")??"")?j.get("server"):null,ge={value:At(J)},z={hellos:0,joins:0,errors:[],lastAlive:0,closed:null},f=new ae(F,{now:()=>Date.now()+Wt,onSetting:(t,e)=>{let o=f.chooseSetting(t,e);o&&(g?.send({t:"state",k:K,v:o}),g?.send({t:"unready"}),f.handle({t:"unready"}),v.emit("room",{t:"unready"}))},onReady:t=>Yt(t),onStart:()=>g?.send({t:"start"}),onStop:()=>g?.send({t:"end"}),onInvite:()=>window.open(X(),"_blank"),onLayout:()=>H.changed()}),O=new ne(F,t=>v.emit("controls",t),()=>H.changed());function Yt(t){g?.send({t:"ready",ready:t}),f.setReadyLocal(t),v.emit("room",{t:"ready",id:xe,ready:t})}function Ne(t,e=!1){O.touch!==t&&(O.setTouch(t),e||v.emit("input",{touch:t}))}addEventListener("pointerdown",t=>t.isTrusted&&Ne(t.pointerType!=="mouse"),!0);addEventListener("keydown",t=>t.isTrusted&&Ne(!1),!0);var H=new ie(Jt,t=>v.emit("reserved",t)),he=new te(async()=>({game:J,player:null})),v=new ee(M,{async"session.get"(){let{player:t,timeOffset:e}=await me;return{player:t,game:{slug:J,name:Y.game.name,owner:"local"},audio:{volume:1,muted:!1},settings:{quality:"auto",reducedMotion:!1,showStats:!1},timeOffset:e,platformOrigin:location.origin}},"save.get":({key:t})=>k(`save?key=${encodeURIComponent(String(t))}`),"save.set":({key:t,value:e})=>k(`save?key=${encodeURIComponent(String(t))}`,{method:"PUT",body:JSON.stringify({value:e??null})}).then(()=>null),"save.delete":({key:t})=>k(`save?key=${encodeURIComponent(String(t))}`,{method:"DELETE"}).then(()=>null),"save.list":()=>k("saves"),"storage.open":t=>he.read(t),"storage.commit":t=>he.commit(t),"storage.delete":t=>he.remove(t),"storage.list":()=>he.list(),async"room.join"(t){await me;let e=t??{};if(je=e.lobby==="card"||e.lobby==="bar"?e.lobby:null,Be=!ut(e),f.setSchema(Qe(e.settings)),e.party&&g)throw new Error("Parties go into matchmaking on onceworlds.com: the local platform keeps everyone where they are.");ue();let o=!e.name&&!P&&!e.private&&ge.value&&To(ge.value.key,e)?ge.value:null;if(ge.value=null,o){let r=await Ut({key:o.key,rejoin:o.rejoin,maxPlayers:e.maxPlayers,minPlayers:e.minPlayers,countdown:e.countdown,teams:e.teams,ranked:e.ranked}).catch(()=>null);if(r)return r;ue()}return Ut(Oo(e))},"room.leave"(){return ue(),null},"net.fetch":()=>{throw new Error("onceworlds.fetch fills in secrets on onceworlds.com: it does nothing on this computer. Push a draft (onceworlds deploy) to try it.")},"badges.list":()=>k("badges"),"badges.award":({key:t})=>I?.paid?{awarded:!1}:k("badges",{method:"POST",body:JSON.stringify({key:String(t)})}).then(e=>(e.awarded&&N(`Badge earned: ${e.badge?.name??t}`),{awarded:e.awarded})),"leaderboards.submit":({board:t,score:e,lowerIsBetter:o})=>I?.paid?null:k("leaderboards",{method:"POST",body:JSON.stringify({board:String(t),score:Number(e),lowerIsBetter:o===!0})}),"leaderboards.top":({board:t,limit:e,lowerIsBetter:o})=>k(`leaderboards?board=${encodeURIComponent(String(t))}&limit=${Number(e)||10}&lower=${o===!0?1:0}`),"ratings.get":()=>null,"ratings.top":()=>[],"ui.invite"(){return window.open(X(),"_blank"),null},"ui.fullscreen"(){return document.documentElement.requestFullscreen?.().catch(()=>{}),null},"ui.tapped":()=>null,"ui.controls"(t){return O.setLayout(t),null},"ui.orientation":()=>null,"ui.menuPosition"(t){let e=t?.position;return(e==="top-left"||e==="top-right"||e==="bottom-left"||e==="bottom-right")&&(B.className=`ow-hud ow-pos-${e}`,H.changed()),null},"ui.look"(t){return Gt(t),null},"player.rename":()=>null,"demo.end":()=>I?Lo(I.paid):!1,"data.game.get":({key:t})=>k(`gamedata?key=${encodeURIComponent(String(t))}`),"data.game.op":t=>k("gamedata",{method:"POST",body:JSON.stringify(t)}),"player.avatar":t=>{let e=t?.id;return typeof e=="string"&&/^[A-Za-z0-9-]{1,64}$/.test(e)?Ve(e):null}},{"room.send":({d:t,to:e})=>g?.send({t:"msg",d:t,to:e}),"room.presence":({d:t})=>g?.send({t:"presence",d:t}),"room.hideLobby":({hidden:t})=>f.setHidden(t===!0),"room.state":({k:t,v:e,w:o})=>g?.send({t:"state",k:t,v:e,...typeof o=="number"&&Number.isSafeInteger(o)&&o>0&&o<=2147483647?{w:o}:{}}),"room.team":({id:t,team:e})=>g?.send({t:"team",id:String(t),team:Number(e)}),"room.open":({open:t})=>g?.send({t:"open",open:t===!0}),"room.result":({result:t})=>g?.send({t:"result",result:t}),"room.kick":({id:t})=>g?.send({t:"kick",id:String(t)}),"room.votekick":({id:t})=>g?.send({t:"votekick",id:String(t)}),"room.ready":({ready:t})=>{g?.send({t:"ready",ready:t===!0}),f.setReadyLocal(t===!0)},"room.unready":()=>{g?.send({t:"unready"}),f.handle({t:"unready"})},"room.transfer":({id:t})=>g?.send({t:"transfer",id:String(t)}),"room.start":({countdown:t,open:e})=>g?.send({t:"start",...Number.isFinite(t)?{countdown:Number(t)}:{},...e===!0?{open:!0}:{}}),"room.end":()=>g?.send({t:"end"}),"room.pause":({paused:t})=>g?.send({t:"pause",paused:t===!0}),"room.idle":({idle:t})=>g?.send({t:"idle",idle:t===!0}),"room.private":({k:t,v:e,id:o})=>typeof t=="string"&&g?.send({t:"private",k:t,v:e,...typeof o=="string"?{id:o}:{}}),"room.datareset":()=>g?.send({t:"datareset"}),"room.admit":({ids:t})=>g?.send({t:"admit",ids:Array.isArray(t)?t.filter(e=>typeof e=="string").slice(0,50):[]}),alive:()=>{z.lastAlive=Date.now()},stats:()=>{},hotkey:()=>{},vibrate:()=>{},input:t=>Ne(t?.touch===!0,!0),error:t=>{z.errors.length<20&&z.errors.push(String(t?.message??t).slice(0,300))},"input.first":()=>{},console:()=>{},debug:()=>{}},()=>{z.hellos++,_t(),ue(),B.className="ow-hud ow-pos-top-left",O.setLayout(null),Gt(null),v.emit("input",{touch:O.touch}),H.resend()},{demo:I!==null}),Te=null;function Lo(t){return Te??=new Promise(e=>{v.emit("pause",null);let o=S("div","ow-name ow-demo-end"),r=S("div","ow-name-form ow-demo-box"),n=S("h2");n.textContent="End of demo";let a=S("p","ow-demo-name");a.textContent=Y.game.name;let i=S("button","ow-btn ow-btn-primary");i.type="button",i.textContent=t?"Buy":"Favorite",i.addEventListener("click",()=>N(t?"On onceworlds.com, Buy opens the game\u2019s store page.":"On onceworlds.com, Favorite follows the game."));let s=S("button","ow-text-btn ow-name-login");s.type="button",s.textContent="Back to game",s.addEventListener("click",()=>{o.remove(),Te=null,v.emit("resume",null),M.focus(),e(!0)}),r.append(n,a,i,s),o.append(r),F.append(o),i.focus()}),Te}function Gt(t){let{look:e}=xt(t);f.setLook(St(e)),O.setLook(zt(e))}function Jt(){let t=M.getBoundingClientRect();if(!t.width||!t.height)return null;let{stick:e,buttons:o}=O.reservedBoxes(),r=_e.getBoundingClientRect(),n=parseFloat(getComputedStyle(B).paddingTop)||0,a=r.width&&r.height?{left:r.left-n,top:r.top-n,width:r.width+2*n,height:r.height+2*n}:null;return Mt(t,[{kind:"menu",box:B.hidden?null:a},{kind:"lobby",box:f.reservedBox()},{kind:"stick",box:e},{kind:"buttons",box:o}])}for(let t of["resize","orientationchange"])addEventListener(t,()=>H.changed());typeof ResizeObserver=="function"&&new ResizeObserver(()=>H.changed()).observe(M);function Co(t){return t.slice(0,t.lastIndexOf(":"))}function To(t,e){let o=(e.teams??0)>=2?e.teams:0,r=Math.min(E.roomMaxPlayersCap,Math.max(2,e.maxPlayers??16)),n=Xe(e.minPlayers,r,Z);return Co(t)===`pub:${we({mode:e.mode||"default",max:r,teams:o,ranked:e.ranked===!0,min:n})}`}function Do(){let t="abcdefghijklmnopqrstuvwxyz0123456789";return Array.from(crypto.getRandomValues(new Uint8Array(12)),e=>t[e%t.length]).join("")}function Oo(t){let{name:e,maxPlayers:o,minPlayers:r,countdown:n,mode:a,teams:i,ranked:s}=t,c=t.minPlayersPrivate??r;if(e)return{name:e,maxPlayers:o,minPlayers:c,countdown:n,teams:i};if(t.private&&!P){P=Do(),$t(J,P);let d=new URL(location.href);d.searchParams.set("server",P),history.replaceState(null,"",d.href)}return P?{server:P,maxPlayers:o,minPlayers:c,countdown:n,teams:i,private:t.private}:{mode:a,maxPlayers:o,minPlayers:r,countdown:n,teams:i,ranked:s}}async function Ut(t){let e=new de(J,t,{onMessage:n=>e===g&&_o(n),onClose:n=>e===g&&Io(n),onConnection:n=>{e===g&&(n||v.emit("room.connection",{connected:!1}))}});g=e;let o=await e.join();if(e!==g)throw new Error("Left the server while joining");let r=o.room.startsWith("private:")?{...o,invite:X()}:o;return xe=o.you,U=o.match??null,G=o.room,z.joins++,Oe=Je(o.room)?.max??Math.min(t.maxPlayers??E.roomMaxPlayersDefault,E.roomMaxPlayersCap),f.enable(je,{ownCountdown:Be}),f.setRoom(r,Oe),r}function _o(t){if(t.t==="update"||t.t==="move")return;if(t.t==="datareset"){N("This server\u2019s world was started over."),M.src=M.src;return}t.t==="chat"&&(t.entry.to||t.entry.channel)||t.t==="channel"||v.emit("room",t),t.t!=="welcome"&&f.handle(t),t.t==="welcome"?(f.setRoom(t,Oe),U=t.match??null):t.t==="match"?U=t.match:t.t==="error"&&t.code==="cooldown"&&(N(t.message),f.setReadyLocal(!1),v.emit("room",{t:"ready",id:xe,ready:!1}))}function Io(t){g=null,G=null,U=null,z.closed=t,f.setRoom(null),N(t==="replaced"?"You opened this game in another tab, so multiplayer moved there.":t==="kicked"?"You were removed from the server.":"Disconnected from the server."),v.emit("room.closed",{reason:t})}function ue(){g&&(g.close(),g=null,G=null,U=null,f.setRoom(null))}window.__owLocal={get you(){return xe},get room(){return G},get match(){return U},get lobby(){return je},get ownCountdown(){return Be},get hellos(){return z.hellos},get joins(){return z.joins},get errors(){return z.errors},get lastAlive(){return z.lastAlive},get closed(){return z.closed},get reserved(){return Jt()},ready(t){return g?(Yt(t),!0):!1},start(t){return g?(g.send({t:"start",...Number.isFinite(t)?{countdown:Number(t)}:{}}),!0):!1},chrome(t){F.style.visibility=t?"":"hidden"}};M.src=`${Y.gameOrigin}/${Ro()}`;})();
package/dist/sdk.js CHANGED
@@ -1,5 +1,5 @@
1
- "use strict";(()=>{var pn=Object.defineProperty;var fn=(n,e,t)=>e in n?pn(n,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):n[e]=t;var p=(n,e,t)=>fn(n,typeof e!="symbol"?e+"":e,t);var gn=["#f6dcc5","#ebc29f","#d4a07a","#b07a55","#875839","#5e3d29","#93c9bb","#a8c595","#94bcd3","#ab9bd9","#dca3ad","#b3bccb"],Ve=["#c95f56","#dc8a4f","#e2bd52","#9cc27a","#5a8a5e","#4f9a8e","#6fb7c8","#5b87c5","#465089","#8b68a8","#dc8fae","#f2eee6","#a9a8ad","#5d5c63","#2b2a30","#80604d"],hn=["Happy","Grin","Shades","Wink","Surprised","Determined","Joyful","Shy"],yn=["None","Sprout","Cap","Beanie","Crown","Headphones","Horns","Antenna","Bow","Halo","Party hat","Cat ears","Short hair","Tuft","Bob","Spikes","Bun","Curls","Long","Mop"];var bn=["Plain","Band","Spots","Stripes","Star"];var wn={skin:gn.length,shirt:Ve.length,pants:Ve.length,face:hn.length,hat:yn.length,top:bn.length};function We(n){if(!n||typeof n!="object")return null;let e=n,t={};for(let[r,s]of Object.entries(wn)){let o=e[r],i=typeof o=="number"?o:typeof o=="string"&&/^[0-9]{1,3}$/.test(o)?Number(o):NaN;if(!Number.isInteger(i)||i<0||i>=s)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 kn="host:",H="data:";function J(n){return n.startsWith(kn)||n.startsWith(H)}var Ye=/^(?!__proto__$)[A-Za-z0-9_.:-]{1,59}$/;function ke(n){return n.startsWith(H)}function ve(n){return H+n}function Qe(n){return n.startsWith("private:")||n.startsWith("room:")}function Se(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 xe=/^[A-Za-z][A-Za-z0-9_.-]{0,31}$/;var vn={counter:["add"],list:["push"],record:["best"],map:["claim","release"],value:["set"]},Sn={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 xn(n){return vn[n].map(e=>`ow.data.game.${Sn[e]}`).join(" or ")}function Me(n,e){let r=Math.floor(e/864e5);if(n==="daily")return{start:r*864e5,next:(r+1)*864e5};let s=r-(r+3)%7;return{start:s*864e5,next:(s+7)*864e5}}function Mn(n,e){switch(n.type){case"counter":return{type:"counter",value:n.min,...n.reset?{resetsAt:Me(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 Mn(n,t);if(e.type==="counter"&&n.type==="counter"){if(!n.reset)return{type:"counter",value:e.value};let o=Me(n.reset,t);return{type:"counter",value:(e.period??0)>=o.start?e.value:n.min,resetsAt:o.next}}let{period:r,...s}=e;return s}function Ze(n,e,t,r,s){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 o={id:r.id,name:r.name},i=Rn(n,e,s);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)),c=n.reset?Me(n.reset,s):null;return{next:{type:"counter",value:l,...c?{resetsAt:c.next,period:c.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:o,at:s},...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:o,at:s},result:{type:"record",value:t.n,by:o,at:s,record:!0}}}case"map":{if(t.op!=="claim"&&t.op!=="release"||n.type!=="map")break;let l={...i.fields},c=Object.hasOwn(l,t.field)?l[t.field]:void 0;return t.op==="release"?!c||c.by.id!==r.id?{next:i,result:{type:"map",ok:!1,...c?{holder:c.by}:{}}}:(delete l[t.field],{next:{type:"map",fields:l},result:{type:"map",ok:!0}}):c?{next:i,result:{type:"map",ok:c.by.id===r.id,holder:c.by}}:Object.values(l).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(l).length>=n.fields?{code:"full",message:`claim('${t.key}'): all ${n.fields} fields are taken (onceworlds.json's "fields").`}:(l[t.field]={by:o,at:s},{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:s},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 ${xn(n.type)}.`}}var Je=n=>n.replace(/[\u0000-\u001f\u007f]/g," ").replace(/\s+/g," ").trim();var En=/^[a-z0-9][a-z0-9-]{0,19}$/;function Xe(n){if(!n||typeof n!="object")return null;let e=n,t=[];for(let s of Array.isArray(e.buttons)?e.buttons:[]){if(t.length>=S.controlButtons)break;let{id:o,label:i}=s??{};if(typeof o!="string"||!En.test(o)||t.some(c=>c.id===o))continue;let l=typeof i=="string"?i.replace(/[\u0000-\u001f\u007f]/g,"").replace(/\s+/g," ").trim().slice(0,S.controlLabelLength).trim():"";t.push({id:o,label:l||o})}let r=e.stick===!0;return r||t.length>0?{stick:r,zone:e.zone==="corner"?"corner":"wide",buttons:t}:null}var Y="host:ow.settings",Pn=/^[a-z][a-zA-Z0-9]{0,15}$/;function Re(n){if(!Array.isArray(n))return[];let e=[];for(let t of n){if(e.length>=6)break;let{id:r,label:s,options:o,default:i}=t??{};if(typeof r!="string"||!Pn.test(r)||e.some(d=>d.id===r)||!Array.isArray(o))continue;let l=[];for(let d of o){let m=typeof d=="object"&&d!==null?d.value:d;if(typeof m!="string"&&typeof m!="number"||typeof m=="number"&&!Number.isFinite(m)||l.length>=8||l.some(f=>f.value===m))continue;let h=typeof d=="object"&&d!==null&&typeof d.label=="string"?d.label:String(m);l.push({value:m,label:Je(h).slice(0,20)||String(m)})}if(l.length<2)continue;let c=typeof s=="string"?Je(s).slice(0,24):"";e.push({id:r,label:c||r,options:l,default:l.some(d=>d.value===i)?i:l[0].value})}return e}function et(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 tt="onceworlds:hello",nt="onceworlds:connect",rt=/^[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 ot=["log","info","warn","error"],st="onceworlds-console";var it=/^[A-Za-z0-9-]{1,64}$/;function at(){let n=1,e=!1,t=()=>e?0:n,r=new Map;if(typeof AudioNode<"u"&&typeof AudioDestinationNode<"u"){let d=AudioNode.prototype.connect,m=AudioNode.prototype.disconnect,h=w=>typeof OfflineAudioContext>"u"||!(w instanceof OfflineAudioContext),f=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,f(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 m.apply(this,w)}}let s=new WeakMap,o=new Set,i=typeof HTMLMediaElement<"u"?Object.getOwnPropertyDescriptor(HTMLMediaElement.prototype,"volume"):void 0,l=d=>i?.set?.call(d,Ee((s.get(d)??1)*t())),c=d=>{s.has(d)||!i?.get||(s.set(d,i.get.call(d)),o.add(new WeakRef(d)))};if(i?.get&&i.set){Object.defineProperty(HTMLMediaElement.prototype,"volume",{configurable:!0,enumerable:i.enumerable,get(){return s.has(this)?s.get(this):i.get.call(this)},set(m){c(this),s.set(this,Ee(Number(m))),l(this)}});let d=HTMLMediaElement.prototype.play;HTMLMediaElement.prototype.play=function(){return c(this),l(this),d.call(this)}}return{get volume(){return n},get muted(){return e},apply(d){n=Ee(d.volume),e=d.muted;for(let[m,h]of r)h.gain.setTargetAtTime(t(),m.currentTime,.02);for(let m of o){let h=m.deref();h?l(h):o.delete(m)}}}}function Ee(n){return Number.isFinite(n)?Math.min(1,Math.max(0,n)):1}function lt(n){try{let e=n?.getAttribute("data-build");return e&&rt.test(e)?e:null}catch{return null}}var O={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 $n=["video/webm;codecs=vp9","video/webm;codecs=vp8","video/webm","video/mp4;codecs=avc1","video/mp4"],Cn=3e3,ct=250,Ln="host:ow.flow";function ut(n){let e=n?.[Ln],t=e&&typeof e=="object"?e.phase:void 0;return typeof t=="string"?t:void 0}var Pe=250,oe=32,se=18,_n=.02,Ae={needed:6,of:8};function Dn(){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 F=(n,e,t,r)=>typeof n=="number"&&Number.isFinite(n)?Math.min(t,Math.max(e,Math.round(n))):r;function On(n){if(!n||typeof n!="object")return null;let e=n;return e.t==="stop"?{t:"stop"}:e.t!=="start"?null:{t:"start",ms:F(e.ms,1e3,15e3,O.ms),long:F(e.long,160,1920,O.long),short:F(e.short,90,1080,O.short),fps:F(e.fps,5,60,O.fps),bitsPerSecond:F(e.bitsPerSecond,25e4,8e6,O.bitsPerSecond),maxBytes:F(e.maxBytes,64*1024,O.maxBytes,O.maxBytes)}}function ie(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 s=typeof r.getBoundingClientRect=="function"?r.getBoundingClientRect():null;if(s&&(s.width<32||s.height<32))continue;let o=s?s.width*s.height:r.width*r.height;o>t&&(e=r,t=o)}catch{}return e}function Tn(n,e,t,r){let s=n>=e,o=Math.min(1,(s?t:r)/n,(s?r:t)/e);if(o>=1)return{width:n,height:e,scale:1};let i=l=>Math.max(2,Math.floor(l*o/2)*2);return{width:i(n),height:i(e),scale:o}}function In(n,e){return new Promise(t=>{e.requestAnimationFrame(()=>{try{let r=n.width,s=n.height,o=Math.min(O.long,Math.max(480,r)),i=Math.round(o*9/16),l=e.document.createElement("canvas");l.width=o,l.height=i;let c=l.getContext("2d");if(!c)return t(null);c.fillStyle="#000",c.fillRect(0,0,o,i);let d=r/s,m=d>=1.25&&d<=2.4?Math.max(o/r,i/s):Math.min(o/r,i/s);c.drawImage(n,(o-r*m)/2,(i-s*m)/2,r*m,s*m),l.toBlob(h=>h?h.arrayBuffer().then(t,()=>t(null)):t(null),"image/jpeg",.85)}catch{t(null)}})})}function Bn(n,e){let t=null,r=null;return s=>{e.requestAnimationFrame(()=>{try{if(!t){let c=e.document.createElement("canvas");c.width=oe,c.height=se,t=c.getContext("2d",{willReadFrequently:!0})}if(!t)return s(null);t.drawImage(n,0,0,oe,se);let o=t.getImageData(0,0,oe,se).data,i=r;if(r=new Uint8ClampedArray(o),!i)return s(null);let l=0;for(let c=0;c+2<o.length;c+=4){let d=o[c]*2+o[c+1]*5+o[c+2],m=i[c]*2+i[c+1]*5+i[c+2];Math.abs(d-m)>128&&l++}s(l/(oe*se))}catch{s(null)}})}}function Nn(n,e,t,r){return new Promise(s=>{let o=Bn(n,e),i=[],l=0,c=0,d=!1,m=()=>{if(r()||l>=O.ceilingMs)return s(!1);let h=null;try{h=t()}catch{}h&&h.phase!=="lobby"&&(d=!0);let f=h?.flow;if(h?.phase==="playing"&&h.paused!==!0&&(f===void 0||f==="playing")){if(c+=Pe,c>(f===void 0?O.playSettleMs:O.flowSettleMs))return s(!0)}else c=0;if(!d){if(l>=O.motionGraceMs&&i.length>=Ae.of&&i.filter(Boolean).length>=Ae.needed)return s(!0);o(w=>{i.push(w!==null&&w>=_n),i.length>Ae.of&&i.shift()})}l+=Pe,e.setTimeout(m,Pe)};m()})}function dt(n,e){let t=e.MediaRecorder;return typeof n.captureStream!="function"||typeof t!="function"?null:$n.find(r=>{try{return t.isTypeSupported(r)}catch{return!1}})??null}function mt(n,e=Dn(),t=()=>null){let r=null,s=l=>{try{n(l)}catch{}},o=l=>s({t:"none",reason:l});function i(l){if(r)return;if(!e)return o("unsupported");let c=e,d=!1,m=null;r={cancel(){d=!0,m!==null&&c.clearTimeout(m)}};let h=y=>{r=null,!d&&y&&s(y)},f=0,w=()=>{if(d)return h(null);let y=ie(c.document.querySelectorAll("canvas"));if(y){if(m=null,!dt(y,c))return h({t:"none",reason:"unsupported"});Nn(y,c,t,()=>d).then(k=>{if(d)return null;if(!k)return{t:"none",reason:"not-playing"};let E=ie(c.document.querySelectorAll("canvas"))??y;return Gn(E,l,c,()=>d,()=>!d&&s({t:"started"}))}).then(h,()=>h({t:"none",reason:"failed"}))}else++f>Cn/ct?h({t:"none",reason:"no-canvas"}):m=c.setTimeout(w,ct)};w()}return{receive(l){try{let c=On(l);if(!c)return;if(c.t==="stop"){r?.cancel(),r=null;return}i(c)}catch{r=null,o("failed")}}}}function Gn(n,e,t,r,s){let o=t.MediaRecorder,i=dt(n,t);if(!o||!i)return Promise.resolve({t:"none",reason:"unsupported"});let l=Tn(n.width,n.height,e.long,e.short),c=!1,d=n;if(l.scale<1){let f=t.document.createElement("canvas");f.width=l.width,f.height=l.height;let w=f.getContext("2d");if(!w)return Promise.resolve({t:"none",reason:"unsupported"});c=!0;let y=()=>{if(c){try{w.drawImage(n,0,0,l.width,l.height)}catch{}t.requestAnimationFrame(y)}};y(),d=f}let m,h;try{m=d.captureStream(e.fps),h=new o(m,{mimeType:i,videoBitsPerSecond:e.bitsPerSecond})}catch{return c=!1,Promise.resolve({t:"none",reason:"failed"})}return new Promise(f=>{let w=[],y=0,k=Promise.resolve(null),E=t.setTimeout(()=>{k=In(n,t)},Math.round(e.ms/2)),_=null,T=()=>{try{h.state!=="inactive"&&h.stop()}catch{}},M=()=>{c=!1,t.clearTimeout(E),_!==null&&t.clearTimeout(_);try{for(let L of m.getTracks())L.stop()}catch{}};h.ondataavailable=L=>{!L.data||L.data.size===0||(w.push(L.data),y+=L.data.size,y>e.maxBytes*.85&&T())},h.onerror=()=>{M(),f(r()?null:{t:"none",reason:"failed"})},h.onstop=()=>{if(M(),r())return f(null);let L=new Blob(w,{type:h.mimeType||i});Promise.all([L.arrayBuffer(),k.catch(()=>null)]).then(([U,N])=>{if(U.byteLength===0)return f({t:"none",reason:"failed"});if(U.byteLength>e.maxBytes)return f({t:"none",reason:"too-large"});f({t:"done",type:L.type||i,video:U,poster:N,width:l.width,height:l.height})}).catch(()=>f({t:"none",reason:"failed"}))};try{h.start(1e3)}catch{return M(),f({t:"none",reason:"failed"})}s(),_=t.setTimeout(()=>{_=null,T()},e.ms);let P=()=>{if(h.state!=="inactive"){if(r())return T();t.setTimeout(P,200)}};t.setTimeout(P,200)})}var jn=200,pt=2,K=20,ft=200;function gt(n){try{return new URLSearchParams(n).get(st)==="1"}catch{return!1}}function ht(n){return typeof n=="object"&&n!==null&&n.solo===!0?"standalone":"platform"}function yt(n){return typeof n=="object"&&n!==null&&n.demo===!0}function bt(n){try{let e=new URLSearchParams(n).get("demo");return e!==null&&e!=="0"&&e!=="false"}catch{return!1}}function wt(n,e,t=Date.now,r=setTimeout){let s=null,o=[],i=-1/0,l=0,c=0,d=!1,m=!1,h=y=>{s?s(y):o.length<jn&&o.push(y)},f=()=>{let y=t();return y-i>=1e3&&(i=y,l=0),l<S.consoleLinesPerSecond?(l++,!0):(c++,d||(d=!0,r(()=>{d=!1;let k=c;c=0,k>0&&f()&&h({level:"warn",text:`${k} more ${k===1?"line":"lines"} left out`,at:t()})},Math.max(0,1e3-(y-i)))),!1)},w=(y,k,E)=>{if(!f())return;let _=kt(e?k.split(`${e}/`).join(""):k);h({level:y,text:_,at:t(),...E?{source:E.source.slice(0,300),line:E.line,column:E.column}:{}})};for(let y of ot){let k=n[y];typeof k=="function"&&(n[y]=function(...E){if(k.apply(n,E),!m){m=!0;try{w(y,Hn(E))}catch{}finally{m=!1}}})}return{error(y,k){if(!m){m=!0;try{w("error",y,k)}catch{}finally{m=!1}}},connect(y){s=y;for(let k of o.splice(0))y(k)}}}function Hn(n){let e="",t=n;if(typeof n[0]=="string"){let r=1;e=n[0].replace(/%[sdifoOc%]/g,s=>{if(s==="%%")return"%";if(r>=n.length)return s;let o=n[r++];return s==="%c"?"":s==="%d"||s==="%i"?String(typeof o=="number"?Math.trunc(o):parseInt(Q(o),10)):s==="%f"?String(typeof o=="number"?o:parseFloat(Q(o))):s==="%s"?Q(o):V(o)}),t=n.slice(r)}for(let r of t)e+=e?` ${Q(r)}`:Q(r);return kt(e)}function Q(n){return typeof n=="string"?n:V(n)}function V(n,e=0){try{switch(typeof n){case"string":return JSON.stringify(n.length>ft?`${n.slice(0,ft)}\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 ae(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>=pt?`Array(${n.length})`:`[${n.slice(0,K).map(i=>V(i,e+1)).join(", ")}${n.length>K?`, \u2026${n.length-K} more`:""}]`;let t=typeof n.constructor=="function"&&n.constructor!==Object?`${n.constructor.name} `:"";if(e>=pt)return`${t}{\u2026}`;let r=Object.keys(n),s=r.slice(0,K).map(o=>`${/^[A-Za-z_$][\w$]*$/.test(o)?o:JSON.stringify(o)}: ${V(n[o],e+1)}`);return`${t}{${s.join(", ")}${r.length>K?`, \u2026${r.length-K} more`:""}}`}catch{return Object.prototype.toString.call(n)}}function ae(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 kt(n){return n.length>S.consoleLineLength?`${n.slice(0,S.consoleLineLength-1)}\u2026`:n}var qn={wasd:{up:"w",down:"s",left:"a",right:"d"},arrows:{up:"ArrowUp",down:"ArrowDown",left:"ArrowLeft",right:"ArrowRight"}},zn=.45,Un=.3,$e={" ":["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]},le=class{constructor(e,t){p(this,"touch");p(this,"stick",{x:0,y:0});p(this,"held",new Set);p(this,"downs",new Map);p(this,"stickMode");p(this,"buttonKeys",new Map);p(this,"down",new Map);p(this,"show");p(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:[],s=e?Xe({stick:this.stickMode!==void 0,zone:t.zone,buttons:r}):null;this.buttonKeys=new Map;for(let o of s?.buttons??[]){let i=r.find(l=>l?.id===o.id)?.key;typeof i=="string"&&i&&this.buttonKeys.set(o.id,i)}this.show(s),s?this.update():this.release()}receive(e){let t=s=>typeof s=="number"&&Number.isFinite(s)?Math.max(-1,Math.min(1,s)):0;this.stick.x=t(e?.x),this.stick.y=t(e?.y);let r=new Set(Array.isArray(e?.buttons)?e.buttons.filter(s=>typeof s=="string"):[]);for(let s of r)this.held.has(s)||this.downs.set(s,(this.downs.get(s)??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=qn[this.stickMode],r=(s,o)=>{o>(this.down.has(s)?Un:zn)&&e.set(s,vt(s))};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,vt(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 vt(n){let e=n==="Space"?" ":n;return Object.prototype.hasOwnProperty.call($e,e)?{key:e,code:$e[e][0],keyCode:$e[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 Fn(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 xt(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 Mt(n,e){let t=new Set,r=async(s,o)=>{let i=`onceworlds.data.server.${o===null?"delete":"set"}('${String(s).slice(0,40)}')`,l=n();if(typeof s!="string"||!Ye.test(s))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 c;try{c=JSON.stringify(o??null)}catch{c=void 0}return c===void 0?(e(`${i} did nothing: the value must be plain JSON data (numbers, text, lists, objects).`),!1):Se(c)>S.stateValueBytes-128?(e(`${i} did nothing: the value is ${Math.ceil(Se(c)/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 l._writeAcked(ve(s),o??null)};return{get(s){let o=n();if(!o||typeof s!="string")return null;let i=o.state[ve(s)];return i===void 0?null:i},all(){let s=n(),o={};if(!s)return o;for(let[i,l]of Object.entries(s.state))i.startsWith("data:")&&(o[i.slice(5)]=l);return o},set:(s,o)=>r(s,o??null),delete:s=>r(s,null),get kept(){return n()?.kept??!1},get canWrite(){let s=n();return!!(s&&!s.closed&&s.isHost)},async reset(){let s=n();return s?s.owner!==s.me.id&&s.kind!=="solo"?(e("onceworlds.data.server.reset() did nothing: only a private server's owner starts its world over (room.owner)."),!1):s._resetData():(e("onceworlds.data.server.reset() did nothing: you're not in a room."),!1)},on(s,o){return s!=="change"||typeof o!="function"?()=>{}:(t.add(o),()=>t.delete(o))},_changed(s,o,i){for(let l of t)try{l(s,o??null,i)}catch(c){console.error('[onceworlds] error in data.server "change" listener',c)}}}}function Rt(n,e){let t=async(s,o,i,l)=>{if(typeof s.key!="string"||!xe.test(s.key))return e(`${o} did nothing: '${String(s.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(s))}catch(c){return e(`${o} did nothing: ${c instanceof Error?c.message:String(c)}`),l}},r=(s,o)=>`onceworlds.data.game.${s}('${String(o).slice(0,40)}')`;return{async get(s){if(typeof s!="string"||!xe.test(s))return e(`${r("get",s)}: '${String(s).slice(0,40)}' isn't a game data key (1-32 letters, digits, _ . or -).`),null;try{return Fn(await(await n()).read(s))}catch(o){return e(`${r("get",s)} read nothing: ${o instanceof Error?o.message:String(o)}`),null}},add:(s,o)=>t({key:s,op:"add",n:Number(o)},r("add",s),i=>i.type==="counter"?i.value:null,null),push:(s,o)=>t({key:s,op:"push",item:o},r("push",s),i=>i.type==="list",!1),best:(s,o)=>t({key:s,op:"best",n:Number(o)},r("best",s),i=>i.type==="record"?{value:i.value,by:i.by,at:i.at,record:i.record}:null,null),claim:(s,o)=>t({key:s,op:"claim",field:String(o)},r("claim",s),i=>i.type==="map"&&i.ok,!1),release:(s,o)=>t({key:s,op:"release",field:String(o)},r("release",s),i=>i.type==="map"&&i.ok,!1),set:(s,o)=>t({key:s,op:"set",value:o},r("set",s),i=>i.type==="value",!1)}}function Et(n,e){let t=S.gameDataNumberMax,r=o=>{switch(o.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}}},s=o=>{try{let i=e.get(`onceworlds:game:${o}`);return i?JSON.parse(i):null}catch{return null}};return{async read(o){let i=s(o);if(!i)throw new Error(`nothing is stored under '${o}' on this page yet (on its own, game data lives in this browser).`);return i},async op(o){let i=await n(),l=s(o.key),c=r(o);if(l&&l.type!==c.type)throw new Error(`'${o.key}' holds a ${l.type} on this page: it was first used that way.`);let d=Ze(c,l,JSON.parse(JSON.stringify(o??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:${o.key}`,JSON.stringify(d.next)),d.result}}}function Pt(n){return{messagesPerSecond:n.messagesPerSecond*.85,messageBurst:n.messagesPerSecond*2*.85,bytesPerSecond:n.bytesPerSecond*.85,byteBurst:n.bytesPerSecond*4*.85}}var Kn=60,Vn=100,Wn=5e3,ce=class{constructor(e={}){p(this,"queue",[]);p(this,"rates",Pt({messagesPerSecond:S.messagesPerSecond,bytesPerSecond:S.roomBytesPerSecond}));p(this,"messages",this.rates.messageBurst);p(this,"bytes",this.rates.byteBurst);p(this,"budget",{messagesPerSecond:S.messagesPerSecond,bytesPerSecond:S.roomBytesPerSecond});p(this,"refilledAt");p(this,"timer",null);p(this,"warnedAt",-1/0);p(this,"dropped",0);p(this,"now");p(this,"setTimer");p(this,"clearTimer");p(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=Pt(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 s=this.queue.length-1;s>=0;s--){let o=this.queue[s];if(o.kind!=="state")break;if(o.key===e)return o.size=t,o.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(Kn,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],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(c){console.error("[onceworlds] a message could not be sent",c)}}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,s=Math.max(0,t-this.bytes)/this.rates.bytesPerSecond,o=Math.min(250,Math.max(8,Math.ceil(Math.max(r,s)*1e3)));this.timer=this.setTimer(()=>{this.timer=null,this.drain(!1)},o)}squeeze(){let e=new Set;for(let s=this.queue.length-1;s>=0;s--){let o=this.queue[s];o.kind==="state"&&(e.has(o.key)?this.queue.splice(s,1):e.add(o.key))}let t=this.queue.filter(s=>s.kind==="event").length,r=this.waitingLimit(Vn,20);for(let s=0;t>r&&s<this.queue.length;)this.queue[s].kind==="event"?(this.queue.splice(s,1),t--,this.dropped++):s++;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<Wn||(this.warnedAt=t,this.warn(e))}};function q(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 Ce=Math.PI*2;function Le(n,e,t,r={},s=""){if(typeof n=="number"&&typeof e=="number"){if(r.angles?.includes(s)){let o=((e-n)%Ce+Ce+Math.PI)%Ce-Math.PI;return n+o*t}return n+(e-n)*t}if(Array.isArray(n)&&Array.isArray(e)&&n.length===e.length)return e.map((o,i)=>Le(n[i],o,t,r,s));if(n&&e&&typeof n=="object"&&typeof e=="object"&&!Array.isArray(n)&&!Array.isArray(e)){let o={};for(let i of Object.keys(e))o[i]=i in n?Le(n[i],e[i],t,r,i):e[i];return o}return t<.5?n:e}function Jn(n,e,t){if(t===void 0||!n||!e||typeof n!="object"||typeof e!="object")return!1;for(let[r,s]of Object.entries(e)){let o=n[r];if(typeof s=="number"&&typeof o=="number"&&Math.abs(s-o)>t)return!0}return!1}function At(n,e,t={}){if(n.length===0)return;let r=n[0],s=n[n.length-1];if(e<=r.at)return r.d;if(e>=s.at)return s.d;let o=n.length-2;for(;o>0&&n[o].at>e;)o--;let i=n[o],l=n[o+1];return Jn(i.d,l.d,t.snap)?l.d:Le(i.d,l.d,(e-i.at)/Math.max(1,l.at-i.at),t)}var $t=8,Ct=2e3;var Yn=3e3,Qn=15e3,Zn=5e3;function Lt(n){let e={};for(let t of Object.keys(n))J(t)&&(e[t]=n[t]);return e}var I=()=>48,Z=class{constructor(e,t,r=Date.now,s=[]){p(this,"id");p(this,"kind");p(this,"invite");p(this,"teams");p(this,"open");p(this,"ranked");p(this,"kept");p(this,"me");p(this,"owner");p(this,"players",new Map);p(this,"state",{});p(this,"host");p(this,"closed",!1);p(this,"connected",!0);p(this,"match");p(this,"listeners",new Map);p(this,"transport");p(this,"outbox",new ce);p(this,"samples",new Map);p(this,"presenceTimer",null);p(this,"pendingPresence",null);p(this,"writes",0);p(this,"written",new Map);p(this,"confirmed",{});p(this,"shares",{messagesPerSecond:S.messagesPerSecond,presenceHz:S.presenceHz,bytesPerSecond:S.roomBytesPerSecond});p(this,"clock");p(this,"schema");p(this,"frozenSettings",null);p(this,"secrets",new Map);p(this,"offlineReady");p(this,"complained",new Map);p(this,"acks",new Map);this.transport=t,this.clock=r,this.schema=s,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??Qe(e.room),this.owner=e.owner??null,this.host=e.host;for(let o of e.players)this.players.set(o.id,{...o}),o.presence!==null&&o.presence!==void 0&&this.samples.set(o.id,[{at:e.now??this.clock(),d:o.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=Lt(e.state);for(let[o,i]of Object.entries(e.private??{}))this.secrets.set(o,{...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(o=>o.id===e);if(!r||!r.options.some(o=>o.value===t)||this.chosenSettings()[e]===t)return;let s=this.state[Y];this.setState(Y,{...s!==null&&typeof s=="object"?s:{},[e]:t}),this.clearReady(),this.emit("settings",this.settings)}chosenSettings(){let e=this.state[Y];return Object.fromEntries(this.schema.map(t=>[t.id,et(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(()=>q(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(()=>q(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:At(r,this.clock()-(t.delay??100),t)}keep(e,t,r){let s=this.samples.get(e)??[],o=s.length;for(;o>0&&s[o-1].at>t;)o--;for(s.splice(o,0,{at:t,d:r});s.length>$t||s.length>2&&s[0].at<t-Ct;)s.shift();this.samples.set(e,s)}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(I,()=>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(I,()=>this.transport.start(r))}endMatch(){this.reachable("endMatch")&&this.outbox.urgent(I,()=>this.transport.end())}pauseMatch(e=!0){this.reachable("pauseMatch")&&this.outbox.urgent(I,()=>this.transport.pause(e))}admit(e){let t=(Array.isArray(e)?e:[e]).map(String);t.length&&this.reachable("admit")&&this.outbox.urgent(I,()=>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(!J(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 s=this.clock(),o=`${e}:${t}`;if(s-(this.complained.get(o)??-1/0)<Zn)return;this.complained.set(o,s);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(I,()=>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(I,()=>this.transport.unready())}}send(e,t={}){this.closed||this.outbox.event(()=>q(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(q(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(J(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,()=>q(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(s=>{let o={w:r,done:l=>{clearTimeout(i),s(l)}},i=setTimeout(()=>this.settleAcks(e,l=>l===o,!1),Qn);this.acks.set(e,[...this.acks.get(e)??[],o])}):Promise.resolve(!1)}_resetData(){return this.closed||!this.connected||!this.transport.dataReset?!1:(this.outbox.urgent(I,()=>this.transport.dataReset()),!0)}settleAcks(e,t,r){let s=this.acks.get(e);if(!s)return;let o=s.filter(i=>!t(i));o.length>0?this.acks.set(e,o):this.acks.delete(e);for(let i of s)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(I,()=>this.transport.team(e,t))}setOpen(e){this.closed||this.outbox.urgent(I,()=>this.transport.open(e))}reportResult(e){this.closed||this.outbox.urgent(()=>q(e),()=>this.transport.result(e))}kick(e){this.closed||this.outbox.urgent(I,()=>this.transport.kick(String(e)))}voteKick(e){this.closed||this.outbox.urgent(I,()=>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,s=>s.w<=e.w,!0),J(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===Y&&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(q(e)),this.presenceTimer=setTimeout(()=>this.flushPresence(),1e3/this.shares.presenceHz)}applyBudget(e){if(!e)return;let t=(r,s)=>typeof r=="number"&&Number.isFinite(r)&&r>0&&r<=s;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 s={...this.secrets.get(e)??{}};r===null?delete s[t]:s[t]=r,Object.keys(s).length>0?this.secrets.set(e,s):this.secrets.delete(e)}applySecrets(e){let t=[];for(let[r,s]of Object.entries(e))for(let[o,i]of Object.entries(s))JSON.stringify(this.secrets.get(r)?.[o]??null)!==JSON.stringify(i)&&t.push([r,o,i]);for(let[r,s]of this.secrets)for(let o of Object.keys(s))o in(e[r]??{})||t.push([r,o,null]);this.secrets=new Map(Object.entries(e).map(([r,s])=>[r,{...s}]));for(let[r,s,o]of t)this.emit("private",s,o,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=Lt(e.state),this.applyBudget(e.budget);let s=new Set;for(let i of e.players){if(s.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 c={...i};this.players.set(i.id,c),this.emit("join",c)}}for(let[i,l]of this.players)s.has(i)||l===this.me||(this.players.delete(i),this.emit("leave",l));let o=new Set([...Object.keys(this.state),...Object.keys(e.state)]);for(let i of o){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(s){console.error(`[onceworlds] error in room "${e}" listener`,s)}}};function _t(n){let e=null,t=s=>n()._receive({t:"match",match:s}),r=()=>{let o=n().match;if(o.phase!=="starting")return;let{startsAt:i,...l}=o;t({...l,phase:"playing",startedAt:Date.now(),pausedMs:0})};return{send(){},presence(){},state(){},team(){},open(){},result(){},kick(){},voteKick(){},ready(){},unready(){},transfer(){},start(s){let o=n();if(o.match.phase!=="lobby")return;let i=Math.min(S.matchCountdownMaxMs,Math.max(0,s.countdown??S.matchCountdownMs));t({phase:"starting",n:o.match.n+1,min:o.match.min,id:`solo${o.match.n+1}`,seed:Math.floor(Math.random()*2**32),participants:[o.me.id],startsAt:Date.now()+i}),i===0?r():e=setTimeout(r,i)},end(){let s=n();e&&clearTimeout(e),e=null,s.match.phase!=="lobby"&&t({phase:"lobby",n:s.match.n,min:s.match.min})},pause(s){let o=n().match;if(o.phase!=="playing")return;let i=Date.now();if(s&&!o.paused)t({...o,paused:{since:i,reason:"host"}});else if(!s&&o.paused){let{paused:l,...c}=o;t({...c,pausedMs:(o.pausedMs??0)+Math.max(0,i-l.since)})}},admit(){},private(){},leave(){e&&clearTimeout(e),e=null}}}var Dt=["pointerdown","pointermove","keydown","wheel","touchstart","touchmove","devicemotion","visibilitychange"],Xn=5e3;function Ot(n,e=S.idleAfterMs){let t=Date.now(),r=!1,s=()=>{t=Date.now(),r&&(r=!1,n(!1))},o=()=>{try{for(let l of navigator.getGamepads?.()??[])if(l&&(l.buttons.some(c=>c.pressed)||l.axes.some(c=>Math.abs(c)>.25)))return!0}catch{}return!1};for(let l of Dt)window.addEventListener(l,s,{capture:!0,passive:!0});let i=setInterval(()=>{if(o())return s();!r&&Date.now()-t>e&&(r=!0,n(!0))},Xn);return{get idle(){return r},stop(){clearInterval(i);for(let l of Dt)window.removeEventListener(l,s,{capture:!0})}}}var Tt=["pointerdown","keydown","touchstart","gamepadconnected"];function It(n,e){let t=r=>{if(!(!r.isTrusted||!n())){for(let s of Tt)window.removeEventListener(s,t,{capture:!0});e()}};for(let r of Tt)window.addEventListener(r,t,{capture:!0,passive:!0})}var Nt=["low","medium","high"],er={low:.6,medium:.8,high:1},tr=24,nr=18.5,rr=26,_e=6e3,Bt=2e4,or=5*6e4,De=class{constructor(e=2){p(this,"level",2);p(this,"slow",0);p(this,"smoothSince",0);p(this,"holdUntil",0);p(this,"probeAfter",Bt);p(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<_e+Bt/2&&(this.probeAfter=Math.min(or,this.probeAfter*2)),this.level--,this.slow=0,this.holdUntil=e+_e)):t<=nr&&r<=rr?(this.slow=0,this.smoothSince||(this.smoothSince=e),this.level<Nt.length-1&&e>=this.holdUntil&&e-this.smoothSince>=this.probeAfter&&(this.level++,this.steppedUpAt=e,this.smoothSince=0,this.holdUntil=e+_e)):(this.slow=0,this.smoothSince=0),this.level}};function Gt(n){let e="auto",t=typeof matchMedia=="function"&&matchMedia("(prefers-reduced-motion: reduce)").matches,r=!1,s=new De(sr()?1:2),o=new Set,i=!1,l=!1,c=0,d=[],m=0,h=0,f=M=>{if(i){if(c&&!document.hidden){let P=M-c;P<250&&d.push(P)}if(c=document.hidden?0:M,m||(m=M),M-m>=1e3){if(d.length>=10){let P=[...d].sort((j,A)=>j-A),L=d.reduce((j,A)=>j+A,0)/d.length,U=P[Math.min(P.length-1,Math.floor(P.length*.95))],N=E();e==="auto"&&s.window(M,L,U),r&&M-h>=500&&(h=M,n.stats({fps:Math.round(1e3/L),frameMs:Math.round(L*10)/10,worstMs:Math.round(P[P.length-1]*10)/10})),E()!==N&&_()}d=[],m=M}w()}},w=()=>{l||!i||(l=!0,requestAnimationFrame(M=>{l=!1,f(M)}))},y=()=>{i||typeof requestAnimationFrame!="function"||(i=!0,c=0,m=0,w())},k=()=>{!r&&e!=="auto"&&i&&(i=!1)},E=()=>e==="auto"?Nt[s.level]:e,_=()=>{for(let M of o)try{M(T)}catch(P){console.error('[onceworlds] error in settings "change" listener',P)}},T={get choice(){return e},get quality(){return e==="auto"&&y(),E()},get scale(){return er[T.quality]},get reducedMotion(){return t},pixelRatio(M=2){let P=typeof devicePixelRatio=="number"&&devicePixelRatio>0?devicePixelRatio:1;return Math.max(.5,Math.min(P,M)*T.scale)},on(M,P){return M!=="change"?()=>{}:(o.add(P),e==="auto"&&y(),()=>o.delete(P))}};return{settings:T,apply(M){let P=`${E()}|${t}`;e=M.quality,t=M.reducedMotion,r=M.showStats,r||e==="auto"&&o.size>0?y():k(),`${E()}|${t}`!==P&&_()}}}function sr(){return typeof matchMedia=="function"&&matchMedia("(pointer: coarse)").matches}var X={maxSide:1280,quality:.85,maxBytes:15e5,answerMs:2500,waitMs:3e3,perSecond:3};var ir=4,ar=250,lr=1e3;function cr(){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 ur(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(X.maxSide,Math.max(64,Math.round(e.maxSide))):X.maxSide,r=typeof e.quality=="number"&&Number.isFinite(e.quality)?Math.min(.95,Math.max(.5,e.quality)):X.quality;return{id:e.id,maxSide:t,quality:r}}function dr(n,e,t){let r=Math.min(1,t/Math.max(n,e,1)),s=o=>Math.max(1,Math.min(t,Math.round(o*r)));return{width:s(n),height:s(e)}}function mr(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 pr=/^(?: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&&!pr.test(r))return r}}catch{}return"#000"}function Oe(n,e,t,r,s){try{let o=r.document.createElement("canvas");o.width=e.width,o.height=e.height;let i=o.getContext("2d");if(!i)return{miss:"unsupported"};if(i.drawImage(n,0,0,e.width,e.height),mr(i.getImageData(0,0,e.width,e.height).data))return{miss:"blank"};i.globalCompositeOperation="destination-over",i.fillStyle=s(),i.fillRect(0,0,e.width,e.height);for(let l of[t.quality,.6]){let c=o.toDataURL("image/jpeg",l);if(!c.startsWith("data:image/jpeg;base64,"))return{miss:"unsupported"};if((c.length-23)*.75<=X.maxBytes)return{image:c}}return{miss:"failed"}}catch(o){return{miss:o?.name==="SecurityError"?"tainted":"failed"}}}function jt(n,e){let t=!1,r=()=>{t||(t=!0,e())};n.requestAnimationFrame(r),n.setTimeout(r,ar)}function gr(n,e,t){return new Promise(r=>{let s,o;try{if(typeof n.captureStream!="function")return r(null);s=n.captureStream(),o=e.document.createElement("video"),o.muted=!0,o.playsInline=!0,o.srcObject=s}catch{return r(null)}let i=!1,l=m=>{if(!i){i=!0,e.clearTimeout(c);try{o.srcObject=null;for(let h of s.getTracks())h.stop()}catch{}r(m)}},c=e.setTimeout(()=>l(null),lr),d=()=>{!i&&o.videoWidth>0&&o.videoHeight>0&&l(t(o))};try{o.addEventListener("loadeddata",d),o.addEventListener("playing",d),o.play()?.catch(()=>{})}catch{l(null)}})}function Ht(n,e=cr()){let t=!1,r=o=>{try{n(o)}catch{}};function s(o){let i=o.id;if(!e)return r({id:i,t:"none",reason:"unsupported"});if(t)return r({id:i,t:"none",reason:"busy"});let l=e,c=ie(l.document.querySelectorAll("canvas"));if(!c)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})},m=dr(c.width,c.height,o.maxSide),h=null,f=()=>h??(h=fr(c,l));if(l.hidden?.()){let k=Oe(c,m,o,l,f);return d("miss"in k&&k.miss==="blank"?{miss:"hidden"}:k)}let w=0,y=()=>{try{let k=Oe(c,m,o,l,f);if(!("miss"in k)||k.miss!=="blank")return d(k);if(++w<ir)return jt(l,y);gr(c,l,E=>Oe(E,m,o,l,f)).then(E=>d(E??{miss:"blank"}),()=>d({miss:"blank"}))}catch{d({miss:"failed"})}};jt(l,y)}return{receive(o){let i=null;try{i=ur(o),i&&s(i)}catch{t=!1,i&&r({id:i.id,t:"none",reason:"failed"})}}}}var qt=(n,e)=>Object.prototype.hasOwnProperty.call(n,e);function Te(n){try{return n(),!0}catch{return!1}}function hr(){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 qt(e,r)?t[r]:n.get(r)},set(t,r,s){return typeof r=="string"&&n.set(r,String(s)),!0},has:(t,r)=>typeof r=="string"&&(qt(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 yr(n=Date.now){let e=new Map;return{read:()=>[...e].map(([t,r])=>`${t}=${r}`).join("; "),write(t){let[r,...s]=String(t).split(";"),o=r.indexOf("="),i=(o<0?"":r.slice(0,o)).trim(),l=(o<0?r:r.slice(o+1)).trim();if(!i&&!l)return;let c=!1;for(let d of s){let[m,...h]=d.split("="),f=h.join("=").trim();m.trim().toLowerCase()==="max-age"&&Number(f)<=0&&(c=!0),m.trim().toLowerCase()==="expires"&&Date.parse(f)<=n()&&(c=!0)}c?e.delete(i):e.set(i,l)}}}function ee(n,e,t){try{Object.defineProperty(n,e,{configurable:!0,...t})}catch{}}function br(){if(typeof HTMLImageElement!="function")return;let n=Object.getOwnPropertyDescriptor(HTMLImageElement.prototype,"src");if(!n?.get||!n.set)return;let{get:e,set:t}=n;ee(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 wr(){let n=window.Worker;if(typeof n!="function")return;let e=function(t,r){try{return new n(t,r)}catch(s){if(!(s instanceof DOMException&&s.name==="SecurityError")||r?.type==="module")throw s;let o;try{o=new URL(String(t),document.baseURI)}catch{throw s}if(o.origin!==location.origin)throw s;let l=`const base = ${JSON.stringify(o.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,ee(window,"Worker",{value:e,writable:!0})}function zt(){try{for(let n of["localStorage","sessionStorage"])Te(()=>window[n].length)||ee(window,n,{value:hr()});if(!Te(()=>document.cookie)){let n=yr();ee(document,"cookie",{get:()=>n.read(),set:e=>n.write(e)})}if(window.origin==="null"&&(wr(),br()),window.origin==="null"||!Te(()=>history.replaceState(history.state,"",location.href)))for(let n of["pushState","replaceState"]){let e=history[n];ee(history,n,{value:function(...t){try{return e.apply(this,t)}catch(r){if(!(r instanceof DOMException&&r.name==="SecurityError"))throw r}}})}}catch{}}var kr=["menu","lobby","stick","buttons"];function Ft(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:s,y:o,w:i,h:l}=t;kr.includes(r)&&(!ue(s)||!ue(o)||!ue(i)||!ue(l)||i<0||l<0||e.push({kind:r,x:s,y:o,w:i,h:l}))}return e}var ue=n=>typeof n=="number"&&Number.isFinite(n),Ie={entries:10,entryMs:1e3,totalMs:2e3};function Kt(n){let e=typeof n=="number"?[n]:Array.isArray(n)?n.slice(0,Ie.entries):null;if(!e||!e.every(s=>typeof s=="number"&&Number.isFinite(s)&&s>=0))return null;let t=[],r=Ie.totalMs;for(let s of e){let o=Math.min(Math.round(s),Ie.entryMs,r);if(t.push(o),r-=o,r<=0)break}return t.some((s,o)=>o%2===0&&s>0)?t:[]}var vr=/^#(?:[0-9a-f]{3}){1,2}$/i,te={panel:"#111216",text:"#f7f7f8",accent:"#d33e00"},Ne=4.5,Be=3,de=["#4ade80","#15803d"];function Vt(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=m=>{let h=t[m];return h==null?null:typeof h=="string"&&vr.test(h)?Wt(h):(e.push(`${m} is not #rgb or #rrggbb`),null)},s=r("panel"),o=r("text"),i=r("accent");if(s||o){let m=z(o??te.text,s??te.panel);m<Ne&&(e.push(`text on panel is ${m.toFixed(1)}:1, under ${Ne}:1: the platform's are used`),s=o=null)}let l=s??te.panel,c=o??te.text;if(i){let m=z(i,l);m<Be&&(e.push(`accent on panel is ${m.toFixed(1)}:1, under ${Be}:1: the platform's is used`),i=null)}if(!i&&s&&z(te.accent,s)<Be&&(i=c),!s&&!o&&!i)return{look:null,notes:e};let d=i?Sr(i):null;return{look:{panel:s,text:o,muted:s||o?xr(c,l):null,accent:i,accentHover:i?Jt(i,d==="#ffffff"?"#000000":"#ffffff",.14):null,onAccent:d,ok:s?z(de[0],s)>=z(de[1],s)?de[0]:de[1]:null},notes:e}}function Wt(n){let e=n.slice(1).toLowerCase();return`#${e.length===3?[...e].map(t=>t+t).join(""):e}`}function Ge(n){let e=Wt(n);return[parseInt(e.slice(1,3),16),parseInt(e.slice(3,5),16),parseInt(e.slice(5,7),16)]}function Ut(n){let[e,t,r]=Ge(n).map(s=>{let o=s/255;return o<=.04045?o/12.92:((o+.055)/1.055)**2.4});return .2126*e+.7152*t+.0722*r}function z(n,e){let[t,r]=[Ut(n),Ut(e)].sort((s,o)=>o-s);return(t+.05)/(r+.05)}function Sr(n){return z(n,"#000000")>z(n,"#ffffff")?"#000000":"#ffffff"}function Jt(n,e,t){let[r,s]=[Ge(n),Ge(e)];return`#${r.map((o,i)=>Math.round(o+(s[i]-o)*t).toString(16).padStart(2,"0")).join("")}`}function xr(n,e){for(let t=.3;t>.001;t-=.05){let r=Jt(n,e,t);if(z(r,e)>=Ne)return r}return n}var me=class{constructor(){p(this,"areas",null);p(this,"key","")}receive(e){let t=Ft(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(s=>Object.freeze(s))),!0)}};function Yt(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 s=n[r];s!=null&&(t[r]=typeof s=="string"?s.slice(0,16):"")}}catch{return e}return{look:t,notes:Vt(t).notes}}function Qt(n,e,t){let r=typeof n.vibrate=="function"?n.vibrate.bind(n):null,s=o=>{try{if(!e())return r?r(o):!1;if(!r)return!1;let i=Kt(Array.isArray(o)?Array.from(o):o);return i?(t(i),!0):!1}catch{return!1}};try{Object.defineProperty(n,"vibrate",{value:s,configurable:!0,writable:!0})}catch{}}var Mr=["RTCPeerConnection","webkitRTCPeerConnection","mozRTCPeerConnection"];function Zt(n){if(n)for(let e of Mr)try{Object.defineProperty(n,e,{value:void 0,writable:!1,enumerable:!1,configurable:!1})}catch{}}function Xt(n,e){if(Zt(n),!!e)for(let t of["contentWindow","contentDocument"])try{let r=Object.getOwnPropertyDescriptor(e.prototype,t),s=r?.get;if(!r||!s)continue;Object.defineProperty(e.prototype,t,{...r,get(){let o=s.call(this);return Zt(t==="contentWindow"?o:o?.defaultView),o}})}catch{}}var en="0.1.0";function on(){let n=globalThis;return n.onceworlds?.__onceworlds||(n.onceworlds=Rr()),n.onceworlds}function Rr(){let n=lt(document.currentScript);zt(),Xt(window,typeof HTMLIFrameElement>"u"?void 0:HTMLIFrameElement);let e=at(),t=Gt({stats:a=>x("stats",a)}),r=window.parent!==window,s=r&&gt(location.search)?wt(console,location.origin):null,o="connecting",i=!r&&bt(location.search),l=null,c=null,d=1,m=new Map,h=new Map,f=null,w=[],y,k=null,E=0,_=new Set,T=new me,M=new Set,P=new Set,L=r?mt(a=>x("clip",a),void 0,()=>f?{phase:f.match.phase,paused:!!f.match.paused,flow:ut(f.state)}:null):null,U=s?Ht(a=>x("snapshot",a)):null,N=new le(a=>{o!=="standalone"&&R("ui.controls",a).catch(()=>{})},a=>x("input",{touch:a})),j,A=new Promise(a=>j=a),je=xt(),He=Mt(()=>f,je),sn={read:a=>R("data.game.get",{key:a}),op:a=>R("data.game.op",a)},an=Et(()=>G().then(a=>a.player),B),ln=Rt(async()=>(await A,o==="platform"?sn:an),je),be=new Set,we=[],qe=a=>{let u=`${a.message}|${a.source}|${a.line}`;be.has(u)||be.size>=S.errorReportsPerPage||(be.add(u),o==="platform"?x("error",a):o==="connecting"&&we.push(a))};if(window.addEventListener("error",a=>{if(!(a instanceof ErrorEvent))return;let u=String(a.message||"Error");if(qe({message:u,source:tn(a.filename),line:a.lineno||0,column:a.colno||0,stack:a.error instanceof Error?String(a.error.stack??""):""}),s){let g=a.error instanceof Error?`Uncaught ${ae(a.error)}`:/^Uncaught\b/.test(u)?u:`Uncaught ${u}`;s.error(g,{source:tn(a.filename),line:a.lineno||0,column:a.colno||0})}}),window.addEventListener("unhandledrejection",a=>{let u=a.reason;s?.error(`Uncaught (in promise) ${u instanceof Error?ae(u):V(u)}`),qe({message:`Unhandled promise rejection: ${u instanceof Error?u.message:String(u)}`,source:"",line:0,column:0,stack:u instanceof Error?String(u.stack??""):""})}),r){window.addEventListener("message",u=>{if(!(u.source!==window.parent||u.data?.type!==nt||!u.ports[0])&&o!=="standalone"){if(c?.close(),c=u.ports[0],c.onmessage=g=>cn(g.data),o=ht(u.data),i=o==="platform"&&yt(u.data),j(),o==="platform")for(let g of we.splice(0))x("error",g);else we.length=0;s?.connect(g=>x("console",g)),y||(x("alive",{}),y=setInterval(()=>x("alive",{}),2e3)),o==="platform"&&G().then(g=>{e.apply(g.audio),g.settings&&t.apply(g.settings)}).catch(()=>{})}});let a={type:tt,version:en,...n?{build:n}:{}};window.parent.postMessage(a,"*"),setTimeout(()=>{o==="connecting"&&(o="standalone",j())},5e3)}else o="standalone",j();if(window.addEventListener("keydown",a=>{a.key!=="/"||o!=="platform"||!f||Ar(a.target)||(a.preventDefault(),a.stopImmediatePropagation(),x("hotkey",{key:"/"}))},!0),r){try{document.documentElement.style.touchAction="pan-x pan-y"}catch{}for(let a of["gesturestart","gesturechange","gestureend"])document.addEventListener(a,u=>u.preventDefault(),{passive:!1})}if(r){let a=u=>{u.pointerType==="mouse"||o!=="platform"||(window.removeEventListener("pointerup",a,!0),R("ui.tapped",void 0).catch(()=>{}))};window.addEventListener("pointerup",a,!0)}if(r&&It(()=>o==="platform",()=>x("input.first",{})),r&&Qt(navigator,()=>o==="platform",a=>x("vibrate",{pattern:a})),r){let a=Element.prototype.requestFullscreen;Element.prototype.requestFullscreen=function(u){return o!=="platform"?a.call(this,u):(R("ui.fullscreen",void 0).catch(()=>{}),Promise.resolve())}}function cn(a){if(a.kind==="res"){let g=m.get(a.id);if(!g)return;m.delete(a.id),a.ok?g.resolve(a.result):g.reject(new Error(a.error));return}if(a.kind!=="event")return;let u=a.name;if(u==="room")f?._receive(a.data);else if(u==="room.connection")a.data?.connected===!1&&f?._disconnected();else if(u==="room.closed"){let g=f;f=null,g?._closed(a.data.reason)}else if(u==="room.moved"){let g=f;f=ze(a.data),g?._closed("moved");for(let v of _)try{v(f)}catch(D){console.error('[onceworlds] error in rooms "moved" listener',D)}}else if(u==="audio")e.apply(a.data),re("audio",a.data);else if(u==="settings")t.apply(a.data);else if(u==="pause"||u==="resume")re(u);else if(u==="controls")N.receive(a.data);else if(u==="input")N.touch=a.data?.touch===!0;else if(u==="reserved")T.receive(a.data)&&re("reserved",T.areas);else if(u==="clip")L?.receive(a.data);else if(u==="snapshot")U?.receive(a.data);else if(u==="debug")for(let g of P)try{g(a.data)}catch(v){console.error("[onceworlds] error in the debugger link",v)}else if(u==="player"){let g=a.data;G().then(v=>{g?.id!==v.player.id||typeof g.name!="string"||(v.player.name=g.name,re("player",v.player))}).catch(()=>{})}}async function R(a,u){await A;let g=c;if(!g)throw new Error("Not connected to Onceworlds");return new Promise((v,D)=>{let b=d++;m.set(b,{resolve:v,reject:D}),g.postMessage({kind:"req",id:b,method:a,params:u})})}function x(a,u){c?.postMessage({kind:"event",name:a,data:u})}function re(a,...u){for(let g of h.get(a)??[])try{g(...u)}catch(v){console.error(`[onceworlds] error in "${a}" listener`,v)}}function ze(a,u=w){let g={send:(b,$)=>x("room.send",{d:b,to:$}),presence:b=>x("room.presence",{d:b}),state:(b,$,C)=>x("room.state",{k:b,v:$,w:C}),hideLobby:b=>x("room.hideLobby",{hidden:b}),team:(b,$)=>x("room.team",{id:b,team:$}),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:C}:{}}),dataReset:()=>x("room.datareset",{}),leave:()=>{f===v&&(f=null),R("room.leave",void 0).catch(()=>{})}};w=u;let v=new Z(a,g,()=>Date.now()+E,u);Ue(v);let D=Ot(b=>x("room.idle",{idle:b}));return v.on("reconnect",()=>D.idle&&x("room.idle",{idle:!0})),v.on("close",()=>D.stop()),v}function Ue(a){a.on("state",(u,g,v)=>{f===a&&ke(u)&&He._changed(u.slice(H.length),g,v)})}function un(a,u){let g={};for(let[C,W]of Object.entries(ge.all()))g[H+C]=W;let v={room:"solo",you:a.id,host:a.id,players:[{...a,presence:null,team:u.teams?1:0}],state:g,chat:[],teams:u.teams??0,open:!0,now:Date.now(),ranked:!1,kept:!0,owner:a.id},b={..._t(()=>$),state(C,W){ke(C)&&ge.set(C.slice(H.length),W)},dataReset(){for(let C of Object.keys(ge.all()))ge.set(C,null),$._receive({t:"state",k:H+C,v:null,from:""})}},$=new Z(v,b,()=>Date.now()+E,Re(u.settings));return Ue($),$}function G(){return k??(k=A.then(()=>o==="platform"?R("session.get",void 0):$r()).then(a=>(E=Number(a.timeOffset)||0,a))),k}G().catch(()=>{});let Fe={async get(a){return await A,o==="platform"?await R("save.get",{key:a}):pe.get(a)},async set(a,u){await A,o==="platform"?await R("save.set",{key:a,value:u}):pe.set(a,u)},async delete(a){await A,o==="platform"?await R("save.delete",{key:a}):pe.delete(a)},async list(){return await A,o==="platform"?R("save.list",void 0):pe.list()}},Ke={__onceworlds:!0,_debug:s?{send:a=>{c&&x("debug",a)},on:a=>(P.add(a),()=>P.delete(a))}:null,version:en,get mode(){return o},ready:()=>A,player:{get:()=>G().then(a=>a.player),async avatarUrl(a,u="full"){let g=await G().catch(()=>null);if(!g?.platformOrigin)return null;let v=typeof a=="string"&&a?a:g.player.id;return`${g.platformOrigin}/avatar/${encodeURIComponent(v)}${u==="head"?"/head":""}.svg`},async avatar(a){if(await A,o!=="platform")return null;let u=typeof a=="string"&&a?a:(await G()).player.id;return it.test(u)?We(await R("player.avatar",{id:u}).catch(()=>null)):null},async rename(){return await A,o!=="platform"?null:await R("player.rename",void 0).catch(()=>null)?(await G()).player:null}},game:{info:()=>G().then(a=>a.game)},save:Fe,data:{player:Fe,server:He,game:ln},rooms:{async join(a={}){await A;let u=a.party===!0&&f!==null&&o==="platform";if(u||(f?.leave(),f=null),o!=="platform"){let{player:D}=await G();return f=un(D,a),f}let g=await R("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}:{}}),v=f;return f=ze(g,Re(a.settings)),u&&v?._closed("moved"),f},get current(){return f},on(a,u){return a!=="moved"?()=>{}:(_.add(u),()=>_.delete(u))}},ratings:{async get(a){return await A,o==="platform"?R("ratings.get",{mode:String(a)}):null},async top(a,u={}){return await A,o==="platform"?R("ratings.top",{mode:String(a),limit:u.limit}):[]}},ui:{setMenuPosition(a){R("ui.menuPosition",{position:a}).catch(()=>{})},get reserved(){return T.areas},setLook(a){let{look:u,notes:g}=Yt(a);for(let v of g)M.has(v)||(M.add(v),console.warn(`[onceworlds] ui.setLook: ${v}`));o!=="standalone"&&R("ui.look",u).catch(()=>{})},requestFullscreen(){o==="platform"?R("ui.fullscreen",void 0).catch(()=>{}):document.documentElement.requestFullscreen?.().catch(()=>{})},showInvite(){o==="platform"&&R("ui.invite",void 0).catch(()=>{})},setOrientation(a){a!=="any"&&a!=="landscape"&&a!=="portrait"||o!=="standalone"&&R("ui.orientation",{orientation:a}).catch(()=>{})}},controls:{set(a){N.set(a)},get stick(){return N.stick},pressed(a){return N.pressed(String(a))},presses(a){return N.presses(String(a))},get touch(){return N.touch}},now:()=>Date.now()+E,leaderboards:{async submit(a,u,g={}){if(await A,o!=="platform")return he.submit(String(a),Number(u),g.lowerIsBetter===!0);try{return await R("leaderboards.submit",{board:String(a),score:Number(u),lowerIsBetter:g.lowerIsBetter===!0})}catch(v){return console.warn(`[onceworlds] score for "${a}" was not saved: ${v instanceof Error?v.message:v}`),null}},async top(a,u={}){return await A,o!=="platform"?he.top(String(a)):R("leaderboards.top",{board:String(a),limit:u.limit,lowerIsBetter:u.lowerIsBetter===!0})}},settings:t.settings,audio:{get volume(){return e.volume},get muted(){return e.muted}},badges:{async award(a){if(await A,o!=="platform")return ye.add(String(a));try{return(await R("badges.award",{key:String(a)})).awarded}catch(u){return console.warn(`[onceworlds] badge "${a}" was not awarded: ${u instanceof Error?u.message:u}`),!1}},async list(){return await A,o==="platform"?R("badges.list",void 0):ye.list()},async has(a){return(await Ke.badges.list()).some(u=>u.key===a&&u.earned)}},demo:{get active(){return i},end(){return l??(l=(async()=>(await A,i?o!=="platform"?(console.info("[onceworlds] demo.end(): the end of the demo. On Onceworlds the platform shows its end-of-demo card here."),!0):R("demo.end",void 0).then(a=>a!==!1,()=>!0):!1))().finally(()=>l=null)),l}},env:Er(),async fetch(a,u={}){if(await A,o!=="platform")throw new Error("onceworlds.fetch only works on Onceworlds, where your secrets are stored. Run the game with `onceworlds dev`.");let g=a instanceof Request?a:null,v=new URL(g?g.url:String(a),location.href).href,D=(u.method??g?.method??"GET").toUpperCase(),b={};new Headers(u.headers??g?.headers).forEach((dn,mn)=>{b[mn]=dn});let $=u.body??null;$===null&&g&&D!=="GET"&&D!=="HEAD"&&($=await g.arrayBuffer()),$ instanceof URLSearchParams&&(b["content-type"]??(b["content-type"]="application/x-www-form-urlencoded;charset=UTF-8"),$=$.toString());let C=await R("net.fetch",{url:v,method:D,headers:b,body:await Pr($)}),W=[101,204,205,304].includes(C.status);return new Response(W?null:C.body,{status:C.status,statusText:C.statusText,headers:C.headers})},on(a,u){let g=h.get(a);return g||h.set(a,g=new Set),g.add(u),()=>g.delete(u)}};return Ke}function Er(){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 Pr(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 tn(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 Ar(n){return n instanceof HTMLElement?n.isContentEditable||["INPUT","TEXTAREA","SELECT"].includes(n.tagName):!1}function $r(){let n=B.get("onceworlds:player-id");return n||(n=`local-${Math.random().toString(36).slice(2,10)}`,B.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 nn="onceworlds:scores",he={all(){try{let n=JSON.parse(B.get(nn)??"{}");return n&&typeof n=="object"?n:{}}catch{return{}}},submit(n,e,t){let r=he.all(),s=r[n],o=s===void 0?e:t?Math.min(s,e):Math.max(s,e);return r[n]=o,B.set(nn,JSON.stringify(r)),{best:o,rank:1}},top(n){let e=he.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}}},ne="onceworlds:save:",rn="onceworlds:badges",ye={earned(){try{let n=JSON.parse(B.get(rn)??"{}");return n&&typeof n=="object"?n:{}}catch{return{}}},add(n){let e=ye.earned();return e[n]?!1:(e[n]=Date.now(),B.set(rn,JSON.stringify(e)),!0)},list(){return Object.entries(ye.earned()).map(([n,e])=>({key:n,name:n,description:"",icon:null,earned:!0,earnedAt:e}))}},pe={get(n){let e=B.get(ne+n);if(e===null)return null;try{return JSON.parse(e)}catch{return null}},set(n,e){B.set(ne+n,JSON.stringify(e??null))},delete(n){B.remove(ne+n)},list(){let n=[];try{for(let e=0;e<localStorage.length;e++){let t=localStorage.key(e);t?.startsWith(ne)&&n.push(t.slice(ne.length))}}catch{}return n.sort()}},fe="onceworlds:server:",ge={all(){let n={};try{for(let e=0;e<localStorage.length;e++){let t=localStorage.key(e);if(t?.startsWith(fe))try{n[t.slice(fe.length)]=JSON.parse(localStorage.getItem(t)??"null")}catch{}}}catch{}return n},set(n,e){e==null?B.remove(fe+n):B.set(fe+n,JSON.stringify(e))}},B={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{}}};on();})();
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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@onceworlds/cli",
3
- "version": "0.11.0",
3
+ "version": "0.12.0",
4
4
  "description": "Deploy games to Onceworlds.",
5
5
  "homepage": "https://onceworlds.com",
6
6
  "type": "module",