@patterkit/play-helpers 0.7.6 → 0.7.8
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/patterplay.min.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
"use strict";var Patterplay=(()=>{var re=Object.defineProperty;var st=Object.getOwnPropertyDescriptor;var ot=Object.getOwnPropertyNames;var it=Object.prototype.hasOwnProperty;var at=(r,e)=>{for(var t in e)re(r,t,{get:e[t],enumerable:!0})},ct=(r,e,t,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let s of ot(e))!it.call(r,s)&&s!==t&&re(r,s,{get:()=>e[s],enumerable:!(n=st(e,s))||n.enumerable});return r};var lt=r=>ct(re({},"__esModule",{value:!0}),r);var Nt={};at(Nt,{Engine:()=>Z,Flow:()=>M,SAVE_SCHEMA:()=>V,applyLiveBundle:()=>Xe,buildTagIndex:()=>X,createAudioResolver:()=>rt,createBundleInspector:()=>nt,createDebugLink:()=>Qe,createPropertyInspector:()=>et,createStateLogger:()=>Ye,describeBundle:()=>ee,deserializeState:()=>ne,diffState:()=>H,effectiveGameData:()=>qe,gameDataFields:()=>_e,gameDataValue:()=>ge,getProperty:()=>Ue,loadState:()=>he,saveState:()=>fe,serializeState:()=>te,setProperties:()=>Je,setProperty:()=>We,snapshotState:()=>ye});function A(r){switch(r[0]){case"b":return{kind:"bool",value:r[1]};case"n":return{kind:"number",value:r[1]};case"s":return{kind:"string",value:r[1]};case"sv":return{kind:"scopedvar",scope:r[1],name:r[2]};case"u":return{kind:"unary",op:r[1],operand:A(r[2])};case"bin":return{kind:"binary",op:r[1],left:A(r[2]),right:A(r[3])};case"call":{let e=r.slice(2).map(A);return{kind:"call",name:r[1],args:e}}case"fd":return{kind:"flagdelta",sign:r[1],name:r[2]}}}var y=class extends Error{constructor(e){super(e),this.name="EvalError"}};function W(r,e,t){let n=new Map(t.scopes.map(o=>[o.token,o.missing??"false"])),s=o=>{switch(o.kind){case"bool":return o.value;case"number":return o.value;case"string":return o.value;case"scopedvar":{let i=e.scopes[o.scope];if(i===void 0)return!1;let a=typeof i.get=="function"?i.get(o.name):i[o.name];if(a===void 0){if(n.get(o.scope)==="throw")throw new y(`@${o.scope}.${o.name} is not declared on the current ${o.scope}.`);return!1}return a}case"call":{if(o.name==="advance"&&!t.functions[o.name]){let a=o.args[0];if(o.args.length!==1||a===void 0)throw new y(`advance() takes exactly 1 argument, got ${o.args.length}`);let l=se(a,e);if(l===void 0)throw new y("advance() needs a quality reference (@scope.name of a quality property)");let g=P(s(a),l,"advance");return l[Math.min(g+1,l.length-1)]}let i=t.functions[o.name];if(!i)throw new y(`unknown function '${o.name}'`);return i.eval(o.args,{evaluate:s,ctx:e})}case"flagdelta":throw new y("flagdelta node is only valid as an argument to a flag-delta function");case"unary":{if(o.op==="not"){let a=s(o.operand);if(typeof a!="boolean")throw new y(`'not' requires a boolean operand, got ${typeof a}`);return!a}let i=s(o.operand);if(typeof i!="number")throw new y(`unary '-' requires a numeric operand, got ${typeof i}`);return-i}case"binary":{if(o.op==="and"){let c=s(o.left);if(typeof c!="boolean")throw new y(`'and' requires boolean operands, left is ${typeof c}`);if(!c)return!1;let m=s(o.right);if(typeof m!="boolean")throw new y(`'and' requires boolean operands, right is ${typeof m}`);return m}if(o.op==="or"){let c=s(o.left);if(typeof c!="boolean")throw new y(`'or' requires boolean operands, left is ${typeof c}`);if(c)return!0;let m=s(o.right);if(typeof m!="boolean")throw new y(`'or' requires boolean operands, right is ${typeof m}`);return m}let i=s(o.left),a=s(o.right),l=se(o.left,e),g=se(o.right,e),f=l??g;if(f!==void 0){if(l&&g&&!pt(l,g)&&(o.op===">"||o.op===">="||o.op==="<"||o.op==="<="))throw new y(`'${o.op}' compares two different qualities, whose stage orders are unrelated`);switch(o.op){case">":return P(i,f,">")>P(a,f,">");case">=":return P(i,f,">=")>=P(a,f,">=");case"<":return P(i,f,"<")<P(a,f,"<");case"<=":return P(i,f,"<=")<=P(a,f,"<=");case"+":case"-":case"*":case"/":throw new y(`'${o.op}' cannot be applied to a quality - a stage is a position, not a number; use advance() to move it`);default:break}}switch(o.op){case"==":return ve(i,a);case"!=":return!ve(i,a);case">":return T(i,a,">"),i>a;case">=":return T(i,a,">="),i>=a;case"<":return T(i,a,"<"),i<a;case"<=":return T(i,a,"<="),i<=a;case"+":if(typeof i=="number"&&typeof a=="number"||typeof i=="string"&&typeof a=="string")return i+a;throw new y(`'+' requires two numbers or two strings, got ${typeof i} and ${typeof a}`);case"-":return T(i,a,"-"),i-a;case"*":return T(i,a,"*"),i*a;case"/":if(T(i,a,"/"),a===0)throw new y("division by zero");return i/a}}}};return s(r)}function ve(r,e){if(Array.isArray(r)||Array.isArray(e)){if(!Array.isArray(r)||!Array.isArray(e)||r.length!==e.length)return!1;let t=[...r].sort(),n=[...e].sort();for(let s=0;s<t.length;s++)if(t[s]!==n[s])return!1;return!0}return r===e}function T(r,e,t){if(typeof r!="number"||typeof e!="number")throw new y(`'${t}' requires numeric operands, got ${typeof r} and ${typeof e}`)}function se(r,e){if(!(r.kind!=="scopedvar"||e.qualities===void 0))return e.qualities(r.scope,r.name)}function P(r,e,t){if(typeof r!="string")throw new y(`'${t}' on a quality compares stages, got ${typeof r}`);let n=e.indexOf(r);if(n<0)throw new y(`"${r}" is not a stage of this quality (stages: ${e.join(", ")})`);return n}var pt=(r,e)=>r.length===e.length&&r.every((t,n)=>t===e[n]);function j(r){if(Number.isNaN(r)||!Number.isFinite(r))return 0;let e=Math.trunc(r)%4294967296;return e<0?e+4294967296:e}function oe(r){let e=j(r);return{next(){e=e+1831565813>>>0;let t=Math.imul(e^e>>>15,1|e);return t=t+Math.imul(t^t>>>7,61|t)^t,((t^t>>>14)>>>0)/4294967296},state(){return e}}}var dt={name:"check_flags",count:r=>Math.max(1,r.args.length-1)},ut=[dt];function we(r,e,t){let n=t?.countingCalls??ut;return J(r,t?.want??!0,e,n)}function J(r,e,t,n){if(r.kind==="binary"&&(r.op==="and"||r.op==="or")){let s=J(r.left,e,t,n),o=J(r.right,e,t,n);return r.op==="and"===e?s>0&&o>0?s+o:0:Math.max(s,o)}if(r.kind==="unary"&&r.op==="not")return J(r.operand,!e,t,n);if(r.kind==="call"){let s=n.find(o=>o.name===r.name);if(s){let o=s.count(r),i=t(r);return e?i?o:0:i?0:1}}return t(r)===e?1:0}function H(r,e){let t=[],n=new Set([...Object.keys(r),...Object.keys(e)]);for(let s of[...n].sort()){let o=r[s],i=e[s];JSON.stringify(o)!==JSON.stringify(i)&&t.push({path:s,from:o,to:i})}return t}var xe=r=>r===void 0?"<unset>":JSON.stringify(r),Ee=r=>r.pathPrefix??r.bag.pathPrefix;function ie(r,e={}){let t=e.sink??(c=>console.log(c)),n=e.label??"",s=c=>{t(`${n}${c.path}: ${xe(c.from)} -> ${xe(c.to)}`)},o=()=>{let c={};for(let m of r.mounts()){let u=Ee(m);for(let[h,d]of Object.entries(m.bag.values))c[u+h]=d}return Object.assign(c,r.extra?.()??{}),structuredClone(c)},i=o(),a=[],l=[],g=(c,m)=>m.onAudit(u=>{let h=structuredClone({path:c+u.name,from:u.prev,to:u.next});s(h),a.push(h),i[h.path]=structuredClone(u.next)}),f=()=>{let c=r.mounts();if(!(l.length===c.length&&c.every((u,h)=>l[h].bag===u.bag))){for(let u of l)u.off();l=c.map(u=>({bag:u.bag,off:g(Ee(u),u.bag)}))}};return f(),{snapshot:o,capture(){let c=o(),m=H(i,c);for(let h of m)s(h);let u=[...a,...m];return a=[],i=c,f(),u},dispose(){for(let c of l)c.off();l=[],a=[]}}}var L=class r{values={};decls=new Map;subscribers=new Set;auditors=new Set;norm;pathPrefix;constructor(e=[],t){this.norm=t?.normalise??(n=>n.toLowerCase()),this.pathPrefix=t?.pathPrefix??"",this.seed(e)}seed(e){for(let t of e){let n=this.norm(t.name);this.decls.set(n,t),this.values[n]=structuredClone(t.default??_(t))}}get(e){return this.values[this.norm(e)]}normalise(e){return this.norm(e)}set(e,t,n){let s=this.norm(e);if(!n?.host&&this.decls.get(s)?.writable===!1)throw new Error(`'${e}' is read-only`);let o={name:s,prev:this.values[s],next:t,silent:n?.silent??!1,reason:n?.reason};this.values[s]=t;for(let i of this.auditors)i(o);if(!o.silent)for(let i of this.subscribers)i(o);return o}subscribe(e){return this.subscribers.add(e),()=>this.subscribers.delete(e)}onAudit(e){return this.auditors.add(e),()=>this.auditors.delete(e)}rows(){return[...this.decls.entries()].map(([e,t])=>Ce(t,this.get(e),void 0,e,this.pathPrefix))}declarations(){return[...this.decls.values()]}clone(){let e=new r([],{normalise:this.norm,pathPrefix:this.pathPrefix});return e.decls=new Map(this.decls),Object.assign(e.values,structuredClone(this.values)),e}reseed(e){for(let t of Object.keys(this.values))delete this.values[t];this.decls.clear(),this.seed(e)}save(){return structuredClone(this.values)}load(e){for(let[t,n]of Object.entries(e))this.values[this.norm(t)]=n}};function Ce(r,e,t,n,s=""){let o=n??r.name.toLowerCase();return{name:o,path:s+o,type:r.type,value:e,default:r.default??_(r),...r.values!==void 0?{values:r.values}:{},...r.stages!==void 0?{stages:r.stages}:{},writable:t??r.writable??!0}}var gt=r=>r.toLowerCase(),ae=1,z=class{scopes=new Map;parked=new Map;rev=0;get revision(){return this.rev}defineOwned(e,t,n){let s=typeof n=="string"?{pathPrefix:n}:n??{},o=new L(t,{pathPrefix:s.pathPrefix??`${e}.`,...s.normalise?{normalise:s.normalise}:{}});return this.mountOwned(e,o,s.owner!==void 0?{owner:s.owner}:void 0)}mountOwned(e,t,n){this.assertFree(e,n?.owner),this.scopes.set(e,{kind:"owned",bag:t,...n?.owner!==void 0?{owner:n.owner}:{}}),this.rev++;let s=this.parked.get(e);return s&&(t.load(s),this.parked.delete(e)),this}remove(e,t){let n=this.scopes.get(e);if(!n)throw new Error(`unknown scope '@${e}'`);return t?.keep&&n.kind==="owned"&&this.parked.set(e,n.bag.save()),this.scopes.delete(e),this.rev++,this}discardParked(e){if(e===void 0)this.parked.clear();else for(let t of[...this.parked.keys()])t.startsWith(e)&&this.parked.delete(t);return this}ownedBag(e){let t=this.scopes.get(e);if(!t||t.kind!=="owned")throw new Error(`'@${e}' is not an owned scope`);return t.bag}reseedOwned(e,t){return this.ownedBag(e).reseed(t),this}defineForeign(e,t,n=[],s=!0){let o=typeof s=="boolean"?{writable:s}:s;this.assertFree(e,o.owner);let i=o.normalise??gt,a=new Map;for(let l of n)a.set(i(l.name),l);return this.scopes.set(e,{kind:"foreign",resolver:t,decls:a,scopeWritable:o.writable??!0,norm:i,...o.owner!==void 0?{owner:o.owner}:{}}),this.rev++,this}has(e){return this.scopes.has(e)}get(e,t){let n=this.scopes.get(e);if(n)return n.kind==="owned"?n.bag.get(t):n.resolver.get(n.norm(t))}set(e,t,n,s){let o=this.scopes.get(e);if(!o)throw new Error(`unknown scope '@${e}'`);if(o.kind==="owned"){try{o.bag.set(t,n,s?.host?{host:!0}:void 0)}catch{throw new Error(`'@${e}.${t}' is read-only`)}return}let i=o.norm(t);if(!o.resolver.set)throw new Error(`'@${e}.${t}' is read-only`);if(!s?.host&&!this.foreignWritable(o,i))throw new Error(`'@${e}.${t}' is read-only`);o.resolver.set(i,n)}foreignWritable(e,t){return e.resolver.set?e.decls.get(t)?.writable??e.scopeWritable:!1}listProperties(){let e=[];for(let[t,n]of this.scopes){let s=n.owner!==void 0?{owner:n.owner}:{};if(n.kind==="owned")for(let o of n.bag.rows())e.push({scope:t,...s,...o});else for(let[o,i]of n.decls)e.push({scope:t,...s,...Ce(i,n.resolver.get(o),this.foreignWritable(n,o),o,`${t}.`)})}return e}toEvalContext(e,t){let n=this.view(t?.aliases),s={};for(let[i,a]of n)s[i]=a.kind==="owned"?a.bag.values:a.resolver;let o=this.qualityLadders(n);return o.size===0?{scopes:s,host:e}:{scopes:s,host:e,qualities:(i,a)=>{let l=n.get(i);return l?o.get(i)?.get(ft(l)(a)):void 0}}}view(e){let t=new Map(this.scopes);for(let[n,s]of Object.entries(e??{})){let o=this.scopes.get(s);if(!o)throw new Error(`alias '@${n}' names '${s}', which is not registered`);t.set(n,o)}return t}qualityLadders(e){let t=new Map;for(let[n,s]of e)for(let[o,i]of ke(s)){if(i.type!=="quality"||i.stages===void 0)continue;let a=t.get(n);a||(a=new Map,t.set(n,a)),a.set(o,i.stages)}return t}toSchema(e){let t=new Map;for(let[n,s]of this.view(e?.aliases)){let o=ke(s);if(o.length===0)continue;let i=new Map;for(let[a,l]of o)i.set(a,{type:l.type,enumValues:l.values,...l.stages!==void 0?{stages:l.stages}:{}});t.set(n,i)}return{properties:t}}save(){let e={};for(let[t,n]of this.scopes)n.kind==="owned"&&(e[t]=n.bag.save());for(let[t,n]of this.parked)e[t]=structuredClone(n);return e}load(e,t){t?.keepParked||this.parked.clear();for(let[n,s]of Object.entries(e)){let o=this.scopes.get(n);o?.kind==="owned"?o.bag.load(s):o||this.parked.set(n,structuredClone(s))}}saveFragment(){return{version:ae,scopes:this.save()}}loadFragment(e){if(e.version!==ae)throw new Error(`unsupported owned-state fragment version ${e.version} (supported: ${ae})`);this.load(e.scopes)}assertFree(e,t){let n=this.scopes.get(e);if(!n)return;let s=n.owner!==void 0?` by ${n.owner}`:"",o=t!==void 0?` (wanted by ${t})`:"";throw new Error(`scope '@${e}' is already registered${s}${o}`)}};function ke(r){return r.kind==="foreign"?[...r.decls.entries()]:r.bag.declarations().map(e=>[r.bag.normalise(e.name),e])}function ft(r){return r.kind==="foreign"?r.norm:e=>r.bag.normalise(e)}function _(r){if(r.default!==void 0)return r.default;switch(r.type){case"boolean":return!1;case"number":return 0;case"string":return"";case"enum":return r.values?.[0]??"";case"flags":return[];case"quality":return r.stages?.[0]??"";default:return!1}}var De=[{token:"patter",engine:"Patterplay",means:"Patter's shared globals"},{token:"story",engine:"Storylet Engine",means:"the Storylet Engine's shared @story properties"}];function q(r){return r.ctx.host??{}}var ce={defaultScope:"patter",scopes:[{token:"patter"},{token:"scene"}],functions:{random:{minArgs:2,maxArgs:2,returnType:"number",eval(r,e){if(r.length!==2)throw new y("random(a, b) requires exactly 2 arguments");let t=q(e).nextRandom;if(!t)throw new y("random() called without a PRNG in context");let n=e.evaluate(r[0]),s=e.evaluate(r[1]);if(typeof n!="number"||typeof s!="number")throw new y("random(a, b) arguments must be numbers");if(!Number.isInteger(n)||!Number.isInteger(s))throw new y("random(a, b) arguments must be integers");let o=Math.min(n,s),i=Math.max(n,s);return Math.floor(t()*(i-o+1))+o}},check_flags:{minArgs:1,returnType:"boolean",flagDeltaArgs:!0,validate:Re("check_flags"),eval(r,e){let t=Ie(r[0],e,"check_flags");for(let n=1;n<r.length;n++){let s=r[n];if(s.kind!=="flagdelta")throw new y("check_flags() flag args must be +flagName or -flagName");if(s.sign==="+"?!t.includes(s.name):t.includes(s.name))return!1}return!0}},set_flags:{minArgs:1,returnType:"flags",flagDeltaArgs:!0,validate:Re("set_flags"),eval(r,e){let t=[...Ie(r[0],e,"set_flags")];for(let n=1;n<r.length;n++){let s=r[n];if(s.kind!=="flagdelta")throw new y("set_flags() flag args must be +flagName or -flagName");if(s.sign==="+")t.includes(s.name)||t.push(s.name);else{let o=t.indexOf(s.name);o>=0&&t.splice(o,1)}}return t}},visits:{minArgs:1,maxArgs:1,returnType:"number",validate:Y("visits"),eval:(r,e)=>q(e).visits?.(K(r,e,"visits"))??0},seen:{minArgs:1,maxArgs:1,returnType:"boolean",validate:Y("seen"),eval:(r,e)=>(q(e).visits?.(K(r,e,"seen"))??0)>0},patter_visits:{minArgs:1,maxArgs:1,returnType:"number",validate:Y("patter_visits"),eval:(r,e)=>q(e).patterVisits?.(K(r,e,"patter_visits"))??0},patter_seen:{minArgs:1,maxArgs:1,returnType:"boolean",validate:Y("patter_seen"),eval:(r,e)=>(q(e).patterVisits?.(K(r,e,"patter_seen"))??0)>0}}},Yt=De.map(r=>r.token).filter(r=>r!=="patter"&&r!=="scene");function Oe(r,e){let t=r.replace(/^@/,"").split(".");return t.length===2&&e(t[0])?{scope:t[0],name:t[1].toLowerCase()}:{scope:"patter",name:t.join(".").toLowerCase()}}function K(r,e,t){let n=e.evaluate(r[0]);if(typeof n!="string")throw new y(`${t}(id) requires a string node id`);return n}function Y(r){return(e,t)=>{let n=e[0];n&&n.kind!=="string"&&t.report({path:[...t.path,"args",0],kind:"wrong-arg-type",severity:"error",message:`${r}(id): the argument must be a string id literal (a scene / block / node id)`})}}function Ie(r,e,t){if(!r)throw new y(`${t}() requires at least one argument (the flags variable)`);let n=e.evaluate(r);if(Array.isArray(n))return n;if(n===!1||n===null||n===void 0)return[];throw new y(`${t}() first argument must be a flags property`)}function Re(r){return(e,t)=>{if(e.length===0)return;let n=e[0];if(n.kind!=="scopedvar"){t.report({path:[...t.path,"args",0],kind:"wrong-arg-type",severity:"error",message:`${r}(): first argument must be a flags property reference (@name or @scope.name)`});return}let s=t.schema.properties.get(n.scope)?.get(n.name);if(s&&s.type!=="flags"){let o=n.scope===t.defaultScope?n.name:`${n.scope}.${n.name}`;t.report({path:[...t.path,"args",0],kind:"wrong-arg-type",severity:"error",message:`${r}(): '@${o}' is not a flags property (got ${s.type})`});return}for(let o=1;o<e.length;o++){let i=e[o];i.kind!=="flagdelta"?t.report({path:[...t.path,"args",o],kind:"wrong-arg-type",severity:"error",message:`${r}(): argument ${o+1} must be +flagName or -flagName`}):s?.type==="flags"&&s.enumValues&&!s.enumValues.includes(i.name)&&t.report({path:[...t.path,"args",o],kind:"unknown-flag-name",severity:"error",message:`${r}(): unknown flag '${i.name}'`,reference:i.name})}}}var ht=/^@[A-Za-z0-9_.]+$/;function*mt(r){let e="",t=0;for(;t<r.length;){let n=r[t];if(n==="{"&&r[t+1]==="{"){e+="{",t+=2;continue}if(n==="}"&&r[t+1]==="}"){e+="}",t+=2;continue}if(n==="{"){let s=r.indexOf("}",t+1);if(s!==-1){let o=r.slice(t,s+1),i=r.slice(t+1,s).trim();if(i.startsWith("@")){e&&(yield{kind:"text",value:e},e=""),yield{kind:"slot",raw:o,inner:i,ref:ht.test(i)?i:void 0},t=s+1;continue}e+=o,t=s+1;continue}}e+=n,t+=1}e&&(yield{kind:"text",value:e})}function yt(r){return Array.isArray(r)?r.join(", "):typeof r=="boolean"?r?"true":"false":String(r)}function St(r){return r===" "||r===" "||r===`
|
|
2
|
-
`||r==="\r"||r==="\f"||r==="\v"}function bt(r){let e="",t=!1;for(let n of r){if(St(n)){t=!0;continue}t&&e.length>0&&(e+=" "),t=!1,e+=n}return e}function Be(r,e,t){if(e.length===0||r.indexOf(e)<0)return r;let n="",s=0,o=!1;for(;s<r.length;){if(r.startsWith(e,s)){let i=r.indexOf(t,s+e.length);if(i>=0){s=i+t.length,o=!0;continue}n+=r.slice(s);break}n+=r[s],s+=1}return o?bt(n):r}function Pe(r,e){if(r.indexOf("{")<0)return r;let t="";for(let n of mt(r)){if(n.kind==="text"){t+=n.value;continue}if(!n.ref){t+=n.raw;continue}let s=e(n.ref);t+=s===void 0?"":yt(s)}return t}function F(r,e){for(let t of r){e(t);let n=t.children;n&&F(n,e)}}function vt(r){return r.toLowerCase().replace(/['’]/g,"").replace(/[^a-z0-9-]+/g,"-").replace(/-+/g,"-").replace(/^-+|-+$/g,"")}function C(r){let e=r.gameId?.trim();return e||vt(r.name)}function le(r){return`cast:${r}`}var pe={open:"[",close:"]"},Ne="SFX",V="patter/save@0",de=3;function Q(r){let e=new Set,t=[];for(let n of r)e.has(n)||(e.add(n),t.push(n));return t}function X(r){let e=new Map,t=(n,s)=>{let o=Q([...s,...n.tags??[]]);if(e.set(n.id,o),n.type==="group")for(let i of n.children)t(i,o);else for(let i of n.beats??[])e.set(i.id,Q([...o,...i.tags??[]]))};for(let n of Object.values(r.scenes)){let s=Q(n.tags??[]);e.set(n.id,s);for(let o of n.blocks){let i=Q([...s,...o.tags??[]]);e.set(o.id,i);for(let a of o.children)t(a,i)}}return e}var Le=new WeakMap,G="Patter",U=r=>r.replace(/%/g,"%25").replace(/\//g,"%2F"),Ae=Symbol("ownsRegistry"),B={stage:r=>`patter/scene/${U(r)}`,flow:r=>`patter/flow/${U(r)}/`,flowGlobals:r=>`patter/flow/${U(r)}/patter`,flowScene:(r,e)=>`patter/flow/${U(r)}/scene/${U(e)}`},Z=class r{host;defaultSeed;flowsById=new Map;allStrings;currentLocale;sourceDebug;sceneGameIdToId=new Map;blockGameIdToId=new Map;creationOptions;engineLog=[];engineTraceHandlers=new Set;constructor(e,t={}){this.creationOptions=t;let n=t.locale??e.locales.default,s=e.strings;this.allStrings=s,this.currentLocale=n;let o=s[n]??{},i=s[e.locales.default]??{},a=e.localisation,l=a?.mode==="ids"&&!a.sourceDebug;this.sourceDebug=a?.mode==="ids"&&!!a.sourceDebug,this.sourceDebug&&typeof console<"u"&&console.warn("[Patterplay] source-only DEBUG build: strings are the source language for debugging, not a shippable localised build.");let g=new Map;for(let S of e.cast??[])S.displayName&&g.set(S.name,S.displayName);this.defaultSeed=(t.seed??2654435769)>>>0;let f=new Map,c=new Map,m=new Map;for(let[S,p]of Object.entries(e.scenes)){this.sceneGameIdToId.set(C(p),S);let w=new Map;for(let x of p.blocks)c.set(x.id,{sceneId:S}),m.set(x.id,x),w.set(C(x),x.id),F(x.children,be=>f.set(be.id,be));this.blockGameIdToId.set(S,w)}let u=e.properties??[],h=u.filter(S=>S.shared??!0).map(Ve),d=u.filter(S=>!(S.shared??!0)).map(Ve),v=new Set(h.map(S=>S.name.toLowerCase())),E=t.registry??new z,k=!t.registry||t[Ae]===!0,R=new L(h,{pathPrefix:"@patter."}),D=[],O=[];try{E.mountOwned("patter",R,{owner:G}),O.push("patter");let S=new Set;if(t.world){let p=e.scopeRegistry?.scopes.find(x=>x.token==="world"),w=(p?.declarations??[]).map(je);E.defineForeign("world",t.world,w,{writable:p?.writable??!0,owner:G}),O.push("world"),S.add("world")}for(let p of k?e.scopeRegistry?.scopes??[]:[]){if(S.has(p.token)||E.has(p.token))continue;let w=(p.declarations??[]).map(x=>wt(x,p.writable));E.defineOwned(p.token,w,{owner:G}),O.push(p.token),D.push(p.token)}}catch(S){for(let p of O)E.remove(p,{keep:!0});throw S}let N=new Map;for(let[S,p]of Object.entries(e.scenes)){let w=new Set((p.sceneProps??[]).filter(x=>x.shared??!1).map(x=>x.name.toLowerCase()));N.set(S,w)}this.host={logEnabled:t.log??!1,emitEngine:(S,p,w)=>this.emitEngine(S,p,w),bundle:e,emitIds:l,strings:o,defaultStrings:i,castDisplay:g,nodeIndex:f,blockIndex:c,blockById:m,sceneGameIdToId:this.sceneGameIdToId,blockGameIdToId:this.blockGameIdToId,tagIndex:X(e),registry:E,ownsRegistry:k,patterBag:R,hostScopes:D,patterSharedDecls:h,patterLocalDecls:d,patterSharedNames:v,sceneSharedNames:N,sharedVisits:new Map,sharedSelectors:new Map,stageBags:new Map,customRng:t.rng,onDryChoice:t.onDryChoice,replayPromptOnChoose:t.replayPromptOnChoose??!1,captionsOn:t.closedCaptions??!0,captionOpen:(e.closedCaptions??pe).open,captionClose:(e.closedCaptions??pe).close,captionCharacter:e.closedCaptions?.character||Ne,refSplitCache:new Map,refSplitRevision:E.revision}}get locale(){return this.currentLocale}get isSourceDebug(){return this.sourceDebug}setLocale(e){this.currentLocale=e,this.host.strings=this.allStrings[e]??{}}replaceStrings(e){this.allStrings=e.strings,this.host.strings=this.allStrings[this.currentLocale]??{},this.host.defaultStrings=this.allStrings[this.host.bundle.locales.default]??{}}hotSwap(e){let t=this.saveGame(),n=i=>(i.setLocale(this.currentLocale),i.setClosedCaptions(this.host.captionsOn),i),s=()=>new r(e,{...this.creationOptions,registry:this.host.registry,[Ae]:this.host.ownsRegistry});this.release(!0);let o=s();try{return o.loadGame(t),n(o)}catch{o.release(!0);let i=s();for(let[a,l]of Object.entries(t.flows)){let g=l.cursor.currentSceneId;try{i.openFlow(a,g!==null?{scene:g}:{})}catch{}}return n(i)}}get closedCaptions(){return this.host.captionsOn}setClosedCaptions(e){this.host.captionsOn=e}openFlow(e,t={}){this.assertExternalScopes();let n=this.resolveSceneRef(t.scene),s=this.resolveBlockRef(n,t.block);this.flowsById.get(e)?.close();let o=new M(e,this.host,t.seed??this.defaultSeed);return this.flowsById.set(e,o),o.start(n,s),o}runFlow(e,t,n){let s=this.flowsById.get(e);if(!s)return this.openFlow(e,{scene:t,block:n}).advanceToStop().played;if(!s.goto(t,n))throw new Error(`runFlow: address not found: ${t}${n===void 0?"":` / ${n}`}`);return s.advanceToStop().played}assertExternalScopes(){for(let e of this.host.bundle.externalScopes??[])if(!this.host.registry.has(e))throw new Error(`this content names @${e}, which no engine on this registry registered: give every engine the game's one registry`)}resolveSceneRef(e){if(e!=null)return this.host.bundle.scenes[e]?e:this.sceneGameIdToId.get(e)??e}resolveBlockRef(e,t){if(t!=null){if(this.host.blockById.has(t))return t;if(e!=null){let n=this.blockGameIdToId.get(e)?.get(t);if(n)return n}return t}}sceneAddress(e){let t=this.host.bundle.scenes[e];return t?C(t):void 0}blockAddress(e){let t=this.host.blockById.get(e);return t?C(t):void 0}tagsForBeat(e){return this.host.tagIndex.get(e)??[]}tagsForScene(e){let t=this.resolveSceneRef(e);return(t!=null?this.host.tagIndex.get(t):void 0)??[]}tagsForBlock(e,t){let n=this.resolveSceneRef(e),s=this.resolveBlockRef(n,t);return(s!=null?this.host.tagIndex.get(s):void 0)??[]}gameDataForScene(e){let t=this.resolveSceneRef(e);return{...(t!=null?this.host.bundle.scenes[t]:void 0)?.gameData}}gameDataForBlock(e,t){let n=this.resolveBlockRef(this.resolveSceneRef(e),t);return{...(n!=null?this.host.blockById.get(n):void 0)?.gameData}}getCast(){let e=[];for(let t of this.host.bundle.cast??[])t?.name&&e.push(t.name);return e}castForScene(e){let t=this.resolveSceneRef(e),n=t!=null?this.host.bundle.scenes[t]:void 0;if(!n)return[];let s=new Set;for(let o of n.blocks)Te(o.children,s);return[...s]}castForBlock(e,t){let n=this.resolveSceneRef(e),s=this.resolveBlockRef(n,t),o=s!=null?this.host.blockById.get(s):void 0;if(!o)return[];let i=new Set;return Te(o.children,i),[...i]}getOutline(){return Object.values(this.host.bundle.scenes).map(e=>({id:e.id,...C(e)?{gameId:C(e)}:{},name:e.name,...Fe(e.gameData),...this.tagsField(e.id),blocks:e.blocks.map(t=>({id:t.id,...C(t)?{gameId:C(t)}:{},name:t.name,...Fe(t.gameData),...this.tagsField(t.id),children:t.children.map(n=>this.outlineNode(n))}))}))}getBeatSequence(){let e=[];for(let t of Object.values(this.host.bundle.scenes))for(let n of t.blocks)F(n.children,s=>{if(s.type==="snippet")for(let o of s.beats??[])e.push({sceneId:t.id,blockId:n.id,snippetId:s.id,beat:this.beatInfo(o)})});return e}outlineNode(e){return e.type==="group"?{type:"group",id:e.id,...this.tagsField(e.id),...e.selector?{selector:e.selector}:{},...e.prompt?{prompt:this.beatInfo(e.prompt)}:{},children:e.children.map(t=>this.outlineNode(t))}:{type:"snippet",id:e.id,...this.tagsField(e.id),beats:(e.beats??[]).map(t=>this.beatInfo(t)),...e.jump?{jumpTo:e.jump.to,...e.jump.mode?{jumpMode:e.jump.mode}:{}}:{}}}beatInfo(e){let t=this.host.tagIndex.get(e.id),n={id:e.id,kind:e.kind};if(e.kind==="line"){if(e.character!==void 0){n.character=e.character;let s=this.host.defaultStrings[le(e.character)]??this.host.castDisplay.get(e.character);s!==void 0&&(n.characterName=s)}e.direction!==void 0&&(n.direction=e.direction)}if(e.kind==="line"||e.kind==="text"){let s=this.host.defaultStrings[e.id];s!==void 0&&(n.text=s)}return e.gameData&&Object.keys(e.gameData).length&&(n.gameData=e.gameData),t&&t.length&&(n.tags=t),n}tagsField(e){let t=this.host.tagIndex.get(e);return t&&t.length?{tags:t}:{}}getFlow(e){return this.flowsById.get(e)}flows(){return[...this.flowsById.values()]}listBags(){let e=[{bag:this.host.patterBag}];for(let[t,n]of this.host.stageBags)e.push({bag:n,pathPrefix:`@scene:${t}.`});return e}closeFlow(e){this.flowsById.get(e)?.close(),this.flowsById.delete(e)}reset(){for(let e of this.flowsById.values())e.close();this.flowsById.clear(),this.host.patterBag.reseed(this.host.patterSharedDecls),this.host.sharedVisits.clear(),this.host.sharedSelectors.clear();for(let e of this.host.stageBags.keys())this.host.registry.remove(B.stage(e));this.host.stageBags.clear(),this.host.registry.discardParked("patter/")}release(e){for(let n of this.flowsById.values())n.releaseBags(e),n.close();this.flowsById.clear();let t=this.host.registry;for(let n of this.host.stageBags.keys())t.remove(B.stage(n),{keep:e});this.host.stageBags.clear();for(let n of["patter",...this.host.hostScopes])t.has(n)&&t.remove(n,{keep:e});this.creationOptions.world&&t.has("world")&&t.remove("world")}getProperty(e){let{scope:t,name:n}=this.splitShared(e);return this.host.registry.get(t,n)}setProperty(e,t){let{scope:n,name:s}=this.splitShared(e);this.host.registry.set(n,s,t,{host:!0})}log(){return this.engineLog}clearLog(){this.engineLog.length=0}onTrace(e){return this.engineTraceHandlers.add(e),()=>this.engineTraceHandlers.delete(e)}emitEngine(e,t,n){for(let s of this.engineTraceHandlers)s(e,t);this.host.logEnabled&&this.engineLog.push({...t,flow:e,seq:this.engineLog.length,...n?{scene:n}:{}})}listProperties(){return this.host.patterSharedDecls.map(e=>({name:e.name,path:`@patter.${e.name}`,type:e.type,values:e.values,stages:e.stages,value:this.getProperty(`@${e.name}`),default:_(e),writable:e.writable??!0}))}splitShared(e){let t=He(this.host,e);if(t.scope==="scene")throw new Error(`'${e}': @scene properties are scene-scoped - read/write them on a Flow, not the Engine`);return t}save(){return{patter:this.host.patterBag.save()}}load(e){e.patter&&this.host.patterBag.load(e.patter)}saveGame(){let e={};for(let[t,n]of this.flowsById)e[t]=n.snapshot();return{version:de,...this.host.ownsRegistry?{registry:this.host.registry.save()}:{},sharedVisits:Object.fromEntries(this.host.sharedVisits),sharedSelectors:Me(this.host.sharedSelectors),flows:e}}loadGame(e){let t=e.version;if(t!==2&&t!==de)throw new Error(`unsupported save version: ${String(t)}`);this.assertExternalScopes();let n=this.host.registry;for(let[o,i]of this.flowsById)i.releaseBags(o in e.flows),i.close();this.flowsById.clear();for(let o of this.host.stageBags.keys())n.remove(B.stage(o),{keep:!0});this.host.stageBags.clear();let s=e.version===2?xt(e):e.registry;s&&(this.host.ownsRegistry?n.load(s):n.load(s,{keepParked:!0})),this.host.sharedVisits.clear();for(let[o,i]of Object.entries(e.sharedVisits??{}))this.host.sharedVisits.set(o,i);this.host.sharedSelectors.clear();for(let[o,i]of $e(e.sharedSelectors))this.host.sharedSelectors.set(o,i);for(let[o,i]of Object.entries(e.flows)){let a=new M(o,this.host,this.defaultSeed);a.restore(i),this.flowsById.set(o,a)}}},M=class{id;host;local;registered=new Set;rngState;started=!1;flowEnded=!1;closed=!1;currentSceneId=null;stack=[];activeSnippet=null;beatIndex=0;pendingChoice=null;pendingPromptBeat=null;pendingPromptOwnerId=null;selectors=new Map;visitCounts=new Map;sceneBags=new Map;patterResolver={get:e=>this.host.patterSharedNames.has(e)?this.host.patterBag.get(e):this.local.get(e),set:(e,t)=>{this.host.patterSharedNames.has(e)?this.host.registry.set("patter",e,t):this.local.set(e,t)}};sceneResolver={get:e=>{let t=this.currentSceneId;if(t!==null)return this.sceneBagFor(t,e)?.get(e)},set:(e,t)=>{let n=this.currentSceneId;if(n===null)return;let s=this.sceneBagFor(n,e);s&&s.set(e,t)}};evalCtx;ctxRevision=-1;registryQualities;flowLog=[];flowSeq=0;constructor(e,t,n){this.id=e,this.host=t,this.rngState=j(n),this.local=this.newLocal(),this.evalCtx={scopes:{},host:{nextRandom:this.rng,visits:s=>this.visitCounts.get(s)??0,patterVisits:s=>this.host.sharedVisits.get(s)??0},qualities:(s,o)=>this.stagesFor(s,o)}}context(){let e=this.host.registry;if(e.revision!==this.ctxRevision){let t=e.toEvalContext(),n=this.evalCtx.scopes;for(let s of Object.keys(n))delete n[s];Object.assign(n,t.scopes),n.patter=this.patterResolver,n.scene=this.sceneResolver,this.registryQualities=t.qualities,this.ctxRevision=e.revision}return this.evalCtx}stagesFor(e,t){let n=t.toLowerCase(),s=o=>o?.find(i=>i.name.toLowerCase()===n&&i.type==="quality")?.stages;if(e==="patter")return s(this.host.patterSharedDecls)??s(this.host.patterLocalDecls);if(e==="scene"){let o=this.currentSceneId!=null?this.host.bundle.scenes[this.currentSceneId]:void 0;return s(o?.sceneProps)}return this.registryQualities?.(e,t)??s(this.host.bundle.scopeRegistry?.scopes.find(o=>o.token===e)?.declarations)}start(e,t){if(this.releaseBags(!1),this.host.registry.discardParked(B.flow(this.id)),this.mountLocal(),this.selectors.clear(),this.visitCounts.clear(),this.stack=[],this.currentSceneId=null,this.flowEnded=!1,this.activeSnippet=null,this.beatIndex=0,this.pendingChoice=null,this.started=!0,t){let n=this.host.blockIndex.get(t);if(!n)throw new Error(`unknown block: ${t}`);this.enterSceneSetup(n.sceneId),this.stack=[{sceneId:n.sceneId,containerId:t,index:0}],this.enter(t)}else{let n=e??Object.keys(this.host.bundle.scenes)[0],s=n?this.host.bundle.scenes[n]:void 0;if(!s)throw new Error(n?`unknown scene: ${n}`:"no scenes in bundle");this.enterSceneSetup(n);let o=s.blocks[0];o&&(this.stack=[{sceneId:n,containerId:o.id,index:0}],this.enter(o.id))}this.settle()}reset(e,t){this.start(e,t)}goto(e,t){if(this.closed)return!1;if(e==="END")return this.started=!0,this.pendingChoice=null,this.pendingPromptBeat=null,this.pendingPromptOwnerId=null,this.activeSnippet=null,this.beatIndex=0,this.flowEnded=!0,this.stack=[],!0;let n=this.host.sceneGameIdToId.get(e)??(this.host.bundle.scenes[e]?e:void 0);if(n===void 0)return!1;let s;return t!==void 0&&(s=this.host.blockGameIdToId.get(n)?.get(t)??(this.host.blockIndex.get(t)?.sceneId===n?t:void 0),s===void 0)?!1:this.started?(this.pendingChoice=null,this.pendingPromptBeat=null,this.pendingPromptOwnerId=null,this.activeSnippet=null,this.beatIndex=0,this.flowEnded=!1,this.enterTarget(s??n,"jump"),this.settle(),!0):(this.start(n,s),!0)}close(){this.releaseBags(!1),this.closed=!0,this.flowEnded=!0,this.stack=[],this.activeSnippet=null,this.beatIndex=0,this.pendingChoice=null,this.pendingPromptBeat=null,this.pendingPromptOwnerId=null}get isClosed(){return this.closed}get currentScene(){return this.currentSceneId}advance(){if(this.closed)return{type:"end"};if(!this.started)throw new Error("flow has not been started");if(this.pendingPromptBeat){let e=this.pendingPromptBeat;return this.pendingPromptBeat=null,this.pendingPromptOwnerId=null,this.beatResult(e)}return this.settle(),this.flowEnded?{type:"end"}:this.pendingChoice?{type:"choice",groupId:this.pendingChoice.groupId,options:this.pendingChoice.options}:this.activeSnippet?this.beatResult(this.activeSnippet.beats[this.beatIndex++]):(this.flowEnded=!0,{type:"end"})}advanceToStop(){let e=[];for(;;){let t=this.advance();if(t.type==="choice"||t.type==="end")return{played:e,stop:t};e.push(t)}}settle(){let e=0;for(;;){if(++e>1e4)throw new Error("flow did not settle after 10000 transitions - likely a jump cycle with no deliverable content");if(this.flowEnded||this.pendingChoice)return;if(this.activeSnippet){if(this.beatIndex<(this.activeSnippet.beats?.length??0))return;this.runEffects(this.activeSnippet.onExit);let o=this.activeSnippet.jump;this.activeSnippet=null,this.beatIndex=0,this.resolveJump(o);continue}let t=this.stack[this.stack.length-1];if(!t){this.flowEnded=!0;return}t.sceneId!==this.currentSceneId&&(this.currentSceneId=t.sceneId);let n=this.childrenOf(t.containerId);if(!n){this.stack.pop();continue}let s=t.index;for(;t.index<n.length&&!this.eligible(n[t.index]);)t.index++;if(this.host.logEnabled&&t.index!==s&&this.emit({type:"select",group:t.containerId,selector:"run",children:n.slice(s,t.index+1).map((o,i)=>({id:o.id,eligible:s+i===t.index})),picked:n[t.index]?.id??null}),t.index>=n.length){this.stack.pop();continue}this.enterChild(n[t.index++])}}listBags(){let e=[{bag:this.local,pathPrefix:`${this.id}/@patter.`}];for(let[t,n]of this.sceneBags)e.push({bag:n,pathPrefix:`${this.id}/@scene:${t}.`});return e}log(){return this.flowLog}clearLog(){this.flowLog.length=0}emit(e){let t=this.currentSceneId??void 0;this.host.emitEngine(this.id,e,t),this.host.logEnabled&&this.flowLog.push({...e,seq:this.flowSeq++,...t?{scene:t}:{}})}getChoices(){return this.pendingChoice?.options??[]}choose(e){let t=this.pendingChoice;if(!t)throw new Error("no choice is pending");let n=t.options.find(o=>o.id===e);if(!n)throw new Error(`unknown choice option: ${e}`);if(!n.eligible)throw new Error(`choice option is not eligible: ${e}`);let s=t.byId.get(e);this.emit({type:"chose",group:t.groupId,option:e}),this.pendingChoice=null,this.pendingPromptBeat=this.host.replayPromptOnChoose?this.promptBeatOf(s)??null:null,this.pendingPromptOwnerId=this.pendingPromptBeat?s.id:null,this.enterChild(s)}isEnded(){return this.flowEnded}getProperty(e){let{scope:t,name:n}=this.splitRef(e);return t==="patter"?this.patterResolver.get(n):t==="scene"?this.sceneResolver.get(n):this.host.registry.get(t,n)}setProperty(e,t){this.writeProperty(e,t,!0)}writeProperty(e,t,n){let{scope:s,name:o}=this.splitRef(e);if(s==="patter")this.patterResolver.set(o,t);else if(s==="scene"){if(this.currentSceneId===null)throw new Error(`'${e}': the flow has not entered a scene yet`);this.sceneResolver.set(o,t)}else this.host.registry.set(s,o,t,n?{host:!0}:void 0)}snapshot(){return{rngState:this.rngState,visits:Object.fromEntries(this.visitCounts),cursor:{flowEnded:this.flowEnded,currentSceneId:this.currentSceneId,stack:this.stack.map(e=>{let t=this.childrenOf(e.containerId)?.[e.index];return t?{...e,nextId:t.id}:{...e}}),activeSnippetId:this.activeSnippet?.id??null,beatIndex:this.beatIndex,pendingChoice:this.pendingChoice?{groupId:this.pendingChoice.groupId,options:this.pendingChoice.options.map(e=>({...e}))}:null,pendingPromptOwnerId:this.pendingPromptOwnerId,selectors:Me(this.selectors)}}}restore(e){this.rngState=j(e.rngState),this.visitCounts=new Map(Object.entries(e.visits??{}));let t=e.cursor;this.started=!0,this.flowEnded=t.flowEnded,this.beatIndex=t.beatIndex,this.currentSceneId=t.currentSceneId,this.stack=t.stack.map(n=>{let{nextId:s,...o}=n;if(s!==void 0){let i=this.childrenOf(o.containerId)?.findIndex(a=>a.id===s)??-1;if(i>=0)return{...o,index:i}}return{...o}}),this.releaseBags(!1),this.mountLocal();for(let n of new Set([t.currentSceneId,...this.stack.map(s=>s.sceneId)]))n!==null&&this.host.bundle.scenes[n]&&this.ensureSceneBags(n);if(this.activeSnippet=null,t.activeSnippetId!==null){let n=this.host.nodeIndex.get(t.activeSnippetId);n&&n.type==="snippet"&&(this.activeSnippet=n)}if(this.selectors=$e(t.selectors),this.pendingChoice=null,t.pendingChoice!==null){let n=new Map,s=[];for(let o of t.pendingChoice.options){let i=this.host.nodeIndex.get(o.id);i&&(n.set(o.id,i),s.push({...o}))}s.length>0&&(this.pendingChoice={groupId:t.pendingChoice.groupId,options:s,byId:n})}if(this.pendingPromptBeat=null,this.pendingPromptOwnerId=t.pendingPromptOwnerId??null,this.pendingPromptOwnerId){let n=this.host.nodeIndex.get(this.pendingPromptOwnerId);this.pendingPromptBeat=n?this.promptBeatOf(n)??null:null,this.pendingPromptBeat||(this.pendingPromptOwnerId=null)}}enterSceneSetup(e){let t=this.host.bundle.scenes[e];if(!t)throw new Error(`unknown scene: ${e}`);this.currentSceneId=e,this.enter(e),this.seedScene(t),this.runEffects(t.onEntry)}enterChild(e){if(this.enter(e.id),e.type==="snippet"){this.beginSnippet(e);return}let t=e.selector??"run";if(t==="run"){this.stack.push({sceneId:this.currentSceneId,containerId:e.id,index:0});return}if(t==="choice"){this.setupChoice(e);return}let n=this.selectChild(e);n&&this.enterChild(n)}childrenOf(e){let t=this.host.blockById.get(e);if(t)return t.children;let n=this.host.nodeIndex.get(e);if(n&&n.type==="group")return n.children}beginSnippet(e){this.runEffects(e.onEnter),this.activeSnippet=e,this.beatIndex=0}setupChoice(e){let t=[],n=new Map,s=[];for(let i of e.children){if(i.fallback===!0){s.push(i);continue}if(i.sticky!==!0&&(this.visitCounts.get(i.id)??0)>=1)continue;let a=this.eligible(i),l=i.secretUntilEligible===!0;!a&&l||(t.push({id:i.id,prompt:this.promptFor(i),eligible:a,gameData:i.gameData}),n.set(i.id,i))}if(t.length>0){this.emit({type:"choice",group:e.id,options:t.map(i=>({id:i.id,eligible:i.eligible}))}),this.pendingChoice={groupId:e.id,options:t,byId:n};return}let o=s.find(i=>this.eligible(i));if(o){this.enterChild(o);return}this.emit({type:"dry",group:e.id}),this.host.onDryChoice?.(e.id)}resolveJump(e){e&&this.enterTarget(e.to,e.mode==="call"?"call":"jump")}enterTarget(e,t){if(this.emit({type:"jump",to:e,mode:t}),e==="END"){this.flowEnded=!0,this.stack=[];return}let n,s,o=this.host.bundle.scenes[e];if(o){this.enterSceneSetup(e);let a=o.blocks[0];if(!a){t==="jump"&&(this.stack=[]);return}n=e,s=a.id}else{let a=this.host.blockIndex.get(e);if(!a)throw new Error(`jump target not found: ${e}`);a.sceneId!==this.currentSceneId&&this.enterSceneSetup(a.sceneId),n=a.sceneId,s=e}this.enter(s);let i={sceneId:n,containerId:s,index:0};t==="call"?this.stack.push(i):this.stack=[i]}selectChild(e){let t=e.children.map(l=>({id:l.id,eligible:this.eligible(l)})),n=e.children.filter(l=>this.eligible(l)),s=e.options?.order??"sequential",o=e.options?.exhaust??"once",i=l=>(this.emit({type:"select",group:e.id,selector:e.selector??"default",...e.selector==="sequence"?{order:s,exhaust:o}:{},children:t,picked:l?.id??null}),l);if(n.length===0)return i(null);let a=this.selectorState(e);switch(e.selector){case"branch":return i(n[0]);case"sequence":return i(s==="shuffle"?this.pickShuffle(n,o,a):s==="specificity"?this.pickSpecificity(n,o,a):this.pickSequential(n,o,a));default:return null}}pickSequential(e,t,n){let s=e.length,o=n.seq??0;return n.seq=o+1,t==="repeat"?e[o%s]:o<s?e[o]:t==="stick"?e[s-1]:null}pickShuffle(e,t,n){let s=e.length,o=t==="stick",i=()=>(o?e.slice(0,s-1):e).map(c=>c.id);if(n.bag===void 0&&(n.bag=i()),n.bag.length===0){if(t==="once")return null;if(o){let c=e[s-1];return n.last=c.id,c}n.bag=i()}let a=n.bag,l=n.last!==void 0&&a.length>1?a.indexOf(n.last):-1,g=Math.floor(this.rng()*(l>=0?a.length-1:a.length));l>=0&&g>=l&&g++;let f=a[g];return a.splice(g,1),n.last=f,e.find(c=>c.id===f)}pickSpecificity(e,t,n){let s=e;if(t!=="repeat"){n.bag===void 0&&(n.bag=e.map(f=>f.id));let g=new Set(n.bag);if(s=e.filter(f=>g.has(f.id)),s.length===0)return t==="stick"&&n.last!==void 0?e.find(f=>f.id===n.last)??null:null}let o=-1,a=s.map(g=>{let f=this.specScore(g);return f>o&&(o=f),{c:g,s:f}}).filter(g=>g.s===o).map(g=>g.c),l;if(a.length===1)l=a[0];else{let g=n.last!==void 0?a.findIndex(c=>c.id===n.last):-1,f=Math.floor(this.rng()*(g>=0?a.length-1:a.length));g>=0&&f>=g&&f++,l=a[f]}return t!=="repeat"&&(n.bag=n.bag.filter(g=>g!==l.id)),n.last=l.id,l}specScore(e){return e.condition?this.matchedSpec(this.conditionAst(e.condition),!0):0}matchedSpec(e,t){return we(e,s=>Ge(W(s,this.context(),ce)),{want:t})}selectorState(e){let t=e.shared?this.host.sharedSelectors:this.selectors,n=t.get(e.id);return n||(n={},t.set(e.id,n)),n}runEffects(e){for(let t of e??[]){let n=this.evalExpr(t.value),s=this.host.logEnabled?this.getProperty(t.target):void 0;this.writeProperty(t.target,n,!1),this.emit({type:"write",target:t.target,value:n,...s!==void 0?{prev:s}:{}})}}eligible(e){return e.condition?Ge(this.evalExpr(e.condition)):!0}evalExpr(e){return W(this.conditionAst(e),this.context(),ce)}conditionAst(e){let t=Le.get(e);return t||(t=A(e.ast),Le.set(e,t)),t}enter(e){this.visitCounts.set(e,(this.visitCounts.get(e)??0)+1),this.host.sharedVisits.set(e,(this.host.sharedVisits.get(e)??0)+1)}rng=()=>{if(this.host.customRng)return this.host.customRng();let e=oe(this.rngState),t=e.next();return this.rngState=e.state(),t};beatResult(e){let t=this.host.tagIndex.get(e.id),n=t&&t.length?{tags:t}:{};switch(e.kind){case"gameEvent":return{type:"gameEvent",id:e.id,gameData:e.gameData,...n};case"text":return{type:"text",id:e.id,text:this.interpolate(this.resolveString(e.id)),gameData:e.gameData,...n};case"line":{let s=this.resolveString(e.id),o=!this.host.captionsOn,a=o&&e.character===this.host.captionCharacter?"":this.captionLine(this.host.bundle.voiced?s:this.interpolate(s)),l=o&&a.length===0;return{type:"line",id:e.id,text:a,character:l?void 0:e.character,characterName:l?void 0:this.resolveCharacterName(e.character),direction:l?void 0:e.direction,gameData:e.gameData,...n}}}}interpolate(e){return Pe(e,t=>this.getProperty(t))}stripCaptions(e){return Be(e,this.host.captionOpen,this.host.captionClose)}captionLine(e){return this.host.captionsOn?e:this.stripCaptions(e)}promptFor(e){let t=this.promptBeatOf(e);if(!t)return;let n=this.interpolate(this.resolveString(t.id));return t.kind==="line"?{kind:"line",text:this.captionLine(n),character:t.character,characterName:this.resolveCharacterName(t.character),direction:t.direction}:{kind:"text",text:n}}promptBeatOf(e){return e.type==="group"&&e.prompt?e.prompt:((e.type==="snippet"?e:this.firstTextSnippetIn(e.children))?.beats??[]).find(n=>n.kind==="line"||n.kind==="text")}firstTextSnippetIn(e){let t;return F(e,n=>{!t&&n.type==="snippet"&&(n.beats??[]).some(s=>s.kind==="line"||s.kind==="text")&&(t=n)}),t}resolveString(e){if(this.host.emitIds)return e;let t=this.host.strings[e];if(t!==void 0)return t;let n=this.host.defaultStrings[e];return n!==void 0?`<Untranslated: ${e}> ${n}`:e}resolveCharacterName(e){if(e===void 0||this.host.emitIds)return;let t=le(e);return this.host.strings[t]??this.host.defaultStrings[t]??this.host.castDisplay.get(e)}splitRef(e){return He(this.host,e)}newLocal(){return new L(this.host.patterLocalDecls,{pathPrefix:"@patter."})}mountLocal(){this.local=this.newLocal();let e=B.flowGlobals(this.id);this.host.registry.mountOwned(e,this.local,{owner:G}),this.registered.add(e)}releaseBags(e){for(let t of this.registered)this.host.registry.remove(t,{keep:e});this.registered.clear(),this.sceneBags.clear()}sceneBagFor(e,t){if(this.host.bundle.scenes[e])return this.ensureSceneBags(e),this.host.sceneSharedNames.get(e)?.has(t.toLowerCase())?this.host.stageBags.get(e):this.sceneBags.get(e)}ensureSceneBags(e){let t=this.host.sceneSharedNames.get(e)??new Set,n=this.host.bundle.scenes[e]?.sceneProps??[];if(!this.sceneBags.has(e)){let s=new L(n.filter(i=>!t.has(i.name.toLowerCase())),{pathPrefix:"@scene."}),o=B.flowScene(this.id,e);this.host.registry.mountOwned(o,s,{owner:G}),this.registered.add(o),this.sceneBags.set(e,s)}if(!this.host.stageBags.has(e)){let s=new L(n.filter(o=>t.has(o.name.toLowerCase())),{pathPrefix:"@scene."});this.host.registry.mountOwned(B.stage(e),s,{owner:G}),this.host.stageBags.set(e,s)}}seedScene(e){let t=this.host.sceneSharedNames.get(e.id)??new Set;this.ensureSceneBags(e.id);for(let n of e.sceneProps??[]){if(!n.temporary)continue;let s=n.name.toLowerCase(),o=t.has(s)?this.host.stageBags.get(e.id):this.sceneBags.get(e.id);o&&o.set(s,_(n))}}};function Te(r,e){F(r,t=>{if(t.type==="group"){t.prompt?.kind==="line"&&t.prompt.character&&e.add(t.prompt.character);return}for(let n of t.beats??[])n.kind==="line"&&n.character&&e.add(n.character)})}function Fe(r){return r&&Object.keys(r).length?{gameData:r}:{}}function Me(r){let e={};for(let[t,n]of r){let s={};n.seq!==void 0&&(s.seq=n.seq),n.bag&&(s.bag=[...n.bag]),n.last!==void 0&&(s.last=n.last),e[t]=s}return e}function $e(r){let e=new Map;for(let[t,n]of Object.entries(r??{})){let s={};n.seq!==void 0&&(s.seq=n.seq),n.bag&&(s.bag=[...n.bag]),n.last!==void 0&&(s.last=n.last),e.set(t,s)}return e}function Ve(r){return{name:r.name,type:r.type,values:r.values,stages:r.stages,default:r.default}}function je(r){return{name:r.name,type:r.type,values:r.values,stages:r.stages,default:r.default,writable:r.writable}}function wt(r,e){let t=je(r),n=r.writable??e;return n===void 0?t:{...t,writable:n}}function He(r,e){r.refSplitRevision!==r.registry.revision&&(r.refSplitCache.clear(),r.refSplitRevision=r.registry.revision);let t=r.refSplitCache.get(e);return t||(t=Oe(e,n=>n==="scene"||r.registry.has(n)||(r.bundle.externalScopes?.includes(n)??!1)),r.refSplitCache.set(e,t)),t}function xt(r){let e={};r.shared?.patter&&(e.patter=r.shared.patter);for(let[t,n]of Object.entries(r.stageBags??{}))e[B.stage(t)]=n;for(let[t,n]of Object.entries(r.flows??{})){n.scopes?.patter&&(e[B.flowGlobals(t)]=n.scopes.patter);for(let[s,o]of Object.entries(n.sceneBags??{}))e[B.flowScene(t,s)]=o}return e}function Ge(r){return typeof r=="boolean"?r:typeof r=="number"?r!==0:typeof r=="string"?r!=="":r.length>0}var Et=(r,e)=>r.shared??e;function ue(r,e){return{name:r.name,type:r.type,hasDefault:r.default!==void 0,...r.default!==void 0?{default:r.default}:{},shared:Et(r,e)}}function kt(r){return{name:r.name,type:r.type,hasDefault:r.default!==void 0,...r.values?{values:[...r.values]}:{},...r.purpose?{purpose:r.purpose}:{}}}function Ct(r,e){e.blocks++;let t=[...r.children];for(;t.length;){let n=t.pop();if(n.type==="group"){e.groups++,n.prompt&&e.prompts++,t.push(...n.children);continue}e.snippets++;for(let s of n.beats??[])e.beats++,s.kind==="gameEvent"&&e.gameEvents++}}function ee(r){let e={scenes:0,blocks:0,groups:0,snippets:0,beats:0,prompts:0,gameEvents:0,cast:r.cast?.length??0},t=[],n=[];for(let i of Object.values(r.scenes)){e.scenes++;let a=C(i);t.push({gameId:a,name:i.name,blocks:i.blocks.map(l=>({gameId:C(l),name:l.name}))});for(let l of i.blocks)Ct(l,e);i.sceneProps?.length&&n.push({gameId:a,properties:i.sceneProps.map(l=>ue(l,!1))})}let s=(r.scopeRegistry?.scopes??[]).map(i=>({token:i.token,writable:i.writable??!0,opaque:i.declarations===void 0,properties:(i.declarations??[]).map(a=>ue(a,!0))})),o=Object.entries(r.gameDataFields??{}).filter(([,i])=>(i?.length??0)>0).map(([i,a])=>({kind:i,fields:(a??[]).map(kt)}));return{identity:{schema:r.schema,project:r.content.project,...r.content.version!==void 0?{version:r.content.version}:{},...r.content.hash!==void 0?{hash:r.content.hash}:{},...r.content.structureHash!==void 0?{structureHash:r.content.structureHash}:{},voiced:r.voiced,defaultLocale:r.locales.default,locales:[...r.locales.included],localisation:r.localisation?.mode??"embedded",sourceDebug:r.localisation?.sourceDebug??!1},addresses:t,hostScopes:s,properties:{patter:(r.properties??[]).map(i=>ue(i,!0)),scene:n},gameData:o,counts:e}}function _e(r,e){return r.gameDataFields?.[e]??[]}function ge(r,e,t){return e&&Object.prototype.hasOwnProperty.call(e,t)?e[t]:r.find(n=>n.name===t)?.default}function qe(r,e){let t={};for(let n of r){let s=ge(r,e,n.name);s!==void 0&&(t[n.name]=s)}for(let[n,s]of Object.entries(e??{}))n in t||(t[n]=s);return t}function fe(r){return{schema:V,save:r.saveGame()}}function he(r,e){if(!e||e.schema!==V||!e.save)throw new Error(`loadState: not a ${V} envelope`);r.loadGame(e.save)}function te(r){return JSON.stringify(fe(r))}function ne(r,e){he(r,JSON.parse(e))}function Ue(r,e){return r.getProperty(e)}function We(r,e,t){r.setProperty(e,t)}function Je(r,e){for(let[t,n]of Object.entries(e))r.setProperty(t,n)}function ye(r){let e={};for(let t of ze(r)){let n=t.pathPrefix??t.bag.pathPrefix;for(let[s,o]of Object.entries(t.bag.save()))e[`${n}${s}`]=o}return Object.assign(e,Ke(r)),e}function ze(r){return[...r.listBags(),...r.flows().flatMap(e=>e.listBags())]}function Dt(r){switch(r.type){case"line":return`line ${r.character??"?"}: ${JSON.stringify(r.text)}${me(r.gameData)}`;case"text":return`text: ${JSON.stringify(r.text)}${me(r.gameData)}`;case"gameEvent":return`game event ${r.id}${me(r.gameData)}`;case"choice":return`choice (${r.options.length} option${r.options.length===1?"":"s"})`;case"end":return"end"}}var me=r=>r?` gameData=${JSON.stringify(r)}`:"";function Ke(r){let e=r.saveGame(),t={};for(let[n,s]of Object.entries(e.sharedVisits))t[`visit:${n}`]=s;for(let[n,s]of Object.entries(e.flows))for(let[o,i]of Object.entries(s.visits))t[`${n}/visit:${o}`]=i;return t}function Ye(r,e={}){let t=e.label?`[${e.label}] `:"",n=ie({mounts:()=>ze(r),extra:()=>Ke(r)},{sink:e.sink,label:t});return{snapshot:()=>ye(r),capture:()=>n.capture(),dispose:()=>n.dispose(),logStep(s){(e.sink??(o=>console.log(o)))(`${t}${Dt(s)}`)}}}function Qe(r){let e=r.url??"ws://127.0.0.1:4471",t=r.WebSocket??globalThis.WebSocket,n=new Set,s=[],o=null,i=!1,a=r.build,l=()=>{if(!(!o||o.readyState!==1)){for(let c of s)try{o.send(c)}catch{}s=[]}},g=c=>{i||(s.push(JSON.stringify(c)),l())};if(!t)return{flowOpened(){},observe(){},flowClosed(){},setBuild(){},close(){i=!0}};let f=()=>{let c=JSON.stringify({t:"hello",v:1,build:a,project:r.project,flows:[...n]});try{o?.send(c)}catch{}};try{o=new t(e),o.addEventListener("open",()=>{f(),l()}),o.addEventListener("message",c=>{if(!(!r.onBundle||typeof c.data!="string"))try{let m=JSON.parse(c.data);m.t==="bundle"&&typeof m.build=="string"&&typeof m.data=="string"&&r.onBundle({build:m.build,data:m.data})}catch{}}),o.addEventListener("error",()=>{}),o.addEventListener("close",()=>{o=null})}catch{o=null}return{flowOpened(c){n.add(c),g({t:"flowOpen",flow:c})},flowClosed(c){n.delete(c),g({t:"flowClose",flow:c})},observe(c,m,u,h,d){n.has(c)||(n.add(c),g({t:"flowOpen",flow:c})),g({t:"frame",flow:c,sceneId:m,beatId:u,type:h,choiceId:d})},setBuild(c){i||c===a||(a=c,o&&o.readyState===1&&f())},close(){i=!0,s=[];try{o?.close()}catch{}o=null}}}function Xe(r,e,t){let n=JSON.parse(t);return e.content.structureHash!==void 0&&e.content.structureHash===n.content.structureHash?(r.replaceStrings(n),{engine:r,bundle:n,kind:"text"}):{engine:r.hotSwap(n),bundle:n,kind:"structure"}}var Ze="pp-inspector-style",It=`
|
|
1
|
+
"use strict";var Patterplay=(()=>{var se=Object.defineProperty;var ot=Object.getOwnPropertyDescriptor;var it=Object.getOwnPropertyNames;var at=Object.prototype.hasOwnProperty;var ct=(r,e)=>{for(var t in e)se(r,t,{get:e[t],enumerable:!0})},lt=(r,e,t,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let s of it(e))!at.call(r,s)&&s!==t&&se(r,s,{get:()=>e[s],enumerable:!(n=ot(e,s))||n.enumerable});return r};var pt=r=>lt(se({},"__esModule",{value:!0}),r);var Lt={};ct(Lt,{Checkpoint:()=>J,Engine:()=>ee,Flow:()=>V,SAVE_SCHEMA:()=>T,applyLiveBundle:()=>Ze,buildTagIndex:()=>Z,createAudioResolver:()=>st,createBundleInspector:()=>rt,createDebugLink:()=>Xe,createPropertyInspector:()=>tt,createStateLogger:()=>Qe,describeBundle:()=>te,deserializeState:()=>re,diffState:()=>H,effectiveGameData:()=>Ue,gameDataFields:()=>_e,gameDataValue:()=>fe,getProperty:()=>Je,loadState:()=>me,saveState:()=>he,serializeState:()=>ne,setProperties:()=>ze,setProperty:()=>We,snapshotState:()=>Se});function A(r){switch(r[0]){case"b":return{kind:"bool",value:r[1]};case"n":return{kind:"number",value:r[1]};case"s":return{kind:"string",value:r[1]};case"sv":return{kind:"scopedvar",scope:r[1],name:r[2]};case"u":return{kind:"unary",op:r[1],operand:A(r[2])};case"bin":return{kind:"binary",op:r[1],left:A(r[2]),right:A(r[3])};case"call":{let e=r.slice(2).map(A);return{kind:"call",name:r[1],args:e}}case"fd":return{kind:"flagdelta",sign:r[1],name:r[2]}}}var y=class extends Error{constructor(e){super(e),this.name="EvalError"}};function W(r,e,t){let n=new Map(t.scopes.map(o=>[o.token,o.missing??"false"])),s=o=>{switch(o.kind){case"bool":return o.value;case"number":return o.value;case"string":return o.value;case"scopedvar":{let i=e.scopes[o.scope];if(i===void 0)return!1;let a=typeof i.get=="function"?i.get(o.name):i[o.name];if(a===void 0){if(n.get(o.scope)==="throw")throw new y(`@${o.scope}.${o.name} is not declared on the current ${o.scope}.`);return!1}return a}case"call":{if(o.name==="advance"&&!t.functions[o.name]){let a=o.args[0];if(o.args.length!==1||a===void 0)throw new y(`advance() takes exactly 1 argument, got ${o.args.length}`);let c=oe(a,e);if(c===void 0)throw new y("advance() needs a quality reference (@scope.name of a quality property)");let u=P(s(a),c,"advance");return c[Math.min(u+1,c.length-1)]}let i=t.functions[o.name];if(!i)throw new y(`unknown function '${o.name}'`);return i.eval(o.args,{evaluate:s,ctx:e})}case"flagdelta":throw new y("flagdelta node is only valid as an argument to a flag-delta function");case"unary":{if(o.op==="not"){let a=s(o.operand);if(typeof a!="boolean")throw new y(`'not' requires a boolean operand, got ${typeof a}`);return!a}let i=s(o.operand);if(typeof i!="number")throw new y(`unary '-' requires a numeric operand, got ${typeof i}`);return-i}case"binary":{if(o.op==="and"){let l=s(o.left);if(typeof l!="boolean")throw new y(`'and' requires boolean operands, left is ${typeof l}`);if(!l)return!1;let m=s(o.right);if(typeof m!="boolean")throw new y(`'and' requires boolean operands, right is ${typeof m}`);return m}if(o.op==="or"){let l=s(o.left);if(typeof l!="boolean")throw new y(`'or' requires boolean operands, left is ${typeof l}`);if(l)return!0;let m=s(o.right);if(typeof m!="boolean")throw new y(`'or' requires boolean operands, right is ${typeof m}`);return m}let i=s(o.left),a=s(o.right),c=oe(o.left,e),u=oe(o.right,e),f=c??u;if(f!==void 0){if(c&&u&&!dt(c,u)&&(o.op===">"||o.op===">="||o.op==="<"||o.op==="<="))throw new y(`'${o.op}' compares two different qualities, whose stage orders are unrelated`);switch(o.op){case">":return P(i,f,">")>P(a,f,">");case">=":return P(i,f,">=")>=P(a,f,">=");case"<":return P(i,f,"<")<P(a,f,"<");case"<=":return P(i,f,"<=")<=P(a,f,"<=");case"+":case"-":case"*":case"/":throw new y(`'${o.op}' cannot be applied to a quality - a stage is a position, not a number; use advance() to move it`);default:break}}switch(o.op){case"==":return we(i,a);case"!=":return!we(i,a);case">":return j(i,a,">"),i>a;case">=":return j(i,a,">="),i>=a;case"<":return j(i,a,"<"),i<a;case"<=":return j(i,a,"<="),i<=a;case"+":if(typeof i=="number"&&typeof a=="number"||typeof i=="string"&&typeof a=="string")return i+a;throw new y(`'+' requires two numbers or two strings, got ${typeof i} and ${typeof a}`);case"-":return j(i,a,"-"),i-a;case"*":return j(i,a,"*"),i*a;case"/":if(j(i,a,"/"),a===0)throw new y("division by zero");return i/a}}}};return s(r)}function we(r,e){if(Array.isArray(r)||Array.isArray(e)){if(!Array.isArray(r)||!Array.isArray(e)||r.length!==e.length)return!1;let t=[...r].sort(),n=[...e].sort();for(let s=0;s<t.length;s++)if(t[s]!==n[s])return!1;return!0}return r===e}function j(r,e,t){if(typeof r!="number"||typeof e!="number")throw new y(`'${t}' requires numeric operands, got ${typeof r} and ${typeof e}`)}function oe(r,e){if(!(r.kind!=="scopedvar"||e.qualities===void 0))return e.qualities(r.scope,r.name)}function P(r,e,t){if(typeof r!="string")throw new y(`'${t}' on a quality compares stages, got ${typeof r}`);let n=e.indexOf(r);if(n<0)throw new y(`"${r}" is not a stage of this quality (stages: ${e.join(", ")})`);return n}var dt=(r,e)=>r.length===e.length&&r.every((t,n)=>t===e[n]);function $(r){if(Number.isNaN(r)||!Number.isFinite(r))return 0;let e=Math.trunc(r)%4294967296;return e<0?e+4294967296:e}function ie(r){let e=$(r);return{next(){e=e+1831565813>>>0;let t=Math.imul(e^e>>>15,1|e);return t=t+Math.imul(t^t>>>7,61|t)^t,((t^t>>>14)>>>0)/4294967296},state(){return e}}}var ut={name:"check_flags",count:r=>Math.max(1,r.args.length-1)},gt=[ut];function xe(r,e,t){let n=t?.countingCalls??gt;return z(r,t?.want??!0,e,n)}function z(r,e,t,n){if(r.kind==="binary"&&(r.op==="and"||r.op==="or")){let s=z(r.left,e,t,n),o=z(r.right,e,t,n);return r.op==="and"===e?s>0&&o>0?s+o:0:Math.max(s,o)}if(r.kind==="unary"&&r.op==="not")return z(r.operand,!e,t,n);if(r.kind==="call"){let s=n.find(o=>o.name===r.name);if(s){let o=s.count(r),i=t(r);return e?i?o:0:i?0:1}}return t(r)===e?1:0}function H(r,e){let t=[],n=new Set([...Object.keys(r),...Object.keys(e)]);for(let s of[...n].sort()){let o=r[s],i=e[s];JSON.stringify(o)!==JSON.stringify(i)&&t.push({path:s,from:o,to:i})}return t}var ke=r=>r===void 0?"<unset>":JSON.stringify(r),Ee=r=>r.pathPrefix??r.bag.pathPrefix;function ae(r,e={}){let t=e.sink??(l=>console.log(l)),n=e.label??"",s=l=>{t(`${n}${l.path}: ${ke(l.from)} -> ${ke(l.to)}`)},o=()=>{let l={};for(let m of r.mounts()){let g=Ee(m);for(let[h,d]of Object.entries(m.bag.values))l[g+h]=d}return Object.assign(l,r.extra?.()??{}),structuredClone(l)},i=o(),a=[],c=[],u=(l,m)=>m.onAudit(g=>{let h=structuredClone({path:l+g.name,from:g.prev,to:g.next});s(h),a.push(h),i[h.path]=structuredClone(g.next)}),f=()=>{let l=r.mounts();if(!(c.length===l.length&&l.every((g,h)=>c[h].bag===g.bag))){for(let g of c)g.off();c=l.map(g=>({bag:g.bag,off:u(Ee(g),g.bag)}))}};return f(),{snapshot:o,capture(){let l=o(),m=H(i,l);for(let h of m)s(h);let g=[...a,...m];return a=[],i=l,f(),g},dispose(){for(let l of c)l.off();c=[],a=[]}}}var L=class r{values={};decls=new Map;subscribers=new Set;auditors=new Set;norm;pathPrefix;constructor(e=[],t){this.norm=t?.normalise??(n=>n.toLowerCase()),this.pathPrefix=t?.pathPrefix??"",this.seed(e)}seed(e){for(let t of e){let n=this.norm(t.name);this.decls.set(n,t),this.values[n]=structuredClone(t.default??q(t))}}get(e){return this.values[this.norm(e)]}normalise(e){return this.norm(e)}set(e,t,n){let s=this.norm(e);if(!n?.host&&this.decls.get(s)?.writable===!1)throw new Error(`'${e}' is read-only`);let o={name:s,prev:this.values[s],next:t,silent:n?.silent??!1,reason:n?.reason};this.values[s]=t;for(let i of this.auditors)i(o);if(!o.silent)for(let i of this.subscribers)i(o);return o}subscribe(e){return this.subscribers.add(e),()=>this.subscribers.delete(e)}onAudit(e){return this.auditors.add(e),()=>this.auditors.delete(e)}rows(){return[...this.decls.entries()].map(([e,t])=>Ie(t,this.get(e),void 0,e,this.pathPrefix))}declarations(){return[...this.decls.values()]}clone(){let e=new r([],{normalise:this.norm,pathPrefix:this.pathPrefix});return e.decls=new Map(this.decls),Object.assign(e.values,structuredClone(this.values)),e}reseed(e){for(let t of Object.keys(this.values))delete this.values[t];this.decls.clear(),this.seed(e)}save(){return structuredClone(this.values)}load(e){for(let[t,n]of Object.entries(e))this.values[this.norm(t)]=n}};function Ie(r,e,t,n,s=""){let o=n??r.name.toLowerCase();return{name:o,path:s+o,type:r.type,value:e,default:r.default??q(r),...r.values!==void 0?{values:r.values}:{},...r.stages!==void 0?{stages:r.stages}:{},writable:t??r.writable??!0}}var ft=r=>r.toLowerCase(),ce=1,K=class{scopes=new Map;parked=new Map;rev=0;get revision(){return this.rev}defineOwned(e,t,n){let s=typeof n=="string"?{pathPrefix:n}:n??{},o=new L(t,{pathPrefix:s.pathPrefix??`${e}.`,...s.normalise?{normalise:s.normalise}:{}});return this.mountOwned(e,o,s.owner!==void 0?{owner:s.owner}:void 0)}mountOwned(e,t,n){this.assertFree(e,n?.owner),this.scopes.set(e,{kind:"owned",bag:t,...n?.owner!==void 0?{owner:n.owner}:{}}),this.rev++;let s=this.parked.get(e);return s&&(t.load(s),this.parked.delete(e)),this}remove(e,t){let n=this.scopes.get(e);if(!n)throw new Error(`unknown scope '@${e}'`);return t?.keep&&n.kind==="owned"&&this.parked.set(e,n.bag.save()),this.scopes.delete(e),this.rev++,this}discardParked(e){if(e===void 0)this.parked.clear();else for(let t of[...this.parked.keys()])t.startsWith(e)&&this.parked.delete(t);return this}ownedBag(e){let t=this.scopes.get(e);if(!t||t.kind!=="owned")throw new Error(`'@${e}' is not an owned scope`);return t.bag}reseedOwned(e,t){return this.ownedBag(e).reseed(t),this}defineForeign(e,t,n=[],s=!0){let o=typeof s=="boolean"?{writable:s}:s;this.assertFree(e,o.owner);let i=o.normalise??ft,a=new Map;for(let c of n)a.set(i(c.name),c);return this.scopes.set(e,{kind:"foreign",resolver:t,decls:a,scopeWritable:o.writable??!0,norm:i,...o.owner!==void 0?{owner:o.owner}:{}}),this.rev++,this}has(e){return this.scopes.has(e)}get(e,t){let n=this.scopes.get(e);if(n)return n.kind==="owned"?n.bag.get(t):n.resolver.get(n.norm(t))}set(e,t,n,s){let o=this.scopes.get(e);if(!o)throw new Error(`unknown scope '@${e}'`);if(o.kind==="owned"){try{o.bag.set(t,n,s?.host?{host:!0}:void 0)}catch{throw new Error(`'@${e}.${t}' is read-only`)}return}let i=o.norm(t);if(!o.resolver.set)throw new Error(`'@${e}.${t}' is read-only`);if(!s?.host&&!this.foreignWritable(o,i))throw new Error(`'@${e}.${t}' is read-only`);o.resolver.set(i,n)}foreignWritable(e,t){return e.resolver.set?e.decls.get(t)?.writable??e.scopeWritable:!1}listProperties(){let e=[];for(let[t,n]of this.scopes){let s=n.owner!==void 0?{owner:n.owner}:{};if(n.kind==="owned")for(let o of n.bag.rows())e.push({scope:t,...s,...o});else for(let[o,i]of n.decls)e.push({scope:t,...s,...Ie(i,n.resolver.get(o),this.foreignWritable(n,o),o,`${t}.`)})}return e}toEvalContext(e,t){let n=this.view(t?.aliases),s={};for(let[i,a]of n)s[i]=a.kind==="owned"?a.bag.values:a.resolver;let o=this.qualityLadders(n);return o.size===0?{scopes:s,host:e}:{scopes:s,host:e,qualities:(i,a)=>{let c=n.get(i);return c?o.get(i)?.get(ht(c)(a)):void 0}}}view(e){let t=new Map(this.scopes);for(let[n,s]of Object.entries(e??{})){let o=this.scopes.get(s);if(!o)throw new Error(`alias '@${n}' names '${s}', which is not registered`);t.set(n,o)}return t}qualityLadders(e){let t=new Map;for(let[n,s]of e)for(let[o,i]of Ce(s)){if(i.type!=="quality"||i.stages===void 0)continue;let a=t.get(n);a||(a=new Map,t.set(n,a)),a.set(o,i.stages)}return t}toSchema(e){let t=new Map;for(let[n,s]of this.view(e?.aliases)){let o=Ce(s);if(o.length===0)continue;let i=new Map;for(let[a,c]of o)i.set(a,{type:c.type,enumValues:c.values,...c.stages!==void 0?{stages:c.stages}:{}});t.set(n,i)}return{properties:t}}save(){let e={};for(let[t,n]of this.scopes)n.kind==="owned"&&(e[t]=n.bag.save());for(let[t,n]of this.parked)e[t]=structuredClone(n);return e}load(e,t){t?.keepParked||this.parked.clear();for(let[n,s]of Object.entries(e)){let o=this.scopes.get(n);o?.kind==="owned"?o.bag.load(s):o||this.parked.set(n,structuredClone(s))}}saveFragment(){return{version:ce,scopes:this.save()}}loadFragment(e){if(e.version!==ce)throw new Error(`unsupported owned-state fragment version ${e.version} (supported: ${ce})`);this.load(e.scopes)}assertFree(e,t){let n=this.scopes.get(e);if(!n)return;let s=n.owner!==void 0?` by ${n.owner}`:"",o=t!==void 0?` (wanted by ${t})`:"";throw new Error(`scope '@${e}' is already registered${s}${o}`)}};function Ce(r){return r.kind==="foreign"?[...r.decls.entries()]:r.bag.declarations().map(e=>[r.bag.normalise(e.name),e])}function ht(r){return r.kind==="foreign"?r.norm:e=>r.bag.normalise(e)}function q(r){if(r.default!==void 0)return r.default;switch(r.type){case"boolean":return!1;case"number":return 0;case"string":return"";case"enum":return r.values?.[0]??"";case"flags":return[];case"quality":return r.stages?.[0]??"";default:return!1}}var De=[{token:"patter",engine:"Patterplay",means:"Patter's shared globals"},{token:"story",engine:"Storylet Engine",means:"the Storylet Engine's shared @story properties"}];function _(r){return r.ctx.host??{}}var le={defaultScope:"patter",scopes:[{token:"patter"},{token:"scene"}],functions:{random:{minArgs:2,maxArgs:2,returnType:"number",eval(r,e){if(r.length!==2)throw new y("random(a, b) requires exactly 2 arguments");let t=_(e).nextRandom;if(!t)throw new y("random() called without a PRNG in context");let n=e.evaluate(r[0]),s=e.evaluate(r[1]);if(typeof n!="number"||typeof s!="number")throw new y("random(a, b) arguments must be numbers");if(!Number.isInteger(n)||!Number.isInteger(s))throw new y("random(a, b) arguments must be integers");let o=Math.min(n,s),i=Math.max(n,s);return Math.floor(t()*(i-o+1))+o}},check_flags:{minArgs:1,returnType:"boolean",flagDeltaArgs:!0,validate:Oe("check_flags"),eval(r,e){let t=Re(r[0],e,"check_flags");for(let n=1;n<r.length;n++){let s=r[n];if(s.kind!=="flagdelta")throw new y("check_flags() flag args must be +flagName or -flagName");if(s.sign==="+"?!t.includes(s.name):t.includes(s.name))return!1}return!0}},set_flags:{minArgs:1,returnType:"flags",flagDeltaArgs:!0,validate:Oe("set_flags"),eval(r,e){let t=[...Re(r[0],e,"set_flags")];for(let n=1;n<r.length;n++){let s=r[n];if(s.kind!=="flagdelta")throw new y("set_flags() flag args must be +flagName or -flagName");if(s.sign==="+")t.includes(s.name)||t.push(s.name);else{let o=t.indexOf(s.name);o>=0&&t.splice(o,1)}}return t}},visits:{minArgs:1,maxArgs:1,returnType:"number",validate:Q("visits"),eval:(r,e)=>_(e).visits?.(Y(r,e,"visits"))??0},seen:{minArgs:1,maxArgs:1,returnType:"boolean",validate:Q("seen"),eval:(r,e)=>(_(e).visits?.(Y(r,e,"seen"))??0)>0},patter_visits:{minArgs:1,maxArgs:1,returnType:"number",validate:Q("patter_visits"),eval:(r,e)=>_(e).patterVisits?.(Y(r,e,"patter_visits"))??0},patter_seen:{minArgs:1,maxArgs:1,returnType:"boolean",validate:Q("patter_seen"),eval:(r,e)=>(_(e).patterVisits?.(Y(r,e,"patter_seen"))??0)>0}}},Qt=De.map(r=>r.token).filter(r=>r!=="patter"&&r!=="scene");function Be(r,e){let t=r.replace(/^@/,"").split(".");return t.length===2&&e(t[0])?{scope:t[0],name:t[1].toLowerCase()}:{scope:"patter",name:t.join(".").toLowerCase()}}function Y(r,e,t){let n=e.evaluate(r[0]);if(typeof n!="string")throw new y(`${t}(id) requires a string node id`);return n}function Q(r){return(e,t)=>{let n=e[0];n&&n.kind!=="string"&&t.report({path:[...t.path,"args",0],kind:"wrong-arg-type",severity:"error",message:`${r}(id): the argument must be a string id literal (a scene / block / node id)`})}}function Re(r,e,t){if(!r)throw new y(`${t}() requires at least one argument (the flags variable)`);let n=e.evaluate(r);if(Array.isArray(n))return n;if(n===!1||n===null||n===void 0)return[];throw new y(`${t}() first argument must be a flags property`)}function Oe(r){return(e,t)=>{if(e.length===0)return;let n=e[0];if(n.kind!=="scopedvar"){t.report({path:[...t.path,"args",0],kind:"wrong-arg-type",severity:"error",message:`${r}(): first argument must be a flags property reference (@name or @scope.name)`});return}let s=t.schema.properties.get(n.scope)?.get(n.name);if(s&&s.type!=="flags"){let o=n.scope===t.defaultScope?n.name:`${n.scope}.${n.name}`;t.report({path:[...t.path,"args",0],kind:"wrong-arg-type",severity:"error",message:`${r}(): '@${o}' is not a flags property (got ${s.type})`});return}for(let o=1;o<e.length;o++){let i=e[o];i.kind!=="flagdelta"?t.report({path:[...t.path,"args",o],kind:"wrong-arg-type",severity:"error",message:`${r}(): argument ${o+1} must be +flagName or -flagName`}):s?.type==="flags"&&s.enumValues&&!s.enumValues.includes(i.name)&&t.report({path:[...t.path,"args",o],kind:"unknown-flag-name",severity:"error",message:`${r}(): unknown flag '${i.name}'`,reference:i.name})}}}var mt=/^@[A-Za-z0-9_.]+$/;function*yt(r){let e="",t=0;for(;t<r.length;){let n=r[t];if(n==="{"&&r[t+1]==="{"){e+="{",t+=2;continue}if(n==="}"&&r[t+1]==="}"){e+="}",t+=2;continue}if(n==="{"){let s=r.indexOf("}",t+1);if(s!==-1){let o=r.slice(t,s+1),i=r.slice(t+1,s).trim();if(i.startsWith("@")){e&&(yield{kind:"text",value:e},e=""),yield{kind:"slot",raw:o,inner:i,ref:mt.test(i)?i:void 0},t=s+1;continue}e+=o,t=s+1;continue}}e+=n,t+=1}e&&(yield{kind:"text",value:e})}function St(r){return Array.isArray(r)?r.join(", "):typeof r=="boolean"?r?"true":"false":String(r)}function bt(r){return r===" "||r===" "||r===`
|
|
2
|
+
`||r==="\r"||r==="\f"||r==="\v"}function vt(r){let e="",t=!1;for(let n of r){if(bt(n)){t=!0;continue}t&&e.length>0&&(e+=" "),t=!1,e+=n}return e}function Pe(r,e,t){if(e.length===0||r.indexOf(e)<0)return r;let n="",s=0,o=!1;for(;s<r.length;){if(r.startsWith(e,s)){let i=r.indexOf(t,s+e.length);if(i>=0){s=i+t.length,o=!0;continue}n+=r.slice(s);break}n+=r[s],s+=1}return o?vt(n):r}function Ne(r,e){if(r.indexOf("{")<0)return r;let t="";for(let n of yt(r)){if(n.kind==="text"){t+=n.value;continue}if(!n.ref){t+=n.raw;continue}let s=e(n.ref);t+=s===void 0?"":St(s)}return t}function F(r,e){for(let t of r){e(t);let n=t.children;n&&F(n,e)}}function wt(r){return r.toLowerCase().replace(/['’]/g,"").replace(/[^a-z0-9-]+/g,"-").replace(/-+/g,"-").replace(/^-+|-+$/g,"")}function C(r){let e=r.gameId?.trim();return e||wt(r.name)}function pe(r){return`cast:${r}`}var de={open:"[",close:"]"},Le="SFX",T="patter/save@0",ue=3;function X(r){let e=new Set,t=[];for(let n of r)e.has(n)||(e.add(n),t.push(n));return t}function Z(r){let e=new Map,t=(n,s)=>{let o=X([...s,...n.tags??[]]);if(e.set(n.id,o),n.type==="group")for(let i of n.children)t(i,o);else for(let i of n.beats??[])e.set(i.id,X([...o,...i.tags??[]]))};for(let n of Object.values(r.scenes)){let s=X(n.tags??[]);e.set(n.id,s);for(let o of n.blocks){let i=X([...s,...o.tags??[]]);e.set(o.id,i);for(let a of o.children)t(a,i)}}return e}var Ae=new WeakMap,G="Patter",U=r=>r.replace(/%/g,"%25").replace(/\//g,"%2F"),je=Symbol("ownsRegistry"),D={stage:r=>`patter/scene/${U(r)}`,flow:r=>`patter/flow/${U(r)}/`,flowGlobals:r=>`patter/flow/${U(r)}/patter`,flowScene:(r,e)=>`patter/flow/${U(r)}/scene/${U(e)}`},J=class{constructor(e){this.journal=e}journal},ee=class r{host;defaultSeed;flowsById=new Map;allStrings;currentLocale;sourceDebug;sceneGameIdToId=new Map;blockGameIdToId=new Map;creationOptions;engineLog=[];engineTraceHandlers=new Set;constructor(e,t={}){this.creationOptions=t;let n=t.locale??e.locales.default,s=e.strings;this.allStrings=s,this.currentLocale=n;let o=s[n]??{},i=s[e.locales.default]??{},a=e.localisation,c=a?.mode==="ids"&&!a.sourceDebug;this.sourceDebug=a?.mode==="ids"&&!!a.sourceDebug,this.sourceDebug&&typeof console<"u"&&console.warn("[Patterplay] source-only DEBUG build: strings are the source language for debugging, not a shippable localised build.");let u=new Map;for(let S of e.cast??[])S.displayName&&u.set(S.name,S.displayName);this.defaultSeed=(t.seed??2654435769)>>>0;let f=new Map,l=new Map,m=new Map;for(let[S,p]of Object.entries(e.scenes)){this.sceneGameIdToId.set(C(p),S);let w=new Map;for(let x of p.blocks)l.set(x.id,{sceneId:S}),m.set(x.id,x),w.set(C(x),x.id),F(x.children,ve=>f.set(ve.id,ve));this.blockGameIdToId.set(S,w)}let g=e.properties??[],h=g.filter(S=>S.shared??!0).map(Ge),d=g.filter(S=>!(S.shared??!0)).map(Ge),v=new Set(h.map(S=>S.name.toLowerCase())),k=t.registry??new K,E=!t.registry||t[je]===!0,O=new L(h,{pathPrefix:"@patter."}),I=[],B=[];try{k.mountOwned("patter",O,{owner:G}),B.push("patter");let S=new Set;if(t.world){let p=e.scopeRegistry?.scopes.find(x=>x.token==="world"),w=(p?.declarations??[]).map(He);k.defineForeign("world",t.world,w,{writable:p?.writable??!0,owner:G}),B.push("world"),S.add("world")}for(let p of E?e.scopeRegistry?.scopes??[]:[]){if(S.has(p.token)||k.has(p.token))continue;let w=(p.declarations??[]).map(x=>xt(x,p.writable));k.defineOwned(p.token,w,{owner:G}),B.push(p.token),I.push(p.token)}}catch(S){for(let p of B)k.remove(p,{keep:!0});throw S}let N=new Map;for(let[S,p]of Object.entries(e.scenes)){let w=new Set((p.sceneProps??[]).filter(x=>x.shared??!1).map(x=>x.name.toLowerCase()));N.set(S,w)}this.host={logEnabled:t.log??!1,emitEngine:(S,p,w)=>this.emitEngine(S,p,w),bundle:e,emitIds:c,strings:o,defaultStrings:i,castDisplay:u,nodeIndex:f,blockIndex:l,blockById:m,sceneGameIdToId:this.sceneGameIdToId,blockGameIdToId:this.blockGameIdToId,tagIndex:Z(e),registry:k,ownsRegistry:E,patterBag:O,hostScopes:I,patterSharedDecls:h,patterLocalDecls:d,patterSharedNames:v,sceneSharedNames:N,sharedVisits:new Map,sharedSelectors:new Map,stageBags:new Map,journal:null,customRng:t.rng,onDryChoice:t.onDryChoice,replayPromptOnChoose:t.replayPromptOnChoose??!1,captionsOn:t.closedCaptions??!0,captionOpen:(e.closedCaptions??de).open,captionClose:(e.closedCaptions??de).close,captionCharacter:e.closedCaptions?.character||Le,refSplitCache:new Map,refSplitRevision:k.revision}}get locale(){return this.currentLocale}get isSourceDebug(){return this.sourceDebug}setLocale(e){this.currentLocale=e,this.host.strings=this.allStrings[e]??{}}replaceStrings(e){this.allStrings=e.strings,this.host.strings=this.allStrings[this.currentLocale]??{},this.host.defaultStrings=this.allStrings[this.host.bundle.locales.default]??{}}hotSwap(e){this.refuseInCheckpoint("hotSwap");let t=this.saveGame(),n=i=>(i.setLocale(this.currentLocale),i.setClosedCaptions(this.host.captionsOn),i),s=()=>new r(e,{...this.creationOptions,registry:this.host.registry,[je]:this.host.ownsRegistry});this.release(!0);let o=s();try{return o.loadGame(t),n(o)}catch{o.release(!0);let i=s();for(let[a,c]of Object.entries(t.flows)){let u=c.cursor.currentSceneId;try{i.openFlow(a,u!==null?{scene:u}:{})}catch{}}return n(i)}}get closedCaptions(){return this.host.captionsOn}setClosedCaptions(e){this.host.captionsOn=e}openFlow(e,t={}){this.assertExternalScopes();let{sceneId:n,blockId:s}=this.resolveOpenAddress(t.scene,t.block),o=this.flowsById.get(e),i=this.host.journal;if(i&&o&&!o.isClosed)throw new Error(`openFlow would replace the open flow '${e}', which can't be undone while a checkpoint is open`);o?.close();let a=new V(e,this.host,t.seed??this.defaultSeed);return i&&(i.flows.add(a),i.opened.add(a),i.undo.push(()=>{a.close(),o?this.flowsById.set(e,o):this.flowsById.delete(e)})),this.flowsById.set(e,a),a.start(n,s),a}runFlow(e,t,n){let s=this.flowsById.get(e);if(!s)return this.openFlow(e,{scene:t,block:n}).advanceToStop().played;if(!s.goto(t,n))throw new Error(`runFlow: address not found: ${t}${n===void 0?"":` / ${n}`}`);return s.advanceToStop().played}assertExternalScopes(){for(let e of this.host.bundle.externalScopes??[])if(!this.host.registry.has(e))throw new Error(`this content names @${e}, which no engine on this registry registered: give every engine the game's one registry`)}resolveOpenAddress(e,t){if(e!==void 0){let n=this.resolveSceneRef(e);if(!this.host.bundle.scenes[n])throw new Error(`unknown scene: ${e}`);if(t===void 0)return{sceneId:n};let s=this.blockGameIdToId.get(n)?.get(t)??(this.host.blockIndex.get(t)?.sceneId===n?t:void 0);if(s===void 0)throw new Error(`unknown block: ${t}`);return{sceneId:n,blockId:s}}if(t!==void 0){if(!this.host.blockIndex.has(t))throw new Error(`unknown block: ${t}`);return{blockId:t}}if(Object.keys(this.host.bundle.scenes).length===0)throw new Error("no scenes in bundle");return{}}resolveSceneRef(e){if(e!=null)return this.host.bundle.scenes[e]?e:this.sceneGameIdToId.get(e)??e}resolveBlockRef(e,t){if(t!=null){if(this.host.blockById.has(t))return t;if(e!=null){let n=this.blockGameIdToId.get(e)?.get(t);if(n)return n}return t}}sceneAddress(e){let t=this.host.bundle.scenes[e];return t?C(t):void 0}blockAddress(e){let t=this.host.blockById.get(e);return t?C(t):void 0}tagsForBeat(e){return this.host.tagIndex.get(e)??[]}tagsForScene(e){let t=this.resolveSceneRef(e);return(t!=null?this.host.tagIndex.get(t):void 0)??[]}tagsForBlock(e,t){let n=this.resolveSceneRef(e),s=this.resolveBlockRef(n,t);return(s!=null?this.host.tagIndex.get(s):void 0)??[]}gameDataForScene(e){let t=this.resolveSceneRef(e);return{...(t!=null?this.host.bundle.scenes[t]:void 0)?.gameData}}gameDataForBlock(e,t){let n=this.resolveBlockRef(this.resolveSceneRef(e),t);return{...(n!=null?this.host.blockById.get(n):void 0)?.gameData}}getCast(){let e=[];for(let t of this.host.bundle.cast??[])t?.name&&e.push(t.name);return e}castForScene(e){let t=this.resolveSceneRef(e),n=t!=null?this.host.bundle.scenes[t]:void 0;if(!n)return[];let s=new Set;for(let o of n.blocks)Fe(o.children,s);return[...s]}castForBlock(e,t){let n=this.resolveSceneRef(e),s=this.resolveBlockRef(n,t),o=s!=null?this.host.blockById.get(s):void 0;if(!o)return[];let i=new Set;return Fe(o.children,i),[...i]}getOutline(){return Object.values(this.host.bundle.scenes).map(e=>({id:e.id,...C(e)?{gameId:C(e)}:{},name:e.name,...Te(e.gameData),...this.tagsField(e.id),blocks:e.blocks.map(t=>({id:t.id,...C(t)?{gameId:C(t)}:{},name:t.name,...Te(t.gameData),...this.tagsField(t.id),children:t.children.map(n=>this.outlineNode(n))}))}))}getBeatSequence(){let e=[];for(let t of Object.values(this.host.bundle.scenes))for(let n of t.blocks)F(n.children,s=>{if(s.type==="snippet")for(let o of s.beats??[])e.push({sceneId:t.id,blockId:n.id,snippetId:s.id,beat:this.beatInfo(o)})});return e}outlineNode(e){return e.type==="group"?{type:"group",id:e.id,...this.tagsField(e.id),...e.selector?{selector:e.selector}:{},...e.prompt?{prompt:this.beatInfo(e.prompt)}:{},children:e.children.map(t=>this.outlineNode(t))}:{type:"snippet",id:e.id,...this.tagsField(e.id),beats:(e.beats??[]).map(t=>this.beatInfo(t)),...e.jump?{jumpTo:e.jump.to,...e.jump.mode?{jumpMode:e.jump.mode}:{}}:{}}}beatInfo(e){let t=this.host.tagIndex.get(e.id),n={id:e.id,kind:e.kind};if(e.kind==="line"){if(e.character!==void 0){n.character=e.character;let s=this.host.defaultStrings[pe(e.character)]??this.host.castDisplay.get(e.character);s!==void 0&&(n.characterName=s)}e.direction!==void 0&&(n.direction=e.direction)}if(e.kind==="line"||e.kind==="text"){let s=this.host.defaultStrings[e.id];s!==void 0&&(n.text=s)}return e.gameData&&Object.keys(e.gameData).length&&(n.gameData=e.gameData),t&&t.length&&(n.tags=t),n}tagsField(e){let t=this.host.tagIndex.get(e);return t&&t.length?{tags:t}:{}}getFlow(e){return this.flowsById.get(e)}flows(){return[...this.flowsById.values()]}listBags(){let e=[{bag:this.host.patterBag}];for(let[t,n]of this.host.stageBags)e.push({bag:n,pathPrefix:`@scene:${t}.`});return e}checkpoint(){if(this.host.journal)throw new Error("a checkpoint is already open: roll it back or commit it first");let e={undo:[],flows:new Set,opened:new Set,selectors:new Set,flowSelectors:new Map};return this.host.journal=e,new J(e)}rollback(e){this.endCheckpoint(e);let t=e.journal.undo;for(let n=t.length-1;n>=0;n--)t[n]();r.forget(e.journal)}commit(e){this.endCheckpoint(e),r.forget(e.journal)}get inCheckpoint(){return this.host.journal!==null}endCheckpoint(e){if(this.host.journal!==e.journal)throw new Error("that checkpoint is not the open one");this.host.journal=null}static forget(e){e.undo=[],e.flows.clear(),e.opened.clear(),e.selectors.clear(),e.flowSelectors.clear()}refuseInCheckpoint(e){if(this.host.journal)throw new Error(`${e} can't be undone, so it isn't allowed while a checkpoint is open`)}closeFlow(e){this.refuseInCheckpoint("closeFlow"),this.flowsById.get(e)?.close(),this.flowsById.delete(e)}reset(){this.refuseInCheckpoint("reset");for(let e of this.flowsById.values())e.close();this.flowsById.clear(),this.host.patterBag.reseed(this.host.patterSharedDecls),this.host.sharedVisits.clear(),this.host.sharedSelectors.clear();for(let e of this.host.stageBags.keys())this.host.registry.remove(D.stage(e));this.host.stageBags.clear(),this.host.registry.discardParked("patter/")}release(e){for(let n of this.flowsById.values())n.releaseBags(e),n.close();this.flowsById.clear();let t=this.host.registry;for(let n of this.host.stageBags.keys())t.remove(D.stage(n),{keep:e});this.host.stageBags.clear();for(let n of["patter",...this.host.hostScopes])t.has(n)&&t.remove(n,{keep:e});this.creationOptions.world&&t.has("world")&&t.remove("world")}getProperty(e){let{scope:t,name:n}=this.splitShared(e);return this.host.registry.get(t,n)}setProperty(e,t){let{scope:n,name:s}=this.splitShared(e),o=this.host.journal?this.host.registry.get(n,s):void 0;this.host.registry.set(n,s,t,{host:!0}),this.host.journal&&o!==void 0&&this.host.journal.undo.push(()=>this.host.registry.set(n,s,o,{host:!0}))}log(){return this.engineLog}clearLog(){this.engineLog.length=0}onTrace(e){return this.engineTraceHandlers.add(e),()=>this.engineTraceHandlers.delete(e)}emitEngine(e,t,n){for(let s of this.engineTraceHandlers)s(e,t);this.host.logEnabled&&this.engineLog.push({...t,flow:e,seq:this.engineLog.length,...n?{scene:n}:{}})}listProperties(){return this.host.patterSharedDecls.map(e=>({name:e.name,path:`@patter.${e.name}`,type:e.type,values:e.values,stages:e.stages,value:this.getProperty(`@${e.name}`),default:q(e),writable:e.writable??!0}))}splitShared(e){let t=qe(this.host,e);if(t.scope==="scene")throw new Error(`'${e}': @scene properties are scene-scoped - read/write them on a Flow, not the Engine`);return t}save(){return{patter:this.host.patterBag.save()}}load(e){e.patter&&this.host.patterBag.load(e.patter)}saveGame(){let e={};for(let[t,n]of this.flowsById)e[t]=n.snapshot();return{version:ue,...this.host.ownsRegistry?{registry:this.host.registry.save()}:{},sharedVisits:Object.fromEntries(this.host.sharedVisits),sharedSelectors:Me(this.host.sharedSelectors),flows:e}}loadGame(e){this.refuseInCheckpoint("loadGame");let t=e.version;if(t!==2&&t!==ue)throw new Error(`unsupported save version: ${String(t)}`);this.assertExternalScopes();let n=this.host.registry;for(let[o,i]of this.flowsById)i.releaseBags(o in e.flows),i.close();this.flowsById.clear();for(let o of this.host.stageBags.keys())n.remove(D.stage(o),{keep:!0});this.host.stageBags.clear();let s=e.version===2?kt(e):e.registry;s&&(this.host.ownsRegistry?n.load(s):n.load(s,{keepParked:!0})),this.host.sharedVisits.clear();for(let[o,i]of Object.entries(e.sharedVisits??{}))this.host.sharedVisits.set(o,i);this.host.sharedSelectors.clear();for(let[o,i]of $e(e.sharedSelectors))this.host.sharedSelectors.set(o,i);for(let[o,i]of Object.entries(e.flows)){let a=new V(o,this.host,this.defaultSeed);a.restore(i),this.flowsById.set(o,a)}}},V=class{id;host;local;registered=new Set;rngState;started=!1;flowEnded=!1;closed=!1;currentSceneId=null;stack=[];activeSnippet=null;beatIndex=0;pendingChoice=null;pendingPromptBeat=null;pendingPromptOwnerId=null;selectors=new Map;visitCounts=new Map;sceneBags=new Map;patterResolver={get:e=>this.host.patterSharedNames.has(e)?this.host.patterBag.get(e):this.local.get(e),set:(e,t)=>{this.host.patterSharedNames.has(e)?this.host.registry.set("patter",e,t):this.local.set(e,t)}};sceneResolver={get:e=>{let t=this.currentSceneId;if(t!==null)return this.sceneBagFor(t,e)?.get(e)},set:(e,t)=>{let n=this.currentSceneId;if(n===null)return;let s=this.sceneBagFor(n,e);s&&s.set(e,t)}};evalCtx;ctxRevision=-1;registryQualities;flowLog=[];flowSeq=0;constructor(e,t,n){this.id=e,this.host=t,this.rngState=$(n),this.local=this.newLocal(),this.evalCtx={scopes:{},host:{nextRandom:this.rng,visits:s=>this.visitCounts.get(s)??0,patterVisits:s=>this.host.sharedVisits.get(s)??0},qualities:(s,o)=>this.stagesFor(s,o)}}context(){let e=this.host.registry;if(e.revision!==this.ctxRevision){let t=e.toEvalContext(),n=this.evalCtx.scopes;for(let s of Object.keys(n))delete n[s];Object.assign(n,t.scopes),n.patter=this.patterResolver,n.scene=this.sceneResolver,this.registryQualities=t.qualities,this.ctxRevision=e.revision}return this.evalCtx}stagesFor(e,t){let n=t.toLowerCase(),s=o=>o?.find(i=>i.name.toLowerCase()===n&&i.type==="quality")?.stages;if(e==="patter")return s(this.host.patterSharedDecls)??s(this.host.patterLocalDecls);if(e==="scene"){let o=this.currentSceneId!=null?this.host.bundle.scenes[this.currentSceneId]:void 0;return s(o?.sceneProps)}return this.registryQualities?.(e,t)??s(this.host.bundle.scopeRegistry?.scopes.find(o=>o.token===e)?.declarations)}start(e,t){if(this.host.journal&&!this.host.journal.opened.has(this))throw new Error("a flow can't be started or reset while a checkpoint is open");if(this.releaseBags(!1),this.host.registry.discardParked(D.flow(this.id)),this.mountLocal(),this.selectors.clear(),this.visitCounts.clear(),this.stack=[],this.currentSceneId=null,this.flowEnded=!1,this.activeSnippet=null,this.beatIndex=0,this.pendingChoice=null,this.started=!0,t){let n=this.host.blockIndex.get(t);if(!n)throw new Error(`unknown block: ${t}`);this.enterSceneSetup(n.sceneId),this.stack=[{sceneId:n.sceneId,containerId:t,index:0}],this.enter(t)}else{let n=e??Object.keys(this.host.bundle.scenes)[0],s=n?this.host.bundle.scenes[n]:void 0;if(!s)throw new Error(n?`unknown scene: ${n}`:"no scenes in bundle");this.enterSceneSetup(n);let o=s.blocks[0];o&&(this.stack=[{sceneId:n,containerId:o.id,index:0}],this.enter(o.id))}this.settle()}reset(e,t){this.start(e,t)}goto(e,t){if(this.closed)return!1;if(this.touch(),e==="END")return this.started=!0,this.pendingChoice=null,this.pendingPromptBeat=null,this.pendingPromptOwnerId=null,this.activeSnippet=null,this.beatIndex=0,this.flowEnded=!0,this.stack=[],!0;let n=this.host.sceneGameIdToId.get(e)??(this.host.bundle.scenes[e]?e:void 0);if(n===void 0)return!1;let s;return t!==void 0&&(s=this.host.blockGameIdToId.get(n)?.get(t)??(this.host.blockIndex.get(t)?.sceneId===n?t:void 0),s===void 0)?!1:this.started?(this.pendingChoice=null,this.pendingPromptBeat=null,this.pendingPromptOwnerId=null,this.activeSnippet=null,this.beatIndex=0,this.flowEnded=!1,this.enterTarget(s??n,"jump"),this.settle(),!0):(this.start(n,s),!0)}close(){this.releaseBags(!1),this.closed=!0,this.flowEnded=!0,this.stack=[],this.activeSnippet=null,this.beatIndex=0,this.pendingChoice=null,this.pendingPromptBeat=null,this.pendingPromptOwnerId=null}touch(){let e=this.host.journal;if(!e||e.flows.has(this))return;e.flows.add(this);let{rngState:t,started:n,flowEnded:s,currentSceneId:o,activeSnippet:i,beatIndex:a,pendingChoice:c,pendingPromptBeat:u,pendingPromptOwnerId:f}=this,l=this.stack.map(m=>({...m}));e.undo.push(()=>{Object.assign(this,{rngState:t,started:n,flowEnded:s,currentSceneId:o,activeSnippet:i,beatIndex:a,pendingChoice:c,pendingPromptBeat:u,pendingPromptOwnerId:f,stack:l})})}get isClosed(){return this.closed}get currentScene(){return this.currentSceneId}advance(){if(this.closed)return{type:"end"};if(!this.started)throw new Error("flow has not been started");if(this.touch(),this.pendingPromptBeat){let e=this.pendingPromptBeat;return this.pendingPromptBeat=null,this.pendingPromptOwnerId=null,this.beatResult(e)}return this.settle(),this.flowEnded?{type:"end"}:this.pendingChoice?{type:"choice",groupId:this.pendingChoice.groupId,options:this.pendingChoice.options}:this.activeSnippet?this.beatResult(this.activeSnippet.beats[this.beatIndex++]):(this.flowEnded=!0,{type:"end"})}advanceToStop(){let e=[];for(;;){let t=this.advance();if(t.type==="choice"||t.type==="end")return{played:e,stop:t};e.push(t)}}settle(){let e=0;for(;;){if(++e>1e4)throw new Error("flow did not settle after 10000 transitions - likely a jump cycle with no deliverable content");if(this.flowEnded||this.pendingChoice)return;if(this.activeSnippet){if(this.beatIndex<(this.activeSnippet.beats?.length??0))return;this.runEffects(this.activeSnippet.onExit);let o=this.activeSnippet.jump;this.activeSnippet=null,this.beatIndex=0,this.resolveJump(o);continue}let t=this.stack[this.stack.length-1];if(!t){this.flowEnded=!0;return}t.sceneId!==this.currentSceneId&&(this.currentSceneId=t.sceneId);let n=this.childrenOf(t.containerId);if(!n){this.stack.pop();continue}let s=t.index;for(;t.index<n.length&&!this.eligible(n[t.index]);)t.index++;if(this.host.logEnabled&&t.index!==s&&this.emit({type:"select",group:t.containerId,selector:"run",children:n.slice(s,t.index+1).map((o,i)=>({id:o.id,eligible:s+i===t.index})),picked:n[t.index]?.id??null}),t.index>=n.length){this.stack.pop();continue}this.enterChild(n[t.index++])}}listBags(){let e=[{bag:this.local,pathPrefix:`${this.id}/@patter.`}];for(let[t,n]of this.sceneBags)e.push({bag:n,pathPrefix:`${this.id}/@scene:${t}.`});return e}log(){return this.flowLog}clearLog(){this.flowLog.length=0}emit(e){let t=this.currentSceneId??void 0;this.host.emitEngine(this.id,e,t),this.host.logEnabled&&this.flowLog.push({...e,seq:this.flowSeq++,...t?{scene:t}:{}})}getChoices(){return this.pendingChoice?.options??[]}choose(e){let t=this.pendingChoice;if(!t)throw new Error("no choice is pending");let n=t.options.find(o=>o.id===e);if(!n)throw new Error(`unknown choice option: ${e}`);if(!n.eligible)throw new Error(`choice option is not eligible: ${e}`);this.touch();let s=t.byId.get(e);this.emit({type:"chose",group:t.groupId,option:e}),this.pendingChoice=null,this.pendingPromptBeat=this.host.replayPromptOnChoose?this.promptBeatOf(s)??null:null,this.pendingPromptOwnerId=this.pendingPromptBeat?s.id:null,this.enterChild(s)}isEnded(){return this.flowEnded}getProperty(e){let{scope:t,name:n}=this.splitRef(e);return t==="patter"?this.patterResolver.get(n):t==="scene"?this.sceneResolver.get(n):this.host.registry.get(t,n)}setProperty(e,t){this.writeProperty(e,t,!0)}writeProperty(e,t,n){let{scope:s,name:o}=this.splitRef(e),i=this.host.journal;if(s==="patter"){if(i){let a=this.host.patterSharedNames.has(o),c=a?this.host.patterBag.get(o):this.local.get(o),u=this.local;c!==void 0&&i.undo.push(a?()=>this.host.registry.set("patter",o,c):()=>u.set(o,c))}this.patterResolver.set(o,t)}else if(s==="scene"){if(this.currentSceneId===null)throw new Error(`'${e}': the flow has not entered a scene yet`);if(i){let a=this.sceneBagFor(this.currentSceneId,o),c=a?.get(o);a&&c!==void 0&&i.undo.push(()=>a.set(o,c))}this.sceneResolver.set(o,t)}else{let a=i?this.host.registry.get(s,o):void 0;this.host.registry.set(s,o,t,n?{host:!0}:void 0),i&&a!==void 0&&i.undo.push(()=>this.host.registry.set(s,o,a,{host:!0}))}}snapshot(){return{rngState:this.rngState,visits:Object.fromEntries(this.visitCounts),cursor:{flowEnded:this.flowEnded,currentSceneId:this.currentSceneId,stack:this.stack.map(e=>{let t=this.childrenOf(e.containerId)?.[e.index];return t?{...e,nextId:t.id}:{...e}}),activeSnippetId:this.activeSnippet?.id??null,beatIndex:this.beatIndex,pendingChoice:this.pendingChoice?{groupId:this.pendingChoice.groupId,options:this.pendingChoice.options.map(e=>({...e}))}:null,pendingPromptOwnerId:this.pendingPromptOwnerId,selectors:Me(this.selectors)}}}restore(e){if(this.host.journal)throw new Error("a flow can't be restored while a checkpoint is open");this.restoreCursor(e),this.releaseBags(!0),this.mountLocal();for(let t of new Set([this.currentSceneId,...this.stack.map(n=>n.sceneId)]))t!==null&&this.host.bundle.scenes[t]&&this.ensureSceneBags(t)}restoreCursor(e){this.rngState=$(e.rngState),this.visitCounts=new Map(Object.entries(e.visits??{}));let t=e.cursor;if(this.started=!0,this.flowEnded=t.flowEnded,this.beatIndex=t.beatIndex,this.currentSceneId=t.currentSceneId,this.stack=t.stack.map(n=>{let{nextId:s,...o}=n;if(s!==void 0){let i=this.childrenOf(o.containerId)?.findIndex(a=>a.id===s)??-1;if(i>=0)return{...o,index:i}}return{...o}}),this.activeSnippet=null,t.activeSnippetId!==null){let n=this.host.nodeIndex.get(t.activeSnippetId);n&&n.type==="snippet"&&(this.activeSnippet=n)}if(this.selectors=$e(t.selectors),this.pendingChoice=null,t.pendingChoice!==null){let n=new Map,s=[];for(let o of t.pendingChoice.options){let i=this.host.nodeIndex.get(o.id);i&&(n.set(o.id,i),s.push({...o}))}s.length>0&&(this.pendingChoice={groupId:t.pendingChoice.groupId,options:s,byId:n})}if(this.pendingPromptBeat=null,this.pendingPromptOwnerId=t.pendingPromptOwnerId??null,this.pendingPromptOwnerId){let n=this.host.nodeIndex.get(this.pendingPromptOwnerId);this.pendingPromptBeat=n?this.promptBeatOf(n)??null:null,this.pendingPromptBeat||(this.pendingPromptOwnerId=null)}}enterSceneSetup(e){let t=this.host.bundle.scenes[e];if(!t)throw new Error(`unknown scene: ${e}`);this.currentSceneId=e,this.enter(e),this.seedScene(t),this.runEffects(t.onEntry)}enterChild(e){if(this.enter(e.id),e.type==="snippet"){this.beginSnippet(e);return}let t=e.selector??"run";if(t==="run"){this.stack.push({sceneId:this.currentSceneId,containerId:e.id,index:0});return}if(t==="choice"){this.setupChoice(e);return}let n=this.selectChild(e);n&&this.enterChild(n)}childrenOf(e){let t=this.host.blockById.get(e);if(t)return t.children;let n=this.host.nodeIndex.get(e);if(n&&n.type==="group")return n.children}beginSnippet(e){this.runEffects(e.onEnter),this.activeSnippet=e,this.beatIndex=0}setupChoice(e){let t=[],n=new Map,s=[];for(let i of e.children){if(i.fallback===!0){s.push(i);continue}if(i.sticky!==!0&&(this.visitCounts.get(i.id)??0)>=1)continue;let a=this.eligible(i),c=i.secretUntilEligible===!0;!a&&c||(t.push({id:i.id,prompt:this.promptFor(i),eligible:a,gameData:i.gameData}),n.set(i.id,i))}if(t.length>0){this.emit({type:"choice",group:e.id,options:t.map(i=>({id:i.id,eligible:i.eligible}))}),this.pendingChoice={groupId:e.id,options:t,byId:n};return}let o=s.find(i=>this.eligible(i));if(o){this.enterChild(o);return}this.emit({type:"dry",group:e.id}),this.host.onDryChoice?.(e.id)}resolveJump(e){e&&this.enterTarget(e.to,e.mode==="call"?"call":"jump")}enterTarget(e,t){if(this.emit({type:"jump",to:e,mode:t}),e==="END"){this.flowEnded=!0,this.stack=[];return}let n,s,o=this.host.bundle.scenes[e];if(o){this.enterSceneSetup(e);let a=o.blocks[0];if(!a){t==="jump"&&(this.stack=[]);return}n=e,s=a.id}else{let a=this.host.blockIndex.get(e);if(!a)throw new Error(`jump target not found: ${e}`);a.sceneId!==this.currentSceneId&&this.enterSceneSetup(a.sceneId),n=a.sceneId,s=e}this.enter(s);let i={sceneId:n,containerId:s,index:0};t==="call"?this.stack.push(i):this.stack=[i]}selectChild(e){let t=e.children.map(c=>({id:c.id,eligible:this.eligible(c)})),n=e.children.filter(c=>this.eligible(c)),s=e.options?.order??"sequential",o=e.options?.exhaust??"once",i=c=>(this.emit({type:"select",group:e.id,selector:e.selector??"default",...e.selector==="sequence"?{order:s,exhaust:o}:{},children:t,picked:c?.id??null}),c);if(n.length===0)return i(null);let a=this.selectorState(e);switch(e.selector){case"branch":return i(n[0]);case"sequence":return i(s==="shuffle"?this.pickShuffle(n,o,a):s==="specificity"?this.pickSpecificity(n,o,a):this.pickSequential(n,o,a));default:return null}}pickSequential(e,t,n){let s=e.length,o=n.seq??0;return n.seq=o+1,t==="repeat"?e[o%s]:o<s?e[o]:t==="stick"?e[s-1]:null}pickShuffle(e,t,n){let s=e.length,o=t==="stick",i=()=>(o?e.slice(0,s-1):e).map(l=>l.id);if(n.bag===void 0&&(n.bag=i()),n.bag.length===0){if(t==="once")return null;if(o){let l=e[s-1];return n.last=l.id,l}n.bag=i()}let a=n.bag,c=n.last!==void 0&&a.length>1?a.indexOf(n.last):-1,u=Math.floor(this.rng()*(c>=0?a.length-1:a.length));c>=0&&u>=c&&u++;let f=a[u];return a.splice(u,1),n.last=f,e.find(l=>l.id===f)}pickSpecificity(e,t,n){let s=e;if(t!=="repeat"){n.bag===void 0&&(n.bag=e.map(f=>f.id));let u=new Set(n.bag);if(s=e.filter(f=>u.has(f.id)),s.length===0)return t==="stick"&&n.last!==void 0?e.find(f=>f.id===n.last)??null:null}let o=-1,a=s.map(u=>{let f=this.specScore(u);return f>o&&(o=f),{c:u,s:f}}).filter(u=>u.s===o).map(u=>u.c),c;if(a.length===1)c=a[0];else{let u=n.last!==void 0?a.findIndex(l=>l.id===n.last):-1,f=Math.floor(this.rng()*(u>=0?a.length-1:a.length));u>=0&&f>=u&&f++,c=a[f]}return t!=="repeat"&&(n.bag=n.bag.filter(u=>u!==c.id)),n.last=c.id,c}specScore(e){return e.condition?this.matchedSpec(this.conditionAst(e.condition),!0):0}matchedSpec(e,t){return xe(e,s=>Ve(W(s,this.context(),le)),{want:t})}selectorState(e){let t=e.shared?this.host.sharedSelectors:this.selectors,n=this.host.journal,s;if(n&&(s=e.shared?n.selectors:n.flowSelectors.get(this),s||(s=new Set,n.flowSelectors.set(this,s))),n&&s&&!s.has(e.id)){s.add(e.id);let i=t.get(e.id),a=i?{...i,...i.bag?{bag:[...i.bag]}:{}}:void 0;n.undo.push(()=>{a?t.set(e.id,a):t.delete(e.id)})}let o=t.get(e.id);return o||(o={},t.set(e.id,o)),o}runEffects(e){for(let t of e??[]){let n=this.evalExpr(t.value),s=this.host.logEnabled?this.getProperty(t.target):void 0;this.writeProperty(t.target,n,!1),this.emit({type:"write",target:t.target,value:n,...s!==void 0?{prev:s}:{}})}}eligible(e){return e.condition?Ve(this.evalExpr(e.condition)):!0}evalExpr(e){return W(this.conditionAst(e),this.context(),le)}conditionAst(e){let t=Ae.get(e);return t||(t=A(e.ast),Ae.set(e,t)),t}enter(e){let t=this.visitCounts,n=t.get(e);t.set(e,(n??0)+1);let s=this.host.sharedVisits,o=s.get(e);s.set(e,(o??0)+1),this.host.journal&&this.host.journal.undo.push(()=>{n===void 0?t.delete(e):t.set(e,n),o===void 0?s.delete(e):s.set(e,o)})}rng=()=>{if(this.host.customRng)return this.host.customRng();let e=ie(this.rngState),t=e.next();return this.rngState=e.state(),t};beatResult(e){let t=this.host.tagIndex.get(e.id),n=t&&t.length?{tags:t}:{};switch(e.kind){case"gameEvent":return{type:"gameEvent",id:e.id,gameData:e.gameData,...n};case"text":return{type:"text",id:e.id,text:this.interpolate(this.resolveString(e.id)),gameData:e.gameData,...n};case"line":{let s=this.resolveString(e.id),o=!this.host.captionsOn,a=o&&e.character===this.host.captionCharacter?"":this.captionLine(this.host.bundle.voiced?s:this.interpolate(s)),c=o&&a.length===0;return{type:"line",id:e.id,text:a,character:c?void 0:e.character,characterName:c?void 0:this.resolveCharacterName(e.character),direction:c?void 0:e.direction,gameData:e.gameData,...n}}}}interpolate(e){return Ne(e,t=>this.getProperty(t))}stripCaptions(e){return Pe(e,this.host.captionOpen,this.host.captionClose)}captionLine(e){return this.host.captionsOn?e:this.stripCaptions(e)}promptFor(e){let t=this.promptBeatOf(e);if(!t)return;let n=this.interpolate(this.resolveString(t.id));return t.kind==="line"?{kind:"line",text:this.captionLine(n),character:t.character,characterName:this.resolveCharacterName(t.character),direction:t.direction}:{kind:"text",text:n}}promptBeatOf(e){return e.type==="group"&&e.prompt?e.prompt:((e.type==="snippet"?e:this.firstTextSnippetIn(e.children))?.beats??[]).find(n=>n.kind==="line"||n.kind==="text")}firstTextSnippetIn(e){let t;return F(e,n=>{!t&&n.type==="snippet"&&(n.beats??[]).some(s=>s.kind==="line"||s.kind==="text")&&(t=n)}),t}resolveString(e){if(this.host.emitIds)return e;let t=this.host.strings[e];if(t!==void 0)return t;let n=this.host.defaultStrings[e];return n!==void 0?`<Untranslated: ${e}> ${n}`:e}resolveCharacterName(e){if(e===void 0||this.host.emitIds)return;let t=pe(e);return this.host.strings[t]??this.host.defaultStrings[t]??this.host.castDisplay.get(e)}splitRef(e){return qe(this.host,e)}newLocal(){return new L(this.host.patterLocalDecls,{pathPrefix:"@patter."})}mountLocal(){this.local=this.newLocal();let e=D.flowGlobals(this.id);this.host.registry.mountOwned(e,this.local,{owner:G}),this.registered.add(e)}releaseBags(e){for(let t of this.registered)this.host.registry.remove(t,{keep:e});this.registered.clear(),this.sceneBags.clear()}sceneBagFor(e,t){if(this.host.bundle.scenes[e])return this.ensureSceneBags(e),this.host.sceneSharedNames.get(e)?.has(t.toLowerCase())?this.host.stageBags.get(e):this.sceneBags.get(e)}ensureSceneBags(e){let t=this.host.sceneSharedNames.get(e)??new Set,n=this.host.bundle.scenes[e]?.sceneProps??[],s=this.host.journal;if(!this.sceneBags.has(e)){let o=new L(n.filter(a=>!t.has(a.name.toLowerCase())),{pathPrefix:"@scene."}),i=D.flowScene(this.id,e);this.host.registry.mountOwned(i,o,{owner:G}),this.registered.add(i),this.sceneBags.set(e,o),s&&s.undo.push(()=>{this.sceneBags.get(e)===o&&(this.host.registry.remove(i),this.registered.delete(i),this.sceneBags.delete(e))})}if(!this.host.stageBags.has(e)){let o=new L(n.filter(i=>t.has(i.name.toLowerCase())),{pathPrefix:"@scene."});this.host.registry.mountOwned(D.stage(e),o,{owner:G}),this.host.stageBags.set(e,o),s&&s.undo.push(()=>{this.host.stageBags.get(e)===o&&(this.host.registry.remove(D.stage(e)),this.host.stageBags.delete(e))})}}seedScene(e){let t=this.host.sceneSharedNames.get(e.id)??new Set;this.ensureSceneBags(e.id);for(let n of e.sceneProps??[]){if(!n.temporary)continue;let s=n.name.toLowerCase(),o=t.has(s)?this.host.stageBags.get(e.id):this.sceneBags.get(e.id);if(!o)continue;let i=this.host.journal?o.get(s):void 0;i!==void 0&&this.host.journal.undo.push(()=>o.set(s,i)),o.set(s,q(n))}}};function Fe(r,e){F(r,t=>{if(t.type==="group"){t.prompt?.kind==="line"&&t.prompt.character&&e.add(t.prompt.character);return}for(let n of t.beats??[])n.kind==="line"&&n.character&&e.add(n.character)})}function Te(r){return r&&Object.keys(r).length?{gameData:r}:{}}function Me(r){let e={};for(let[t,n]of r){let s={};n.seq!==void 0&&(s.seq=n.seq),n.bag&&(s.bag=[...n.bag]),n.last!==void 0&&(s.last=n.last),e[t]=s}return e}function $e(r){let e=new Map;for(let[t,n]of Object.entries(r??{})){let s={};n.seq!==void 0&&(s.seq=n.seq),n.bag&&(s.bag=[...n.bag]),n.last!==void 0&&(s.last=n.last),e.set(t,s)}return e}function Ge(r){return{name:r.name,type:r.type,values:r.values,stages:r.stages,default:r.default}}function He(r){return{name:r.name,type:r.type,values:r.values,stages:r.stages,default:r.default,writable:r.writable}}function xt(r,e){let t=He(r),n=r.writable??e;return n===void 0?t:{...t,writable:n}}function qe(r,e){r.refSplitRevision!==r.registry.revision&&(r.refSplitCache.clear(),r.refSplitRevision=r.registry.revision);let t=r.refSplitCache.get(e);return t||(t=Be(e,n=>n==="scene"||r.registry.has(n)||(r.bundle.externalScopes?.includes(n)??!1)),r.refSplitCache.set(e,t)),t}function kt(r){let e={};r.shared?.patter&&(e.patter=r.shared.patter);for(let[t,n]of Object.entries(r.stageBags??{}))e[D.stage(t)]=n;for(let[t,n]of Object.entries(r.flows??{})){n.scopes?.patter&&(e[D.flowGlobals(t)]=n.scopes.patter);for(let[s,o]of Object.entries(n.sceneBags??{}))e[D.flowScene(t,s)]=o}return e}function Ve(r){return typeof r=="boolean"?r:typeof r=="number"?r!==0:typeof r=="string"?r!=="":r.length>0}var Et=(r,e)=>r.shared??e;function ge(r,e){return{name:r.name,type:r.type,hasDefault:r.default!==void 0,...r.default!==void 0?{default:r.default}:{},shared:Et(r,e)}}function Ct(r){return{name:r.name,type:r.type,hasDefault:r.default!==void 0,...r.values?{values:[...r.values]}:{},...r.purpose?{purpose:r.purpose}:{}}}function It(r,e){e.blocks++;let t=[...r.children];for(;t.length;){let n=t.pop();if(n.type==="group"){e.groups++,n.prompt&&e.prompts++,t.push(...n.children);continue}e.snippets++;for(let s of n.beats??[])e.beats++,s.kind==="gameEvent"&&e.gameEvents++}}function te(r){let e={scenes:0,blocks:0,groups:0,snippets:0,beats:0,prompts:0,gameEvents:0,cast:r.cast?.length??0},t=[],n=[];for(let i of Object.values(r.scenes)){e.scenes++;let a=C(i);t.push({gameId:a,name:i.name,blocks:i.blocks.map(c=>({gameId:C(c),name:c.name}))});for(let c of i.blocks)It(c,e);i.sceneProps?.length&&n.push({gameId:a,properties:i.sceneProps.map(c=>ge(c,!1))})}let s=(r.scopeRegistry?.scopes??[]).map(i=>({token:i.token,writable:i.writable??!0,opaque:i.declarations===void 0,properties:(i.declarations??[]).map(a=>ge(a,!0))})),o=Object.entries(r.gameDataFields??{}).filter(([,i])=>(i?.length??0)>0).map(([i,a])=>({kind:i,fields:(a??[]).map(Ct)}));return{identity:{schema:r.schema,project:r.content.project,...r.content.version!==void 0?{version:r.content.version}:{},...r.content.hash!==void 0?{hash:r.content.hash}:{},...r.content.structureHash!==void 0?{structureHash:r.content.structureHash}:{},voiced:r.voiced,defaultLocale:r.locales.default,locales:[...r.locales.included],localisation:r.localisation?.mode??"embedded",sourceDebug:r.localisation?.sourceDebug??!1},addresses:t,hostScopes:s,properties:{patter:(r.properties??[]).map(i=>ge(i,!0)),scene:n},gameData:o,counts:e}}function _e(r,e){return r.gameDataFields?.[e]??[]}function fe(r,e,t){return e&&Object.prototype.hasOwnProperty.call(e,t)?e[t]:r.find(n=>n.name===t)?.default}function Ue(r,e){let t={};for(let n of r){let s=fe(r,e,n.name);s!==void 0&&(t[n.name]=s)}for(let[n,s]of Object.entries(e??{}))n in t||(t[n]=s);return t}function he(r){return{schema:T,save:r.saveGame()}}function me(r,e){if(!e||e.schema!==T||!e.save)throw new Error(`loadState: not a ${T} envelope`);r.loadGame(e.save)}function ne(r){return JSON.stringify(he(r))}function re(r,e){me(r,JSON.parse(e))}function Je(r,e){return r.getProperty(e)}function We(r,e,t){r.setProperty(e,t)}function ze(r,e){for(let[t,n]of Object.entries(e))r.setProperty(t,n)}function Se(r){let e={};for(let t of Ke(r)){let n=t.pathPrefix??t.bag.pathPrefix;for(let[s,o]of Object.entries(t.bag.save()))e[`${n}${s}`]=o}return Object.assign(e,Ye(r)),e}function Ke(r){return[...r.listBags(),...r.flows().flatMap(e=>e.listBags())]}function Dt(r){switch(r.type){case"line":return`line ${r.character??"?"}: ${JSON.stringify(r.text)}${ye(r.gameData)}`;case"text":return`text: ${JSON.stringify(r.text)}${ye(r.gameData)}`;case"gameEvent":return`game event ${r.id}${ye(r.gameData)}`;case"choice":return`choice (${r.options.length} option${r.options.length===1?"":"s"})`;case"end":return"end"}}var ye=r=>r?` gameData=${JSON.stringify(r)}`:"";function Ye(r){let e=r.saveGame(),t={};for(let[n,s]of Object.entries(e.sharedVisits))t[`visit:${n}`]=s;for(let[n,s]of Object.entries(e.flows))for(let[o,i]of Object.entries(s.visits))t[`${n}/visit:${o}`]=i;return t}function Qe(r,e={}){let t=e.label?`[${e.label}] `:"",n=ae({mounts:()=>Ke(r),extra:()=>Ye(r)},{sink:e.sink,label:t});return{snapshot:()=>Se(r),capture:()=>n.capture(),dispose:()=>n.dispose(),logStep(s){(e.sink??(o=>console.log(o)))(`${t}${Dt(s)}`)}}}function Xe(r){let e=r.url??"ws://127.0.0.1:4471",t=r.WebSocket??globalThis.WebSocket,n=new Set,s=[],o=null,i=!1,a=r.build,c=()=>{if(!(!o||o.readyState!==1)){for(let l of s)try{o.send(l)}catch{}s=[]}},u=l=>{i||(s.push(JSON.stringify(l)),c())};if(!t)return{flowOpened(){},observe(){},flowClosed(){},setBuild(){},close(){i=!0}};let f=()=>{let l=JSON.stringify({t:"hello",v:1,build:a,project:r.project,flows:[...n]});try{o?.send(l)}catch{}};try{o=new t(e),o.addEventListener("open",()=>{f(),c()}),o.addEventListener("message",l=>{if(!(!r.onBundle||typeof l.data!="string"))try{let m=JSON.parse(l.data);m.t==="bundle"&&typeof m.build=="string"&&typeof m.data=="string"&&r.onBundle({build:m.build,data:m.data})}catch{}}),o.addEventListener("error",()=>{}),o.addEventListener("close",()=>{o=null})}catch{o=null}return{flowOpened(l){n.add(l),u({t:"flowOpen",flow:l})},flowClosed(l){n.delete(l),u({t:"flowClose",flow:l})},observe(l,m,g,h,d){n.has(l)||(n.add(l),u({t:"flowOpen",flow:l})),u({t:"frame",flow:l,sceneId:m,beatId:g,type:h,choiceId:d})},setBuild(l){i||l===a||(a=l,o&&o.readyState===1&&f())},close(){i=!0,s=[];try{o?.close()}catch{}o=null}}}function Ze(r,e,t){let n=JSON.parse(t);return e.content.structureHash!==void 0&&e.content.structureHash===n.content.structureHash?(r.replaceStrings(n),{engine:r,bundle:n,kind:"text"}):{engine:r.hotSwap(n),bundle:n,kind:"structure"}}var et="pp-inspector-style",Rt=`
|
|
3
3
|
.pp-insp{font:13px/1.4 ui-sans-serif,system-ui,sans-serif;color:#15201e;background:#f4efe6;border:1px solid #cfc7b8;border-radius:10px;padding:.6rem .7rem;max-width:22rem;box-shadow:0 6px 20px rgba(21,32,30,.12)}
|
|
4
4
|
.pp-insp h4{margin:0 0 .4rem;font:600 .72rem/1 ui-sans-serif,system-ui,sans-serif;letter-spacing:.08em;text-transform:uppercase;color:#5c6b62}
|
|
5
5
|
.pp-insp-empty{color:#8a9691;font-style:italic}
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
.pp-insp-ctl input[type=text],.pp-insp-ctl input[type=number],.pp-insp-ctl select{width:100%;box-sizing:border-box;font:inherit;padding:.15rem .3rem;border:1px solid #cfc7b8;border-radius:6px;background:#fff;color:inherit}
|
|
12
12
|
.pp-insp-reset{flex:0 0 auto;border:1px solid #cfc7b8;background:#fff;border-radius:6px;cursor:pointer;color:#5c6b62;width:1.6rem;height:1.6rem;line-height:1;padding:0}
|
|
13
13
|
.pp-insp-reset:disabled{opacity:.35;cursor:default}
|
|
14
|
-
`;function
|
|
14
|
+
`;function Ot(r){if(r.getElementById(et))return;let e=r.createElement("style");e.id=et,e.textContent=Rt,(r.head??r.documentElement).appendChild(e)}function Bt(r,e){return Array.isArray(r)&&Array.isArray(e)?r.length===e.length&&r.every((t,n)=>t===e[n]):r===e}function tt(r,e={}){let t=e.container?.ownerDocument??document;Ot(t);let n=t.createElement("div");n.className="pp-insp";let s=t.createElement("h4");s.textContent=e.title??"Runtime state";let o=t.createElement("div"),i=t.createElement("div");i.className="pp-insp-io";let a=t.createElement("button");a.type="button",a.textContent="Save state\u2026",a.addEventListener("click",()=>{let d=new Blob([ne(r)],{type:"application/json"}),v=t.createElement("a");v.href=URL.createObjectURL(d),v.download="save.patterstate",v.click(),URL.revokeObjectURL(v.href)});let c=t.createElement("button");c.type="button",c.textContent="Load state\u2026",c.addEventListener("click",()=>{let d=t.createElement("input");d.type="file",d.accept=".patterstate,application/json",d.addEventListener("change",()=>{let v=d.files?.[0];v&&v.text().then(k=>{try{re(r,k),m()}catch(E){console.error("Load state failed:",E instanceof Error?E.message:E)}})}),d.click()}),i.append(a,c),n.append(s,i,o);let u=[],f=d=>{let v=t.createElement("div");v.className="pp-insp-row";let k=t.createElement("span");k.className="pp-insp-ref",k.textContent=d.path,k.title=d.path;let E=t.createElement("div");E.className="pp-insp-ctl";let O=t.createElement("button");O.className="pp-insp-reset",O.type="button",O.textContent="\u21BA",O.title="Reset to default",v.append(k,E,O),o.appendChild(v);let I,B=p=>{r.setProperty(d.path,p),S()},N=p=>t.activeElement===p;function S(){O.disabled=Bt(r.getProperty(d.path),d.default)}if(O.addEventListener("click",()=>{r.setProperty(d.path,d.default),I(),S()}),d.type==="boolean"){let p=t.createElement("input");p.type="checkbox",p.addEventListener("change",()=>B(p.checked)),E.appendChild(p),I=()=>{N(p)||(p.checked=r.getProperty(d.path)===!0)}}else if(d.type==="number"){let p=t.createElement("input");p.type="number",p.addEventListener("change",()=>B(Number(p.value))),E.appendChild(p),I=()=>{N(p)||(p.value=String(r.getProperty(d.path)??""))}}else if(d.type==="enum"||d.type==="quality"){let p=t.createElement("select");for(let w of(d.type==="quality"?d.stages:d.values)??[]){let x=t.createElement("option");x.value=w,x.textContent=w,p.appendChild(x)}p.addEventListener("change",()=>B(p.value)),E.appendChild(p),I=()=>{N(p)||(p.value=String(r.getProperty(d.path)??""))}}else if(d.type==="flags"){let p=t.createElement("input");p.type="text",p.placeholder="comma, separated, flags",p.addEventListener("change",()=>B(p.value.split(",").map(w=>w.trim()).filter(w=>w.length>0))),E.appendChild(p),I=()=>{if(!N(p)){let w=r.getProperty(d.path);p.value=Array.isArray(w)?w.join(", "):""}}}else{let p=t.createElement("input");p.type="text",p.addEventListener("change",()=>B(p.value)),E.appendChild(p),I=()=>{N(p)||(p.value=String(r.getProperty(d.path)??""))}}I(),S(),u.push(()=>{I(),S()})},l=r.listProperties();if(l.length===0){let d=t.createElement("div");d.className="pp-insp-empty",d.textContent="No @patter properties.",o.appendChild(d)}else for(let d of l)f(d);let m=()=>{for(let d of u)d()};e.container?.appendChild(n);let g=e.pollMs??250,h;return g>0&&(h=setInterval(m,g)),{el:n,refresh:m,destroy(){h!==void 0&&clearInterval(h),n.remove()}}}var nt="pp-bundle-style",Pt=`
|
|
15
15
|
.pp-bundle{font:13px/1.4 ui-sans-serif,system-ui,sans-serif;color:#15201e;background:#f4efe6;border:1px solid #cfc7b8;border-radius:10px;padding:.6rem .7rem;max-width:26rem;box-shadow:0 6px 20px rgba(21,32,30,.12)}
|
|
16
16
|
.pp-bundle h4{margin:0 0 .4rem;font:600 .72rem/1 ui-sans-serif,system-ui,sans-serif;letter-spacing:.08em;text-transform:uppercase;color:#5c6b62}
|
|
17
17
|
.pp-bundle details{border-top:1px solid #e3dccf;padding:.3rem 0}
|
|
@@ -28,5 +28,5 @@
|
|
|
28
28
|
.pp-bundle-empty{color:#8a9691;font-style:italic;margin-left:1rem}
|
|
29
29
|
.pp-bundle-warn{color:#8a3a2f;font-weight:600}
|
|
30
30
|
.pp-bundle-tag{font-size:.7rem;color:#5c6b62;border:1px solid #cfc7b8;border-radius:5px;padding:0 .25rem;margin-left:.3rem}
|
|
31
|
-
`;function
|
|
31
|
+
`;function Nt(r){if(r.getElementById(nt))return;let e=r.createElement("style");e.id=nt,e.textContent=Pt,(r.head??r.documentElement).appendChild(e)}var b=(r,e,t,n)=>{let s=r.createElement(e);return t&&(s.className=t),n!==void 0&&(s.textContent=n),s};function R(r,e,t,n="pp-bundle-val"){let s=b(r,"div","pp-bundle-row");return s.append(b(r,"span","pp-bundle-key",e),b(r,"span",n,t)),s}function be(r,e){let t=b(r,"div","pp-bundle-row");t.append(b(r,"span","pp-bundle-key pp-bundle-addr",e.name));let n=b(r,"span","pp-bundle-val",e.type);return e.hasDefault||n.append(b(r,"span","pp-bundle-tag","no default")),t.append(n),t}function M(r,e,t,n,s){let o=r.createElement("details");o.dataset.section=e,o.open=s;let i=r.createElement("summary");return i.textContent=t,n!==null&&i.append(b(r,"span","pp-bundle-count",` ${n}`)),o.append(i),o}function rt(r,e={}){let t=e.container?.ownerDocument??document;Nt(t);let n=te(r),s=new Set(e.open??["identity","addresses"]),o=b(t,"div","pp-bundle");o.append(b(t,"h4",void 0,e.title??"Bundle"));let i=M(t,"identity",n.identity.project||"(unnamed project)",null,s.has("identity"));n.identity.version&&i.append(R(t,"version",n.identity.version)),i.append(R(t,"schema",n.identity.schema)),i.append(R(t,"locales",`${n.identity.defaultLocale}${n.identity.locales.length>1?` (+${n.identity.locales.length-1})`:""}`)),i.append(R(t,"strings",n.identity.localisation)),n.identity.voiced&&i.append(R(t,"voiced","yes")),n.identity.hash&&i.append(R(t,"hash",n.identity.hash)),n.identity.structureHash&&i.append(R(t,"structure",n.identity.structureHash)),n.identity.sourceDebug&&i.append(R(t,"build","SOURCE DEBUG - not shippable","pp-bundle-val pp-bundle-warn")),o.append(i);let a=M(t,"addresses","Addresses",n.addresses.length,s.has("addresses"));n.addresses.length||a.append(b(t,"div","pp-bundle-empty","no scenes"));for(let g of n.addresses){let h=b(t,"div","pp-bundle-row");h.append(b(t,"span","pp-bundle-key pp-bundle-addr",g.gameId),b(t,"span","pp-bundle-val",g.name)),a.append(h);for(let d of g.blocks){let v=b(t,"div","pp-bundle-row pp-bundle-sub");v.append(b(t,"span","pp-bundle-key pp-bundle-addr",d.gameId),b(t,"span","pp-bundle-val",d.name)),a.append(v)}}o.append(a);let c=n.hostScopes.reduce((g,h)=>g+h.properties.length,0),u=M(t,"hostScopes","Host properties",c,s.has("hostScopes"));n.hostScopes.length||u.append(b(t,"div","pp-bundle-empty","the game supplies nothing"));for(let g of n.hostScopes){let h=b(t,"div","pp-bundle-row");h.append(b(t,"span","pp-bundle-key pp-bundle-addr",`@${g.token}`));let d=b(t,"span","pp-bundle-val",g.opaque?"any name, unchecked":`${g.properties.length} declared`);g.writable||d.append(b(t,"span","pp-bundle-tag","read-only")),h.append(d),u.append(h);for(let v of g.properties){let k=be(t,v);k.classList.add("pp-bundle-sub"),u.append(k)}}o.append(u);let f=n.properties.patter.length+n.properties.scene.reduce((g,h)=>g+h.properties.length,0),l=M(t,"properties","Story properties",f,s.has("properties"));f||l.append(b(t,"div","pp-bundle-empty","none declared"));for(let g of n.properties.patter)l.append(be(t,g));for(let g of n.properties.scene){l.append(R(t,"@scene",g.gameId,"pp-bundle-val pp-bundle-addr"));for(let h of g.properties){let d=be(t,h);d.classList.add("pp-bundle-sub"),l.append(d)}}if(o.append(l),n.gameData.length){let g=M(t,"gameData","Game data",n.gameData.reduce((h,d)=>h+d.fields.length,0),s.has("gameData"));for(let h of n.gameData){g.append(R(t,"on",h.kind));for(let d of h.fields){let v=b(t,"div","pp-bundle-row pp-bundle-sub");v.append(b(t,"span","pp-bundle-key pp-bundle-addr",d.name),b(t,"span","pp-bundle-val",d.type)),g.append(v)}}o.append(g)}let m=M(t,"counts","Counts",null,s.has("counts"));for(let[g,h]of Object.entries(n.counts))m.append(R(t,g,String(h)));return o.append(m),e.container?.append(o),{el:o,description:n,destroy(){o.remove()}}}function st(r,e){let n=JSON.parse(r).clips??{},s=e.replace(/[/\\]+$/,"");return{resolve(o){let i=n[o];return!i||!i.file?null:s?`${s}/${i.file}`:i.file}}}return pt(Lt);})();
|
|
32
32
|
//# sourceMappingURL=patterplay.min.js.map
|