@cyberart-io/engine 0.0.2 → 0.0.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/README.md +137 -7
- package/dist/headless.d.ts +637 -0
- package/dist/headless.js +8 -0
- package/dist/index.d.ts +467 -64
- package/dist/index.js +1 -1
- package/docs/asset-resolver.md +155 -0
- package/docs/deterministic-mode.md +1 -1
- package/docs/events.md +79 -10
- package/docs/headless-harness.md +58 -16
- package/docs/presentation-adapter.md +150 -0
- package/docs/presentation-cue.md +82 -0
- package/package.json +13 -2
package/dist/headless.js
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* @cyberart-io/engine
|
|
3
|
+
* Copyright (c) 2026 Aaron Boyarsky
|
|
4
|
+
* Licensed under the CyberArt Engine License. See LICENSE.
|
|
5
|
+
* Not an OSI open-source license.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
var ft=(t,e)=>()=>(t&&(e=t(t=0)),e);var Ct={};function St(t,e){let n=t.indexOf(Ke);if(n===-1)return null;let r=n+Ke.length,s=`const __cyberSkip=new Set(${JSON.stringify(e)});const __cyberOrig=registerProcessor;registerProcessor=(n,p)=>__cyberSkip.has(n)?undefined:__cyberOrig(n,p);`;return t.slice(0,r)+s+t.slice(r)}var fe,ae,wt,X,Ke,je=ft(()=>{"use strict";fe=/AudioWorkletProcessor with name:\s*["'`][^"'`]+["'`]\s+is already registered/i,ae="__cyberartWorkletPatchApplied";typeof window<"u"&&!window[ae]&&(window.addEventListener("error",t=>{let e=t?.message??"";fe.test(e)&&(t.preventDefault(),t.stopImmediatePropagation())},!0),window.addEventListener("unhandledrejection",t=>{let e=t?.reason,n=typeof e=="string"?e:e?.message??"";fe.test(n)&&t.preventDefault()}),window[ae]=!0);wt=!1,X=(...t)=>{wt&&console.log("[workletPatch]",...t)},Ke="((AudioWorkletProcessor,registerProcessor)=>{";if(typeof AudioWorklet<"u"&&!AudioWorklet.prototype[ae]){let t=new WeakMap,e=/registerProcessor\s*\(\s*['"`]([^'"`]+)['"`]/g,n=AudioWorklet.prototype.addModule,r=0;AudioWorklet.prototype.addModule=async function(s,o){let d=++r,l=t.get(this);l||(l=new Set,t.set(this,l)),X(`#${d} addModule`,{url:s.slice(0,64),isBlob:s.startsWith("blob:"),knownBefore:[...l]});let y=s,f=null;if(s.startsWith("blob:")){let u=null;try{u=await(await fetch(s)).text()}catch(g){X(`#${d} blob fetch failed`,g)}if(u!==null){let g=new Set;for(let C of u.matchAll(e))g.add(C[1]);if(g.size>0){let C=[...g].filter(k=>l.has(k)),m=[...g].filter(k=>!l.has(k));if(C.length>0&&m.length===0){X(`#${d} short-circuit \u2014 all processors already registered`,C);return}if(C.length>0&&m.length>0){let k=St(u,C);if(k!==null){let c=new Blob([k],{type:"application/javascript"});f=URL.createObjectURL(c),y=f,X(`#${d} rewrote blob; skipping`,C,"allowing",m)}else X(`#${d} blob rewrite failed; passing original through`)}m.forEach(k=>l.add(k))}}}return n.call(this,y,o).then(()=>{f&&URL.revokeObjectURL(f)},u=>{f&&URL.revokeObjectURL(f);let g=(u&&u.message)??"";if(!(fe.test(g)||/already registered/i.test(g)))throw u})},AudioWorklet.prototype[ae]=!0}});var Te=()=>{let t=["ms","moz","webkit","o"];for(let e=0;e<t.length&&!window.requestAnimationFrame;++e)window.requestAnimationFrame=window[t[e]+"RequestAnimationFrame"],window.cancelAnimationFrame=window[t[e]+"CancelAnimationFrame"]||window[t[e]+"CancelRequestAnimationFrame"]},M=window.devicePixelRatio||1,$=/Headless/i.test(navigator.userAgent),tn=/Android|webOS|iPhone|iPad|iPod|BlackBerry/i.test(navigator.userAgent)||/Android|webOS|iPhone|iPad|iPod|BlackBerry/i.test(navigator.platform);function Pe(){return Math.min(window.innerWidth,window.innerHeight)}var ce="data-cyberart-canvas",B=class{constructor(e,n,r=1,a={}){this.width=e,this.height=n;let s=a.container,o=a.adoptFromDocument??!s,d=s?s.querySelector(`canvas[${ce}]`)??s.querySelector("canvas"):null;if(d)this.canvas=d,this.adopted=!0;else if(o){let l=document.getElementById("canvas")??document.querySelector("canvas");l?(this.canvas=l,this.adopted=!0):(this.canvas=document.createElement("canvas"),this.canvas.setAttribute("id","canvas"),this.adopted=!1)}else this.canvas=document.createElement("canvas"),this.adopted=!1;this.canvas.hasAttribute(ce)||this.canvas.setAttribute(ce,""),this.canvas.style.display="block",this.canvas.style.margin="auto",this.ctx=this.canvas.getContext("2d",{colorSpace:"display-p3",alpha:!1}),this.ctx.globalAlpha=r,this.ctx.imageSmoothingEnabled=!1,this.setSize(e,n)}setSize(e,n){this.width=e,this.height=n,this.canvas.width=e,this.canvas.height=n,this.canvas.style.width=`${e/M}px`,this.canvas.style.height=`${n/M}px`,this.imageData=this.ctx.createImageData(e,n),this.ctx.putImageData(this.imageData,0,0)}_blank(e=1){let n=e?Math.max(e,.03):1;this.ctx.fillStyle=`rgba(0,0,0,${n})`,this.ctx.fillRect(0,0,this.width,this.height)}clearAll(){this.ctx.save(),this.ctx.globalAlpha=1,this._blank(),this.ctx.restore()}};function De(t,e){let n=t/e,r,a;return n>1?(r=t,a=~~(t/n)):(a=e,r=~~(e*n)),{width:r,height:a,iWidth:1/r,iHeight:1/a,area:r*a,largeDim:Math.max(r,a),smallDim:Math.min(r,a),aspectRatio:n}}function Me(t,e=window.innerWidth,n=window.innerHeight){let r=Pe(),a,s;return n<e?t>1?e>=r*t?(a=r*t,s=r):(a=e,s=a/t):(a=r*t,s=r):t>1?(a=r,s=r/t):n<r/t?(s=n,a=s*t):(a=r,s=r/t),[a,s]}var le=class{constructor(e=!1,n=!0){this.debugMode=e,this.actionMap={},this.listening=n,this.checkKeypress=this.checkKeypress.bind(this),this.registerAction=this.registerAction.bind(this),this.listening&&window.addEventListener("keydown",this.checkKeypress,!1)}checkKeypress({key:e}){this.debugMode&&console.log(`Pressed ${e}`),e in this.actionMap&&this.actionMap[e]()}inject(e){this.checkKeypress({key:e})}registerAction(e,n,r=!1){if(e.length!==1)throw new Error(`Only single-character actions may be registered. Cannot register: ${e}`);if(e in this.actionMap&&!r)throw new Error(`Action already exists for code: ${e}`);this.actionMap[e]=n}destroy(){this.listening&&window.removeEventListener("keydown",this.checkKeypress,!1),this.actionMap={}}},Fe=le;var he=class{constructor(e,n={}){this.x=-1;this.y=-1;this.isDown=!1;this.clicks=[];this.canvas=e,this.listening=n.listen!==!1,this.onPointerDown=this.onPointerDown.bind(this),this.onPointerMove=this.onPointerMove.bind(this),this.onPointerUp=this.onPointerUp.bind(this),this.listening&&(e.addEventListener("pointerdown",this.onPointerDown),e.addEventListener("pointermove",this.onPointerMove),e.addEventListener("pointerup",this.onPointerUp))}toCanvasCoords(e){let n=this.canvas.getBoundingClientRect();return{x:(e.clientX-n.left)*(this.canvas.width/n.width),y:(e.clientY-n.top)*(this.canvas.height/n.height)}}onPointerDown(e){let{x:n,y:r}=this.toCanvasCoords(e);this.x=n,this.y=r,this.isDown=!0,this.clicks.push({x:n,y:r})}onPointerMove(e){let{x:n,y:r}=this.toCanvasCoords(e);this.x=n,this.y=r}onPointerUp(e){let{x:n,y:r}=this.toCanvasCoords(e);this.x=n,this.y=r,this.isDown=!1}hasClick(){return this.clicks.length>0}consumeClick(){return this.clicks.shift()??null}inject(e,n,r){this.x=n,this.y=r,e==="down"?(this.isDown=!0,this.clicks.push({x:n,y:r})):e==="up"&&(this.isDown=!1)}destroy(){this.listening&&(this.canvas.removeEventListener("pointerdown",this.onPointerDown),this.canvas.removeEventListener("pointermove",this.onPointerMove),this.canvas.removeEventListener("pointerup",this.onPointerUp))}},He=he;function te(){return{now:()=>performance.now()}}function Le(t=0){let e=t;return{now:()=>e,set(n){e=n},advance(n){e+=n}}}var Ie=(t,e,n,r)=>({now:t,startTime:e,elapsedSinceStart:t-e,deltaSinceLastUpdate:n===null?0:t-n,deltaSinceLastRender:r===null?0:t-r}),ne=class{constructor(e,n,r,a,s,o={}){this.startTime=0;this.lastUpdateAt=null;this.lastRenderAt=null;this.clockOffsetMs=0;this.pauseStartedAt=null;this.renderAnimation=this.renderAnimation.bind(this),this.dimensionContext=De(e,n),this.R=r,this.gameManager=o.gameManager,this.hostChannel=o.hostChannel,this.clock=o.clock??te(),this.canvas=new B(this.dimensionContext.width,this.dimensionContext.height,1,o.canvasMount),this.drawingContext=this.canvas.ctx,this.keyboardManager=new Fe(!1,o.captureKeyboard??!0),this.pointerManager=new He(this.canvas.canvas,{listen:o.listenToPointer!==!1}),this.animationCart=s;let d=o.customState;this.featureState=s.getDefaultFeatureState?.(this.R,this.dimensionContext,a,this.keyboardManager,d,this.pointerManager,this.gameManager,this.hostChannel),this.cartState=s.getDefaultState(this.R,this.dimensionContext,a,this.keyboardManager,d,this.pointerManager,this.gameManager,this.featureState,this.hostChannel),this.startTime=this.clock.now(),this.canvas.clearAll()}captureFramebuffer(){let e=this.canvas.imageData,n=new ImageData(e.width,e.height);return n.data.set(e.data),n}restoreFramebuffer(e){let n=this.canvas.imageData;return n.width!==e.width||n.height!==e.height||n.data.length!==e.data.length?!1:(n.data.set(e.data),this.drawingContext.putImageData(n,0,0),!0)}setPaused(e){let n=this.clock.now();if(e){this.pauseStartedAt===null&&(this.pauseStartedAt=n);return}this.pauseStartedAt!==null&&(this.clockOffsetMs+=n-this.pauseStartedAt,this.pauseStartedAt=null)}resolveNow(e){let n=this.pauseStartedAt!==null?e-this.pauseStartedAt:0;return e-this.clockOffsetMs-n}getElapsedSinceStart(e=this.clock.now()){return Math.max(0,this.resolveNow(e)-this.startTime)}restoreClock(e,n){this.pauseStartedAt=null,this.lastUpdateAt=null,this.lastRenderAt=null;let r=Math.max(0,e);if(typeof n=="number"&&Number.isFinite(n)){this.startTime=n,this.clockOffsetMs=this.clock.now()-n-r;return}this.clockOffsetMs=0,this.startTime=this.clock.now()-r}getRandomState(){return this.R.getState()}injectKey(e){this.keyboardManager.inject(e)}injectPointer(e,n,r){this.pointerManager.inject(e,n,r)}async updateAnimationState(e,n,r=this.clock.now()){let a=this.resolveNow(r),s=Ie(a,this.startTime,this.lastUpdateAt,this.lastRenderAt);this.cartState=this.animationCart.update(this.R,e,n,this.dimensionContext,this.cartState,this.keyboardManager,this.pointerManager,this.gameManager,s,this.featureState,this.hostChannel),this.lastUpdateAt=a}async renderAnimation(e,n,r=this.clock.now()){let a=this.resolveNow(r),s=Ie(a,this.startTime,this.lastUpdateAt,this.lastRenderAt);this.animationCart.render(this.R,e,n,this.dimensionContext,this.cartState,this.drawingContext,this.canvas.imageData,this.pointerManager,this.gameManager,s,this.featureState,this.hostChannel),this.lastRenderAt=a}getCanvas(){return this.canvas.canvas}getDrawDetails(){return[this.canvas.canvas,0,0,this.dimensionContext.width,this.dimensionContext.height]}teardown(){try{this.animationCart.teardown?.(this.cartState,this.featureState)}catch(e){console.error("Error during cart teardown",e)}this.keyboardManager.destroy(),this.pointerManager.destroy()}};var re=class extends B{constructor(e,n,r=1,a=!0,s={}){if(super(e,n,r,s),this.adopted)return;let o=s.container;if(o){this.canvas.parentNode!==o&&o.appendChild(this.canvas);return}if(a){let d=document.getElementById("canvas");d&&d!==this.canvas&&d.parentNode===document.body&&document.body.removeChild(d),document.body.appendChild(this.canvas)}}};function Oe(t){let e=parseInt(t.substring(0,8),16),n=parseInt(t.substring(8,8),16),r=parseInt(t.substring(16,8),16),a=parseInt(t.substring(24,8),16);return{next:()=>{e|=0,n|=0,r|=0,a|=0;let o=(e+n|0)+a|0;return a=a+1|0,e=n^n>>>9,n=r+(r<<3)|0,r=r<<21|r>>>11,r=r+o|0,(o>>>0)/4294967296},getRegs:()=>({a:e,b:n,c:r,d:a}),setRegs:o=>{e=o.a,n=o.b,r=o.c,a=o.d}}}var ie=class{constructor(e){this.seed=e.hash,this.useA=!1,this.genA=Oe(e.hash.substring(2,32)),this.genB=Oe(e.hash.substring(34,32)),this.prngA=this.genA.next,this.prngB=this.genB.next;for(let n=0;n<1e6;n+=2)this.prngA(),this.prngB()}getState(){let e=this.genA.getRegs(),n=this.genB.getRegs();return{seed:this.seed,useA:this.useA,prngA:{a:e.a,b:e.b,c:e.c,d:e.d},prngB:{a:n.a,b:n.b,c:n.c,d:n.d}}}setState(e){if(e.seed!==this.seed)throw new Error(`Random.setState: seed ${e.seed} does not match ${this.seed}`);this.useA=e.useA,this.genA.setRegs(e.prngA),this.genB.setRegs(e.prngB)}r_zero_one(){return this.useA=!this.useA,this.useA?this.prngA():this.prngB()}dec(e,n){return e===void 0?this.r_zero_one():n===void 0?e*this.r_zero_one():e+(n-e)*this.r_zero_one()}int(e,n){return n===void 0&&(n=e,e=0),Math.floor(this.dec(e,n))}bool(e=.5){return this.r_zero_one()<e}sign(){return this.bool()?1:-1}choose(e){return e[this.int(e.length)]}};var Ne="bafybeicjwcq5lxxtfnyj4p2ugcr7ctyb5wl62cbcechj6tsabdq5whcs7u",_e="https://ipfs.io/ipfs/";function mt(t){return t.endsWith("/")?t:`${t}/`}var J=null;function gt(t){return[...Array(t)].map(()=>Math.floor(Math.random()*16).toString(16)).join("")}function yt(t){return t&&t.length>0?t:[{cid:Ne}]}function bt(t){return t.startsWith("0x")?t:`0x${t}`}var We=/^(0[xX])?[0-9a-fA-F]{64}$/;function vt(t){let e="",n=2166136261,r=522970236;for(let a=0;e.length<64;a++){for(let s=0;s<t.length;s++)n^=t.charCodeAt(s)+a,n=Math.imul(n,16777619),r^=t.charCodeAt(s)+a*17,r=Math.imul(r,16777619);e+=(n>>>0).toString(16).padStart(8,"0"),e+=(r>>>0).toString(16).padStart(8,"0")}return`0x${e.slice(0,64)}`}function Ue(t){let e=typeof t=="number"?String(t):t;return We.test(e)?`0x${(e.startsWith("0x")||e.startsWith("0X")?e.slice(2):e).toLowerCase()}`:vt(e)}function $e(t,e){if(typeof t=="number"||e==="deterministic")return Ue(t);let n=String(t);return We.test(n)?Ue(n):n.startsWith("0x")||n.startsWith("0X")?n:`0x${n}`}function At(t){if(!t&&typeof tokenData<"u"&&tokenData?.hash)return{hash:tokenData.hash,tokenId:String(tokenData.tokenId),externalAssetDependencies:yt(tokenData.externalAssetDependencies),preferredIPFSGateway:mt(tokenData.preferredIPFSGateway||_e),preferredArweaveGateway:tokenData.preferredArweaveGateway};let e=typeof window<"u"?new URLSearchParams(window.location.search):new URLSearchParams;return{hash:t?bt(t):e.get("hash")||`0x${gt(64)}`,tokenId:"18009999",externalAssetDependencies:[{cid:Ne}],preferredIPFSGateway:_e}}function pe(t){let e=t?.useCache!==!1;if(e&&J&&!t?.hash)return J;let n=At(t?.hash);return e?J=n:J||(J=n),n}function Be(t){return new Array(32).fill(null).map((e,n)=>parseInt(t.hash.slice(2+n*2,4+n*2),16))}async function me(){let t=await import("tone");if(typeof t.start=="function")return t;let e=t.default;return e&&typeof e.start=="function"?e:t}var Ve={id:"tone",async load(){await Promise.resolve().then(()=>(je(),Ct))},async unlock(){await Ve.load(),await(await me()).start()},async resumeIfSuspended(){let t=await me();t.context.state==="suspended"&&await t.context.resume()},async suspendIfRunning(){let e=(await me()).context.rawContext;"suspend"in e&&e.state==="running"&&await e.suspend()}},ze={tone:Ve};function ge(t){if(!t)return[];let e=Array.isArray(t)?t:[t],n=[];for(let r of e){if(!(r in ze)){console.warn(`Unknown audio library "${r}"`);continue}let a=r;n.includes(a)||n.push(a)}return n}function ye(t){return t.map(e=>ze[e])}var se="$cyberartTa",F=class extends Error{constructor(e){super(e),this.name="IncompatibleCartStateError"}},be={Float32Array,Float64Array,Int8Array,Int16Array,Int32Array,Uint8Array,Uint8ClampedArray,Uint16Array,Uint32Array};function kt(t){for(let e of Object.keys(be))if(t instanceof be[e])return e}function Ye(t){return ArrayBuffer.isView(t)&&!(t instanceof DataView)}function H(t){if(t===null||typeof t!="object"||Array.isArray(t))return!1;let e=Object.getPrototypeOf(t);return e===Object.prototype||e===null}function ve(t){return H(t)?typeof t[se]=="string"&&Array.isArray(t.d):!1}function Et(t){return t==null?!1:typeof t=="function"?!0:!(typeof t!="object"||Array.isArray(t)||Ye(t)||H(t))}var Rt=new Set(["audioContextStarted","midiSynths","keepRatioPrimed","audioInitStarted","musicSeekApplied"]);function Ge(t){return t===null?"null":ve(t)?String(t[se]):Array.isArray(t)?"array":H(t)?"object":typeof t}function xt(t,e){return t===e||t==="null"||e==="null"}function qe(t){return t.trim().toLowerCase().replace(/^0x/,"")}function Je(t,e,n,r){if(!(!n&&!r)&&qe(t)!==qe(e))throw new F(`Generative cart state is for seed "${e}", but the live token is "${t}"`)}function K(t){return typeof t=="number"&&Number.isFinite(t)&&t>0}function Xe(t,e){let n=t.dimensions;if(n&&K(n.width)&&K(n.height))return n;if(e&&K(e.width)&&K(e.height))return{width:e.width,height:e.height};if(H(t.state)){let r=t.state.containerWidth,a=t.state.containerHeight;if(K(r)&&K(a))return{width:r,height:a}}return null}function j(t,e=new WeakSet){if(t===null||typeof t=="string"||typeof t=="boolean")return t;if(typeof t=="number")return Number.isFinite(t)?t:null;if(!(typeof t=="function"||typeof t>"u"||typeof t=="bigint"||typeof t=="symbol")){if(Ye(t)){let n=kt(t);return n?{[se]:n,d:Array.from(t)}:void 0}if(typeof t=="object"&&!e.has(t)){e.add(t);try{if(Array.isArray(t)){let a=[],s=0;for(let o of t){let d=j(o,e);d!==void 0&&(a.push(d),s++)}return t.length>0&&s===0?void 0:a}if(!H(t)||Et(t))return;let n=Object.keys(t),r={};for(let a of n){if(Rt.has(a))continue;let s=j(t[a],e);s!==void 0&&(r[a]=s)}return n.length>0&&Object.keys(r).length===0?void 0:r}finally{e.delete(t)}}}}function Q(t){if(ve(t)){let e=be[t[se]];return e?new e(t.d.map(n=>Number(n))):t}if(Array.isArray(t))return t.map(e=>Q(e));if(H(t)){let e={};for(let n of Object.keys(t))e[n]=Q(t[n]);return e}return t}function Ae(t,e,n,r,a=!0){if(a&&n&&r&&n!==r)throw new F(`Cart state is for "${r}", but the live cart is "${n}"`);if(!H(e)){if(a)throw new F("Cart state snapshot is empty");return}let s=Object.keys(e);if(s.length===0){if(a)throw new F("Cart state snapshot is empty");return}let o=j(t);if(!H(o)||Object.keys(o).length===0){if(a)throw new F("Live cart has no serializable state");return}let d=s.filter(l=>l in o);if(d.length===0){if(a)throw new F("Cart state snapshot does not overlap the live cart shape");return}for(let l of d){let y=Ge(o[l]),f=Ge(e[l]);if(!xt(y,f))throw new F(`Cart state field "${l}" has type ${f}, live cart expects ${y}`);if(y==="object"){let u=e[l],g=t[l];H(u)&&!ve(u)&&Ae(g,u,void 0,void 0,!1)}}}function Qe(t,e){if(!H(t)||!H(e))return;let n=j(t);if(H(n))for(let r of Object.keys(e))r in n&&(t[r]=Q(e[r]))}function Ze(t){let e=typeof t=="string"?JSON.parse(t):t;if(!e||typeof e!="object")throw new F("Cart state bundle is not an object");if(e.version!==1)throw new F(`Unsupported cart state version ${String(e.version)}`);if(typeof e.seed!="string"||typeof e.framesElapsed!="number")throw new F("Cart state bundle is missing seed or framesElapsed");return e}var we="cyberart.asset.ready",Se="cyberart.asset.failed";function U(t){try{return JSON.parse(JSON.stringify(t))}catch{return t}}function et(t){return{type:t.status==="ready"?we:Se,kind:"state",payload:t.detail===void 0?{id:t.id}:{id:t.id,detail:t.detail}}}function Pt(t){if(!t||typeof t!="object")return 0;let e=t;return typeof e.startTime=="number"&&typeof e.lastSimulationUpdateAt=="number"?Math.max(0,e.lastSimulationUpdateAt-e.startTime):0}function Dt(t,e){if(typeof window.resizeTo!="function")return!1;try{if(window.top!==window)return!1}catch{return!1}let n=Math.max(1,Math.round(t)),r=Math.max(1,Math.round(e)),a=Math.max(0,window.outerWidth-window.innerWidth),s=Math.max(0,window.outerHeight-window.innerHeight);try{window.resizeTo(n+a,r+s)}catch{return!1}return Math.abs(window.innerWidth-n)<=8&&Math.abs(window.innerHeight-r)<=8}var Mt=[[0,0],[16,9],[9,16],[4,3],[3,4],[2,1],[1,2],[3,1],[1,3],[1,1]],ke=Mt[0],Ft=ke[0]/ke[1],Ce=30,Ht=120,Lt=3840/2160,It=2160/3840,oe=class{constructor(e=Ce,n=!1,r=window.innerWidth,a=window.innerHeight,s=!0,o,d={}){this.framesElapsed=0;this.frameRate=Ce;this._paused=!1;this.savedToken=!1;this.prepared=!1;this.loopRunning=!1;this.fallbackAudio=[];this.audioLibrariesInternal=[];this.virtualClock=null;this.scriptedActions=[];this.initialScriptedActions=[];this.appliedActions=[];this.consumedActionIndexes=new Set;this.outboundEvents=[];this.consecutiveErrorCount=0;this.lastErrorLogAt=0;this.reinitStayPaused=!1;this.reinitPending=!1;this.lastExportedFramebuffer=null;this.pinnedOutput=null;this.pinViewportAtImport=null;this.importing=!1;this.drawLoop=this.drawLoop.bind(this),this.loadCart=this.loadCart.bind(this),this.prepareCart=this.prepareCart.bind(this),this.beginPlayback=this.beginPlayback.bind(this),this.reinit=this.reinit.bind(this),this.tuneFramerate=this.tuneFramerate.bind(this),this.container=d.container,this.seed=d.seed,this.captureKeyboard=d.captureKeyboard??!0,this.customState=d.customState,this.hostChannel=d.hostChannel,this.fallbackAudio=ge(d.audio),this.audioLibrariesInternal=this.fallbackAudio;let l=d.deterministic;this.deterministic=!!l;let y=l&&typeof l=="object"?l:{};if(this.deterministic){if(d.clock){let f=d.clock;if(typeof f.advance!="function")throw new Error("deterministic mode requires a virtual clock with advance()");this.virtualClock=f,this.clock=f}else this.virtualClock=Le(y.origin??0),this.clock=this.virtualClock;this.initialScriptedActions=U(y.actions??[]),this.scriptedActions=U(this.initialScriptedActions)}else this.clock=d.clock??te();this.isBodyCanvas=this.container?!1:s,this.autoMode=n,this.aspectRatio=Ft,this.selectedAsp=ke,this.isFullscreen=!!document.fullscreenElement,this.updateFrameRate(e),this.tempUnpause=!1,this.synchronous=$,this.containerWidth=r,this.containerHeight=a,this.gameManager=o,this.init(!0)}setGameManager(e){this.gameManager=e}reinit(e){if(!this.importing){if(this.shouldKeepPinnedOutput()){this.fitPinnedCanvas();return}this.reinitPending||(this.reinitStayPaused=this._paused,this.reinitPending=!0),this.paused=!0,clearTimeout(this.reinitTimeout),this.reinitTimeout=setTimeout(()=>{if(this.importing){this.paused=this.reinitStayPaused,this.reinitPending=!1;return}this.updateInProgress?this.reinit(e):(this.requestedAnimationFrame&&cancelAnimationFrame(this.requestedAnimationFrame),this.clearPinnedOutput(),this.init(),this.reloadCart(),this.paused=this.reinitStayPaused,this.reinitPending=!1)},150)}}initSeed(){this.tokenData=this.seed?pe({hash:this.seed,useCache:!1}):pe(),this.rawParams=Be(this.tokenData),this.mintNo=parseInt(this.tokenData.tokenId)%1e6,console.log("token",this.mintNo,this.tokenData.hash)}init(e=!1){e&&this.initSeed(),this.pureAspectUpdate(this.selectedAsp);let n=this.aspectRatio,[r,a]=Me(n,this.containerWidth,this.containerHeight);r*=M,a*=M,this.width=~~r,this.height=~~a,this.atCenterX=this.width/2,this.atCenterY=this.height/2,this.mainCanvas?this.mainCanvas.setSize(this.width,this.height):this.mainCanvas=new re(this.width,this.height,1,this.isBodyCanvas,this.canvasMountOptions())}loadCart(e){this.prepareCart(e)&&this.beginPlayback()}prepareCart(e){if(this.prepared)return!0;try{let n=~~(this.width/1),r=~~(this.height/this.width*n),a=new ie(this.tokenData),s=new ne(n,r,a,this.rawParams,e,{gameManager:this.gameManager,canvasMount:this.canvasMountOptions(),customState:this.customState,captureKeyboard:this.deterministic?!1:this.captureKeyboard,hostChannel:this.hostChannel,clock:this.clock,listenToPointer:!this.deterministic});return this.animation=s,this.animationCart=e,this.paused=!1,this.framesElapsed=0,this.outboundEvents=[],this.scriptedActions=U(this.initialScriptedActions),this.appliedActions=[],this.consumedActionIndexes=new Set,this.outboundUnsubscribe?.(),this.outboundUnsubscribe=void 0,this.deterministic&&this.hostChannel&&(this.outboundUnsubscribe=this.hostChannel.onEvent(o=>{this.outboundEvents.push(o)})),this.R=a,this.applyCartFrameRate(e,s),this.resolveAudioLibraries(e),this.prepared=!0,!0}catch(n){return console.error(n),!1}}applyCartFrameRate(e,n){let r=e.metadata,a=r?.frameRate??Ce,s=n.cartState?.visualMode??n.featureState?.visualMode,o=s&&r?.frameRateByVisualMode?r.frameRateByVisualMode[s]:void 0;this.updateFrameRate(typeof o=="number"&&o>0?o:a)}get audioLibraries(){return this.audioLibrariesInternal}get needsAudio(){return this.audioLibrariesInternal.length>0}resolveAudioLibraries(e){this.audioLibrariesInternal=ge(e.metadata?.audio)}async unlockAudio(){if(this.audioLibrariesInternal.length===0)return;let e=ye(this.audioLibrariesInternal);if($){for(let n of e)await n.load();return}for(let n of e)await n.unlock()}async resumeAudioLibraries(){if(!(this.paused||$))for(let e of ye(this.audioLibrariesInternal))try{await e.resumeIfSuspended()}catch(n){console.error(`Failed to resume audio library "${e.id}" after reload`,n)}}beginPlayback(){!this.prepared||this.loopRunning||(this.prepared=!1,this.loopRunning=!0,this.consecutiveErrorCount=0,!this.deterministic&&(this.requestedAnimationFrame=requestAnimationFrame(this.drawLoop)))}get isPrepared(){return this.prepared}get isLoopRunning(){return this.loopRunning}get isDeterministic(){return this.deterministic}getClock(){return{now:this.clock.now(),framesElapsed:this.framesElapsed,frameRate:this.frameRate}}getRandomState(){return this.requirePreparedAnimation().getRandomState()}schedule(e){this.scriptedActions.push(U(e))}async getReplayMetadata(){let e=await this.exportState();return{seed:this.tokenData.hash,clock:this.getClock(),rng:this.getRandomState(),actions:U(this.scriptedActions),applied:U(this.appliedActions),events:U(this.outboundEvents),state:e.state}}async step(e=1){if(!this.deterministic)throw new Error("step() requires createRuntime({ deterministic: true })");this.requirePreparedAnimation(),this.prepared&&!this.loopRunning&&this.beginPlayback(),this.paused=!1;let n=Math.max(0,Math.floor(e));for(let r=0;r<n&&this.animation;r++){let a=this.framesElapsed;if(this.applyScheduledActions(a),await this.processFrame(this.clock.now(),{ignorePause:!0,scheduleNext:!1}),this.framesElapsed===a||(this.virtualClock?.advance(this.targetDrawTime),!this.loopRunning))break}}async advance(e){let n=Math.max(0,Math.round(e/this.targetDrawTime));await this.step(n)}applyScheduledActions(e){let n=this.animation;n&&this.scriptedActions.forEach((r,a)=>{r.atFrame===e&&(this.consumedActionIndexes.has(a)||(this.consumedActionIndexes.add(a),r.type==="pointer"?n.injectPointer(r.pointer.kind,r.pointer.x,r.pointer.y):r.type==="key"?n.injectKey(r.key):r.type==="event"?this.hostChannel?.dispatch(r.event):r.type==="asset"&&this.hostChannel?.dispatch(et(r)),this.appliedActions.push({frame:e,action:r})))})}get paused(){return this._paused}set paused(e){this._paused!==e&&(this._paused=e,this.animation?.setPaused(e))}async waitUntilUpdateIdle(){for(;this.updateInProgress;)await new Promise(e=>{this.deterministic?queueMicrotask(e):typeof requestAnimationFrame=="function"?requestAnimationFrame(()=>e()):setTimeout(e,0)})}requirePreparedAnimation(){if(!this.animation)throw new Error("No prepared cart");return this.animation}async exportState(){let e=this.requirePreparedAnimation(),n=this._paused;this.paused=!0,await this.waitUntilUpdateIdle();try{this.lastExportedFramebuffer=e.captureFramebuffer();let r=e.getCanvas();return{version:1,cartId:this.animationCart?.metadata?.id,generative:this.animationCart?.metadata?.generative,seed:this.tokenData.hash,framesElapsed:this.framesElapsed,elapsedSinceStart:e.getElapsedSinceStart(),dimensions:{width:r.width,height:r.height,cssWidth:this.containerWidth,cssHeight:this.containerHeight,dpr:M},state:j(e.cartState)}}finally{this.paused=n}}async exportStateJSON(){return JSON.stringify(await this.exportState())}peekExportedFramebuffer(){return this.lastExportedFramebuffer}peekSeed(){return this.tokenData?.hash}isGenerative(){return this.animationCart?.metadata?.generative===!0}async importState(e,n){let r=this.requirePreparedAnimation(),a=Ze(e),s=this._paused,o=this.loopRunning;this.paused=!0,await this.waitUntilUpdateIdle(),Ae(r.cartState,a.state,this.animationCart?.metadata?.id,a.cartId),Je(this.tokenData.hash,a.seed,this.animationCart?.metadata?.generative,a.generative),clearTimeout(this.reinitTimeout),this.reinitPending=!1,this.importing=!0;let d=Xe(a,n?.framebuffer??this.lastExportedFramebuffer);if(d){this.pinOutputSize(d);let f=d.cssWidth??d.width/M,u=d.cssHeight??d.height/M;Dt(f,u),this.syncContainerFromDom(),this.pinViewportAtImport={w:this.containerWidth,h:this.containerHeight}}let l=this.customState,y=!1;try{if(this.customState=Q(a.state),this.unloadCart(),!this.prepareCart(this.animationCart))throw new Error("Failed to prepare cart while loading state");this.animation.cartState!==this.customState&&Qe(this.animation.cartState,a.state),this.framesElapsed=a.framesElapsed;let f=this.animation,u=f.cartState,g=typeof a.elapsedSinceStart=="number"?a.elapsedSinceStart:Pt(u);f.restoreClock(g,typeof u?.startTime=="number"?u.startTime:void 0),s&&f.setPaused(!0);let C=n?.framebuffer??this.lastExportedFramebuffer;C&&f.restoreFramebuffer(C)?u.keepRatioPrimed=!0:await f.renderAnimation(this.framesElapsed,this.rawParams),this.fitPinnedCanvas(),y=!0}catch(f){throw this.clearPinnedOutput(),this.customState=l,this.paused=s,this.animationCart&&(this.syncContainerFromDom(),this.init(),this.reloadCart()),f}finally{this.importing=!1,y&&(this.customState=l,this.paused=s,o&&this.beginPlayback())}}unloadCart(){this.loopRunning=!1,this.requestedAnimationFrame&&cancelAnimationFrame(this.requestedAnimationFrame),this.drawLoopTimeout&&clearTimeout(this.drawLoopTimeout),this.animation?.teardown(),this.animation=void 0,this.prepared=!1,this.audioLibrariesInternal=this.fallbackAudio,this.mainCanvas?.clearAll()}reloadCart(e=!1){let n=this.animationCart;if(!n)return;this.pinnedOutput&&(this.clearPinnedOutput(),this.syncContainerFromDom(),this.init());let r=this.reinitPending?this.reinitStayPaused:this._paused;this.unloadCart(),e&&this.initSeed(),this.loadCart(n),this.paused=r,!this.paused&&!$&&this.resumeAudioLibraries()}getFrameRate(){return this.frameRate}updateFrameRate(e){if(this.frameRate=e,e>=1)this.targetDrawTime=1e3/e;else{let r=1/(2-e);this.targetDrawTime=1e3/r}this.drawTime=this.targetDrawTime}canvasMountOptions(){return{container:this.container,adoptFromDocument:!this.container}}syncContainerFromDom(){if(this.container){this.containerWidth=this.container.clientWidth||this.containerWidth,this.containerHeight=this.container.clientHeight||this.containerHeight;return}this.containerWidth=window.innerWidth,this.containerHeight=window.innerHeight}pinOutputSize(e){this.pinnedOutput=e,this.width=~~e.width,this.height=~~e.height,this.atCenterX=this.width/2,this.atCenterY=this.height/2,this.aspectRatio=this.width/this.height,this.mainCanvas&&this.mainCanvas.setSize(this.width,this.height)}shouldKeepPinnedOutput(){return this.pinnedOutput?(this.syncContainerFromDom(),this.viewportMatches(this.pinnedCssSize())?!0:!!(this.pinViewportAtImport&&this.viewportMatches(this.pinViewportAtImport))):!1}pinnedCssSize(){let e=this.pinnedOutput;return{w:e.cssWidth??e.width/M,h:e.cssHeight??e.height/M}}viewportMatches(e){return Math.abs(this.containerWidth-e.w)<8&&Math.abs(this.containerHeight-e.h)<8}fitPinnedCanvas(){let e=this.pinnedOutput,n=this.canvas;if(!e||!n)return;this.container&&!this.container.style.position&&(this.container.style.position="relative");let r=this.containerWidth||window.innerWidth,a=this.containerHeight||window.innerHeight,s=e.width/M,o=e.height/M;if(s<1||o<1||r<1||a<1)return;let d=Math.min(r/s,a/o),l=s*d,y=o*d;n.style.position="absolute",n.style.left="50%",n.style.top="50%",n.style.transform="translate(-50%, -50%)",n.style.margin="0",n.style.width=`${l}px`,n.style.height=`${y}px`,n.style.imageRendering=Math.abs(d-1)<.01?"auto":"pixelated"}clearPinnedOutput(){let e=this.canvas;this.pinnedOutput=null,this.pinViewportAtImport=null,e&&(e.style.position="",e.style.left="",e.style.top="",e.style.transform="",e.style.imageRendering="",e.style.width="",e.style.height="",e.style.margin="auto")}get canvas(){return this.animation?.getCanvas()??this.mainCanvas?.canvas}destroy(){this.outboundUnsubscribe?.(),this.outboundUnsubscribe=void 0,this.clearPinnedOutput(),this.unloadCart(),clearTimeout(this.reinitTimeout),this.mainCanvas&&!this.mainCanvas.adopted&&this.mainCanvas.canvas.remove()}drawIt(){}tuneFramerate(e){let n=this.lastCall||e;this.lastCall=e,this.drawTime=Math.max(0,this.drawTime+this.targetDrawTime-this.lastCall+n)}async processFrame(e,n={}){let r=n.ignorePause===!0,a=n.scheduleNext!==!1;if(!this.loopRunning&&!r)return;let s=!1,o,d="update";try{if(r||!this.paused||this.tempUnpause){if(!$&&!r&&this.tuneFramerate(e),!this.animation)return;if(d="update",this.updateInProgress=!0,await this.animation.updateAnimationState(this.framesElapsed,this.rawParams,e),this.updateInProgress=!1,d="render",await this.animation.renderAnimation(this.framesElapsed,this.rawParams,e),this.autoMode&&this.animation.cartState.saveToken&&!this.savedToken&&!new URLSearchParams(window.location.search).get("hash")){let f=localStorage.getItem("goodones"),u=JSON.stringify(f?[...JSON.parse(f),this.tokenData.hash]:[this.tokenData.hash]);localStorage.setItem("goodones",u),this.savedToken=!0,localStorage.setItem(this.tokenData.hash,this.mainCanvas.canvas.toDataURL("image/png")),window.location.reload(),this.loopRunning=!1;return}this.framesElapsed++,this.tempUnpause&&(this.tempUnpause=!1)}d="draw",this.drawIt()}catch(l){s=!0,o=l,this.handleFrameError(l,d)}finally{this.updateInProgress=!1}s?(this.consecutiveErrorCount++,this.consecutiveErrorCount>=Ht&&(this.loopRunning=!1,this.onError?.(o,{phase:d,consecutive:this.consecutiveErrorCount,stopped:!0}))):this.consecutiveErrorCount=0,!(!this.loopRunning||!a)&&(this.drawLoopTimeout=setTimeout(()=>{this.requestedAnimationFrame=requestAnimationFrame(this.drawLoop)},this.drawTime))}async drawLoop(e){await this.processFrame(e,{scheduleNext:!0})}handleFrameError(e,n){let r=performance.now();r-this.lastErrorLogAt>=1e3&&(this.lastErrorLogAt=r,console.error(`Animation ${n} error:`,e)),this.consecutiveErrorCount===0&&this.onError?.(e,{phase:n,consecutive:1,stopped:!1})}pureAspectUpdate(e){if(e[0]===0&&e[1]===0){let r=this.containerWidth||window.innerWidth,a=this.containerHeight||window.innerHeight,s=r/a;this.aspectRatio=Math.min(Lt,Math.max(It,s))}else this.aspectRatio=e[0]/e[1]}};var Ot="HostChannel has been destroyed",de=class{constructor(){this.inbound=[];this.listeners=[];this.closed=!1}dispatch(e){this.requireOpen(),this.inbound.push(e),this.inbound.length>32&&this.inbound.splice(0,this.inbound.length-32)}consume(){if(this.requireOpen(),this.inbound.length===0)return[];let e=this.inbound;return this.inbound=[],e}emit(e){this.requireOpen();for(let n of this.listeners)n(e)}onEvent(e){return this.requireOpen(),this.listeners.push(e),()=>{this.listeners=this.listeners.filter(n=>n!==e)}}clearInbound(){this.requireOpen(),this.inbound=[]}clear(){this.inbound=[],this.listeners=[]}close(){this.closed=!0,this.clear()}requireOpen(){if(this.closed)throw new Error(Ot)}};var _t=["image","audio","font","spritesheet"],Ut=["timeout","cors","not-found","invalid","aborted","resolver"],Z="cyberart:fallback/silent",tt="Asset preloader has been destroyed",Nt=4,Wt=new Set(_t),$t=new Set(Ut),Bt={timeout:"asset load timed out",cors:"CORS blocked this asset","not-found":"asset was not found",invalid:"asset declaration or resource is invalid",aborted:"asset load was aborted",resolver:"asset resolver failed"};function Kt(t){return typeof t=="string"&&Wt.has(t)}function jt(t){return typeof t=="string"&&$t.has(t)}function Ee(t){if(!t||typeof t!="object")return!1;let e=t;return typeof e.id=="string"&&typeof e.ref=="string"&&jt(e.code)&&typeof e.message=="string"}function x(t){return{id:t.id,ref:t.ref,code:t.code,message:t.message&&t.message.length>0?t.message:Bt[t.code]}}function V(t,e){return{type:t==="ready"?we:Se,kind:"state",payload:e}}function Vt(t){return t instanceof Error&&t.name==="AbortError"||typeof DOMException<"u"&&t instanceof DOMException&&t.name==="AbortError"}function Re(t){return t?{...t}:void 0}function L(t){let e={id:t.id,ref:t.ref,type:t.type,url:t.url};return t.integrity!==void 0&&(e.integrity=t.integrity),t.provenance&&(e.provenance=Re(t.provenance)),t.cors!==void 0&&(e.cors=t.cors),t.usedFallback&&(e.usedFallback=!0),t.managed&&(e.managed=!0),e}function ee(t){return{id:t.id,ref:t.ref,code:t.code,message:t.message}}function zt(t){if(t.state==="ready"){let e={state:"ready",resource:L(t.resource)};return t.failure&&(e.failure=ee(t.failure)),e}return t.state==="failed"?{state:"failed",failure:ee(t.failure)}:{state:t.state}}function Gt(t){if(!t||typeof t!="object")return x({id:"",ref:"",code:"invalid",message:"declaration is required"});if(typeof t.id!="string"||t.id.length===0)return x({id:typeof t.id=="string"?t.id:"",ref:typeof t.ref=="string"?t.ref:"",code:"invalid",message:"id is required"});if(typeof t.ref!="string"||t.ref.length===0)return x({id:t.id,ref:"",code:"invalid",message:"ref is required"});if(!Kt(t.type))return x({id:t.id,ref:t.ref,code:"invalid",message:`unsupported type ${String(t.type)}`});if(t.integrity!==void 0&&typeof t.integrity!="string")return x({id:t.id,ref:t.ref,code:"invalid",message:"integrity must be a string"});if(t.timeoutMs!==void 0&&(typeof t.timeoutMs!="number"||!Number.isFinite(t.timeoutMs)||t.timeoutMs<0))return x({id:t.id,ref:t.ref,code:"invalid",message:"timeoutMs must be a non-negative finite number"})}function nt(t){return{id:t.id,ref:Z,type:t.type,url:Z,usedFallback:!0,cors:"omit"}}function rt(t,e){return Ee(e)?{id:t.id,ref:t.ref,code:e.code,message:e.message}:Vt(e)?x({id:t.id,ref:t.ref,code:"aborted"}):x({id:t.id,ref:t.ref,code:"resolver",message:e instanceof Error?e.message:String(e)})}function it(t,e){if(!e||typeof e.url!="string"||e.url.length===0)throw x({id:t.id,ref:t.ref,code:"invalid",message:"resolver returned no url"});if(e.integrity&&t.integrity&&e.integrity!==t.integrity)throw x({id:t.id,ref:t.ref,code:"invalid",message:"integrity mismatch"});let n=L(e);return n.id=t.id,n.ref=e.ref||t.ref,n.type=t.type,!n.integrity&&t.integrity&&(n.integrity=t.integrity),!n.provenance&&t.provenance&&(n.provenance=Re(t.provenance)),n}function at(t){if(typeof t?.resolver?.resolve!="function")throw new Error("createAssetPreloader: resolver is required");let e=t.emitEvents!==!1,n=t.wallClockTimeout!==!1,r=new Map,a=[],s=new Map,o=new Map,d=new Map,l=new Map,y=new Map,f=new Set,u=!1;function g(i){return i.code==="aborted"||i.code==="timeout"}function C(i,h,p){let v=rt(i,p);return v.code==="timeout"?v:h.aborted?x({id:i.id,ref:i.ref,code:"aborted"}):v}function m(i,h){let p=y.get(i);p||(p=new Set,y.set(i,p)),p.add(h)}function k(i){if(i?.state==="ready")return`${i.resource.type}\0${i.resource.ref}`}function c(i,h){for(let[p,v]of y)if(p!==h&&v.has(i))return!0;for(let[p,v]of r)if(p!==h&&k(v)===i)return!0;return!1}function z(i,h){let p=new Set(y.get(i)),v=k(h);v&&p.add(v),y.delete(i);for(let D of p)c(D,i)||d.delete(D)}function I(){let i=0,h=0,p=0,v=0,D={};for(let[S,w]of r)D[S]=zt(w),w.state==="pending"||w.state==="loading"?i+=1:w.state==="failed"?p+=1:(h+=1,(w.resource.usedFallback||w.failure)&&(v+=1));return{total:r.size,pending:i,ready:h,failed:p,fallbacks:v,items:D,failures:a.map(ee)}}function G(){if(f.size===0)return;let i=I();for(let h of f)h(i)}function R(i){a.push(ee(i))}function P(i){u||!e||!t.dispatch||t.dispatch(i)}function N(i){if(i?.managed&&i.url.startsWith("blob:")&&!(typeof URL>"u"||typeof URL.revokeObjectURL!="function"))try{URL.revokeObjectURL(i.url)}catch{}}function A(i,h){if(u)return;let p=r.get(i);p?.state==="ready"&&N(p.resource),r.set(i,h),G()}function q(i){if(i.fallback!==void 0)return i.fallback==="silent"?{id:`${i.id}::fallback`,ref:Z,type:i.type}:typeof i.fallback=="string"?{id:`${i.id}::fallback`,ref:i.fallback,type:i.type}:{...i.fallback,id:typeof i.fallback.id=="string"&&i.fallback.id.length>0?i.fallback.id:`${i.id}::fallback`}}function T(i,h,p){let v=`${i.type}\0${i.ref}`,D=d.get(v);if(D)return h.aborted?Promise.reject(x({id:i.id,ref:i.ref,code:"aborted"})):(m(p,v),Promise.resolve(L(D.resource)));if(h.aborted)return Promise.reject(x({id:i.id,ref:i.ref,code:"aborted"}));let S=l.get(v);if(!S){let b=new AbortController,E={id:i.id,ref:i.ref,type:i.type};i.integrity!==void 0&&(E.integrity=i.integrity),i.provenance&&(E.provenance=Re(i.provenance)),S={promise:Promise.resolve().then(()=>t.resolver.resolve(E,b.signal)).then(W=>{let _=it(i,W);if(b.signal.aborted)throw x({id:i.id,ref:i.ref,code:"aborted"});return d.set(v,{resource:L(_)}),_}).catch(W=>{throw rt(i,W)}).finally(()=>{l.delete(v)}),controller:b,waiters:0},l.set(v,S)}let w=S;return w.waiters+=1,new Promise((b,E)=>{let O=!1,W=(Y,pt)=>{O||(O=!0,h.removeEventListener("abort",_),w.waiters-=1,pt&&w.waiters<=0&&w.controller.abort(),Y())},_=()=>{W(()=>E(x({id:i.id,ref:i.ref,code:"aborted"})),!0)};if(h.aborted){_();return}h.addEventListener("abort",_,{once:!0}),w.promise.then(Y=>{if(!O){if(h.aborted){_();return}m(p,v),W(()=>b(L(Y)),!1)}},Y=>{if(!O){if(h.aborted){_();return}W(()=>E(Y),!1)}})})}function ue(i,h,p){if(h.aborted)return Promise.reject(x({id:i.id,ref:i.ref,code:"aborted"}));if(i.ref===Z)return Promise.resolve(nt(i));let v=new AbortController,D=()=>v.abort();h.addEventListener("abort",D,{once:!0});let S=i.timeoutMs??t.timeoutMs,w,b=!1;return n&&S!==void 0&&S>0&&Number.isFinite(S)&&(w=setTimeout(()=>{b=!0,v.abort()},S)),T(i,v.signal,p).then(E=>{let O=it(i,E);return O.id=i.id,O}).catch(E=>{throw b?x({id:i.id,ref:i.ref,code:"timeout"}):E}).finally(()=>{w!==void 0&&clearTimeout(w),h.removeEventListener("abort",D)})}async function xe(i,h,p,v){try{return{resource:await ue(i,h,v)}}catch(D){let S=C(i,h,D);if(g(S)||h.aborted||p>=Nt)throw S;let w=q(i);if(!w)throw S;if(h.aborted)throw x({id:i.id,ref:i.ref,code:"aborted"});if(i.fallback==="silent"||w.ref===Z)return{resource:nt(i),failure:S};try{let b=await xe(w,h,p+1,v);return{resource:{...L(b.resource),id:i.id,usedFallback:!0},failure:S}}catch(b){let E=Ee(b)&&!g(b)&&!h.aborted?b:C(i,h,b);throw!g(E)&&!h.aborted&&R(S),E}}}async function ht(i,h){if(u)throw new Error(tt);let p=r.get(i.id);if(p?.state==="ready"||p?.state==="failed")return;let v=s.get(i.id);if(v){await v;return}let D=(async()=>{let S=Gt(i);if(S){A(i.id,{state:"failed",failure:S}),R(S),P(V("failed",{id:i.id,ref:i.ref,failure:S}));return}A(i.id,{state:"loading"});let w=o.get(i.id)??new AbortController;o.has(i.id)||o.set(i.id,w);try{let b=await xe(i,w.signal,h,i.id);if(u)return;if(w.signal.aborted){let E=x({id:i.id,ref:i.ref,code:"aborted"});A(i.id,{state:"failed",failure:E}),R(E),P(V("failed",{id:i.id,ref:i.ref,failure:E}));return}if(b.resource.id=i.id,b.failure){A(i.id,{state:"ready",resource:b.resource,failure:b.failure}),R(b.failure),P(V("failed",{id:i.id,ref:i.ref,failure:b.failure,resource:L(b.resource)})),P(V("ready",{id:i.id,ref:b.resource.ref,resource:L(b.resource),failure:b.failure}));return}A(i.id,{state:"ready",resource:b.resource}),P(V("ready",{id:i.id,ref:i.ref,resource:L(b.resource)}))}catch(b){if(u)return;let E=Ee(b)&&!g(b)&&!w.signal.aborted?{...ee(b),id:i.id}:C(i,w.signal,b);A(i.id,{state:"failed",failure:E}),R(E),P(V("failed",{id:i.id,ref:i.ref,failure:E}))}finally{o.get(i.id)===w&&o.delete(i.id)}})();s.set(i.id,D);try{await D}finally{s.delete(i.id)}}return{async preload(i){if(u)throw new Error(tt);let h=Array.isArray(i)?i:[];for(let p of h)p&&typeof p.id=="string"&&p.id.length>0&&(r.has(p.id)||r.set(p.id,{state:"pending"}),o.has(p.id)||o.set(p.id,new AbortController));return G(),await Promise.all(h.map(p=>ht(p,0))),I()},get(i){let h=r.get(i);if(h?.state==="ready")return L(h.resource)},getProgress(){return I()},onProgress(i){return f.add(i),()=>{f.delete(i)}},abort(i){if(!u){if(i!==void 0){o.get(i)?.abort();return}for(let h of o.values())h.abort()}},forget(i){if(u)return;if(i===void 0){for(let p of r.values())p.state==="ready"&&N(p.resource);r.clear(),a.length=0,d.clear(),y.clear(),G();return}let h=r.get(i);h?.state==="ready"&&N(h.resource),z(i,h),r.delete(i);for(let p=a.length-1;p>=0;p--)a[p].id===i&&a.splice(p,1);G()},dispose(){if(!u){u=!0;for(let i of o.values())i.abort();o.clear();for(let i of r.values())i.state==="ready"&&N(i.resource);r.clear(),a.length=0,s.clear();for(let i of l.values())i.controller.abort();d.clear(),l.clear(),y.clear(),f.clear()}}}}function st(t){Te();let{container:e,seed:n,captureKeyboard:r=!1,audio:a,deterministic:s,assets:o}=t,d=n===void 0?void 0:$e(n,s?"deterministic":"live"),l=new de;if(o&&typeof o.resolver?.resolve!="function")throw new Error("createRuntime: assets.resolver is required");let y=o?at({resolver:o.resolver,timeoutMs:o.timeoutMs,emitEvents:o.emitEvents??!s,wallClockTimeout:!s,dispatch:R=>l.dispatch(R)}):void 0,f=!1,u=null,g,C=!1,m=e.clientWidth||window.innerWidth,k=e.clientHeight||window.innerHeight,c=new oe(30,!1,m,k,!1,void 0,{container:e,seed:d,captureKeyboard:r,hostChannel:l,audio:a,deterministic:s}),z=()=>{let R=e.clientWidth||window.innerWidth,P=e.clientHeight||window.innerHeight;return R===c.containerWidth&&P===c.containerHeight?!1:(c.containerWidth=R,c.containerHeight=P,!0)},I=null;return!c.isDeterministic&&typeof ResizeObserver<"u"&&(I=new ResizeObserver(()=>{if(f||!u)return;z()&&C&&c.reinit()}),I.observe(e)),c.onError=(R,P)=>{g?.(R,P)},{get tokenData(){return c.tokenData},get hostChannel(){return l},get assets(){return y},get onError(){return g},set onError(R){g=R},mount(R,P={}){if(f)throw new Error("createRuntime: cannot mount on a destroyed runtime");u?.destroy(),C=!1,c.customState=P.initialState,c.setGameManager(P.gameManager);let N=P.onEvent?l.onEvent(P.onEvent):()=>{};if(!c.prepareCart(R))throw N(),new Error("createRuntime: failed to prepare cart");let A=!1,q={async start(){if(!A){if(z()&&c.isPrepared&&(c.init(),c.unloadCart(),!c.prepareCart(R)))throw new Error("createRuntime: failed to prepare cart");c.needsAudio&&(await c.unlockAudio(),A)||(C=!0,c.beginPlayback())}},pause(){A||(c.paused=!0)},resume(){A||(c.paused=!1)},dispatch(T){A||l.dispatch(T)},snapshot(){if(A)return{seed:"",pngDataUrl:""};let T=c.canvas;return{seed:c.tokenData.hash,metadata:R.metadata,pngDataUrl:T?T.toDataURL("image/png"):""}},destroy(){A||(A=!0,C=!1,N(),l.clearInbound(),c.unloadCart(),u===q&&(u=null))},reload(){if(!A){if(!C){if(c.isPrepared&&(c.unloadCart(),!c.prepareCart(R)))throw new Error("createRuntime: failed to prepare cart");return}c.reloadCart()}},reinit(T){if(!A){if(!C){z();return}c.reinit(T)}},getCartState(){return c.animation?.cartState},exportState(){return A?Promise.reject(new Error("Cart handle has been destroyed")):c.exportState()},exportStateJSON(){return A?Promise.reject(new Error("Cart handle has been destroyed")):c.exportStateJSON()},async importState(T,ue){if(A)throw new Error("Cart handle has been destroyed");await c.importState(T,ue)},peekExportedFramebuffer(){return A?null:c.peekExportedFramebuffer()},peekSeed(){if(!A)return c.peekSeed()},isGenerative(){return A?!1:c.isGenerative()},async step(T=1){if(A)throw new Error("Cart handle has been destroyed");await c.step(T)},async advance(T){if(A)throw new Error("Cart handle has been destroyed");await c.advance(T)},schedule(T){A||c.schedule(T)},getClock(){if(A)throw new Error("Cart handle has been destroyed");return c.getClock()},getRandomState(){if(A)throw new Error("Cart handle has been destroyed");return c.getRandomState()},getReplayMetadata(){return A?Promise.reject(new Error("Cart handle has been destroyed")):c.getReplayMetadata()},get canvas(){return c.canvas},get paused(){return c.paused},set paused(T){A||(c.paused=T)},get tokenData(){return c.tokenData},get isPrepared(){return c.isPrepared},get isLoopRunning(){return c.isLoopRunning},get needsAudio(){return c.needsAudio},get audioLibraries(){return c.audioLibraries}};return u=q,q},async unlockAudio(){await c.unlockAudio()},destroy(){f||(f=!0,u?.destroy(),u=null,I?.disconnect(),I=null,y?.dispose(),l.close(),c.destroy())}}}var ot="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8z8BQDwAEhQGAhKmMIQAAAABJRU5ErkJggg==",dt=320,ut=180,qt="Headless harness has been destroyed",ct=!1;function lt(){if(typeof globalThis.ImageData>"u"){class e{constructor(r,a){this.colorSpace="srgb";this.width=r,this.height=a,this.data=new Uint8ClampedArray(r*a*4)}}globalThis.ImageData=e}let t=HTMLCanvasElement.prototype;t.getContext=function(){return{globalAlpha:1,imageSmoothingEnabled:!1,fillStyle:"",save(){},restore(){},fillRect(){},putImageData(){},createImageData(r,a){return{data:new Uint8ClampedArray(r*a*4),width:r,height:a}}}},t.toDataURL=()=>ot,ct=!0}function Yt(t,e){let n=document.createElement("div");return Object.defineProperty(n,"clientWidth",{value:t,configurable:!0}),Object.defineProperty(n,"clientHeight",{value:e,configurable:!0}),document.body.appendChild(n),n}function Jt(t){let e=t.indexOf(","),n=e>=0?t.slice(e+1):t,r=globalThis.atob(n),a=new Uint8Array(r.length);for(let s=0;s<r.length;s++)a[s]=r.charCodeAt(s);return a}function Xt(){return typeof process<"u"&&!!process.versions?.node}async function Qt(t,e){if(!Xt())throw new Error("captureFrame(path) requires Node.js; omit the path to get the snapshot only");let n;try{({writeFile:n}=await import("node:fs/promises"))}catch(r){let a=r instanceof Error?r.message:String(r);throw new Error(`captureFrame(path) could not load node:fs/promises (${a}). Omit the path, or run under Node.`)}try{await n(t,Jt(e))}catch(r){let a=r instanceof Error?r.message:String(r);throw new Error(`captureFrame could not write ${t}: ${a}`)}}function Zt(t){ct||lt();let e=t.width??dt,n=t.height??ut,r=Yt(e,n),a=[],s=[],o=!1,d=t.onEvent,l=t.onError,y=st({container:r,seed:t.seed,deterministic:{origin:t.origin,actions:t.actions??[]}});y.onError=(m,k)=>{s.push({error:m,info:k}),l?.(m,k)},Object.defineProperty(y,"onError",{configurable:!0,enumerable:!0,get(){return l},set(m){l=m}});let f=m=>{a.push(m),d?.(m)},u=y.mount(t.cart,{initialState:t.initialState,gameManager:t.gameManager,onEvent:f}),g=()=>{if(o)throw new Error(qt)};return{runtime:y,container:r,get events(){return a.slice()},get errors(){return s.slice()},get cart(){return u},async step(m=1){g(),await u.step(m)},async advance(m){g(),await u.advance(m)},schedule(m){g(),u.schedule(m)},dispatch(m){g(),u.dispatch(m)},start(){return g(),u.start()},pause(){g(),u.pause()},resume(){g(),u.resume()},get paused(){return u.paused},key(m){g(),u.schedule({type:"key",atFrame:u.getClock().framesElapsed,key:m})},click(m,k){g(),u.schedule({type:"pointer",atFrame:u.getClock().framesElapsed,pointer:{kind:"down",x:m,y:k}})},async inspect(){g();let m=await u.getReplayMetadata();return{state:m.state,events:a.slice(),errors:s.slice(),replay:m,clock:u.getClock()}},async captureFrame(m){g();let k=u.snapshot();return m&&await Qt(m,k.pngDataUrl),k},remount(m={}){return g(),a.length=0,s.length=0,"onEvent"in m&&(d=m.onEvent),u=y.mount(t.cart,{initialState:m.initialState??t.initialState,gameManager:m.gameManager??t.gameManager,onEvent:f}),u},destroy(){if(!o){o=!0;try{u.destroy()}finally{try{y.destroy()}finally{r.remove()}}}}}}export{ut as DEFAULT_HEADLESS_HEIGHT,dt as DEFAULT_HEADLESS_WIDTH,ot as HEADLESS_PNG_DATA_URL,Zt as createHeadlessHarness,lt as installHeadlessCanvas};
|