@phantomclient/plugin 0.1.1 → 0.1.3
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/lib/chunks/{api-Cu4nKe7h.js → api-DhaU9Jsd.js} +327 -307
- package/dist/lib/chunks/api-q8Jk0T10.js +1729 -0
- package/dist/lib/chunks/sdk-permissions-CyDMa4we.js +429 -0
- package/dist/lib/chunks/sdk-permissions-DQOAag0j.js +429 -0
- package/dist/lib/chunks/{state-kAlKf5xt.js → state-BGYMFLti.js} +9 -8
- package/dist/lib/chunks/state-CAfC_MRc.js +34 -0
- package/dist/lib/guest.js +1126 -851
- package/dist/lib/index.js +33 -27
- package/dist/lib/styles.css +1 -1
- package/dist/lib/vue.js +3 -3
- package/dist/runtime/chunks/api-0JFqyaCU.js +1 -0
- package/dist/runtime/chunks/sdk-permissions-CDp6went.js +1 -0
- package/dist/runtime/chunks/state-C-LOzJQV.js +1 -0
- package/dist/runtime/frame.html +3 -3
- package/dist/runtime/runtime.css +1 -1
- package/dist/runtime/runtime.js +4 -1
- package/dist/runtime/sdk-vue.js +1 -1
- package/dist/runtime/sdk.js +1 -1
- package/dist/types/index.d.ts +10023 -1393
- package/dist/types/vue.d.ts +11505 -2235
- package/package.json +1 -1
- package/dist/lib/chunks/sdk-permissions-DPyveeLR.js +0 -250
- package/dist/runtime/chunks/api-ByZmAFMe.js +0 -1
- package/dist/runtime/chunks/sdk-permissions-BKJgZYgg.js +0 -1
- package/dist/runtime/chunks/state-BjAtxWlm.js +0 -1
package/dist/runtime/runtime.js
CHANGED
|
@@ -1 +1,4 @@
|
|
|
1
|
-
import{j as Rt,S as $t,i as Ct,P as I,a as Ft}from"./chunks/sdk-permissions-BKJgZYgg.js";import{M as bt,P as De,X as Lt,a as Nt,b as It,C as ye,c as S}from"./chunks/api-ByZmAFMe.js";import{i as jt,t as _t,d as zt,o as re,c as ae,a as K,b as be,e as qe,f as Bt,g as We,h as Ue}from"./chunks/runtime-dom.esm-bundler-Dcouf4CU.js";import{f as k,b as Ht,r as Dt,s as Ve,P as qt}from"./chunks/state-BjAtxWlm.js";class C extends Error{constructor(e,t,r=null){super(Wt(t,r,e)),this.code=e,this.flash=r,this.name="BridgeError"}code;flash}function Wt(n,e,t){if(typeof n=="string"&&n.trim()!=="")return Vt(n,e);const r=Gt(n);if(r)return r;const a=typeof(e==null?void 0:e.name)=="string"?e.name.trim():"";return a||`The game answered with no reason (${t})`}const Ut={1006:"that member is not a method",1009:"something the call reached was null",1010:"that member is not there",1034:"a value was not of the type the member takes",1056:"that object has nowhere to put the value",1063:"the call was given the wrong number of arguments",1069:"the object has no member of that name",1502:"a script in the game ran for longer than the player allows",2007:"a value the call needs was null"};function Vt(n,e){const t=typeof(e==null?void 0:e.errorId)=="number"?e.errorId:0,r=Ut[t];return!r||!/^\s*Error #\d+\s*$/.test(n)?n:`${n.trim()}: ${r}`}function Gt(n){if(n==null)return"";if(typeof n=="string")return n.trim();if(typeof n!="object")return String(n);const e=n;if(typeof e.message=="string"&&e.message.trim()!=="")return e.message;try{const t=JSON.stringify(n);return t&&t!=="{}"?t:""}catch{return""}}const Ge=2;function X(n){return encodeURIComponent(JSON.stringify(n))}function vt(n){return JSON.parse(decodeURIComponent(n))}function Yt(n){return typeof n=="object"&&n!==null&&"$handle"in n}function Kt(n){switch(n.kind){case"result":return n.id;case"event":return n.listener;case"callback":return n.callback;case"hook":case"override":case"hook-dropped":case"hook-failed":return n.registration;case"watch":return n.watch;case"tick":return n.tick;case"overlay":return n.node;case"key":return n.key;case"drive-failed":return n.drive;case"track":return n.track;default:return null}}class fe{constructor(e,t=[]){this.className=e,this.args=t}className;args}class L{constructor(e,t,r){this.bridge=e,this.handle=t,this.className=r}bridge;handle;className;at(...e){return new V(this.bridge,{kind:"handle",handle:this.handle},e)}release(){return this.bridge.release([this])}}class V{constructor(e,t,r=[]){this.bridge=e,this.target=t,this.path=r}bridge;target;path;at(...e){return new V(this.bridge,this.target,[...this.path,...e])}get(){return this.bridge.request({op:"get",target:this.target,path:[...this.path]})}set(e){return this.bridge.request({op:"set",target:this.target,path:[...this.path],value:this.bridge.encode(e)}).then(()=>{})}call(...e){return this.bridge.request({op:"call",target:this.target,path:[...this.path],args:e.map(t=>this.bridge.encode(t))})}describe(){return this.bridge.request({op:"describe",target:this.target,path:[...this.path]})}listen(e,t){return this.bridge.listen(this,e,t)}get entry(){return{target:this.target,path:[...this.path]}}}const Xt=new Set(["drive-failed","track","hook","override","hook-dropped","hook-failed","watch","tick","overlay","key"]);class Jt{constructor(e,t={}){this.transport=e,this.timeoutMs=t.timeoutMs??5e3,this.firstId=t.firstId??1,this.nextId=this.firstId,this.batchOption=t.batch,this.stopReceiving=e.onMessage(r=>this.receive(r))}transport;stateValue="waiting";nextId;pending=new Map;listeners=new Map;callbacks=new Map;readyWaiters=[];clientListeners=new Set;uncaughtListeners=new Set;timeoutMs;stopReceiving;clientVersion=null;featureList=[];firstId;batchOption;queue=[];batches=new Map;subscriptions=new Map;ticks=new Map;get state(){return this.stateValue}get client(){return this.clientVersion}get features(){return this.featureList}allocate(){return this.nextId++}whenReady(){return this.stateValue==="ready"?Promise.resolve():this.stateValue==="closed"?Promise.reject(new C("CLOSED","The game is closed")):new Promise((e,t)=>this.readyWaiters.push({resolve:e,reject:t}))}definition(e){return new V(this,{kind:"definition",name:e})}gameClient(){return new V(this,{kind:"client"})}stage(){return new V(this,{kind:"stage"})}construct(e,...t){return this.request({op:"construct",className:e,args:t.map(r=>this.encode(r))})}onClient(e){return this.clientListeners.add(e),()=>this.clientListeners.delete(e)}onUncaught(e){return this.uncaughtListeners.add(e),()=>this.uncaughtListeners.delete(e)}async listen(e,t,r){const a=this.nextId++;this.listeners.set(a,r);try{await this.request({op:"listen",target:e.target,path:[...e.path],event:t,listener:a})}catch(i){throw this.listeners.delete(a),i}return async()=>{!this.listeners.delete(a)||this.stateValue==="closed"||await this.request({op:"unlisten",listener:a})}}async subscribe(e,t,r){const a=this.nextId++;this.subscriptions.set(a,r);try{await this.request(e(a))}catch(i){throw this.subscriptions.delete(a),i}return async()=>{!this.subscriptions.delete(a)||this.stateValue==="closed"||await this.request(t(a))}}onSubscription(e,t){return this.subscriptions.set(e,t),()=>{this.subscriptions.get(e)===t&&this.subscriptions.delete(e)}}async hookTable(e){return await this.request(e===void 0?{op:"hookTable"}:{op:"hookTable",url:e})}async hook(e,t,r){let a=0;const i=await this.subscribe(s=>(a=s,{op:"hook",registration:s,hook:e,rules:t}),s=>({op:"unhook",registration:s}),r);return{registration:a,stop:i}}watch(e,t,r){return this.subscribe(a=>({op:"watch",watch:a,entries:e.map(i=>({target:i.target,path:[...i.path]})),everyFrames:Math.max(1,Math.floor(t.everyFrames??1)),handles:t.handles??!1}),a=>({op:"unwatch",watch:a}),a=>{a.kind==="watch"&&r(a.values.map(i=>this.decode(i)),a.errors??null)})}async tick(e,t){const r=Math.max(1,Math.floor(e));let a=this.ticks.get(r);if(!a){const o=new Set,l=this.subscribe(c=>({op:"tick",tick:c,everyFrames:r}),c=>({op:"untick",tick:c}),c=>{if(c.kind==="tick")for(const h of[...o])h(c.frame,c.time)});a={listeners:o,started:l},this.ticks.set(r,a),l.catch(()=>{this.ticks.get(r)===a&&this.ticks.delete(r)})}const i=a;i.listeners.add(t);try{await i.started}catch(o){throw i.listeners.delete(t),o}let s=!1;return async()=>{s||(s=!0,i.listeners.delete(t),!(i.listeners.size>0||this.ticks.get(r)!==i)&&(this.ticks.delete(r),await(await i.started)()))}}highlight(e,t){return this.subscribe(r=>({op:"highlight",highlight:r,target:e.target,path:[...e.path],effect:t}),r=>({op:"unhighlight",highlight:r}),()=>{})}style(e,t){return this.subscribe(r=>({op:"style",style:r,target:e.target,path:[...e.path],format:t}),r=>({op:"unstyle",style:r}),()=>{})}invokeOriginal(e,t,r){return this.request({op:"invokeOriginal",registration:e,token:t,arguments:r===null?null:r.map(a=>this.encode(a))})}async overrideDone(e,t){this.stateValue!=="closed"&&await this.request({op:"overrideDone",registration:e,token:t})}onKey(e,t){return this.subscribe(r=>({op:"key",key:r,spec:e}),r=>({op:"unkey",key:r}),r=>{r.kind==="key"&&t(r)})}async draw(e,t){await this.request({op:"draw",node:e,spec:t})}async erase(e){if(!(e.length===0||this.stateValue==="closed")){for(const t of e)this.subscriptions.delete(t);await this.request({op:"erase",nodes:[...e]})}}drive(e,t){return this.subscribe(r=>({op:"drive",drive:r,spec:e}),r=>({op:"undrive",drive:r}),r=>{r.kind==="drive-failed"&&(t==null||t(r.error))})}async collect(e,t){const a=await this.request({op:"collect",target:e.target,path:[...e.path],spec:t});return{items:Array.isArray(a==null?void 0:a.items)?a.items:[],total:typeof(a==null?void 0:a.total)=="number"?a.total:0}}track(e,t,{mode:r="displayList",everyFrames:a=15}={},i){return this.subscribe(s=>({op:"track",track:s,target:e.target,path:[...e.path],className:t,mode:r,everyFrames:a}),s=>({op:"untrack",track:s}),s=>{s.kind==="track"&&i({added:s.added.map(o=>this.decode(o)),removed:s.removed.map(o=>this.decode(o))})})}async snapshot(e,{scale:t=1,background:r=null,maxSize:a=0}={}){const i=await this.request({op:"snapshot",target:e.target,path:[...e.path],scale:t,background:r,maxSize:a});if(typeof i!="string")throw new C("FLASH","The picture came back empty");return i}note(e,t,r,a){if(t==="keys"||t==="clear")return this.request({op:"note",table:e,verb:t});if(!r)throw new TypeError(`A note to ${t} is kept beside an object; name the place`);const i={target:r.target,path:[...r.path]};return t==="write"?this.request({op:"note",table:e,verb:t,...i,value:this.encode(a)}):this.request({op:"note",table:e,verb:t,...i})}async find(e,t){const r=await this.request({op:"find",target:e.target,path:[...e.path],spec:t});return(Array.isArray(r)?r:[]).filter(a=>a instanceof L)}async answer(e,t){this.stateValue!=="closed"&&await this.request({op:"answer",callback:e,...t===void 0?{}:{value:this.encode(t)}})}async release(e){e.length===0||this.stateValue==="closed"||await this.request({op:"release",handles:e.map(t=>t.handle)})}close(){if(this.stateValue==="closed")return;if(this.stateValue==="ready"&&this.featureList.includes("dispose")){const t=this.nextId++;try{this.transport.send(X({id:t,op:"dispose",from:this.firstId,to:this.nextId}))}catch{}}this.stateValue="closed",this.stopReceiving();const e=new C("CLOSED","The game was closed");for(const t of this.pending.values())clearTimeout(t.timer),t.reject(e);this.pending.clear();for(const t of this.batches.values())clearTimeout(t.timer);this.batches.clear(),this.queue=[],this.listeners.clear(),this.callbacks.clear(),this.subscriptions.clear(),this.ticks.clear(),this.readyWaiters.splice(0).forEach(t=>t.reject(e))}readyWithin(e){return new Promise((t,r)=>{const a=setTimeout(()=>r(new C("NOT_READY","The game has not started yet")),e);this.whenReady().then(()=>{clearTimeout(a),t()},i=>{clearTimeout(a),r(i)})})}encodeRequest(e){return X({...e,id:this.nextId++})}request(e){if(this.stateValue==="closed")return Promise.reject(new C("CLOSED","The game is closed"));if(this.stateValue!=="ready")return this.readyWithin(this.timeoutMs).then(()=>this.request(e));const t=this.nextId++;return new Promise((r,a)=>{const i=setTimeout(()=>{this.pending.delete(t),a(new C("TIMEOUT",`The game did not answer "${e.op}" in ${this.timeoutMs}ms`))},this.timeoutMs);this.pending.set(t,{resolve:r,reject:a,timer:i});const s={...e,id:t};if(!this.batching||s.op==="hookTable"||s.op==="batch"){this.transport.send(X(s));return}this.queue.push(s),this.queue.length===1&&queueMicrotask(()=>this.flush())})}get batching(){return this.batchOption??this.featureList.includes("batch")}flush(){const e=this.queue;if(this.queue=[],e.length===0||this.stateValue!=="ready")return;if(e.length===1){this.transport.send(X(e[0]));return}const t=this.nextId++,r=e.map(i=>i.id),a=setTimeout(()=>this.batches.delete(t),this.timeoutMs+1e3);this.batches.set(t,{ids:r,timer:a}),this.transport.send(X({id:t,op:"batch",requests:e}))}settle(e,t){const r=this.pending.get(e);r&&(this.pending.delete(e),clearTimeout(r.timer),t.ok?r.resolve(this.decode(t.value)):r.reject(new C("FLASH",t.error.message,t.error)))}encode(e){if(e===void 0)return{$undefined:!0};if(e===null||typeof e!="object"){if(typeof e=="function"){const t=this.nextId++;return this.callbacks.set(t,e),{$callback:t}}return e}return e instanceof L?{$handle:e.handle}:e instanceof fe?{$new:e.className,args:e.args.map(t=>this.encode(t))}:Array.isArray(e)?e.map(t=>this.encode(t)):Object.fromEntries(Object.entries(e).map(([t,r])=>[t,this.encode(r)]))}decode(e){if(e===null||typeof e!="object")return e;if(Array.isArray(e))return e.map(t=>this.decode(t));if(Yt(e))return new L(this,e.$handle,e.className);if(!("$undefined"in e))return Object.fromEntries(Object.entries(e).map(([t,r])=>[t,this.decode(r)]))}receive(e){var t,r,a;if(this.stateValue==="closed")return;let i;try{i=vt(e)}catch{return}switch(i.kind){case"ready":if(i.version!==Ge){const s=new C("VERSION",`The loader speaks bridge ${i.version}; this Phantom speaks ${Ge}`);this.readyWaiters.splice(0).forEach(o=>o.reject(s)),this.close();return}this.stateValue="ready",this.clientVersion=i.client,this.featureList=Array.isArray(i.features)?[...i.features]:[],this.readyWaiters.splice(0).forEach(s=>s.resolve());return;case"client-loaded":this.clientListeners.forEach(s=>s(!0,null));return;case"client-failed":this.clientListeners.forEach(s=>s(!1,i.message));return;case"result":{const s=this.batches.get(i.id);if(s){this.batches.delete(i.id),clearTimeout(s.timer);const o=i.ok&&Array.isArray(i.value)?i.value:null;s.ids.forEach((l,c)=>{i.ok?o&&c<o.length&&this.settle(l,o[c]):this.settle(l,i)});return}this.settle(i.id,i.ok?{ok:!0,value:i.value}:i);return}case"event":(t=this.listeners.get(i.listener))==null||t(this.decode(i.event));return;case"callback":(r=this.callbacks.get(i.callback))==null||r(...i.args.map(s=>this.decode(s)));return;case"uncaught":{const s=new C("FLASH",i.error.message,i.error);this.uncaughtListeners.forEach(o=>o(s));return}default:if(Xt.has(i.kind)){const s=Kt(i);s!==null&&((a=this.subscriptions.get(s))==null||a(i))}}}}const Zt=[1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0],kt={r:.3086,g:.6094,b:.082};function ie(n,e){const t=new Array(20).fill(0);for(let r=0;r<4;r++)for(let a=0;a<5;a++){let i=a===4?e[r*5+4]:0;for(let s=0;s<4;s++)i+=e[r*5+s]*n[s*5+a];t[r*5+a]=i}return t}function xt(n){const e=n,{r:t,g:r,b:a}=kt;return[t*(1-e)+e,r*(1-e),a*(1-e),0,0,t*(1-e),r*(1-e)+e,a*(1-e),0,0,t*(1-e),r*(1-e),a*(1-e)+e,0,0,0,0,0,1,0]}function Qt(n){const e=n*255;return[1,0,0,0,e,0,1,0,0,e,0,0,1,0,e,0,0,0,1,0]}function en(n){const e=n+1,t=128*(1-e);return[e,0,0,0,t,0,e,0,0,t,0,0,e,0,t,0,0,0,1,0]}function tn(n){const e=n*Math.PI/180,t=Math.cos(e),r=Math.sin(e),{r:a,g:i,b:s}=kt;return[a+t*(1-a)+r*-a,i+t*-i+r*-i,s+t*-s+r*(1-s),0,0,a+t*-a+r*.143,i+t*(1-i)+r*.14,s+t*-s+r*-.283,0,0,a+t*-a+r*-.6914,i+t*-i+r*i,s+t*(1-s)+r*s,0,0,0,0,0,1,0]}const nn={grayscale:xt(0),sepia:[.393,.769,.189,0,0,.349,.686,.168,0,0,.272,.534,.131,0,0,0,0,0,1,0],invert:[-1,0,0,0,255,0,-1,0,0,255,0,0,-1,0,255,0,0,0,1,0],night:[.45,0,0,0,0,0,.5,0,0,0,0,0,.8,0,20,0,0,0,1,0]};function Et(n){if(typeof n=="string"){const t=nn[n];if(!t)throw new TypeError(`Unknown colour look "${String(n)}"`);return{matrix:[...t],colorTransform:null}}if("matrix"in n){if(n.matrix.length!==20)throw new TypeError("A colour matrix has twenty numbers");return{matrix:[...n.matrix],colorTransform:null}}if("tint"in n){const t=Math.max(0,Math.min(1,n.amount??.5)),r=a=>(n.tint>>a&255)*t;return{matrix:null,colorTransform:Ye({redMultiplier:1-t,greenMultiplier:1-t,blueMultiplier:1-t,redOffset:r(16),greenOffset:r(8),blueOffset:r(0)})}}if("transform"in n)return{matrix:null,colorTransform:Ye(n.transform)};let e=[...Zt];return n.saturation!==void 0&&(e=ie(e,xt(n.saturation))),n.hue!==void 0&&(e=ie(e,tn(n.hue))),n.contrast!==void 0&&(e=ie(e,en(n.contrast))),n.brightness!==void 0&&(e=ie(e,Qt(n.brightness))),{matrix:e,colorTransform:null}}function Ye(n){return{redMultiplier:n.redMultiplier??1,greenMultiplier:n.greenMultiplier??1,blueMultiplier:n.blueMultiplier??1,alphaMultiplier:n.alphaMultiplier??1,redOffset:n.redOffset??0,greenOffset:n.greenOffset??0,blueOffset:n.blueOffset??0,alphaOffset:n.alphaOffset??0}}function ee(n={}){const e=n.recolor?Et(n.recolor):{matrix:null,colorTransform:null},r=n.glow??!(n.recolor||n.hide)?{color:n.color??9133302,alpha:n.alpha??1,blur:n.blur??8,strength:n.strength??2,inner:n.inner??!1,knockout:n.knockout??!1}:null;if(r&&e.matrix)throw new TypeError("A highlight is a glow or a colour matrix, not both: use two highlights");const a=n.pulse===void 0||n.pulse===!1?null:n.pulse===!0?{frames:60,from:.6,to:1}:{frames:n.pulse.frames??60,from:n.pulse.from??.6,to:n.pulse.to??1};return{glow:r,matrix:e.matrix,colorTransform:e.colorTransform,hide:n.hide??!1,pulse:a}}const pe=Symbol.for("phantom.typedFlash");function Tt(n){return typeof n=="function"&&n[pe]!==void 0}function R(n,e,t={}){const r={reference:e,handle:t.handle??null,className:t.className??null},a=o=>O(n,o),i={$get:()=>e.get().then(a),$set:async o=>e.set((await G(n,[o]))[0]),$listen:(o,l)=>e.listen(o,c=>l(a(c))),$describe:()=>e.describe(),$at:(...o)=>R(n,e.at(...o)),$as:()=>R(n,e,{...r.handle?{handle:r.handle}:{}}),$release:()=>r.handle?r.handle.release():Promise.resolve(),$reference:e,$new:async(...o)=>{if(!r.className)throw new TypeError("Only a class can make objects with $new");return a(await n.construct(r.className,...await G(n,o)))},toJSON:()=>`[Flash ${rn(r)}]`},s=(()=>{});return new Proxy(s,{get:(o,l)=>{if(l===pe)return r;if(typeof l!="symbol"&&l!=="then")return Object.prototype.hasOwnProperty.call(i,l)?i[l]:R(n,e.at(l))},apply:async(o,l,c)=>a(await e.call(...await G(n,c)))})}function te(n){return Tt(n)?n[pe].reference:n instanceof L?n.at():n&&typeof n=="object"&&"target"in n&&"path"in n&&typeof n.at=="function"?n:null}function O(n,e){if(e instanceof L)return R(n,e.at(),{handle:e});if(Array.isArray(e))return e.map(t=>O(n,t));if(e&&typeof e=="object"){const t={};for(const[r,a]of Object.entries(e))t[r]=O(n,a);return t}return e}async function G(n,e){return Promise.all(e.map(t=>Fe(n,t)))}async function Fe(n,e){if(Tt(e)){const t=e[pe];return t.handle&&t.reference.path.length===0?t.handle:t.reference.get()}if(typeof e=="function"){const t=e;return(...r)=>t(...r.map(a=>O(n,a)))}if(Array.isArray(e))return Promise.all(e.map(t=>Fe(n,t)));if(e&&typeof e=="object"&&Object.getPrototypeOf(e)===Object.prototype){const t={};for(const[r,a]of Object.entries(e))t[r]=await Fe(n,a);return t}return e}function rn({reference:n,className:e}){const t=n.target,r=t.kind==="definition"?t.name:t.kind==="handle"?`object ${t.handle}`:t.kind,a=n.path.join(".");return e??(a?`${r}.${a}`:r)}class an{constructor(e,t,r){this.bridge=e;const a=e.encode(t);this.callback=a.$callback,r!==void 0&&this.answers(r)}bridge;callback;stopped=!1;get argument(){return{$callback:this.callback}}async answers(e){if(this.stopped)return;await this.ready();const[t]=await G(this.bridge,[e]);await this.bridge.answer(this.callback,t)}async answersNothing(){this.stopped||(await this.ready(),await this.bridge.answer(this.callback))}async stop(){this.stopped||(this.stopped=!0,await this.bridge.answer(this.callback))}async ready(){if(await this.bridge.whenReady(),!this.bridge.features.includes("answer"))throw new Error("This game is running a loader from before answers; a function of yours gives the game nothing back")}}function T(n){const e=te(n);if(!e)throw new TypeError("Expected a place in Flash: a typed place, an object read from Flash, or a reference");return{target:e.target,path:[...e.path]}}async function sn(n,e,t,r){if(await n.whenReady(),!n.features.includes("collect"))throw new Error("This game is running a loader from before collects; read the items one by one");const a={fields:on(t)};r.skip!==void 0&&(a.skip=Math.max(0,Math.trunc(r.skip))),r.limit!==void 0&&(a.limit=Math.max(1,Math.trunc(r.limit))),r.handles!==void 0&&(a.handles=r.handles);const i=await n.collect(T(e),a);return{rows:i.items.map(s=>O(n,s)),total:i.total}}function on(n){const e=Array.isArray(n)?n.map(t=>[t,t]):Object.entries(n);if(e.length===0)throw new TypeError("A collect needs the members to read");return e.map(([t,r])=>({name:t,path:(Array.isArray(r)?r:String(r).split(".")).filter(a=>a.length>0)}))}function ne(n){const e=`${n.className}.${n.member}`;return n.kind==="getter"?`${e}@get`:n.kind==="setter"?`${e}@set`:e}const ge=Symbol.for("phantom.hookRead"),Y=Symbol.for("phantom.hookTest");class ln{constructor(e){this.table=e;for(const t of e.hooks){this.byId.set(t.id,t);const r=ne(t);this.byKey.has(r)||this.byKey.set(r,t)}}table;byKey=new Map;byId=new Map;get size(){return this.byId.size}names(){return[...this.byKey.keys()]}find(e){return e.startsWith("#")?this.byId.get(Number(e.slice(1)))??null:this.byKey.get(e)??this.byKey.get(`${e}@get`)??this.byKey.get(`${e}@set`)??null}}function W(n){return n.flatMap(e=>Array.isArray(e)?e:e.includes("::")?[e]:e.split(".").filter(Boolean))}function D(n){return Object.freeze({[ge]:n})}function N(n,e,t){return Object.freeze({[Y]:t===void 0&&n==="exists"?{test:n,left:e}:{test:n,left:e,right:t}})}const cn={self:(...n)=>D({from:"self",path:W(n)}),arg:(n,...e)=>D({from:"arg",arg:n,path:W(e)}),returned:(...n)=>D({from:"return",path:W(n)}),fromClass:(n,...e)=>D({from:"class",name:n,path:W(e)}),place:(n,...e)=>D({from:"place",place:n,path:W(e)}),calls:()=>D({from:"calls"}),constant:n=>D({from:"constant",value:n}),equals:(n,e)=>N("equals",n,e),notEquals:(n,e)=>N("notEquals",n,e),less:(n,e)=>N("less",n,e),lessOrEqual:(n,e)=>N("lessOrEqual",n,e),greater:(n,e)=>N("greater",n,e),greaterOrEqual:(n,e)=>N("greaterOrEqual",n,e),contains:(n,e)=>N("contains",n,e),startsWith:(n,e)=>N("startsWith",n,e),endsWith:(n,e)=>N("endsWith",n,e),oneOf:(n,e)=>N("in",n,e),exists:n=>N("exists",n),all:(...n)=>Object.freeze({[Y]:{all:n}}),any:(...n)=>Object.freeze({[Y]:{any:n}}),not:n=>Object.freeze({[Y]:{not:n}})};function Mt(n){return typeof n=="object"&&n!==null&&ge in n}function St(n){return typeof n=="object"&&n!==null&&Y in n}function Le(n,e,t,r){const a=u=>{if(typeof u=="number")return Ke(e,u);const d=e.parameters.findIndex(g=>g.name===u);if(d>=0)return d;if(/^\d+$/.test(u))return Ke(e,Number(u));const p=e.parameters.map(g=>g.name).join(", ")||"none";throw new TypeError(`${ne(e)} has no argument "${u}" (its arguments: ${p})`)},i=u=>{if(!Mt(u))return ue(u)??{from:"constant",value:J(n,u)};const d=u[ge];switch(d.from){case"constant":return{from:"constant",value:J(n,d.value)};case"arg":return{from:"arg",index:a(d.arg),path:d.path};case"self":return{from:"self",path:d.path};case"return":return{from:"return",path:d.path};case"class":return{from:"class",name:d.name,path:d.path};case"calls":return{from:"calls"};case"place":{const p=ue(d.place,d.path);if(!p)throw new TypeError("rules.place takes a place in the game");return p}}},s=u=>{if(!St(u)){const p=Object.entries(u).map(([g,f])=>({test:"equals",left:{from:"arg",index:a(g),path:[]},right:i(f)}));if(p.length===0)throw new TypeError("A hook condition names nothing to compare");return p.length===1?p[0]:{all:p}}const d=u[Y];return"all"in d?{all:d.all.map(s)}:"any"in d?{any:d.any.map(s)}:"not"in d?{not:s(d.not)}:d.test==="exists"?{test:d.test,left:i(d.left)}:{test:d.test,left:i(d.left),right:i(d.right)}},o=t.phase??(r?"enter":"none"),l=t.capture??{},c=e.parameters.map((u,d)=>d),h=l.args===!0||l.args===void 0&&r?c:(l.args??[]).map(a);return{observe:o==="both"?["enter","exit"]:o==="none"?[]:[o],capture:{args:h,self:Ne(l.self).map(([,u])=>u),value:l.value??!1,handles:l.handles??!1},when:t.when===void 0?null:s(t.when),first:t.first??null,every:t.every??null,skip:t.skip===void 0||t.skip===!1?null:t.skip===!0?{from:"constant",value:{$undefined:!0}}:i(t.skip.returns),replaceArgs:Object.entries(t.replaceArgs??{}).map(([u,d])=>({index:a(u),value:i(d)})),replaceReturn:"replaceReturn"in t?i(t.replaceReturn):null,perFrame:t.perFrame??20}}function Ke(n,e){if(!Number.isInteger(e)||e<0||n.parameters.length>0&&e>=n.parameters.length)throw new RangeError(`${ne(n)} has no argument ${e}`);return e}function Ne(n){return n?Array.isArray(n)?n.map(e=>[e,W([e])]):Object.entries(n).map(([e,t])=>[e,W([t])]):[]}function Ot(n,e){const t=r=>{if(!St(r))throw new TypeError("A condition between calls has no call to read: compare with rules.equals and its like");const a=r[Y];return"all"in a?{all:a.all.map(t)}:"any"in a?{any:a.any.map(t)}:"not"in a?{not:t(a.not)}:a.test==="exists"?{test:a.test,left:Q(n,a.left)}:{test:a.test,left:Q(n,a.left),right:Q(n,a.right)}};return t(e)}function ue(n,e=[]){const t=te(n);return t?{from:"place",target:t.target,path:[...t.path,...e]}:null}function Q(n,e){if(!Mt(e))return ue(e)??{from:"constant",value:J(n,e)};const t=e[ge];switch(t.from){case"constant":return{from:"constant",value:J(n,t.value)};case"class":return{from:"class",name:t.name,path:t.path};case"place":{const r=ue(t.place,t.path);if(!r)throw new TypeError("rules.place takes a place in the game");return r}default:throw new TypeError(`rules.${t.from} reads the call it is in; a value held between calls is a constant, rules.fromClass or a place`)}}function J(n,e){if(e===void 0)return{$undefined:!0};if(e instanceof L||e instanceof fe)return n.encode(e);const t=te(e);if(t){if(t.target.kind==="handle"&&t.path.length===0)return{$handle:t.target.handle};throw new TypeError("A place inside a list or object in a rule cannot be read there: pass the place on its own, or read it first")}if(typeof e=="function")throw new TypeError("A hook rule cannot call a function");return Array.isArray(e)?e.map(r=>J(n,r)):e!==null&&typeof e=="object"?Object.fromEntries(Object.entries(e).map(([r,a])=>[r,J(n,a)])):e}async function hn(n,e,t,r,a){var i;const s=e.find(t);if(!s)throw new TypeError(`There is no hook "${t}" in the hook table`);let o=r,l=Ne((i=r.capture)==null?void 0:i.self).map(([p])=>p),c=Le(n,s,r,a!==void 0);const{registration:h,stop:u}=await n.hook(s.id,c,p=>{var g;switch(p.kind){case"hook":{if(!a)return;const f=(p.args??[]).map(b=>O(n,n.decode(b))),m={};c.capture.args.forEach((b,x)=>{var M;m[((M=s.parameters[b])==null?void 0:M.name)??String(b)]=f[x]});const w={};(p.self??[]).forEach((b,x)=>{w[l[x]??String(x)]=O(n,n.decode(b))}),a({phase:p.phase,call:p.call,args:m,argList:f,self:w,..."value"in p?{value:O(n,n.decode(p.value))}:{},skipped:p.skipped===!0,hook:s});return}case"hook-dropped":(g=o.onDropped)==null||g.call(o,p.dropped);return;case"hook-failed":{const f=new C("FLASH",`The hook on ${ne(s)} failed and is off: ${p.error.message}`,p.error);o.onError?o.onError(f):console.error(f.message);return}}});return Object.assign(()=>u(),{registration:h,hook:s,update:async(p,g={})=>{var f;const m=Le(n,s,p,a!==void 0);await n.request({op:"rehook",registration:h,rules:m,resetCounts:g.resetCounts??!1}),o=p,c=m,l=Ne((f=p.capture)==null?void 0:f.self).map(([w])=>w)},stats:async()=>(await n.request({op:"hookStats"})).find(g=>g.registration===h)??null})}async function un(n,e,t){if(await n.whenReady(),!n.features.includes("drive"))throw new Error("This game is running a loader from before repeated calls; call it yourself each frame");const r=T(e);if(r.path.length===0)throw new TypeError("A repeat calls a method, so name one: `place.method`, not the object");const a=t.while?Ot(n,t.while):null;return n.drive({writes:[],calls:[{target:r.target,path:r.path,args:(t.args??[]).map(i=>Q(n,i)),times:Math.max(1,Math.trunc(t.times??1))}],everyFrames:Math.max(1,Math.trunc(t.everyFrames??1)),while:a,restore:!1,once:t.once===!0},t.onFailed)}async function Xe(n,e,t){if(await n.whenReady(),!n.features.includes("drive"))throw new Error("This game is running a loader from before held values; write it yourself each frame");if(e.length===0)throw new TypeError("A hold needs a value to keep");const r=e.map(({place:i,value:s})=>{const o=T(i);if(o.path.length===0)throw new TypeError("A hold writes to a member, so name one: `place.member`, not the object");return{target:o.target,path:o.path,value:Q(n,s)}}),a=t.while?Ot(n,t.while):null;return n.drive({writes:r,everyFrames:Math.max(1,Math.trunc(t.everyFrames??1)),while:a,restore:t.restore!==!1,once:t.once===!0},t.onFailed)}class ve{constructor(e,t,r,a,i,s,o){this.host=e,this.kind=t,this.id=r,this.name=a,this.tagY=s,this.handle=o,this.place=i}host;kind;id;name;tagY;handle;place;highlight(e={}){return this.host.bridge.highlight(this.entry(),ee(e))}tag(e,t={}){const{anchorX:r,anchorY:a,...i}=t;return this.host.overlay.text(e,{centered:!0,font:{size:12,bold:!0,color:16777215},outline:0,...i,anchor:{place:this.place,x:r??0,y:a??this.tagY}})}onClick(e){const t=this.host.bridge;return this.kind!=="object"?this.place.$listen("mouseDown",()=>e(this)):t.stage().listen("mouseDown",r=>{const{stageX:a,stageY:i}=r??{};typeof a!="number"||typeof i!="number"||this.place.$reference.at("hitTestPoint").call(a,i,!0).then(s=>{s===!0&&e(this)}).catch(()=>{})})}async release(){this.handle&&await this.handle.release()}entry(){const e=this.place.$reference;return{target:e.target,path:[...e.path]}}}class dn{constructor(e){this.host=e}host;async players(){const e=this.host.bridge,t=e.definition("avatar.AvatarManager").at("avatarViewList"),r=await t.get(),a=r&&typeof r=="object"&&!(r instanceof L)?Object.keys(r):[],i=a.map(s=>r[s]).filter(s=>s instanceof L);try{const s=await Promise.all(a.map(o=>B(t.at(o,"userName").get())));return a.map((o,l)=>new ve(this.host,"player",o,typeof s[l]=="string"?s[l]:null,R(e,t.at(o)),-80,null))}finally{await e.release(i)}}async npcs(){const e=this.host.bridge,t=e.definition("quest.QuestManager").at("_questActors"),r=await B(t.at("length").get());if(typeof r!="number"||r<=0)return[];const a=Array.from({length:Math.min(r,500)},(c,h)=>String(h)),[i,s,o]=await Promise.all([Promise.all(a.map(c=>B(t.at(c).get()))),Promise.all(a.map(c=>B(t.at(c,"_actorId").get()))),Promise.all(a.map(c=>B(t.at(c,"currAvatar","avName").get())))]),l=[];return a.forEach((c,h)=>{const u=i[h];if(!(u instanceof L))return;const d=o[h];l.push(new ve(this.host,"npc",typeof s[h]=="string"?s[h]:c,typeof d=="string"&&d?d:null,R(e,u.at(),{handle:u}),-90,u))}),l}async objects(){const e=this.host.bridge,t=e.definition("room.RoomManagerWorld").at("instance","volumeManager","_volumeActors");let r;try{r=await t.at("length").get()}catch(h){throw h instanceof C&&h.code==="FLASH"?new C("FLASH",`The room's objects are private to the client, and this client does not reach them: ${h.message}`,h.flash):h}if(typeof r!="number"||r<=0)return[];const a=Array.from({length:Math.min(r,500)},(h,u)=>String(u)),[i,s]=await Promise.all([Promise.all(a.map(h=>B(t.at(h,"name").get()))),Promise.all(a.map(h=>B(t.at(h,"interactiveObjs","length").get())))]),o=[];a.forEach((h,u)=>{const d=s[u],p=i[u];for(let g=0;typeof d=="number"&&g<Math.min(d,50);g++)o.push([h,String(g),typeof p=="string"?p:null])});const l=await Promise.all(o.map(([h,u])=>B(t.at(h,"interactiveObjs",u,"mc").get()))),c=[];return o.forEach(([h,u,d],p)=>{const g=l[p];g instanceof L&&c.push(new ve(this.host,"object",`${d??h}#${u}`,d,R(e,g.at(),{handle:g}),0,g))}),c}}function B(n){return n.catch(()=>null)}async function fn(n,e,t){if(await n.whenReady(),!n.features.includes("find"))throw new Error("This game is running a loader from before searches; only a path reaches an object");const r=e===void 0?{target:{kind:"stage"},path:[]}:T(e);return(await n.find(r,pn(t))).map(i=>R(n,i.at(),{handle:i}))}function pn(n){const e={};return n.ofClass!==void 0&&(e.ofClass=n.ofClass),n.named!==void 0&&(e.named=n.named),n.containing!==void 0&&(e.containing=n.containing),n.visibleOnly!==void 0&&(e.visibleOnly=n.visibleOnly),n.through!==void 0&&(e.through=n.through),n.depth!==void 0&&(e.depth=n.depth),n.limit!==void 0&&(e.limit=n.limit),e}const Je={backspace:8,tab:9,enter:13,return:13,shift:16,control:17,ctrl:17,alt:18,pause:19,capslock:20,escape:27,esc:27,space:32,pageup:33,pagedown:34,end:35,home:36,left:37,arrowleft:37,up:38,arrowup:38,right:39,arrowright:39,down:40,arrowdown:40,insert:45,delete:46,";":186,"=":187,",":188,"-":189,".":190,"/":191,"`":192,"[":219,"\\":220,"]":221,"'":222};function gn(n){return n===!0?"always":n===!1?"never":n??"empty"}function mn(n,e={}){const t={phase:e.phase??"down",consume:e.consume??!1,whileTyping:gn(e.whileTyping),repeat:e.repeat??!1};if(typeof n=="number")return{code:n,ctrl:null,shift:null,alt:null,...t};const r=n==="+"||n.endsWith("++"),a=(r?n.slice(0,-1):n).split("+").map(o=>o.trim()).filter(Boolean);r&&a.push("+");const i={ctrl:!1,shift:!1,alt:!1};let s=null;for(const o of a){const l=o.toLowerCase();l==="ctrl"||l==="control"||l==="cmd"||l==="meta"?i.ctrl=!0:l==="shift"?i.shift=!0:l==="alt"||l==="option"?i.alt=!0:l==="any"?s=null:s=wn(o)}if(s===null&&!a.some(o=>o.toLowerCase()==="any"))throw new TypeError(`"${n}" names no key`);return{code:s,...i,...t}}function wn(n){const e=n.toLowerCase();if(e in Je)return Je[e];if(/^[a-z0-9]$/i.test(n))return n.toUpperCase().charCodeAt(0);const t=/^f([1-9]|1[0-5])$/i.exec(n);if(t)return 111+Number(t[1]);const r=/^num(?:pad)?([0-9])$/i.exec(n);if(r)return 96+Number(r[1]);if(n==="+")return 187;throw new TypeError(`Unknown key "${n}"`)}class yn{constructor(e){this.bridge=e}bridge;table=null;async set(e,t){const[r]=await G(this.bridge,[t]);await this.bridge.note(await this.number(),"write",T(e),r)}async get(e){const t=await this.bridge.note(await this.number(),"read",T(e));return t==null?void 0:O(this.bridge,t)}async has(e){return await this.bridge.note(await this.number(),"has",T(e))===!0}async forget(e){return await this.bridge.note(await this.number(),"forget",T(e))===!0}async objects(){const e=await this.bridge.note(await this.number(),"keys");return Array.isArray(e)?e.filter(t=>t instanceof L).map(t=>R(this.bridge,t.at(),{handle:t})):[]}async clear(){this.table!==null&&await this.bridge.note(this.table,"clear")}async number(){if(await this.bridge.whenReady(),!this.bridge.features.includes("notes"))throw new Error("This game is running a loader from before notes; nothing can be kept beside its objects");return this.table??=this.bridge.allocate(),this.table}}const bn=127;function At(n){const e=[],t=[];let r="",a=0;const i=()=>{const o={};for(const l of t)Object.assign(o,l.look);return o},s=()=>{if(r==="")return;const o={text:r,...i()},l=e[e.length-1];l&&Mn(l,o)?l.text+=r:e.push(o),r=""};for(;a<n.length;){const o=n[a];if(o!=="["){r+=o,a++;continue}if(n[a+1]==="["){r+="[",a+=2;continue}const l=n.indexOf("]",a+1),c=l<0?null:vn(n.slice(a+1,l));if(c===null){r+=o,a++;continue}if(c.closing){const h=Tn(t,c.name);h<0?r+=n.slice(a,l+1):(s(),t.splice(h))}else s(),t.push({tag:c.name,look:c.look});a=l+1}return s(),e}function vn(n){if(n.startsWith("/")){const a=n.slice(1);return kn.has(a)?{name:a,closing:!0}:null}const e=n.indexOf("="),t=e<0?n:n.slice(0,e),r=e<0?null:n.slice(e+1);switch(t){case"b":return r===null?{name:t,closing:!1,look:{bold:!0}}:null;case"i":return r===null?{name:t,closing:!1,look:{italic:!0}}:null;case"u":return r===null?{name:t,closing:!1,look:{underline:!0}}:null;case"color":{const a=r===null?null:En(r);return a===null?null:{name:t,closing:!1,look:{color:a}}}case"size":{const a=r===null?NaN:Number(r);return Number.isInteger(a)&&a>=1&&a<=bn?{name:t,closing:!1,look:{size:a}}:null}case"link":return r===null||r===""?null:{name:t,closing:!1,look:{link:r}};default:return null}}const kn=new Set(["b","i","u","color","size","link"]),xn="0123456789abcdef";function En(n){const e=n.toLowerCase(),t=e.startsWith("#")?e.slice(1):e.startsWith("0x")?e.slice(2):null;if(t===null||t.length!==6)return null;let r=0;for(const a of t){const i=xn.indexOf(a);if(i<0)return null;r=r*16+i}return r}function Tn(n,e){for(let t=n.length-1;t>=0;t--)if(n[t].tag===e)return t;return-1}function Mn(n,e){return["color","bold","italic","underline","size","font","link"].every(r=>n[r]===e[r])}const ke={className:"avatar.AvatarManager",path:["playerAvatarWorldView","parent"]},Ze=new Set(["click","down","up","over","out"]);class Sn{constructor(e){this.bridge=e}bridge;nodes=new Map;async draw(e,t={}){const{handle:r}=await this.make(e,t);return r}world(e={x:0,y:0},t={}){return{place:this.bridge.definition(ke.className).at(ke.path[0],ke.path[1]),x:e.x,y:e.y,...t}}marker(e,t={}){const{kind:r="circle",...a}=t;return this.draw(r,{radius:8,...a,anchor:this.world(e)})}group(e={}){return this.draw("group",e)}text(e,t={}){return this.draw("text",{...t,text:e})}rich(e,t={}){return this.draw("text",{...t,rich:e})}rect(e){return this.draw("rect",e)}circle(e){return this.draw("circle",e)}line(e){return this.draw("line",e)}image(e,t={}){return this.draw("image",{...t,url:e})}async input(e={}){const{handle:t,state:r}=await this.make("input",{width:200,height:24,fill:16777215,stroke:10265519,padding:4,...e,font:{color:1120295,...e.font}});return r.value=e.value??"",Object.assign(t,{value:()=>r.value,setValue:async i=>{r.value=i,r.removed||await this.bridge.draw(t.node,{value:i})},focus:async()=>{r.removed||await this.bridge.draw(t.node,{focus:!0})}})}async button(e,t={}){const{handle:r,state:a}=await this.make("button",{width:72,height:24,fill:8141549,hoverFill:9133302,pressedFill:7153881,cornerRadius:4,...t,font:{color:16777215,bold:!0,...t.font},label:e});return Object.assign(r,{setLabel:i=>a.removed?Promise.resolve():this.bridge.draw(r.node,{label:i}),setDisabled:i=>a.removed?Promise.resolve():this.bridge.draw(r.node,{disabled:i})})}async panel(e={}){const{onMove:t,onResize:r,...a}=e,{handle:i}=await this.make("panel",{width:260,height:200,fill:{color:1120295,alpha:.92},stroke:3621201,titleFill:2042167,titleHeight:22,cornerRadius:6,...a,titleFont:{color:16777215,bold:!0,...a.titleFont}}),s=i;return t&&s.on("move",t),r&&s.on("resize",r),s}async list(e={}){const{handle:t,state:r}=await this.make("list",{width:240,height:160,fill:{color:0,alpha:.55},padding:4,...e,font:{color:16777215,...e.font}});return Object.assign(t,{append:(...a)=>r.removed||a.length===0?Promise.resolve():this.bridge.draw(t.node,{append:a.map(xe)}),setRows:a=>r.removed?Promise.resolve():this.bridge.draw(t.node,{rows:a.map(xe)})})}async replace(e,t){return await t.update({parent:null,host:null,replaces:e}),()=>t.remove()}async attach(e,t){return await t.update({parent:null,replaces:null,host:e}),()=>t.remove()}async focusGame(){await this.bridge.stage().at("focus").set(null)}async clear(){const e=[...this.nodes.entries()].filter(([,t])=>t.parent===null||!this.nodes.has(t.parent)).map(([t])=>t);await this.remove(e)}async make(e,t){var r;const a=this.bridge.allocate(),i={type:e,...this.specOf(t)},s={parent:t.parent?t.parent.node:null,children:new Set,listeners:new Map,failed:new Set,gone:new Set,stopHearing:()=>{},removed:!1,value:""};s.stopHearing=this.bridge.onSubscription(a,o=>{var l;if(o.kind==="overlay"){if(o.event==="failed"){s.failed.forEach(c=>c(o.message??"The image did not load"));return}(o.event==="change"||o.event==="submit")&&o.value!==void 0&&(s.value=o.value),(l=s.listeners.get(o.event))==null||l.forEach(c=>c(o))}}),this.nodes.set(a,s);try{await this.bridge.draw(a,i)}catch(o){throw s.stopHearing(),this.nodes.delete(a),o}return s.parent!==null&&((r=this.nodes.get(s.parent))==null||r.children.add(a)),{handle:this.handle(a,e,s),state:s}}handle(e,t,r){const a=()=>this.remove([e]);return Object.assign(a,{node:e,type:t,update:async s=>{var o,l;if(r.removed)return;const c=this.specOf(s);"parent"in s&&(r.parent!==null&&((o=this.nodes.get(r.parent))==null||o.children.delete(e)),r.parent=s.parent?s.parent.node:null,r.parent!==null&&((l=this.nodes.get(r.parent))==null||l.children.add(e))),await this.bridge.draw(e,c)},show:()=>r.removed?Promise.resolve():this.bridge.draw(e,{visible:!0}),hide:()=>r.removed?Promise.resolve():this.bridge.draw(e,{visible:!1}),remove:a,on:(s,o)=>{const l=o,c=g=>{switch(g.event){case"change":case"submit":case"link":l(g.value??"");return;case"focus":case"blur":l(void 0);return;case"row":l(g.index??-1);return;case"move":l({x:g.x,y:g.y});return;case"resize":l({width:g.width??0,height:g.height??0});return;default:l({x:g.x,y:g.y})}};let h=r.listeners.get(s);const u=!h||h.size===0;h||(h=new Set,r.listeners.set(s,h)),h.add(c);const d=Ze.has(s);u&&d&&this.sendMouse(e,r);let p=!1;return async()=>{p||(p=!0,h.delete(c),d&&h.size===0&&!r.removed&&await this.sendMouse(e,r))}},onFailed:s=>(r.failed.add(s),()=>{r.failed.delete(s)}),onRemoved:s=>r.removed?(s(),()=>{}):(r.gone.add(s),()=>{r.gone.delete(s)})})}async sendMouse(e,t){const r=[...t.listeners.entries()].filter(([a,i])=>Ze.has(a)&&i.size>0).map(([a])=>a);await this.bridge.draw(e,{mouse:r})}async remove(e){const t=[],r=[],a=s=>{var o;const l=this.nodes.get(s);!l||l.removed||(l.removed=!0,l.stopHearing(),this.nodes.delete(s),t.push(s),r.push(...l.gone),l.gone.clear(),l.children.forEach(a),l.parent!==null&&((o=this.nodes.get(l.parent))==null||o.children.delete(s)))};e.forEach(a);const i=e.filter(s=>t.includes(s));try{await this.bridge.erase(i)}finally{for(const s of r)try{s()}catch(o){console.error("phantom.flash.overlay: a removal listener failed",o)}}}specOf(e){const t={};for(const[r,a]of Object.entries(e))if(a!==void 0)switch(r){case"parent":t.parent=a===null?null:a.node;break;case"anchor":t.anchor=a===null?null:An(a);break;case"host":case"replaces":t[r]=a===null?null:Pn(a);break;case"fill":case"background":case"hoverFill":case"pressedFill":case"titleFill":t[r]=a===null?null:Rn(a);break;case"stroke":t.stroke=a===null?null:$n(a);break;case"font":case"titleFont":t[r]=On(a);break;case"rich":t.spans=a===null?null:typeof a=="string"?At(a):a;break;case"rows":case"append":t[r]=a.map(xe);break;default:t[r]=a}return t}}function On(n){return{family:"_sans",size:12,color:16777215,bold:!1,italic:!1,...n}}function xe(n){if(typeof n=="string")return n||" ";const e=(Array.isArray(n)?n:At(n.markup)).filter(t=>t.text.length>0);return e.length?e:" "}function An(n){const e=typeof n=="object"&&n!==null&&"place"in n?n:{place:n},t=T(e.place);return{target:t.target,path:t.path,x:e.x??0,y:e.y??0,refreshFrames:e.refreshFrames??12,hideWhenGone:e.hideWhenGone??!0}}function Pn(n){const e=typeof n=="object"&&n!==null&&"place"in n?n:{place:n},t=T(e.place);return{target:t.target,path:t.path,refreshFrames:e.refreshFrames??12}}function Rn(n){return typeof n=="number"?{color:n,alpha:1}:{color:n.color,alpha:n.alpha??1}}function $n(n){return typeof n=="number"?{color:n,alpha:1,width:1}:{color:n.color,alpha:n.alpha??1,width:n.width??1}}async function Cn(n,e,t,r,a={}){const i=e.find(t);if(!i)throw new TypeError(`There is no hook "${t}" in the hook table`);const s={perFrame:a.perFrame??50};a.when!==void 0&&(s.when=a.when),a.first!==void 0&&(s.first=a.first),a.every!==void 0&&(s.every=a.every),a.replaceArgs!==void 0&&(s.replaceArgs=a.replaceArgs),"returns"in a&&(s.skip={returns:a.returns});const o={...Le(n,i,s,!1),override:!0};let l=0,c=Promise.resolve();const h=ne(i),u=async f=>{l++;let m=!1,w=!1;const b=f.args.map(A=>O(n,n.decode(A))),x={};b.forEach((A,_)=>{var y;x[((y=i.parameters[_])==null?void 0:y.name)??String(_)]=A});const M=i.isStatic?R(n,n.definition(i.className),{className:i.className}):O(n,n.decode(f.self)),j={hook:i,call:f.call,self:M,args:x,argList:b,original:async(...A)=>{if(w)throw new C("FLASH",`The call of ${h} has ended: its handler finished`);m=!0;const _=await n.invokeOriginal(d,f.token,A.length===0?null:await G(n,A));return O(n,_)}};try{await r(j)}catch(A){if(console.error(`The override of ${h} failed: ${A instanceof Error?A.message:String(A)}`),!m&&(a.onError??"original")==="original")try{await n.invokeOriginal(d,f.token,null)}catch(_){console.error(`The original ${h} failed after its override did: ${_ instanceof Error?_.message:String(_)}`)}}finally{w=!0,l--;try{await n.overrideDone(d,f.token)}catch{}}},{registration:d,stop:p}=await n.hook(i.id,o,f=>{var m;switch(f.kind){case"override":a.sequential?c=c.then(()=>u(f)):u(f);return;case"hook-dropped":(m=a.onDropped)==null||m.call(a,f.dropped);return;case"hook-failed":console.error(`The override of ${h} failed and is off: ${f.error.message}`);return}}),g=Object.assign(()=>p(),{registration:d,hook:i,stats:async()=>(await n.request({op:"hookStats"})).find(m=>m.registration===d)??null});return Object.defineProperty(g,"running",{get:()=>l,enumerable:!0}),g}const Fn={fit:"showAll",stretch:"exactFit",fill:"noBorder",none:"noScale"};class Ln{constructor(e){this.bridge=e}bridge;async zoom(e){await this.bridge.definition("room.RoomManagerWorld").at("instance","updateRoomZoom").call(Math.round(e))}async zoomLevel(){return await this.bridge.definition("gMainFrame").at("layerManager","bkg","scaleX").get()*100}async stretch(e){await this.bridge.stage().at("scaleMode").set(Fn[e])}hideHud(e){return this.bridge.highlight({target:{kind:"definition",name:"gui.GuiManager"},path:e?["mainHud",e]:["mainHud"]},ee({hide:!0}))}hideLayer(e){return this.bridge.highlight({target:{kind:"definition",name:"gMainFrame"},path:["layerManager",e]},ee({hide:!0}))}async setQuality(e){await this.bridge.stage().at("quality").set(e)}async setFrameRate(e){const t=this.bridge.stage().at("frameRate"),r=await t.get();return await t.set(Math.max(1,Math.min(120,e))),r}}class ze extends bt{format="json";envelope;constructor(e,t){super(e,t),this.envelope=Nn(e)}static create(e,t,r,a=-1,i="o"){const s=e==="toServer"?{t:"xt",b:{x:i,c:t,r:a,p:r}}:{t:"xt",b:{r:a,o:{_cmd:t,...r}}};return new ze(JSON.stringify(s),e)}get type(){return this.envelope.t}get command(){var e;const t=this.direction==="toServer"?this.envelope.b.c:(e=this.envelope.b.o)==null?void 0:e._cmd;return typeof t=="string"?t:null}get room(){const e=this.envelope.b.r;return typeof e=="number"&&Number.isInteger(e)?e:null}get params(){if(this.direction==="toServer")return this.envelope.b.p??{};const{_cmd:e,...t}=this.envelope.b.o??{};return t}get value(){return this.envelope}edit(e){e(this.envelope),this.markModified()}serialize(){return JSON.stringify(this.envelope)}}function Nn(n){let e;try{e=JSON.parse(n)}catch(t){throw new De(`Not JSON: ${t.message}`,"JSON_SYNTAX")}if(!Qe(e)||typeof e.t!="string"||!Qe(e.b))throw new De('A JSON message is an object with "t" and "b"',"JSON_SYNTAX");return e}function Qe(n){return typeof n=="object"&&n!==null&&!Array.isArray(n)}class et extends bt{constructor(e,t,r=null){super(e,t),this.problem=r}problem;format="raw";get command(){return null}get room(){return null}serialize(){return this.raw}}function Pt(n,e){try{switch(n.charAt(0)){case"<":return new It(n,e);case Lt:return new Nt(n,e);case"{":return new ze(n,e);default:return new et(n,e)}}catch(t){return new et(n,e,t)}}const Ie={send:"avatar.UserCommXtCommManager.onSendMessage",focusChat:"gui.ChatHistory.setFocusOnMsgText"};function In(n,e){const t=new Map;for(const[s,o]of Object.entries(e))t.set(s.toLowerCase(),o);if(t.size===0)return n;let r="",a="";const i=()=>{r+=t.get(a.toLowerCase())??a,a=""};for(const s of n)s===" "||s===" "?(i(),r+=s):a+=s;return i(),r}function jn(n,e){const t=n.toLowerCase();return e.some(r=>typeof r=="string"?r!==""&&t.includes(r.toLowerCase()):(r.lastIndex=0,r.test(n)))}async function _n(n,e={}){const{arg:t,fromClass:r,equals:a,exists:i,all:s}=n.flash.rules,o=e.shortcuts??{},l=e.blocked??[],c=r("avatar.UserCommXtCommManager","_mainHud","chatBar","text01_chat","text"),h=[],u=Be(async()=>{for(const d of h.splice(0).reverse())await d().catch(()=>{})});try{h.push(await n.flash.hook(Ie.send,{when:s(a(t("myMsg"),""),i(c)),replaceArgs:{myMsg:c}})),h.push(await n.flash.override(Ie.send,async d=>{var p;const[g,f]=d.argList,m=typeof f=="string"?f:"";if(m.trim()!==""&&jn(m,l)){(p=e.onBlocked)==null||p.call(e,m);return}const w=In(m,o);w===m?await d.original():await d.original(g,w)},{sequential:!0}))}catch(d){throw await u(),d}return u}async function zn(n,e={}){const t=e.style??{},r=n.flash.overlay,a=n.flash.use("gui.GuiManager").$at("mainHud"),i=e.maxLength??await n.flash.use("gui.GuiManager").$at("chatHist","chatMsgText","maxChars").$get().then(c=>typeof c=="number"&&c>0?c:70).catch(()=>70),s={family:t.font??"_sans",size:t.size??13},o=[],l=Be(async()=>{for(const c of o.splice(0).reverse())await c().catch(()=>{})});try{o.push(async()=>{await n.flash.use("gui.GuiManager").setFocusToChatText()});const c=await r.input({replaces:a.$at("chatBar"),placeholder:t.placeholderText??"Say something",maxLength:i,fill:t.background??16777215,stroke:t.border??8141549,cornerRadius:t.cornerRadius??6,padding:6,font:{...s,color:t.text??1120295}});o.push(()=>c.remove());const h=await r.button(t.buttonLabel??"Send",{replaces:a.$at("sendChatBtn"),fill:t.button??8141549,hoverFill:t.buttonHover??9133302,cornerRadius:t.cornerRadius??6,font:{...s,color:t.buttonText??16777215,bold:!0}});o.push(()=>h.remove());let u=!1;const d=async()=>{const p=c.value();if(!(u||p.trim()==="")){u=!0;try{await n.chat.say(p),await c.setValue(""),await c.focus()}finally{u=!1}}};return o.push(c.on("submit",()=>{d()})),o.push(h.on("click",()=>{d()})),o.push(await n.flash.hook(Ie.focusChat,{skip:!0,phase:"enter",capture:{args:[]}},()=>{c.focus()})),(e.focus??!0)&&await c.focus(),Object.assign(l,{input:c,send:d})}catch(c){throw await l(),c}}const Bn=[16096779,1096065,3900150,15485081,9133302,15680580,1357990,15381256],Ee=22;async function Hn(n,e={}){const t=e.style??{},r=n.flash.overlay,a=t.nameColors&&t.nameColors.length>0?t.nameColors:Bn,i=e.width??280,s=e.height??200,o={family:t.font??"_sans",size:t.size??12},l=new Map,c=[],h=Be(async()=>{for(const u of c.splice(0).reverse())await Promise.resolve(u()).catch(()=>{})});try{const u=await r.panel({title:e.title??"Chat",x:e.x??12,y:e.y??60,width:i,height:s,resizable:!0,fill:{color:t.background??1120295,alpha:t.backgroundAlpha??.9},stroke:t.border??3621201,titleFill:t.titleBar??2042167,titleHeight:Ee,titleFont:{...o,color:t.titleText??16777215,bold:!0},...e.onMove?{onMove:e.onMove}:{}});c.push(()=>u.remove());const d=await r.list({parent:u,width:i,height:s-Ee,fill:null,maxRows:e.maxRows??200,font:{...o,color:t.text??15987958}});c.push(u.on("resize",w=>{var b;(b=e.onResize)==null||b.call(e,w),d.update({width:w.width,height:w.height-Ee})})),c.push(d.on("link",w=>{const b=l.get(w);if(b){if(e.onNameClick){e.onNameClick(b);return}Dn(n,b.userId)}}));const p=async w=>{let b=null;if(w.kind===ye.free||w.kind===ye.freeSafeChat?b=w.text:w.kind===ye.safeChat&&(b=await n.chat.phrase(w.text).catch(()=>null)??null),b===null)return null;const x=n.room.players.get(w.userId),M=(x==null?void 0:x.avatarName)||(x==null?void 0:x.userName)||`#${w.userId}`,j=String(w.userId);return l.set(j,{userId:w.userId,name:M}),[{text:M,bold:!0,color:a[Math.abs(w.userId)%a.length],link:j},{text:`: ${b}`}]},f=(await Promise.all(n.chat.recent.map(p))).filter(w=>w!==null);f.length>0&&await d.append(...f);let m=Promise.resolve();return c.push(n.chat.onMessage(w=>{m=m.then(async()=>{const b=await p(w);b&&await d.append(b)}).catch(()=>{})})),Object.assign(h,{panel:u,note:w=>d.append({markup:w})})}catch(u){throw await h(),u}}async function Dn(n,e){const t=n.flash.use("avatar.AvatarManager").avatarViewList.$at(String(e)),r=await n.flash.highlight(t,{color:16436245,strength:3});setTimeout(()=>{r()},2e3)}function Be(n){let e=null;return()=>e??=n()}class qn{constructor(e){this.bridge=e,this.overlay=new Sn(e),this.entities=new dn(this),this.view=new Ln(e)}bridge;overlay;entities;view;rules=cn;hookIndex=null;use(e){return R(this.bridge,this.bridge.definition(e),{className:e})}global(e){return R(this.bridge,this.bridge.definition(e))}stage(){return R(this.bridge,this.bridge.stage())}client(){return R(this.bridge,this.bridge.gameClient())}whenReady(){return this.bridge.whenReady()}hooks(e){if(e!==void 0||!this.hookIndex){const t=this.bridge.hookTable(e).then(r=>new ln(r));t.catch(()=>{this.hookIndex===t&&(this.hookIndex=null)}),this.hookIndex=t}return this.hookIndex}async hook(e,t={},r){return hn(this.bridge,await this.hooks(),e,t,r)}async override(e,t,...[r]){return Cn(this.bridge,await this.hooks(),e,t,r??{})}style(e,t){return this.bridge.style(T(e),t)}hold(e,t,r={}){return Xe(this.bridge,[{place:e,value:t}],r)}holdAll(e,t={}){return Xe(this.bridge,e,t)}repeat(e,t={}){return un(this.bridge,e,t)}collect(e,t,r={}){return sn(this.bridge,e,t,r)}async track(e,t,r={}){if(await this.bridge.whenReady(),!this.bridge.features.includes("track"))throw new Error("This game is running a loader from before lists; look for them yourself");const a=r.where===void 0?{target:{kind:"stage"},path:[]}:T(r.where),i=s=>s.filter(o=>o instanceof L).map(o=>R(this.bridge,o.at(),{handle:o}));return this.bridge.track(a,e,{...r.mode!==void 0?{mode:r.mode}:{},...r.everyFrames!==void 0?{everyFrames:r.everyFrames}:{}},({added:s,removed:o})=>t({added:i(s),removed:i(o)}))}async snapshot(e,t={}){if(await this.bridge.whenReady(),!this.bridge.features.includes("snapshot"))throw new Error("This game is running a loader from before pictures; nothing can be drawn");return this.bridge.snapshot(T(e),t)}notes(){return new yn(this.bridge)}async find(e,t){return await fn(this.bridge,t,e??{})}answering(e,t){return new an(this.bridge,e,t)}watch(e,t,r){const a=r;let i,s=[],o;if(Array.isArray(e))i="list",o=[...e];else if(Un(e))i="one",o=[e];else{i="record";const u=e;s=Object.keys(u),o=s.map(d=>u[d])}const l=o.map(T),c=u=>i==="one"?u[0]:i==="list"?u:Object.fromEntries(s.map((d,p)=>[d,u[p]]));let h=null;return this.bridge.watch(l,t,(u,d)=>{const p=u.map(m=>O(this.bridge,m)),g=c(p),f=l.map((m,w)=>(d==null?void 0:d[w])??null);a(g,h,i==="one"?f[0]:c(f)),h=g})}onTick(e,t={}){return this.bridge.tick(t.everyFrames??1,e)}highlight(e,t={}){return this.bridge.highlight(T(e),ee(t))}hide(e){return this.bridge.highlight(T(e),ee({hide:!0}))}recolor(e,t){const r=t?T(t):{target:{kind:"loader"},path:[]};return this.bridge.highlight(r,{glow:null,...Et(e),hide:!1,pulse:null})}onKey(e,t,r={}){return this.bridge.onKey(mn(e,r),a=>Wn(t)({code:a.code,char:a.char,ctrl:a.ctrl,shift:a.shift,alt:a.alt,phase:a.phase,consumed:a.consumed===!0}))}}function Wn(n){return e=>{try{const t=n(e);t instanceof Promise&&t.catch(r=>tt(r))}catch(t){tt(t)}}}function tt(n){console.error("phantom.flash.onKey: a listener failed",n)}function Un(n){try{return T(n),!0}catch{return!1}}const Vn={avatarManager:"avatar.AvatarManager"},Gn="com.sbi.loader.LoaderCache.fetchCDNURL",Yn=2e4;class Kn{channel;flash;hooks=new Map;constructor(e,t){this.channel=e.content??null,this.flash=t}get available(){return this.channel!==null}async replace(e,t){const r=this.reach(),a=nt(e);await this.unhook(Te(a));const i=await r.replace(a,Me(t)),s=[],o=await this.pointClientAt(a,i.url);return o&&(this.hooks.set(Te(a),o),s.push("client")),s.push("proxy"),{...i,how:s,stop:()=>this.restore(a).then(()=>{})}}async restore(e){const t=this.reach(),r=nt(e);return await this.unhook(Te(r)),t.restore(r)}replacements(){return this.reach().list()}onRequest(e){return this.reach().observe(e)}async replaceOnScreen(e,t,r={}){const{url:a,id:i}=await this.addressOf(t),{refreshFrames:s,...o}=r,l=await this.flash.overlay.image(a,{...o,replaces:s===void 0?e:{place:e,refreshFrames:s}});return{url:a,stop:async()=>{await l.remove(),i&&await this.reach().release(i)}}}async load(e,t={}){const r=this.flash.bridge,a=Me(e),i=await r.construct("flash.display.Loader"),s=[];try{const o=await r.definition("flash.system.ApplicationDomain").at("currentDomain").get();s.push(()=>o.release());const l=await r.construct("flash.system.LoaderContext",!1,o);s.push(()=>l.release()),await l.at("allowCodeImport").set(t.allowCode===!0).catch(()=>{});const c=this.whenLoaded(i,t.timeoutMs??Yn);if(a.kind==="data-url"){const u=await this.decodeInFlash(a.url);s.push(()=>u.release()),await i.at("loadBytes").call(u,l)}else{const u=await this.reach().hold(a);s.push(()=>this.reach().release(u.id)),await i.at("load").call(new fe("flash.net.URLRequest",[u.url]),l)}await c;const h=await i.at("content").get();if(!h)throw new Error("Nothing was loaded");return{content:h,loader:i,unload:async()=>{await i.at("unloadAndStop").call().catch(()=>{}),await h.release().catch(()=>{}),await i.release().catch(()=>{})}}}catch(o){throw await i.release().catch(()=>{}),o}finally{for(const o of s)await o().catch(()=>{})}}async pointClientAt(e,t){if(e.kind==="pattern")return null;const r=Xn(e.value);if(!r)return null;const{arg:a,equals:i,startsWith:s,any:o}=this.flash.rules,l=e.kind==="prefix"?s:i;try{return await this.flash.hook(Gn,{when:o(l(a("assetPath"),r),l(a("assetPath"),`/${r}`)),replaceReturn:t})}catch{return null}}async unhook(e){const t=this.hooks.get(e);t&&(this.hooks.delete(e),await t().catch(()=>{}))}async addressOf(e){const t=Me(e);if(t.kind==="data-url")return{url:t.url,id:null};const r=await this.reach().hold(t);return{url:r.url,id:r.id}}async decodeInFlash(e){const t=e.indexOf(",");if(t===-1||e.slice(0,t).indexOf(";base64")===-1)throw new Error("Only base64 data: URLs can be loaded into the client");const r=await this.flash.bridge.definition("phantom.overlay.Base64").at("decode").call(e.slice(t+1));if(!r)throw new Error("The loader could not decode those bytes");return r}whenLoaded(e,t){const r=e.at("contentLoaderInfo");return new Promise((a,i)=>{const s=[],o=h=>{clearTimeout(l);for(const u of s.splice(0))u().catch(()=>{});h?i(h):a()},l=setTimeout(()=>o(new Error(`Flash did not load those bytes within ${t}ms`)),t),c=(h,u)=>r.listen(h,()=>o(u===null?null:new Error(u))).then(d=>s.push(d),d=>o(d));c("complete",null),c("ioError","Flash could not read those bytes"),c("securityError","Flash refused those bytes")})}reach(){if(!this.channel)throw new Error("This game cannot replace content: it was made without a content origin");return this.channel}}function Te(n){return`${n.kind}:${n.value}`}function Xn(n){let e=n.charAt(0)==="/"?n.slice(1):n;const t=e.indexOf("?");t!==-1&&(e=e.slice(0,t)),e.slice(0,8)==="content/"&&(e=e.slice(8));const r=e.indexOf("/"),a=r===-1?e:e.slice(0,r);return r!==-1&&a.length>0&&Jn(a)&&(e=e.slice(r+1)),e}function Jn(n){for(const e of n)if(e<"0"||e>"9")return!1;return n.length>0}function nt(n){const e=typeof n=="string"?{kind:"path",value:n}:n;if(!e||typeof e.value!="string"||!e.value)throw new TypeError("A replacement matches a path, a prefix or a pattern");const t=e.kind;if(t!=="path"&&t!=="prefix"&&t!=="pattern")throw new TypeError(`${t} is not path, prefix or pattern`);const r=e.value.charAt(0)==="/"?e.value:`/${e.value}`;return{kind:t,value:r}}function Me(n){if(typeof n=="string")return n.slice(0,5).toLowerCase()==="data:"?{kind:"data-url",url:n}:{kind:"file",path:n};if(n instanceof ArrayBuffer)return{kind:"bytes",bytes:new Uint8Array(n)};if(ArrayBuffer.isView(n)){const e=n;return{kind:"bytes",bytes:new Uint8Array(e.buffer,e.byteOffset,e.byteLength)}}if(n&&typeof n=="object"){const e="contentType"in n&&n.contentType?n.contentType:null,t=e?{contentType:e}:{};if("bytes"in n){const r=n.bytes,a=r instanceof ArrayBuffer?new Uint8Array(r):r;if(!(a instanceof Uint8Array))throw new TypeError("bytes are a Uint8Array");return{kind:"bytes",bytes:a,...t}}if("dataUrl"in n&&typeof n.dataUrl=="string")return{kind:"data-url",url:n.dataUrl,...t};if("file"in n&&typeof n.file=="string")return{kind:"file",path:n.file,...t}}throw new TypeError("A source is bytes, a data: URL, or the path of a file on this computer")}const $={definitionByName:"GETDEFINITIONBYNAME",resourceStack:"com.sbi.loader.ResourceStack",guiManager:"gui.GuiManager",loadProgress:"loadProgress.LoadProgress",denEditor:"gui.DenEditor",fonts:"gui.Fonts",palette:"com.sbi.graphics.PaletteHelper",colorTable:"gui.ColorTable",avatarManager:"avatar.AvatarManager"},Zn={message:"com.sbi.popup.SBMessage",ok:"com.sbi.popup.SBOkPopup",okCancel:"com.sbi.popup.SBOkCancelPopup",yesNo:"com.sbi.popup.SBYesNoPopup",titled:"com.sbi.popup.SBStandardTitlePopup",parchment:"com.sbi.popup.SBParchmentPopup"},je={ink:1118483,line:3816e3,light:15790322,muted:10000543,accent:8141549,danger:15680580,size:12,cornerRadius:4},_e={ink:4403228,line:9071167,light:16643032,muted:9402972,accent:3123423,danger:13369344,size:11,cornerRadius:8},Se={game:28,phantom:24},Oe=22,Ae=4,rt={top:12,left:10,right:10,bottom:12},at=4293980400,Qn=12e4,er=500;function se(n){return(...e)=>{try{const t=n(...e);t instanceof Promise&&t.catch(U)}catch(t){U(t)}}}function U(n){console.error("phantom.ui: a listener failed",n)}const tr={game:110,phantom:96},ce="_sans";function nr(n,e=ce){return{skin:n,font:e,...n==="game"?_e:je}}const rr={PopupSkin:"The plain popup frame: `ba` (its `t`, `m` and `b` slices) and `c`, its content box.",PopupContent:"What a plain popup shows: a `text` field the popup sizes itself around.",OkPopupSkin:"The frame of a popup with one button.",OkPopupContent:"An OK button (`okBtn`) and the `text` above it.",YesNoPopupSkin:"The frame of a popup with two buttons.",YesNoPopupContent:"Yes (`yesBtn`) and No (`noBtn`), and the `text` above them.",okCancelPopupContent:"OK (`okCancelBtn`) and Cancel (`cancelBtn`).",ConfirmSkin:"The frame the client asks you to confirm something in.",Tooltip:"The client's own tooltip (`gui.ToolTipPopup`): `txt`, and `l`, `m` and `r`.",HelpTxtBubble:"The bubble the client points at something it is explaining.",closeBtn:"The round close button in the corner of the client windows.",scrollbar2:"A scrollbar: `track`, `handle`, `topBtn` and `botBtn`.",BuddyListPopup:"The buddy list window's frame.",BuddyListContent:"What the buddy list shows inside that frame.",BD_AvatarEditorSkin:"The frame of the avatar editor's own dialog.",BD_AvatarEditorContent:"What that dialog shows.",DenEditorAsset:"The whole den editor, as the client builds it.",MySettings:"The settings window.",MainHud:"The whole HUD.",FreeNameBar:"The name bar above a player who is not a member.",memberNameBar:"The name bar above a member.",AnimsTitleBanner:"The banner the client puts a title in.",ChatBalloonAsset:"A chat balloon.",Cursor:"The client's own mouse cursor.",QuestPickupIcon:"The icon an adventure shows over something to pick up.",MinigameLobbySkin:"A minigame lobby's frame.",MinigameLobbyContent:"What a minigame lobby shows.",BroadcastPopupSkin:"The frame an announcement is shown in.",BroadcastPopupContent:"What an announcement shows.",DenLockPopupSkin:"The frame of the den's lock settings.",DenLockPopupContent:"What the den lock settings show.",ReportRulesPopupSkin:"The frame of the report window's rules.",ReportRulesPopupContent:"What the report rules show."},ar=/^[A-Za-z_][A-Za-z0-9_]*$/;function it(n){if(!ar.test(n))throw new TypeError(`"${n}" is not a symbol name: a symbol is named in letters, digits and underscores`);return n}const st={gui:{className:$.guiManager,path:["guiLayer"]},hud:{className:$.guiManager,path:["mainHud"]},room:{className:$.avatarManager,path:["playerAvatarWorldView","parent"]},avatarEditor:{className:$.guiManager,path:["avatarEditor","avEditor"]},denEditor:{className:$.denEditor,path:["staticEditor"]}},ot="stage",lt={avatarEditor:{open:"gui.AvatarEditor.init",close:"gui.AvatarEditor.destroy",spot:"avatarEditor"},denEditor:{open:"gui.DenEditor.init",close:"gui.DenEditor.destroy",spot:"denEditor"},settings:{open:"gui.MySettings.init",close:"gui.MySettings.destroy",spot:null},buddyList:{open:"buddy.BuddyList.init",close:"buddy.BuddyList.destroy",spot:null},petCreator:{open:"gui.PetCreator.init",close:"gui.PetCreator.destroy",spot:null},achievements:{open:"gui.AchievementViewer.init",close:"gui.AchievementViewer.destroy",spot:null},bulletinBoard:{open:"gui.BulletinBoard.init",close:"gui.BulletinBoard.destroy",spot:null},playerSearch:{open:"gui.PlayerSearch.init",close:"gui.PlayerSearch.destroy",spot:null},recycle:{open:"gui.RecycleItems.init",close:"gui.RecycleItems.destroy",spot:null},trade:{open:"gui.TradeManager.init",close:"gui.TradeManager.destroy",spot:null},petInventory:{open:"gui.PetInventory.init",close:"gui.PetInventory.destroy",spot:null},reportPlayer:{open:"gui.ReportAPlayer.init",close:"gui.ReportAPlayer.destroy",spot:null},serverSelector:{open:"gui.ServerSelector.init",close:"gui.ServerSelector.destroy",spot:null}},ir={ok:0,yesNo:1,continueExit:2,continue:3};function sr(n,e,t={}){const r={slot:"layer"},a={slot:"callback"},i=t.name??null,s=Zn[n];switch(n){case"message":return{className:s,args:[r,{slot:"skin"},e,!0,!0,t.modal??!1,t.draggable??!0,t.darken??!1,i]};case"ok":return{className:s,args:[r,e,t.darken??!0,null,!0,!0,t.modal??!0,t.draggable??!1,i]};case"yesNo":return{className:s,args:[r,e,t.darken??!0,a,null,!0,!0,t.modal??!0,t.draggable??!1,i]};case"okCancel":return{className:s,args:[r,e,t.darken??!0,a,null]};case"titled":return{className:s,args:[r,e,t.title??null,t.mediaId??370,a,!0,t.darken??!0]};case"parchment":return{className:s,args:[r,ir[t.buttons??"ok"],e,t.darken??!0,a,null]}}}function ct(n){const e=Math.max(1,Math.floor(n.columns)),t=[];for(let r=0;r<Math.max(0,Math.floor(n.count));r++){const a=Math.floor(r/e),i=r%e;t.push({index:r,row:a,column:i,x:i*(n.tileWidth+n.gap),y:a*(n.tileHeight+n.gap),width:n.tileWidth,height:n.tileHeight})}return t}function or(n,e){const t=e.gap,r=n.length;if(r===0)return[];const a=(e.width+t)/r;return n.map((i,s)=>{const o=Math.round(s*a),l=s===r-1?e.width+t:Math.round((s+1)*a);return{index:s,value:i,x:o,width:Math.max(0,l-o-t)}})}function lr(n){const e=Math.max(0,n.contentHeight-n.viewHeight),t=Math.min(e,Math.max(0,n.offset)),r=n.minThumb??16,a=n.contentHeight>0?n.viewHeight/n.contentHeight:1,i=Math.max(Math.min(n.trackHeight,r),Math.min(n.trackHeight,Math.round(n.trackHeight*a))),s=n.trackHeight-i;return{offset:t,max:e,thumbY:e>0?Math.round(t/e*s):0,thumbHeight:i}}function cr(n,e,t){const r=Math.max(1,Math.round(n-e-t+1)),a=-Math.floor(r/2);return{middle:r,middleY:a,topY:a-e,bottomY:a+r-1}}function hr(n,e){const t=e?{top:e.y,left:e.x,right:n.width-e.x-e.width,bottom:n.height-e.y-e.height}:null,r=(s,o)=>{const l=t==null?void 0:t[s];return l!==void 0&&Number.isFinite(l)&&l>=2&&l<=o/4?Math.ceil(l):rt[s]},a={top:r("top",n.height),left:r("left",n.width),right:r("right",n.width),bottom:r("bottom",n.height)},i={x:a.left+Ae,y:a.top,width:Math.max(0,Math.floor(n.width-a.left-a.right-2*Ae)),height:Math.max(Oe,Math.floor(n.height-a.top-a.bottom-Ae))};return{edge:a,measured:t!==null&&Object.keys(rt).every(s=>a[s]===Math.ceil(t[s])),panel:i,titleHeight:Oe,body:{width:i.width,height:i.height-Oe}}}class ur{bridge;flash;drawn=new Set;popups=new Set;symbolMaker=null;gameFont=null;defaultSkin="phantom";known={art:!1,palettes:!1};readyTimeoutMs=Qn;popup;constructor(e,t){this.bridge=e.flash,this.flash=t,this.popup=new dr((r,a,i,s,o)=>this.openPopup(r,a,i,s,o),()=>this.clear())}get skin(){return this.defaultSkin}set skin(e){this.defaultSkin=e}async status(){const[e,t]=await Promise.all([this.artLoaded(),this.palettesLoaded()]);return{art:e,palettes:t}}async ready(e=this.readyTimeoutMs){const t=await this.waitFor({art:!0,palettes:!0},e);if(t.art&&t.palettes)return t;const r=[t.art?null:"its library art",t.palettes?null:"its colour palettes"].filter(Boolean);throw new Error(`The game has not loaded ${r.join(" or ")} yet: waited ${Math.round(e/1e3)} seconds`)}async theme(e){const t=e??this.defaultSkin;return nr(t,t==="game"?await this.clientFont():ce)}symbols(){return Object.entries(rr)}async hasSymbol(e){const t=it(e);try{return await this.bridge.definition($.resourceStack).at("hudAssetsLoaderInfo","applicationDomain","hasDefinition").call(t)===!0}catch{return!1}}async symbol(e,t={}){const r=it(e);await this.waitFor({art:!0});const a=await this.flash.overlay.group({x:t.x??0,y:t.y??0,...t.scale===void 0?{}:{scale:t.scale},...t.visible===void 0?{}:{visible:t.visible}});let i=null;try{i=await(await this.maker()).at("apply").call(null,[r,t.localize===!0]),await(await this.nodeObject(a)).at("addChild").call(i),await this.adopt(a,{...t.parent===void 0||t.parent===null?{}:{parent:P(t.parent)},...t.host===void 0?{}:{host:t.host===null?null:this.placeOf(t.host)},...t.replaces===void 0?{}:{replaces:t.replaces===null?null:this.placeOf(t.replaces)}})}catch(h){throw await a.remove(),i&&await this.bridge.release([i]).catch(()=>{}),h}const s=i,o=s.at(),l=new Set;return this.widget(a,t.skin??this.defaultSkin,{name:r,object:s,on:async(h,u)=>{const d=await o.listen(ht[h],()=>u()),p=async()=>{l.delete(p),await d()};return l.add(p),p},size:async()=>({width:await s.at("width").get()??0,height:await s.at("height").get()??0})},async()=>{for(const h of[...l])await h().catch(()=>{});await this.bridge.release([s]).catch(()=>{})})}async window(e={}){const t=e.skin??this.defaultSkin,r=t==="game",a=r&&(await this.waitFor({art:!0})).art,i=await this.theme(t),s={width:e.width??280,height:e.height??200},o={x:e.x??40,y:e.y??40},l=r?30:24,c=await this.flash.overlay.panel({x:o.x,y:o.y,width:s.width,height:s.height,title:e.title??"",titleHeight:l,draggable:e.draggable!==!1,resizable:e.resizable===!0&&!r,cornerRadius:i.cornerRadius,fill:r?{color:i.light,alpha:0}:{color:i.ink,alpha:.94},stroke:r?null:i.line,titleFill:i.line,titleFont:{family:i.font,size:i.size+1,bold:!0,color:i.light},visible:!1});let h=null;if(a)try{h=await this.dressWindow(c,s.height)}catch(w){console.warn(`phantom.ui.window: the popup frame could not be drawn: ${Re(w)}`)}else r&&console.warn(`phantom.ui.window: the game has not loaded its popup art after ${Math.round(this.readyTimeoutMs/1e3)} seconds, so "${e.title??""}" is drawn in the game skin's colours instead`);const u=h?{x:h.layout.panel.x,y:h.layout.panel.y}:{x:0,y:0};if(h?await c.update({x:o.x+u.x,y:o.y+u.y,width:h.layout.panel.width,height:h.layout.panel.height,titleHeight:h.layout.titleHeight,titleFill:{color:i.line,alpha:.004},titleFont:{family:i.font,size:i.size+1,bold:!0,color:i.ink}}):r&&await c.update({fill:{color:_e.light,alpha:.96},stroke:{color:_e.line,width:2}}),e.parent)try{await this.adopt(c,{parent:P(e.parent)})}catch(w){throw await c.remove(),h&&await this.bridge.release(h.held).catch(()=>{}),w}const d=h?{width:h.width,height:h.height,bodyWidth:h.layout.body.width,bodyHeight:h.layout.body.height}:{...s,bodyWidth:s.width,bodyHeight:Math.max(0,s.height-l)},p=new Set,g=[],f=this.widget(c,t,{body:c,...d,framed:h!==null,move:(w,b)=>c.update({x:w+u.x,y:b+u.y}),setTitle:w=>c.update({title:w}),onClose:w=>(p.add(w),async()=>{p.delete(w)}),onMove:w=>{const b=c.on("move",({x,y:M})=>w({x:x-u.x,y:M-u.y}));return async()=>{await b()}}},async()=>{for(const w of g.splice(0))await w().catch(()=>{});h&&await this.bridge.release(h.held).catch(()=>{})}),m=()=>{f().then(()=>p.forEach(w=>w()))};if(e.closable!==!1&&(h!=null&&h.close)){const w=await h.close.at().listen(ht.down,m);g.push(async()=>{await w()})}else e.closable!==!1&&(await this.flash.overlay.button("x",{parent:c,x:d.bodyWidth-(r?26:24),y:2,width:18,height:16,cornerRadius:i.cornerRadius,fill:i.line,hoverFill:{color:i.danger,alpha:.8},font:{family:i.font,size:i.size,bold:!0,color:i.light}})).on("click",m);return e.visible!==!1&&await c.show(),f}async button(e,t={}){const r=t.skin??this.defaultSkin,a=await this.theme(r),i=await this.flash.overlay.button(e,{...this.box(t,{width:tr[r],height:Se[r]}),...Z(a,t.primary===!0),cornerRadius:a.cornerRadius,...t.disabled===void 0?{}:{disabled:t.disabled},font:{family:a.font,size:a.size,bold:!0,color:t.primary===!0||r==="phantom"?a.light:a.ink}});return this.widget(i,r,{setLabel:s=>i.setLabel(s),setDisabled:s=>i.setDisabled(s),onClick:s=>{const o=i.on("click",se(s));return async()=>{await o()}}})}async label(e,t={}){const r=t.skin??this.defaultSkin,a=await this.theme(r),i=await this.flash.overlay.text(e,{x:t.x??0,y:t.y??0,...t.parent?{parent:P(t.parent)}:{},...t.visible===void 0?{}:{visible:t.visible},centered:t.centered===!0,font:{family:a.font,size:t.heading===!0?a.size+3:a.size,bold:t.heading===!0,color:t.muted===!0?a.muted:r==="game"?a.ink:a.light},...t.background===!0?{background:r==="game"?{color:a.light,alpha:.9}:{color:a.ink,alpha:.7},padding:4}:{}});return this.widget(i,r,{setText:s=>i.update({text:s})})}async input(e={}){const t=e.skin??this.defaultSkin,r=await this.theme(t),a=await this.flash.overlay.input({...this.box(e,{width:200,height:Se[t]}),...e.value===void 0?{}:{value:e.value},...e.placeholder===void 0?{}:{placeholder:e.placeholder},...e.maxLength===void 0?{}:{maxLength:e.maxLength},...e.multiline===void 0?{}:{multiline:e.multiline},...e.disabled===void 0?{}:{disabled:e.disabled},fill:t==="game"?r.light:16777215,stroke:r.line,cornerRadius:r.cornerRadius,font:{family:r.font,size:r.size,color:t==="game"?r.ink:1120295}});return this.widget(a,t,{value:()=>a.value(),setValue:i=>a.setValue(i),focus:()=>a.focus(),onChange:i=>{const s=a.on("change",se(i));return async()=>{await s()}},onSubmit:i=>{const s=a.on("submit",se(i));return async()=>{await s()}}})}async checkbox(e,t={}){const r=t.skin??this.defaultSkin,a=await this.theme(r),i=await this.flash.overlay.group({x:t.x??0,y:t.y??0,...t.parent?{parent:P(t.parent)}:{},...t.visible===void 0?{}:{visible:t.visible}});let s=t.checked===!0;const o=await this.flash.overlay.button(s?"x":"",{parent:i,width:14,height:14,cornerRadius:Math.min(3,a.cornerRadius),fill:r==="game"?a.light:{color:a.ink,alpha:.9},hoverFill:r==="game"?16777215:{color:a.line,alpha:.9},stroke:a.line,font:{family:a.font,size:a.size,bold:!0,color:a.accent}});await this.flash.overlay.text(e,{parent:i,x:20,y:0,font:{family:a.font,size:a.size,color:r==="game"?a.ink:a.light}});const l=new Set,c=async h=>{s=h,await o.setLabel(h?"x":"")};return o.on("click",()=>{c(!s).then(()=>l.forEach(h=>h(s)))}),this.widget(i,r,{checked:()=>s,setChecked:c,onChange:h=>(l.add(h),async()=>{l.delete(h)})})}async dropdown(e){var t;const r=e.skin??this.defaultSkin,a=await this.theme(r),i=e.width??140,s=e.height??Se[r],o=await this.flash.overlay.group({x:e.x??0,y:e.y??0,...e.parent?{parent:P(e.parent)}:{},...e.visible===void 0?{}:{visible:e.visible}});let l=[...e.choices],c=e.value??((t=l[0])==null?void 0:t.value)??null;const h=f=>{var m;return((m=l.find(w=>w.value===f))==null?void 0:m.label)??e.placeholder??"Choose..."},u=await this.flash.overlay.button(h(c),{parent:o,width:i,height:s,cornerRadius:a.cornerRadius,...Z(a,!1),font:{family:a.font,size:a.size,color:r==="game"?a.ink:a.light}}),d=await this.flash.overlay.list({parent:o,y:s+2,width:i,height:Math.min(140,Math.max(20,l.length*16+8)),visible:!1,fill:r==="game"?a.light:{color:a.ink,alpha:.96},stroke:a.line,cornerRadius:a.cornerRadius,rows:l.map(f=>f.label),font:{family:a.font,size:a.size,color:r==="game"?a.ink:a.light}});let p=!1;const g=new Set;return u.on("click",()=>{p=!p,p?d.show():d.hide()}),d.on("row",f=>{const m=l[f];p=!1,d.hide(),m&&(c=m.value,u.setLabel(m.label).then(()=>g.forEach(w=>w(m.value))))}),this.widget(o,r,{value:()=>c,setValue:async f=>{c=f,await u.setLabel(h(f))},setChoices:async f=>{l=[...f],await d.setRows(l.map(m=>m.label)),await u.setLabel(h(c))},onChange:f=>(g.add(f),async()=>{g.delete(f)})})}async tabs(e){var t;const r=e.skin??this.defaultSkin,a=await this.theme(r),i=e.width??260,s=e.tabHeight??22,o=await this.flash.overlay.group({x:e.x??0,y:e.y??0,...e.parent?{parent:P(e.parent)}:{},...e.visible===void 0?{}:{visible:e.visible}}),l=or(e.tabs.map(g=>g.value),{width:i,gap:2});let c=e.value??((t=e.tabs[0])==null?void 0:t.value)??"";const h=new Map,u=new Map,d=new Set;for(const g of l){const f=e.tabs[g.index];u.set(f.value,await this.flash.overlay.button(f.label,{parent:o,x:g.x,width:g.width,height:s,cornerRadius:a.cornerRadius,...Z(a,f.value===c),font:{family:a.font,size:a.size,bold:f.value===c,color:f.value===c||r==="phantom"?a.light:a.ink}})),h.set(f.value,await this.flash.overlay.group({parent:o,y:s+4,visible:f.value===c}))}const p=async g=>{if(h.has(g)){c=g;for(const[f,m]of h)await(f===g?m.show():m.hide());for(const[f,m]of u)await m.update({...Z(a,f===g),font:{family:a.font,size:a.size,bold:f===g,color:f===g||r==="phantom"?a.light:a.ink}})}};for(const[g,f]of u)f.on("click",()=>{p(g).then(()=>d.forEach(m=>m(g)))});return this.widget(o,r,{current:()=>c,select:p,body:g=>{const f=h.get(g);if(!f)throw new TypeError(`There is no tab called "${g}"`);return f},onSelect:g=>(d.add(g),async()=>{d.delete(g)})})}async list(e={}){const t=e.skin??this.defaultSkin,r=await this.theme(t),a=await this.flash.overlay.list({...this.box(e,{width:240,height:160}),...e.rows===void 0?{}:{rows:[...e.rows]},...e.maxRows===void 0?{}:{maxRows:e.maxRows},fill:t==="game"?r.light:{color:r.ink,alpha:.85},stroke:r.line,cornerRadius:r.cornerRadius,font:{family:r.font,size:r.size,color:t==="game"?r.ink:r.light}});return this.widget(a,t,{setRows:i=>a.setRows([...i]),append:(...i)=>a.append(...i),onRow:i=>{const s=a.on("row",se(i));return async()=>{await s()}}})}async grid(e){const t=e.skin??this.defaultSkin,r=await this.theme(t),a={columns:e.columns??4,tileWidth:e.tileWidth??48,tileHeight:e.tileHeight??48,gap:e.gap??4},i=await this.flash.overlay.group({x:e.x??0,y:e.y??0,...e.parent?{parent:P(e.parent)}:{},...e.visible===void 0?{}:{visible:e.visible}}),s=new Set,o=[],l=async c=>{for(const u of o.splice(0))await u.remove();const h=ct({count:c.length,...a});for(const u of h){const d=c[u.index],p=await this.flash.overlay.button(d.label??"",{parent:i,x:u.x,y:u.y,width:u.width,height:u.height,cornerRadius:r.cornerRadius,fill:d.color??(t==="game"?r.light:{color:r.ink,alpha:.9}),hoverFill:d.color??(t==="game"?16777215:r.line),pressedFill:d.color??r.accent,stroke:r.line,...d.disabled===void 0?{}:{disabled:d.disabled},font:{family:r.font,size:r.size-2,color:t==="game"?r.ink:r.light}});p.on("click",()=>s.forEach(g=>g(d.value,u.index))),o.push(p),d.image!==void 0&&o.push(await this.flash.overlay.image(d.image,{parent:i,x:u.x+2,y:u.y+2,width:u.width-4,height:u.height-4}))}};return await l(e.items),this.widget(i,t,{setItems:l,onSelect:c=>(s.add(c),async()=>{s.delete(c)})})}async scroll(e={}){const t=e.skin??this.defaultSkin,r=await this.theme(t),a=e.width??220,i=e.height??120,s=e.step??32,o=await this.flash.overlay.panel({x:e.x??0,y:e.y??0,width:a,height:i,titleHeight:0,draggable:!1,cornerRadius:r.cornerRadius,fill:t==="game"?{color:r.light,alpha:.9}:{color:r.ink,alpha:.85},stroke:r.line,...e.parent?{parent:P(e.parent)}:{},...e.visible===void 0?{}:{visible:e.visible}}),l=await this.flash.overlay.group({parent:o,x:0,y:0});let c=e.contentHeight??i,h=0;const u=async d=>{h=lr({contentHeight:c,viewHeight:i,offset:d,trackHeight:i}).offset,await l.update({y:-h})};for(const[d,p,g]of[["^",-s,0],["v",s,i-16]])(await this.flash.overlay.button(d,{parent:o,x:a-16,y:g,width:14,height:14,cornerRadius:Math.min(3,r.cornerRadius),...Z(r,!1),font:{family:r.font,size:r.size-2,bold:!0,color:t==="game"?r.ink:r.light}})).on("click",()=>{u(h+p)});return this.widget(o,t,{body:l,offset:()=>h,scrollTo:u,setContentHeight:async d=>{c=d,await u(h)}})}async tooltip(e={}){const t=await this.bubble(e);return e.target&&this.explain(t,P(e.target)),t}async bubble(e){const t=e.skin??this.defaultSkin,r=e.text??"";if(t==="game"){const s=await this.clientTooltip(r,e);if(s)return s}const a=await this.theme(t),i=await this.flash.overlay.text(r,{x:e.x??0,y:e.y??0,visible:e.visible===!0,...e.parent?{parent:P(e.parent)}:{},background:t==="game"?{color:a.light,alpha:.95}:{color:a.ink,alpha:.92},padding:4,font:{family:a.font,size:a.size,color:t==="game"?a.ink:a.light}});return this.widget(i,t,{setText:s=>i.update({text:s}),showAt:async(s,o)=>{await i.update({x:s,y:o,visible:!0})}})}explain(e,t){const r=t.on("over",({x:s,y:o})=>{e.showAt(s+12,o-10).catch(U)}),a=t.on("out",()=>{e.hide().catch(U)}),i=t.onRemoved(()=>{e.remove().catch(U)});e.node.onRemoved(()=>{i(),r().catch(()=>{}),a().catch(()=>{})})}async progress(e={}){const t=e.skin??this.defaultSkin,r=await this.theme(t),a=e.width??200,i=e.height??16,s=await this.flash.overlay.group({x:e.x??0,y:e.y??0,...e.parent?{parent:P(e.parent)}:{},...e.visible===void 0?{}:{visible:e.visible}});await this.flash.overlay.rect({parent:s,width:a,height:i,cornerRadius:r.cornerRadius,fill:t==="game"?r.light:{color:r.ink,alpha:.9},stroke:r.line});let o=ut(e.value??0);const l=await this.flash.overlay.rect({parent:s,width:Math.round(a*o),height:i,cornerRadius:r.cornerRadius,fill:r.accent}),c=await this.flash.overlay.text(e.label??"",{parent:s,x:Math.round(a/2),y:Math.round(i/2),centered:!0,font:{family:r.font,size:r.size-1,bold:!0,color:t==="game"?r.ink:r.light}});return this.widget(s,t,{value:()=>o,setValue:async h=>{o=ut(h),await l.update({width:Math.round(a*o)})},setLabel:h=>c.update({text:h})})}async colors(e={}){const t=e.skin??this.defaultSkin,r=e.columns??10,a=e.swatchWidth??24,i=e.swatchHeight??30,{values:s,indexes:o}=await this.palette(e.palette??1),l=new Set;let c=e.value??o[0]??0;const h=p=>{c=p,l.forEach(g=>g(p,s[p]??0))},u=Math.max(1,Math.ceil(o.length/r)),d=t==="game"?await this.clientColorTable({columns:r,rows:u,width:r*a,height:u*i,values:s,indexes:o,current:c,options:e,tell:h}):await this.swatchGrid({columns:r,swatchWidth:a,swatchHeight:i,values:s,indexes:o,current:c,options:e,tell:h});return this.widget(d,t,{value:()=>c,onPick:p=>(l.add(p),async()=>{l.delete(p)})})}async paletteValues(e="game"){const{values:t,indexes:r}=await this.palette(e);return r.map(a=>t[a]??0)}places(){const e=Object.keys(st);return[ot,...e,...pr]}place(e){if(e===ot)return this.bridge.stage();const t=st[e];return t?this.bridge.definition(t.className).at(...t.path):this.bridge.definition($.guiManager).at("mainHud",e)}async attach(e,t){const r=P(t);return await this.flash.overlay.attach(this.placeOf(e),r),()=>r.remove()}async replace(e,t){const r=P(t);return await this.flash.overlay.replace(this.placeOf(e),r),()=>r.remove()}async hide(e){const t=await this.flash.hide(this.placeOf(e)),r=async()=>{this.drawn.delete(r),await t()};return this.drawn.add(r),r}piece(e,...t){return this.pieceOf(this.placeOf(e),t)}async feed(e,t,r={}){return typeof t=="function"?this.deferredFeed(e,t,r):this.insideFeed(e,t,r)}async insideFeed(e,t,r){if(!Object.keys(t).length)throw new TypeError(`A feed of ${e} names no argument to change`);let a=null,i=0;const s=await this.flash.hook(e,{phase:"enter",capture:{args:!0},replaceArgs:t,...r.when===void 0?{}:{when:r.when},...r.first===void 0?{}:{first:r.first},...r.every===void 0?{}:{every:r.every},...r.perFrame===void 0?{}:{perFrame:r.perFrame}},o=>{i+=1,a={method:e,call:o.call,args:[...o.argList],named:{...o.args},on:this.pieceOf(this.bridge.stage(),[])}});return this.feedOf(e,!0,s,()=>i,()=>a)}async deferredFeed(e,t,r){if(r.deferred!==!0)throw new TypeError(`A feed of ${e} was given a function, which cannot run inside the call: the client's method is skipped and run again once the function answers. A builder whose result the client uses in the same breath comes up empty that way. Give the arguments themselves to change them inside the call, or set "deferred" to say the waiting is understood.`);let a=null,i=0;const s=async c=>{i+=1;const h={method:e,call:c.call,args:[...c.argList],named:{...c.args},on:this.pieceOf(te(c.self)??this.bridge.stage(),[])};a=h;const u=await t(h);if(!u){await c.original();return}const d=[...h.args];for(const[p,g]of Object.entries(u)){const f=/^\d+$/.test(p)?Number(p):c.hook.parameters.findIndex(m=>m.name===p);if(f<0||f>=d.length){const m=c.hook.parameters.map(w=>w.name).join(", ");throw new TypeError(`${e} has no argument "${p}" (its arguments: ${m})`)}d[f]=g}await c.original(...d)},o={};r.when!==void 0&&(o.when=r.when),r.first!==void 0&&(o.first=r.first),r.every!==void 0&&(o.every=r.every),r.sequential!==void 0&&(o.sequential=r.sequential),r.perFrame!==void 0&&(o.perFrame=r.perFrame),r.returns!==void 0&&(o.returns=r.returns);const l=await this.flash.override(e,s,o);return this.feedOf(e,!1,l,()=>i,()=>a)}feedOf(e,t,r,a,i){const s=async()=>{this.drawn.delete(s),await r()};this.drawn.add(s);const o=s;return Object.defineProperty(o,"method",{value:e,enumerable:!0}),Object.defineProperty(o,"inside",{value:t,enumerable:!0}),Object.defineProperty(o,"calls",{get:a,enumerable:!0}),Object.defineProperty(o,"last",{value:i,enumerable:!0}),o}screens(){return Object.keys(lt)}onScreen(e,t){const r=lt[e];let a=!0;const i=[];return(async()=>{for(const[o,l]of[[r.open,!0],[r.close,!1]]){const c=await this.flash.hook(o,{phase:l?"exit":"enter",capture:{args:[]}},()=>t({name:e,open:l,spot:r.spot}));if(!a){await c();return}i.push(c)}})().catch(o=>{console.error(`phantom.ui.onScreen could not hook ${e}: ${Re(o)}`)}),()=>{a=!1;for(const o of i.splice(0))o().catch(()=>{})}}async clear(){for(const e of[...this.popups])await e().catch(()=>{});for(const e of[...this.drawn])await e().catch(()=>{})}pieceOf(e,t){const r=te(e);if(!r)throw new TypeError("Expected a place in the client, or one of Phantom's spots");const a=r.at(...t);return{place:a,at:(...s)=>this.pieceOf(a,s),exists:async()=>{try{const s=await a.get();return s!=null}catch{return!1}},get:async(...s)=>{try{const o=await a.at(...s).get();return O(this.bridge,o)??null}catch{return null}},set:(s,o)=>a.at(...typeof s=="string"?[s]:s).set(o),read:async(...s)=>{const o=await Promise.all(s.map(c=>a.at(c).get().catch(()=>null))),l={};return s.forEach((c,h)=>{l[c]=O(this.bridge,o[h]??null)}),l},call:async(s,...o)=>{const l=await G(this.bridge,o);return O(this.bridge,await a.at(s).call(...l))},on:async(s,o)=>{const l=await a.listen(s,h=>o(O(this.bridge,h))),c=async()=>{this.drawn.delete(c),await l()};return this.drawn.add(c),c},attach:s=>this.attach(a,s),replace:s=>this.replace(a,s),hide:()=>this.hide(a),use:()=>R(this.bridge,a)}}widget(e,t,r,a){let i=null;const s=()=>(i??=(async()=>{this.drawn.delete(o),a&&await a().catch(()=>{})})(),i),o=async()=>{await e.remove(),await s()};this.drawn.add(o),e.onRemoved(()=>{s()});const l={skin:t,node:e,move:(c,h)=>e.update({x:c,y:h}),show:()=>e.show(),hide:()=>e.hide(),remove:o,...r};for(const[c,h]of Object.entries(l))Object.defineProperty(o,c,{value:h,enumerable:!0,configurable:!0});return o}box(e,t){return{x:e.x??0,y:e.y??0,width:e.width??t.width,height:e.height??t.height,...e.parent?{parent:P(e.parent)}:{},...e.visible===void 0?{}:{visible:e.visible}}}placeOf(e){return typeof e=="string"?this.place(e):e}maker(){if(!this.symbolMaker){const e=this.bridge.definition($.definitionByName).get().then(t=>{if(!t)throw new TypeError("This client has no GETDEFINITIONBYNAME");return t});e.catch(()=>{this.symbolMaker===e&&(this.symbolMaker=null)}),this.symbolMaker=e}return this.symbolMaker}async nodeObject(e){const t=await new V(this.bridge,{kind:"overlay"},[]).at("getChildByName").call(`phantomNode${e.node}`);if(!t)throw new TypeError(`Overlay node ${e.node} is not drawn straight into the overlay, so it cannot be dressed`);return t}async adopt(e,t){const r=t.parent;if(r&&gr(r))throw new Error("What it was to be drawn in was taken off the screen before it could be put there");await e.update(t)}async waitFor(e,t=this.readyTimeoutMs){const r=Date.now()+Math.max(0,t);for(;;){const a=await this.status(),i=(!e.art||a.art)&&(!e.palettes||a.palettes),s=r-Date.now();if(i||s<=0||this.bridge.state==="closed")return a;await new Promise(o=>setTimeout(o,Math.min(er,s)))}}async artLoaded(){return this.known.art||(this.known.art=await this.hasSymbol("PopupSkin")),this.known.art}async palettesLoaded(){if(!this.known.palettes)try{const e=await this.bridge.definition($.palette).at("gamePalette").get();this.known.palettes=Array.isArray(e)&&e.length>0}catch{}return this.known.palettes}clientFont(){if(!this.gameFont){const e=this.bridge.definition($.fonts),t=this.known.palettes,r=(async()=>{for(const a of[["defaultFontFormat","font"],["defaultFont","fontName"]])try{const i=await e.at(...a).get();if(typeof i=="string"&&i.length>0)return i}catch{}return ce})();r.then(a=>{a===ce&&!t&&this.gameFont===r&&(this.gameFont=null)},()=>{this.gameFont===r&&(this.gameFont=null)}),this.gameFont=r}return this.gameFont}async frameOnly(e){const t=await e.at("numChildren").get()??0;for(let r=0;r<Math.min(t,32);r+=1){const a=await e.at("getChildAt").call(r);try{await a.at("name").get()!=="ba"&&await a.at("visible").set(!1)}finally{await this.bridge.release([a]).catch(()=>{})}}}async dressWindow(e,t){const a=await(await this.maker()).at("apply").call(null,["PopupSkin",!1]),i=[a];try{const s=a.at("ba"),[o,l]=await Promise.all([oe(s.at("t","height")),oe(s.at("b","height"))]),c=cr(t,o,l);await Promise.all([s.at("m","height").set(c.middle),s.at("m","y").set(c.middleY),s.at("t","y").set(c.topY),s.at("b","y").set(c.bottomY)]),await this.frameOnly(a);const h=await this.boundsOf(s,a),u={width:Math.round(h.width),height:Math.round(h.height)},d=await this.parchmentOf(a,h).catch(()=>null),p=hr(u,d);await Promise.all([a.at("x").set(Math.round(-h.x-p.panel.x)),a.at("y").set(Math.round(-h.y-p.panel.y))]);const g=await this.nodeObject(e);i.push(g),await g.at("addChildAt").call(a,0);const f=await this.frameClose(g,p).catch(()=>null);return f&&i.push(f),{...u,layout:p,close:f,held:i}}catch(s){throw await this.bridge.release(i).catch(()=>{}),s}}async frameClose(e,t){const a=await(await this.maker()).at("apply").call(null,["closeBtn",!1]);try{const i=await this.boundsOf(a,a);if(i.width<=0||i.height<=0)throw new TypeError("The close button has no size");const s=Math.min(1,(t.titleHeight-2)/i.height);return await Promise.all([a.at("scaleX").set(s),a.at("scaleY").set(s),a.at("x").set(Math.round(t.panel.width-2-(i.x+i.width)*s)),a.at("y").set(Math.round((t.titleHeight-i.height*s)/2-i.y*s))]),await e.at("addChild").call(a),a}catch(i){throw await this.bridge.release([a]).catch(()=>{}),i}}async boundsOf(e,t){const r=await e.at("getBounds").call(t);try{const[a,i,s,o]=await Promise.all(["x","y","width","height"].map(l=>oe(r.at(l))));return{x:a,y:i,width:s,height:o}}finally{await this.bridge.release([r]).catch(()=>{})}}async parchmentOf(e,t){const r=Math.ceil(t.width),a=Math.ceil(t.height);if(r<=0||a<=0||r>2048||a>2048)return null;const i=await this.bridge.construct("flash.display.BitmapData",r,a,!0,0);try{await i.at("draw").call(e,new fe("flash.geom.Matrix",[1,0,0,1,-t.x,-t.y]));const s=await i.at("getPixel32").call(Math.floor(r/2),Math.floor(a/2));if(typeof s!="number"||s>>>24!==255)return null;const o=await i.at("getColorBoundsRect").call(at,(s&at)>>>0,!0);try{const[l,c,h,u]=await Promise.all(["x","y","width","height"].map(d=>oe(o.at(d))));return{x:l,y:c,width:h,height:u}}finally{await this.bridge.release([o]).catch(()=>{})}}finally{await i.at("dispose").call().catch(()=>{}),await this.bridge.release([i]).catch(()=>{})}}async clientTooltip(e,t){let r;try{r=await this.symbol("Tooltip",{skin:"game",x:t.x??0,y:t.y??0,visible:t.visible===!0,...t.parent?{parent:t.parent}:{}})}catch{return null}const a=async i=>{await r.object.at("setToolTipText").call(i)};try{e&&await a(e)}catch{return await r.remove(),null}return Object.assign(r,{setText:a,showAt:async(i,s)=>{await r.node.update({x:i,y:s,visible:!0})}})}async palette(e){const t=await this.waitFor({palettes:!0}),r=this.bridge.definition($.palette),a=t.palettes?await r.at("gamePalette").get():null,i=dt(a);if(!i.length)throw new Error(`The game has not loaded its colour palettes yet: waited ${Math.round(this.readyTimeoutMs/1e3)} seconds`);if(e==="game")return{values:i,indexes:i.map((o,l)=>l)};const s=dt(await r.at(e===1?"avatarPalette1":"avatarPalette2").get());return{values:i,indexes:s.length?s:i.map((o,l)=>l)}}async clientColorTable(e){const t=await this.flash.overlay.group({x:e.options.x??0,y:e.options.y??0,visible:!1});try{const r=await this.bridge.construct($.colorTable);await r.at("init").call(0,e.width,e.height,e.columns,e.rows,e.values,e.indexes,e.current,(i,s)=>e.tell(Number(s)),-1);const a=await this.nodeObject(t);await a.at("addChild").call(r),await this.bridge.release([a,r]).catch(()=>{}),await this.adopt(t,{...e.options.parent?{parent:P(e.options.parent)}:{},visible:e.options.visible!==!1})}catch(r){throw await t.remove(),r}return t}async swatchGrid(e){const t=await this.flash.overlay.group({x:e.options.x??0,y:e.options.y??0,...e.options.parent?{parent:P(e.options.parent)}:{},...e.options.visible===void 0?{}:{visible:e.options.visible}}),r=ct({count:e.indexes.length,columns:e.columns,tileWidth:e.swatchWidth,tileHeight:e.swatchHeight,gap:1}),a={color:je.line,alpha:.6},i={color:je.light,width:2},s=new Map;let o=e.current;for(const l of r){const c=e.indexes[l.index],h=await this.flash.overlay.button("",{parent:t,x:l.x,y:l.y,width:l.width,height:l.height,cornerRadius:2,fill:e.values[c]??0,hoverFill:e.values[c]??0,stroke:c===o?i:a});s.set(c,h),h.on("click",()=>{var u;const d=o;o=c,d!==c&&((u=s.get(d))==null||u.update({stroke:a}).catch(U),h.update({stroke:i}).catch(U)),e.tell(c)})}return t}openPopup(e,t,r,a,i){let s=()=>{};const o=new Promise(f=>{s=f});let l=null,c=!1,h=null;const u=f=>{c||(c=!0,h&&clearTimeout(h),h=null,this.popups.delete(p),s(f))},d=()=>{c||h||(h=setTimeout(()=>u(i),fr))},p=async()=>{const f=l;l=null,u(i),f&&await f.at("destroy").call().catch(()=>{})};this.popups.add(p);const g=sr(e,t,r);return(async()=>{await this.waitFor({art:!0});const f=this.bridge.definition(r.layer==="load"?$.loadProgress:$.guiManager).at(r.layer==="load"?"loadLayer":"guiLayer"),m=[];for(const b of g.args){if(b!==null&&typeof b=="object"){if(b.slot==="layer")m.push(await f.get());else if(b.slot==="callback")m.push((...x)=>u(a(x[0]??null)));else{const x=await this.maker();m.push(await x.at("apply").call(null,["PopupSkin",!1]))}continue}m.push(b)}const w=await this.bridge.construct(g.className,...m);l=w,await w.at("closeCallback").set(()=>d()).catch(()=>{})})().catch(f=>{this.popups.delete(p),c||(c=!0,s(i)),console.error(`phantom.ui.popup.${e} could not open: ${Re(f)}`)}),Object.assign(o,{close:p})}}class dr{constructor(e,t){this.open=e,this.closeEverything=t}open;closeEverything;message(e,t={}){return this.open("message",e,t,()=>{},void 0)}ok(e,t={}){return this.open("ok",e,t,()=>{},void 0)}okCancel(e,t={}){return this.open("okCancel",e,t,Pe,null)}yesNo(e,t={}){return this.open("yesNo",e,t,Pe,null)}titled(e,t={}){return this.open("titled",e,t,()=>{},void 0)}parchment(e,t={}){return this.open("parchment",e,t,Pe,null)}async closeAll(){await this.closeEverything()}}const fr=50,ht={click:"click",down:"mouseDown",up:"mouseUp",over:"rollOver",out:"rollOut"},pr=["chatBar","chatHist","chatTxt","sendChatBtn","safeChatBtn","actionsBtn","emotesBtn","denBtn","worldMapBtn","buddyListBtn","newsBtn","partyBtn","mySettingsBtn","money","zoneName"];function P(n){if(!n)throw new TypeError("Expected a widget or an overlay node");return typeof n.node=="number"?n:n.node}function gr(n){let e=!1;return n.onRemoved(()=>{e=!0})(),e}function Z(n,e){return e?{fill:n.accent,hoverFill:{color:n.accent,alpha:.85},pressedFill:{color:n.accent,alpha:.7},stroke:n.line}:n.skin==="game"?{fill:n.light,hoverFill:16777215,pressedFill:n.line,stroke:n.line}:{fill:{color:n.ink,alpha:.92},hoverFill:n.line,pressedFill:{color:n.line,alpha:.7},stroke:n.line}}function Pe(n){if(n!==null&&typeof n=="object"&&!Array.isArray(n)){const e=n.status;if(typeof e=="boolean")return e}return null}function ut(n){return Number.isFinite(n)?Math.min(1,Math.max(0,n)):0}function Re(n){return n instanceof Error?n.message:String(n)}async function oe(n){const e=await n.get();if(typeof e!="number"||!Number.isFinite(e))throw new TypeError(`Expected a number at ${n.path.join(".")}, and read ${String(e)}`);return e}function dt(n){return Array.isArray(n)?n.map(e=>typeof e=="number"?e:0):[]}function he(n){return n instanceof S?{code:n.code,message:n.message,...n.stack?{stack:n.stack}:{}}:n instanceof Error?{code:"FAILED",message:n.message||n.name,...n.stack?{stack:n.stack}:{}}:{code:"FAILED",message:F(n)}}function mr(n){const e=n&&typeof n.code=="string"&&n.code?n.code:"FAILED";return new S(e,(n==null?void 0:n.message)||"Phantom could not do this")}function de(n){return q(n,new WeakMap)}function q(n,e){if(jt(n))return q(n.value,e);if(typeof n=="function"||typeof n=="symbol")return;if(typeof n!="object"||n===null)return n;const t=_t(n);if(e.has(t))return e.get(t);if(t instanceof Date||t instanceof RegExp||t instanceof ArrayBuffer||ArrayBuffer.isView(t))return t;if(Array.isArray(t)){const a=[];e.set(t,a);for(const i of t)a.push(q(i,e));return a}if(t instanceof Map){const a=new Map;e.set(t,a);for(const[i,s]of t)a.set(q(i,e),q(s,e));return a}if(t instanceof Set){const a=new Set;e.set(t,a);for(const i of t)a.add(q(i,e));return a}if(t instanceof Error)return he(t);const r={};e.set(t,r);for(const[a,i]of Object.entries(t)){const s=q(i,e);s!==void 0&&(r[a]=s)}return r}function F(n){if(typeof n=="string")return n;if(n instanceof Error)return n.stack||`${n.name}: ${n.message}`;if(n===void 0)return"undefined";if(typeof n=="function")return`[Function ${n.name||"anonymous"}]`;if(typeof n=="symbol"||typeof n=="bigint")return n.toString();try{const e=new WeakSet,t=JSON.stringify(de(n),(r,a)=>{if(typeof a=="object"&&a!==null){if(e.has(a))return"[Circular]";e.add(a)}return typeof a=="bigint"?`${a}n`:a});return ft(t??String(n))}catch{return ft(String(n))}}const $e=1e4;function ft(n){return n.length>$e?`${n.slice(0,$e)}… (${n.length-$e} more)`:n}const wr=["log","info","warn","error"];function yr(n,e){const t=new Map;let r=!1;for(const a of wr){const i=n[a].bind(n);t.set(a,i),n[a]=(...s)=>{if(i(...s),!r){r=!0;try{e(a,s.map(F))}finally{r=!1}}}}return()=>{for(const[a,i]of t)n[a]=i}}function br(n,e,t){return new qn(new Jt(vr(n,e),{firstId:t}))}function vr(n,e){const t=new Set;let r=null;const a=i=>{for(const s of t)s(i)};return{send(i){n.call("flash.request",e,[i]).catch(s=>{const o=kr(i,s);o?a(o):n.log("warn",[`A Flash request was refused: ${F(s)}`])})},onMessage(i){return t.add(i),r??=n.subscribe("flash.messages",e,{event(s){const[o]=s;typeof o=="string"&&a(o)},ended(s){r=null,s&&n.log("warn",[`Flash stopped answering: ${s.message}`])}}),()=>{t.delete(i),!t.size&&r&&(r(),r=null)}}}}function kr(n,e){let t;try{t=vt(n)}catch{return null}if(typeof(t==null?void 0:t.id)!="number")return null;const r=e instanceof S?e.code:"FAILED",a=e instanceof Error?e.message:F(e);return X({kind:"result",id:t.id,ok:!1,error:{name:r,message:a,errorId:0}})}function xr(n){let e=null,t=null;const r=()=>{const a=n.flash();return e??=new Kn({flash:a.bridge,content:Er(n.port,n.game)},a),e};return{avatar:{view:()=>n.flash().bridge.definition(Vn.avatarManager).at("playerAvatarWorldView").get()},adventures:{record:()=>Tr(n.remote)},realtime:{join:(a,i)=>Rt(n.remote.realtime,a,i)},content:{load:(a,i)=>r().load(a,i),replaceOnScreen:(a,i,s)=>r().replaceOnScreen(a,i,s)},ui:()=>{const a=n.flash();return t??=new ur({flash:a.bridge},a),t},recipes:{chatShortcuts:async a=>_n(await Ce(n),a),customChatBox:async a=>zn(await Ce(n),a),chatHistoryPanel:async a=>Hn(await Ce(n),a)}}}function Er(n,e){const t=()=>{throw new S("NOT_SUPPORTED","Only holding and releasing content happen in a frame")};return{hold:r=>n.call("content.hold",e,[r]),release:r=>n.call("content.release",e,[r]),replace:t,restore:t,list:t,observe:t}}function Tr(n){const e=Date.now(),t=[];let r=null,a=null;const i=()=>{r===null&&n.adventures.current().then(o=>r??=(o==null?void 0:o.scriptDefId)??null).catch(()=>{}),a===null&&n.adventures.actor("diff_level").then(o=>a??=(o==null?void 0:o.state)??null).catch(()=>{})};i();const s=n.adventures.onStep(({time:o,...l})=>{i(),t.push({...l,at:o-e})});return{stop:()=>(s(),{version:1,scriptDefId:r,difficulty:a,steps:[...t]})}}async function Ce(n){const e=n.flash(),{remote:t}=n,r=[...await t.chat.recent()],a=new Map;for(const i of await t.room.players.list())a.set(i.userId,i);return t.room.players.onEnter(i=>a.set(i.userId,i)),t.room.players.onLeave(i=>a.delete(i.userId)),t.chat.onMessage(i=>r.push(i)),{flash:e,chat:{say:t.chat.say,phrase:t.chat.phrase,onMessage:t.chat.onMessage,recent:r},room:{players:{get:i=>a.get(i)??null}}}}function Mr(n,e){const t={};for(const r of Object.keys($t)){const a=r.split(".");let i=t;for(const o of a.slice(0,-1))i=i[o]??={};const s=a[a.length-1];i[s]=Ct(r)?Ar(n,e,r):Or(n,e,r)}return He(t,"")}const Sr=new Set(["then","toJSON","constructor","nodeType","tagName"]);function He(n,e){for(const[t,r]of Object.entries(Object.getOwnPropertyDescriptors(n))){const a=r.get||r.set?null:r.value;!a||typeof a!="object"||!r.writable||(n[t]=He(a,`${e}${t}.`))}return new Proxy(Object.freeze(n),{get(t,r,a){if(typeof r!="string"||r in t)return Reflect.get(t,r,a);if(!(Sr.has(r)||r.startsWith("__v_")))throw new S("NOT_SUPPORTED",`phantom.${e}${r} is not in this Phantom's copy of the plugin SDK. Either the name is wrong, or Phantom is serving an older build of @phantomclient/plugin than this plugin was written against; building that package again gives every plugin the newer SDK.`)}})}function Or(n,e,t){return(...r)=>n.call(`sdk:${t}`,e,r)}function Ar(n,e,t){return r=>{if(typeof r!="function")throw new TypeError(`${t} takes a listener function`);return n.subscribe(`sdk:${t}`,e,{event:a=>r(...a),ended(a){a&&n.log("warn",[`${t} stopped: ${a.code}: ${F(a.message)}`])}})}}function pt(n,e,t,r){const a=i=>({direction:r,...i==="*"?{}:{commands:[...i]}});return{send(i){return n.call("packets.send",e,[t,String(i)])},watch(i,s){return n.subscribe("packets.watch",e,{event(o){const l=Rr(o,r);l&&s(Pt(l.text,l.direction))},ended:o=>{o&&n.log("warn",[`Watching the traffic stopped: ${o.message}`])}},a(i))},on(i,s){return n.subscribe("packets.intercept",e,{event:()=>{},intercepted:o=>{Pr(n,o,s)},ended:o=>{o&&n.log("warn",[`Hooking the traffic stopped: ${o.message}`])}},a(i))}}}async function Pr(n,e,t){let r;try{r=Pt(e.text,e.direction),await t(r)}catch(a){n.log("error",[`A traffic hook failed: ${F(a)}`]),n.verdict(e.requestId,!1,null);return}n.verdict(e.requestId,r.dropped,r.modified?r.encode():null)}function Rr(n,e){const[t,r]=n;if(typeof t=="string")return{text:t,direction:gt(r)?r:e};if(typeof t=="object"&&t!==null){const{text:a,direction:i}=t;if(typeof a=="string")return{text:a,direction:gt(i)?i:e}}return null}function gt(n){return n==="toServer"||n==="toClient"}function $r(n){const e=new Map,t=new Set;function r(i){var s,o;const l=i??Ht(k.role);if(!l)throw new S("NO_GAME",((s=k.role)==null?void 0:s.kind)==="page"||((o=k.role)==null?void 0:o.kind)==="logic"?"This frame works with several games: name one, as ctx.phantom(id), from ctx.games()":"This frame is not bound to a game yet");let c=e.get(l);return c||(c=Cr(n,l),e.set(l,c)),c}return{ctx:{get plugin(){return k.plugin},get granted(){return k.granted},get preferences(){return k.preferences},can:i=>Fr(k.granted.scopes,i),games:()=>[...k.games],onGames(i){return t.add(i),()=>t.delete(i)},phantom:r,storage:{get:i=>n.call("storage.get",null,[String(i)]),set:(i,s)=>n.call("storage.set",null,[String(i),s]),remove:i=>n.call("storage.remove",null,[String(i)]),keys:()=>n.call("storage.keys",null,[])},async fetch(i,s){const o=await n.call("fetch",null,[String(i),s??{}]);return Lr(o)},copy:i=>n.call("copy",null,[String(i)]),notify:(i,s)=>n.call("notify",null,s===void 0?[String(i)]:[String(i),String(s)]),toast:(i,s)=>n.call("toast",null,[String(i),s??{}]),confirm:(i,s)=>n.call("confirm",null,[String(i),s??{}]),openUrl:i=>n.call("openUrl",null,[String(i)]),log:(...i)=>n.log("log",i.map(F))},notifyGames(i){for(const s of[...t])try{s([...i])}catch(o){n.log("error",[`An onGames listener failed: ${F(o)}`])}},dispose(){t.clear(),e.clear()}}}function Cr(n,e){let t=null;const r=()=>{if(t)return t;if(k.flashIds===null)throw new S("PERMISSION_DENIED","game.flash needs the flash scope, which this plugin was not granted");return t=br(n,e,k.flashIds),t},a=Mr(n,e),i=xr({port:n,game:e,remote:a,flash:r}),s={...a,avatar:Object.freeze({...a.avatar,...i.avatar}),adventures:Object.freeze({...a.adventures,...i.adventures}),content:Object.freeze({...a.content,...i.content}),realtime:Object.freeze({...a.realtime,...i.realtime}),recipes:Object.freeze(i.recipes),id:e,server:pt(n,e,"toServer","toClient"),client:pt(n,e,"toClient","toServer")};return Object.defineProperties(s,{flash:{enumerable:!0,get:r},ui:{enumerable:!0,get:i.ui}}),He(s,"")}function Fr(n,e){if(n.includes(e))return!0;if(!e.startsWith("network:"))return!1;const t=e.slice(8);return n.some(r=>{if(!r.startsWith("network:*."))return!1;const a=r.slice(9);return t.endsWith(a)&&t.length>a.length})}function Lr(n){const e=n.body??"";return{status:n.status,ok:n.status>=200&&n.status<300,headers:n.headers??{},text:async()=>e,json:async()=>JSON.parse(e)}}const Nr=6e4;function Ir(n,e={}){const t=e.prefix??`f${Math.random().toString(36).slice(2,10)}-`,r=e.timeoutMs??Nr;let a=0,i=!1;const s=new Map,o=new Map,l=()=>`${t}${a+=1}`;function c(f,m){if(!i)try{n({phantom:I,type:"log",level:f,values:m})}catch{}}function h(f,m,w){if(i)return Promise.reject(new S("FAILED","The frame was closed"));const b=l();return new Promise((x,M)=>{const j=setTimeout(()=>{s.delete(b),M(new S("TIMEOUT",`Phantom did not answer ${f} in ${r/1e3}s`))},r);s.set(b,{resolve:x,reject:M,timer:j});try{n({phantom:I,type:"call",id:b,method:f,game:m,args:de(w)})}catch(A){clearTimeout(j),s.delete(b),M(new S("FAILED",`${f} could not be sent: ${F(A)}`))}})}function u(f,m,w,b){if(i)return()=>{};const x=l();o.set(x,w);try{n({phantom:I,type:"subscribe",id:x,topic:f,game:m,...b?{filter:de(b)}:{}})}catch(M){throw o.delete(x),new S("FAILED",`${f} could not be heard: ${F(M)}`)}return()=>{!o.delete(x)||i||n({phantom:I,type:"unsubscribe",id:x})}}function d(f,m,w){i||n({phantom:I,type:"verdict",requestId:f,drop:m,text:w})}function p(f){switch(f.type){case"call-result":{const m=s.get(f.id);return m?(s.delete(f.id),clearTimeout(m.timer),f.ok?m.resolve(f.value):m.reject(mr(f.error)),!0):!1}case"event":{const m=o.get(f.subscription);return m?(g(()=>m.event(Array.isArray(f.args)?f.args:[])),!0):!1}case"intercepted":{const m=o.get(f.subscription);return m!=null&&m.intercepted?(m.intercepted(f),!0):(d(f.requestId,!1,null),!!m)}case"subscription-ended":{const m=o.get(f.subscription);return m?(o.delete(f.subscription),g(()=>{var w;return(w=m.ended)==null?void 0:w.call(m,f.error)}),!0):!1}}}function g(f){try{f()}catch(m){c("error",[`A listener failed: ${F(m)}`])}}return{call:h,subscribe:u,verdict:d,log:c,receive:p,close(f){if(!i){i=!0;for(const m of s.values())clearTimeout(m.timer),m.reject(new S("FAILED",f));s.clear(),o.clear()}}}}function jr(n,e,t=new Set){const r=new Set;for(const[i,s]of Object.entries((e==null?void 0:e.variables)??{}))!i.startsWith("--phantom-")||typeof s!="string"||(n.style.setProperty(i,s),r.add(i));for(const i of t)r.has(i)||n.style.removeProperty(i);const a=(e==null?void 0:e.mode)==="light"?"light":"dark";return n.dataset.theme=a,n.style.setProperty("color-scheme",a),r}const _r=2e3;function zr(n,e){Dt(e.development??!1);let t=!1,r=new Set,a=null,i=null;function s(y){var v;t||(n.post(y),(v=e.tap)==null||v.call(e,y))}const o=Ir(s),l=$r(o),c=l.ctx;Ve(c);function h(y){var v;const E=he(y);try{s({phantom:I,type:"crash",error:E})}catch{}(v=n.view)==null||v.showError(E,k.development)}let u;const p=new Promise(y=>u=y).then(async()=>{try{const y=e.definition,v=await(typeof y=="function"?y():y);return a=Br(v),!0}catch(y){return h(y),!1}}),g=p.then(async y=>{var v;if(!y||((v=k.role)==null?void 0:v.kind)!=="logic")return y;if(s({phantom:I,type:"ready",implements:{pages:le(a==null?void 0:a.pages),panels:le(a==null?void 0:a.panels),commands:le(a==null?void 0:a.commands),commandViews:le(a==null?void 0:a.commandViews)}}),!(a!=null&&a.setup))return!0;try{const E=await a.setup(c);typeof E=="function"&&(t?j(E):i=E)}catch(E){h(E)}return!0});function f(y){if(t||!Ft(y))return;const v=y;switch(v.type){case"init":m(v);return;case"games":k.games=Array.isArray(v.games)?v.games:[],l.notifyGames(k.games);return;case"stop":_();return;case"mount":b(v);return;case"invoke":M(v);return;case"call-result":case"event":case"subscription-ended":case"intercepted":o.receive(v);return}}function m(y){var v;n.root&&y.theme&&(r=jr(n.root,y.theme,r)),Object.assign(k,{role:k.role??y.role??null,plugin:y.plugin??k.plugin,mode:((v=y.theme)==null?void 0:v.mode)==="light"?"light":"dark",granted:y.granted??{scopes:[]},preferences:y.preferences??{},games:Array.isArray(y.games)?y.games:[],flashIds:typeof y.flashIds=="number"?y.flashIds:null,development:k.development||!!y.development,initialized:!0}),l.notifyGames(k.games),u()}const w=n.listen(f);async function b(y){var v,E;const[H]=await Promise.all([p,((v=n.loadStyles)==null?void 0:v.call(n))??Promise.resolve()]);t||((E=k.role)==null?void 0:E.kind)==="logic"||(Object.assign(k,{kind:y.kind,contribution:y.contribution,props:y.props??{}}),H&&x())}function x(){var y;if(!k.kind||!k.contribution)return;const[v,E]=k.kind==="page"?[a==null?void 0:a.pages,"pages"]:k.kind==="panel"?[a==null?void 0:a.panels,"panels"]:[a==null?void 0:a.commandViews,"commandViews"],H=v==null?void 0:v[k.contribution];if(!H){h(new S("NOT_SUPPORTED",`definePlugin has no ${E}["${k.contribution}"], so there is nothing to show here`));return}try{(y=n.view)==null||y.mount(H,c)}catch(z){h(z)}}async function M(y){var v,E;const H=(z,me)=>{try{s({phantom:I,type:"result",id:y.id,ok:z,...me})}catch(we){s({phantom:I,type:"result",id:y.id,ok:!1,error:he(new S("FAILED",`The answer could not be sent to Phantom: ${F(we)}`))})}};try{if(!await g||!a)throw new S("FAILED","The plugin did not load");if(y.kind!=="commands")throw new S("NOT_SUPPORTED",`Phantom asked for an unknown kind, "${y.kind}"`);const z=(v=a.commands)==null?void 0:v[y.contribution];if(typeof z!="function")throw new S("NOT_SUPPORTED",`definePlugin has no commands["${y.contribution}"] function`);const me={arguments:((E=y.input)==null?void 0:E.arguments)??{}},we=await z(me,c.phantom(y.game),c);H(!0,{value:de(we??null)})}catch(z){H(!1,{error:he(z)})}}function j(y){try{const v=y();v instanceof Promise&&v.catch(E=>A(E))}catch(v){A(v)}}function A(y){o.log("error",[`setup's cleanup failed: ${F(y)}`])}async function _(){const y=i;if(i=null,y)try{await Promise.race([Promise.resolve(y()),new Promise(v=>setTimeout(v,_r))])}catch(v){A(v)}s({phantom:I,type:"stopped"})}return{ctx:c,crash:h,log:(y,v)=>o.log(y,v),replaceDefinition(y){var v;a=y,((v=k.role)==null?void 0:v.kind)!=="logic"&&x()},stop(){t||(i&&(j(i),i=null),t=!0,w(),o.close("The frame was closed"),l.dispose(),Ve(null))}}}function le(n){return Object.keys(n??{})}function Br(n){return!n||typeof n!="object"?{}:"default"in n&&n.default&&typeof n.default=="object"?n.default:n}const Hr={class:"flex flex-col p-3",role:"alert"},Dr={class:"flex flex-col gap-2 overflow-hidden rounded-lg border border-phantom-danger/25 bg-phantom-danger/10 px-3 py-2.5"},qr={class:"flex items-start gap-2"},Wr={class:"min-w-0 flex-1"},Ur={class:"text-xs font-medium text-phantom-danger"},Vr={class:"mt-0.5 break-words text-2xs text-phantom-text-soft"},Gr=["textContent"],Yr={key:1,class:"text-2xs text-phantom-subtle"},Kr=zt({__name:"ErrorCard",props:{error:{},development:{type:Boolean},kind:{}},emits:["dismiss"],setup(n,{emit:e}){const t=n,r=e,a=Bt(()=>t.kind==="panel"?"This panel":t.kind==="page"?"This page":"This plugin");return(i,s)=>(re(),ae("div",Hr,[K("div",Dr,[K("div",qr,[s[1]||(s[1]=K("span",{class:"mt-1.5 h-1.5 w-1.5 shrink-0 rounded-full bg-phantom-danger","aria-hidden":"true"},null,-1)),K("div",Wr,[K("p",Ur,be(a.value)+" stopped with an error",1),K("p",Vr,be(n.error.message),1)]),n.development?(re(),ae("button",{key:0,type:"button",class:"shrink-0 rounded px-1.5 text-2xs text-phantom-muted transition-colors hover:bg-phantom-danger/10 hover:text-phantom-text",onClick:s[0]||(s[0]=o=>r("dismiss"))}," Dismiss ")):qe("",!0)]),n.development&&n.error.stack?(re(),ae("pre",{key:0,class:"max-h-64 overflow-auto whitespace-pre-wrap break-words rounded-md bg-phantom-canvas/60 px-2.5 py-2 font-mono text-3xs text-phantom-muted",textContent:be(n.error.stack)},null,8,Gr)):n.development?qe("",!0):(re(),ae("p",Yr," More is in the plugin's log, in Plugins. "))])]))}});function Xr(n){let e=null,t=null,r=-1;const a=()=>{const o=Math.ceil(Math.max(n.content.scrollHeight,n.content.getBoundingClientRect().height));o!==r&&(r=o,n.onResize(o))},i=typeof ResizeObserver>"u"?null:new ResizeObserver(a);i==null||i.observe(n.content);function s(){t==null||t.unmount(),t=null,n.content.hidden=!1}return{mount(o,l){s(),e==null||e.unmount(),document.documentElement.dataset.kind=k.kind??"",e=We({name:"PhantomPluginView",render:()=>Ue(o,{...k.props})}),e.provide(qt,l),e.config.errorHandler=c=>n.onError(c),e.mount(n.content)},showError(o,l){t==null||t.unmount(),n.content.hidden=!0,t=We({render:()=>Ue(Kr,{error:o,development:l,kind:k.kind,onDismiss:()=>s()})}),t.mount(n.errors),a()},unmount(){i==null||i.disconnect(),e==null||e.unmount(),t==null||t.unmount(),e=null,t=null}}}function Jr(n){window.parent===window&&Zr();const e=mt("app"),t=mt("phantom-error");let r=null;function a(o){window.parent.postMessage(o,"*")}const i=Xr({content:e,errors:t,onError:o=>r==null?void 0:r.crash(o),onResize:o=>{document.documentElement.dataset.kind&&a({phantom:I,type:"resize",height:o})}});r=zr({post:a,listen(o){const l=c=>{c.source===window.parent&&o(c.data)};return window.addEventListener("message",l),()=>window.removeEventListener("message",l)},root:document.documentElement,view:i,...n.loadStyles?{loadStyles:n.loadStyles}:{}},n);const s=r;return yr(console,(o,l)=>s.log(o,l)),window.addEventListener("error",o=>{String(o.message).includes("ResizeObserver loop")||s.crash(o.error??o.message)}),window.addEventListener("unhandledrejection",o=>s.crash(o.reason)),window.addEventListener("pagehide",()=>{i.unmount(),s.stop()}),document.addEventListener("click",o=>{const l=o.target,c=l&&typeof l.closest=="function"?l.closest("a[href]"):null;if(!c)return;const h=c.getAttribute("href")??"";h.startsWith("#")||(o.preventDefault(),/^https:\/\//i.test(h)?s.ctx.openUrl(h).catch(()=>{}):s.log("warn",[`Only https links open from a plugin; this one goes to ${h}`]))}),s}function mt(n){const e=document.getElementById(n);if(e)return e;const t=document.createElement("div");return t.id=n,document.body.append(t),t}function Zr(){const n=document.createElement("p");n.className="m-6 max-w-md text-xs text-phantom-muted",n.textContent="This is a Phantom plugin frame. It runs inside Phantom: turn on Developer mode in Plugins, and a plugin served by phantom-plugin dev shows up there.",document.body.prepend(n)}const wt="/dist/plugin.js",Qr="/dist/plugin.css";let yt=null;function ea(){return yt??=new Promise(n=>{const e=document.createElement("link");e.rel="stylesheet",e.href=Qr,e.onload=e.onerror=()=>n(),document.head.append(e)}),yt}async function ta(){const n=await import(wt);if(!n.default)throw new Error(`${wt} has no default export. Export definePlugin({ ... }) as default.`);return n.default}Jr({definition:ta,loadStyles:ea});
|
|
1
|
+
import{i as hn,s as un,c as _n,a as Fn,b as Ln,d as In,j as jn,S as Dn,e as zn,P as q,f as Hn}from"./chunks/sdk-permissions-CDp6went.js";import{M as dn,P as vt,X as Wn,a as Bn,b as qn,C as De,c as $,r as Un,N as Ae,i as Vn}from"./chunks/api-0JFqyaCU.js";import{f as S,b as Ce,r as Gn,s as kt,P as Yn}from"./chunks/state-C-LOzJQV.js";import{i as Kn,t as Xn,d as Jn,o as ve,c as ke,a as le,b as ze,e as xt,f as Qn,g as Mt,h as St}from"./chunks/runtime-dom.esm-bundler-Dcouf4CU.js";class z extends Error{constructor(e,t,a=null){super(Zn(t,a,e)),this.code=e,this.flash=a,this.name="BridgeError"}code;flash}function Zn(n,e,t){if(typeof n=="string"&&n.trim()!=="")return ta(n,e);const a=na(n);if(a)return a;const r=typeof(e==null?void 0:e.name)=="string"?e.name.trim():"";return r||`The game answered with no reason (${t})`}const ea={1006:"that member is not a method",1009:"something the call reached was null",1010:"that member is not there",1034:"a value was not of the type the member takes",1056:"that object has nowhere to put the value",1063:"the call was given the wrong number of arguments",1069:"the object has no member of that name",1502:"a script in the game ran for longer than the player allows",2007:"a value the call needs was null"};function ta(n,e){const t=typeof(e==null?void 0:e.errorId)=="number"?e.errorId:0,a=ea[t];return!a||!/^\s*Error #\d+\s*$/.test(n)?n:`${n.trim()}: ${a}`}function na(n){if(n==null)return"";if(typeof n=="string")return n.trim();if(typeof n!="object")return String(n);const e=n;if(typeof e.message=="string"&&e.message.trim()!=="")return e.message;try{const t=JSON.stringify(n);return t&&t!=="{}"?t:""}catch{return""}}const Et=2;function ce(n){return encodeURIComponent(JSON.stringify(n))}function fn(n){return JSON.parse(decodeURIComponent(n))}function aa(n){return typeof n=="object"&&n!==null&&"$handle"in n}function ra(n){switch(n.kind){case"result":return n.id;case"event":return n.listener;case"callback":return n.callback;case"hook":case"override":case"hook-dropped":case"hook-failed":return n.registration;case"watch":return n.watch;case"tick":return n.tick;case"overlay":return n.node;case"key":return n.key;case"drive-failed":return n.drive;case"track":return n.track;default:return null}}const ia="__AS3__.vec",sa=new Set(["*","Array","Boolean","Class","Date","Function","int","Number","Object","RegExp","String","uint","XML","XMLList"]);function oa(n){return`${ia}::Vector.<${la(n)}>`}function la(n){const e=n.trim();if(!e)throw new TypeError("A vector needs the class of what it holds");if(e.includes("::")||sa.has(e))return e;const t=e.lastIndexOf(".");return t===-1?e:`${e.slice(0,t)}::${e.slice(t+1)}`}class _e{constructor(e,t=[]){this.className=e,this.args=t}className;args}class W{constructor(e,t,a){this.bridge=e,this.handle=t,this.className=a}bridge;handle;className;at(...e){return new se(this.bridge,{kind:"handle",handle:this.handle},e)}release(){return this.bridge.release([this])}}class se{constructor(e,t,a=[]){this.bridge=e,this.target=t,this.path=a}bridge;target;path;at(...e){return new se(this.bridge,this.target,[...this.path,...e])}get(){return this.bridge.request({op:"get",target:this.target,path:[...this.path]})}set(e){return this.bridge.request({op:"set",target:this.target,path:[...this.path],value:this.bridge.encode(e)}).then(()=>{})}call(...e){return this.bridge.request({op:"call",target:this.target,path:[...this.path],args:e.map(t=>this.bridge.encode(t))})}describe(){return this.bridge.request({op:"describe",target:this.target,path:[...this.path]})}listen(e,t,a={}){return this.bridge.listen(this,e,t,a)}get entry(){return{target:this.target,path:[...this.path]}}}const ca=new Set(["drive-failed","track","hook","override","hook-dropped","hook-failed","watch","tick","overlay","key"]);class ha{constructor(e,t={}){this.transport=e,this.timeoutMs=t.timeoutMs??5e3,this.firstId=t.firstId??1,this.nextId=this.firstId,this.batchOption=t.batch,this.stopReceiving=e.onMessage(a=>this.receive(a))}transport;stateValue="waiting";nextId;pending=new Map;listeners=new Map;callbacks=new Map;readyWaiters=[];clientListeners=new Set;uncaughtListeners=new Set;timeoutMs;stopReceiving;clientVersion=null;featureList=[];firstId;batchOption;queue=[];batches=new Map;subscriptions=new Map;ticks=new Map;get state(){return this.stateValue}get client(){return this.clientVersion}get features(){return this.featureList}allocate(){return this.nextId++}whenReady(){return this.stateValue==="ready"?Promise.resolve():this.stateValue==="closed"?Promise.reject(new z("CLOSED","The game is closed")):new Promise((e,t)=>this.readyWaiters.push({resolve:e,reject:t}))}definition(e){return new se(this,{kind:"definition",name:e})}gameClient(){return new se(this,{kind:"client"})}stage(){return new se(this,{kind:"stage"})}construct(e,...t){return this.request({op:"construct",className:e,args:t.map(a=>this.encode(a))})}async vector(e,t=[]){const a=await this.construct(oa(e));for(const r of t)await a.at("push").call(r);return a}onClient(e){return this.clientListeners.add(e),()=>this.clientListeners.delete(e)}onUncaught(e){return this.uncaughtListeners.add(e),()=>this.uncaughtListeners.delete(e)}async listen(e,t,a,r={}){if((r.read!==void 0||r.capture===!0)&&(await this.whenReady(),!this.featureList.includes("capturePaths")))throw new z("VERSION","This game is running a loader from before events could be read as they happen; listen without `read` and `capture`, or update Phantom");const i=this.nextId++;this.listeners.set(i,a);try{await this.request({op:"listen",target:e.target,path:[...e.path],event:t,listener:i,...r.read!==void 0?{read:r.read.map(s=>[...s])}:{},...r.capture===!0?{capture:!0}:{}})}catch(s){throw this.listeners.delete(i),s}return async()=>{!this.listeners.delete(i)||this.stateValue==="closed"||await this.request({op:"unlisten",listener:i})}}async subscribe(e,t,a){const r=this.nextId++;this.subscriptions.set(r,a);try{await this.request(e(r))}catch(i){throw this.subscriptions.delete(r),i}return async()=>{!this.subscriptions.delete(r)||this.stateValue==="closed"||await this.request(t(r))}}onSubscription(e,t){return this.subscriptions.set(e,t),()=>{this.subscriptions.get(e)===t&&this.subscriptions.delete(e)}}async hookTable(e){return await this.request(e===void 0?{op:"hookTable"}:{op:"hookTable",url:e})}async hook(e,t,a){let r=0;const i=await this.subscribe(s=>(r=s,{op:"hook",registration:s,hook:e,rules:t}),s=>({op:"unhook",registration:s}),a);return{registration:r,stop:i}}watch(e,t,a){return this.subscribe(r=>({op:"watch",watch:r,entries:e.map(i=>({target:i.target,path:[...i.path]})),everyFrames:Math.max(1,Math.floor(t.everyFrames??1)),handles:t.handles??!1}),r=>({op:"unwatch",watch:r}),r=>{r.kind==="watch"&&a(r.values.map(i=>this.decode(i)),r.errors??null)})}async tick(e,t){const a=Math.max(1,Math.floor(e));let r=this.ticks.get(a);if(!r){const o=new Set,h=this.subscribe(l=>({op:"tick",tick:l,everyFrames:a}),l=>({op:"untick",tick:l}),l=>{if(l.kind==="tick")for(const c of[...o])c(l.frame,l.time)});r={listeners:o,started:h},this.ticks.set(a,r),h.catch(()=>{this.ticks.get(a)===r&&this.ticks.delete(a)})}const i=r;i.listeners.add(t);try{await i.started}catch(o){throw i.listeners.delete(t),o}let s=!1;return async()=>{s||(s=!0,i.listeners.delete(t),!(i.listeners.size>0||this.ticks.get(a)!==i)&&(this.ticks.delete(a),await(await i.started)()))}}highlight(e,t){return this.subscribe(a=>({op:"highlight",highlight:a,target:e.target,path:[...e.path],effect:t}),a=>({op:"unhighlight",highlight:a}),()=>{})}style(e,t){return this.subscribe(a=>({op:"style",style:a,target:e.target,path:[...e.path],format:t}),a=>({op:"unstyle",style:a}),()=>{})}invokeOriginal(e,t,a){return this.request({op:"invokeOriginal",registration:e,token:t,arguments:a===null?null:a.map(r=>this.encode(r))})}async overrideDone(e,t){this.stateValue!=="closed"&&await this.request({op:"overrideDone",registration:e,token:t})}onKey(e,t){return this.subscribe(a=>({op:"key",key:a,spec:e}),a=>({op:"unkey",key:a}),a=>{a.kind==="key"&&t(a)})}async draw(e,t){await this.request({op:"draw",node:e,spec:t})}async erase(e){if(!(e.length===0||this.stateValue==="closed")){for(const t of e)this.subscriptions.delete(t);await this.request({op:"erase",nodes:[...e]})}}async measure(e){return await this.request({op:"measure",...e})}async bounds(e){return await this.request({op:"bounds",node:e})}drive(e,t){return this.subscribe(a=>({op:"drive",drive:a,spec:e}),a=>({op:"undrive",drive:a}),a=>{a.kind==="drive-failed"&&(t==null||t(a.error))})}async collect(e,t){const r=await this.request({op:"collect",target:e.target,path:[...e.path],spec:t});return{items:Array.isArray(r==null?void 0:r.items)?r.items:[],total:typeof(r==null?void 0:r.total)=="number"?r.total:0}}track(e,t,{mode:a="displayList",everyFrames:r=15}={},i){return this.subscribe(s=>({op:"track",track:s,target:e.target,path:[...e.path],className:t,mode:a,everyFrames:r}),s=>({op:"untrack",track:s}),s=>{s.kind==="track"&&i({added:s.added.map(o=>this.decode(o)),removed:s.removed.map(o=>this.decode(o))})})}async snapshot(e,{scale:t=1,background:a=null,maxSize:r=0}={}){const i=await this.request({op:"snapshot",target:e.target,path:[...e.path],scale:t,background:a,maxSize:r});if(typeof i!="string")throw new z("FLASH","The picture came back empty");return i}note(e,t,a,r){if(t==="keys"||t==="clear")return this.request({op:"note",table:e,verb:t});if(!a)throw new TypeError(`A note to ${t} is kept beside an object; name the place`);const i={target:a.target,path:[...a.path]};return t==="write"?this.request({op:"note",table:e,verb:t,...i,value:this.encode(r)}):this.request({op:"note",table:e,verb:t,...i})}async find(e,t){const a=await this.request({op:"find",target:e.target,path:[...e.path],spec:t});return(Array.isArray(a)?a:[]).filter(r=>r instanceof W)}async answer(e,t){this.stateValue!=="closed"&&await this.request({op:"answer",callback:e,...t===void 0?{}:{value:this.encode(t)}})}async release(e){e.length===0||this.stateValue==="closed"||await this.request({op:"release",handles:e.map(t=>t.handle)})}close(){if(this.stateValue==="closed")return;if(this.stateValue==="ready"&&this.featureList.includes("dispose")){const t=this.nextId++;try{this.transport.send(ce({id:t,op:"dispose",from:this.firstId,to:this.nextId}))}catch{}}this.stateValue="closed",this.stopReceiving();const e=new z("CLOSED","The game was closed");for(const t of this.pending.values())clearTimeout(t.timer),t.reject(e);this.pending.clear();for(const t of this.batches.values())clearTimeout(t.timer);this.batches.clear(),this.queue=[],this.listeners.clear(),this.callbacks.clear(),this.subscriptions.clear(),this.ticks.clear(),this.readyWaiters.splice(0).forEach(t=>t.reject(e))}readyWithin(e){return new Promise((t,a)=>{const r=setTimeout(()=>a(new z("NOT_READY","The game has not started yet")),e);this.whenReady().then(()=>{clearTimeout(r),t()},i=>{clearTimeout(r),a(i)})})}encodeRequest(e){return ce({...e,id:this.nextId++})}request(e){if(this.stateValue==="closed")return Promise.reject(new z("CLOSED","The game is closed"));if(this.stateValue!=="ready")return this.readyWithin(this.timeoutMs).then(()=>this.request(e));const t=this.nextId++;return new Promise((a,r)=>{const i=setTimeout(()=>{this.pending.delete(t),r(new z("TIMEOUT",`The game did not answer "${e.op}" in ${this.timeoutMs}ms`))},this.timeoutMs);this.pending.set(t,{resolve:a,reject:r,timer:i});const s={...e,id:t};if(!this.batching||s.op==="hookTable"||s.op==="batch"){this.transport.send(ce(s));return}this.queue.push(s),this.queue.length===1&&queueMicrotask(()=>this.flush())})}get batching(){return this.batchOption??this.featureList.includes("batch")}flush(){const e=this.queue;if(this.queue=[],e.length===0||this.stateValue!=="ready")return;if(e.length===1){this.transport.send(ce(e[0]));return}const t=this.nextId++,a=e.map(i=>i.id),r=setTimeout(()=>this.batches.delete(t),this.timeoutMs+1e3);this.batches.set(t,{ids:a,timer:r}),this.transport.send(ce({id:t,op:"batch",requests:e}))}settle(e,t){const a=this.pending.get(e);a&&(this.pending.delete(e),clearTimeout(a.timer),t.ok?a.resolve(this.decode(t.value)):a.reject(new z("FLASH",t.error.message,t.error)))}encode(e){if(e===void 0)return{$undefined:!0};if(e===null||typeof e!="object"){if(typeof e=="function"){const t=this.nextId++;return this.callbacks.set(t,e),{$callback:t}}return e}return e instanceof W?{$handle:e.handle}:e instanceof _e?{$new:e.className,args:e.args.map(t=>this.encode(t))}:Array.isArray(e)?e.map(t=>this.encode(t)):Object.fromEntries(Object.entries(e).map(([t,a])=>[t,this.encode(a)]))}decode(e){if(e===null||typeof e!="object")return e;if(Array.isArray(e))return e.map(t=>this.decode(t));if(aa(e))return new W(this,e.$handle,e.className);if(!("$undefined"in e))return Object.fromEntries(Object.entries(e).map(([t,a])=>[t,this.decode(a)]))}receive(e){var t,a,r;if(this.stateValue==="closed")return;let i;try{i=fn(e)}catch{return}switch(i.kind){case"ready":if(i.version!==Et){const s=new z("VERSION",`The loader speaks bridge ${i.version}; this Phantom speaks ${Et}`);this.readyWaiters.splice(0).forEach(o=>o.reject(s)),this.close();return}this.stateValue="ready",this.clientVersion=i.client,this.featureList=Array.isArray(i.features)?[...i.features]:[],this.readyWaiters.splice(0).forEach(s=>s.resolve());return;case"client-loaded":this.clientListeners.forEach(s=>s(!0,null));return;case"client-failed":this.clientListeners.forEach(s=>s(!1,i.message));return;case"result":{const s=this.batches.get(i.id);if(s){this.batches.delete(i.id),clearTimeout(s.timer);const o=i.ok&&Array.isArray(i.value)?i.value:null;s.ids.forEach((h,l)=>{i.ok?o&&l<o.length&&this.settle(h,o[l]):this.settle(h,i)});return}this.settle(i.id,i.ok?{ok:!0,value:i.value}:i);return}case"event":(t=this.listeners.get(i.listener))==null||t(this.decode(i.event));return;case"callback":(a=this.callbacks.get(i.callback))==null||a(...i.args.map(s=>this.decode(s)));return;case"uncaught":{const s=new z("FLASH",i.error.message,i.error);this.uncaughtListeners.forEach(o=>o(s));return}default:if(ca.has(i.kind)){const s=ra(i);s!==null&&((r=this.subscriptions.get(s))==null||r(i))}}}}const ua=[1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0],wn={r:.3086,g:.6094,b:.082};function xe(n,e){const t=new Array(20).fill(0);for(let a=0;a<4;a++)for(let r=0;r<5;r++){let i=r===4?e[a*5+4]:0;for(let s=0;s<4;s++)i+=e[a*5+s]*n[s*5+r];t[a*5+r]=i}return t}function gn(n){const e=n,{r:t,g:a,b:r}=wn;return[t*(1-e)+e,a*(1-e),r*(1-e),0,0,t*(1-e),a*(1-e)+e,r*(1-e),0,0,t*(1-e),a*(1-e),r*(1-e)+e,0,0,0,0,0,1,0]}function da(n){const e=n*255;return[1,0,0,0,e,0,1,0,0,e,0,0,1,0,e,0,0,0,1,0]}function fa(n){const e=n+1,t=128*(1-e);return[e,0,0,0,t,0,e,0,0,t,0,0,e,0,t,0,0,0,1,0]}function wa(n){const e=n*Math.PI/180,t=Math.cos(e),a=Math.sin(e),{r,g:i,b:s}=wn;return[r+t*(1-r)+a*-r,i+t*-i+a*-i,s+t*-s+a*(1-s),0,0,r+t*-r+a*.143,i+t*(1-i)+a*.14,s+t*-s+a*-.283,0,0,r+t*-r+a*-.6914,i+t*-i+a*i,s+t*(1-s)+a*s,0,0,0,0,0,1,0]}const ga={grayscale:gn(0),sepia:[.393,.769,.189,0,0,.349,.686,.168,0,0,.272,.534,.131,0,0,0,0,0,1,0],invert:[-1,0,0,0,255,0,-1,0,0,255,0,0,-1,0,255,0,0,0,1,0],night:[.45,0,0,0,0,0,.5,0,0,0,0,0,.8,0,20,0,0,0,1,0]};function mn(n){if(typeof n=="string"){const t=ga[n];if(!t)throw new TypeError(`Unknown colour look "${String(n)}"`);return{matrix:[...t],colorTransform:null}}if("matrix"in n){if(n.matrix.length!==20)throw new TypeError("A colour matrix has twenty numbers");return{matrix:[...n.matrix],colorTransform:null}}if("tint"in n){const t=Math.max(0,Math.min(1,n.amount??.5)),a=r=>(n.tint>>r&255)*t;return{matrix:null,colorTransform:Tt({redMultiplier:1-t,greenMultiplier:1-t,blueMultiplier:1-t,redOffset:a(16),greenOffset:a(8),blueOffset:a(0)})}}if("transform"in n)return{matrix:null,colorTransform:Tt(n.transform)};let e=[...ua];return n.saturation!==void 0&&(e=xe(e,gn(n.saturation))),n.hue!==void 0&&(e=xe(e,wa(n.hue))),n.contrast!==void 0&&(e=xe(e,fa(n.contrast))),n.brightness!==void 0&&(e=xe(e,da(n.brightness))),{matrix:e,colorTransform:null}}function Tt(n){return{redMultiplier:n.redMultiplier??1,greenMultiplier:n.greenMultiplier??1,blueMultiplier:n.blueMultiplier??1,alphaMultiplier:n.alphaMultiplier??1,redOffset:n.redOffset??0,greenOffset:n.greenOffset??0,blueOffset:n.blueOffset??0,alphaOffset:n.alphaOffset??0}}function ye(n={}){const e=n.recolor?mn(n.recolor):{matrix:null,colorTransform:null},a=n.glow??!(n.recolor||n.hide)?{color:n.color??9133302,alpha:n.alpha??1,blur:n.blur??8,strength:n.strength??2,inner:n.inner??!1,knockout:n.knockout??!1}:null;if(a&&e.matrix)throw new TypeError("A highlight is a glow or a colour matrix, not both: use two highlights");const r=n.pulse===void 0||n.pulse===!1?null:n.pulse===!0?{frames:60,from:.6,to:1}:{frames:n.pulse.frames??60,from:n.pulse.from??.6,to:n.pulse.to??1};return{glow:a,matrix:e.matrix,colorTransform:e.colorTransform,hide:n.hide??!1,pulse:r}}function B(n){const e=`${n.className}.${n.member}`;return n.kind==="getter"?`${e}@get`:n.kind==="setter"?`${e}@set`:e}const Fe=Symbol.for("phantom.hookRead"),oe=Symbol.for("phantom.hookTest"),$e=200,ma=20;class pa{constructor(e){this.table=e;for(const t of e.hooks){this.byId.set(t.id,t);const a=B(t);this.byKey.has(a)||this.byKey.set(a,t);const r=this.byClass.get(t.className);r?r.push(t):this.byClass.set(t.className,[t])}}table;byKey=new Map;byId=new Map;byClass=new Map;get size(){return this.byId.size}names(){return[...this.byKey.keys()]}entries(){return[...this.byId.values()]}classNames(){return[...this.byClass.keys()]}inClass(e){return[...this.byClass.get(e)??[]]}find(e){return e.startsWith("#")?this.byId.get(Number(e.slice(1)))??null:this.byKey.get(e)??this.byKey.get(`${e}@get`)??this.byKey.get(`${e}@set`)??null}}function J(n){return n.flatMap(e=>Array.isArray(e)?e:e.includes("::")?[e]:e.split(".").filter(Boolean))}function re(n){return Object.freeze({[Fe]:n})}function G(n,e,t){return Object.freeze({[oe]:t===void 0&&n==="exists"?{test:n,left:e}:{test:n,left:e,right:t}})}const ya={self:(...n)=>re({from:"self",path:J(n)}),arg:(n,...e)=>re({from:"arg",arg:n,path:J(e)}),returned:(...n)=>re({from:"return",path:J(n)}),fromClass:(n,...e)=>re({from:"class",name:n,path:J(e)}),place:(n,...e)=>re({from:"place",place:n,path:J(e)}),calls:()=>re({from:"calls"}),constant:n=>re({from:"constant",value:n}),equals:(n,e)=>G("equals",n,e),notEquals:(n,e)=>G("notEquals",n,e),less:(n,e)=>G("less",n,e),lessOrEqual:(n,e)=>G("lessOrEqual",n,e),greater:(n,e)=>G("greater",n,e),greaterOrEqual:(n,e)=>G("greaterOrEqual",n,e),contains:(n,e)=>G("contains",n,e),startsWith:(n,e)=>G("startsWith",n,e),endsWith:(n,e)=>G("endsWith",n,e),oneOf:(n,e)=>G("in",n,e),exists:n=>G("exists",n),all:(...n)=>Object.freeze({[oe]:{all:n}}),any:(...n)=>Object.freeze({[oe]:{any:n}}),not:n=>Object.freeze({[oe]:{not:n}})};function pn(n){return typeof n=="object"&&n!==null&&Fe in n}function yn(n){return typeof n=="object"&&n!==null&&oe in n}function rt(n,e,t,a){const r=u=>{if(typeof u=="number")return Ot(e,u);const d=e.parameters.findIndex(g=>g.name===u);if(d>=0)return d;if(/^\d+$/.test(u))return Ot(e,Number(u));const w=e.parameters.map(g=>g.name).join(", ")||"none";throw new TypeError(`${B(e)} has no argument "${u}" (its arguments: ${w})`)},i=u=>{if(!pn(u))return Ne(u)??{from:"constant",value:de(n,u)};const d=u[Fe];switch(d.from){case"constant":return{from:"constant",value:de(n,d.value)};case"arg":return{from:"arg",index:r(d.arg),path:d.path};case"self":return{from:"self",path:d.path};case"return":return{from:"return",path:d.path};case"class":return{from:"class",name:d.name,path:d.path};case"calls":return{from:"calls"};case"place":{const w=Ne(d.place,d.path);if(!w)throw new TypeError("rules.place takes a place in the game");return w}}},s=u=>{if(!yn(u)){const w=Object.entries(u).map(([g,f])=>({test:"equals",left:{from:"arg",index:r(g),path:[]},right:i(f)}));if(w.length===0)throw new TypeError("A hook condition names nothing to compare");return w.length===1?w[0]:{all:w}}const d=u[oe];return"all"in d?{all:d.all.map(s)}:"any"in d?{any:d.any.map(s)}:"not"in d?{not:s(d.not)}:d.test==="exists"?{test:d.test,left:i(d.left)}:{test:d.test,left:i(d.left),right:i(d.right)}},o=t.phase??(a?"enter":"none"),h=t.capture??{},l=bn(e,h.args,a,r);if(l.some(({path:u})=>u.length>0)&&!n.features.includes("capturePaths"))throw new Error(`The hook on ${B(e)} reads along from an argument, which this game's loader is from before; capture the argument itself, or update Phantom`);const c=l.map(({index:u,path:d})=>d.length===0?u:{index:u,path:d});return{observe:o==="both"?["enter","exit"]:o==="none"?[]:[o],capture:{args:c,self:it(h.self).map(([,u])=>u),value:h.value??!1,handles:h.handles??!1},when:t.when===void 0?null:s(t.when),first:t.first??null,every:t.every??null,skip:t.skip===void 0||t.skip===!1?null:t.skip===!0?{from:"constant",value:{$undefined:!0}}:i(t.skip.returns),replaceArgs:Object.entries(t.replaceArgs??{}).map(([u,d])=>({index:r(u),value:i(d)})),replaceReturn:"replaceReturn"in t?i(t.replaceReturn):null,perFrame:t.perFrame??ma}}function Ot(n,e){if(!Number.isInteger(e)||e<0||n.parameters.length>0&&e>=n.parameters.length)throw new RangeError(`${B(n)} has no argument ${e}`);return e}function bn(n,e,t,a){const r=i=>{var s;return{name:((s=n.parameters[i])==null?void 0:s.name)??String(i),index:i,path:[]}};return e===!0||e===void 0&&t?n.parameters.map((i,s)=>r(s)):e===void 0?[]:Array.isArray(e)?e.map(i=>r(a(i))):Object.entries(e).map(([i,s])=>{const o=Array.isArray(s)?s.flatMap(c=>typeof c=="number"?[String(c)]:J([c])):J([s]),[h,...l]=o;if(h===void 0)throw new TypeError(`${B(n)}: "${i}" names no argument to read from`);return{name:i,index:a(h),path:l}})}function it(n){return n?Array.isArray(n)?n.map(e=>[e,J([e])]):Object.entries(n).map(([e,t])=>[e,J([t])]):[]}function vn(n,e){const t=a=>{if(!yn(a))throw new TypeError("A condition between calls has no call to read: compare with rules.equals and its like");const r=a[oe];return"all"in r?{all:r.all.map(t)}:"any"in r?{any:r.any.map(t)}:"not"in r?{not:t(r.not)}:r.test==="exists"?{test:r.test,left:me(n,r.left)}:{test:r.test,left:me(n,r.left),right:me(n,r.right)}};return t(e)}function Ne(n,e=[]){const t=ae(n);return t?{from:"place",target:t.target,path:[...t.path,...e]}:null}function me(n,e){if(!pn(e))return Ne(e)??{from:"constant",value:de(n,e)};const t=e[Fe];switch(t.from){case"constant":return{from:"constant",value:de(n,t.value)};case"class":return{from:"class",name:t.name,path:t.path};case"place":{const a=Ne(t.place,t.path);if(!a)throw new TypeError("rules.place takes a place in the game");return a}default:throw new TypeError(`rules.${t.from} reads the call it is in; a value held between calls is a constant, rules.fromClass or a place`)}}function de(n,e){if(e===void 0)return{$undefined:!0};if(e instanceof W||e instanceof _e)return n.encode(e);const t=ae(e);if(t){if(t.target.kind==="handle"&&t.path.length===0)return{$handle:t.target.handle};throw new TypeError("A place inside a list or object in a rule cannot be read there: pass the place on its own, or read it first")}if(typeof e=="function")throw new TypeError("A hook rule cannot call a function");return Array.isArray(e)?e.map(a=>de(n,a)):e!==null&&typeof e=="object"?Object.fromEntries(Object.entries(e).map(([a,r])=>[a,de(n,r)])):e}function At(n,e,t){var a;const r=i=>{if(typeof i=="number")return i;const s=n.parameters.findIndex(o=>o.name===i);return s>=0?s:Number(i)};return bn(n,(a=e.capture)==null?void 0:a.args,t,r).map(({name:i})=>i)}async function ba(n,e,t,a,r){var i;if(typeof a=="function")throw new TypeError(`phantom.flash.hook("${t}", ...) was given a function where its options go. A hook takes its options second and its listener third: hook(name, options, listener). An override is the other way about: override(name, handler, options).`);const s=e.find(t);if(!s)throw new TypeError(`There is no hook "${t}" in the hook table`);let o=a,h=it((i=a.capture)==null?void 0:i.self).map(([f])=>f),l=rt(n,s,a,r!==void 0),c=At(s,a,r!==void 0),u=!1;const{registration:d,stop:w}=await n.hook(s.id,l,f=>{switch(f.kind){case"hook":{if(!r)return;const m=(f.args??[]).map(b=>_(n,n.decode(b))),p={};c.forEach((b,k)=>{p[b]=m[k]});const y={};(f.self??[]).forEach((b,k)=>{y[h[k]??String(k)]=_(n,n.decode(b))}),r({phase:f.phase,call:f.call,args:p,argList:m,self:y,..."value"in f?{value:_(n,n.decode(f.value))}:{},skipped:f.skipped===!0,hook:s});return}case"hook-dropped":o.onDropped?o.onDropped(f.dropped):u||(u=!0,console.warn(`The hook on ${B(s)} went untold of ${f.dropped} calls in one frame: it hears at most ${l.perFrame} a frame. Raise perFrame (${$e} is the most the game allows), narrow the hook with when/first/every, or pass onDropped to count them yourself. Said once per hook.`));return;case"hook-failed":{const m=new z("FLASH",`The hook on ${B(s)} failed and is off: ${f.error.message}`,f.error);o.onError?o.onError(m):console.error(m.message);return}}});return Object.assign(()=>w(),{registration:d,hook:s,update:async(f,m={})=>{var p;const y=rt(n,s,f,r!==void 0);await n.request({op:"rehook",registration:d,rules:y,resetCounts:m.resetCounts??!1}),o=f,l=y,h=it((p=f.capture)==null?void 0:p.self).map(([b])=>b),c=At(s,f,r!==void 0)},stats:async()=>(await n.request({op:"hookStats"})).find(m=>m.registration===d)??null})}function A(n){const e=ae(n);if(!e)throw new TypeError("Expected a place in Flash: a typed place, an object read from Flash, or a reference");return{target:e.target,path:[...e.path]}}function ue(n){return ae(n)!==null}async function va(n,e,t){if(await n.whenReady(),!n.features.includes("drive"))throw new Error("This game is running a loader from before repeated calls; call it yourself each frame");const a=A(e);if(a.path.length===0)throw new TypeError("A repeat calls a method, so name one: `place.method`, not the object");const r=t.while?vn(n,t.while):null;return n.drive({writes:[],calls:[{target:a.target,path:a.path,args:(t.args??[]).map(i=>me(n,i)),times:Math.max(1,Math.trunc(t.times??1))}],everyFrames:Math.max(1,Math.trunc(t.everyFrames??1)),while:r,restore:!1,once:t.once===!0},t.onFailed)}async function st(n,e,t){if(await n.whenReady(),!n.features.includes("drive"))throw new Error("This game is running a loader from before held values; write it yourself each frame");if(e.length===0)throw new TypeError("A hold needs a value to keep");const a=e.map(({place:i,value:s})=>{const o=A(i);if(o.path.length===0)throw new TypeError("A hold writes to a member, so name one: `place.member`, not the object");return{target:o.target,path:o.path,value:me(n,s)}}),r=t.while?vn(n,t.while):null;return n.drive({writes:a,everyFrames:Math.max(1,Math.trunc(t.everyFrames??1)),while:r,restore:t.restore!==!1,once:t.once===!0},t.onFailed)}const Le=Symbol.for("phantom.typedFlash");function kn(n){return typeof n=="function"&&n[Le]!==void 0}function N(n,e,t={}){const a={reference:e,handle:t.handle??null,className:t.className??null},r=o=>_(n,o),i={$get:()=>e.get().then(r),$set:async o=>e.set((await te(n,[o]))[0]),$keep:(o,h={})=>st(n,[{place:e,value:o}],h),$call:async(...o)=>r(await e.call(...await te(n,o))),$listen:(o,h)=>e.listen(o,l=>h(r(l))),$describe:()=>e.describe(),$at:(...o)=>N(n,e.at(...o)),$as:()=>N(n,e,{...a.handle?{handle:a.handle}:{}}),$release:()=>a.handle?a.handle.release():Promise.resolve(),$reference:e,$new:async(...o)=>{if(!a.className)throw new TypeError("Only a class can make objects with $new");return r(await n.construct(a.className,...await te(n,o)))},toJSON:()=>`[Flash ${ka(a)}]`},s=(()=>{});return new Proxy(s,{get:(o,h)=>{if(h===Le)return a;if(typeof h!="symbol"&&h!=="then")return Object.prototype.hasOwnProperty.call(i,h)?i[h]:N(n,e.at(h))},apply:async(o,h,l)=>r(await e.call(...await te(n,l)))})}function ae(n){return kn(n)?n[Le].reference:n instanceof W?n.at():n&&typeof n=="object"&&"target"in n&&"path"in n&&typeof n.at=="function"?n:null}function _(n,e){if(e instanceof W)return N(n,e.at(),{handle:e});if(Array.isArray(e))return e.map(t=>_(n,t));if(e&&typeof e=="object"){const t={};for(const[a,r]of Object.entries(e))t[a]=_(n,r);return t}return e}async function te(n,e){return Promise.all(e.map(t=>ot(n,t)))}async function ot(n,e){if(kn(e)){const t=e[Le];return t.handle&&t.reference.path.length===0?t.handle:t.reference.get()}if(typeof e=="function"){const t=e;return(...a)=>t(...a.map(r=>_(n,r)))}if(Array.isArray(e))return Promise.all(e.map(t=>ot(n,t)));if(e&&typeof e=="object"&&Object.getPrototypeOf(e)===Object.prototype){const t={};for(const[a,r]of Object.entries(e))t[a]=await ot(n,r);return t}return e}function ka({reference:n,className:e}){const t=n.target,a=t.kind==="definition"?t.name:t.kind==="handle"?`object ${t.handle}`:t.kind,r=n.path.join(".");return e??(r?`${a}.${r}`:a)}class xa{constructor(e,t,a){this.bridge=e;const r=e.encode(t);this.callback=r.$callback,a!==void 0&&this.answers(a)}bridge;callback;stopped=!1;get argument(){return{$callback:this.callback}}async answers(e){if(this.stopped)return;await this.ready();const[t]=await te(this.bridge,[e]);await this.bridge.answer(this.callback,t)}async answersNothing(){this.stopped||(await this.ready(),await this.bridge.answer(this.callback))}async stop(){this.stopped||(this.stopped=!0,await this.bridge.answer(this.callback))}async ready(){if(await this.bridge.whenReady(),!this.bridge.features.includes("answer"))throw new Error("This game is running a loader from before answers; a function of yours gives the game nothing back")}}async function Ma(n,e,t,a){if(await n.whenReady(),!n.features.includes("collect"))throw new Error("This game is running a loader from before collects; read the items one by one");const r={fields:Sa(t)};a.skip!==void 0&&(r.skip=Math.max(0,Math.trunc(a.skip))),a.limit!==void 0&&(r.limit=Math.max(1,Math.trunc(a.limit))),a.handles!==void 0&&(r.handles=a.handles);const i=await n.collect(A(e),r);return{rows:i.items.map(s=>_(n,s)),total:i.total}}function Sa(n){const e=Array.isArray(n)?n.map(t=>[t,t]):Object.entries(n);if(e.length===0)throw new TypeError("A collect needs the members to read");return e.map(([t,a])=>({name:t,path:(Array.isArray(a)?a:String(a).split(".")).filter(r=>r.length>0)}))}const Ea=50;async function Ta(n,e,t,a={}){const r=typeof t=="string"?t:null;if(r!==null&&r.trim()==="")throw new TypeError("Name a class to describe, or give a place in the game");let i=null,s=null;if(a.live??!0)try{const l=r===null?$a(t):n.definition(r);i=Pa(await l.describe())}catch(l){s=l instanceof Error?l.message:String(l)}const o=r??(i==null?void 0:i.name)??"",h=new Map;for(const l of o?e.inClass(o):[])Ra(h,l);return i&&Ca(h,i),{className:o,liveClassName:(i==null?void 0:i.name)??null,base:i&&i.base&&i.base!=="Class"?i.base:null,members:[...h.values()].sort(Fa),liveError:s}}function Oa(n,e,t={}){var a;const r=e.trim().toLowerCase();if(!r)return[];const i=r.lastIndexOf("."),s=i>0?r.slice(0,i):"",o=i>0?r.slice(i+1):r,h=((a=t.inClass)==null?void 0:a.trim().toLowerCase())??"",l=Math.max(0,t.limit??Ea),c=[];for(const u of n.entries()){if(t.isStatic!==void 0&&u.isStatic!==t.isStatic||t.kind!==void 0&&u.kind!==t.kind)continue;const d=u.className.toLowerCase();if(h&&!d.includes(h)||s&&!d.includes(s))continue;const w=Aa(d,u.member.toLowerCase(),o,s!=="");w!==null&&c.push({score:w,entry:u})}return c.sort((u,d)=>u.score-d.score||u.entry.className.localeCompare(d.entry.className)||u.entry.member.localeCompare(d.entry.member)||u.entry.kind.localeCompare(d.entry.kind)),c.slice(0,l).map(({entry:u})=>({hook:B(u),className:u.className,member:u.member,kind:u.kind,isStatic:u.isStatic,parameters:u.parameters.map(d=>({...d})),returns:u.returns,namespace:u.namespace}))}function Aa(n,e,t,a){return t===""?3:e===t?0:e.startsWith(t)?1:e.includes(t)?2:a?null:n.includes(t)?4:null}function $a(n){return A(n),ae(n)}function Pa(n){const e=n??{};return{name:typeof e.name=="string"?e.name.replace(/::/g,"."):"",base:typeof e.base=="string"?e.base.replace(/::/g,"."):"",methods:Array.isArray(e.methods)?e.methods:[],properties:Array.isArray(e.properties)?e.properties:[]}}function lt(n,e){return`${e?"static":"instance"} ${n}`}function Ra(n,e){var t;const a=e.member==="<constructor>",r=lt(e.member,e.isStatic),s=n.get(r)??{name:e.member,kind:a?"constructor":e.kind==="method"?"method":"property",isStatic:e.isStatic,access:null,type:"",parameters:[],hooks:[],namespace:e.namespace,from:"hooks"};s.hooks.push(B(e)),e.kind==="method"?(s.parameters=e.parameters.map(o=>({...o})),s.type||(s.type=e.returns)):(e.kind==="getter"&&!s.type&&(s.type=e.returns),e.kind==="setter"&&!s.type&&(s.type=((t=e.parameters[0])==null?void 0:t.type)??""),s.access=_a(s.access,e.kind==="getter"?"read":"write")),n.set(r,s)}function Ca(n,e){for(const t of e.methods){const a=lt(t.name,!1),r=n.get(a);if(r){r.from="both",r.type||(r.type=t.returns);continue}n.set(a,{name:t.name,kind:"method",isStatic:!1,access:null,type:t.returns,parameters:t.parameters.map((i,s)=>({name:String(s),type:i.type,optional:i.optional})),hooks:[],namespace:t.namespace,from:"live"})}for(const t of e.properties){const a=lt(t.name,!1),r=n.get(a),i=Na(t.access);if(r){r.from="both",r.type||(r.type=t.type),i&&(r.access=i);continue}n.set(a,{name:t.name,kind:"property",isStatic:!1,access:i,type:t.type,parameters:[],hooks:[],namespace:t.namespace,from:"live"})}}function Na(n){return n==="readonly"?"read":n==="writeonly"?"write":n==="readwrite"?"readwrite":null}function _a(n,e){return n===null||n===e?e:"readwrite"}function Fa(n,e){const t=a=>a.kind==="constructor"?0:a.isStatic?2:1;return t(n)-t(e)||n.name.localeCompare(e.name)}class He{constructor(e,t,a,r,i,s,o){this.host=e,this.kind=t,this.id=a,this.name=r,this.tagY=s,this.handle=o,this.place=i}host;kind;id;name;tagY;handle;place;highlight(e={}){return this.host.bridge.highlight(this.entry(),ye(e))}tag(e,t={}){const{anchorX:a,anchorY:r,...i}=t;return this.host.overlay.text(e,{centered:!0,font:{size:12,bold:!0,color:16777215},outline:0,...i,anchor:{place:this.place,x:a??0,y:r??this.tagY}})}onClick(e){const t=this.host.bridge;return this.kind!=="object"?this.place.$listen("mouseDown",()=>e(this)):t.stage().listen("mouseDown",a=>{const{stageX:r,stageY:i}=a??{};typeof r!="number"||typeof i!="number"||this.place.$reference.at("hitTestPoint").call(r,i,!0).then(s=>{s===!0&&e(this)}).catch(()=>{})})}async release(){this.handle&&await this.handle.release()}entry(){const e=this.place.$reference;return{target:e.target,path:[...e.path]}}}class La{constructor(e){this.host=e}host;async players(){const e=this.host.bridge,t=e.definition("avatar.AvatarManager").at("avatarViewList"),a=await t.get(),r=a&&typeof a=="object"&&!(a instanceof W)?Object.keys(a):[],i=r.map(s=>a[s]).filter(s=>s instanceof W);try{const s=await Promise.all(r.map(o=>Q(t.at(o,"userName").get())));return r.map((o,h)=>new He(this.host,"player",o,typeof s[h]=="string"?s[h]:null,N(e,t.at(o)),-80,null))}finally{await e.release(i)}}async npcs(){const e=this.host.bridge,t=e.definition("quest.QuestManager").at("_questActors"),a=await Q(t.at("length").get());if(typeof a!="number"||a<=0)return[];const r=Array.from({length:Math.min(a,500)},(l,c)=>String(c)),[i,s,o]=await Promise.all([Promise.all(r.map(l=>Q(t.at(l).get()))),Promise.all(r.map(l=>Q(t.at(l,"_actorId").get()))),Promise.all(r.map(l=>Q(t.at(l,"currAvatar","avName").get())))]),h=[];return r.forEach((l,c)=>{const u=i[c];if(!(u instanceof W))return;const d=o[c];h.push(new He(this.host,"npc",typeof s[c]=="string"?s[c]:l,typeof d=="string"&&d?d:null,N(e,u.at(),{handle:u}),-90,u))}),h}async objects(){const e=this.host.bridge,t=e.definition("room.RoomManagerWorld").at("instance","volumeManager","_volumeActors");let a;try{a=await t.at("length").get()}catch(c){throw c instanceof z&&c.code==="FLASH"?new z("FLASH",`The room's objects are private to the client, and this client does not reach them: ${c.message}`,c.flash):c}if(typeof a!="number"||a<=0)return[];const r=Array.from({length:Math.min(a,500)},(c,u)=>String(u)),[i,s]=await Promise.all([Promise.all(r.map(c=>Q(t.at(c,"name").get()))),Promise.all(r.map(c=>Q(t.at(c,"interactiveObjs","length").get())))]),o=[];r.forEach((c,u)=>{const d=s[u],w=i[u];for(let g=0;typeof d=="number"&&g<Math.min(d,50);g++)o.push([c,String(g),typeof w=="string"?w:null])});const h=await Promise.all(o.map(([c,u])=>Q(t.at(c,"interactiveObjs",u,"mc").get()))),l=[];return o.forEach(([c,u,d],w)=>{const g=h[w];g instanceof W&&l.push(new He(this.host,"object",`${d??c}#${u}`,d,N(e,g.at(),{handle:g}),0,g))}),l}}function Q(n){return n.catch(()=>null)}async function Ia(n,e,t){if(await n.whenReady(),!n.features.includes("find"))throw new Error("This game is running a loader from before searches; only a path reaches an object");const a=e===void 0?{target:{kind:"stage"},path:[]}:A(e);return(await n.find(a,ja(t))).map(i=>N(n,i.at(),{handle:i}))}function ja(n){const e={};return n.ofClass!==void 0&&(e.ofClass=n.ofClass),n.named!==void 0&&(e.named=n.named),n.containing!==void 0&&(e.containing=n.containing),n.visibleOnly!==void 0&&(e.visibleOnly=n.visibleOnly),n.through!==void 0&&(e.through=n.through),n.depth!==void 0&&(e.depth=n.depth),n.limit!==void 0&&(e.limit=n.limit),e}const $t={backspace:8,tab:9,enter:13,return:13,shift:16,control:17,ctrl:17,alt:18,pause:19,capslock:20,escape:27,esc:27,space:32,pageup:33,pagedown:34,end:35,home:36,left:37,arrowleft:37,up:38,arrowup:38,right:39,arrowright:39,down:40,arrowdown:40,insert:45,delete:46,";":186,"=":187,",":188,"-":189,".":190,"/":191,"`":192,"[":219,"\\":220,"]":221,"'":222};function Da(n){return n===!0?"always":n===!1?"never":n??"empty"}function za(n,e={}){const t={phase:e.phase??"down",consume:e.consume??!1,whileTyping:Da(e.whileTyping),repeat:e.repeat??!1};if(typeof n=="number")return{code:n,ctrl:null,shift:null,alt:null,...t};const a=n==="+"||n.endsWith("++"),r=(a?n.slice(0,-1):n).split("+").map(o=>o.trim()).filter(Boolean);a&&r.push("+");const i={ctrl:!1,shift:!1,alt:!1};let s=null;for(const o of r){const h=o.toLowerCase();h==="ctrl"||h==="control"||h==="cmd"||h==="meta"?i.ctrl=!0:h==="shift"?i.shift=!0:h==="alt"||h==="option"?i.alt=!0:h==="any"?s=null:s=Ha(o)}if(s===null&&!r.some(o=>o.toLowerCase()==="any"))throw new TypeError(`"${n}" names no key`);return{code:s,...i,...t}}function Ha(n){const e=n.toLowerCase();if(e in $t)return $t[e];if(/^[a-z0-9]$/i.test(n))return n.toUpperCase().charCodeAt(0);const t=/^f([1-9]|1[0-5])$/i.exec(n);if(t)return 111+Number(t[1]);const a=/^num(?:pad)?([0-9])$/i.exec(n);if(a)return 96+Number(a[1]);if(n==="+")return 187;throw new TypeError(`Unknown key "${n}"`)}const Wa=new Set(["then","toJSON","toString","constructor","nodeType","tagName","inspect"]),Ba=["overlay","entities","view","bridge"];function xn(n){const e=new Set;if(n===null||typeof n!="object"&&typeof n!="function")return e;for(let t=n;t&&!(t===Object.prototype||t===Function.prototype);t=Object.getPrototypeOf(t))for(const a of Object.getOwnPropertyNames(t))a!=="constructor"&&e.add(a);return e}function qa(n,e,t){if(Math.abs(n.length-e.length)>t)return t+1;let a=Array.from({length:e.length+1},(r,i)=>i);for(let r=1;r<=n.length;r++){const i=[r];for(let s=1;s<=e.length;s++)i[s]=Math.min(a[s]+1,i[s-1]+1,a[s-1]+(n[r-1]===e[s-1]?0:1));a=i}return a[e.length]}function Ua(n,e){const t=n.length<=4?1:2;let a=null,r=t+1;for(const i of e){if(i.startsWith("_"))continue;const s=qa(n.toLowerCase(),i.toLowerCase(),t);s<r&&(r=s,a=i)}return r<=t?a:null}function Va(n,e,t){for(const r of Ba){const i=n[r];if(!xn(i).has(e))continue;return r!=="bridge"?`phantom.flash has no "${e}". phantom.flash.${r} has it: write phantom.flash.${r}.${e}.`:`phantom.flash has no "${e}". The bridge underneath has it: write phantom.flash.bridge.${e}.${e==="definition"?' For a class with its types, phantom.flash.use("avatar.AvatarManager") is the same object typed.':""}`}const a=Ua(e,t);return a?`phantom.flash has no "${e}". Did you mean phantom.flash.${a}?`:`phantom.flash has no "${e}". Its own calls read, call and hook the client (use, global, hook, override, watch, find, hold); drawing is phantom.flash.overlay, the room's players and props are phantom.flash.entities, the camera is phantom.flash.view, and anything the declarations do not describe is phantom.flash.bridge.`}function Ga(n){const e=xn(n);return new Proxy(n,{get(t,a,r){if(typeof a!="string"||a in t)return Reflect.get(t,a,r);if(!(Wa.has(a)||a.startsWith("__v_")||a.startsWith("$$")))throw new TypeError(Va(t,a,e))}})}class Ya{constructor(e){this.bridge=e}bridge;table=null;async set(e,t){const[a]=await te(this.bridge,[t]);await this.bridge.note(await this.number(),"write",A(e),a)}async get(e){const t=await this.bridge.note(await this.number(),"read",A(e));return t==null?void 0:_(this.bridge,t)}async has(e){return await this.bridge.note(await this.number(),"has",A(e))===!0}async forget(e){return await this.bridge.note(await this.number(),"forget",A(e))===!0}async objects(){const e=await this.bridge.note(await this.number(),"keys");return Array.isArray(e)?e.filter(t=>t instanceof W).map(t=>N(this.bridge,t.at(),{handle:t})):[]}async clear(){this.table!==null&&await this.bridge.note(this.table,"clear")}async number(){if(await this.bridge.whenReady(),!this.bridge.features.includes("notes"))throw new Error("This game is running a loader from before notes; nothing can be kept beside its objects");return this.table??=this.bridge.allocate(),this.table}}function be(){const n=new Set;return{add(e){return n.add(e),()=>{n.delete(e)}},tell(e){for(const t of[...n])try{t(e)}catch(a){console.error("phantom.flash.overlay: a control listener failed",a)}}}}function Pt(n){return typeof n=="string"?{value:n,label:n}:{value:n.value,label:n.label??n.value}}function he(n,e,t){return Math.min(t,Math.max(e,n))}async function Ka(n,e){const{label:t="",checked:a=!1,boxSize:r=14,tickFill:i=2278750,disabled:s=!1,onChange:o,fill:h=1120295,stroke:l=10265519,font:c,...u}=e,d=be();o&&d.add(o);const w=await n.group(u),g=await n.rect({parent:w,width:r,height:r,cornerRadius:3,fill:h,stroke:l,hand:!s}),f=await n.rect({parent:w,x:3,y:3,width:r-6,height:r-6,cornerRadius:2,fill:i,visible:a}),m=t?await n.text(t,{parent:w,x:r+6,y:Math.max(0,Math.round((r-12)/2)),...c?{font:c}:{},hand:!s}):null;let p=a,y=s;const b=async()=>{await f.update({visible:p}),await w.update({alpha:y?.5:1}),await g.update({hand:!y}),m&&await m.update({hand:!y})},k=()=>{y||(p=!p,b(),d.tell(p))};return g.on("click",k),m&&m.on("click",k),await b(),Object.assign(w,{value:()=>p,setValue:async M=>{p=M,await b()},setDisabled:async M=>{y=M,await b()},onChange:d.add})}async function Xa(n,e){const{choices:t=[],value:a="",placeholder:r="Choose...",rowHeight:i=16,maxRows:s=6,opens:o="down",disabled:h=!1,onChange:l,width:c=160,height:u=24,...d}=e,w=be();l&&w.add(l);let g=t.map(Pt),f=a,m=h,p=null;const y=await n.group(d),b=()=>{var E;return((E=g.find(I=>I.value===f))==null?void 0:E.label)??r},k=await n.button(b(),{parent:y,width:c,height:u,hand:!m,disabled:m}),M=async()=>{const E=p;p=null,E&&await E.remove()},O=async()=>{if(m||p)return;const I=Math.max(1,Math.min(s,g.length))*i+8;p=await n.list({parent:y,x:0,y:o==="up"?-I:u+2,width:c,height:I,rows:g.map(F=>F.label),maxRows:Math.max(g.length,1)}),p.on("row",F=>{const U=g[F];M(),!(!U||U.value===f)&&(f=U.value,k.setLabel(b()),w.tell(f))})};return k.on("click",()=>{p?M():O()}),Object.assign(y,{value:()=>f,setValue:async E=>{f=E,await k.setLabel(b())},setChoices:async E=>{g=E.map(Pt),await M(),await k.setLabel(b())},setDisabled:async E=>{m=E,await M(),await k.setDisabled(E)},open:O,close:M,isOpen:()=>p!==null,onChange:w.add})}async function Ja(n,e){const{tabs:t=[],active:a,tabWidth:r,tabHeight:i=22,gap:s=2,activeFill:o=8141549,idleFill:h=3621201,onChange:l,font:c,...u}=e;if(t.length===0)throw new TypeError('overlay.tabs needs the tabs it is drawing: overlay.tabs({ tabs: [{ name: "one" }] })');const d=be();l&&d.add(l);const w=await n.group(u),g=new Map,f=new Map;let m=a&&t.some(k=>k.name===a)?a:t[0].name,p=0;for(const k of t){const M=k.label??k.name,O=c?{font:c}:{},E=r??Math.ceil((await n.measure(M,O)).width)+16,I=await n.button(M,{parent:w,x:p,y:0,width:E,height:i,fill:k.name===m?o:h,...O});p+=E+s,f.set(k.name,I),g.set(k.name,await n.group({parent:w,y:i+s}))}const y=async()=>{await Promise.all([...f].map(([k,M])=>M.update({fill:k===m?o:h}))),await Promise.all([...g].map(([k,M])=>k===m?M.show():M.hide()))};for(const[k,M]of f)M.on("click",()=>{k!==m&&(m=k,y(),d.tell(k))});await y();const b=k=>{const M=g.get(k);if(!M)throw new TypeError(`There is no tab called "${k}"; these tabs are ${[...g.keys()].join(", ")}`);return M};return Object.assign(w,{value:()=>m,setValue:async k=>{b(k),m=k,await y()},show:async k=>{b(k),k!==m&&(m=k,await y(),d.tell(k))},page:b,onChange:d.add})}async function Qa(n,e){const{width:t=240,height:a=160,step:r=24,onScroll:i,fill:s={color:0,alpha:.55},...o}=e,h=be();i&&h.add(i);const l=await n.panel({...o,width:t,height:a,fill:s,stroke:null,cornerRadius:0,titleHeight:0,draggable:!1}),c=await n.group({parent:l});let u=0,d=0;const w=async()=>{const f=await c.bounds();d=Math.max(0,Math.round(f.y+u+f.height-a)),u>d&&await g(d)},g=async f=>{const m=Math.round(he(f,0,d));m!==u&&(u=m,await c.update({y:-u}),h.tell(u))};return l.on("wheel",({delta:f})=>{g(u-f*(r/3))}),await w(),Object.assign(l,{content:c,top:()=>u,scrollTo:g,scrollBy:f=>g(u+f),refresh:w,onScroll:h.add})}async function Za(n,e){const{min:t=0,max:a=100,value:r,step:i,length:s=120,knobRadius:o=6,trackFill:h=3621201,knobFill:l=16777215,onChange:c,...u}=e;if(a<=t)throw new TypeError(`overlay.slider needs max above min; it was given ${t} and ${a}`);const d=be();c&&d.add(c);const w=await n.group(u);await n.rect({parent:w,y:o-2,width:s,height:4,cornerRadius:2,fill:h});const g=a-t,f=b=>(he(b,t,a)-t)/g*s,m=b=>{const k=t+he(b,0,s)/s*g;return i&&i>0?he(Math.round(k/i)*i,t,a):k};let p=r===void 0?t:he(r,t,a);const y=await n.circle({parent:w,x:f(p),y:o,radius:o,fill:l,hand:!0,drag:{axis:"x",left:0,right:s,live:!0,...i&&i>0?{step:i/g*s}:{}}});return y.on("move",({x:b})=>{const k=m(b);k!==p&&(p=k,d.tell(p))}),Object.assign(w,{value:()=>p,setValue:async b=>{p=he(b,t,a),await y.update({x:f(p)})},onChange:d.add})}const er=127;function Mn(n){const e=[],t=[];let a="",r=0;const i=()=>{const o={};for(const h of t)Object.assign(o,h.look);return o},s=()=>{if(a==="")return;const o={text:a,...i()},h=e[e.length-1];h&&sr(h,o)?h.text+=a:e.push(o),a=""};for(;r<n.length;){const o=n[r];if(o!=="["){a+=o,r++;continue}if(n[r+1]==="["){a+="[",r+=2;continue}const h=n.indexOf("]",r+1),l=h<0?null:tr(n.slice(r+1,h));if(l===null){a+=o,r++;continue}if(l.closing){const c=ir(t,l.name);c<0?a+=n.slice(r,h+1):(s(),t.splice(c))}else s(),t.push({tag:l.name,look:l.look});r=h+1}return s(),e}function tr(n){if(n.startsWith("/")){const r=n.slice(1);return nr.has(r)?{name:r,closing:!0}:null}const e=n.indexOf("="),t=e<0?n:n.slice(0,e),a=e<0?null:n.slice(e+1);switch(t){case"b":return a===null?{name:t,closing:!1,look:{bold:!0}}:null;case"i":return a===null?{name:t,closing:!1,look:{italic:!0}}:null;case"u":return a===null?{name:t,closing:!1,look:{underline:!0}}:null;case"color":{const r=a===null?null:rr(a);return r===null?null:{name:t,closing:!1,look:{color:r}}}case"size":{const r=a===null?NaN:Number(a);return Number.isInteger(r)&&r>=1&&r<=er?{name:t,closing:!1,look:{size:r}}:null}case"link":return a===null||a===""?null:{name:t,closing:!1,look:{link:a}};default:return null}}const nr=new Set(["b","i","u","color","size","link"]),ar="0123456789abcdef";function rr(n){const e=n.toLowerCase(),t=e.startsWith("#")?e.slice(1):e.startsWith("0x")?e.slice(2):null;if(t===null||t.length!==6)return null;let a=0;for(const r of t){const i=ar.indexOf(r);if(i<0)return null;a=a*16+i}return a}function ir(n,e){for(let t=n.length-1;t>=0;t--)if(n[t].tag===e)return t;return-1}function sr(n,e){return["color","bold","italic","underline","size","font","link"].every(a=>n[a]===e[a])}const We={className:"avatar.AvatarManager",path:["playerAvatarWorldView","parent"]},Rt=new Set(["click","down","up","over","out","hover","wheel"]);class or{constructor(e){this.bridge=e}bridge;nodes=new Map;async draw(e,t={}){const{handle:a}=await this.make(e,t);return a}world(e={x:0,y:0},t={}){return{place:this.bridge.definition(We.className).at(We.path[0],We.path[1]),x:e.x,y:e.y,...t}}marker(e,t={}){const{kind:a="circle",...r}=t;return this.draw(a,{radius:8,...r,anchor:this.world(e)})}group(e={}){return this.draw("group",e)}text(e,t={}){return Be("text",e,"the words","overlay.text('hello', { x: 20 })"),this.draw("text",{...t,text:e})}rich(e,t={}){if(typeof e!="string"&&!Array.isArray(e))throw new TypeError("overlay.rich takes markup or spans first: overlay.rich('[b]hello[/b]', { x: 20 }). Its other fields go in the options.");return this.draw("text",{...t,rich:e})}rect(e){return this.draw("rect",e)}circle(e){return this.draw("circle",e)}line(e){return this.draw("line",e)}image(e,t={}){return Be("image",e,"the address","overlay.image('/path.png', { x: 20 })"),this.draw("image",{...t,url:e})}async input(e={}){const{handle:t,state:a}=await this.make("input",{width:200,height:24,fill:16777215,stroke:10265519,padding:4,...e,font:{color:1120295,...e.font}});return a.value=e.value??"",Object.assign(t,{value:()=>a.value,setValue:async i=>{a.value=i,a.removed||await this.bridge.draw(t.node,{value:i})},focus:async()=>{a.removed||await this.bridge.draw(t.node,{focus:!0})}})}async button(e,t={}){Be("button",e,"the label","overlay.button('Send', { x: 20 })");const{handle:a,state:r}=await this.make("button",{width:72,height:24,fill:8141549,hoverFill:9133302,pressedFill:7153881,cornerRadius:4,...t,font:{color:16777215,bold:!0,...t.font},label:e});return Object.assign(a,{setLabel:i=>r.removed?Promise.resolve():this.bridge.draw(a.node,{label:i}),setDisabled:i=>r.removed?Promise.resolve():this.bridge.draw(a.node,{disabled:i})})}async panel(e={}){const{onMove:t,onResize:a,...r}=e,{handle:i}=await this.make("panel",{width:260,height:200,fill:{color:1120295,alpha:.92},stroke:3621201,titleFill:2042167,titleHeight:22,cornerRadius:6,...r,titleFont:{color:16777215,bold:!0,...r.titleFont}}),s=i;return t&&s.on("move",t),a&&s.on("resize",a),s}async list(e={}){const{handle:t,state:a}=await this.make("list",{width:240,height:160,fill:{color:0,alpha:.55},padding:4,...e,font:{color:16777215,...e.font}});return Object.assign(t,{append:(...r)=>a.removed||r.length===0?Promise.resolve():this.bridge.draw(t.node,{append:r.map(qe)}),setRows:r=>a.removed?Promise.resolve():this.bridge.draw(t.node,{rows:r.map(qe)})})}checkbox(e={}){return Ka(this,e)}select(e={}){return Xa(this,e)}tabs(e){return Ja(this,e)}scroller(e={}){return Qa(this,e)}slider(e={}){return Za(this,e)}async measure(e,t={}){return await this.bridge.whenReady(),this.needs("measure","measuring text; draw it and read the node’s bounds instead"),this.bridge.measure({...typeof e=="string"?{text:e}:{spans:e},font:Nt(t.font??{}),padding:t.padding??0,...t.wrapWidth===void 0?{}:{wrapWidth:t.wrapWidth}})}row(e,t={}){return this.layout("row",e,t)}column(e,t={}){return this.layout("column",e,t)}async replace(e,t){return Ct("replace",e),await t.update({parent:null,host:null,replaces:e}),()=>t.remove()}async attach(e,t){return Ct("attach",e),await t.update({parent:null,replaces:null,host:e}),()=>t.remove()}async focusGame(){await this.bridge.stage().at("focus").set(null)}async clear(){const e=[...this.nodes.entries()].filter(([,t])=>t.parent===null||!this.nodes.has(t.parent)).map(([t])=>t);await this.remove(e)}async layout(e,t,a){const r=a.gap??6,i=a.x??0,s=a.y??0,o=a.align??"start",h=t.filter(f=>this.nodes.has(f.node));if(h.length===0)return{width:0,height:0};const l=await Promise.all(h.map(f=>f.bounds())),c=Math.max(...l.map(f=>e==="row"?f.height:f.width));let u=e==="row"?i:s,d=0,w=0;const g=[];for(const[f,m]of h.entries()){const p=l[f],y=this.nodes.get(m.node),b=c-(e==="row"?p.height:p.width),k=o==="middle"?b/2:o==="end"?b:0,M=e==="row"?u:i+k,O=e==="row"?s+k:u,E=Math.round(y.x+(M-p.x)),I=Math.round(y.y+(O-p.y));(E!==y.x||I!==y.y)&&g.push(m.update({x:E,y:I})),d=Math.max(d,M-i+p.width),w=Math.max(w,O-s+p.height),u+=(e==="row"?p.width:p.height)+r}return await Promise.all(g),{width:d,height:w}}needs(e,t){if(!this.bridge.features.includes(e))throw new Error(`This game is running a loader from before ${t}`)}async allowed(e){await this.bridge.whenReady(),e.align!=null&&this.needs("align","aligning; place the node with x and y, and follow the stage yourself"),e.drag!=null&&this.needs("gestures","dragging; a panel is the one thing the player can move")}async make(e,t){var a;const r=this.bridge.allocate(),i={type:e,...this.specOf(t)};(i.align!==void 0||i.drag!==void 0)&&await this.allowed(i);const s={parent:t.parent?t.parent.node:null,children:new Set,listeners:new Map,failed:new Set,gone:new Set,stopHearing:()=>{},removed:!1,value:"",x:t.x??0,y:t.y??0};s.stopHearing=this.bridge.onSubscription(r,o=>{var h;if(o.kind==="overlay"){if(o.event==="failed"){s.failed.forEach(l=>l(o.message??"The image did not load"));return}(o.event==="change"||o.event==="submit")&&o.value!==void 0&&(s.value=o.value),o.event==="move"&&(s.x=o.x,s.y=o.y),(h=s.listeners.get(o.event))==null||h.forEach(l=>l(o))}}),this.nodes.set(r,s);try{await this.bridge.draw(r,i)}catch(o){throw s.stopHearing(),this.nodes.delete(r),o}return s.parent!==null&&((a=this.nodes.get(s.parent))==null||a.children.add(r)),{handle:this.handle(r,e,s),state:s}}handle(e,t,a){const r=()=>this.remove([e]);return Object.assign(r,{node:e,type:t,update:async s=>{var o,h;if(a.removed)return;const l=this.specOf(s);(l.align!==void 0||l.drag!==void 0)&&await this.allowed(l),s.x!==void 0&&(a.x=s.x),s.y!==void 0&&(a.y=s.y),"parent"in s&&(a.parent!==null&&((o=this.nodes.get(a.parent))==null||o.children.delete(e)),a.parent=s.parent?s.parent.node:null,a.parent!==null&&((h=this.nodes.get(a.parent))==null||h.children.add(e))),await this.bridge.draw(e,l)},bounds:async()=>{if(a.removed)throw new Error("That node has been removed, so it is nowhere and no size");return await this.bridge.whenReady(),this.needs("measure","measuring; a node cannot say where it is or how big"),this.bridge.bounds(e)},show:()=>a.removed?Promise.resolve():this.bridge.draw(e,{visible:!0}),hide:()=>a.removed?Promise.resolve():this.bridge.draw(e,{visible:!1}),remove:r,on:(s,o)=>{const h=o,l=g=>{switch(g.event){case"change":case"submit":case"link":h(g.value??"");return;case"focus":case"blur":h(void 0);return;case"row":h(g.index??-1);return;case"move":h({x:g.x,y:g.y});return;case"resize":h({width:g.width??0,height:g.height??0});return;case"wheel":h({x:g.x,y:g.y,delta:g.delta??0});return;default:h({x:g.x,y:g.y})}};let c=a.listeners.get(s);const u=!c||c.size===0;c||(c=new Set,a.listeners.set(s,c)),c.add(l);const d=Rt.has(s);u&&d&&this.sendMouse(e,a);let w=!1;return async()=>{w||(w=!0,c.delete(l),d&&c.size===0&&!a.removed&&await this.sendMouse(e,a))}},onFailed:s=>(a.failed.add(s),()=>{a.failed.delete(s)}),onRemoved:s=>a.removed?(s(),()=>{}):(a.gone.add(s),()=>{a.gone.delete(s)})})}async sendMouse(e,t){const a=[...t.listeners.entries()].filter(([r,i])=>Rt.has(r)&&i.size>0).map(([r])=>r);await this.bridge.draw(e,{mouse:a})}async remove(e){const t=[],a=[],r=s=>{var o;const h=this.nodes.get(s);!h||h.removed||(h.removed=!0,h.stopHearing(),this.nodes.delete(s),t.push(s),a.push(...h.gone),h.gone.clear(),h.children.forEach(r),h.parent!==null&&((o=this.nodes.get(h.parent))==null||o.children.delete(s)))};e.forEach(r);const i=e.filter(s=>t.includes(s));try{await this.bridge.erase(i)}finally{for(const s of a)try{s()}catch(o){console.error("phantom.flash.overlay: a removal listener failed",o)}}}specOf(e){const t={};for(const[a,r]of Object.entries(e))if(r!==void 0)switch(a){case"parent":t.parent=r===null?null:r.node;break;case"anchor":t.anchor=r===null?null:cr(r);break;case"host":case"replaces":t[a]=r===null?null:hr(r);break;case"fill":case"background":case"hoverFill":case"pressedFill":case"titleFill":t[a]=r===null?null:ur(r);break;case"stroke":t.stroke=r===null?null:dr(r);break;case"font":case"titleFont":t[a]=Nt(r);break;case"drag":t.drag=r===null||r===!1?null:r===!0?{}:r;break;case"rich":t.spans=r===null?null:typeof r=="string"?Mn(r):r;break;case"rows":case"append":t[a]=r.map(qe);break;default:t[a]=r}return t}}function lr(n){return typeof n=="function"&&typeof n.node=="number"}function Be(n,e,t,a){if(typeof e!="string")throw new TypeError(`overlay.${n} takes ${t} first: ${a}. Everything else goes in the options.`)}function Ct(n,e){if(lr(e))throw new TypeError(`overlay.${n} takes the client's place first and your node second: overlay.${n}(place, node).`)}function Nt(n){return{family:"_sans",size:12,color:16777215,bold:!1,italic:!1,...n}}function qe(n){if(typeof n=="string")return n||" ";const e=(Array.isArray(n)?n:Mn(n.markup)).filter(t=>t.text.length>0);return e.length?e:" "}function cr(n){const e=typeof n=="object"&&n!==null&&"place"in n?n:{place:n},t=A(e.place);return{target:t.target,path:t.path,x:e.x??0,y:e.y??0,refreshFrames:e.refreshFrames??12,hideWhenGone:e.hideWhenGone??!0}}function hr(n){const e=typeof n=="object"&&n!==null&&"place"in n?n:{place:n},t=A(e.place);return{target:t.target,path:t.path,refreshFrames:e.refreshFrames??12}}function ur(n){return typeof n=="number"?{color:n,alpha:1}:{color:n.color,alpha:n.alpha??1}}function dr(n){return typeof n=="number"?{color:n,alpha:1,width:1}:{color:n.color,alpha:n.alpha??1,width:n.width??1}}async function fr(n,e,t,a,r={}){if(typeof a!="function")throw new TypeError(`phantom.flash.override("${t}", ...) was given ${mr(a)} where its handler goes. An override takes its handler second and its options third: override(name, handler, options). A hook is the other way about: hook(name, options, listener).`);const i=e.find(t);if(!i)throw new TypeError(`There is no hook "${t}" in the hook table`);const s=r.perFrame??$e,o=r.sequential??!0,h={perFrame:s};r.when!==void 0&&(h.when=r.when),r.first!==void 0&&(h.first=r.first),r.every!==void 0&&(h.every=r.every),r.replaceArgs!==void 0&&(h.replaceArgs=r.replaceArgs),"returns"in r&&(h.skip={returns:r.returns});const l={...rt(n,i,h,!1),override:!0};let c=0,u=Promise.resolve(),d=!1;const w=B(i),g=async y=>{c++;let b=!1,k=!1;const M=y.args.map(F=>_(n,n.decode(F))),O=gr(i,M),E=i.isStatic?N(n,n.definition(i.className),{className:i.className}):_(n,n.decode(y.self)),I={hook:i,call:y.call,self:E,args:O,argList:M,arg:F=>M[wr(i,F)],original:async(...F)=>{if(k)throw new z("FLASH",`The call of ${w} has ended: its handler finished`);b=!0;const U=await n.invokeOriginal(f,y.token,F.length===0?null:await te(n,F));return _(n,U)}};try{await a(I)}catch(F){if(console.error(`The override of ${w} failed: ${F instanceof Error?F.message:String(F)}`),!b&&(r.onError??"original")==="original")try{await n.invokeOriginal(f,y.token,null)}catch(U){console.error(`The original ${w} failed after its override did: ${U instanceof Error?U.message:String(U)}`)}}finally{k=!0,c--;try{await n.overrideDone(f,y.token)}catch{}}},{registration:f,stop:m}=await n.hook(i.id,l,y=>{switch(y.kind){case"override":o?u=u.then(()=>g(y)):g(y);return;case"hook-dropped":r.onDropped?r.onDropped(y.dropped):d||(d=!0,console.warn(`The override of ${w} let ${y.dropped} calls through untouched in one frame: it catches at most ${s} a frame, and 256 may wait on handlers at once. `+(s<$e?`Raise perFrame (${$e} is the most the game allows), `:"Let the handler finish sooner, narrow the override with when/first/every, ")+"or pass onDropped to count them yourself. Said once per override."));return;case"hook-failed":console.error(`The override of ${w} failed and is off: ${y.error.message}`);return}}),p=Object.assign(()=>m(),{registration:f,hook:i,stats:async()=>(await n.request({op:"hookStats"})).find(b=>b.registration===f)??null});return Object.defineProperty(p,"running",{get:()=>c,enumerable:!0}),p}function ct(n){return n.parameters.map(e=>e.name).join(", ")||"none"}function wr(n,e){if(typeof e=="number"||/^\d+$/.test(e)){const a=Number(e);if(!Number.isInteger(a)||a<0||n.parameters.length>0&&!n.rest&&a>=n.parameters.length)throw new RangeError(`${B(n)} has no argument ${a} (its arguments: ${ct(n)})`);return a}const t=n.parameters.findIndex(a=>a.name===e);if(t>=0)return t;throw new TypeError(`${B(n)} has no argument "${e}" (its arguments: ${ct(n)})`)}function gr(n,e){const t={};return e.forEach((a,r)=>{var i;t[((i=n.parameters[r])==null?void 0:i.name)??String(r)]=a}),Object.defineProperty(t,Symbol.iterator,{value:()=>{throw new TypeError(`${B(n)}: call.args holds the arguments by name (${ct(n)}), so it does not destructure in order. Take call.argList for that, or call.arg(name) for one.`)}}),t}function mr(n){if(n===void 0)return"nothing";if(n===null)return"null";if(Array.isArray(n))return"a list";if(typeof n=="object"){const e=Object.keys(n).slice(0,4).join(", ");return e?`an options object (${e})`:"an object"}return`a ${typeof n}`}const pr=2,yr=1e4,br=12,vr=["room.RoomManagerWorld.sceneAssetsLoaded","gui.GuiHud.init"];async function _t(n,e){const t=Math.max(1,Math.trunc(e));let a=0,r=null,i=!1;return new Promise((s,o)=>{const h=l=>{i||(i=!0,r&&r().catch(()=>{}),s(l))};n.tick(1,l=>{a+=1,a>=t&&h(l)}).then(l=>{r=l,i&&l().catch(()=>{})}).catch(o)})}function Me(n){return n!=null&&n!==!1}function kr(n,e,t){const a=t.timeoutMs??yr;return new Promise((r,i)=>{let s=!1,o=null,h;const l=c=>{s||(s=!0,h!==void 0&&clearTimeout(h),o&&o().catch(()=>{}),r(c))};Number.isFinite(a)&&(h=setTimeout(()=>l(null),Math.max(0,a))),n(c=>{if(s)return;let u=!1;try{u=e(c)}catch(d){s=!0,h!==void 0&&clearTimeout(h),o&&o().catch(()=>{}),i(d instanceof Error?d:new Error(String(d)));return}u&&l(c)}).then(c=>{o=c,s&&c().catch(()=>{})}).catch(c=>{s||(s=!0,h!==void 0&&clearTimeout(h),i(c instanceof Error?c:new Error(String(c))))})})}class xr{constructor(e,t,a,r,i){this.bridge=e,this.table=t,this.source=a,this.attach=r,this.options=i}bridge;table;source;attach;options;live=!0;held=null;detach=null;looking=!1;again=!1;async look(){if(this.looking){this.again=!0;return}this.looking=!0;try{do this.again=!1,await this.lookOnce();while(this.again&&this.live)}finally{this.looking=!1}}async end(){this.live=!1,await this.letGo(!1),await this.bridge.note(this.table,"clear").catch(()=>{})}async lookOnce(){if(!this.live)return;const e=await this.find();if(!e)return this.letGo(!0);try{await this.lookAt(e)}finally{ue(this.source)||await Mr(e)}}async lookAt(e){let t;try{t=await this.bridge.note(this.table,"has",A(e))===!0}catch{return this.letGo(!0)}if(t&&this.held)return;const a=await ae(e).get().catch(()=>null);if(!(a instanceof W))return this.letGo(!0);if(await this.letGo(!1),!this.live){await a.release().catch(()=>{});return}try{await this.bridge.note(this.table,"write",a.at().entry,!0)}catch{await a.release().catch(()=>{});return}this.held=a;try{const r=await this.attach(N(this.bridge,a.at(),{handle:a}));typeof r=="function"&&(this.detach=r)}catch(r){this.failed(r)}this.live||await this.letGo(!1)}async find(){if(ue(this.source))return this.source;try{const e=await this.source();return ue(e)?e:null}catch{return null}}async letGo(e){var t,a;const r=this.held,i=this.detach;if(this.held=null,this.detach=null,i)try{await i()}catch(s){this.failed(s)}if(r&&(await this.bridge.note(this.table,"forget",r.at().entry).catch(()=>{}),await r.release().catch(()=>{}),e&&this.live))try{(a=(t=this.options).onGone)==null||a.call(t)}catch(s){this.failed(s)}}failed(e){if(this.options.onFailed){try{this.options.onFailed(e)}catch{}return}console.error("phantom.flash.whenever: what was put on the object failed",e)}}async function Mr(n){if(n instanceof W){await n.release().catch(()=>{});return}const e=n.$release;typeof e=="function"&&await e().catch(()=>{})}class Sr{constructor(e){this.host=e}host;moments=new Map;async whenever(e,t,a={}){const r=this.host.bridge;if(await r.whenReady(),!r.features.includes("notes")||!r.features.includes("tick"))throw new Error("This game is running a loader from before notes; put it on the object yourself each time");if(!ue(e)&&typeof e!="function")throw new TypeError("Expected a place in the game, or a function that finds one");if(typeof t!="function")throw new TypeError("Expected a function to run on the object each time it is made");const i=new xr(r,r.allocate(),e,t,a),s=()=>{i.look().catch(()=>{})},o=a.moments??vr;for(const u of o)this.join(u,i);const h=Math.max(1,Math.trunc(a.everyFrames??br));let l;try{l=await r.tick(h,s)}catch(u){for(const d of o)this.leave(d,i);throw u}await i.look();let c=!1;return async()=>{if(!c){c=!0;for(const u of o)this.leave(u,i);await l().catch(()=>{}),await i.end()}}}join(e,t){let a=this.moments.get(e);if(!a){const r=new Set,i=this.host.hook(e,{phase:"exit",capture:{args:[]}},()=>{for(const s of[...r])s.look().catch(()=>{})}).catch(()=>null);a={keepers:r,stop:i},this.moments.set(e,a)}a.keepers.add(t)}leave(e,t){const a=this.moments.get(e);a&&(a.keepers.delete(t),!(a.keepers.size>0)&&(this.moments.delete(e),a.stop.then(r=>r==null?void 0:r().catch(()=>{}))))}}const Er={fit:"showAll",stretch:"exactFit",fill:"noBorder",none:"noScale"};class Tr{constructor(e){this.bridge=e}bridge;async zoom(e){await this.bridge.definition("room.RoomManagerWorld").at("instance","updateRoomZoom").call(Math.round(e))}async zoomLevel(){return await this.bridge.definition("gMainFrame").at("layerManager","bkg","scaleX").get()*100}async stretch(e){await this.bridge.stage().at("scaleMode").set(Er[e])}hideHud(e){return this.bridge.highlight({target:{kind:"definition",name:"gui.GuiManager"},path:e?["mainHud",e]:["mainHud"]},ye({hide:!0}))}hideLayer(e){return this.bridge.highlight({target:{kind:"definition",name:"gMainFrame"},path:["layerManager",e]},ye({hide:!0}))}async setQuality(e){await this.bridge.stage().at("quality").set(e)}async setFrameRate(e){const t=this.bridge.stage().at("frameRate"),a=await t.get();return await t.set(Math.max(1,Math.min(120,e))),a}}class wt extends dn{format="json";envelope;constructor(e,t){super(e,t),this.envelope=Or(e)}static create(e,t,a,r=-1,i="o"){const s=e==="toServer"?{t:"xt",b:{x:i,c:t,r,p:a}}:{t:"xt",b:{r,o:{_cmd:t,...a}}};return new wt(JSON.stringify(s),e)}get type(){return this.envelope.t}get command(){var e;const t=this.direction==="toServer"?this.envelope.b.c:(e=this.envelope.b.o)==null?void 0:e._cmd;return typeof t=="string"?t:null}get room(){const e=this.envelope.b.r;return typeof e=="number"&&Number.isInteger(e)?e:null}get params(){if(this.direction==="toServer")return this.envelope.b.p??{};const{_cmd:e,...t}=this.envelope.b.o??{};return t}get value(){return this.envelope}edit(e){e(this.envelope),this.markModified()}serialize(){return JSON.stringify(this.envelope)}}function Or(n){let e;try{e=JSON.parse(n)}catch(t){throw new vt(`Not JSON: ${t.message}`,"JSON_SYNTAX")}if(!Ft(e)||typeof e.t!="string"||!Ft(e.b))throw new vt('A JSON message is an object with "t" and "b"',"JSON_SYNTAX");return e}function Ft(n){return typeof n=="object"&&n!==null&&!Array.isArray(n)}class Lt extends dn{constructor(e,t,a=null){super(e,t),this.problem=a}problem;format="raw";get command(){return null}get room(){return null}serialize(){return this.raw}}function Sn(n,e){try{switch(n.charAt(0)){case"<":return new qn(n,e);case Wn:return new Bn(n,e);case"{":return new wt(n,e);default:return new Lt(n,e)}}catch(t){return new Lt(n,e,t)}}const ht={send:"avatar.UserCommXtCommManager.onSendMessage",focusChat:"gui.ChatHistory.setFocusOnMsgText"};function Ar(n,e){const t=new Map;for(const[s,o]of Object.entries(e))t.set(s.toLowerCase(),o);if(t.size===0)return n;let a="",r="";const i=()=>{a+=t.get(r.toLowerCase())??r,r=""};for(const s of n)s===" "||s===" "?(i(),a+=s):r+=s;return i(),a}function $r(n,e){const t=n.toLowerCase();return e.some(a=>typeof a=="string"?a!==""&&t.includes(a.toLowerCase()):(a.lastIndex=0,a.test(n)))}async function Pr(n,e={}){const{arg:t,fromClass:a,equals:r,exists:i,all:s}=n.flash.rules,o=e.shortcuts??{},h=e.blocked??[],l=a("avatar.UserCommXtCommManager","_mainHud","chatBar","text01_chat","text"),c=[],u=gt(async()=>{for(const d of c.splice(0).reverse())await d().catch(()=>{})});try{c.push(await n.flash.hook(ht.send,{when:s(r(t("myMsg"),""),i(l)),replaceArgs:{myMsg:l}})),c.push(await n.flash.override(ht.send,async d=>{var w;const[g,f]=d.argList,m=typeof f=="string"?f:"";if(m.trim()!==""&&$r(m,h)){(w=e.onBlocked)==null||w.call(e,m);return}const p=Ar(m,o);p===m?await d.original():await d.original(g,p)},{sequential:!0}))}catch(d){throw await u(),d}return u}async function Rr(n,e={}){const t=e.style??{},a=n.flash.overlay,r=n.flash.use("gui.GuiManager").$at("mainHud"),i=e.maxLength??await n.flash.use("gui.GuiManager").$at("chatHist","chatMsgText","maxChars").$get().then(l=>typeof l=="number"&&l>0?l:70).catch(()=>70),s={family:t.font??"_sans",size:t.size??13},o=[],h=gt(async()=>{for(const l of o.splice(0).reverse())await l().catch(()=>{})});try{o.push(async()=>{await n.flash.use("gui.GuiManager").setFocusToChatText()});const l=await a.input({replaces:r.$at("chatBar"),placeholder:t.placeholderText??"Say something",maxLength:i,fill:t.background??16777215,stroke:t.border??8141549,cornerRadius:t.cornerRadius??6,padding:6,font:{...s,color:t.text??1120295}});o.push(()=>l.remove());const c=await a.button(t.buttonLabel??"Send",{replaces:r.$at("sendChatBtn"),fill:t.button??8141549,hoverFill:t.buttonHover??9133302,cornerRadius:t.cornerRadius??6,font:{...s,color:t.buttonText??16777215,bold:!0}});o.push(()=>c.remove());let u=!1;const d=async()=>{const w=l.value();if(!(u||w.trim()==="")){u=!0;try{await n.chat.say(w),await l.setValue(""),await l.focus()}finally{u=!1}}};return o.push(l.on("submit",()=>{d()})),o.push(c.on("click",()=>{d()})),o.push(await n.flash.hook(ht.focusChat,{skip:!0,phase:"enter",capture:{args:[]}},()=>{l.focus()})),(e.focus??!0)&&await l.focus(),Object.assign(h,{input:l,send:d})}catch(l){throw await h(),l}}const Cr=[16096779,1096065,3900150,15485081,9133302,15680580,1357990,15381256],Ue=22;async function Nr(n,e={}){const t=e.style??{},a=n.flash.overlay,r=t.nameColors&&t.nameColors.length>0?t.nameColors:Cr,i=e.width??280,s=e.height??200,o={family:t.font??"_sans",size:t.size??12},h=new Map,l=[],c=gt(async()=>{for(const u of l.splice(0).reverse())await Promise.resolve(u()).catch(()=>{})});try{const u=await a.panel({title:e.title??"Chat",x:e.x??12,y:e.y??60,width:i,height:s,resizable:!0,fill:{color:t.background??1120295,alpha:t.backgroundAlpha??.9},stroke:t.border??3621201,titleFill:t.titleBar??2042167,titleHeight:Ue,titleFont:{...o,color:t.titleText??16777215,bold:!0},...e.onMove?{onMove:e.onMove}:{}});l.push(()=>u.remove());const d=await a.list({parent:u,width:i,height:s-Ue,fill:null,maxRows:e.maxRows??200,font:{...o,color:t.text??15987958}});l.push(u.on("resize",p=>{var y;(y=e.onResize)==null||y.call(e,p),d.update({width:p.width,height:p.height-Ue})})),l.push(d.on("link",p=>{const y=h.get(p);if(y){if(e.onNameClick){e.onNameClick(y);return}_r(n,y.userId)}}));const w=async p=>{let y=null;if(p.kind===De.free||p.kind===De.freeSafeChat?y=p.text:p.kind===De.safeChat&&(y=await n.chat.phrase(p.text).catch(()=>null)??null),y===null)return null;const b=n.room.players.get(p.userId),k=(b==null?void 0:b.avatarName)||(b==null?void 0:b.userName)||`#${p.userId}`,M=String(p.userId);return h.set(M,{userId:p.userId,name:k}),[{text:k,bold:!0,color:r[Math.abs(p.userId)%r.length],link:M},{text:`: ${y}`}]},f=(await Promise.all(n.chat.recent.map(w))).filter(p=>p!==null);f.length>0&&await d.append(...f);let m=Promise.resolve();return l.push(n.chat.onMessage(p=>{m=m.then(async()=>{const y=await w(p);y&&await d.append(y)}).catch(()=>{})})),Object.assign(c,{panel:u,note:p=>d.append({markup:p})})}catch(u){throw await c(),u}}async function _r(n,e){const t=n.flash.use("avatar.AvatarManager").avatarViewList.$at(String(e)),a=await n.flash.highlight(t,{color:16436245,strength:3});setTimeout(()=>{a()},2e3)}function gt(n){let e=null;return()=>e??=n()}class Fr{constructor(e){return this.bridge=e,this.overlay=new or(e),this.entities=new La(this),this.view=new Tr(e),this.timing=new Sr(this),Ga(this)}bridge;overlay;entities;view;rules=ya;hookIndex=null;timing;use(e){return N(this.bridge,this.bridge.definition(e),{className:e})}global(e){return N(this.bridge,this.bridge.definition(e))}stage(){return N(this.bridge,this.bridge.stage())}client(){return N(this.bridge,this.bridge.gameClient())}whenReady(){return this.bridge.whenReady()}hooks(e){if(e!==void 0||!this.hookIndex){const t=this.bridge.hookTable(e).then(a=>new pa(a));t.catch(()=>{this.hookIndex===t&&(this.hookIndex=null)}),this.hookIndex=t}return this.hookIndex}async describe(e,t={}){return Ta(this.bridge,await this.hooks(),e,t)}async search(e,t={}){return Oa(await this.hooks(),e,t)}async hook(e,t={},a){return ba(this.bridge,await this.hooks(),e,t,a)}async override(e,t,...[a]){return fr(this.bridge,await this.hooks(),e,t,a??{})}style(e,t){return this.bridge.style(A(e),t)}hold(e,t,a={}){return st(this.bridge,[{place:e,value:t}],a)}holdAll(e,t={}){return st(this.bridge,e,t)}repeat(e,t={}){return va(this.bridge,e,t)}collect(e,t,a={}){return Ma(this.bridge,e,t,a)}async track(e,t,a={}){if(await this.bridge.whenReady(),!this.bridge.features.includes("track"))throw new Error("This game is running a loader from before lists; look for them yourself");const r=a.where===void 0?{target:{kind:"stage"},path:[]}:A(a.where),i=s=>s.filter(o=>o instanceof W).map(o=>N(this.bridge,o.at(),{handle:o}));return this.bridge.track(r,e,{...a.mode!==void 0?{mode:a.mode}:{},...a.everyFrames!==void 0?{everyFrames:a.everyFrames}:{}},({added:s,removed:o})=>t({added:i(s),removed:i(o)}))}async snapshot(e,t={}){if(await this.bridge.whenReady(),!this.bridge.features.includes("snapshot"))throw new Error("This game is running a loader from before pictures; nothing can be drawn");return this.bridge.snapshot(A(e),t)}notes(){return new Ya(this.bridge)}async find(e,t){return await Ia(this.bridge,t,e??{})}answering(e,t){return new xa(this.bridge,e,t)}watch(e,t,a){const r=a;let i,s=[],o;if(Array.isArray(e))i="list",o=[...e];else if(jt(e))i="one",o=[e];else{i="record";const u=e;s=Object.keys(u),o=s.map(d=>u[d])}const h=o.map(A),l=u=>i==="one"?u[0]:i==="list"?u:Object.fromEntries(s.map((d,w)=>[d,u[w]]));let c=null;return this.bridge.watch(h,t,(u,d)=>{const w=u.map(m=>_(this.bridge,m)),g=l(w),f=h.map((m,p)=>(d==null?void 0:d[p])??null);r(g,c,i==="one"?f[0]:l(f)),c=g})}frames(e=1){return _t(this.bridge,e)}nextFrame(){return _t(this.bridge,1)}until(e,t,a={}){const r=typeof t=="function"?a:t??a,i=typeof t=="function"?t:h=>Ir(h,jt(e)),s=r.everyFrames??pr,o=this.watch.bind(this);return kr(h=>o(e,{everyFrames:s},h),i,r)}whenever(e,t,a={}){return this.timing.whenever(e,t,a)}onTick(e,t={}){return this.bridge.tick(t.everyFrames??1,e)}highlight(e,t={}){return this.bridge.highlight(A(e),ye(t))}hide(e){return this.bridge.highlight(A(e),ye({hide:!0}))}recolor(e,t){const a=t?A(t):{target:{kind:"loader"},path:[]};return this.bridge.highlight(a,{glow:null,...mn(e),hide:!1,pulse:null})}onKey(e,t,a={}){return this.bridge.onKey(za(e,a),r=>Lr(t)({code:r.code,char:r.char,ctrl:r.ctrl,shift:r.shift,alt:r.alt,phase:r.phase,consumed:r.consumed===!0}))}}function Lr(n){return e=>{try{const t=n(e);t instanceof Promise&&t.catch(a=>It(a))}catch(t){It(t)}}}function It(n){console.error("phantom.flash.onKey: a listener failed",n)}function Ir(n,e){return e?Me(n):Array.isArray(n)?n.every(Me):n&&typeof n=="object"?Object.values(n).every(Me):Me(n)}function jt(n){try{return A(n),!0}catch{return!1}}const jr={avatarManager:"avatar.AvatarManager"},Dr="com.sbi.loader.LoaderCache.fetchCDNURL",zr=2e4;class Hr{channel;flash;hooks=new Map;constructor(e,t){this.channel=e.content??null,this.flash=t}get available(){return this.channel!==null}async replace(e,t){const a=this.reach(),r=Dt(e);await this.unhook(Ve(r));const i=await a.replace(r,Ge(t)),s=[],o=await this.pointClientAt(r,i.url);return o&&(this.hooks.set(Ve(r),o),s.push("client")),s.push("proxy"),{...i,how:s,stop:()=>this.restore(r).then(()=>{})}}async restore(e){const t=this.reach(),a=Dt(e);return await this.unhook(Ve(a)),t.restore(a)}replacements(){return this.reach().list()}onRequest(e){return this.reach().observe(e)}async replaceOnScreen(e,t,a={}){const{url:r,id:i}=await this.addressOf(t),{refreshFrames:s,...o}=a,h=await this.flash.overlay.image(r,{...o,replaces:s===void 0?e:{place:e,refreshFrames:s}});return{url:r,stop:async()=>{await h.remove(),i&&await this.reach().release(i)}}}async load(e,t={}){const a=this.flash.bridge,r=Ge(e),i=await a.construct("flash.display.Loader"),s=[];try{const o=await a.definition("flash.system.ApplicationDomain").at("currentDomain").get();s.push(()=>o.release());const h=await a.construct("flash.system.LoaderContext",!1,o);s.push(()=>h.release()),await h.at("allowCodeImport").set(t.allowCode===!0).catch(()=>{});const l=this.whenLoaded(i,t.timeoutMs??zr);if(r.kind==="data-url"){const u=await this.decodeInFlash(r.url);s.push(()=>u.release()),await i.at("loadBytes").call(u,h)}else{const u=await this.reach().hold(r);s.push(()=>this.reach().release(u.id)),await i.at("load").call(new _e("flash.net.URLRequest",[u.url]),h)}await l;const c=await i.at("content").get();if(!c)throw new Error("Nothing was loaded");return{content:c,loader:i,unload:async()=>{await i.at("unloadAndStop").call().catch(()=>{}),await c.release().catch(()=>{}),await i.release().catch(()=>{})}}}catch(o){throw await i.release().catch(()=>{}),o}finally{for(const o of s)await o().catch(()=>{})}}async pointClientAt(e,t){if(e.kind==="pattern")return null;const a=Wr(e.value);if(!a)return null;const{arg:r,equals:i,startsWith:s,any:o}=this.flash.rules,h=e.kind==="prefix"?s:i;try{return await this.flash.hook(Dr,{when:o(h(r("assetPath"),a),h(r("assetPath"),`/${a}`)),replaceReturn:t})}catch{return null}}async unhook(e){const t=this.hooks.get(e);t&&(this.hooks.delete(e),await t().catch(()=>{}))}async addressOf(e){const t=Ge(e);if(t.kind==="data-url")return{url:t.url,id:null};const a=await this.reach().hold(t);return{url:a.url,id:a.id}}async decodeInFlash(e){const t=e.indexOf(",");if(t===-1||e.slice(0,t).indexOf(";base64")===-1)throw new Error("Only base64 data: URLs can be loaded into the client");const a=await this.flash.bridge.definition("phantom.overlay.Base64").at("decode").call(e.slice(t+1));if(!a)throw new Error("The loader could not decode those bytes");return a}whenLoaded(e,t){const a=e.at("contentLoaderInfo");return new Promise((r,i)=>{const s=[],o=c=>{clearTimeout(h);for(const u of s.splice(0))u().catch(()=>{});c?i(c):r()},h=setTimeout(()=>o(new Error(`Flash did not load those bytes within ${t}ms`)),t),l=(c,u)=>a.listen(c,()=>o(u===null?null:new Error(u))).then(d=>s.push(d),d=>o(d));l("complete",null),l("ioError","Flash could not read those bytes"),l("securityError","Flash refused those bytes")})}reach(){if(!this.channel)throw new Error("This game cannot replace content: it was made without a content origin");return this.channel}}function Ve(n){return`${n.kind}:${n.value}`}function Wr(n){let e=n.charAt(0)==="/"?n.slice(1):n;const t=e.indexOf("?");t!==-1&&(e=e.slice(0,t)),e.slice(0,8)==="content/"&&(e=e.slice(8));const a=e.indexOf("/"),r=a===-1?e:e.slice(0,a);return a!==-1&&r.length>0&&Br(r)&&(e=e.slice(a+1)),e}function Br(n){for(const e of n)if(e<"0"||e>"9")return!1;return n.length>0}function Dt(n){const e=typeof n=="string"?{kind:"path",value:n}:n;if(!e||typeof e.value!="string"||!e.value)throw new TypeError("A replacement matches a path, a prefix or a pattern");const t=e.kind;if(t!=="path"&&t!=="prefix"&&t!=="pattern")throw new TypeError(`${t} is not path, prefix or pattern`);const a=e.value.charAt(0)==="/"?e.value:`/${e.value}`;return{kind:t,value:a}}function Ge(n){if(typeof n=="string")return n.slice(0,5).toLowerCase()==="data:"?{kind:"data-url",url:n}:{kind:"file",path:n};if(n instanceof ArrayBuffer)return{kind:"bytes",bytes:new Uint8Array(n)};if(ArrayBuffer.isView(n)){const e=n;return{kind:"bytes",bytes:new Uint8Array(e.buffer,e.byteOffset,e.byteLength)}}if(n&&typeof n=="object"){const e="contentType"in n&&n.contentType?n.contentType:null,t=e?{contentType:e}:{};if("bytes"in n){const a=n.bytes,r=a instanceof ArrayBuffer?new Uint8Array(a):a;if(!(r instanceof Uint8Array))throw new TypeError("bytes are a Uint8Array");return{kind:"bytes",bytes:r,...t}}if("dataUrl"in n&&typeof n.dataUrl=="string")return{kind:"data-url",url:n.dataUrl,...t};if("file"in n&&typeof n.file=="string")return{kind:"file",path:n.file,...t}}throw new TypeError("A source is bytes, a data: URL, or the path of a file on this computer")}const H={definitionByName:"GETDEFINITIONBYNAME",resourceStack:"com.sbi.loader.ResourceStack",guiManager:"gui.GuiManager",loadProgress:"loadProgress.LoadProgress",denEditor:"gui.DenEditor",fonts:"gui.Fonts",palette:"com.sbi.graphics.PaletteHelper",colorTable:"gui.ColorTable",avatarManager:"avatar.AvatarManager"},qr={message:"com.sbi.popup.SBMessage",ok:"com.sbi.popup.SBOkPopup",okCancel:"com.sbi.popup.SBOkCancelPopup",yesNo:"com.sbi.popup.SBYesNoPopup",titled:"com.sbi.popup.SBStandardTitlePopup",parchment:"com.sbi.popup.SBParchmentPopup"},ut={ink:1118483,line:3816e3,light:15790322,muted:10000543,accent:8141549,danger:15680580,size:12,cornerRadius:4},dt={ink:4403228,line:9071167,light:16643032,muted:9402972,accent:3123423,danger:13369344,size:11,cornerRadius:8},K={game:28,phantom:24},Ye=22,Ke=4,zt={top:12,left:10,right:10,bottom:12},Ht=4293980400,Ur=12e4,Vr=500;function Z(n){return(...e)=>{try{const t=n(...e);t instanceof Promise&&t.catch(X)}catch(t){X(t)}}}function X(n){console.error("phantom.ui: a listener failed",n)}function Xe(n,e){console.warn(`phantom.ui: the picture ${n} did not load: ${e}`)}const Se={game:110,phantom:96},ee=2,Wt=.5,Pe="_sans";function Gr(n,e=Pe){return{skin:n,font:e,...n==="game"?dt:ut}}const Yr={PopupSkin:"The plain popup frame: `ba` (its `t`, `m` and `b` slices) and `c`, its content box.",PopupContent:"What a plain popup shows: a `text` field the popup sizes itself around.",OkPopupSkin:"The frame of a popup with one button.",OkPopupContent:"An OK button (`okBtn`) and the `text` above it.",YesNoPopupSkin:"The frame of a popup with two buttons.",YesNoPopupContent:"Yes (`yesBtn`) and No (`noBtn`), and the `text` above them.",okCancelPopupContent:"OK (`okCancelBtn`) and Cancel (`cancelBtn`).",ConfirmSkin:"The frame the client asks you to confirm something in.",Tooltip:"The client's own tooltip (`gui.ToolTipPopup`): `txt`, and `l`, `m` and `r`.",HelpTxtBubble:"The bubble the client points at something it is explaining.",closeBtn:"The round close button in the corner of the client windows.",scrollbar2:"A scrollbar: `track`, `handle`, `topBtn` and `botBtn`.",BuddyListPopup:"The buddy list window's frame.",BuddyListContent:"What the buddy list shows inside that frame.",BD_AvatarEditorSkin:"The frame of the avatar editor's own dialog.",BD_AvatarEditorContent:"What that dialog shows.",DenEditorAsset:"The whole den editor, as the client builds it.",MySettings:"The settings window.",MainHud:"The whole HUD.",FreeNameBar:"The name bar above a player who is not a member.",memberNameBar:"The name bar above a member.",AnimsTitleBanner:"The banner the client puts a title in.",ChatBalloonAsset:"A chat balloon.",Cursor:"The client's own mouse cursor.",QuestPickupIcon:"The icon an adventure shows over something to pick up.",MinigameLobbySkin:"A minigame lobby's frame.",MinigameLobbyContent:"What a minigame lobby shows.",BroadcastPopupSkin:"The frame an announcement is shown in.",BroadcastPopupContent:"What an announcement shows.",DenLockPopupSkin:"The frame of the den's lock settings.",DenLockPopupContent:"What the den lock settings show.",ReportRulesPopupSkin:"The frame of the report window's rules.",ReportRulesPopupContent:"What the report rules show."},Kr=/^[A-Za-z_][A-Za-z0-9_]*$/;function Bt(n){if(!Kr.test(n))throw new TypeError(`"${n}" is not a symbol name: a symbol is named in letters, digits and underscores`);return n}const qt={gui:{className:H.guiManager,path:["guiLayer"]},hud:{className:H.guiManager,path:["mainHud"]},room:{className:H.avatarManager,path:["playerAvatarWorldView","parent"]},avatarEditor:{className:H.guiManager,path:["avatarEditor","avEditor"]},denEditor:{className:H.denEditor,path:["staticEditor"]}},Ut="stage",Vt={avatarEditor:{open:"gui.AvatarEditor.init",close:"gui.AvatarEditor.destroy",spot:"avatarEditor"},denEditor:{open:"gui.DenEditor.init",close:"gui.DenEditor.destroy",spot:"denEditor"},settings:{open:"gui.MySettings.init",close:"gui.MySettings.destroy",spot:null},buddyList:{open:"buddy.BuddyList.init",close:"buddy.BuddyList.destroy",spot:null},petCreator:{open:"gui.PetCreator.init",close:"gui.PetCreator.destroy",spot:null},achievements:{open:"gui.AchievementViewer.init",close:"gui.AchievementViewer.destroy",spot:null},bulletinBoard:{open:"gui.BulletinBoard.init",close:"gui.BulletinBoard.destroy",spot:null},playerSearch:{open:"gui.PlayerSearch.init",close:"gui.PlayerSearch.destroy",spot:null},recycle:{open:"gui.RecycleItems.init",close:"gui.RecycleItems.destroy",spot:null},trade:{open:"gui.TradeManager.init",close:"gui.TradeManager.destroy",spot:null},petInventory:{open:"gui.PetInventory.init",close:"gui.PetInventory.destroy",spot:null},reportPlayer:{open:"gui.ReportAPlayer.init",close:"gui.ReportAPlayer.destroy",spot:null},serverSelector:{open:"gui.ServerSelector.init",close:"gui.ServerSelector.destroy",spot:null}},Xr=5,Gt=18,Jr={game:180,phantom:170},Qr=10,Zr=4,fe=8,Je=16,ei=240,Qe=20,ti=48,ni=-80,Yt={x:12,y:-10},P=8,Ze=22,Kt={game:320,phantom:300},ai={game:190,phantom:150},Ee={x:60,y:90},ri={ok:0,yesNo:1,continueExit:2,continue:3};function ii(n,e,t={}){const a={slot:"layer"},r={slot:"callback"},i=t.name??null,s=qr[n];switch(n){case"message":return{className:s,args:[a,{slot:"skin"},e,!0,!0,t.modal??!1,t.draggable??!0,t.darken??!1,i]};case"ok":return{className:s,args:[a,e,t.darken??!0,null,!0,!0,t.modal??!0,t.draggable??!1,i]};case"yesNo":return{className:s,args:[a,e,t.darken??!0,r,null,!0,!0,t.modal??!0,t.draggable??!1,i]};case"okCancel":return{className:s,args:[a,e,t.darken??!0,r,null]};case"titled":return{className:s,args:[a,e,t.title??null,t.mediaId??370,r,!0,t.darken??!0]};case"parchment":return{className:s,args:[a,ri[t.buttons??"ok"],e,t.darken??!0,r,null]}}}function Xt(n){const e=Math.max(1,Math.floor(n.columns)),t=[];for(let a=0;a<Math.max(0,Math.floor(n.count));a++){const r=Math.floor(a/e),i=a%e;t.push({index:a,row:r,column:i,x:i*(n.tileWidth+n.gap),y:r*(n.tileHeight+n.gap),width:n.tileWidth,height:n.tileHeight})}return t}function si(n,e){const t=e.gap,a=n.length;if(a===0)return[];const r=(e.width+t)/a;return n.map((i,s)=>{const o=Math.round(s*r),h=s===a-1?e.width+t:Math.round((s+1)*r);return{index:s,value:i,x:o,width:Math.max(0,h-o-t)}})}function oi(n){const e=Math.max(0,n.contentHeight-n.viewHeight),t=Math.min(e,Math.max(0,n.offset)),a=n.minThumb??16,r=n.contentHeight>0?n.viewHeight/n.contentHeight:1,i=Math.max(Math.min(n.trackHeight,a),Math.min(n.trackHeight,Math.round(n.trackHeight*r))),s=n.trackHeight-i;return{offset:t,max:e,thumbY:e>0?Math.round(t/e*s):0,thumbHeight:i}}function li(n,e,t){const a=Math.max(1,Math.round(n-e-t+1)),r=-Math.floor(a/2);return{middle:a,middleY:r,topY:r-e,bottomY:r+a-1}}function ci(n,e){const t=e?{top:e.y,left:e.x,right:n.width-e.x-e.width,bottom:n.height-e.y-e.height}:null,a=(s,o)=>{const h=t==null?void 0:t[s];return h!==void 0&&Number.isFinite(h)&&h>=2&&h<=o/4?Math.ceil(h):zt[s]},r={top:a("top",n.height),left:a("left",n.width),right:a("right",n.width),bottom:a("bottom",n.height)},i={x:r.left+Ke,y:r.top,width:Math.max(0,Math.floor(n.width-r.left-r.right-2*Ke)),height:Math.max(Ye,Math.floor(n.height-r.top-r.bottom-Ke))};return{edge:r,measured:t!==null&&Object.keys(zt).every(s=>r[s]===Math.ceil(t[s])),panel:i,titleHeight:Ye,body:{width:i.width,height:i.height-Ye}}}class hi{bridge;flash;drawn=new Set;popups=new Set;tags=new Map;symbolMaker=null;gameFont=null;defaultSkin="phantom";known={art:!1,palettes:!1};readyTimeoutMs=Ur;popup;constructor(e,t){this.bridge=e.flash,this.flash=t,this.popup=new ui((a,r,i,s,o)=>this.openPopup(a,r,i,s,o),()=>this.clear())}get skin(){return this.defaultSkin}set skin(e){this.defaultSkin=e}async status(){const[e,t]=await Promise.all([this.artLoaded(),this.palettesLoaded()]);return{art:e,palettes:t}}async ready(e=this.readyTimeoutMs){const t=await this.waitFor({art:!0,palettes:!0},e);if(t.art&&t.palettes)return t;const a=[t.art?null:"its library art",t.palettes?null:"its colour palettes"].filter(Boolean);throw new Error(`The game has not loaded ${a.join(" or ")} yet: waited ${Math.round(e/1e3)} seconds`)}async theme(e){const t=e??this.defaultSkin;return Gr(t,t==="game"?await this.clientFont():Pe)}symbols(){return Object.entries(Yr)}async hasSymbol(e){const t=Bt(e);try{return await this.bridge.definition(H.resourceStack).at("hudAssetsLoaderInfo","applicationDomain","hasDefinition").call(t)===!0}catch{return!1}}async symbol(e,t={}){const a=Bt(e);await this.waitFor({art:!0});const r=await this.flash.overlay.group({x:t.x??0,y:t.y??0,...t.scale===void 0?{}:{scale:t.scale},...t.visible===void 0?{}:{visible:t.visible}});let i=null;try{i=await(await this.maker()).at("apply").call(null,[a,t.localize===!0]),await(await this.nodeObject(r)).at("addChild").call(i),await this.adopt(r,{...t.parent===void 0||t.parent===null?{}:{parent:C(t.parent)},...t.host===void 0?{}:{host:t.host===null?null:this.placeOf(t.host)},...t.replaces===void 0?{}:{replaces:t.replaces===null?null:this.placeOf(t.replaces)}})}catch(c){throw await r.remove(),i&&await this.bridge.release([i]).catch(()=>{}),c}const s=i,o=s.at(),h=new Set;return this.widget(r,t.skin??this.defaultSkin,{name:a,object:s,on:async(c,u)=>{const d=await o.listen(Jt[c],()=>u()),w=async()=>{h.delete(w),await d()};return h.add(w),w},size:async()=>({width:await s.at("width").get()??0,height:await s.at("height").get()??0})},async()=>{for(const c of[...h])await c().catch(()=>{});await this.bridge.release([s]).catch(()=>{})})}async window(e={}){const t=e.skin??this.defaultSkin,a=t==="game",r=a&&(await this.waitFor({art:!0})).art,i=await this.theme(t),s={width:e.width??280,height:e.height??200},o={x:e.x??40,y:e.y??40},h=a?30:24,l=await this.flash.overlay.panel({x:o.x,y:o.y,width:s.width,height:s.height,title:e.title??"",titleHeight:h,draggable:e.draggable!==!1,resizable:e.resizable===!0&&!a,cornerRadius:i.cornerRadius,fill:a?{color:i.light,alpha:0}:{color:i.ink,alpha:.94},stroke:a?null:i.line,titleFill:i.line,titleFont:{family:i.font,size:i.size+1,bold:!0,color:i.light},visible:!1});let c=null;if(r)try{c=await this.dressWindow(l,s.height)}catch(p){console.warn(`phantom.ui.window: the popup frame could not be drawn: ${Y(p)}`)}else a&&console.warn(`phantom.ui.window: the game has not loaded its popup art after ${Math.round(this.readyTimeoutMs/1e3)} seconds, so "${e.title??""}" is drawn in the game skin's colours instead`);const u=c?{x:c.layout.panel.x,y:c.layout.panel.y}:{x:0,y:0};if(c?await l.update({x:o.x+u.x,y:o.y+u.y,width:c.layout.panel.width,height:c.layout.panel.height,titleHeight:c.layout.titleHeight,titleFill:{color:i.line,alpha:.004},titleFont:{family:i.font,size:i.size+1,bold:!0,color:i.ink}}):a&&await l.update({fill:{color:dt.light,alpha:.96},stroke:{color:dt.line,width:2}}),e.parent)try{await this.adopt(l,{parent:C(e.parent)})}catch(p){throw await l.remove(),c&&await this.bridge.release(c.held).catch(()=>{}),p}const d=c?{width:c.width,height:c.height,bodyWidth:c.layout.body.width,bodyHeight:c.layout.body.height}:{...s,bodyWidth:s.width,bodyHeight:Math.max(0,s.height-h)},w=new Set,g=[],f=this.widget(l,t,{body:l,...d,framed:c!==null,move:(p,y)=>l.update({x:p+u.x,y:y+u.y}),setTitle:p=>l.update({title:p}),onClose:p=>(w.add(p),async()=>{w.delete(p)}),onMove:p=>{const y=l.on("move",({x:b,y:k})=>p({x:b-u.x,y:k-u.y}));return async()=>{await y()}}},async()=>{for(const p of g.splice(0))await p().catch(()=>{});c&&await this.bridge.release(c.held).catch(()=>{})}),m=()=>{f().then(()=>w.forEach(p=>p()))};if(e.closable!==!1&&(c!=null&&c.close)){const p=await c.close.at().listen(Jt.down,m);g.push(async()=>{await p()})}else e.closable!==!1&&(await this.flash.overlay.button("x",{parent:l,x:d.bodyWidth-(a?26:24),y:2,width:18,height:16,cornerRadius:i.cornerRadius,fill:i.line,hoverFill:{color:i.danger,alpha:.8},font:{family:i.font,size:i.size,bold:!0,color:i.light}})).on("click",m);return e.visible!==!1&&await l.show(),f}async button(e,t={}){const a=t.skin??this.defaultSkin,r=await this.theme(a),i=this.box(t,{width:Se[a],height:K[a]}),s=i.width??Se[a],o=i.height??K[a],h=t.image===void 0?null:await this.flash.overlay.group({x:i.x??0,y:i.y??0,...i.parent?{parent:i.parent}:{},...i.visible===void 0?{}:{visible:i.visible}});let l=e,c=h===null||t.imageOnly!==!0,u=t.disabled===!0;const d=await this.flash.overlay.button(c?l:"",{...h===null?i:{x:0,y:0,width:s,height:o,parent:h},...we(r,t.primary===!0),cornerRadius:r.cornerRadius,...t.disabled===void 0?{}:{disabled:t.disabled},font:{family:r.font,size:r.size,bold:!0,color:t.primary===!0||a==="phantom"?r.light:r.ink}}),w=o-ee*2,g=t.imageOnly===!0?{width:s-ee*2,height:w}:{width:w,height:w};let f=null;const m=async()=>{c||(c=!0,await d.setLabel(l))},p=async y=>{if(f){await f.update({url:y});return}f=await this.picture(y,{parent:h,x:ee,y:ee,...g,...u?{alpha:Wt}:{}},b=>{Xe("on a button",b),m().catch(X)})};return t.image!==void 0&&await p(t.image),this.widget(h??d,a,{label:()=>l,setLabel:async y=>{l=y,await d.setLabel(c?y:"")},setDisabled:async y=>{u=y,await d.setDisabled(y),f&&await f.update({alpha:y?Wt:1})},setImage:async y=>{if(h===null)throw new TypeError("This button was drawn without a picture, so there is nowhere to put one: give it `image` when it is drawn");if(y===null){const b=f;f=null,await(b==null?void 0:b.remove()),await m();return}c=t.imageOnly!==!0,await d.setLabel(c?l:""),await p(y)},onClick:y=>{const b=d.on("click",Z(y));return async()=>{await b()}}})}async label(e,t={}){const a=t.skin??this.defaultSkin,r=await this.theme(a),i=await this.flash.overlay.text(e,{x:t.x??0,y:t.y??0,...t.parent?{parent:C(t.parent)}:{},...t.visible===void 0?{}:{visible:t.visible},centered:t.centered===!0,font:{family:r.font,size:t.heading===!0?r.size+3:r.size,bold:t.heading===!0,color:t.muted===!0?r.muted:a==="game"?r.ink:r.light},...t.background===!0?{background:a==="game"?{color:r.light,alpha:.9}:{color:r.ink,alpha:.7},padding:4}:{}});return this.widget(i,a,{setText:s=>i.update({text:s})})}async input(e={}){const t=e.skin??this.defaultSkin,a=await this.theme(t),r=await this.flash.overlay.input({...this.box(e,{width:200,height:K[t]}),...e.value===void 0?{}:{value:e.value},...e.placeholder===void 0?{}:{placeholder:e.placeholder},...e.maxLength===void 0?{}:{maxLength:e.maxLength},...e.multiline===void 0?{}:{multiline:e.multiline},...e.disabled===void 0?{}:{disabled:e.disabled},fill:t==="game"?a.light:16777215,stroke:a.line,cornerRadius:a.cornerRadius,font:{family:a.font,size:a.size,color:t==="game"?a.ink:1120295}});return this.widget(r,t,{value:()=>r.value(),setValue:i=>r.setValue(i),focus:()=>r.focus(),onChange:i=>{const s=r.on("change",Z(i));return async()=>{await s()}},onSubmit:i=>{const s=r.on("submit",Z(i));return async()=>{await s()}}})}async checkbox(e,t={}){const a=t.skin??this.defaultSkin,r=await this.theme(a),i=await this.flash.overlay.group({x:t.x??0,y:t.y??0,...t.parent?{parent:C(t.parent)}:{},...t.visible===void 0?{}:{visible:t.visible}});let s=t.checked===!0;const o=await this.flash.overlay.button(s?"x":"",{parent:i,width:14,height:14,cornerRadius:Math.min(3,r.cornerRadius),fill:a==="game"?r.light:{color:r.ink,alpha:.9},hoverFill:a==="game"?16777215:{color:r.line,alpha:.9},stroke:r.line,font:{family:r.font,size:r.size,bold:!0,color:r.accent}});await this.flash.overlay.text(e,{parent:i,x:20,y:0,font:{family:r.font,size:r.size,color:a==="game"?r.ink:r.light}});const h=new Set,l=async c=>{s=c,await o.setLabel(c?"x":"")};return o.on("click",()=>{l(!s).then(()=>h.forEach(c=>c(s)))}),this.widget(i,a,{checked:()=>s,setChecked:l,onChange:c=>(h.add(c),async()=>{h.delete(c)})})}async dropdown(e){var t;const a=e.skin??this.defaultSkin,r=await this.theme(a),i=e.width??140,s=e.height??K[a],o=await this.flash.overlay.group({x:e.x??0,y:e.y??0,...e.parent?{parent:C(e.parent)}:{},...e.visible===void 0?{}:{visible:e.visible}});let h=[...e.choices],l=e.value??((t=h[0])==null?void 0:t.value)??null;const c=f=>{var m;return((m=h.find(p=>p.value===f))==null?void 0:m.label)??e.placeholder??"Choose..."},u=await this.flash.overlay.button(c(l),{parent:o,width:i,height:s,cornerRadius:r.cornerRadius,...we(r,!1),font:{family:r.font,size:r.size,color:a==="game"?r.ink:r.light}}),d=await this.flash.overlay.list({parent:o,y:s+2,width:i,height:Math.min(140,Math.max(20,h.length*16+8)),visible:!1,fill:a==="game"?r.light:{color:r.ink,alpha:.96},stroke:r.line,cornerRadius:r.cornerRadius,rows:h.map(f=>f.label),font:{family:r.font,size:r.size,color:a==="game"?r.ink:r.light}});let w=!1;const g=new Set;return u.on("click",()=>{w=!w,w?d.show():d.hide()}),d.on("row",f=>{const m=h[f];w=!1,d.hide(),m&&(l=m.value,u.setLabel(m.label).then(()=>g.forEach(p=>p(m.value))))}),this.widget(o,a,{value:()=>l,setValue:async f=>{l=f,await u.setLabel(c(f))},setChoices:async f=>{h=[...f],await d.setRows(h.map(m=>m.label)),await u.setLabel(c(l))},onChange:f=>(g.add(f),async()=>{g.delete(f)})})}async tabs(e){var t;const a=e.skin??this.defaultSkin,r=await this.theme(a),i=e.width??260,s=e.tabHeight??22,o=await this.flash.overlay.group({x:e.x??0,y:e.y??0,...e.parent?{parent:C(e.parent)}:{},...e.visible===void 0?{}:{visible:e.visible}}),h=si(e.tabs.map(g=>g.value),{width:i,gap:2});let l=e.value??((t=e.tabs[0])==null?void 0:t.value)??"";const c=new Map,u=new Map,d=new Set;for(const g of h){const f=e.tabs[g.index];u.set(f.value,await this.flash.overlay.button(f.label,{parent:o,x:g.x,width:g.width,height:s,cornerRadius:r.cornerRadius,...we(r,f.value===l),font:{family:r.font,size:r.size,bold:f.value===l,color:f.value===l||a==="phantom"?r.light:r.ink}})),c.set(f.value,await this.flash.overlay.group({parent:o,y:s+4,visible:f.value===l}))}const w=async g=>{if(c.has(g)){l=g;for(const[f,m]of c)await(f===g?m.show():m.hide());for(const[f,m]of u)await m.update({...we(r,f===g),font:{family:r.font,size:r.size,bold:f===g,color:f===g||a==="phantom"?r.light:r.ink}})}};for(const[g,f]of u)f.on("click",()=>{w(g).then(()=>d.forEach(m=>m(g)))});return this.widget(o,a,{current:()=>l,select:w,body:g=>{const f=c.get(g);if(!f)throw new TypeError(`There is no tab called "${g}"`);return f},onSelect:g=>(d.add(g),async()=>{d.delete(g)})})}async list(e={}){const t=e.skin??this.defaultSkin,a=await this.theme(t),r=await this.flash.overlay.list({...this.box(e,{width:240,height:160}),...e.rows===void 0?{}:{rows:[...e.rows]},...e.maxRows===void 0?{}:{maxRows:e.maxRows},fill:t==="game"?a.light:{color:a.ink,alpha:.85},stroke:a.line,cornerRadius:a.cornerRadius,font:{family:a.font,size:a.size,color:t==="game"?a.ink:a.light}});return this.widget(r,t,{setRows:i=>r.setRows([...i]),append:(...i)=>r.append(...i),onRow:i=>{const s=r.on("row",Z(i));return async()=>{await s()}}})}async grid(e){const t=e.skin??this.defaultSkin,a=await this.theme(t),r={columns:e.columns??4,tileWidth:e.tileWidth??48,tileHeight:e.tileHeight??48,gap:e.gap??4},i=await this.flash.overlay.group({x:e.x??0,y:e.y??0,...e.parent?{parent:C(e.parent)}:{},...e.visible===void 0?{}:{visible:e.visible}}),s=new Set,o=[],h=async l=>{for(const u of o.splice(0))await u.remove();const c=Xt({count:l.length,...r});for(const u of c){const d=l[u.index],w=await this.flash.overlay.button(d.label??"",{parent:i,x:u.x,y:u.y,width:u.width,height:u.height,cornerRadius:a.cornerRadius,fill:d.color??(t==="game"?a.light:{color:a.ink,alpha:.9}),hoverFill:d.color??(t==="game"?16777215:a.line),pressedFill:d.color??a.accent,stroke:a.line,...d.disabled===void 0?{}:{disabled:d.disabled},font:{family:a.font,size:a.size-2,color:t==="game"?a.ink:a.light}});w.on("click",()=>s.forEach(g=>g(d.value,u.index))),o.push(w),d.image!==void 0&&o.push(await this.picture(d.image,{parent:i,x:u.x+ee,y:u.y+ee,width:u.width-ee*2,height:u.height-ee*2},g=>Xe(`on the grid tile ${d.value}`,g)))}};return await h(e.items),this.widget(i,t,{setItems:h,onSelect:l=>(s.add(l),async()=>{s.delete(l)})})}async image(e,t={}){const a=t.skin??this.defaultSkin,r=await this.theme(a),i=await this.flash.overlay.group({x:t.x??0,y:t.y??0,...t.parent?{parent:C(t.parent)}:{},...t.visible===void 0?{}:{visible:t.visible}}),s=new Set;let o=e,h=null,l=!1;const c=async()=>{if(l)return;l=!0;const d=t.width??K[a],w=t.height??K[a],g=await this.flash.overlay.group({parent:i,...t.centered===!0?{x:-Math.round(d/2),y:-Math.round(w/2)}:{}});h=g,await this.flash.overlay.rect({parent:g,width:d,height:w,cornerRadius:r.cornerRadius,fill:a==="game"?{color:r.light,alpha:.6}:{color:r.ink,alpha:.6},stroke:r.line}),!(t.alt===void 0||t.alt==="")&&await this.flash.overlay.text(t.alt,{parent:g,x:Math.round(d/2),y:Math.round(w/2),centered:!0,font:{family:r.font,size:r.size-1,color:r.muted}})},u=await this.picture(o,{parent:i,...t.width===void 0?{}:{width:t.width},...t.height===void 0?{}:{height:t.height},...t.centered===void 0?{}:{centered:t.centered},...t.alpha===void 0?{}:{alpha:t.alpha}},d=>{Xe(t.alt===void 0?"drawn on its own":`of ${t.alt}`,d),c().catch(X),s.forEach(w=>w(d))});return this.widget(i,a,{source:()=>o,setSource:async d=>{o=d;const w=h;h=null,l=!1,await(w==null?void 0:w.remove()),await u.update({url:d})},onFailed:d=>{const w=Z(d);return s.add(w),async()=>{s.delete(w)}}})}async scroll(e={}){const t=e.skin??this.defaultSkin,a=await this.theme(t),r=e.width??220,i=e.height??120,s=e.step??32,o=await this.flash.overlay.panel({x:e.x??0,y:e.y??0,width:r,height:i,titleHeight:0,draggable:!1,cornerRadius:a.cornerRadius,fill:t==="game"?{color:a.light,alpha:.9}:{color:a.ink,alpha:.85},stroke:a.line,...e.parent?{parent:C(e.parent)}:{},...e.visible===void 0?{}:{visible:e.visible}}),h=await this.flash.overlay.group({parent:o,x:0,y:0});let l=e.contentHeight??i,c=0;const u=async d=>{c=oi({contentHeight:l,viewHeight:i,offset:d,trackHeight:i}).offset,await h.update({y:-c})};for(const[d,w,g]of[["^",-s,0],["v",s,i-16]])(await this.flash.overlay.button(d,{parent:o,x:r-16,y:g,width:14,height:14,cornerRadius:Math.min(3,a.cornerRadius),...we(a,!1),font:{family:a.font,size:a.size-2,bold:!0,color:t==="game"?a.ink:a.light}})).on("click",()=>{u(c+w)});return this.widget(o,t,{body:h,offset:()=>c,scrollTo:u,setContentHeight:async d=>{l=d,await u(c)}})}async tooltip(e={}){const t=await this.bubble(e);return e.target&&this.explain(t,C(e.target)),t}async bubble(e){const t=e.skin??this.defaultSkin,a=e.text??"";if(t==="game"){const s=await this.clientTooltip(a,e);if(s)return s}const r=await this.theme(t),i=await this.flash.overlay.text(a,{x:e.x??0,y:e.y??0,visible:e.visible===!0,...e.parent?{parent:C(e.parent)}:{},background:t==="game"?{color:r.light,alpha:.95}:{color:r.ink,alpha:.92},padding:4,font:{family:r.font,size:r.size,color:t==="game"?r.ink:r.light}});return this.widget(i,t,{setText:s=>i.update({text:s}),showAt:async(s,o)=>{await i.update({x:s,y:o,visible:!0})}})}explain(e,t){const a=t.on("over",({x:s,y:o})=>{e.showAt(s+12,o-10).catch(X)}),r=t.on("out",()=>{e.hide().catch(X)}),i=t.onRemoved(()=>{e.remove().catch(X)});e.node.onRemoved(()=>{i(),a().catch(()=>{}),r().catch(()=>{})})}async progress(e={}){const t=e.skin??this.defaultSkin,a=await this.theme(t),r=e.width??200,i=e.height??16,s=await this.flash.overlay.group({x:e.x??0,y:e.y??0,...e.parent?{parent:C(e.parent)}:{},...e.visible===void 0?{}:{visible:e.visible}});await this.flash.overlay.rect({parent:s,width:r,height:i,cornerRadius:a.cornerRadius,fill:t==="game"?a.light:{color:a.ink,alpha:.9},stroke:a.line});let o=Qt(e.value??0);const h=await this.flash.overlay.rect({parent:s,width:Math.round(r*o),height:i,cornerRadius:a.cornerRadius,fill:a.accent}),l=await this.flash.overlay.text(e.label??"",{parent:s,x:Math.round(r/2),y:Math.round(i/2),centered:!0,font:{family:a.font,size:a.size-1,bold:!0,color:t==="game"?a.ink:a.light}});return this.widget(s,t,{value:()=>o,setValue:async c=>{o=Qt(c),await h.update({width:Math.round(r*o)})},setLabel:c=>l.update({text:c})})}async colors(e={}){const t=e.skin??this.defaultSkin,a=e.columns??10,r=e.swatchWidth??24,i=e.swatchHeight??30,{values:s,indexes:o}=await this.palette(e.palette??1),h=new Set;let l=e.value??o[0]??0;const c=w=>{l=w,h.forEach(g=>g(w,s[w]??0))},u=Math.max(1,Math.ceil(o.length/a)),d=t==="game"?await this.clientColorTable({columns:a,rows:u,width:a*r,height:u*i,values:s,indexes:o,current:l,options:e,tell:c}):await this.swatchGrid({columns:a,swatchWidth:r,swatchHeight:i,values:s,indexes:o,current:l,options:e,tell:c});return this.widget(d,t,{value:()=>l,onPick:w=>(h.add(w),async()=>{h.delete(w)})})}async paletteValues(e="game"){const{values:t,indexes:a}=await this.palette(e);return a.map(r=>t[r]??0)}prompt(e,t={}){let a=()=>{};const r=new Promise(l=>{a=l});let i=!1,s=null;const o=async l=>{if(i)return;i=!0,this.popups.delete(h);const c=s;s=null,c&&await c().catch(()=>{}),a(l)},h=()=>o(null);return this.popups.add(h),(async()=>{const l=t.skin??this.defaultSkin,c=t.width??Kt[l],u=await this.window({skin:l,title:t.title??"",x:t.x??Ee.x,y:t.y??Ee.y,width:c,height:ai[l],closable:!0}),d=u.body,w=u.bodyWidth-2*P;await this.label(e,{skin:l,parent:d,x:P,y:P});const g=await this.input({skin:l,parent:d,x:P,y:P+Ze,width:w,...t.value===void 0?{}:{value:t.value},...t.placeholder===void 0?{}:{placeholder:t.placeholder},...t.maxLength===void 0?{}:{maxLength:t.maxLength}}),f={width:Math.min(Se[l],Math.floor((w-P)/2))},m=u.bodyHeight-P-K[l],p=await this.button(t.cancelLabel??"Cancel",{skin:l,parent:d,x:P,y:m,width:f.width}),y=await this.button(t.okLabel??"OK",{skin:l,parent:d,x:u.bodyWidth-P-f.width,y:m,width:f.width,primary:!0});if(s=async()=>{await u(),await this.flash.overlay.focusGame().catch(()=>{})},i){const b=s;s=null,await b();return}g.onSubmit(b=>{o(b)}),y.onClick(()=>{o(g.value())}),p.onClick(()=>{o(null)}),u.onClose(()=>{o(null)}),await g.focus()})().catch(l=>{console.error(`phantom.ui.prompt could not be drawn: ${Y(l)}`),o(null)}),Object.assign(r,{close:h})}choose(e,t,a={}){const r=t.map(u=>typeof u=="string"?{value:u,label:u}:u);let i=()=>{};const s=new Promise(u=>{i=u});let o=!1,h=null;const l=async u=>{if(o)return;o=!0,this.popups.delete(c);const d=h;h=null,d&&await d().catch(()=>{}),i(u)},c=()=>l(null);return this.popups.add(c),(async()=>{const u=a.skin??this.defaultSkin,d=a.width??Kt[u],w=Math.max(1,a.rows??Xr),g=Math.min(r.length||1,w)*Gt+2*P,f=await this.window({skin:u,title:a.title??"",x:a.x??Ee.x,y:a.y??Ee.y,width:d,height:P*4+Ze+g+K[u],closable:!0}),m=f.body,p=f.bodyWidth-2*P;await this.label(e,{skin:u,parent:m,x:P,y:P});const y=await this.list({skin:u,parent:m,x:P,y:P+Ze,width:p,height:g,rows:r.map(M=>M.label)}),b={width:Math.min(Se[u],Math.floor((p-P)/2))},k=await this.button(a.cancelLabel??"Cancel",{skin:u,parent:m,x:f.bodyWidth-P-b.width,y:f.bodyHeight-P-K[u],width:b.width});if(h=async()=>{await f()},o){const M=h;h=null,await M();return}y.onRow(M=>{var O;l(((O=r[M])==null?void 0:O.value)??null)}),k.onClick(()=>{l(null)}),f.onClose(()=>{l(null)})})().catch(u=>{console.error(`phantom.ui.choose could not be drawn: ${Y(u)}`),l(null)}),Object.assign(s,{close:c})}menu(e,t={}){const a=e.map(c=>c==="-"?{label:"",value:null,disabled:!0,divider:!0,onSelect:void 0}:{label:c.label,value:c.value??c.label,disabled:c.disabled===!0,divider:!1,onSelect:c.onSelect});let r=()=>{};const i=new Promise(c=>{r=c});let s=!1,o=null;const h=async c=>{if(s)return;s=!0,this.popups.delete(l);const u=o;o=null,u&&await u().catch(()=>{}),r(c)},l=()=>h(null);return this.popups.add(l),(async()=>{const c=t.skin??this.defaultSkin,u=await this.theme(c),d=await this.stageSize(),w=Math.min(t.width??Jr[c],d.width),g=Math.min(Math.max(a.length,1),Math.max(1,t.rows??Qr)),f=Math.min(g*Gt+2*Zr,d.height),m=t.x===void 0&&t.y===void 0?await this.mouse():{x:t.x??0,y:t.y??0},p=m.x+w>d.width?Math.max(0,m.x-w):m.x,y=m.y+f>d.height?Math.max(0,m.y-f):m.y,b=await this.flash.overlay.rect({x:0,y:0,width:d.width,height:d.height,fill:{color:0,alpha:.01}});b.on("click",()=>{h(null)});const k=await this.list({skin:c,x:p,y,width:w,height:f,rows:a.map(M=>M.divider?[{text:"—".repeat(Math.max(4,Math.floor(w/9))),color:u.muted}]:M.disabled?[{text:M.label,color:u.muted}]:M.label)});if(o=async()=>{await k().catch(()=>{}),await b().catch(()=>{})},s){const M=o;o=null,await M();return}k.onRow(M=>{var O;const E=a[M];if(!(!E||E.divider||E.disabled||E.value===null)){try{(O=E.onSelect)==null||O.call(E)}catch(I){console.error(`A menu line's onSelect failed: ${Y(I)}`)}h(E.value)}})})().catch(c=>{console.error(`phantom.ui.menu could not be drawn: ${Y(c)}`),h(null)}),Object.assign(i,{close:l})}async menuButton(e,t,a={}){const{menu:r,...i}=a,s=await this.button(e,i),o=new Set;let h=t,l=!1;s.onClick(()=>{l||(l=!0,(async()=>{try{const u=typeof h=="function"?await h():h,d=await this.menu(u,{...a.skin?{skin:a.skin}:{},...r??{}});if(d===null)return;for(const w of[...o])try{w(d)}catch(g){console.error(`A menu button's onSelect failed: ${Y(g)}`)}}catch(u){console.error(`phantom.ui.menuButton could not open its menu: ${Y(u)}`)}finally{l=!1}})())});const c={onSelect:u=>(o.add(u),async()=>{o.delete(u)}),setItems:u=>{h=u}};for(const[u,d]of Object.entries(c))Object.defineProperty(s,u,{value:d,enumerable:!0,configurable:!0});return s}async notice(e,t={}){const a=t.skin??this.defaultSkin,r=await this.theme(a),i=t.seconds??6,s=t.width??ei,o=Math.max(Je,(a==="game"?s-ti:s)-2*fe),h=tt(e,en(o,r.size)),l=await this.stageSize(),c={x:t.x??(l.width?l.width-s-Qe:Qe),y:t.y??Qe},u=await this.window({skin:a,title:t.title??"",x:c.x,y:c.y,width:s,height:2*fe+(h.length+1)*Je+(a==="game"?30:24),closable:t.closable!==!1,...t.draggable===void 0?{}:{draggable:t.draggable}}),d=Math.max(Je,Math.min(o,u.bodyWidth-2*fe)),w=en(d,r.size),g=await this.label(tt(e,w).join(`
|
|
2
|
+
`),{skin:a,parent:u.body,x:fe,y:fe}),f=new Set;let m=!1;const p=i>0?setTimeout(()=>{u().catch(()=>{})},i*1e3):null,y=()=>{if(!m){m=!0,p&&clearTimeout(p);for(const b of[...f])Z(b)()}};return u.onClose(y),u.node.onRemoved(y),this.widget(u.node,a,{setText:async b=>{await g.setText(tt(b,w).join(`
|
|
3
|
+
`))},onClose:b=>(f.add(b),async()=>{f.delete(b)})},async()=>y())}async tag(e,t,a={}){const r=a.skin??this.defaultSkin,i=await this.theme(r),s=await this.anchorOf(e);if(!s)throw new TypeError(typeof e=="number"?`No player with user id ${e} is in the room, so there is nothing to tag`:"Expected a player id, something from phantom.flash.entities, or a place in the client");const o=a.key??(typeof e=="number"?`player:${e}`:null),h=o?this.tags.get(o):void 0;h&&await h().catch(()=>{});const l=await this.flash.overlay.text(t,{anchor:{place:s,x:a.offsetX??0,y:a.offsetY??(typeof e=="number"?ni:0)},centered:!0,font:{family:i.font,size:a.heading===!0?i.size+3:i.size,bold:a.heading===!0,color:a.colour??(r==="game"?i.ink:i.light)},...a.background===!1?{outline:0}:{background:r==="game"?{color:i.light,alpha:.9}:{color:i.ink,alpha:.8},padding:4}}),c=a.seconds&&a.seconds>0?setTimeout(()=>{l.remove().catch(()=>{})},a.seconds*1e3):null,u=this.widget(l,r,{setText:d=>l.update({text:d})},async()=>{c&&clearTimeout(c),o&&this.tags.get(o)===u&&this.tags.delete(o)});return o&&this.tags.set(o,u),u}async tipOn(e,t,a={}){const r=a.skin??this.defaultSkin,i=await this.tooltip({skin:r,text:typeof t=="string"?t:""}),s=this.piece(e),o={x:a.offsetX??Yt.x,y:a.offsetY??Yt.y},h=async d=>{typeof t!="string"&&await i.setText(await t());const w=gi(d)??await this.mouse();await i.showAt(w.x+o.x,w.y+o.y)},l=await s.on("rollOver",d=>{h(d).catch(w=>{console.error(`phantom.ui.tipOn could not show the tooltip: ${Y(w)}`)})}),c=await s.on("rollOut",()=>{i.hide().catch(()=>{})});let u=!1;return async()=>{u||(u=!0,await l().catch(()=>{}),await c().catch(()=>{}),await i.remove().catch(()=>{}))}}async stageSize(){const e=this.bridge.stage(),[t,a]=await Promise.all([e.at("stageWidth").get().catch(()=>null),e.at("stageHeight").get().catch(()=>null)]);return{width:Oe(t),height:Oe(a)}}onStageResize(e){let t=!0,a=null;return(async()=>{const i=await this.bridge.stage().listen("resize",()=>{this.stageSize().then(s=>Z(e)(s)).catch(()=>{})});if(!t){await i();return}a=i})().catch(i=>{console.error(`phantom.ui.onStageResize could not hear the stage: ${Y(i)}`)}),()=>{t=!1;const i=a;a=null,i&&i().catch(()=>{})}}places(){const e=Object.keys(qt);return[Ut,...e,...fi]}place(e){if(e===Ut)return this.bridge.stage();const t=qt[e];return t?this.bridge.definition(t.className).at(...t.path):this.bridge.definition(H.guiManager).at("mainHud",e)}async attach(e,t){const a=C(t);return await this.flash.overlay.attach(this.placeOf(e),a),()=>a.remove()}async replace(e,t){const a=C(t);return await this.flash.overlay.replace(this.placeOf(e),a),()=>a.remove()}async hide(e){const t=await this.flash.hide(this.placeOf(e)),a=async()=>{this.drawn.delete(a),await t()};return this.drawn.add(a),a}piece(e,...t){return this.pieceOf(this.placeOf(e),t)}async feed(e,t,a={}){return typeof t=="function"?this.deferredFeed(e,t,a):this.insideFeed(e,t,a)}async insideFeed(e,t,a){if(!Object.keys(t).length)throw new TypeError(`A feed of ${e} names no argument to change`);let r=null,i=0;const s=await this.flash.hook(e,{phase:"enter",capture:{args:!0},replaceArgs:t,...a.when===void 0?{}:{when:a.when},...a.first===void 0?{}:{first:a.first},...a.every===void 0?{}:{every:a.every},...a.perFrame===void 0?{}:{perFrame:a.perFrame}},o=>{i+=1,r={method:e,call:o.call,args:[...o.argList],named:{...o.args},on:this.pieceOf(this.bridge.stage(),[])}});return this.feedOf(e,!0,s,()=>i,()=>r)}async deferredFeed(e,t,a){if(a.deferred!==!0)throw new TypeError(`A feed of ${e} was given a function, which cannot run inside the call: the client's method is skipped and run again once the function answers. A builder whose result the client uses in the same breath comes up empty that way. Give the arguments themselves to change them inside the call, or set "deferred" to say the waiting is understood.`);let r=null,i=0;const s=async l=>{i+=1;const c={method:e,call:l.call,args:[...l.argList],named:{...l.args},on:this.pieceOf(ae(l.self)??this.bridge.stage(),[])};r=c;const u=await t(c);if(!u){await l.original();return}const d=[...c.args];for(const[w,g]of Object.entries(u)){const f=/^\d+$/.test(w)?Number(w):l.hook.parameters.findIndex(m=>m.name===w);if(f<0||f>=d.length){const m=l.hook.parameters.map(p=>p.name).join(", ");throw new TypeError(`${e} has no argument "${w}" (its arguments: ${m})`)}d[f]=g}await l.original(...d)},o={};a.when!==void 0&&(o.when=a.when),a.first!==void 0&&(o.first=a.first),a.every!==void 0&&(o.every=a.every),a.sequential!==void 0&&(o.sequential=a.sequential),a.perFrame!==void 0&&(o.perFrame=a.perFrame),a.returns!==void 0&&(o.returns=a.returns);const h=await this.flash.override(e,s,o);return this.feedOf(e,!1,h,()=>i,()=>r)}feedOf(e,t,a,r,i){const s=async()=>{this.drawn.delete(s),await a()};this.drawn.add(s);const o=s;return Object.defineProperty(o,"method",{value:e,enumerable:!0}),Object.defineProperty(o,"inside",{value:t,enumerable:!0}),Object.defineProperty(o,"calls",{get:r,enumerable:!0}),Object.defineProperty(o,"last",{value:i,enumerable:!0}),o}screens(){return Object.keys(Vt)}onScreen(e,t){const a=Vt[e];let r=!0;const i=[];return(async()=>{for(const[o,h]of[[a.open,!0],[a.close,!1]]){const l=await this.flash.hook(o,{phase:h?"exit":"enter",capture:{args:[]}},()=>t({name:e,open:h,spot:a.spot}));if(!r){await l();return}i.push(l)}})().catch(o=>{console.error(`phantom.ui.onScreen could not hook ${e}: ${Y(o)}`)}),()=>{r=!1;for(const o of i.splice(0))o().catch(()=>{})}}async clear(){for(const e of[...this.popups])await e().catch(()=>{});for(const e of[...this.drawn])await e().catch(()=>{})}pieceOf(e,t){const a=ae(e);if(!a)throw new TypeError("Expected a place in the client, or one of Phantom's spots");const r=a.at(...t);return{place:r,at:(...s)=>this.pieceOf(r,s),exists:async()=>{try{const s=await r.get();return s!=null}catch{return!1}},get:async(...s)=>{try{const o=await r.at(...s).get();return _(this.bridge,o)??null}catch{return null}},set:(s,o)=>r.at(...typeof s=="string"?[s]:s).set(o),read:async(...s)=>{const o=await Promise.all(s.map(l=>r.at(l).get().catch(()=>null))),h={};return s.forEach((l,c)=>{h[l]=_(this.bridge,o[c]??null)}),h},call:async(s,...o)=>{const h=await te(this.bridge,o);return _(this.bridge,await r.at(s).call(...h))},on:async(s,o)=>{const h=await r.listen(s,c=>o(_(this.bridge,c))),l=async()=>{this.drawn.delete(l),await h()};return this.drawn.add(l),l},whenever:async(s,o={})=>{const h=await this.flash.whenever(r,c=>s(this.pieceOf(c,[])),o),l=async()=>{this.drawn.delete(l),await h()};return this.drawn.add(l),l},attach:s=>this.attach(r,s),replace:s=>this.replace(r,s),hide:()=>this.hide(r),use:()=>N(this.bridge,r)}}widget(e,t,a,r){let i=null;const s=()=>(i??=(async()=>{this.drawn.delete(o),r&&await r().catch(()=>{})})(),i),o=async()=>{await e.remove(),await s()};this.drawn.add(o),e.onRemoved(()=>{s()});const h={skin:t,node:e,move:(l,c)=>e.update({x:l,y:c}),show:()=>e.show(),hide:()=>e.hide(),remove:o,...a};for(const[l,c]of Object.entries(h))Object.defineProperty(o,l,{value:c,enumerable:!0,configurable:!0});return o}async picture(e,t,a){const r=await this.flash.overlay.image(e,t);return r.onFailed(Z(a)),r}box(e,t){return{x:e.x??0,y:e.y??0,width:e.width??t.width,height:e.height??t.height,...e.parent?{parent:C(e.parent)}:{},...e.visible===void 0?{}:{visible:e.visible}}}async anchorOf(e){if(typeof e=="number"){const r=(await this.flash.entities.players()).find(i=>i.id===String(e));return r?r.place:null}if(typeof e=="string")return this.place(e);if(ue(e))return e;const t=e.place;return ue(t)?t:null}async mouse(){const e=this.bridge.stage(),[t,a]=await Promise.all([e.at("mouseX").get().catch(()=>null),e.at("mouseY").get().catch(()=>null)]);return{x:Oe(t),y:Oe(a)}}placeOf(e){return typeof e=="string"?this.place(e):e}maker(){if(!this.symbolMaker){const e=this.bridge.definition(H.definitionByName).get().then(t=>{if(!t)throw new TypeError("This client has no GETDEFINITIONBYNAME");return t});e.catch(()=>{this.symbolMaker===e&&(this.symbolMaker=null)}),this.symbolMaker=e}return this.symbolMaker}async nodeObject(e){const t=await new se(this.bridge,{kind:"overlay"},[]).at("getChildByName").call(`phantomNode${e.node}`);if(!t)throw new TypeError(`Overlay node ${e.node} is not drawn straight into the overlay, so it cannot be dressed`);return t}async adopt(e,t){const a=t.parent;if(a&&wi(a))throw new Error("What it was to be drawn in was taken off the screen before it could be put there");await e.update(t)}async waitFor(e,t=this.readyTimeoutMs){const a=Date.now()+Math.max(0,t);for(;;){const r=await this.status(),i=(!e.art||r.art)&&(!e.palettes||r.palettes),s=a-Date.now();if(i||s<=0||this.bridge.state==="closed")return r;await new Promise(o=>setTimeout(o,Math.min(Vr,s)))}}async artLoaded(){return this.known.art||(this.known.art=await this.hasSymbol("PopupSkin")),this.known.art}async palettesLoaded(){if(!this.known.palettes)try{const e=await this.bridge.definition(H.palette).at("gamePalette").get();this.known.palettes=Array.isArray(e)&&e.length>0}catch{}return this.known.palettes}clientFont(){if(!this.gameFont){const e=this.bridge.definition(H.fonts),t=this.known.palettes,a=(async()=>{for(const r of[["defaultFontFormat","font"],["defaultFont","fontName"]])try{const i=await e.at(...r).get();if(typeof i=="string"&&i.length>0)return i}catch{}return Pe})();a.then(r=>{r===Pe&&!t&&this.gameFont===a&&(this.gameFont=null)},()=>{this.gameFont===a&&(this.gameFont=null)}),this.gameFont=a}return this.gameFont}async frameOnly(e){const t=await e.at("numChildren").get()??0;for(let a=0;a<Math.min(t,32);a+=1){const r=await e.at("getChildAt").call(a);try{await r.at("name").get()!=="ba"&&await r.at("visible").set(!1)}finally{await this.bridge.release([r]).catch(()=>{})}}}async dressWindow(e,t){const r=await(await this.maker()).at("apply").call(null,["PopupSkin",!1]),i=[r];try{const s=r.at("ba"),[o,h]=await Promise.all([Te(s.at("t","height")),Te(s.at("b","height"))]),l=li(t,o,h);await Promise.all([s.at("m","height").set(l.middle),s.at("m","y").set(l.middleY),s.at("t","y").set(l.topY),s.at("b","y").set(l.bottomY)]),await this.frameOnly(r);const c=await this.boundsOf(s,r),u={width:Math.round(c.width),height:Math.round(c.height)},d=await this.parchmentOf(r,c).catch(()=>null),w=ci(u,d);await Promise.all([r.at("x").set(Math.round(-c.x-w.panel.x)),r.at("y").set(Math.round(-c.y-w.panel.y))]);const g=await this.nodeObject(e);i.push(g),await g.at("addChildAt").call(r,0);const f=await this.frameClose(g,w).catch(()=>null);return f&&i.push(f),{...u,layout:w,close:f,held:i}}catch(s){throw await this.bridge.release(i).catch(()=>{}),s}}async frameClose(e,t){const r=await(await this.maker()).at("apply").call(null,["closeBtn",!1]);try{const i=await this.boundsOf(r,r);if(i.width<=0||i.height<=0)throw new TypeError("The close button has no size");const s=Math.min(1,(t.titleHeight-2)/i.height);return await Promise.all([r.at("scaleX").set(s),r.at("scaleY").set(s),r.at("x").set(Math.round(t.panel.width-2-(i.x+i.width)*s)),r.at("y").set(Math.round((t.titleHeight-i.height*s)/2-i.y*s))]),await e.at("addChild").call(r),r}catch(i){throw await this.bridge.release([r]).catch(()=>{}),i}}async boundsOf(e,t){const a=await e.at("getBounds").call(t);try{const[r,i,s,o]=await Promise.all(["x","y","width","height"].map(h=>Te(a.at(h))));return{x:r,y:i,width:s,height:o}}finally{await this.bridge.release([a]).catch(()=>{})}}async parchmentOf(e,t){const a=Math.ceil(t.width),r=Math.ceil(t.height);if(a<=0||r<=0||a>2048||r>2048)return null;const i=await this.bridge.construct("flash.display.BitmapData",a,r,!0,0);try{await i.at("draw").call(e,new _e("flash.geom.Matrix",[1,0,0,1,-t.x,-t.y]));const s=await i.at("getPixel32").call(Math.floor(a/2),Math.floor(r/2));if(typeof s!="number"||s>>>24!==255)return null;const o=await i.at("getColorBoundsRect").call(Ht,(s&Ht)>>>0,!0);try{const[h,l,c,u]=await Promise.all(["x","y","width","height"].map(d=>Te(o.at(d))));return{x:h,y:l,width:c,height:u}}finally{await this.bridge.release([o]).catch(()=>{})}}finally{await i.at("dispose").call().catch(()=>{}),await this.bridge.release([i]).catch(()=>{})}}async clientTooltip(e,t){let a;try{a=await this.symbol("Tooltip",{skin:"game",x:t.x??0,y:t.y??0,visible:t.visible===!0,...t.parent?{parent:t.parent}:{}})}catch{return null}const r=async i=>{await a.object.at("setToolTipText").call(i)};try{e&&await r(e)}catch{return await a.remove(),null}return Object.assign(a,{setText:r,showAt:async(i,s)=>{await a.node.update({x:i,y:s,visible:!0})}})}async palette(e){const t=await this.waitFor({palettes:!0}),a=this.bridge.definition(H.palette),r=t.palettes?await a.at("gamePalette").get():null,i=Zt(r);if(!i.length)throw new Error(`The game has not loaded its colour palettes yet: waited ${Math.round(this.readyTimeoutMs/1e3)} seconds`);if(e==="game")return{values:i,indexes:i.map((o,h)=>h)};const s=Zt(await a.at(e===1?"avatarPalette1":"avatarPalette2").get());return{values:i,indexes:s.length?s:i.map((o,h)=>h)}}async clientColorTable(e){const t=await this.flash.overlay.group({x:e.options.x??0,y:e.options.y??0,visible:!1});try{const a=await this.bridge.construct(H.colorTable);await a.at("init").call(0,e.width,e.height,e.columns,e.rows,e.values,e.indexes,e.current,(i,s)=>e.tell(Number(s)),-1);const r=await this.nodeObject(t);await r.at("addChild").call(a),await this.bridge.release([r,a]).catch(()=>{}),await this.adopt(t,{...e.options.parent?{parent:C(e.options.parent)}:{},visible:e.options.visible!==!1})}catch(a){throw await t.remove(),a}return t}async swatchGrid(e){const t=await this.flash.overlay.group({x:e.options.x??0,y:e.options.y??0,...e.options.parent?{parent:C(e.options.parent)}:{},...e.options.visible===void 0?{}:{visible:e.options.visible}}),a=Xt({count:e.indexes.length,columns:e.columns,tileWidth:e.swatchWidth,tileHeight:e.swatchHeight,gap:1}),r={color:ut.line,alpha:.6},i={color:ut.light,width:2},s=new Map;let o=e.current;for(const h of a){const l=e.indexes[h.index],c=await this.flash.overlay.button("",{parent:t,x:h.x,y:h.y,width:h.width,height:h.height,cornerRadius:2,fill:e.values[l]??0,hoverFill:e.values[l]??0,stroke:l===o?i:r});s.set(l,c),c.on("click",()=>{var u;const d=o;o=l,d!==l&&((u=s.get(d))==null||u.update({stroke:r}).catch(X),c.update({stroke:i}).catch(X)),e.tell(l)})}return t}openPopup(e,t,a,r,i){let s=()=>{};const o=new Promise(f=>{s=f});let h=null,l=!1,c=null;const u=f=>{l||(l=!0,c&&clearTimeout(c),c=null,this.popups.delete(w),s(f))},d=()=>{l||c||(c=setTimeout(()=>u(i),di))},w=async()=>{const f=h;h=null,u(i),f&&await f.at("destroy").call().catch(()=>{})};this.popups.add(w);const g=ii(e,t,a);return(async()=>{await this.waitFor({art:!0});const f=this.bridge.definition(a.layer==="load"?H.loadProgress:H.guiManager).at(a.layer==="load"?"loadLayer":"guiLayer"),m=[];for(const y of g.args){if(y!==null&&typeof y=="object"){if(y.slot==="layer")m.push(await f.get());else if(y.slot==="callback")m.push((...b)=>u(r(b[0]??null)));else{const b=await this.maker();m.push(await b.at("apply").call(null,["PopupSkin",!1]))}continue}m.push(y)}const p=await this.bridge.construct(g.className,...m);h=p,a.name!==void 0&&await p.at("name").set(a.name).catch(()=>{}),await p.at("closeCallback").set(()=>d()).catch(()=>{})})().catch(f=>{this.popups.delete(w),l||(l=!0,s(i)),console.error(`phantom.ui.popup.${e} could not open: ${Y(f)}`)}),Object.assign(o,{close:w})}}class ui{constructor(e,t){this.open=e,this.closeEverything=t}open;closeEverything;message(e,t={}){return this.open("message",e,t,()=>{},void 0)}ok(e,t={}){return this.open("ok",e,t,()=>{},void 0)}okCancel(e,t={}){return this.open("okCancel",e,t,et,null)}yesNo(e,t={}){return this.open("yesNo",e,t,et,null)}titled(e,t={}){return this.open("titled",e,t,()=>{},void 0)}parchment(e,t={}){return this.open("parchment",e,t,et,null)}async closeAll(){await this.closeEverything()}}const di=50,Jt={click:"click",down:"mouseDown",up:"mouseUp",over:"rollOver",out:"rollOut"},fi=["chatBar","chatHist","chatTxt","sendChatBtn","safeChatBtn","actionsBtn","emotesBtn","denBtn","worldMapBtn","buddyListBtn","newsBtn","partyBtn","mySettingsBtn","money","zoneName"];function C(n){if(!n)throw new TypeError("Expected a widget or an overlay node");return typeof n.node=="number"?n:n.node}function wi(n){let e=!1;return n.onRemoved(()=>{e=!0})(),e}function we(n,e){return e?{fill:n.accent,hoverFill:{color:n.accent,alpha:.85},pressedFill:{color:n.accent,alpha:.7},stroke:n.line}:n.skin==="game"?{fill:n.light,hoverFill:16777215,pressedFill:n.line,stroke:n.line}:{fill:{color:n.ink,alpha:.92},hoverFill:n.line,pressedFill:{color:n.line,alpha:.7},stroke:n.line}}function et(n){if(n!==null&&typeof n=="object"&&!Array.isArray(n)){const e=n.status;if(typeof e=="boolean")return e}return null}function Qt(n){return Number.isFinite(n)?Math.min(1,Math.max(0,n)):0}function Y(n){return n instanceof Error?n.message:String(n)}async function Te(n){const e=await n.get();if(typeof e!="number"||!Number.isFinite(e))throw new TypeError(`Expected a number at ${n.path.join(".")}, and read ${String(e)}`);return e}function Zt(n){return Array.isArray(n)?n.map(e=>typeof e=="number"?e:0):[]}function tt(n,e){const t=[];for(const a of n.split(`
|
|
4
|
+
`)){let r="";for(const i of a.split(/\s+/).filter(Boolean))r?r.length+1+i.length<=e?r=`${r} ${i}`:(t.push(r),r=i):r=i;t.push(r)}return t.length?t:[""]}function en(n,e){return Math.max(8,Math.floor(n/Math.max(1,e*.55)))}function gi(n){if(!n||typeof n!="object"||Array.isArray(n))return null;const{stageX:e,stageY:t}=n;return typeof e!="number"||typeof t!="number"?null:{x:e,y:t}}function Oe(n){return typeof n=="number"&&Number.isFinite(n)&&n>0?n:0}const En=Symbol("phantom.call"),mi=new Set(["constructor","nodeType","tagName"]),tn=new Set;function pi(n,e,t){return new Proxy(n,{get(a,r,i){if(r===En)return e;if(typeof r=="symbol")return Reflect.get(a,r,i);if(r==="toString"||r==="toJSON")return()=>`[Phantom ${e}, a call]`;if(mi.has(r)||r.startsWith("__v_"))return Reflect.get(a,r,i);throw bi(e,r,t)}})}function yi(n){if(typeof n!="function")return null;const e=n[En];return typeof e=="string"?e:null}function bi(n,e,t){const a=vi(n,e);return S.development&&!tn.has(`${n}.${e}`)&&(tn.add(`${n}.${e}`),t(a)),new $("NOT_A_VALUE",a)}function vi(n,e){return hn(n)&&un(n)==="now"?`phantom.${n} takes a listener: phantom.${n}((...) => {}), and what it gives back stops it. Reading .${e} off it reads that function itself, not what the event carries.`:e==="then"?`await phantom.${n} awaits the call itself and hands the function straight back. Write await phantom.${n}(), with the brackets: a plugin asks Phantom for every value, so it awaits the call.`:`phantom.${n} is a call in a plugin: write await phantom.${n}(). Reading .${e} off it reads the call itself, not what it answers. A script has the SDK beside the game and reads phantom.${n} as a property; a plugin's frame has to ask Phantom for it.`}function Re(n){return n instanceof $?{code:n.code,message:n.message,...n.stack?{stack:n.stack}:{}}:n instanceof Error?{code:"FAILED",message:n.message||n.name,...n.stack?{stack:n.stack}:{}}:{code:"FAILED",message:L(n)}}function Tn(n){const e=n&&typeof n.code=="string"&&n.code?n.code:"FAILED";return new $(e,(n==null?void 0:n.message)||"Phantom could not do this")}function pe(n){return ie(n,new WeakMap)}function ie(n,e){if(Kn(n))return ie(n.value,e);if(typeof n=="function"||typeof n=="symbol")return;if(typeof n!="object"||n===null)return n;const t=Xn(n);if(e.has(t))return e.get(t);if(t instanceof Date||t instanceof RegExp||t instanceof ArrayBuffer||ArrayBuffer.isView(t))return t;if(Array.isArray(t)){const r=[];e.set(t,r);for(const i of t)r.push(ie(i,e));return r}if(t instanceof Map){const r=new Map;e.set(t,r);for(const[i,s]of t)r.set(ie(i,e),ie(s,e));return r}if(t instanceof Set){const r=new Set;e.set(t,r);for(const i of t)r.add(ie(i,e));return r}if(t instanceof Error)return Re(t);const a={};e.set(t,a);for(const[r,i]of Object.entries(t)){const s=ie(i,e);s!==void 0&&(a[r]=s)}return a}function L(n){if(typeof n=="string")return n;if(n instanceof Error)return n.stack||`${n.name}: ${n.message}`;if(n===void 0)return"undefined";if(typeof n=="function"){const e=yi(n);return e?`[Phantom ${e}, a call]`:`[Function ${n.name||"anonymous"}]`}if(typeof n=="symbol"||typeof n=="bigint")return n.toString();try{const e=new WeakSet,t=JSON.stringify(pe(n),(a,r)=>{if(typeof r=="object"&&r!==null){if(e.has(r))return"[Circular]";e.add(r)}return typeof r=="bigint"?`${r}n`:r});return nn(t??String(n))}catch{return nn(String(n))}}const nt=1e4;function nn(n){return n.length>nt?`${n.slice(0,nt)}… (${n.length-nt} more)`:n}const ki=["log","info","warn","error"];function xi(n,e){const t=new Map;let a=!1;for(const r of ki){const i=n[r].bind(n);t.set(r,i),n[r]=(...s)=>{if(i(...s),!a){a=!0;try{e(r,s.map(L))}finally{a=!1}}}}return()=>{for(const[r,i]of t)n[r]=i}}const mt={game:{id:"game",waiting:"the game to finish loading",detail:"The client is logged in and its world extension answers (phantom.session.ready). Until then a request can go quietly nowhere, which is why the client holds its own back too.",area:"session"},room:{id:"room",waiting:"the player to be in a room",detail:"The player is standing in a room. Read from the games Phantom already sends the frame, so it costs nothing and needs no permission.",area:null},language:{id:"language",waiting:"the game’s words to load",detail:"The client has its dictionary (phantom.localization.hasLocalizations), which arrives after login. Until then every text id translates to an empty string, so a plugin that recognises the game’s own wording has nothing to recognise it by.",area:"localization"},hud:{id:"hud",waiting:"the HUD to be drawn",detail:"The main HUD is on screen. The client makes it in GuiManager.init, once play has started, so anything hooked onto a HUD button before that is hooked onto nothing.",area:"gui"},interface:{id:"interface",waiting:"the game’s interface art to load",detail:"The client has its library art and its colour palettes (phantom.ui.status), which arrive as the player logs in. Drawing in the game skin, or reading a palette, needs them.",area:"ui"},shops:{id:"shops",waiting:"the item definitions to arrive",detail:"The client has its item definitions (phantom.shops.definitionsReady). Until then every item reads back as null, whether or not the id is real.",area:"shops"}},Mi=Object.keys(mt);function ne(n){const e=new Set(typeof n=="string"?[n]:n??[]);return Mi.filter(t=>e.has(t))}function On(n){const[e,...t]=ne(n);if(!e)return"It is ready.";const a=t.length===1?"one more thing":`${t.length} more things`;return`Waiting for ${mt[e].waiting}${t.length?`, and ${a} after it`:""}.`}function Si(n,e,t){return new Fr(new ha(Ei(n,e),{firstId:t}))}function Ei(n,e){const t=new Set;let a=null;const r=i=>{for(const s of t)s(i)};return{send(i){n.call("flash.request",e,[i]).catch(s=>{const o=Ti(i,s);o?r(o):n.log("warn",[`A Flash request was refused: ${L(s)}`])})},onMessage(i){return t.add(i),a??=n.subscribe("flash.messages",e,{event(s){const[o]=s;typeof o=="string"&&r(o)},ended(s){a=null,s&&n.log("warn",[`Flash stopped answering: ${s.message}`])}}),()=>{t.delete(i),!t.size&&a&&(a(),a=null)}}}}function Ti(n,e){let t;try{t=fn(n)}catch{return null}if(typeof(t==null?void 0:t.id)!="number")return null;const a=e instanceof $?e.code:"FAILED",r=e instanceof Error?e.message:L(e);return ce({kind:"result",id:t.id,ok:!1,error:{name:a,message:r,errorId:0}})}function Oi(n){let e=null,t=null;const a=()=>{const r=n.flash();return e??=new Hr({flash:r.bridge,content:Ai(n.port,n.game)},r),e};return{avatar:{view:()=>n.flash().bridge.definition(jr.avatarManager).at("playerAvatarWorldView").get()},adventures:{record:()=>$i(n.remote)},realtime:{join:(r,i)=>jn(n.remote.realtime,r,i),stayIn:(r,i,s)=>In(n.remote.realtime,r,i,s)},customRooms:{prop:(r,i)=>Ln(n.remote.customRooms,r,i),object:(r,i)=>Fn(n.remote.customRooms,r,i),character:(r,i)=>_n(n.remote.customRooms,r,i)},room:{surfaces:()=>Un(n.flash().bridge)},content:{load:(r,i)=>a().load(r,i),replaceOnScreen:(r,i,s)=>a().replaceOnScreen(r,i,s)},ui:()=>{const r=n.flash();return t??=new hi({flash:r.bridge},r),t},recipes:{chatShortcuts:async r=>Pr(await at(n),r),customChatBox:async r=>Rr(await at(n),r),chatHistoryPanel:async r=>Nr(await at(n),r)}}}function Ai(n,e){const t=()=>{throw new $("NOT_SUPPORTED","Only holding and releasing content happen in a frame")};return{hold:a=>n.call("content.hold",e,[a]),release:a=>n.call("content.release",e,[a]),replace:t,restore:t,list:t,observe:t}}function $i(n){const e=Date.now(),t=[];let a=null,r=null;const i=()=>{a===null&&n.adventures.current().then(o=>a??=(o==null?void 0:o.scriptDefId)??null).catch(()=>{}),r===null&&n.adventures.actor("diff_level").then(o=>r??=(o==null?void 0:o.state)??null).catch(()=>{})};i();const s=n.adventures.onStep(({time:o,...h})=>{i(),t.push({...h,at:o-e})});return{stop:()=>(s(),{version:1,scriptDefId:a,difficulty:r,steps:[...t]})}}async function at(n){const e=n.flash(),{remote:t}=n,a=[...await t.chat.recent()],r=new Map;for(const i of await t.room.players.list())r.set(i.userId,i);return t.room.players.onEnter(i=>r.set(i.userId,i)),t.room.players.onLeave(i=>r.delete(i.userId)),t.chat.onMessage(i=>a.push(i)),{flash:e,chat:{say:t.chat.say,phrase:t.chat.phrase,onMessage:t.chat.onMessage,recent:a},room:{players:{get:i=>r.get(i)??null}}}}function Pi(n,e){const t={};for(const a of Object.keys(Dn)){const r=a.split(".");let i=t;for(const o of r.slice(0,-1))i=i[o]??={};const s=r[r.length-1];i[s]=hn(a)?Ni(n,e,a,un(a)):Ci(n,e,a)}return pt(t,"")}const Ri=new Set(["then","toJSON","constructor","nodeType","tagName"]);function pt(n,e){for(const[t,a]of Object.entries(Object.getOwnPropertyDescriptors(n))){const r=a.get||a.set?null:a.value;!r||typeof r!="object"||!a.writable||(n[t]=pt(r,`${e}${t}.`))}return new Proxy(Object.freeze(n),{get(t,a,r){if(typeof a!="string"||a in t)return Reflect.get(t,a,r);if(!(Ri.has(a)||a.startsWith("__v_")))throw new $("NOT_SUPPORTED",`phantom.${e}${a} is not in this Phantom's copy of the plugin SDK. Either the name is wrong, or Phantom is serving an older build of @phantomclient/plugin than this plugin was written against; building that package again gives every plugin the newer SDK.`)}})}function Ci(n,e,t){return An(n,t,(...a)=>n.call(`sdk:${t}`,e,a))}function An(n,e,t){return pi(t,e,a=>n.log("error",[a]))}function Ni(n,e,t,a){return An(n,t,(...r)=>{const i=r.findIndex(u=>typeof u=="function");if(i===-1&&zn(t))throw new TypeError(`${t} takes a listener function`);const s=i===-1?null:r[i],o=i===-1?r:[...r.slice(0,i),...r.slice(i+1)];let h=null;const l=a==="awaited"?new Promise((u,d)=>{h=(w,g)=>{h=null,w?u(w):d(g)}}):null,c=n.subscribe(`sdk:${t}`,e,{event:u=>s==null?void 0:s(...u),started:()=>h==null?void 0:h(()=>c()),ended(u){if(h){h(null,Tn(u??{code:"FAILED",message:`${t} could not be started`}));return}u&&n.log("warn",[`${t} stopped: ${u.code}: ${L(u.message)}`])}},{args:o,...i===-1?{}:{listenerAt:i}});return l??c})}const $n=500,Pn=5e3,_i=12e4;function ft(n,e,t){return Math.min(t,e*2**Math.max(0,n-1))}const Fi={async game(n){const e=await n.call("session.ready");return(e==null?void 0:e.worldReady)===!0},room:async n=>{var e;return((e=n.view())==null?void 0:e.room)!=null},language:async n=>await n.call("localization.hasLocalizations")===!0,hud:async n=>await n.call("gui.bounds",["hud"])!=null,async interface(n){const e=await n.call("ui.status");return(e==null?void 0:e.art)===!0&&(e==null?void 0:e.palettes)===!0},shops:async n=>await n.call("shops.definitionsReady")===!0};function Li(n){let e=null;const t=new Set;let a=null;function r(c){return new Promise((u,d)=>{const w=setTimeout(()=>{t.delete(g),u()},c),g=f=>{clearTimeout(w),d(f)};t.add(g)})}function i(c){const u=c??n.boundGame();if(u)return u;throw new $("NO_GAME","This frame works with several games: name one, as ctx.ready.wait(what, { game }), from ctx.games()")}function s(c){if(!(!c.area||n.can(`sdk:${c.area}:read`)))throw new $("PERMISSION_DENIED",`Waiting for "${c.id}" reads sdk:${c.area}:read, which this plugin was not granted: add "${c.area}" to permissions.sdk`)}function o(c){return{call:(u,d=[])=>n.port.call(`sdk:${u}`,c,d).catch(()=>null),view:()=>n.games().find(u=>u.id===c)??null}}async function h(c,u){const d=ne(c);if(!d.length)return[];for(const f of d)s(mt[f]);const w=o(u??i(void 0)),g=await Promise.all(d.map(f=>Fi[f](w)));return d.filter((f,m)=>g[m]!==!0)}const l={async missing(c,u){return h(ne(c),i(u==null?void 0:u.game))},async check(c,u){return(await l.missing(c,u).catch(()=>[...ne(c)])).length===0},async wait(c,u){const d=ne(c),w=i(u==null?void 0:u.game),g=(u==null?void 0:u.timeoutMs)??_i,f=Number.isFinite(g)?Date.now()+g:1/0;for(let m=1;;m++){if(a)throw new Ae(a,d);const p=await h(d,w);if(!p.length)return;if(Date.now()>=f)throw new Ae(`${On(p)} It did not happen in ${Math.round(g/1e3)} seconds.`,p);await r(ft(m,$n,Pn))}},waitingFor(c){const u=typeof c=="string"&&c.trim()?c.trim().slice(0,200):null;u!==e&&(e=u,n.onReason(e))}};return{api:l,missing:h,get reason(){return e},dispose(c){a=c,e=null;for(const u of[...t])u(new Ae(c));t.clear()}}}function an(n,e,t,a){const r=i=>({direction:a,...i==="*"?{}:{commands:[...i]}});return{send(i){return n.call("packets.send",e,[t,String(i)])},watch(i,s){return n.subscribe("packets.watch",e,{event(o){const h=ji(o,a);h&&s(Sn(h.text,h.direction))},ended:o=>{o&&n.log("warn",[`Watching the traffic stopped: ${o.message}`])}},{filter:r(i)})},on(i,s){return n.subscribe("packets.intercept",e,{event:()=>{},intercepted:o=>{Ii(n,o,s)},ended:o=>{o&&n.log("warn",[`Hooking the traffic stopped: ${o.message}`])}},{filter:r(i)})}}}async function Ii(n,e,t){let a;try{a=Sn(e.text,e.direction),await t(a)}catch(r){n.log("error",[`A traffic hook failed: ${L(r)}`]),n.verdict(e.requestId,!1,null);return}n.verdict(e.requestId,a.dropped,a.modified?a.encode():null)}function ji(n,e){const[t,a]=n;if(typeof t=="string")return{text:t,direction:rn(a)?a:e};if(typeof t=="object"&&t!==null){const{text:r,direction:i}=t;if(typeof r=="string")return{text:r,direction:rn(i)?i:e}}return null}function rn(n){return n==="toServer"||n==="toClient"}function Di(n,e={}){const t=new Map,a=new Set,r=Li({port:n,boundGame:()=>Ce(S.role),games:()=>S.games,can:l=>sn(S.granted.scopes,l),onReason:l=>{var c;return(c=e.onWaitingFor)==null?void 0:c.call(e,l)}}),i=new Set;function s(l){var c,u;const d=l??Ce(S.role);if(!d)throw new $("NO_GAME",((c=S.role)==null?void 0:c.kind)==="page"||((u=S.role)==null?void 0:u.kind)==="logic"?"This frame works with several games: name one, as ctx.phantom(id), from ctx.games()":"This frame is not bound to a game yet");let w=t.get(d);return w||(w=zi(n,d),t.set(d,w)),w}function o(l){const c=l?S.players[l]:void 0;return c?{...S.preferences,...c}:S.preferences}return{ctx:{get plugin(){return S.plugin},get granted(){return S.granted},get preferences(){return S.preferences},get preferenceFields(){return S.preferenceFields},preferencesFor(l){const c=S.games.find(u=>u.id===String(l));return o((c==null?void 0:c.accountId)??null)},onPreferences(l){return i.add(l),()=>i.delete(l)},setPreferences:(l,c)=>n.call("preferences.set",(c==null?void 0:c.game)??null,[l&&typeof l=="object"?{...l}:{}]),snag:(l,c)=>{n.call("snag",null,[String(l),c===null?null:String(c)]).catch(u=>n.log("error",[`A snag could not be told: ${L(u)}`]))},get snags(){return S.snags},can:l=>sn(S.granted.scopes,l),games:()=>[...S.games],onGames(l){return a.add(l),()=>a.delete(l)},phantom:s,ready:r.api,storage:{get:l=>n.call("storage.get",null,[String(l)]),set:(l,c)=>n.call("storage.set",null,[String(l),c]),remove:l=>n.call("storage.remove",null,[String(l)]),keys:()=>n.call("storage.keys",null,[])},async fetch(l,c){const u=await n.call("fetch",null,[String(l),c??{}]);return Hi(u)},copy:l=>n.call("copy",null,[String(l)]),notify:(l,c)=>n.call("notify",null,c===void 0?[String(l)]:[String(l),String(c)]),toast:(l,c)=>n.call("toast",null,[String(l),c??{}]),confirm:(l,c)=>n.call("confirm",null,[String(l),c??{}]),openUrl:l=>n.call("openUrl",null,[String(l)]),openPanel:(l,c)=>n.call("panel.open",(c==null?void 0:c.game)??null,[String(l)]),closePanel:(l,c)=>n.call("panel.close",(c==null?void 0:c.game)??null,[String(l)]),log:(...l)=>n.log("log",l.map(L))},ready:r,notifyGames(l){for(const c of[...a])try{c([...l])}catch(u){n.log("error",[`An onGames listener failed: ${L(u)}`])}},notifyPreferences(){for(const l of[...i])try{l(S.preferences)}catch(c){n.log("error",[`An onPreferences listener failed: ${L(c)}`])}},dispose(){r.dispose("The frame was closed"),a.clear(),i.clear(),t.clear()}}}function zi(n,e){let t=null;const a=()=>{if(t)return t;if(S.flashIds===null)throw new $("PERMISSION_DENIED","game.flash needs the flash scope, which this plugin was not granted");return t=Si(n,e,S.flashIds),t},r=Pi(n,e),i=Oi({port:n,game:e,remote:r,flash:a}),s={...r,avatar:Object.freeze({...r.avatar,...i.avatar}),adventures:Object.freeze({...r.adventures,...i.adventures}),content:Object.freeze({...r.content,...i.content}),realtime:Object.freeze({...r.realtime,...i.realtime}),customRooms:Object.freeze({...r.customRooms,...i.customRooms}),room:Object.freeze({...r.room,...i.room}),recipes:Object.freeze(i.recipes),id:e,server:an(n,e,"toServer","toClient"),client:an(n,e,"toClient","toServer")};return Object.defineProperties(s,{flash:{enumerable:!0,get:a},ui:{enumerable:!0,get:i.ui}}),pt(s,"")}function sn(n,e){if(n.includes(e))return!0;if(!e.startsWith("network:"))return!1;const t=e.slice(8);return n.some(a=>{if(!a.startsWith("network:*."))return!1;const r=a.slice(9);return t.endsWith(r)&&t.length>r.length})}function Hi(n){const e=n.body??"";return{status:n.status,ok:n.status>=200&&n.status<300,headers:n.headers??{},text:async()=>e,json:async()=>JSON.parse(e)}}const Wi=6e4;function Bi(n,e={}){const t=e.prefix??`f${Math.random().toString(36).slice(2,10)}-`,a=e.timeoutMs??Wi;let r=0,i=!1;const s=new Map,o=new Map,h=()=>`${t}${r+=1}`;function l(f,m){if(!i)try{n({phantom:q,type:"log",level:f,values:m})}catch{}}function c(f,m,p){if(i)return Promise.reject(new $("FAILED","The frame was closed"));const y=h();return new Promise((b,k)=>{const M=setTimeout(()=>{s.delete(y),k(new $("TIMEOUT",`Phantom did not answer ${f} in ${a/1e3}s`))},a);s.set(y,{resolve:b,reject:k,timer:M});try{n({phantom:q,type:"call",id:y,method:f,game:m,args:pe(p)})}catch(O){clearTimeout(M),s.delete(y),k(new $("FAILED",`${f} could not be sent: ${L(O)}`))}})}function u(f,m,p,y={}){if(i)return g(()=>{var k;return(k=p.ended)==null?void 0:k.call(p,{code:"FAILED",message:"The frame was closed"})}),()=>{};const b=h();o.set(b,p);try{n({phantom:q,type:"subscribe",id:b,topic:f,game:m,...y.filter?{filter:pe(y.filter)}:{},...y.args?{args:pe(y.args)}:{},...typeof y.listenerAt=="number"?{listenerAt:y.listenerAt}:{}})}catch(k){throw o.delete(b),new $("FAILED",`${f} could not be heard: ${L(k)}`)}return()=>{!o.delete(b)||i||n({phantom:q,type:"unsubscribe",id:b})}}function d(f,m,p){i||n({phantom:q,type:"verdict",requestId:f,drop:m,text:p})}function w(f){switch(f.type){case"call-result":{const m=s.get(f.id);return m?(s.delete(f.id),clearTimeout(m.timer),f.ok?m.resolve(f.value):m.reject(Tn(f.error)),!0):!1}case"event":{const m=o.get(f.subscription);return m?(g(()=>m.event(Array.isArray(f.args)?f.args:[])),!0):!1}case"subscribed":{const m=o.get(f.subscription);return m?(g(()=>{var p;return(p=m.started)==null?void 0:p.call(m)}),!0):!1}case"intercepted":{const m=o.get(f.subscription);return m!=null&&m.intercepted?(m.intercepted(f),!0):(d(f.requestId,!1,null),!!m)}case"subscription-ended":{const m=o.get(f.subscription);return m?(o.delete(f.subscription),g(()=>{var p;return(p=m.ended)==null?void 0:p.call(m,f.error)}),!0):!1}}}function g(f){try{f()}catch(m){l("error",[`A listener failed: ${L(m)}`])}}return{call:c,subscribe:u,verdict:d,log:l,receive:w,close(f){if(!i){i=!0;for(const m of s.values())clearTimeout(m.timer),m.reject(new $("FAILED",f));s.clear(),o.clear()}}}}function qi(n,e,t=new Set){const a=new Set;for(const[i,s]of Object.entries((e==null?void 0:e.variables)??{}))!i.startsWith("--phantom-")||typeof s!="string"||(n.style.setProperty(i,s),a.add(i));for(const i of t)a.has(i)||n.style.removeProperty(i);const r=(e==null?void 0:e.mode)==="light"?"light":"dark";return n.dataset.theme=r,n.style.setProperty("color-scheme",r),a}const Ui=2e3,Vi=1e3,Gi=3e4;function Yi(n,e){Gn(e.development??!1);let t=!1,a=new Set,r=null,i=null;function s(v){var x;t||(n.post(v),(x=e.tap)==null||x.call(e,v))}const o=Bi(s);let h=null,l=null,c;const u=new Promise(v=>c=v);function d(){const v=w.ready.reason,x=h?{...h,reason:v}:v?{for:[],reason:v,attempt:0,nextInMs:null}:null,T=JSON.stringify(x);T!==l&&(l=T,s({phantom:q,type:"waiting",game:Ce(S.role),waiting:x}),x&&c())}const w=Di(o,{onWaitingFor:()=>d()}),g=w.ctx;kt(g);function f(v){var x;const T=Re(v);try{s({phantom:q,type:"crash",error:T})}catch{}(x=n.view)==null||x.showError(T,S.development)}let m;const y=new Promise(v=>m=v).then(async()=>{try{const v=e.definition,x=await(typeof v=="function"?v():v);return r=Ki(x),!0}catch(v){return f(v),!1}}),b=y.then(async v=>{var x;if(!v||((x=S.role)==null?void 0:x.kind)!=="logic")return v;const T=ge(r==null?void 0:r.widgets);return s({phantom:q,type:"ready",implements:{pages:ge(r==null?void 0:r.pages),panels:ge(r==null?void 0:r.panels),commands:ge(r==null?void 0:r.commands),commandViews:ge(r==null?void 0:r.commandViews),...T.length?{widgets:T}:{}}}),!(r!=null&&r.setup)&&!M().length||await Promise.race([O(),u]),!0}),k=v=>new Promise(x=>setTimeout(x,v));function M(){return ne([...S.requires,...(r==null?void 0:r.requires)??[]])}async function O(){const v=r==null?void 0:r.setup,x=M(),T=Ce(S.role);x.length&&!T&&o.log("warn",[`definePlugin requires ${x.join(", ")}, but this plugin runs once for every game at once, so there is no one game to be ready. Wait inside setup instead, as ctx.ready.wait(what, { game }).`]);for(let R=0,D=0;!t;){if(x.length&&T){let j;try{j=await w.ready.missing(x,T)}catch(V){h=null,d(),f(V);return}if(j.length){const V=ft(D+=1,$n,Pn);h={for:j,attempt:R,nextInMs:V},d(),await k(V);continue}D=0}R+=1;try{const j=await(v==null?void 0:v(g));h=null,d(),typeof j=="function"&&(t?bt(j):i=j);return}catch(j){const V=await E(j,x,T);if(!V){h=null,d(),f(j);return}const je=ft(R,Vi,Gi);o.log("warn",[`setup said the game is not ready (${L(j)}).`,`Try ${R} of it; Phantom will run it again in ${Math.round(je/1e3)}s.`]),h={for:V,attempt:R,nextInMs:je},d(),await k(je)}}}async function E(v,x,T){const R=x.length&&T?await w.ready.missing(x,T).catch(()=>[]):[];if(Vn(v)){const D=ne(v.waitingFor);return D.length?D:R}return R.length?R:null}function I(v){if(t||!Hn(v))return;const x=v;switch(x.type){case"init":F(x);return;case"games":S.games=Array.isArray(x.games)?x.games:[],w.notifyGames(S.games);return;case"snags":S.snags=Array.isArray(x.snags)?x.snags:[];return;case"stop":Nn();return;case"mount":Rn(x);return;case"invoke":Cn(x);return;case"call-result":case"event":case"subscribed":case"subscription-ended":case"intercepted":o.receive(x);return}}function F(v){var x;n.root&&v.theme&&(a=qi(n.root,v.theme,a));const T=JSON.stringify([S.preferences,S.players]);Object.assign(S,{role:S.role??v.role??null,plugin:v.plugin??S.plugin,mode:((x=v.theme)==null?void 0:x.mode)==="light"?"light":"dark",granted:v.granted??{scopes:[]},requires:ne(v.requires),preferences:v.preferences??{},preferenceFields:Array.isArray(v.preferenceFields)?v.preferenceFields:[],players:v.players??{},snags:Array.isArray(v.snags)?v.snags:[],games:Array.isArray(v.games)?v.games:[],flashIds:typeof v.flashIds=="number"?v.flashIds:null,development:S.development||!!v.development,initialized:!0}),w.notifyGames(S.games),JSON.stringify([S.preferences,S.players])!==T&&w.notifyPreferences(),m()}const U=n.listen(I);async function Rn(v){var x,T;const[R]=await Promise.all([y,((x=n.loadStyles)==null?void 0:x.call(n))??Promise.resolve()]);t||((T=S.role)==null?void 0:T.kind)==="logic"||(Object.assign(S,{kind:v.kind,contribution:v.contribution,props:v.props??{}}),R&&yt())}function yt(){var v;if(!S.kind||!S.contribution)return;const[x,T]=S.kind==="page"?[r==null?void 0:r.pages,"pages"]:S.kind==="panel"?[r==null?void 0:r.panels,"panels"]:S.kind==="widget"?[r==null?void 0:r.widgets,"widgets"]:[r==null?void 0:r.commandViews,"commandViews"],R=x==null?void 0:x[S.contribution];if(!R){f(new $("NOT_SUPPORTED",`definePlugin has no ${T}["${S.contribution}"], so there is nothing to show here`));return}try{(v=n.view)==null||v.mount(R,g)}catch(D){f(D)}}async function Cn(v){var x,T;const R=(D,j)=>{try{s({phantom:q,type:"result",id:v.id,ok:D,...j})}catch(V){s({phantom:q,type:"result",id:v.id,ok:!1,error:Re(new $("FAILED",`The answer could not be sent to Phantom: ${L(V)}`))})}};try{if(!await b||!r)throw new $("FAILED","The plugin did not load");if(h)throw new Ae(`${On(h.for)} Its background code has not started, so the command was not run.`,h.for);if(v.kind!=="commands")throw new $("NOT_SUPPORTED",`Phantom asked for an unknown kind, "${v.kind}"`);const D=(x=r.commands)==null?void 0:x[v.contribution];if(typeof D!="function")throw new $("NOT_SUPPORTED",`definePlugin has no commands["${v.contribution}"] function`);const j={arguments:((T=v.input)==null?void 0:T.arguments)??{}},V=await D(j,g.phantom(v.game),g);R(!0,{value:pe(V??null)})}catch(D){R(!1,{error:Re(D)})}}function bt(v){try{const x=v();x instanceof Promise&&x.catch(T=>Ie(T))}catch(x){Ie(x)}}function Ie(v){o.log("error",[`setup's cleanup failed: ${L(v)}`])}async function Nn(){const v=i;if(i=null,v)try{await Promise.race([Promise.resolve(v()),new Promise(x=>setTimeout(x,Ui))])}catch(x){Ie(x)}s({phantom:q,type:"stopped"})}return{ctx:g,crash:f,log:(v,x)=>o.log(v,x),replaceDefinition(v){var x;r=v,((x=S.role)==null?void 0:x.kind)!=="logic"&&yt()},stop(){t||(i&&(bt(i),i=null),t=!0,U(),o.close("The frame was closed"),w.dispose(),kt(null))}}}function ge(n){return Object.keys(n??{})}function Ki(n){return!n||typeof n!="object"?{}:"default"in n&&n.default&&typeof n.default=="object"?n.default:n}const Xi={class:"flex flex-col p-3",role:"alert"},Ji={class:"flex flex-col gap-2 overflow-hidden rounded-lg border border-phantom-danger/25 bg-phantom-danger/10 px-3 py-2.5"},Qi={class:"flex items-start gap-2"},Zi={class:"min-w-0 flex-1"},es={class:"text-xs font-medium text-phantom-danger"},ts={class:"mt-0.5 break-words text-2xs text-phantom-text-soft"},ns=["textContent"],as={key:1,class:"text-2xs text-phantom-subtle"},rs=Jn({__name:"ErrorCard",props:{error:{},development:{type:Boolean},kind:{}},emits:["dismiss"],setup(n,{emit:e}){const t=n,a=e,r=Qn(()=>t.kind==="panel"?"This panel":t.kind==="page"?"This page":"This plugin");return(i,s)=>(ve(),ke("div",Xi,[le("div",Ji,[le("div",Qi,[s[1]||(s[1]=le("span",{class:"mt-1.5 h-1.5 w-1.5 shrink-0 rounded-full bg-phantom-danger","aria-hidden":"true"},null,-1)),le("div",Zi,[le("p",es,ze(r.value)+" stopped with an error",1),le("p",ts,ze(n.error.message),1)]),n.development?(ve(),ke("button",{key:0,type:"button",class:"shrink-0 rounded px-1.5 text-2xs text-phantom-muted transition-colors hover:bg-phantom-danger/10 hover:text-phantom-text",onClick:s[0]||(s[0]=o=>a("dismiss"))}," Dismiss ")):xt("",!0)]),n.development&&n.error.stack?(ve(),ke("pre",{key:0,class:"max-h-64 overflow-auto whitespace-pre-wrap break-words rounded-md bg-phantom-canvas/60 px-2.5 py-2 font-mono text-3xs text-phantom-muted",textContent:ze(n.error.stack)},null,8,ns)):n.development?xt("",!0):(ve(),ke("p",as," More is in the plugin's log, in Plugins. "))])]))}});function is(n){let e=null,t=null,a=-1;const r=()=>{const o=Math.ceil(Math.max(n.content.scrollHeight,n.content.getBoundingClientRect().height));o!==a&&(a=o,n.onResize(o))},i=typeof ResizeObserver>"u"?null:new ResizeObserver(r);i==null||i.observe(n.content);function s(){t==null||t.unmount(),t=null,n.content.hidden=!1}return{mount(o,h){s(),e==null||e.unmount(),document.documentElement.dataset.kind=S.kind??"",e=Mt({name:"PhantomPluginView",render:()=>St(o,{...S.props})}),e.provide(Yn,h),e.config.errorHandler=l=>n.onError(l),e.mount(n.content)},showError(o,h){t==null||t.unmount(),n.content.hidden=!0,t=Mt({render:()=>St(rs,{error:o,development:h,kind:S.kind,onDismiss:()=>s()})}),t.mount(n.errors),r()},unmount(){i==null||i.disconnect(),e==null||e.unmount(),t==null||t.unmount(),e=null,t=null}}}function ss(n){window.parent===window&&os();const e=on("app"),t=on("phantom-error");let a=null;function r(o){window.parent.postMessage(o,"*")}const i=is({content:e,errors:t,onError:o=>a==null?void 0:a.crash(o),onResize:o=>{document.documentElement.dataset.kind&&r({phantom:q,type:"resize",height:o})}});a=Yi({post:r,listen(o){const h=l=>{l.source===window.parent&&o(l.data)};return window.addEventListener("message",h),()=>window.removeEventListener("message",h)},root:document.documentElement,view:i,...n.loadStyles?{loadStyles:n.loadStyles}:{}},n);const s=a;return xi(console,(o,h)=>s.log(o,h)),window.addEventListener("error",o=>{String(o.message).includes("ResizeObserver loop")||s.crash(o.error??o.message)}),window.addEventListener("unhandledrejection",o=>s.crash(o.reason)),window.addEventListener("pagehide",()=>{i.unmount(),s.stop()}),document.addEventListener("click",o=>{const h=o.target,l=h&&typeof h.closest=="function"?h.closest("a[href]"):null;if(!l)return;const c=l.getAttribute("href")??"";c.startsWith("#")||(o.preventDefault(),/^https:\/\//i.test(c)?s.ctx.openUrl(c).catch(()=>{}):s.log("warn",[`Only https links open from a plugin; this one goes to ${c}`]))}),s}function on(n){const e=document.getElementById(n);if(e)return e;const t=document.createElement("div");return t.id=n,document.body.append(t),t}function os(){const n=document.createElement("p");n.className="m-6 max-w-md text-xs text-phantom-muted",n.textContent="This is a Phantom plugin frame. It runs inside Phantom: turn on Developer mode in Plugins, and a plugin served by phantom-plugin dev shows up there.",document.body.prepend(n)}const ln="/dist/plugin.js",ls="/dist/plugin.css";let cn=null;function cs(){return cn??=new Promise(n=>{const e=document.createElement("link");e.rel="stylesheet",e.href=ls,e.onload=e.onerror=()=>n(),document.head.append(e)}),cn}async function hs(){const n=await import(ln);if(!n.default)throw new Error(`${ln} has no default export. Export definePlugin({ ... }) as default.`);return n.default}ss({definition:hs,loadStyles:cs});
|