octiqflow-linux-x64 0.3.26 → 0.3.28
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/bin/octiq-server +0 -0
- package/bin/v2/assets/IslandPage-Cvcho1fQ.js +19 -0
- package/bin/v2/assets/IslandPage-Cvcho1fQ.js.br +0 -0
- package/bin/v2/assets/IslandPage-Cvcho1fQ.js.gz +0 -0
- package/bin/v2/assets/{index-D22ujAMP.js → index-B7UxlWSj.js} +1 -1
- package/bin/v2/assets/index-B7UxlWSj.js.br +0 -0
- package/bin/v2/assets/{index-D22ujAMP.js.gz → index-B7UxlWSj.js.gz} +0 -0
- package/bin/v2/assets/{index-CPT_YpjT.js → index-BTcEhwL0.js} +1 -1
- package/bin/v2/assets/index-BTcEhwL0.js.br +0 -0
- package/bin/v2/assets/index-BTcEhwL0.js.gz +0 -0
- package/bin/v2/assets/{index-C7kRVW7q.js → index-Bgpcl8no.js} +1 -1
- package/bin/v2/assets/index-Bgpcl8no.js.br +0 -0
- package/bin/v2/assets/index-Bgpcl8no.js.gz +0 -0
- package/bin/v2/assets/{index-DQtP_CC6.js → index-BvuLK453.js} +1 -1
- package/bin/v2/assets/index-BvuLK453.js.br +0 -0
- package/bin/v2/assets/index-BvuLK453.js.gz +0 -0
- package/bin/v2/assets/{index-BijqmrIf.js → index-CL_gihHg.js} +1 -1
- package/bin/v2/assets/index-CL_gihHg.js.br +0 -0
- package/bin/v2/assets/index-CL_gihHg.js.gz +0 -0
- package/bin/v2/assets/{index-E_k_kYir.js → index-CPtE-P3-.js} +1 -1
- package/bin/v2/assets/index-CPtE-P3-.js.br +0 -0
- package/bin/v2/assets/index-CPtE-P3-.js.gz +0 -0
- package/bin/v2/assets/{index-CKmCA1gi.js → index-CS2AxWn8.js} +149 -149
- package/bin/v2/assets/index-CS2AxWn8.js.br +0 -0
- package/bin/v2/assets/index-CS2AxWn8.js.gz +0 -0
- package/bin/v2/assets/{index-jZgYW6KS.js → index-Co0vjxPD.js} +1 -1
- package/bin/v2/assets/index-Co0vjxPD.js.br +0 -0
- package/bin/v2/assets/index-Co0vjxPD.js.gz +0 -0
- package/bin/v2/assets/index-DpGkwj-g.css +1 -0
- package/bin/v2/assets/index-DpGkwj-g.css.br +0 -0
- package/bin/v2/assets/index-DpGkwj-g.css.gz +0 -0
- package/bin/v2/assets/{index-YNnmRrtC.js → index-DpkB3iQf.js} +1 -1
- package/bin/v2/assets/index-DpkB3iQf.js.br +0 -0
- package/bin/v2/assets/index-DpkB3iQf.js.gz +0 -0
- package/bin/v2/assets/{index-DfreU7M_.js → index-T8sCdMRf.js} +1 -1
- package/bin/v2/assets/index-T8sCdMRf.js.br +0 -0
- package/bin/v2/assets/index-T8sCdMRf.js.gz +0 -0
- package/bin/v2/assets/{index-DQNuXjur.js → index-pwKWZXjk.js} +1 -1
- package/bin/v2/assets/index-pwKWZXjk.js.br +0 -0
- package/bin/v2/assets/index-pwKWZXjk.js.gz +0 -0
- package/bin/v2/assets/{index-DAwl9HGY.js → index-s590-ZtY.js} +1 -1
- package/bin/v2/assets/index-s590-ZtY.js.br +0 -0
- package/bin/v2/assets/index-s590-ZtY.js.gz +0 -0
- package/bin/v2/assets/portrait-CfI5HYbj.js +1 -0
- package/bin/v2/assets/portrait-CfI5HYbj.js.br +0 -0
- package/bin/v2/assets/portrait-CfI5HYbj.js.gz +0 -0
- package/bin/v2/assets/{robot-DgoHoWJ_.js → robot-CzDIvswk.js} +1 -1
- package/bin/v2/assets/robot-CzDIvswk.js.br +0 -0
- package/bin/v2/assets/{robot-DgoHoWJ_.js.gz → robot-CzDIvswk.js.gz} +0 -0
- package/bin/v2/index.html +2 -2
- package/package.json +1 -1
- package/bin/v2/assets/IslandPage-B8zXknRt.js +0 -16
- package/bin/v2/assets/IslandPage-B8zXknRt.js.br +0 -0
- package/bin/v2/assets/IslandPage-B8zXknRt.js.gz +0 -0
- package/bin/v2/assets/index-BN4tJeS6.css +0 -1
- package/bin/v2/assets/index-BN4tJeS6.css.br +0 -0
- package/bin/v2/assets/index-BN4tJeS6.css.gz +0 -0
- package/bin/v2/assets/index-BijqmrIf.js.br +0 -0
- package/bin/v2/assets/index-BijqmrIf.js.gz +0 -0
- package/bin/v2/assets/index-C7kRVW7q.js.br +0 -0
- package/bin/v2/assets/index-C7kRVW7q.js.gz +0 -0
- package/bin/v2/assets/index-CKmCA1gi.js.br +0 -0
- package/bin/v2/assets/index-CKmCA1gi.js.gz +0 -0
- package/bin/v2/assets/index-CPT_YpjT.js.br +0 -0
- package/bin/v2/assets/index-CPT_YpjT.js.gz +0 -0
- package/bin/v2/assets/index-D22ujAMP.js.br +0 -0
- package/bin/v2/assets/index-DAwl9HGY.js.br +0 -0
- package/bin/v2/assets/index-DAwl9HGY.js.gz +0 -0
- package/bin/v2/assets/index-DQNuXjur.js.br +0 -0
- package/bin/v2/assets/index-DQNuXjur.js.gz +0 -0
- package/bin/v2/assets/index-DQtP_CC6.js.br +0 -0
- package/bin/v2/assets/index-DQtP_CC6.js.gz +0 -0
- package/bin/v2/assets/index-DfreU7M_.js.br +0 -0
- package/bin/v2/assets/index-DfreU7M_.js.gz +0 -0
- package/bin/v2/assets/index-E_k_kYir.js.br +0 -0
- package/bin/v2/assets/index-E_k_kYir.js.gz +0 -0
- package/bin/v2/assets/index-YNnmRrtC.js.br +0 -0
- package/bin/v2/assets/index-YNnmRrtC.js.gz +0 -0
- package/bin/v2/assets/index-jZgYW6KS.js.br +0 -0
- package/bin/v2/assets/index-jZgYW6KS.js.gz +0 -0
- package/bin/v2/assets/portrait-BuBLkdle.js +0 -1
- package/bin/v2/assets/portrait-BuBLkdle.js.br +0 -0
- package/bin/v2/assets/portrait-BuBLkdle.js.gz +0 -0
- package/bin/v2/assets/robot-DgoHoWJ_.js.br +0 -0
package/bin/octiq-server
CHANGED
|
Binary file
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import{r as I,b as qe,a as Mt,T as Re,c as Ve,d as Is,p as Ce,e as ce,C as Pe,o as Lt,f as gs,P as wt,g as Os,S as Ht,h as Ws,u as $s,i as Us,j as Bs,k as Fs,w as Et,l as x,W as Gs,A as Ks}from"./index-CS2AxWn8.js";import{G as he,B as ht,M as ze,a as O,c as ys,p as xs,C as Nt,b as ee,d as ct,A as It,S as lt,e as ws,R as zt,f as Ys,V as oe,g as Je,T as Ze,Q as qt,h as Zt,i as Me,j as Hs,P as qs,k as Zs,l as bs,m as H,N as Xs,n as Ot,o as Wt,q as Qs,r as Dt,s as Xe,t as Xt,I as Vs,u as Qt,D as Rt,v as ks,w as bt,x as Js,y as Ms,F as ei,z as ti,E as si,W as ii,H as ni,J as ai,K as oi,L as ri,O as ci,U as li,X as hi,Y as di,Z as ui,_ as Vt,$ as pi,a0 as fi,a1 as Jt,a2 as At,a3 as mi}from"./robot-CzDIvswk.js";const gi=o=>String(o?.message??o);function yi(o){const[e,t]=I.useState(null),[s,i]=I.useState(null),[n,a]=I.useState(null),r=I.useRef(null),l=I.useRef(0),h=I.useCallback(()=>{const p=++l.current;qe.invoke("island_get").then(c=>{if(p!==l.current||!c?.island)return;const d=c.island;r.current&&r.current.rev>d.rev||(r.current=d,t(d),i(null))}).catch(c=>{p===l.current&&i(gi(c))})},[]);I.useEffect(()=>{if(!o)return;h();const p=qe.on("island-changed",d=>{d&&(r.current&&d.rev<=r.current.rev||(a(d),h()))}),c=qe.on("chat-status",d=>{d?.key.startsWith("chat:island-wish-")&&h()});return()=>{p(),c()}},[o,h]);const m=I.useCallback(async(p,c={})=>{await qe.invoke(p,c),h()},[h]);return{island:e,error:s,change:n,reload:h,dismissWish:p=>m("island_wish_dismiss",{id:p}),grantWish:p=>m("island_wish_start",{id:p}),rollWish:()=>m("island_wish_roll"),inviteBot:()=>m("island_bot_invite"),farewell:p=>m("island_bot_farewell",{id:p}),setPace:p=>m("island_settings_set",{wishPace:p}),setBuildPace:p=>m("island_build_pace",{pace:p})}}function xi(o,e=Date.now()){const t=new Map;for(const s of o){const i=a=>s.activities.find(r=>r.state===a)?.title,n=s.state==="working"?{state:"working",label:i("working")}:s.state==="needs_you"?{state:"needs_you",label:i("needs_you")}:s.state==="failed"?{state:"failed",label:i("failed")}:{state:"free",...s.recent?{idleFor:Math.max(0,Math.round((e-s.recent.at)/6e4))}:{}};t.set(`agent:${s.id}`,n)}return t}function wi(o,e=Date.now()){const t=Math.max(0,Math.round((e-o)/6e4));if(t<1)return"just now";if(t<60)return`${t} min ago`;const s=Math.round(t/60);return s<24?`${s} h ago`:`${Math.round(s/24)} d ago`}function zs(o,e){const t=new Map;for(const c of[...e].sort((d,g)=>d.key.localeCompare(g.key))){const d=c.agent?.teamId?`team:${c.agent.teamId}`:"general";t.set(d,[...t.get(d)??[],c])}t.has("general")||t.set("general",[]);const s=[],i=o.assets.filter(c=>c.kind==="accessory"),n=[],a=[],r=new Map,l=o.plots.filter(c=>c.owner.kind==="home"&&c.owner.id.startsWith("public:")||o.placed.some(d=>d.plot===c.id&&o.assets.some(g=>g.id===d.asset&&g.kind==="building"&&g.name!=="Workshop"))),h=[];for(let c=1;h.length<t.size+l.length;c++)h.push(...Mt(c).filter(([d,g])=>(d!==-1||g!==0)&&(d!==0||g!==-1)));const m=(c,d,g)=>({shape:"box",size:c,at:d,color:g});for(const[c,[d,g]]of[...t].sort(([j],[b])=>j.localeCompare(b)).entries()){const[j,b]=h[c],k=Ve(j,b),f=`office:${d}`,E=d==="general"?"Agent Tower":`${g[0].agent?.teamName??"Team"} Office`,z={id:f,owner:{kind:"home",id:d},ring:Math.max(Math.abs(j),Math.abs(b),Math.abs(j+b)),slot:c,q:j,r:b,...k,facing:Math.atan2(-k.x,-k.z)*180/Math.PI,radius:Re,claimedAt:0,members:g.map(A=>A.owner.id),officeName:E};s.push(z);const _=Math.max(d==="general"?3:1,Math.ceil(g.length/6)),L=[];for(let A=0;A<_;A++){const S=A*2.3;L.push(m([8,.08,6],[0,S+.04,-.7],"#d6dce5")),L.push({...m([8,2,.14],[0,S+1,-3.6],"#b6c9dd"),finish:"glass"}),L.push({...m([.16,2.3,6],[-3.95,S+1.15,-.7],"#7a94b1"),finish:"glass"}),L.push({...m([.16,2.3,6],[3.95,S+1.15,-.7],"#7a94b1"),finish:"glass"});for(const N of[-2.7,0,2.7])L.push({...m([1.5,1,.025],[N,S+1.2,-3.51],"#b5e5fa"),finish:"glass"})}i.push({id:f,rev:_,name:E,kind:"building",parts:L,by:{name:"Island offices"},madeAt:0,updatedAt:0}),n.push({id:f,asset:f,plot:f,x:0,z:0,y:0,turn:0});for(const[A,S]of g.entries()){a.push({...S,plot:z});const N=`office-desk:${S.key}`,$=(A%3-1)*2.4,W=Math.floor(A%6/3)*2.5-2.4,X=Math.floor(A/6)*2.3;i.push({id:N,rev:Number.parseInt(S.look.trim.slice(1)+S.look.glow.slice(1),16),name:`${S.name}'s desk`,kind:"furniture",use:"desk",spot:{at:[0,0,.65],face:180},parts:[m([1.3,.08,.7],[0,.6,0],"#cfa783"),m([.12,.6,.12],[-.5,.3,0],S.look.trim),m([.12,.6,.12],[.5,.3,0],S.look.trim),m([.65,.42,.08],[0,.88,-.18],"#26354a"),{...m([.55,.32,.02],[0,.88,-.13],S.look.glow),finish:"glow"}],by:{name:S.name,agentId:S.owner.id},madeAt:0,updatedAt:0}),n.push({id:N,asset:N,plot:f,x:$,z:W,y:X,turn:0}),r.set(N,S.key);const Y=o.placed.filter(F=>F.plot===S.plot?.id).filter(F=>{const V=o.assets.find(ve=>ve.id===F.asset);return V&&V.kind!=="building"&&V.name!=="Workshop"&&V.name!=="Desk"&&V.use!=="bed"});for(const[F,V]of Y.entries()){const ve=o.assets.find(fe=>fe.id===V.asset);i.some(fe=>fe.id===ve.id)||i.push(ve);const ne=(A+F/Math.max(1,Y.length))/g.length*Math.PI*2;n.push({...V,plot:f,x:Math.sin(ne)*4.8,z:Math.cos(ne)*4.8,y:0})}}}for(const[c,d]of l.entries()){const[g,j]=h[t.size+c],b=Ve(g,j),k=o.placed.filter(z=>z.plot===d.id&&o.assets.some(_=>_.id===z.asset&&(d.owner.kind==="home"||_.kind==="building"&&_.name!=="Workshop"))),f=o.assets.find(z=>k.some(_=>_.asset===z.id)&&z.kind==="building"),E={...d,q:g,r:j,...b,ring:Math.max(Math.abs(g),Math.abs(j),Math.abs(g+j)),facing:Math.atan2(-b.x,-b.z)*180/Math.PI,officeName:f?.name??"Public project"};s.push(E),n.push(...k);for(const z of k){const _=o.assets.find(L=>L.id===z.asset);_&&!i.some(L=>L.id===_.id)&&i.push(_)}}const p=Math.max(30,o.radius,...s.map(c=>Math.hypot(c.x,c.z)+Re+4));return{island:{...o,plots:s,assets:i,placed:n,radius:p},residents:a,deskOwners:r}}function bi(){const o=new he;o.name="planted-seedlings";const e=new he;o.add(e);const t=new ht(1,1,1),s=new ze({color:"#88674b"}),i=new ze({color:"#64a856"}),n=new O(t,s);n.scale.set(.8,.035,.45),n.position.y=.02,o.add(n);for(const r of[-.26,0,.26]){const l=new O(t,i);l.scale.set(.025,.3,.025),l.position.set(r,.17,0),e.add(l);for(const h of[-1,1]){const m=new O(t,i);m.scale.set(.17,.045,.08),m.position.set(r+h*.07,.23,0),m.rotation.z=h*.4,e.add(m)}}let a=0;return{root:o,update(r,l){l&&(a=Math.min(1,a+r/12)),e.scale.setScalar(.12+a*.88),o.visible=a>0},dispose(){t.dispose(),s.dispose(),i.dispose()}}}const we=Ve(0,-1),ki={x:we.x,z:we.z-.8};function Mi(o){return{x:we.x+(o%4-1.5)*1.6,z:we.z+.6+Math.floor(o/4)*1}}function zi(){const o=new he;o.name="bot-society",o.position.set(we.x,.05,we.z);const e=new ht(1,1,1),t=new ze({color:"#ded8c9",roughness:.8}),s=new ze({color:"#caa45c",metalness:.5,roughness:.3}),i=new ze({color:"#b8e5f0",transparent:!0,opacity:.22,depthWrite:!1}),n=(c,d,g,j,b,k,f=t)=>{const E=new O(e,f);E.position.set(c,d,g),E.scale.set(j,b,k),o.add(E)};n(0,.05,0,8,.1,7),n(-3.9,1.2,0,.15,2.4,7,i),n(3.9,1.2,0,.15,2.4,7,i);for(const c of[-3.2,3.2])n(c,1.5,2.8,.45,3,.45),n(c,3.1,2.8,.75,.2,.75,s);n(0,3.15,2.8,6.8,.25,.35,s),n(0,.45,-1.6,3.2,.9,.65),n(0,.94,-1.6,3.5,.1,.9,s),n(0,.5,-3.7,2.4,1,1.8),n(0,1.07,-3.7,2.7,.15,2,s);const a=Is({id:"bot-society-statue",agent:"codex",model:"sol"}),r=ys({...a,shell:"#d7c592",trim:"#a98642",glow:"#fff2af",antenna:"crown"});xs(r,"raise",0,{calm:!0}),r.root.scale.setScalar(4.5),r.root.position.set(0,1.15,-3.7),o.add(r.root);const l=document.createElement("canvas");l.width=768,l.height=128;const h=l.getContext("2d");h.fillStyle="#f7e8bd",h.fillRect(0,0,768,128),h.fillStyle="#5d4828",h.font="bold 56px sans-serif",h.textAlign="center",h.fillText("BOT SOCIETY",384,80);const m=new Nt(l),p=new ee({map:m});return n(0,3.15,3.02,4.8,.8,.04,p),{root:o,solids:[{cx:we.x-3.9,cz:we.z,hx:.08,hz:3.5,yaw:0},{cx:we.x+3.9,cz:we.z,hx:.08,hz:3.5,yaw:0},{cx:we.x,cz:we.z-1.6,hx:1.7,hz:.45,yaw:0},{cx:we.x,cz:we.z-3.7,hx:1.4,hz:1.1,yaw:0}],dispose(){r.dispose(),e.dispose(),t.dispose(),s.dispose(),i.dispose(),m.dispose(),p.dispose()}}}function vi(o){if(o.kind==="accessory"||o.use==="none")return null;if(["read","paint","garden","perform","play","observe"].includes(o.use??""))return o.use;const e=o.name.toLowerCase();for(const[t,s]of[["garden",/garden|planter|greenhouse|seedling|herb|mint|花|种植|种子|盆栽|薄荷|温室|苗/],["paint",/easel|paint|画架|绘画|畫架/],["read",/library|bookshelf|bookcase|café|cafe|reading|书架|图书|書架|咖啡/],["perform",/music|concert|stage|piano|音乐|合奏|舞台|钢琴/],["play",/arcade|game|toy|游戏|玩具|游乐/],["observe",/lamp|light|灯|燈/]])if(s.test(e))return t;return/\b(chair|bench|stool|bed)\b|椅|凳|床/.test(e)&&!o.use?null:!o.use&&/\b(table|desk|workbench)\b|桌|工作台/.test(e)?/workbench|工作台/.test(e)?"play":"read":o.use==="desk"?/workbench|工作台/.test(e)?"play":"read":o.use==="seat"||o.use==="bed"?null:o.kind==="building"||o.kind==="furniture"||o.kind==="decor"?"observe":null}function _i(o,e,t){if(t.id.startsWith("office-desk:"))return null;const s=vi(o);if(!s||!o.parts.length)return null;const i=Math.max(...o.parts.map(c=>ct(c).max[2])),n=Math.max(0,...o.parts.map(c=>ct(c)).filter(c=>c.max[1]<=.35&&c.max[1]-c.min[1]<=.16).map(c=>c.max[1])),a=o.spot??(o.kind==="building"&&s!=="observe"?{at:[0,n,0],face:180}:{at:[0,0,i+.85],face:180}),r=t.turn*Math.PI/180,[l,h,m]=a.at,p=Ce(e,t.x+l*Math.cos(r)+m*Math.sin(r),t.z-l*Math.sin(r)+m*Math.cos(r));return{key:t.id,name:o.name,activity:s,...p,y:ce+t.y+h,face:(e.facing+t.turn+a.face)*Math.PI/180}}function es(o,e){const t={garden:"gardening",read:"reading",paint:"painting",perform:"music",play:"games"};return e==="observe"||!!o?.includes(t[e])}function Si(){const o=new he,e=new ht(1,1,1),t=["#f1e7cb","#6b86b6","#f5a14a","#76b9a5","#71c7ff"].map(m=>new ee({color:m})),s=(m,p,c)=>{const d=new he;d.name=m;const g=new O(e,t[c]);return g.scale.set(...p),d.add(g),o.add(d),d.visible=!1,d},i=s("read",[.32,.24,.05],1),n=s("paint",[.035,.32,.035],2),a=s("garden",[.22,.16,.17],3),r=s("register",[.24,.3,.02],0),l=s("play",[.25,.1,.1],1),h=new O(e,t[4]);return h.scale.set(.18,.035,.035),h.position.x=.16,a.add(h),{root:o,show(m){for(const p of[i,n,a,r,l])p.visible=p.name===m},dispose(){e.dispose(),t.forEach(m=>m.dispose())}}}function Pi(){const o=new he;o.name="concert-stage";const e=new ee({color:"#253044"}),t=new ee({color:"#9d8dff"}),s=new ee({color:"#c2a1ff",transparent:!0,opacity:.32,depthWrite:!1}),i=new ee({color:"#b997ff",transparent:!0,opacity:.13,depthWrite:!1,blending:It}),n=new lt(.75,20,12),a=new O(n,i);a.position.y=.65,o.add(a);const r=new ht(.5,.8,.4),l=new ws(.16,20),h=new zt(.7,1.25,40),m=new O(h,s);m.rotation.x=-Math.PI/2,m.position.y=.05,o.add(m);const p=[];for(const d of[-1,1]){const g=new he;g.position.set(d*1.2,.4,0),g.add(new O(r,e));for(const j of[-.19,.19]){const b=new O(l,t);b.position.set(0,j,.205),g.add(b)}o.add(g),p.push(g)}o.visible=!1;let c=0;return{root:o,update(d,g,j,b){c=Math.max(0,Math.min(1,c+(d?1:-1)*g*3)),o.visible=c>0;const k=b?1:1+Math.sin(j*8)*.09;o.scale.setScalar(Math.max(.001,c)),m.scale.setScalar(k),a.scale.setScalar(k),s.opacity=.24+(b?0:(Math.sin(j*8)+1)*.1),p.forEach(f=>f.scale.set(1,k,k))},dispose(){n.dispose(),i.dispose(),r.dispose(),l.dispose(),h.dispose(),e.dispose(),t.dispose(),s.dispose()}}}const ts={type:"change"},$t={type:"start"},vs={type:"end"},gt=new Hs,ss=new qs,ji=Math.cos(70*Zs.DEG2RAD),ae=new oe,xe=2*Math.PI,K={NONE:-1,ROTATE:0,DOLLY:1,PAN:2,TOUCH_ROTATE:3,TOUCH_PAN:4,TOUCH_DOLLY_PAN:5,TOUCH_DOLLY_ROTATE:6},Tt=1e-6;class Ei extends Ys{constructor(e,t=null){super(e,t),this.state=K.NONE,this.target=new oe,this.cursor=new oe,this.minDistance=0,this.maxDistance=1/0,this.minZoom=0,this.maxZoom=1/0,this.minTargetRadius=0,this.maxTargetRadius=1/0,this.minPolarAngle=0,this.maxPolarAngle=Math.PI,this.minAzimuthAngle=-1/0,this.maxAzimuthAngle=1/0,this.enableDamping=!1,this.dampingFactor=.05,this.enableZoom=!0,this.zoomSpeed=1,this.enableRotate=!0,this.rotateSpeed=1,this.keyRotateSpeed=1,this.enablePan=!0,this.panSpeed=1,this.screenSpacePanning=!0,this.keyPanSpeed=7,this.zoomToCursor=!1,this.autoRotate=!1,this.autoRotateSpeed=2,this.keys={LEFT:"ArrowLeft",UP:"ArrowUp",RIGHT:"ArrowRight",BOTTOM:"ArrowDown"},this.mouseButtons={LEFT:Je.ROTATE,MIDDLE:Je.DOLLY,RIGHT:Je.PAN},this.touches={ONE:Ze.ROTATE,TWO:Ze.DOLLY_PAN},this.target0=this.target.clone(),this.position0=this.object.position.clone(),this.zoom0=this.object.zoom,this._cursorStyle="auto",this._domElementKeyEvents=null,this._lastPosition=new oe,this._lastQuaternion=new qt,this._lastTargetPosition=new oe,this._quat=new qt().setFromUnitVectors(e.up,new oe(0,1,0)),this._quatInverse=this._quat.clone().invert(),this._spherical=new Zt,this._sphericalDelta=new Zt,this._scale=1,this._panOffset=new oe,this._rotateStart=new Me,this._rotateEnd=new Me,this._rotateDelta=new Me,this._panStart=new Me,this._panEnd=new Me,this._panDelta=new Me,this._dollyStart=new Me,this._dollyEnd=new Me,this._dollyDelta=new Me,this._dollyDirection=new oe,this._mouse=new Me,this._performCursorZoom=!1,this._pointers=[],this._pointerPositions={},this._controlActive=!1,this._onPointerMove=Ti.bind(this),this._onPointerDown=Ai.bind(this),this._onPointerUp=Li.bind(this),this._onContextMenu=Wi.bind(this),this._onMouseWheel=Ci.bind(this),this._onKeyDown=Ni.bind(this),this._onTouchStart=Ii.bind(this),this._onTouchMove=Oi.bind(this),this._onMouseDown=Di.bind(this),this._onMouseMove=Ri.bind(this),this._interceptControlDown=$i.bind(this),this._interceptControlUp=Ui.bind(this),this.domElement!==null&&this.connect(this.domElement),this.update()}set cursorStyle(e){this._cursorStyle=e,e==="grab"?this.domElement.style.cursor="grab":this.domElement.style.cursor="auto"}get cursorStyle(){return this._cursorStyle}connect(e){super.connect(e),this.domElement.addEventListener("pointerdown",this._onPointerDown),this.domElement.addEventListener("pointercancel",this._onPointerUp),this.domElement.addEventListener("contextmenu",this._onContextMenu),this.domElement.addEventListener("wheel",this._onMouseWheel,{passive:!1}),this.domElement.getRootNode().addEventListener("keydown",this._interceptControlDown,{passive:!0,capture:!0}),this.domElement.style.touchAction="none"}disconnect(){this.domElement.removeEventListener("pointerdown",this._onPointerDown),this.domElement.ownerDocument.removeEventListener("pointermove",this._onPointerMove),this.domElement.ownerDocument.removeEventListener("pointerup",this._onPointerUp),this.domElement.removeEventListener("pointercancel",this._onPointerUp),this.domElement.removeEventListener("wheel",this._onMouseWheel),this.domElement.removeEventListener("contextmenu",this._onContextMenu),this.stopListenToKeyEvents(),this.domElement.getRootNode().removeEventListener("keydown",this._interceptControlDown,{capture:!0}),this.domElement.style.touchAction=""}dispose(){this.disconnect()}getPolarAngle(){return this._spherical.phi}getAzimuthalAngle(){return this._spherical.theta}getDistance(){return this.object.position.distanceTo(this.target)}listenToKeyEvents(e){e.addEventListener("keydown",this._onKeyDown),this._domElementKeyEvents=e}stopListenToKeyEvents(){this._domElementKeyEvents!==null&&(this._domElementKeyEvents.removeEventListener("keydown",this._onKeyDown),this._domElementKeyEvents=null)}saveState(){this.target0.copy(this.target),this.position0.copy(this.object.position),this.zoom0=this.object.zoom}reset(){this.target.copy(this.target0),this.object.position.copy(this.position0),this.object.zoom=this.zoom0,this.object.updateProjectionMatrix(),this.dispatchEvent(ts),this.update(),this.state=K.NONE}pan(e,t){this._pan(e,t),this.update()}dollyIn(e){this._dollyIn(e),this.update()}dollyOut(e){this._dollyOut(e),this.update()}rotateLeft(e){this._rotateLeft(e),this.update()}rotateUp(e){this._rotateUp(e),this.update()}update(e=null){const t=this.object.position;ae.copy(t).sub(this.target),ae.applyQuaternion(this._quat),this._spherical.setFromVector3(ae),this.autoRotate&&this.state===K.NONE&&this._rotateLeft(this._getAutoRotationAngle(e)),this.enableDamping?(this._spherical.theta+=this._sphericalDelta.theta*this.dampingFactor,this._spherical.phi+=this._sphericalDelta.phi*this.dampingFactor):(this._spherical.theta+=this._sphericalDelta.theta,this._spherical.phi+=this._sphericalDelta.phi);let s=this.minAzimuthAngle,i=this.maxAzimuthAngle;isFinite(s)&&isFinite(i)&&(s<-Math.PI?s+=xe:s>Math.PI&&(s-=xe),i<-Math.PI?i+=xe:i>Math.PI&&(i-=xe),s<=i?this._spherical.theta=Math.max(s,Math.min(i,this._spherical.theta)):this._spherical.theta=this._spherical.theta>(s+i)/2?Math.max(s,this._spherical.theta):Math.min(i,this._spherical.theta)),this._spherical.phi=Math.max(this.minPolarAngle,Math.min(this.maxPolarAngle,this._spherical.phi)),this._spherical.makeSafe(),this.enableDamping===!0?this.target.addScaledVector(this._panOffset,this.dampingFactor):this.target.add(this._panOffset),this.target.sub(this.cursor),this.target.clampLength(this.minTargetRadius,this.maxTargetRadius),this.target.add(this.cursor);let n=!1;if(this.zoomToCursor&&this._performCursorZoom||this.object.isOrthographicCamera)this._spherical.radius=this._clampDistance(this._spherical.radius);else{const a=this._spherical.radius;this._spherical.radius=this._clampDistance(this._spherical.radius*this._scale),n=a!=this._spherical.radius}if(ae.setFromSpherical(this._spherical),ae.applyQuaternion(this._quatInverse),t.copy(this.target).add(ae),this.object.lookAt(this.target),this.enableDamping===!0?(this._sphericalDelta.theta*=1-this.dampingFactor,this._sphericalDelta.phi*=1-this.dampingFactor,this._panOffset.multiplyScalar(1-this.dampingFactor)):(this._sphericalDelta.set(0,0,0),this._panOffset.set(0,0,0)),this.zoomToCursor&&this._performCursorZoom){let a=null;if(this.object.isPerspectiveCamera){const r=ae.length();a=this._clampDistance(r*this._scale);const l=r-a;this.object.position.addScaledVector(this._dollyDirection,l),this.object.updateMatrixWorld(),n=!!l}else if(this.object.isOrthographicCamera){const r=new oe(this._mouse.x,this._mouse.y,0);r.unproject(this.object);const l=this.object.zoom;this.object.zoom=Math.max(this.minZoom,Math.min(this.maxZoom,this.object.zoom/this._scale)),this.object.updateProjectionMatrix(),n=l!==this.object.zoom;const h=new oe(this._mouse.x,this._mouse.y,0);h.unproject(this.object),this.object.position.sub(h).add(r),this.object.updateMatrixWorld(),a=ae.length()}else console.warn("WARNING: OrbitControls.js encountered an unknown camera type - zoom to cursor disabled."),this.zoomToCursor=!1;a!==null&&(this.screenSpacePanning?this.target.set(0,0,-1).transformDirection(this.object.matrix).multiplyScalar(a).add(this.object.position):(gt.origin.copy(this.object.position),gt.direction.set(0,0,-1).transformDirection(this.object.matrix),Math.abs(this.object.up.dot(gt.direction))<ji?this.object.lookAt(this.target):(ss.setFromNormalAndCoplanarPoint(this.object.up,this.target),gt.intersectPlane(ss,this.target))))}else if(this.object.isOrthographicCamera){const a=this.object.zoom;this.object.zoom=Math.max(this.minZoom,Math.min(this.maxZoom,this.object.zoom/this._scale)),a!==this.object.zoom&&(this.object.updateProjectionMatrix(),n=!0)}return this._scale=1,this._performCursorZoom=!1,n||this._lastPosition.distanceToSquared(this.object.position)>Tt||8*(1-this._lastQuaternion.dot(this.object.quaternion))>Tt||this._lastTargetPosition.distanceToSquared(this.target)>Tt?(this.dispatchEvent(ts),this._lastPosition.copy(this.object.position),this._lastQuaternion.copy(this.object.quaternion),this._lastTargetPosition.copy(this.target),!0):!1}_getAutoRotationAngle(e){return e!==null?xe/60*this.autoRotateSpeed*e:xe/60/60*this.autoRotateSpeed}_getZoomScale(e){const t=Math.abs(e*.01);return Math.pow(.95,this.zoomSpeed*t)}_rotateLeft(e){this._sphericalDelta.theta-=e}_rotateUp(e){this._sphericalDelta.phi-=e}_panLeft(e,t){ae.setFromMatrixColumn(t,0),ae.multiplyScalar(-e),this._panOffset.add(ae)}_panUp(e,t){this.screenSpacePanning===!0?ae.setFromMatrixColumn(t,1):(ae.setFromMatrixColumn(t,0),ae.crossVectors(this.object.up,ae)),ae.multiplyScalar(e),this._panOffset.add(ae)}_pan(e,t){const s=this.domElement;if(this.object.isPerspectiveCamera){const i=this.object.position;ae.copy(i).sub(this.target);let n=ae.length();n*=Math.tan(this.object.fov/2*Math.PI/180),this._panLeft(2*e*n/s.clientHeight,this.object.matrix),this._panUp(2*t*n/s.clientHeight,this.object.matrix)}else this.object.isOrthographicCamera?(this._panLeft(e*(this.object.right-this.object.left)/this.object.zoom/s.clientWidth,this.object.matrix),this._panUp(t*(this.object.top-this.object.bottom)/this.object.zoom/s.clientHeight,this.object.matrix)):(console.warn("WARNING: OrbitControls.js encountered an unknown camera type - pan disabled."),this.enablePan=!1)}_dollyOut(e){this.object.isPerspectiveCamera||this.object.isOrthographicCamera?this._scale/=e:(console.warn("WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled."),this.enableZoom=!1)}_dollyIn(e){this.object.isPerspectiveCamera||this.object.isOrthographicCamera?this._scale*=e:(console.warn("WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled."),this.enableZoom=!1)}_updateZoomParameters(e,t){if(!this.zoomToCursor)return;this._performCursorZoom=!0;const s=this.domElement.getBoundingClientRect(),i=e-s.left,n=t-s.top,a=s.width,r=s.height;this._mouse.x=i/a*2-1,this._mouse.y=-(n/r)*2+1,this._dollyDirection.set(this._mouse.x,this._mouse.y,1).unproject(this.object).sub(this.object.position).normalize()}_clampDistance(e){return Math.max(this.minDistance,Math.min(this.maxDistance,e))}_handleMouseDownRotate(e){this._rotateStart.set(e.clientX,e.clientY)}_handleMouseDownDolly(e){this._updateZoomParameters(e.clientX,e.clientX),this._dollyStart.set(e.clientX,e.clientY)}_handleMouseDownPan(e){this._panStart.set(e.clientX,e.clientY)}_handleMouseMoveRotate(e){this._rotateEnd.set(e.clientX,e.clientY),this._rotateDelta.subVectors(this._rotateEnd,this._rotateStart).multiplyScalar(this.rotateSpeed);const t=this.domElement;this._rotateLeft(xe*this._rotateDelta.x/t.clientHeight),this._rotateUp(xe*this._rotateDelta.y/t.clientHeight),this._rotateStart.copy(this._rotateEnd),this.update()}_handleMouseMoveDolly(e){this._dollyEnd.set(e.clientX,e.clientY),this._dollyDelta.subVectors(this._dollyEnd,this._dollyStart),this._dollyDelta.y>0?this._dollyOut(this._getZoomScale(this._dollyDelta.y)):this._dollyDelta.y<0&&this._dollyIn(this._getZoomScale(this._dollyDelta.y)),this._dollyStart.copy(this._dollyEnd),this.update()}_handleMouseMovePan(e){this._panEnd.set(e.clientX,e.clientY),this._panDelta.subVectors(this._panEnd,this._panStart).multiplyScalar(this.panSpeed),this._pan(this._panDelta.x,this._panDelta.y),this._panStart.copy(this._panEnd),this.update()}_handleMouseWheel(e){this._updateZoomParameters(e.clientX,e.clientY),e.deltaY<0?this._dollyIn(this._getZoomScale(e.deltaY)):e.deltaY>0&&this._dollyOut(this._getZoomScale(e.deltaY)),this.update()}_handleKeyDown(e){let t=!1;switch(e.code){case this.keys.UP:e.ctrlKey||e.metaKey||e.shiftKey?this.enableRotate&&this._rotateUp(xe*this.keyRotateSpeed/this.domElement.clientHeight):this.enablePan&&this._pan(0,this.keyPanSpeed),t=!0;break;case this.keys.BOTTOM:e.ctrlKey||e.metaKey||e.shiftKey?this.enableRotate&&this._rotateUp(-xe*this.keyRotateSpeed/this.domElement.clientHeight):this.enablePan&&this._pan(0,-this.keyPanSpeed),t=!0;break;case this.keys.LEFT:e.ctrlKey||e.metaKey||e.shiftKey?this.enableRotate&&this._rotateLeft(xe*this.keyRotateSpeed/this.domElement.clientHeight):this.enablePan&&this._pan(this.keyPanSpeed,0),t=!0;break;case this.keys.RIGHT:e.ctrlKey||e.metaKey||e.shiftKey?this.enableRotate&&this._rotateLeft(-xe*this.keyRotateSpeed/this.domElement.clientHeight):this.enablePan&&this._pan(-this.keyPanSpeed,0),t=!0;break}t&&(e.preventDefault(),this.update())}_handleTouchStartRotate(e){if(this._pointers.length===1)this._rotateStart.set(e.pageX,e.pageY);else{const t=this._getSecondPointerPosition(e),s=.5*(e.pageX+t.x),i=.5*(e.pageY+t.y);this._rotateStart.set(s,i)}}_handleTouchStartPan(e){if(this._pointers.length===1)this._panStart.set(e.pageX,e.pageY);else{const t=this._getSecondPointerPosition(e),s=.5*(e.pageX+t.x),i=.5*(e.pageY+t.y);this._panStart.set(s,i)}}_handleTouchStartDolly(e){const t=this._getSecondPointerPosition(e),s=e.pageX-t.x,i=e.pageY-t.y,n=Math.sqrt(s*s+i*i);this._dollyStart.set(0,n)}_handleTouchStartDollyPan(e){this.enableZoom&&this._handleTouchStartDolly(e),this.enablePan&&this._handleTouchStartPan(e)}_handleTouchStartDollyRotate(e){this.enableZoom&&this._handleTouchStartDolly(e),this.enableRotate&&this._handleTouchStartRotate(e)}_handleTouchMoveRotate(e){if(this._pointers.length==1)this._rotateEnd.set(e.pageX,e.pageY);else{const s=this._getSecondPointerPosition(e),i=.5*(e.pageX+s.x),n=.5*(e.pageY+s.y);this._rotateEnd.set(i,n)}this._rotateDelta.subVectors(this._rotateEnd,this._rotateStart).multiplyScalar(this.rotateSpeed);const t=this.domElement;this._rotateLeft(xe*this._rotateDelta.x/t.clientHeight),this._rotateUp(xe*this._rotateDelta.y/t.clientHeight),this._rotateStart.copy(this._rotateEnd)}_handleTouchMovePan(e){if(this._pointers.length===1)this._panEnd.set(e.pageX,e.pageY);else{const t=this._getSecondPointerPosition(e),s=.5*(e.pageX+t.x),i=.5*(e.pageY+t.y);this._panEnd.set(s,i)}this._panDelta.subVectors(this._panEnd,this._panStart).multiplyScalar(this.panSpeed),this._pan(this._panDelta.x,this._panDelta.y),this._panStart.copy(this._panEnd)}_handleTouchMoveDolly(e){const t=this._getSecondPointerPosition(e),s=e.pageX-t.x,i=e.pageY-t.y,n=Math.sqrt(s*s+i*i);this._dollyEnd.set(0,n),this._dollyDelta.set(0,Math.pow(this._dollyEnd.y/this._dollyStart.y,this.zoomSpeed)),this._dollyOut(this._dollyDelta.y),this._dollyStart.copy(this._dollyEnd);const a=(e.pageX+t.x)*.5,r=(e.pageY+t.y)*.5;this._updateZoomParameters(a,r)}_handleTouchMoveDollyPan(e){this.enableZoom&&this._handleTouchMoveDolly(e),this.enablePan&&this._handleTouchMovePan(e)}_handleTouchMoveDollyRotate(e){this.enableZoom&&this._handleTouchMoveDolly(e),this.enableRotate&&this._handleTouchMoveRotate(e)}_addPointer(e){this._pointers.push(e.pointerId)}_removePointer(e){delete this._pointerPositions[e.pointerId];for(let t=0;t<this._pointers.length;t++)if(this._pointers[t]==e.pointerId){this._pointers.splice(t,1);return}}_isTrackingPointer(e){for(let t=0;t<this._pointers.length;t++)if(this._pointers[t]==e.pointerId)return!0;return!1}_trackPointer(e){let t=this._pointerPositions[e.pointerId];t===void 0&&(t=new Me,this._pointerPositions[e.pointerId]=t),t.set(e.pageX,e.pageY)}_getSecondPointerPosition(e){const t=e.pointerId===this._pointers[0]?this._pointers[1]:this._pointers[0];return this._pointerPositions[t]}_customWheelEvent(e){const t=e.deltaMode,s={clientX:e.clientX,clientY:e.clientY,deltaY:e.deltaY};switch(t){case 1:s.deltaY*=16;break;case 2:s.deltaY*=100;break}return e.ctrlKey&&!this._controlActive&&(s.deltaY*=10),s}}function Ai(o){this.enabled!==!1&&(this._pointers.length===0&&(this.domElement.setPointerCapture(o.pointerId),this.domElement.ownerDocument.addEventListener("pointermove",this._onPointerMove),this.domElement.ownerDocument.addEventListener("pointerup",this._onPointerUp)),!this._isTrackingPointer(o)&&(this._addPointer(o),o.pointerType==="touch"?this._onTouchStart(o):this._onMouseDown(o),this._cursorStyle==="grab"&&(this.domElement.style.cursor="grabbing")))}function Ti(o){this.enabled!==!1&&(o.pointerType==="touch"?this._onTouchMove(o):this._onMouseMove(o))}function Li(o){switch(this._removePointer(o),this._pointers.length){case 0:this.domElement.releasePointerCapture(o.pointerId),this.domElement.ownerDocument.removeEventListener("pointermove",this._onPointerMove),this.domElement.ownerDocument.removeEventListener("pointerup",this._onPointerUp),this.dispatchEvent(vs),this.state=K.NONE,this._cursorStyle==="grab"&&(this.domElement.style.cursor="grab");break;case 1:const e=this._pointers[0],t=this._pointerPositions[e];this._onTouchStart({pointerId:e,pageX:t.x,pageY:t.y});break}}function Di(o){let e;switch(o.button){case 0:e=this.mouseButtons.LEFT;break;case 1:e=this.mouseButtons.MIDDLE;break;case 2:e=this.mouseButtons.RIGHT;break;default:e=-1}switch(e){case Je.DOLLY:if(this.enableZoom===!1)return;this._handleMouseDownDolly(o),this.state=K.DOLLY;break;case Je.ROTATE:if(o.ctrlKey||o.metaKey||o.shiftKey){if(this.enablePan===!1)return;this._handleMouseDownPan(o),this.state=K.PAN}else{if(this.enableRotate===!1)return;this._handleMouseDownRotate(o),this.state=K.ROTATE}break;case Je.PAN:if(o.ctrlKey||o.metaKey||o.shiftKey){if(this.enableRotate===!1)return;this._handleMouseDownRotate(o),this.state=K.ROTATE}else{if(this.enablePan===!1)return;this._handleMouseDownPan(o),this.state=K.PAN}break;default:this.state=K.NONE}this.state!==K.NONE&&this.dispatchEvent($t)}function Ri(o){switch(this.state){case K.ROTATE:if(this.enableRotate===!1)return;this._handleMouseMoveRotate(o);break;case K.DOLLY:if(this.enableZoom===!1)return;this._handleMouseMoveDolly(o);break;case K.PAN:if(this.enablePan===!1)return;this._handleMouseMovePan(o);break}}function Ci(o){this.enabled===!1||this.enableZoom===!1||this.state!==K.NONE||(o.preventDefault(),this.dispatchEvent($t),this._handleMouseWheel(this._customWheelEvent(o)),this.dispatchEvent(vs))}function Ni(o){this.enabled!==!1&&this._handleKeyDown(o)}function Ii(o){switch(this._trackPointer(o),this._pointers.length){case 1:switch(this.touches.ONE){case Ze.ROTATE:if(this.enableRotate===!1)return;this._handleTouchStartRotate(o),this.state=K.TOUCH_ROTATE;break;case Ze.PAN:if(this.enablePan===!1)return;this._handleTouchStartPan(o),this.state=K.TOUCH_PAN;break;default:this.state=K.NONE}break;case 2:switch(this.touches.TWO){case Ze.DOLLY_PAN:if(this.enableZoom===!1&&this.enablePan===!1)return;this._handleTouchStartDollyPan(o),this.state=K.TOUCH_DOLLY_PAN;break;case Ze.DOLLY_ROTATE:if(this.enableZoom===!1&&this.enableRotate===!1)return;this._handleTouchStartDollyRotate(o),this.state=K.TOUCH_DOLLY_ROTATE;break;default:this.state=K.NONE}break;default:this.state=K.NONE}this.state!==K.NONE&&this.dispatchEvent($t)}function Oi(o){switch(this._trackPointer(o),this.state){case K.TOUCH_ROTATE:if(this.enableRotate===!1)return;this._handleTouchMoveRotate(o),this.update();break;case K.TOUCH_PAN:if(this.enablePan===!1)return;this._handleTouchMovePan(o),this.update();break;case K.TOUCH_DOLLY_PAN:if(this.enableZoom===!1&&this.enablePan===!1)return;this._handleTouchMoveDollyPan(o),this.update();break;case K.TOUCH_DOLLY_ROTATE:if(this.enableZoom===!1&&this.enableRotate===!1)return;this._handleTouchMoveDollyRotate(o),this.update();break;default:this.state=K.NONE}}function Wi(o){this.enabled!==!1&&o.preventDefault()}function $i(o){o.key==="Control"&&(this._controlActive=!0,this.domElement.getRootNode().addEventListener("keyup",this._interceptControlUp,{passive:!0,capture:!0}))}function Ui(o){o.key==="Control"&&(this._controlActive=!1,this.domElement.getRootNode().removeEventListener("keyup",this._interceptControlUp,{passive:!0,capture:!0}))}function Bi(o){if(o.kind!=="building"||!o.parts.length)return[];const e=o.parts.map(ct).filter(({min:t,max:s})=>(s[1]<=1.2+1e-6||s[1]-t[1]<.3)&&s[0]-t[0]>1&&s[2]-t[2]>1);if(!e.length){const t=Qs(o);e.push({min:[t.min[0],0,t.min[2]],max:[t.max[0],0,t.max[2]]})}return e.map(({min:t,max:s})=>({x:(t[0]+s[0])/2,y:s[1]+.012,z:(t[2]+s[2])/2,width:(s[0]-t[0])*.96,depth:(s[2]-t[2])*.96}))}class _s{group=new he;material=new bs({uniforms:{night:{value:0},warmth:{value:new H("#ffb24d")},strength:{value:.34}},vertexShader:`varying vec2 lightUv;
|
|
2
|
+
void main() { lightUv = uv; gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0); }`,fragmentShader:`uniform float night; uniform vec3 warmth; uniform float strength; varying vec2 lightUv;
|
|
3
|
+
void main() {
|
|
4
|
+
vec2 p = lightUv * 2.0 - 1.0;
|
|
5
|
+
float falloff = pow(max(0.0, 1.0 - dot(p, p)), 2.0);
|
|
6
|
+
gl_FragColor = vec4(warmth, night * strength * falloff);
|
|
7
|
+
#include <tonemapping_fragment>
|
|
8
|
+
#include <colorspace_fragment>
|
|
9
|
+
}`,transparent:!0,depthWrite:!1,blending:It,toneMapped:!1});geometry;constructor({interior:e=!1}={}){e&&(this.material.blending=Xs,this.material.uniforms.warmth.value.set("#ffa62e"),this.material.uniforms.strength.value=.68),this.group.name="night-light-pools",this.group.visible=!1}replace(e){if(this.group.clear(),this.geometry?.dispose(),this.geometry=void 0,!e.length)return;const t=e.map(s=>{const i=new Ot(s.width,s.depth);return i.rotateX(-Math.PI/2),i.translate(s.x,s.y,s.z),s.transform&&i.applyMatrix4(s.transform),i});if(this.geometry=Wt(t,!1)??void 0,t.forEach(s=>s.dispose()),this.geometry){this.geometry.computeBoundingSphere();const s=new O(this.geometry,this.material);s.renderOrder=1,this.group.add(s)}}update(e){this.material.uniforms.night.value=Math.max(0,Math.min(1,e)),this.group.visible=this.material.uniforms.night.value>0}dispose(){this.geometry?.dispose(),this.material.dispose(),this.group.clear()}}const We=.4,Fi=.15;class is{constructor(e,t=[],s=1.5,i=[]){this.radius=e,this.shore=s;const n=Math.max(e,...i.map(r=>Math.hypot(r.cx,r.cz)+Math.hypot(r.hx,r.hz)));this.half=Math.ceil(n/We),this.size=this.half*2+1,this.blocked=new Uint8Array(this.size*this.size);const a=e-s;for(let r=0;r<this.size;r++)for(let l=0;l<this.size;l++){const{x:h,z:m}=this.center(r,l);Math.hypot(h,m)>a&&(this.blocked[l*this.size+r]=1)}for(const r of i)this.mark(r,0,0);for(const r of t)this.block(r)}radius;shore;size;half;blocked;center(e,t){return{x:(e-this.half)*We,z:(t-this.half)*We}}cellOf(e){return[Math.round(e.x/We)+this.half,Math.round(e.z/We)+this.half]}inside(e,t){return e>=0&&t>=0&&e<this.size&&t<this.size}free(e,t){return this.inside(e,t)&&!this.blocked[t*this.size+e]}block(e){this.mark(e,Fi,1)}mark(e,t,s){const i=e.hx+t,n=e.hz+t,a=Math.cos(e.yaw),r=Math.sin(e.yaw),l=Math.hypot(i,n),[h,m]=this.cellOf({x:e.cx-l,z:e.cz-l}),[p,c]=this.cellOf({x:e.cx+l,z:e.cz+l});for(let d=Math.max(0,h);d<=Math.min(this.size-1,p);d++)for(let g=Math.max(0,m);g<=Math.min(this.size-1,c);g++){const j=this.center(d,g),b=j.x-e.cx,k=j.z-e.cz,f=b*a-k*r,E=b*r+k*a;Math.abs(f)<=i&&Math.abs(E)<=n&&(this.blocked[g*this.size+d]=s)}}isFree(e){const[t,s]=this.cellOf(e);return this.free(t,s)}nearestFree(e,t=6){const[s,i]=this.cellOf(e);if(this.free(s,i))return this.center(s,i);const n=Math.ceil(t/We);for(let a=1;a<=n;a++){let r=null,l=1/0;for(let h=-a;h<=a;h++)for(const m of Math.abs(h)===a?Ki(-a,a):[-a,a]){const p=s+h,c=i+m;if(!this.free(p,c))continue;const d=this.center(p,c),g=Math.hypot(d.x-e.x,d.z-e.z);g<l&&(r=d,l=g)}if(r)return r}return null}clear(e,t){const s=Math.hypot(t.x-e.x,t.z-e.z),i=Math.max(1,Math.ceil(s/(We/3)));for(let n=0;n<=i;n++){const a=n/i;if(!this.isFree({x:e.x+(t.x-e.x)*a,z:e.z+(t.z-e.z)*a}))return!1}return!0}path(e,t,s=4e4){const i=this.nearestFree(e),n=this.nearestFree(t);if(!i||!n)return null;const[a,r]=this.cellOf(i),[l,h]=this.cellOf(n),m=this.size,p=r*m+a,c=h*m+l,d=new Int32Array(m*m).fill(-1),g=new Float32Array(m*m).fill(1/0),j=new Yi;g[p]=0,j.push(p,ns(a,r,l,h));let b=0,k=p===c;for(;!k&&j.size&&b++<s;){const _=j.pop();if(_===c){k=!0;break}const L=_%m,A=(_-L)/m;for(const[S,N,$]of Gi){const W=L+S,X=A+N;if(!this.free(W,X)||S&&N&&(!this.free(L+S,A)||!this.free(L,A+N)))continue;const Y=X*m+W,F=g[_]+$;F>=g[Y]||(g[Y]=F,d[Y]=_,j.push(Y,F+ns(W,X,l,h)))}}if(!k)return null;const f=[];for(let _=c;_!==-1&&_!==p;_=d[_]){const L=_%m;f.push(this.center(L,(_-L)/m))}f.reverse();const E=this.smooth([e,...f]);E.shift();const z=E[E.length-1];return(!z||Math.hypot(z.x-t.x,z.z-t.z)>1e-6)&&E.push(t),E}smooth(e){if(e.length<=2)return e;const t=[e[0]];let s=0;for(let i=2;i<e.length;i++)this.clear(e[s],e[i])||(t.push(e[i-1]),s=i-1);return t.push(e[e.length-1]),t}}const at=Math.SQRT2,Gi=[[1,0,1],[-1,0,1],[0,1,1],[0,-1,1],[1,1,at],[1,-1,at],[-1,1,at],[-1,-1,at]];function ns(o,e,t,s){const i=Math.abs(o-t),n=Math.abs(e-s);return i+n+(at-2)*Math.min(i,n)}function Ki(o,e){const t=[];for(let s=o;s<=e;s++)t.push(s);return t}class Yi{items=[];keys=[];get size(){return this.items.length}push(e,t){this.items.push(e),this.keys.push(t);let s=this.items.length-1;for(;s>0;){const i=s-1>>1;if(this.keys[i]<=this.keys[s])break;this.swap(s,i),s=i}}pop(){const e=this.items[0],t=this.items.pop(),s=this.keys.pop();if(this.items.length){this.items[0]=t,this.keys[0]=s;let i=0;for(;;){const n=i*2+1,a=n+1;let r=i;if(n<this.items.length&&this.keys[n]<this.keys[r]&&(r=n),a<this.items.length&&this.keys[a]<this.keys[r]&&(r=a),r===i)break;this.swap(i,r),i=r}}return e}swap(e,t){[this.items[e],this.items[t]]=[this.items[t],this.items[e]],[this.keys[e],this.keys[t]]=[this.keys[t],this.keys[e]]}}class ot{constructor(e){this.materials=e}materials;pieces=new Map;add(e,t,s,i,n,a={}){const r=t.index?t.toNonIndexed():t.clone();for(const m of Object.keys(r.attributes))m!=="position"&&m!=="normal"&&r.deleteAttribute(m);r.scale(a.sx??1,a.sy??1,a.sz??1),a.rx&&r.rotateX(a.rx),a.rz&&r.rotateZ(a.rz),a.ry&&r.rotateY(a.ry),r.translate(s,i,n);const l=this.materials[e],h=this.pieces.get(l)??[];h.push(r),this.pieces.set(l,h)}addAt(e,t,s,i,n,a,r,l,h={}){const m=Math.cos(s),p=Math.sin(s);this.add(i,n,e+a*m+l*p,r,t-a*p+l*m,{...h,ry:(h.ry??0)+s})}build(e){const t=new he;for(const[s,i]of this.pieces){const n=Wt(i,!1);if(i.forEach(l=>l.dispose()),!n)continue;const a=new O(n,s),r=!(s instanceof ee);a.castShadow=e&&r,a.receiveShadow=e&&r,t.add(a)}return this.pieces.clear(),t}}const G=(o,e=.8,t=0)=>new ze({color:o,roughness:e,metalness:t,flatShading:!0}),yt={q:-1,r:0},nt={x:-2.4,z:-2.4,top:2.3,rope:1.68,seats:[-.75,.75]},Hi={x:-2.2,z:2.7,height:.45,half:1.45},as={x:2.6,ladderZ:-3.3,platformZ:-2.9,top:1.35,chuteFrom:-2.5,chuteTo:.45,bottom:.22};function qi(o){const e=o.facing*Math.PI/180,t=Math.cos(e),s=Math.sin(e),i=(T,B)=>({x:o.x+T*t+B*s,z:o.z-T*s+B*t}),n=(T,B,te)=>({...i(T,te),y:ce+B}),a=[],r=T=>(a.push(T),T),l={frame:r(G("#afa2d9",.6)),red:r(G("#e9a5bd",.6)),yellow:r(G("#f0d39e",.5)),teal:r(G("#9bcebf",.6)),wood:r(G("#ddb78e",.8)),darkWood:r(G("#806071",.8)),rope:r(G("#fff0e7",.9))},h=r(new Dt(1,1,1,2,.08)),m=r(new Xe(.5,.5,1,10)),p=new he;p.name="playground",p.position.set(o.x,ce,o.z),p.rotation.y=e;const c=new ot(l),{x:d,z:g,top:j}=nt;c.add("frame",m,d,j,g,{sx:.13,sy:3.3,sz:.13,rz:Math.PI/2});for(const T of[-1.6,1.6])for(const B of[-1,1]){const ge=Math.hypot(j,.75);c.add("frame",m,d+T,j/2,g+B*.75/2,{sx:.12,sy:ge,sz:.12,rx:-B*Math.atan2(.75,j)})}const b=nt.seats.map(T=>{const B=new he;B.position.set(d+T,j-.04,g);for(const ge of[-.22,.22]){const ye=new O(m,l.rope);ye.scale.set(.035,nt.rope,.035),ye.position.set(ge,-1.68/2,0),B.add(ye)}const te=new O(h,l.red);return te.scale.set(.56,.06,.34),te.position.set(0,-1.68,0),te.castShadow=o.shadows,B.add(te),p.add(B),B}),{x:k,z:f,height:E,half:z}=Hi;c.add("darkWood",h,k,E/2-.05,f,{sx:.34,sy:E-.1,sz:.5}),c.add("frame",m,k,E,f,{sx:.1,sy:.56,sz:.1,rx:Math.PI/2});const _=new he;_.position.set(k,E,f);const L=[["yellow",0,.05,0,z*2+.5,.08,.32],["teal",-z,.12,0,.42,.07,.36],["teal",z,.12,0,.42,.07,.36],["frame",-z+.32,.3,0,.06,.4,.06],["frame",z-.32,.3,0,.06,.4,.06],["frame",-z+.32,.48,0,.06,.06,.4],["frame",z-.32,.48,0,.06,.06,.4]];for(const[T,B,te,ge,ye,se,re]of L){const be=new O(h,l[T]);be.scale.set(ye,se,re),be.position.set(B,te,ge),be.castShadow=o.shadows,_.add(be)}p.add(_);const{x:A,ladderZ:S,platformZ:N,chuteFrom:$,chuteTo:W,bottom:X}=as,Y=as.top;for(const T of[-.32,.32])c.add("frame",m,A+T,Y/2+.15,S,{sx:.07,sy:Y+.3,sz:.07});for(let T=.25;T<Y;T+=.27)c.add("yellow",m,A,T,S,{sx:.05,sy:.64,sz:.05,rz:Math.PI/2});for(const T of[[-.4,-.38],[.4,-.38],[-.4,.38],[.4,.38]])c.add("frame",m,A+T[0],Y/2,N+T[1],{sx:.08,sy:Y,sz:.08});c.add("wood",h,A,Y,N,{sx:.95,sy:.08,sz:.85});for(const T of[-.45,.45])c.add("red",h,A+T,Y+.3,N,{sx:.05,sy:.06,sz:.8});const F=Y-X,V=W-$,ve=Math.hypot(F,V),ne=Math.atan2(F,V),fe=($+W)/2,q=(Y+X)/2;c.add("yellow",h,A,q,fe,{sx:.7,sy:.06,sz:ve,rx:ne});for(const T of[-.37,.37])c.add("red",h,A+T,q+.09,fe,{sx:.06,sy:.18,sz:ve,rx:ne});c.add("yellow",h,A,X,W+.3,{sx:.7,sy:.06,sz:.6});for(const T of[$+V*.55])c.add("frame",m,A,(X+F*.45)/2,T,{sx:.07,sy:X+F*.45,sz:.07});const Ee=3.3,Ae=3.4;c.add("wood",h,Ee,.27,Ae,{sx:1.6,sy:.08,sz:.45}),c.add("wood",h,Ee,.52,Ae+.2,{sx:1.6,sy:.28,sz:.07});for(const T of[-.65,.65])c.add("darkWood",h,Ee+T,.13,Ae,{sx:.09,sy:.26,sz:.4});const de=c.build(o.shadows);de.traverse(T=>{const B=T;B.geometry&&r(B.geometry)}),p.add(de);const Ne={x:s,z:t},Be=nt.seats.map(T=>({pivot:n(d+T,j-.04,g),rope:nt.rope+.03,face:e,stand:i(d+T,g+.75)})),Fe={pivot:n(k,E,f),half:z,yaw:e,stand:[i(k-z,f+.55),i(k+z,f+.55)]},U={queue:i(A,S-1),back:{x:-Ne.x,z:-Ne.z},foot:i(A,S-.35),top:n(A,Y+.04,N),from:n(A,Y+.1,$+.15),to:n(A,X+.12,W+.2),exit:i(A,W+1),face:e},me=(T,B,te,ge)=>({...Zi(i(T,B)),hx:te,hz:ge,yaw:e}),_e=[...[-1.6,1.6].flatMap(T=>[-.75,.75].map(B=>me(d+T,g+B,.12,.12))),me(k,f,z+.2,.22),me(A,(S+W)/2,.42,(W-S)/2+.1),me(Ee,Ae,.8,.25)],De=e+Math.PI,ue=[-.4,.4].map(T=>{const B=i(Ee+T,Ae-.02);return{key:`playground:bench:${T}`,kind:"seat",x:B.x,z:B.z,y:ce+.31,face:De,plot:null,name:"the playground bench"}});return{group:p,solids:_e,seats:ue,anchors:{center:i(0,0),swings:Be,seesaw:Fe,slide:U},setMotion(T){b.forEach((B,te)=>{B.rotation.x=-(T.swings[te]??0)}),_.rotation.z=T.seesaw},dispose(){a.forEach(T=>T.dispose())}}}function Zi(o){return{cx:o.x,cz:o.z}}function Xi(o,e,t){const s=e===0?-1:1,i=s*o.half*Math.cos(t),n=s*o.half*Math.sin(t);return{x:o.pivot.x+i*Math.cos(o.yaw),z:o.pivot.z-i*Math.sin(o.yaw),y:o.pivot.y+n+.19,face:o.yaw+(e===0?Math.PI/2:-Math.PI/2)}}function Qi(o,e){const t=o.rope*Math.sin(e);return{x:o.pivot.x+Math.sin(o.face)*t,z:o.pivot.z+Math.cos(o.face)*t,y:o.pivot.y-o.rope*Math.cos(e)+.04,face:o.face}}const Vi=1/840,Ji=150,xt=1.05,en=7,os=.9,tn=1.8,sn=300,rs=60,nn=["how are you?","nice day!","🌊","☕?","haha","look!","🎵","same!","really?","😄","✨","🍩","ok!","me too!","🌸","so sunny","🐚","hmm…","💡","yay!"];function an(o){let e=o>>>0;return()=>{e=e+1831565813>>>0;let t=e;return t=Math.imul(t^t>>>15,t|1),t^=t+Math.imul(t^t>>>7,t|61),((t^t>>>14)>>>0)/4294967296}}function on(o){let e=2166136261;for(const t of o)e=Math.imul(e^(t.codePointAt(0)??0),16777619);return e>>>0}function Ye(o,e=0){const t=(o-e/60+24)%24;return t>=22.5||t<6.5}const cs={cozy:{wander:.6,visit:.6,sit:3,gaze:1.5,chat:1.2,dance:.3,tend:.4,play:.7},curious:{wander:2.2,visit:2,sit:.6,gaze:1,chat:1,dance:.4,tend:.3,play:1.6},sporty:{wander:1.6,visit:.8,sit:.4,gaze:.6,chat:1,dance:1.6,tend:.3,play:2.8},artsy:{wander:1,visit:.8,sit:1,gaze:2,chat:1,dance:1.2,tend:.5,play:1.2},tinkerer:{wander:.8,visit:1.5,sit:.8,gaze:.5,chat:1,dance:.3,tend:1.4,play:.9},dreamy:{wander:.8,visit:.5,sit:1.6,gaze:3,chat:.7,dance:.5,tend:.4,play:1.1},foodie:{wander:.8,visit:1.6,sit:2,gaze:.6,chat:1.6,dance:.6,tend:.4,play:1},gardener:{wander:.8,visit:.6,sit:.8,gaze:.8,chat:.8,dance:.3,tend:3,play:.7},agent:{wander:1,visit:1,sit:1.2,gaze:1,chat:1.5,dance:.4,tend:.6,play:.9}};function je(o,e){return o.length?o[Math.floor(e()*o.length)%o.length]:void 0}function rn(o,e){const t=Object.entries(o),s=t.reduce((n,[,a])=>n+a,0);let i=e()*s;for(const[n,a]of t)if(i-=a,i<=0)return n;return t[t.length-1][0]}const $e=(o,e)=>Math.atan2(e.x-o.x,e.z-o.z),Le=(o,e,t)=>o+(e-o)*t,ls=new Set(["invite","swing","seesaw","slide","tag"]);class cn{constructor(e,t,s=Math.random){this.nav=e,this.places=t,this.random=s}nav;places;random;wishTickets=[];onWishRegister;onWishGiveUp;wishPatience=new Map;robots=new Map;motion={swings:[0,0],seesaw:0};taken=new Map;hour=12;swingRider=[null,null];swingAmp=[0,0];swingPhase=[0,0];seesawRider=[null,null];seesawSeated=[!1,!1];seesawSince=0;slideQueue=[];slideRide=null;tags=new Map;greeted=new Map;helloAfter=new Map;greetAt=0;games=0;clockNow=0;reset(e,t,s,i){this.nav=e,this.places=t;const n=new Set(s.map(r=>r.key));for(const r of[...this.robots.keys()])n.has(r)||this.remove(r,i);const a=new Set([...t.seats.map(r=>r.key),...(t.activities??[]).map(r=>r.key)]);for(const[r,l]of[...this.taken])if(!a.has(r)){this.taken.delete(r);const h=this.robots.get(l);h&&this.replan(h,i)}for(const r of s){const l=this.robots.get(r.key);if(l){l.resident=r;continue}this.robots.set(r.key,this.arrive(r,i))}}arrive(e,t){const s=an(on(e.key)^Math.floor(this.random()*4294967295)),i=this.places.plots.get(e.key),n=this.nav.nearestFree(i?.door??{x:(s()-.5)*8,z:(s()-.5)*8})??{x:0,z:this.places.plaza+1};return{key:e.key,resident:e,x:n.x,z:n.z,y:0,perched:!1,heading:s()*Math.PI*2,pose:"stand",lean:0,stride:0,speed:xt,path:[],bubble:null,gesture:null,mode:{state:"free"},rng:s,plan:{label:"Looking around",goal:null,act:{kind:"look",seconds:1+s()*3},since:t},repathAt:0,chatAfter:t+s()*20,bedtimeShift:Math.round((s()-.5)*80),boredom:.2+s()*.35,boredomRead:e.owner.kind!=="agent",excitedUntil:0}}remove(e,t){const s=this.robots.get(e);s&&this.release(s,t),this.robots.delete(e);for(const i of this.robots.values()){const n=i.plan.act;(n.kind==="chat"||n.kind==="invite")&&n.with===e&&this.replan(i,t)}}setModes(e,t){for(const s of this.robots.values()){if(s.resident.owner.kind!=="agent")continue;const i=e.get(s.key)??{state:"free"},n=s.mode;if(s.mode=i,!s.boredomRead&&e.has(s.key)&&(s.boredomRead=!0,s.boredom=i.state==="free"&&i.idleFor!==void 0?Math.min(.95,Math.max(0,i.idleFor)/Ji):i.state==="free"?s.boredom:0,n.state==="free"&&i.state!=="free")){this.replan(s,t);continue}if(n.state==="free"&&i.state==="working"){this.excite(s,t);continue}n.state!==i.state?this.replan(s,t):n.label!==i.label&&i.state!=="free"&&(s.plan.label=this.overrideLabel(s))}}excite(e,t){const s=e.boredom;this.release(e,t),e.perched=!1,e.excitedUntil=t+4,e.bubble={text:s>.5?"work! ✨":"!",tone:"plain",until:t+2};const i=this.choose(e,t);e.plan={label:"Got work!",goal:null,act:{kind:"cheer",seconds:s>.5?1.6:.8,then:i},since:t}}mood(e){const t=this.robots.get(e);return t?{boredom:t.boredom,excited:t.excitedUntil>this.clockNow}:null}event(e,t,s){const i=this.robots.get(t);if(!(!i||i.mode.state!=="free")){if(this.release(i,s),e==="wish"){const n=i.rng()*Math.PI*2,a={x:this.places.tree.x+Math.sin(n)*2.6,z:this.places.tree.z+Math.cos(n)*2.6};i.plan={label:"Hanging a wish on the tree",goal:a,act:{kind:"wish",seconds:3.5,face:$e(a,this.places.tree)}}}else i.plan={label:"Opening a present",goal:null,act:{kind:"cheer",seconds:4}},i.bubble={text:"🎁",tone:"plain",until:s+4},i.boredom=0,i.excitedUntil=s+4;this.route(i)}}buildHome(e,t){for(const s of this.robots.values()){const i=this.places.plots.get(s.key);if(!i||i.id!==e||s.mode.state!=="free"||s.plan.act.kind==="sleep")continue;this.release(s,t),s.perched=!1;const n=s.rng()*Math.PI*2,a={x:i.center.x+Math.sin(n)*2.4,z:i.center.z+Math.cos(n)*2.4};s.plan={label:"Building our home together",goal:a,act:{kind:"tend",seconds:6+s.rng()*4,face:$e(a,i.center)}},s.bubble={text:"🔨",tone:"plain",until:t+3},s.boredom=Math.max(0,s.boredom-.4),this.route(s)}}landAt(e,t,s){const i=this.robots.get(e);if(!i)return;this.release(i,s),i.x=t.x,i.z=t.z,i.heading=t.face;const n=this.places.plots.get(e);i.plan={label:"Arriving on the island",goal:n?{x:n.door.x,z:n.door.z,face:n.front.face+Math.PI}:null,act:{kind:"cheer",seconds:3}},i.bubble={text:"hi!",tone:"plain",until:s+3},this.route(i)}setWishQueue(e){this.wishTickets=[...e];for(const t of this.wishPatience.keys())e.some(s=>s.id===t)||this.wishPatience.delete(t);for(const t of this.robots.values()){const s=t.plan.act;(s.kind==="wish-queue"||s.kind==="wish-register")&&!e.some(i=>i.id===s.ticket)&&(this.release(t,this.clockNow),t.plan={label:"Wish registered",goal:null,act:{kind:"cheer",seconds:2},since:this.clockNow},t.bubble={text:"✨",tone:"plain",until:this.clockNow+2})}}wishQueue(e){for(const s of this.wishTickets){const i=this.robots.get(s.key);i&&(i.mode.state!=="free"||Ye(this.hour,i.bedtimeShift))&&["wish-queue","wish-register"].includes(i.plan.act.kind)&&(this.wishPatience.delete(s.id),this.replan(i,e))}for(const s of this.wishTickets){const i=this.wishPatience.get(s.id);i?.gaveUp&&e>=i.next&&(i.next=e+8,this.onWishGiveUp?.(s.id))}const t=this.wishTickets.filter(s=>{if(this.wishPatience.get(s.id)?.gaveUp)return!1;const i=this.robots.get(s.key);return i&&i.mode.state==="free"&&!Ye(this.hour,i.bedtimeShift)});for(const[s,i]of t.entries()){const n=this.robots.get(i.key),a=n.plan.act;a.kind==="wish-register"&&a.ticket===i.id||a.kind==="wish-queue"&&a.ticket===i.id&&a.index===s||(this.release(n,e),n.perched=!1,n.plan={label:"Queuing at BOT Society",goal:Mi(s),act:{kind:"wish-queue",ticket:i.id,index:s}},this.route(n))}}useAsset(e,t){const s=this.places.activities?.find(a=>a.key===e);if(!s){const a=this.places.seats.find(h=>h.kind==="seat"&&h.key.startsWith(e+":"));if(!a)return null;const r=this.taken.get(a.key);if(r)return r;const l=[...this.robots.values()].filter(h=>(!t||h.key===t)&&h.mode.state==="free"&&!Ye(this.hour,h.bedtimeShift)&&!this.busyPlaying(h)&&h.plan.act.kind!=="sleep");l.sort((h,m)=>Math.hypot(h.x-a.x,h.z-a.z)-Math.hypot(m.x-a.x,m.z-a.z));for(const h of l){const m=this.nav.path(h,a);if(m)return this.release(h,this.clockNow),this.takeSeat(h,a),h.plan={label:`Sitting on ${a.name}`,goal:a,act:{kind:"sit",seat:a,seconds:25}},h.path=m,h.key}return null}const i=this.taken.get(e);if(i)return!t||t===i?i:null;const n=[...this.robots.values()].filter(a=>(!t||a.key===t)&&a.mode.state==="free"&&!Ye(this.hour,a.bedtimeShift)&&!["sleep","wish-queue","wish-register","interact"].includes(a.plan.act.kind)&&es(a.resident.hobbies,s.activity));n.sort((a,r)=>Math.hypot(a.x-s.x,a.z-s.z)-Math.hypot(r.x-s.x,r.z-s.z));for(const a of n){const r=this.nav.path(a,s);if(r)return this.release(a,this.clockNow),this.taken.set(s.key,a.key),a.perched=!1,a.plan={label:`${{read:"Reading at",paint:"Painting at",garden:"Planting and watering at",perform:"Performing at",play:"Playing at",observe:"Enjoying"}[s.activity]} ${s.name}`,goal:s,act:{kind:"interact",site:s,seconds:s.activity==="perform"?25:14}},a.path=r,a.key}return null}update(e,t,s){this.hour=s,this.clockNow=t;const i=Math.min(e,.1);this.wishQueue(t),this.playground(i,t);for(const n of this.robots.values())this.tick(n,i,t),this.feel(n,i);this.concerts(t),this.greetings(t)}concerts(e){for(const t of this.robots.values()){if(t.mode.state!=="free"||!this.performing(t)||t.path.length)continue;const s=[...this.robots.values()].filter(i=>i.plan.act.kind==="watch"&&i.plan.act.performer===t.key);if(!(s.length>=5))for(const i of this.robots.values()){if(i===t||i.mode.state!=="free"||i.chatAfter>e||i.plan.seek||!["look","gaze","sit"].includes(i.plan.act.kind)||Math.hypot(i.x-t.x,i.z-t.z)>8)continue;const n=t.heading+Math.PI*2*s.length/5,a={x:t.x+Math.sin(n)*2.4,z:t.z+Math.cos(n)*2.4},r=this.nav.path(i,a);if(r&&(this.release(i,e),i.perched=!1,i.plan={label:`Watching ${t.resident.name} perform`,goal:a,act:{kind:"watch",performer:t.key}},i.path=r,s.push(i),s.length>=5))break}}}performing(e){return e.plan.act.kind==="dance"||e.plan.act.kind==="interact"&&e.plan.act.site.activity==="perform"}audience(e){return[...this.robots.values()].filter(t=>t.mode.state==="free"&&!t.path.length&&t.plan.act.kind==="watch"&&t.plan.act.performer===e).length}feel(e,t){const s=e.plan.act.kind;if(e.mode.state==="working"||e.excitedUntil>this.clockNow){e.boredom=Math.max(0,e.boredom-t*.5);return}if(s==="sleep")return;const i=s==="swing"||s==="seesaw"||s==="tag"||s==="dance"||s==="chat"||s==="slide"&&this.slideRide?.key===e.key||s==="cheer";e.boredom=Math.min(1,Math.max(0,e.boredom+(i?-.022222222222222223:Vi)*t))}tick(e,t,s){e.bubble&&e.bubble.until<s&&(e.bubble=null),e.gesture&&e.gesture.until<s&&(e.gesture=null);const i=e.plan;if(i.act.kind==="watch"){const n=this.robots.get(i.act.performer);if(!n||n.mode.state!=="free"||!this.performing(n)||n.path.length){e.chatAfter=s+30,this.replan(e,s);return}}if(i.act.kind==="interact"){const n=i.act.site,a=(this.places.activities??[]).find(r=>r.key===n.key);if(!a||a.activity!==n.activity||Math.hypot(a.x-n.x,a.z-n.z)>.01||Math.abs(a.y-n.y)>.01){this.replan(e,s);return}}if(i.act.kind==="tag"&&i.since!==void 0){this.tagTick(e,i.act.game,t,s);return}if(this.slideRide?.key!==e.key){if(i.seek){const n=this.robots.get(i.seek);if(!n||n.plan.act.kind==="sleep"||n.mode.state!=="free"||this.busyPlaying(n)){this.replan(e,s);return}if(Math.hypot(n.x-e.x,n.z-e.z)<1.5){i.act.kind!=="invite"?this.startChat(e,n,s):i.act.answer==="yes"||i.act.answer!=="no"&&this.accepts(n)?this.startPlay(i.act.game,e,n,s):this.decline(e,n,s);return}if(s>e.repathAt&&(e.repathAt=s+1.2,e.path=this.nav.path(e,n)??[],!e.path.length)){this.replan(e,s);return}}if(e.path.length){this.walk(e,t);return}i.since===void 0&&this.begin(e,s),this.act(e,t,s),e.gesture&&(e.pose==="stand"||e.pose==="talk")&&(e.pose=e.gesture.pose)}}walk(e,t){let s=e.speed*t;for(e.pose="walk",e.perched=!1;s>0&&e.path.length;){const i=e.path[0],n=i.x-e.x,a=i.z-e.z,r=Math.hypot(n,a);if(r<=s){e.x=i.x,e.z=i.z,s-=r,e.stride=(e.stride+r/os)%1,e.path.shift();continue}e.x+=n/r*s,e.z+=a/r*s,e.stride=(e.stride+s/os)%1,this.turn(e,Math.atan2(n,a),t),s=0}}turn(e,t,s){let i=t-e.heading;i=Math.atan2(Math.sin(i),Math.cos(i));const n=en*s;e.heading+=Math.max(-n,Math.min(n,i))}begin(e,t){const s=e.plan;s.since=t,s.goal&&(e.x=s.goal.x,e.z=s.goal.z);const i=s.act,n="seat"in i?i.seat:null;e.perched=!!n,n?(e.x=n.x,e.z=n.z,e.y=n.y,e.heading=n.face):s.goal?.face!==void 0&&(e.heading=s.goal.face),i.kind==="interact"&&(e.heading=i.site.face,e.y=i.site.y,e.perched=i.site.y>.1),i.kind==="seesaw"&&(this.seesawSeated[i.end]=!0,this.seesawSeated[0]&&this.seesawSeated[1]&&this.seesawSince===0&&(this.seesawSince=t)),i.kind==="slide"&&!this.slideQueue.includes(e.key)&&this.slideQueue.push(e.key),i.kind==="chat"&&i.first&&(e.bubble={text:"hi!",tone:"plain",until:t+1.6})}act(e,t,s){const i=e.plan,n=i.act,a=s-(i.since??s),r=h=>a>=h,l=this.places.playground;switch(n.kind){case"wish-queue":{e.y=.15,e.perched=!0,e.pose="stand",this.turn(e,Math.PI,t);let h=this.wishPatience.get(n.ticket);if(h||(h={since:s,next:s+45+e.rng()*35,gaveUp:!1},this.wishPatience.set(n.ticket,h)),n.index>0&&s>=h.next&&(h.next=s+10,e.rng()<.35)){h.gaveUp=!0,h.next=s+8,this.release(e,s),e.plan={label:"Maybe another time",goal:null,act:{kind:"look",seconds:4},since:s},e.bubble={text:"maybe later…",tone:"plain",until:s+4},e.chatAfter=s+30,this.onWishGiveUp?.(n.ticket);return}n.index===0&&a>.5&&(e.plan={label:"Registering a wish at BOT Society",goal:{...ki,face:Math.PI},act:{kind:"wish-register",ticket:n.ticket}},this.route(e));return}case"wish-register":e.y=.15,e.perched=!0,e.pose="register",this.turn(e,Math.PI,t),e.bubble={text:"📝 ✨",tone:"plain",until:s+1},a>=4&&(n.triedAt===void 0||s-n.triedAt>5)&&(n.triedAt=s,this.onWishRegister?.(n.ticket));return;case"interact":{const h=n.site.activity;e.pose=h==="perform"?"dance":h==="observe"?"think":h==="play"?"cheer":h==="read"?"think":"work",e.heading=n.site.face,e.bubble={text:{read:"📖",paint:"🎨",garden:a<5?"🌱":"💧",perform:"🎵",play:"🎮",observe:"✨"}[h],tone:"plain",until:s+1},e.boredom=Math.max(0,e.boredom-t/30),r(n.seconds)&&this.replan(e,s);return}case"look":e.pose="stand",n.face!==void 0&&this.turn(e,n.face,t),this.sigh(e,t,s),r(n.seconds)&&this.replan(e,s);return;case"sit":e.pose="sit",this.sigh(e,t,s),r(e.boredom>.8?Math.min(n.seconds,8):n.seconds)&&this.replan(e,s);return;case"sleep":e.pose="sleep",(!e.bubble||e.bubble.until<s+.5)&&(e.bubble={text:"z",tone:"sleep",until:s+6}),Ye(this.hour,e.bedtimeShift)||this.replan(e,s);return;case"gaze":e.pose=e.perched?"sit":"stand",this.turn(e,n.face,t),this.sigh(e,t,s),r(n.seconds)&&this.replan(e,s);return;case"watch":{const h=this.robots.get(n.performer);if(!h||h.mode.state!=="free"||!this.performing(h)||h.path.length){e.chatAfter=s+30,this.replan(e,s);return}this.turn(e,$e(e,h),t),e.pose=Math.floor(a/2)%3===1?"cheer":"stand",e.boredom=Math.max(0,e.boredom-t/45);return}case"dance":e.pose="dance",e.bubble||(e.bubble={text:"🎵",tone:"plain",until:s+2.5}),r(n.seconds)&&this.replan(e,s);return;case"tend":e.pose="think",this.turn(e,n.face,t),r(n.seconds)&&this.replan(e,s);return;case"chat":{const h=this.robots.get(n.with);if(!h||r(n.seconds)){if(e.chatAfter=s+25+e.rng()*40,h&&n.first&&l&&this.likesToPlay(e)&&e.rng()<.4&&h.plan.act.kind==="chat"){e.bubble={text:"wanna play?",tone:"plain",until:s+1.8},this.startPlay(je(this.jointGames(),e.rng)??"tag",e,h,s);return}this.replan(e,s);return}this.turn(e,$e(e,h),t);const m=Math.floor(a/1.8)%2===(n.first?0:1);e.pose=m?"talk":"stand",m&&a>1.6&&(!e.bubble||e.bubble.until<s)&&(e.bubble={text:this.chatLine(e,h),tone:"plain",until:s+1.6});return}case"invite":this.replan(e,s);return;case"sob":{if(e.pose="sob",e.bubble||(e.bubble={text:Math.floor(a/1.6)%2?"sob…":"😭",tone:"plain",until:s+1.5}),!r(n.seconds))return;const h=n.then==="ask"?He(this.partners(e,30).filter(m=>m.key!==n.from),e,e.rng):null;h?this.invite(e.key,h.key,je(this.jointGames(),e.rng)??"tag",s):this.replan(e,s);return}case"swing":{if(!l){this.replan(e,s);return}const h=l.swings[n.swing];this.swingAmp[n.swing]=Math.min(.62,this.swingAmp[n.swing]+t*.07);const m=this.motion.swings[n.swing],p=Qi(h,m);e.perched=!0,e.x=p.x,e.z=p.z,e.y=p.y,e.heading=p.face,e.pose="swing",e.lean=m,!e.bubble&&e.rng()<t*.25&&(e.bubble={text:je(["wheee!","😄","✨","higher!"],e.rng),tone:"plain",until:s+1.5}),r(n.seconds)&&this.replan(e,s);return}case"seesaw":{if(!l){this.replan(e,s);return}const h=Xi(l.seesaw,n.end,this.motion.seesaw);e.perched=!0,e.x=h.x,e.z=h.z,e.y=h.y,e.heading=h.face,e.pose="ride";const m=this.seesawRider[n.end===0?1:0];if(!(this.seesawSeated[0]&&this.seesawSeated[1])){if(e.bubble||(e.bubble={text:"🙋",tone:"plain",until:s+2.2}),!m&&a>2&&s>=(n.askAt??0)){n.askAt=s+3;const c=He(this.partners(e,40).filter(d=>!n.asked?.includes(d.key)),e,e.rng);if(c)if((n.asked??=[]).push(c.key),this.accepts(c)){if(this.release(c,s),c.perched=!1,c.plan=this.seesawPlan(c,n.end===0?1:0,e.resident.name),this.route(c),c.plan.act.kind==="seesaw"){c.bubble={text:"coming!",tone:"plain",until:s+2.2},e.plan.label=`On the seesaw with ${c.resident.name}`;return}}else c.bubble={text:"maybe later",tone:"plain",until:s+2.2}}!m&&a>16&&this.sob(e,s,"nobody came to play","leave");return}!e.bubble&&e.rng()<t*.3&&(e.bubble={text:je(["haha!","up!","😄","🎵","whoa!"],e.rng),tone:"plain",until:s+1.4}),s-this.seesawSince>n.seconds&&this.replan(e,s);return}case"slide":{e.pose="stand",l&&this.turn(e,l.slide.face,t),a>40&&this.replan(e,s);return}case"tag":return;case"work":e.pose="work",(!e.bubble||e.bubble.until<s+.5)&&(e.bubble={text:"…",tone:"work",until:s+4});return;case"wait":e.pose="raise",this.turn(e,n.face,t),(!e.bubble||e.bubble.until<s+.5)&&(e.bubble={text:"?",tone:"decide",until:s+4});return;case"trouble":e.pose="think",(!e.bubble||e.bubble.until<s+.5)&&(e.bubble={text:"!",tone:"danger",until:s+4});return;case"wish":e.pose=a<n.seconds*.6?"raise":"cheer",this.turn(e,n.face,t),r(n.seconds)&&this.replan(e,s);return;case"cheer":if(e.pose="cheer",!r(n.seconds))return;n.then?(e.plan=n.then,e.speed=e.excitedUntil>s?1.6:xt,this.route(e)):this.replan(e,s);return}}sigh(e,t,s){e.boredom<.72||e.bubble||e.rng()>t*.08||(e.bubble={text:je(["🥱","so bored…","hmm…","anyone?"],e.rng),tone:"plain",until:s+2})}chatLine(e,t){const s=e.rng,i=t.resident.look.worn;return i.head&&s()<.25?"nice hat!":i.back&&s()<.2?"cool backpack!":t.resident.owner.kind==="agent"&&s()<.15?"busy day?":this.likesToPlay(e)&&s()<.12?"wanna play?":je(nn,s)??"😄"}release(e,t){for(const[i,n]of[...this.taken])n===e.key&&this.taken.delete(i);this.swingRider=this.swingRider.map(i=>i===e.key?null:i);for(const i of[0,1])this.seesawRider[i]===e.key&&(this.seesawRider[i]=null,this.seesawSeated[i]=!1);this.slideQueue=this.slideQueue.filter(i=>i!==e.key),this.slideRide?.key===e.key&&(this.slideRide=null);const s=e.plan.act;s.kind==="tag"&&this.endTag(s.game,t,e.key),e.path=[],e.plan.seek=void 0,e.speed=xt,e.lean=0,e.perched&&!("seat"in s&&s.seat)&&(e.perched=!1)}replan(e,t){this.release(e,t),e.perched=!1,e.plan=this.choose(e,t),this.route(e)}route(e){const t=e.plan;if(t.since=void 0,e.path=[],t.seek){e.repathAt=0;return}if(!t.goal)return;const s={x:e.x,z:e.z};if(Math.hypot(t.goal.x-s.x,t.goal.z-s.z)<.05)return;const i=this.nav.path(s,t.goal);if(i){e.path=i;return}if("seat"in t.act&&t.act.seat||ls.has(t.act.kind)||t.act.kind==="wish-queue"||t.act.kind==="wish-register"){this.release(e,0),e.plan={label:"Looking around",goal:null,act:{kind:"look",seconds:2+e.rng()*3}};return}t.goal=null}overrideLabel(e){const t=e.mode.label;switch(e.mode.state){case"working":return t?`Working · ${t}`:"Working";case"needs_you":return t?`Waiting for you · ${t}`:"Waiting for you";case"failed":return t?`Stuck · ${t}`:"Something went wrong";default:return"Looking around"}}ownSeat(e,t){const s=this.places.plots.get(e.key);return s?this.places.seats.find(i=>i.plot===s.id&&i.kind===t&&(!i.owner||i.owner===e.key)&&!this.taken.has(i.key))??null:null}takeSeat(e,t){return t&&this.taken.set(t.key,e.key),t}likesToPlay(e){return cs[e.resident.trait??"agent"].play>=.9}choose(e,t){const s=e.rng,i=this.places.plots.get(e.key);switch(e.mode.state){case"working":{const d=this.takeSeat(e,this.ownSeat(e,"desk")),g=d??(i?i.center:null);return{label:this.overrideLabel(e),goal:g&&{x:g.x,z:g.z},act:{kind:"work",seat:d}}}case"needs_you":return{label:this.overrideLabel(e),goal:i?{x:i.front.x,z:i.front.z,face:i.front.face}:null,act:{kind:"wait",face:i?.front.face??e.heading}};case"failed":{const d=this.takeSeat(e,this.ownSeat(e,"desk")),g=d??(i?i.center:null);return{label:this.overrideLabel(e),goal:g&&{x:g.x,z:g.z},act:{kind:"trouble",seat:d}}}}if(Ye(this.hour,e.bedtimeShift)){const d=this.takeSeat(e,this.ownSeat(e,"bed")??this.ownSeat(e,"seat")),g=d??i?.center??null;return{label:"Asleep",goal:g&&{x:g.x,z:g.z},act:{kind:"sleep",seat:d}}}const n=(this.places.activities??[]).filter(d=>!this.taken.has(d.key)&&es(e.resident.hobbies,d.activity));if(n.length&&s()<.4){const d=He(n,e,s);if(d&&this.nav.path(e,d))return this.taken.set(d.key,e.key),{label:`${d.activity==="garden"?"Planting and watering":"Enjoying"} ${d.name}`,goal:d,act:{kind:"interact",site:d,seconds:d.activity==="perform"?25:14}}}const a={...cs[e.resident.trait??"agent"]},r=e.boredom;r>.5&&(a.play*=1+r*3,a.chat*=1+r*2,a.dance*=1+r,a.sit*=.5,a.gaze*=.6),!e.resident.hobbies?.includes("gardening")&&e.resident.trait!=="gardener"&&e.resident.trait!=="tinkerer"&&(a.tend=0);const l=this.freeSeats();switch(l.length||(a.sit=0),(t<e.chatAfter||this.partners(e).length===0)&&(a.chat=0),this.places.playground||(a.play=0),rn(a,s)){case"play":{const d=this.choosePlay(e,t);if(d)return d;break}case"sit":{const d=this.takeSeat(e,He(l,e,s));if(!d)break;return{label:d.plot?`Sitting on ${d.name}`:`Resting on ${d.name}`,goal:{x:d.x,z:d.z},act:{kind:"sit",seat:d,seconds:12+s()*30}}}case"gaze":{const d=s()*Math.PI*2,g=this.places.radius-2.2,j={x:Math.sin(d)*g,z:Math.cos(d)*g};return{label:"Watching the sea",goal:j,act:{kind:"gaze",seconds:10+s()*18,face:Math.atan2(j.x,j.z)}}}case"visit":{const d=[...this.places.plots.entries()].filter(([j])=>j!==e.key),[,g]=je(d,s)??[];if(!g)break;return{label:"Visiting a neighbour",goal:{x:g.front.x,z:g.front.z},act:{kind:"look",seconds:4+s()*6,face:g.front.face+Math.PI}}}case"chat":{const d=He(this.partners(e),e,s);if(!d)break;return{label:`Going to see ${d.resident.name}`,goal:null,seek:d.key,act:{kind:"look",seconds:2}}}case"dance":{const d=s()*Math.PI*2,g=2.6+s()*1.2;return{label:"Dancing on the plaza",goal:{x:Math.sin(d)*g,z:Math.cos(d)*g},act:{kind:"dance",seconds:18+s()*10}}}case"tend":{const d=i?.center??{x:0,z:0},g={x:d.x+(s()-.5)*6,z:d.z+(s()-.5)*6};return{label:e.resident.trait==="tinkerer"?"Tinkering":"Tending the garden",goal:g,act:{kind:"tend",seconds:6+s()*8,face:s()*Math.PI*2}}}}const m=i&&s()<.55,p=m?i.center:{x:0,z:0},c=m?6:this.places.radius-4;for(let d=0;d<6;d++){const g=s()*Math.PI*2,j=Math.sqrt(s())*c,b={x:p.x+Math.sin(g)*j,z:p.z+Math.cos(g)*j};if(!(Math.hypot(b.x,b.z)>this.places.radius-2)&&this.nav.isFree(b))return{label:"Exploring",goal:b,act:{kind:"look",seconds:2+s()*5}}}return{label:"Looking around",goal:null,act:{kind:"look",seconds:3}}}freeSeats(){return this.places.seats.filter(e=>e.kind==="seat"&&!this.taken.has(e.key))}busyPlaying(e){return ls.has(e.plan.act.kind)||["interact","wish-queue","wish-register"].includes(e.plan.act.kind)||this.slideQueue.includes(e.key)}partners(e,t=18){return[...this.robots.values()].filter(s=>s!==e&&s.mode.state==="free"&&s.plan.act.kind!=="sleep"&&s.plan.act.kind!=="chat"&&!s.plan.seek&&!this.busyPlaying(s)&&Math.hypot(s.x-e.x,s.z-e.z)<t)}startChat(e,t,s){const i=7+e.rng()*9;for(const[n,a,r]of[[e,t,!0],[t,e,!1]])this.release(n,s),n.perched=!1,n.plan={label:`Chatting with ${a.resident.name}`,goal:null,act:{kind:"chat",with:a.key,seconds:i,first:r},since:s},r&&(n.bubble={text:"hi!",tone:"plain",until:s+1.6})}greetings(e){if(e<this.greetAt)return;this.greetAt=e+1.2;const t=[...this.robots.values()].filter(s=>s.plan.act.kind!=="sleep"&&!s.perched&&s.plan.act.kind!=="work"&&s.plan.act.kind!=="tag"&&s.plan.act.kind!=="sob"&&this.slideRide?.key!==s.key);for(let s=0;s<t.length;s++)for(let i=s+1;i<t.length;i++){const n=t[s],a=t[i];if(e<(this.helloAfter.get(n.key)??0)||e<(this.helloAfter.get(a.key)??0)||n.bubble||a.bubble||n.plan.seek||a.plan.seek||n.plan.act.kind==="chat"||a.plan.act.kind==="chat"||Math.hypot(n.x-a.x,n.z-a.z)>tn)continue;const r=n.key<a.key?`${n.key}|${a.key}`:`${a.key}|${n.key}`;if(!(e-(this.greeted.get(r)??-1/0)<sn)){this.greeted.set(r,e),this.helloAfter.set(n.key,e+rs),this.helloAfter.set(a.key,e+rs);for(const[l,h]of[[n,a],[a,n]])l.plan.act.kind!=="chat"&&((!l.bubble||l.bubble.tone==="plain")&&(l.bubble={text:l.rng()<.75?"hi!":"👋",tone:"plain",until:e+1.5}),l.path.length||(l.gesture={pose:"wave",until:e+1.4},l.heading=$e(l,h)))}}}jointGames(){const e=["tag"];return this.places.playground&&(!this.seesawRider[0]&&!this.seesawRider[1]&&e.push("seesaw","seesaw"),!this.swingRider[0]&&!this.swingRider[1]&&e.push("swings"),this.slideQueue.length<2&&!this.slideRide&&e.push("slide")),e}choosePlay(e,t){if(!this.places.playground)return null;const i=e.rng;for(const l of[0,1]){const h=l===0?1:0;if(!this.seesawRider[l]&&this.seesawRider[h]&&this.seesawSeated[h]&&i()<.8)return this.seesawPlan(e,l,this.robots.get(this.seesawRider[h])?.resident.name)}const n=this.partners(e,30);if(n.length&&t>=e.chatAfter&&i()<.6){const l=He(n,e,i);return{label:`Asking ${l.resident.name} to play`,goal:null,seek:l.key,act:{kind:"invite",game:je(this.jointGames(),i)??"tag",with:l.key}}}const a=[],r=this.swingRider.findIndex(l=>!l);return r>=0&&a.push(()=>this.swingPlan(e,r)),this.slideQueue.length<3&&a.push(()=>this.slidePlan(2+Math.floor(i()*3))),!this.seesawRider[0]&&!this.seesawRider[1]&&a.push(()=>this.seesawPlan(e,i()<.5?0:1)),je(a,i)?.()??null}swingPlan(e,t,s){const i=this.places.playground;this.swingRider[t]=e.key;const n=i.swings[t].stand;return{label:s?`Swinging with ${s}`:"On the swings",goal:{x:n.x,z:n.z,face:i.swings[t].face},act:{kind:"swing",swing:t,seconds:14+e.rng()*16}}}seesawPlan(e,t,s){const i=this.places.playground;this.seesawRider[t]=e.key;const n=i.seesaw.stand[t];return{label:s?`On the seesaw with ${s}`:"Waiting for a friend on the seesaw",goal:{x:n.x,z:n.z},act:{kind:"seesaw",end:t,seconds:14+e.rng()*12}}}slidePlan(e,t){const s=this.places.playground,i=this.slideQueue.length+(this.slideRide?1:0),n={x:s.slide.queue.x+s.slide.back.x*i*.8,z:s.slide.queue.z+s.slide.back.z*i*.8};return{label:t?`Taking turns on the slide with ${t}`:"Playing on the slide",goal:{...n,face:s.slide.face},act:{kind:"slide",runs:e}}}invite(e,t,s,i,n={}){const a=this.robots.get(e),r=this.robots.get(t);return!a||!r||a.mode.state!=="free"||r.mode.state!=="free"?!1:(this.release(a,i),a.perched=!1,a.plan={label:`Asking ${r.resident.name} to play`,goal:null,seek:r.key,act:{kind:"invite",game:s,with:r.key,...n.answer?{answer:n.answer}:{}}},this.route(a),!0)}waitOnSeesaw(e,t){const s=this.robots.get(e);return!s||!this.places.playground||this.seesawRider[0]||this.seesawRider[1]?!1:(this.release(s,t),s.perched=!1,s.plan=this.seesawPlan(s,0),this.route(s),!0)}accepts(e){const t=e.resident.trait;let s=.68+e.boredom*.3;return t==="sporty"&&(s+=.15),t==="curious"&&(s+=.08),t==="cozy"&&(s-=.22),t==="dreamy"&&(s-=.15),e.plan.act.kind==="sit"&&(s-=.15),e.rng()<Math.min(.98,Math.max(.1,s))}decline(e,t,s){t.bubble={text:je(["not now 😅","maybe later","sorry!"],t.rng),tone:"plain",until:s+2.2},t.path.length||(t.heading=$e(t,e),t.gesture={pose:"think",until:s+1.6}),this.sob(e,s,`${t.resident.name} said no`,e.rng()<.5?"ask":"leave",t.key)}sob(e,t,s,i,n){this.release(e,t),e.perched=!1,e.boredom=Math.min(1,e.boredom+.12),e.bubble={text:"😭",tone:"plain",until:t+1.6},e.plan={label:`Crying · ${s}`,goal:null,act:{kind:"sob",seconds:3.5+e.rng()*2,then:i,...n?{from:n}:{}},since:t}}startPlay(e,t,s,i){this.release(t,i),this.release(s,i),t.perched=!1,s.perched=!1,t.bubble={text:"wanna play?",tone:"plain",until:i+1.6},s.bubble={text:"yes!",tone:"plain",until:i+1.6},t.chatAfter=s.chatAfter=i+30+t.rng()*30;const a=this.jointGames().includes(e)?e:"tag",r=[t.resident.name,s.resident.name];if(a==="seesaw")t.plan=this.seesawPlan(t,0,r[1]),s.plan=this.seesawPlan(s,1,r[0]);else if(a==="swings")t.plan=this.swingPlan(t,0,r[1]),s.plan=this.swingPlan(s,1,r[0]);else if(a==="slide")t.plan=this.slidePlan(3,r[1]),s.plan=this.slidePlan(3,r[0]);else{const l=`tag-${++this.games}`,h=t.rng()<.5?t.key:s.key;this.tags.set(l,{id:l,players:[t.key,s.key],it:h,until:i+22+t.rng()*14,center:{x:(t.x+s.x)/2,z:(t.z+s.z)/2},pausedUntil:i+1.6});for(const[m,p]of[[t,s],[s,t]])m.plan={label:`Playing tag with ${p.resident.name}`,goal:null,act:{kind:"tag",game:l},since:i};return}this.route(t),this.route(s)}tagTick(e,t,s,i){const n=this.tags.get(t),a=n?.players.find(l=>l!==e.key),r=a?this.robots.get(a):void 0;if(!n||!r||r.plan.act.kind!=="tag"){this.replan(e,i);return}if(i>n.until){this.tags.delete(t);for(const l of[e,r])this.release(l,i),l.plan={label:"Had fun playing tag",goal:null,act:{kind:"cheer",seconds:2},since:i},l.bubble={text:"😆",tone:"plain",until:i+2};return}if(n.it===e.key){if(e.speed=1.5,i<n.pausedUntil){e.pose="think",this.turn(e,$e(e,r),s);return}if(Math.hypot(r.x-e.x,r.z-e.z)<.9){n.it=r.key,n.pausedUntil=i+1.5,e.bubble={text:"tag!",tone:"plain",until:i+1.4},r.bubble={text:"😆",tone:"plain",until:i+1.4},e.path=[],r.path=[];return}(i>e.repathAt||!e.path.length)&&(e.repathAt=i+.45,e.path=this.nav.path(e,r)??[])}else if(e.speed=1.32,!e.path.length){const l=this.robots.get(n.it);let h=null,m=-1;for(let p=0;p<6;p++){const c=e.rng()*Math.PI*2,d=2+e.rng()*6,g={x:n.center.x+Math.sin(c)*d,z:n.center.z+Math.cos(c)*d};if(!this.nav.isFree(g)||Math.hypot(g.x,g.z)>this.places.radius-3)continue;const j=Math.hypot(g.x-l.x,g.z-l.z);j>m&&(h=g,m=j)}e.path=h?this.nav.path(e,h)??[]:[]}e.path.length?this.walk(e,s):e.pose="stand"}endTag(e,t,s){const i=this.tags.get(e);if(i){this.tags.delete(e);for(const n of i.players){if(n===s)continue;const a=this.robots.get(n);a&&a.plan.act.kind==="tag"&&(a.path=[],a.speed=xt,a.plan={label:"Looking around",goal:null,act:{kind:"look",seconds:1.5},since:t})}}}playground(e,t){const s=this.places.playground;for(let p=0;p<2;p++){const c=this.swingRider[p]?this.robots.get(this.swingRider[p]):void 0;c?.plan.act.kind==="swing"&&c.plan.since!==void 0||(this.swingAmp[p]=Math.max(0,this.swingAmp[p]-e*.12)),this.swingPhase[p]+=e*2.4,this.motion.swings[p]=this.swingAmp[p]*Math.sin(this.swingPhase[p])}const i=this.seesawSeated[0]&&this.seesawSeated[1];i&&this.seesawSince===0&&(this.seesawSince=t),i||(this.seesawSince=0);const n=i?.24*Math.sin(1.9*(t-this.seesawSince)):this.seesawSeated[0]?.24:this.seesawSeated[1]?-.24:0;if(this.motion.seesaw+=(n-this.motion.seesaw)*Math.min(1,e*(i?12:3)),!s)return;if(!this.slideRide){const p=this.slideQueue[0]?this.robots.get(this.slideQueue[0]):void 0;p&&p.plan.act.kind==="slide"&&p.plan.since!==void 0?(this.slideQueue.shift(),this.slideRide={key:p.key,phase:"approach",since:t,from:{x:p.x,z:p.z}}):this.slideQueue[0]&&!p&&this.slideQueue.shift()}const a=this.slideRide;if(!a)return;const r=this.robots.get(a.key);if(!r||r.plan.act.kind!=="slide"){this.slideRide=null;return}const l=s.slide,h=t-a.since,m=p=>{a.phase=p,a.since=t};switch(a.phase){case"approach":{const p=Math.min(1,h/.6);r.x=Le(a.from.x,l.foot.x,p),r.z=Le(a.from.z,l.foot.z,p),r.perched=!1,r.pose="walk",r.stride=(r.stride+e*1.4)%1,r.heading=l.face,p>=1&&m("climb");return}case"climb":{const p=Math.min(1,h/1.8);r.perched=!0,r.x=Le(l.foot.x,l.top.x,p),r.z=Le(l.foot.z,l.top.z,p),r.y=Le(l.top.y-1.35,l.top.y,p),r.pose="climb",r.stride=(r.stride+e*1.2)%1,r.heading=l.face,p>=1&&m("perch");return}case"perch":r.pose="stand",r.heading=l.face,h>.5&&(r.bubble={text:je(["wheee!","here I go!","😆"],r.rng),tone:"plain",until:t+1.6},m("ride"));return;case"ride":{const p=Math.min(1,h/1.1),c=p*p;r.x=Le(l.from.x,l.to.x,c),r.z=Le(l.from.z,l.to.z,c),r.y=Le(l.from.y,l.to.y,c),r.pose="ride",r.heading=l.face,p>=1&&m("hop");return}case"hop":{const p=Math.min(1,h/.45);if(r.x=Le(l.to.x,l.exit.x,p),r.z=Le(l.to.z,l.exit.z,p),r.perched=!1,r.pose="cheer",p<1)return;this.slideRide=null;const c=r.plan.act;if(c.runs-=1,c.runs>0){const d=this.slidePlan(c.runs);r.plan={...d,label:r.plan.label},this.route(r)}else r.bubble={text:"😄",tone:"plain",until:t+1.5},this.replan(r,t);return}}}describe(e){const t=this.robots.get(e);if(!t)return null;const s=t.plan.act;if(s.kind==="slide"){const i=this.slideRide?.key===e?this.slideRide:null;if(i?.phase==="climb"||i?.phase==="approach")return"Climbing up the slide";if(i?.phase==="perch")return"At the top of the slide";if(i?.phase==="ride")return"Going down the slide!";if(t.plan.since!==void 0){const n=this.slideQueue.indexOf(e)+(this.slideRide?1:0);return n>0?`Waiting in line for the slide · ${n} ahead`:"Next on the slide"}}if(s.kind==="tag"){const i=this.tags.get(s.game),n=i?.players.find(r=>r!==e),a=n?this.robots.get(n)?.resident.name:void 0;if(i&&a)return i.it===e?`Playing tag with ${a} · it's ${t.resident.name}'s turn to chase`:`Playing tag with ${a} · running away`}return s.kind==="seesaw"&&t.plan.since!==void 0&&!(this.seesawSeated[0]&&this.seesawSeated[1])?"Waiting for a friend on the seesaw":t.path.length&&s.kind==="sit"?`Going to sit on ${s.seat.name}`:t.plan.label}said(e){const t=this.robots.get(e)?.bubble;return t&&t.tone==="plain"?t.text:null}}function He(o,e,t){if(!o.length)return null;const s=[...o].sort((n,a)=>Math.hypot(n.x-e.x,n.z-e.z)-Math.hypot(a.x-e.x,a.z-e.z)),i=Math.min(s.length,3);return s[Math.floor(t()*i)]??s[0]}const rt=-.18;function kt(o,e,t){const s=(g,j)=>{let b=Math.imul(g,374761393)^Math.imul(j,668265263)^Math.imul(t,2246822519);return b=Math.imul(b^b>>>13,1274126177),((b^b>>>16)>>>0)/4294967296},i=Math.floor(o),n=Math.floor(e),a=o-i,r=e-n,l=a*a*(3-2*a),h=r*r*(3-2*r),m=s(i,n),p=s(i+1,n),c=s(i,n+1),d=s(i+1,n+1);return m+(p-m)*l+(c-m)*h+(m-p-c+d)*l*h}const et=(o,e,t)=>{const s=Math.min(1,Math.max(0,(t-o)/(e-o)));return s*s*(3-2*s)};function Qe(o,e){return o<=e-5?0:o<=e+.6?-.32*et(e-5,e+.6,o):-.32-2.4*et(e+.6,e+12,o)}const Ue={grass:new H("#8fd9a8"),grassDark:new H("#53b781"),sand:new H("#f7c9d4"),wetSand:new H("#eeb3c3"),deep:new H("#c2abd2")};function ln(o,e,t){const s=o+14,i=128,n=[0];for(let k=.9;k<s;k+=k<o-6?1.6:.8)n.push(k);n.push(s);const a=[],r=[],l=[],h=new H("#b5e4ce"),m=new H("#efd0dc"),p=new H("#fff0ec"),c=new H("#e8c9dc"),d=(k,f)=>{const E=k>o-7?(kt(Math.cos(f)*3,Math.sin(f)*3,e)-.5)*2.2:0,z=k+E*et(o-7,o,k),_=Math.sin(f)*z,L=Math.cos(f)*z,A=Qe(k,o)+(k>o-5&&k<o+8?(kt(_*.4,L*.4,e+7)-.5)*.12:0),S=new H,N=new H;if(k<o-5.2){const $=kt(_*.15,L*.15,e)*.7;S.copy(Ue.grass).lerp(Ue.grassDark,$),N.copy(h).lerp(m,$)}else if(k<o+.4){const $=et(o-1.5,o+.4,k);S.copy(Ue.sand).lerp(Ue.wetSand,$),N.copy(p).lerp(c,$)}else{const $=et(o+.4,o+8,k);S.copy(Ue.wetSand).lerp(Ue.deep,$),N.copy(c).lerp(Ue.deep,$)}return{p:[_,A,L],c:[S.r,S.g,S.b],n:[N.r,N.g,N.b]}};for(let k=0;k<n.length-1;k++)for(let f=0;f<i;f++){const E=f/i*Math.PI*2,z=(f+1)/i*Math.PI*2,_=d(n[k],E),L=d(n[k],z),A=d(n[k+1],E),S=d(n[k+1],z);for(const N of k===0?[[_,A,S]]:[[_,A,S],[_,S,L]]){const $=N[0].c;for(const W of N)a.push(...W.p),r.push(...$),l.push(...N[0].n)}}const g=new ks;g.setAttribute("position",new bt(new Float32Array(a),3)),g.setAttribute("color",new bt(new Float32Array(r),3)),g.setAttribute("nightColor",new bt(new Float32Array(l),3)),g.computeVertexNormals();const j=new ze({vertexColors:!0,flatShading:!0,roughness:.95});j.onBeforeCompile=k=>{k.uniforms.uCandyNight=t,k.vertexShader=k.vertexShader.replace("#include <common>",`#include <common>
|
|
10
|
+
attribute vec3 nightColor;
|
|
11
|
+
uniform float uCandyNight;`).replace("#include <color_vertex>",`#include <color_vertex>
|
|
12
|
+
vColor.rgb = mix(vColor.rgb, nightColor, uCandyNight);`)};const b=new O(g,j);return b.receiveShadow=!0,b.name="terrain",b}function hn(o){const e=new Ot(900,900,150,150);e.rotateX(-Math.PI/2);const t=new ze({color:"#62cfc8",flatShading:!0,roughness:.32,metalness:.08,transparent:!0,opacity:.88}),s={value:0};t.onBeforeCompile=n=>{n.uniforms.uTime=s,n.uniforms.uShore={value:o},n.vertexShader=n.vertexShader.replace("#include <common>",`#include <common>
|
|
13
|
+
uniform float uTime;
|
|
14
|
+
uniform float uShore;`).replace("#include <begin_vertex>",`#include <begin_vertex>
|
|
15
|
+
float away = smoothstep(uShore + 1.0, uShore + 16.0, length(position.xz));
|
|
16
|
+
transformed.y += away * (sin(position.x * 0.17 + uTime * 0.8) * 0.12
|
|
17
|
+
+ cos(position.z * 0.14 + uTime * 0.65) * 0.1
|
|
18
|
+
+ sin((position.x + position.z) * 0.33 + uTime * 1.5) * 0.04);`)};const i=new O(e,t);return i.position.y=rt,i.name="sea",{mesh:i,material:t,time:s}}function dn(){const o=new H("#b9b5ef"),e=new H("#ffe1eb"),t=new bs({side:Js,depthWrite:!1,fog:!1,uniforms:{top:{value:o},horizon:{value:e}},vertexShader:"varying vec3 vDir; void main() { vDir = normalize(position); gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0); }",fragmentShader:`uniform vec3 top; uniform vec3 horizon; varying vec3 vDir;
|
|
19
|
+
void main() { float h = clamp(vDir.y * 1.6 + 0.05, 0.0, 1.0); gl_FragColor = vec4(mix(horizon, top, pow(h, 0.7)), 1.0); }`}),s=new O(new lt(600,24,12),t);return s.name="sky",s.renderOrder=-1,{mesh:s,top:o,horizon:e}}function un(o){if(typeof document>"u")return null;const e=document.createElement("canvas");e.width=256,e.height=96;const t=e.getContext("2d");if(!t)return null;t.fillStyle="#f6ead2",t.fillRect(0,0,256,96),t.fillStyle="#5a3e2b",t.textAlign="center",t.textBaseline="middle";let s=40;const i=()=>`600 ${s}px Inter, system-ui, sans-serif`;for(t.font=i();t.measureText(o).width>228&&s>22;)s-=2,t.font=i();let n=o;for(;t.measureText(n).width>228&&n.length>2;)n=`${n.slice(0,-2)}…`;t.fillText(n,128,50);const a=new Nt(e);return a.colorSpace=Ms,a}function pn(o){const{radius:e,seed:t,plots:s}=o,i=new he;i.name="scenery";const n=[],a=u=>(n.push(u),u),r={value:0},l=ln(e,t,r);l.material.polygonOffset=!0,l.material.polygonOffsetUnits=2,a(l.geometry),a(l.material),i.add(l);const h=hn(e);a(h.mesh.geometry),a(h.material),i.add(h.mesh);const m=a(new ee({color:"#ffffff",transparent:!0,opacity:.32,depthWrite:!1})),p=new O(a(new zt(e-.2,e+1.4,128)),m);p.rotation.x=-Math.PI/2,p.position.y=rt+.06,i.add(p);const c=dn();a(c.mesh.geometry),a(c.mesh.material),i.add(c.mesh);const d=[],g=(u,w,P=.95)=>{const M=a(G(u,P));return d.push({material:M,day:new H(u),night:new H(w)}),M},j={wood:a(G("#ce9c78")),darkWood:a(G("#77505a")),leaf:a(G("#e9a9cb")),leafLight:a(G("#bca6e0")),pine:a(G("#daa0c4")),pineLight:a(G("#f3bfd8")),trunk:a(G("#fff0df")),rock:a(G("#b7a6e6",.9)),metal:a(G("#785c84",.5,.5)),white:a(G("#fff6ef",.7)),red:a(G("#e58da9",.7)),blue:a(G("#a3a5df",.7)),stone:a(G("#ead3df",.9)),paper:a(G("#fbf7ee",.8)),lamp:a(new ee({color:"#ffe3a8"})),nightLamp:a(new ee({color:"#ffe3a8",transparent:!0,opacity:0,depthWrite:!1})),nightMetal:a(new ze({color:"#785c84",roughness:.5,metalness:.5,transparent:!0,opacity:0})),star:a(new ee({color:"#ffd56b"})),seal:a(new ee({color:"#e0584f"})),light0:a(new ee({color:"#ffcf7a"})),light1:a(new ee({color:"#ff9f8a"})),light2:a(new ee({color:"#9fe0ff"})),light3:a(new ee({color:"#c8a8ff"})),path:g("#edb0c4","#fff0e7"),plaza:g("#f1bdd3","#f8dce8",.9),plazaInner:g("#df9fc5","#edd1e2",.9),tileAgent:g("#80d9a6","#b8e1cd"),tileBot:g("#f1b2cf","#ecd1de"),tileEmpty:g("#9bd9b1","#cce8da"),tileLemon:g("#edda8b","#cce8da"),tileLilac:g("#c7a5e2","#cce8da"),tileEdge:g("#dd85aa","#a4caba"),cocoa:a(G("#80525b",.32)),caramel:a(G("#e6bb8c")),mint:a(G("#a4ddcf")),playTile:a(G("#f4d8e9",.95)),lemon:a(G("#efd17e"))};for(const[u,w]of[["tileEdge",-1],["plaza",-1],["plazaInner",-2],["tileAgent",-2],["tileBot",-2],["tileEmpty",-2],["tileLemon",-2],["tileLilac",-2],["playTile",-2]]){const P=j[u];P.polygonOffset=!0,P.polygonOffsetFactor=w,P.polygonOffsetUnits=w*2}const b=new ot(j),k=a(new Dt(1,1,1,2,.12)),f=a(new Xe(.5,.5,1,12)),E=a(new Xt(.5,1,9)),z=a(new Vs(.5,1)),_=a(new Xt(.5,1,5)),L=a(new Qt(1.15,.38,6,24)),A=[],S=[],N=new _s,$=[],W=new ot(j);n.push(N),i.add(N.group);const X=a(new Xe(1,1,1,6)),Y=a(new Xe(.97,1,1,6)),F=Math.max(2,...s.map(u=>u.ring)),V=new Map(s.map(u=>[`${u.q},${u.r}`,u])),ve=`${yt.q},${yt.r}`;for(let u=0;u<=F;u++)for(const[w,P]of Mt(u)){const M=Ve(w,P);if(b.add("path",X,M.x,.01,M.z,{sx:Pe-.02,sy:.02,sz:Pe-.02}),u===0)continue;const v=V.get(`${w},${P}`),R=`${w},${P}`===ve?"playTile":v?v.owner.kind==="agent"?"tileAgent":"tileBot":["tileEmpty","tileLemon","tileLilac"][((w-P)%3+3)%3];b.add("tileEdge",X,M.x,ce/2-.005,M.z,{sx:Re,sy:ce-.01,sz:Re}),b.add(R,Y,M.x,ce/2+.005,M.z,{sx:Re-.08,sy:ce-.01,sz:Re-.08})}b.add("plaza",Y,0,ce/2,0,{sx:Pe-.45,sy:ce,sz:Pe-.45}),b.add("plazaInner",X,0,ce+.004,0,{sx:3.4,sy:.01,sz:3.4});const ne=Ve(yt.q,yt.r),fe=qi({x:ne.x,z:ne.z,facing:Os(ne.x,ne.z),shadows:o.shadows});i.add(fe.group);const q=ce;b.add("stone",f,0,q+.25,0,{sx:3,sy:.5,sz:3}),b.add("trunk",f,0,q+1,0,{sx:.6,sy:1.6,sz:.6}),[[1.5,3.6,2.2],[2.7,2.9,1.9],[3.8,2.2,1.6],[4.8,1.5,1.3]].forEach(([u,w,P],M)=>b.add(M%2?"pineLight":"pine",E,0,q+u+P/2,0,{sx:w,sy:P,sz:w})),b.add("star",z,0,q+6.35,0,{sx:.5,sy:.5,sz:.5}),S.push({cx:0,cz:0,hx:1.6,hz:1.6,yaw:0});const Ae=a(new lt(.07,8,6));for(let u=0;u<44;u++){const w=u/44,P=q+1.6+w*4.4,M=(1-w)*1.65+.2,v=w*Math.PI*9;b.add(`light${u%4}`,Ae,Math.sin(v)*M,P,Math.cos(v)*M)}const de=new he,Ne=a(new Dt(.36,.25,.05,1,.02)),Be=a(new lt(.045,8,6)),Fe=a(new Xe(.008,.008,.3,4));for(let u=0;u<12;u++){const w=u/12*Math.PI*2+.3,P=q+2+u%3*.75,M=1.95-u%3*.35,v=new he;v.position.set(Math.sin(w)*M,P,Math.cos(w)*M),v.rotation.y=w;const R=new O(Ne,j.paper);R.position.y=-.18;const D=new O(Be,j.seal);D.position.set(0,-.18,.03);const Z=new O(Fe,j.darkWood);Z.position.y=0,v.add(R,D,Z),v.visible=!1,v.userData.swing=u*1.7,de.add(v)}i.add(de);for(let u=0;u<6;u++){const w=u*Math.PI/3,P=4.5,M=Math.cos(w)*P,v=Math.sin(w)*P,R=Math.atan2(-M,-v);b.addAt(M,v,R,"wood",k,0,q+.27,0,{sx:1.9,sy:.08,sz:.5}),b.addAt(M,v,R,u%3===0?"red":u%3===1?"mint":"leafLight",k,0,q+.55,-.24,{sx:1.9,sy:.32,sz:.07});for(const D of[-.8,.8])b.addAt(M,v,R,"darkWood",k,D,q+.13,0,{sx:.1,sy:.26,sz:.44});S.push({cx:M,cz:v,hx:.95,hz:.3,yaw:R});for(const D of[-.45,.45]){const Z=M+Math.cos(R)*D,Q=v-Math.sin(R)*D;A.push({key:`plaza:${u}:${D}`,kind:"seat",x:Z,z:Q,y:q+.3,face:R,plot:null,name:"a bench"})}}for(let u=0;u<6;u++){const w=Math.PI/6+u*Math.PI/3,P=wt-1.3,M=Math.cos(w)*P,v=Math.sin(w)*P;for(let D=0;D<10;D++)b.add(D%2?"red":"white",f,M,q+.11+D*.22,v,{sx:.16,sy:.22,sz:.16});b.add("white",L,M+.21,q+2.14,v,{sx:.2,sy:.2,sz:.2}),b.add("metal",k,M,q+2.28,v,{sx:.34,sy:.08,sz:.34});const R=new O(k,j.lamp);R.scale.set(.26,.3,.26),R.position.set(M,q+2.1,v),i.add(R),$.push({x:M,y:q+.016,z:v,width:5.6,depth:5.6}),S.push({cx:M,cz:v,hx:.15,hz:.15,yaw:0})}const U=Math.PI+.35,me=e-4,_e=e+9,De=(me+_e)/2,ue=Math.sin(U),T=Math.cos(U);b.add("wood",k,ue*De,.12,T*De,{sx:2.2,sy:.14,sz:_e-me,ry:U});for(let u=me+1;u<=_e;u+=2.2)for(const w of[-1.15,1.15]){const P=ue*u+Math.cos(U)*w,M=T*u-Math.sin(U)*w;b.add("darkWood",f,P,-.4,M,{sx:.18,sy:1.3,sz:.18})}const B=_e+1.6,te=ue*B+Math.cos(U)*2.2,ge=T*B-Math.sin(U)*2.2;b.add("white",k,te,rt+.25,ge,{sx:1.5,sy:.6,sz:3.6,ry:U}),b.add("red",k,te,rt+.42,ge,{sx:1.56,sy:.1,sz:3.66,ry:U}),b.add("blue",k,te+ue*.3,rt+.85,ge+T*.3,{sx:1,sy:.6,sz:1.2,ry:U});const ye={x:ue*(_e-1),z:T*(_e-1),face:U+Math.PI},se=[{cx:ue*De,cz:T*De,hx:.9,hz:(_e-me)/2,yaw:U}];for(const u of[me+1,me+5.4,me+9.8]){const w=ue*u+Math.cos(U)*1.15,P=T*u-Math.sin(U)*1.15;W.add("nightMetal",f,w,.55,P,{sx:.08,sy:.6,sz:.08}),W.add("nightLamp",z,w,.91,P,{sx:.24,sy:.3,sz:.24}),$.push({x:ue*u,y:.196,z:T*u,width:2.1,depth:2.1})}const re=u=>kt(u*1.37,u*2.11,t+99),be=U+1.9,Se=(u,w,P)=>Math.hypot(u,w)<Pe+P+.5||Math.hypot(u-ne.x,w-ne.z)<Pe+P+.5?!1:s.every(M=>Math.hypot(u-M.x,w-M.z)>M.radius+P+.8),Ie=(u,w,P)=>Qe(Math.hypot(u,w)+P+1.1,e)-.12,Oe=new Set;for(let u=1;u<=F;u++)for(const[w,P]of Mt(u)){const M=Ve(w,P);for(let v=0;v<6;v++){const R=v*Math.PI/3,D=M.x+Math.sin(R)*Pe,Z=M.z+Math.cos(R)*Pe,Q=`${Math.round(D*100)},${Math.round(Z*100)}`;if(Oe.has(Q)||Math.hypot(D,Z)>e-8||(Oe.add(Q),Lt(D,Z,Re+.55)||Math.hypot(D,Z)<Pe+.8||Math.hypot(D-ne.x,Z-ne.z)<Pe+.8))continue;const ie=Oe.size%3===0,Te=["red","leafLight","lemon","mint"][Oe.size%4];ie?(b.add("white",f,D,.6,Z,{sx:.11,sy:1.2,sz:.11}),b.add(Te,z,D,1.28,Z,{sx:.85,sy:.85,sz:.5}),b.add("white",z,D,1.28,Z+.22,{sx:.33,sy:.33,sz:.1})):(b.add(Te,z,D,.33,Z,{sx:.85,sy:1,sz:.85}),b.add("white",z,D-.12,.62,Z+.14,{sx:.13,sy:.07,sz:.13})),S.push({cx:D,cz:Z,hx:.43,hz:.43,yaw:0})}}const pe=-.2,dt=u=>{const w=P=>Math.abs(Math.atan2(Math.sin(u-P),Math.cos(u-P)))<.2;return w(pe)||w(U)||w(be)||w(.65)||w(1.55)};for(let u=0;u<22;u++){const w=u/22*Math.PI*2+re(u)*.18;if(dt(w))continue;const P=e-2.8+re(u+40)*.8,M=Math.sin(w)*P,v=Math.cos(w)*P;if(!Se(M,v,1.2))continue;const R=2.8+re(u+20)*1.4,D=Qe(P,e),Z=Ie(M,v,.11),Q=D+R;b.add("white",f,M,(Z+Q)/2,v,{sx:.22,sy:Q-Z,sz:.22}),b.addAt(M,v,w,u%2?"leaf":"leafLight",f,0,D+R,0,{sx:2.1,sy:.38,sz:2.1,rx:Math.PI/2}),b.addAt(M,v,w,"white",L,0,D+R,.22,{sx:.55,sy:.55,sz:.25}),b.addAt(M,v,w,"caramel",z,0,D+R,.24,{sx:.28,sy:.28,sz:.16}),S.push({cx:M,cz:v,hx:.24,hz:.24,yaw:0});const ie=M+Math.cos(w)*1.3,Te=v-Math.sin(w)*1.3;Se(ie,Te,.6)&&(b.add(u%2?"mint":"leaf",z,ie,D+.32,Te,{sx:1,sy:.95,sz:1}),S.push({cx:ie,cz:Te,hx:.5,hz:.5,yaw:0}))}for(let u=0;u<16;u++){const w=re(u+200)*Math.PI*2;if(dt(w))continue;const P=e-2+re(u+220)*1.2,M=Math.sin(w)*P,v=Math.cos(w)*P;if(!Se(M,v,.85))continue;const R=.7+re(u+240)*1.2;for(let D=0;D<3;D++)b.add(D%2?"mint":"rock",_,M+(D-1)*.32,Qe(P,e)+R/2,v,{sx:.55,sy:R*(D===1?1.3:.8),sz:.6,rz:(D-1)*.22,ry:u});S.push({cx:M,cz:v,hx:.8,hz:.45,yaw:0})}const ut=e-1.8,y=ue*ut,C=T*ut;if(Se(y,C,2.8)){for(const u of[-1.8,1.8]){const w=y+Math.cos(U)*u,P=C-Math.sin(U)*u,M=Ie(w,P,Math.hypot(.425,.45));b.addAt(y,C,U,"caramel",k,u,(4.2+M)/2,0,{sx:.85,sy:4.2-M,sz:.9});for(let v=0;v<5;v++)b.addAt(y,C,U,"white",z,u,.7+v*.7,.48,{sx:.2,sy:.2,sz:.12});S.push({cx:y+Math.cos(U)*u,cz:C-Math.sin(U)*u,hx:.45,hz:.5,yaw:U})}b.addAt(y,C,U,"caramel",k,0,4.2,0,{sx:4.6,sy:.8,sz:.9}),b.addAt(y,C,U,"white",k,0,4.65,0,{sx:4.7,sy:.16,sz:.98}),b.addAt(y,C,U,"red",z,0,4.3,.5,{sx:.62,sy:.62,sz:.18})}const J=e-3,le=Math.sin(pe)*J,ke=Math.cos(pe)*J;if(Se(le,ke,5.5)){for(let u=0;u<5;u++){const w=a(new Qt(3.4+u*.42,.24,4,20,Math.PI));b.addAt(le,ke,pe,["mint","blue","leafLight","lemon","red"][u],w,0,.4,0)}for(const u of[-4.25,4.25]){const w=le+Math.cos(pe)*u,P=ke-Math.sin(pe)*u,M=Ie(w,P,1.05);b.addAt(le,ke,pe,"white",z,u,(.75+M)/2,0,{sx:2.1,sy:.75-M,sz:1.4}),S.push({cx:le+Math.cos(pe)*u,cz:ke-Math.sin(pe)*u,hx:1.1,hz:.7,yaw:pe})}}for(const[u,w]of[[.65,"donut"],[1.55,"fountain"]]){const P=e-3,M=Math.sin(u)*P,v=Math.cos(u)*P;if(!Se(M,v,2.9))continue;const R=Qe(P,e),D=Ie(M,v,2.55),Z=R+.27;if(b.add("white",f,M,(Z+D)/2,v,{sx:5.1,sy:Z-D,sz:5.1}),S.push({cx:M,cz:v,hx:2.6,hz:2.6,yaw:0}),w==="donut"){b.addAt(M,v,u,"caramel",L,0,R+2.55,0,{sx:1.65,sy:1.65,sz:1.65}),b.addAt(M,v,u,"red",L,0,R+2.55,.3,{sx:1.62,sy:1.62,sz:1.05});for(let Q=0;Q<12;Q++){const ie=Q*Math.PI/6;b.addAt(M,v,u,Q%2?"white":"mint",k,Math.sin(ie)*1.92,R+2.55+Math.cos(ie)*1.92,.74,{sx:.14,sy:.33,sz:.1,rz:ie+.4})}}else{b.add("caramel",f,M,R+.55,v,{sx:4.5,sy:.7,sz:4.5}),b.add("cocoa",f,M,R+.92,v,{sx:4.1,sy:.08,sz:4.1});for(let Q=0;Q<3;Q++){const ie=2.7-Q*.78;b.add("cocoa",E,M,R+1.35+Q*.85,v,{sx:ie,sy:1.1,sz:ie})}b.add("white",z,M,R+3.8,v,{sx:.6,sy:.5,sz:.6}),$.push({x:M,y:R+.25,z:v,width:3.5,depth:3.5})}}const Ge=Math.sin(be)*(e-2.4),Ke=Math.cos(be)*(e-2.4);b.add("stone",f,Ge,.3,Ke,{sx:2.6,sy:.6,sz:2.6});for(let u=0;u<5;u++)b.add(u%2?"red":"white",f,Ge,.6+u*1.1+.55,Ke,{sx:1.7-u*.14,sy:1.1,sz:1.7-u*.14});b.add("metal",f,Ge,6.7,Ke,{sx:1.3,sy:.15,sz:1.3}),b.add("red",E,Ge,7.75,Ke,{sx:1.2,sy:.7,sz:1.2});const vt=new O(k,j.lamp);vt.scale.set(.8,.8,.8),vt.position.set(Ge,7.15,Ke),i.add(vt),S.push({cx:Ge,cz:Ke,hx:1.4,hz:1.4,yaw:0});const js=a(new Ot(1.1,.42));for(const u of s){const w=gs(u,o.residents);if(!w)continue;const P=u.radius*Math.sqrt(3)/2,M=Ce(u,-u.radius/2+.2,P-.45),v=u.facing*Math.PI/180;b.add("darkWood",k,M.x,q+.45,M.z,{sx:.1,sy:.9,sz:.1}),b.add("wood",k,M.x,q+.95,M.z,{sx:1.2,sy:.5,sz:.08,ry:v}),W.add("nightLamp",z,M.x,q+1.3,M.z,{sx:.26,sy:.2,sz:.26});const R=Ce(u,-u.radius/2+.2,P+.6);$.push({x:R.x,y:.036,z:R.z,width:6.5,depth:6.5});const D=un(w);if(D){a(D);const Z=a(new ee({map:D,side:Rt})),Q=new O(js,Z);Q.position.set(M.x+Math.sin(v)*.05,q+.95,M.z+Math.cos(v)*.05),Q.rotation.y=v,i.add(Q)}S.push({cx:M.x,cz:M.z,hx:.15,hz:.15,yaw:0})}const _t=[],pt=(u,w,P,M,v,R,D,Z,Q=!1)=>{const ie=u.index?u.toNonIndexed():u.clone();ie.deleteAttribute("uv"),ie.scale(R,D,Z),Q&&ie.rotateX(Math.PI),ie.translate(P,M,v);const Te=new H(w),Yt=ie.getAttribute("position").count,mt=new Float32Array(Yt*3);for(let it=0;it<Yt;it++)mt[it*3]=Te.r,mt[it*3+1]=Te.g,mt[it*3+2]=Te.b;ie.setAttribute("color",new bt(mt,3)),_t.push(ie)};for(let u=0;u<3;u++){const w=-.26+u*.25,P=e+13+u%2*4,M=Math.sin(w)*P,v=Math.cos(w)*P,R=9+u%2*4;pt(E,"#ba91d7",M,R-1,v,6,3,4.8,!0);for(let D=0;D<4;D++)pt(z,D%2?"#f3b6d3":"#b0e6c5",M+(D-1.5)*1.55,R+D%2*.5,v,3.5,1.5,3.8);pt(f,"#fff0ce",M,R+1.6,v,.2,2.2,.2),pt(z,["#ea93b6","#b49cdd","#efd17d"][u],M,R+3,v,1.8,1.8,1.2)}const Es=a(Wt(_t,!1));_t.forEach(u=>u.dispose());const St=new O(Es,a(new ze({vertexColors:!0,flatShading:!0,roughness:.85})));St.name="floating-sugar-islands",i.add(St);const Ut=a(G("#fff1f4")),Bt=a(G("#f0c0da")),Ft=a(new ee({color:"#fff1de",transparent:!0,opacity:0,depthWrite:!1,fog:!1})),Gt=new ot({white:Ut,pink:Bt});for(let u=0;u<7;u++){const w=u*Math.PI*2/7,P=e+13+u%2*8;for(let M=0;M<5;M++)Gt.add(M%3?"white":"pink",z,Math.sin(w)*P+(M-2)*2.1,14+u%3*2+M%2*.9,Math.cos(w)*P,{sx:5.2,sy:2.6+M%2,sz:3.8})}const Pt=Gt.build(!1);Pt.name="cotton-candy-clouds";const Kt=new ot({star:Ft});for(let u=0;u<100;u++){const w=u*2.3999632297,P=.08+re(u+700)*.85,M=Math.sqrt(1-P*P)*220,v=.35+re(u+850)*.5;Kt.add("star",z,Math.sin(w)*M,P*220,Math.cos(w)*M,{sx:v,sy:v,sz:v})}const ft=Kt.build(!1);ft.name="sugar-stars",ft.visible=!1;for(const u of[Pt,ft])u.traverse(w=>{w instanceof O&&a(w.geometry)}),i.add(u);const As=new H("#fff1f4"),Ts=new H("#9283b3"),Ls=new H("#f0c0da"),Ds=new H("#89729f");for(let u=0;u<90;u++){const w=re(u+400)*Math.PI*2,P=e-5.5-re(u+500)*1.5,M=Math.sin(w)*P,v=Math.cos(w)*P;Se(M,v,.3)&&b.add(u%3===0?"white":u%3===1?"red":"caramel",k,M,.025,v,{sx:.09,sy:.035,sz:.24,ry:w*4})}for(let u=0;u<180;u++){const w=re(u+1100)*Math.PI*2,P=u<42,M=P?2.1+re(u+1200)*3.5:9+re(u+1200)*(e-15),v=Math.sin(w)*M,R=Math.cos(w)*M;!P&&(Lt(v,R,Re+.15)||Math.hypot(v-ne.x,R-ne.z)<Pe+.5)||P&&S.some(D=>Math.hypot(v-D.cx,R-D.cz)<Math.hypot(D.hx,D.hz)+.3)||b.add(["red","lemon","leafLight","mint"][u%4],k,v,P?q+.03:.045,R,{sx:.14,sy:.045,sz:.4,ry:w*4})}const jt=b.build(o.shadows);jt.name="candy-scenery",jt.traverse(u=>{const w=u;w.geometry&&a(w.geometry)}),i.add(jt),N.replace($);const st=W.build(!1);st.name="night-lanterns",st.visible=!1,st.traverse(u=>{const w=u;w.geometry&&a(w.geometry)}),i.add(st);const Rs=new H("#ffe3a8"),Cs=new H("#fff3d6"),Ns=j.lamp;return S.push(...fe.solids),A.push(...fe.seats),n.push(fe),{group:i,seats:A,solids:S,dock:ye,walkways:se,deck:.19,playground:fe,update(u,w,P,M){h.time.value=u,r.value=w;for(const v of d)v.material.color.copy(v.day).lerp(v.night,w);St.position.y=Math.sin(u*.65)*.35,Pt.rotation.y=Math.sin(u*.035)*.035,Ut.color.copy(As).lerp(Ts,w),Bt.color.copy(Ls).lerp(Ds,w),ft.visible=w>0,Ft.opacity=w*.85,c.top.copy(P.top),c.horizon.copy(P.horizon),h.material.color.copy(M),m.opacity=.22+Math.sin(u*.9)*.08,Ns.color.copy(Cs).lerp(Rs,w).multiplyScalar(.75+w*.5),N.update(w),st.visible=w>0,j.nightLamp.opacity=w,j.nightMetal.opacity=w;for(const v of de.children)v.visible&&(v.rotation.z=Math.sin(u*1.3+v.userData.swing)*.08)},setLetters(u){de.children.forEach((w,P)=>{w.visible=P<u})},dispose(){n.forEach(u=>u.dispose())}}}function fn(o,e,t){return t.some(s=>{const i=o-s.cx,n=e-s.cz,a=i*Math.cos(s.yaw)-n*Math.sin(s.yaw),r=i*Math.sin(s.yaw)+n*Math.cos(s.yaw);return Math.abs(a)<=s.hx+.2&&Math.abs(r)<=s.hz+.2})}function hs(o){const e=[{h:0,top:"#201c46",horizon:"#51406d",sea:"#285b70",night:1,sun:"#9fb6ff",power:.35,hemi:.55},{h:5.5,top:"#29204e",horizon:"#65507e",sea:"#315e78",night:1,sun:"#9fb6ff",power:.35,hemi:.55},{h:6.6,top:"#9d8bc9",horizon:"#ffc6a6",sea:"#76b9bd",night:.4,sun:"#ffc59a",power:1.6,hemi:1},{h:8,top:"#b9b5ef",horizon:"#ffe1eb",sea:"#28c9c4",night:0,sun:"#fff4e2",power:2.7,hemi:1.45},{h:17.2,top:"#b9b5ef",horizon:"#ffe1eb",sea:"#28c9c4",night:0,sun:"#fff4e2",power:2.7,hemi:1.45},{h:18.8,top:"#9d7fba",horizon:"#ffb487",sea:"#679ba9",night:.35,sun:"#ffad7a",power:1.6,hemi:1},{h:20.3,top:"#312552",horizon:"#63517f",sea:"#345b74",night:.9,sun:"#9fb6ff",power:.45,hemi:.6},{h:24,top:"#201c46",horizon:"#51406d",sea:"#285b70",night:1,sun:"#9fb6ff",power:.35,hemi:.55}],t=(o%24+24)%24;let s=0;for(;s<e.length-2&&e[s+1].h<=t;)s++;const i=e[s],n=e[s+1],a=et(0,1,(t-i.h)/Math.max(1e-4,n.h-i.h)),r=(c,d)=>new H(c).lerp(new H(d),a),l=t>=6&&t<=19.5,m=(l?(t-6)/13.5:(t+24-19.5)%24/10.5)*Math.PI,p=new oe(Math.cos(m)*60,Math.max(12,Math.sin(m)*80),l?-35:35);return{top:r(i.top,n.top),horizon:r(i.horizon,n.horizon),sea:r(i.sea,n.sea),night:i.night+(n.night-i.night)*a,sun:p,sunColor:r(i.sun,n.sun),sunIntensity:i.power+(n.power-i.power)*a,hemi:i.hemi+(n.hemi-i.hemi)*a}}function ds(o,e,t="auto"){if(t!=="auto")return t;let s=Math.imul(o^Math.floor(e/72e4),73244475);s=Math.imul(s^s>>>16,73244475);const i=(s>>>0)%10;return i<5?"sunny":i<8?"cloudy":"rain"}function mn(o,e){return o==="rain"&&e!=="sleep"}function gn(o){const e=new he;e.name="rain-umbrella",e.visible=!1;const t=new O(new lt(.72,16,8,0,Math.PI*2,0,Math.PI/2),new ze({color:o,roughness:.65,side:Rt}));t.scale.y=.45,t.position.set(.26,1.46,.08),e.add(t);const s=new O(new Xe(.016,.016,.92,8),new ze({color:"#4b5967",metalness:.5}));s.position.set(.26,1,.08),e.add(s);const i=new O(new zt(.58,.8,48),new ee({color:"#ffd687",transparent:!0,opacity:.42,depthWrite:!1,side:Rt,blending:It}));return i.name="lead-aura",i.rotation.x=-Math.PI/2,i.position.y=.035,i.visible=!1,{umbrella:e,aura:i,dispose(){for(const n of[t,s,i])n.geometry.dispose(),n.material.dispose()}}}class yn{object;positions=new Float32Array(450*3);constructor(){for(let t=0;t<450;t++)this.positions[t*3]=(t*.61803398875%1-.5)*70,this.positions[t*3+1]=t*.38196601125%1*24,this.positions[t*3+2]=(t*.754877666%1-.5)*70;const e=new ks;e.setAttribute("position",new ei(this.positions,3)),this.object=new ti(e,new si({color:"#c6e3fa",size:.09,transparent:!0,opacity:.65,depthWrite:!1})),this.object.name="island-rain",this.object.visible=!1}update(e,t,s,i,n){if(this.object.visible=t==="rain",this.object.position.set(s,0,i),t!=="rain"||n)return;const a=this.object.geometry.getAttribute("position");for(let r=0;r<a.count;r++){const l=a.getY(r)-e*13;a.setY(r,l<.2?24:l)}a.needsUpdate=!0}dispose(){this.object.geometry.dispose(),this.object.material.dispose()}}const tt=Math.PI/180;class xn{constructor(e){this.colors=e}colors;made=new Map;material(e){const t=`${e.tone}:${e.text}`,s=this.made.get(t);if(s)return s;if(typeof document>"u")return null;const i=document.createElement("canvas"),n=i.getContext("2d");if(!n)return null;const a=[...e.text].length<=2&&new RegExp("\\p{Extended_Pictographic}","u").test(e.text),r=a?"52px system-ui, 'Apple Color Emoji', 'Segoe UI Emoji', sans-serif":"700 46px Inter, system-ui, sans-serif";n.font=r;const l=Math.ceil(n.measureText(e.text).width),h=Math.max(128,Math.min(512,l+64));i.width=h,i.height=128;const{decide:m,danger:p}=this.colors(),c=e.tone==="decide"?m:e.tone==="danger"?p:e.tone==="sleep"?"#dfe9ff":"#ffffff",d=e.tone==="decide"||e.tone==="danger"?"#ffffff":"#33424d";n.fillStyle=c,n.strokeStyle="rgba(30, 40, 50, 0.18)",n.lineWidth=4,n.beginPath(),n.roundRect(14,12,h-28,84,34),n.moveTo(h/2-12,94),n.lineTo(h/2,116),n.lineTo(h/2+12,94),n.fill(),n.stroke(),n.fillStyle=d,n.font=r,n.textAlign="center",n.textBaseline="middle",n.fillText(e.text,h/2,a?58:56,h-40);const g=new Nt(i);g.colorSpace=Ms;const j={material:new mi({map:g,depthWrite:!1,transparent:!0}),aspect:h/128};return this.made.set(t,j),j}dispose(){for(const{material:e}of this.made.values())e.map?.dispose(),e.dispose();this.made.clear()}}function us(o,e){return typeof document>"u"?e:getComputedStyle(document.documentElement).getPropertyValue(o).trim()||e}class wn{constructor(e,t,s=!1){this.host=e,this.events=t,this.reducedMotion=s;const i=document.createElement("canvas");i.className="island-canvas",i.setAttribute("aria-hidden","true"),this.canvas=i,e.prepend(i);try{this.renderer=new ii({canvas:i,antialias:!0,powerPreference:"high-performance"})}catch(n){throw i.remove(),n}this.renderer.setPixelRatio(Math.min(window.devicePixelRatio||1,1.75)),this.renderer.shadowMap.enabled=!0,this.renderer.shadowMap.type=ni,this.renderer.toneMapping=ai,this.renderer.toneMappingExposure=1.02,this.scene.fog=new oi("#e8f3fb",90,420),this.scene.add(this.society.root,this.buildingLights.group),this.scene.add(this.hemi,this.sun,this.sun.target,this.proxies,this.rain.object),this.proxies.visible=!1,this.sun.castShadow=!0,this.sun.shadow.mapSize.set(2048,2048),this.sun.shadow.bias=-4e-4,this.sun.shadow.normalBias=.03,this.controls=new Ei(this.camera,i),this.controls.enableDamping=!0,this.controls.dampingFactor=.08,this.controls.screenSpacePanning=!1,this.controls.minPolarAngle=.18,this.controls.maxPolarAngle=1.18,this.controls.minDistance=4,this.controls.maxDistance=140,this.controls.zoomSpeed=.8,this.controls.rotateSpeed=.6,this.controls.addEventListener("start",()=>{this.flight=null}),this.camera.position.set(22,31,33),this.controls.target.set(0,0,0),this.nav=new is(40),this.sim=new cn(this.nav,{seats:[],plots:new Map,tree:{x:0,z:0},plaza:wt,radius:40}),this.sim.onWishRegister=n=>this.events.onWishRegister?.(n),this.sim.onWishGiveUp=n=>this.events.onWishGiveUp?.(n),this.bubbles=new xn(()=>({decide:us("--decide","#3d7bd9"),danger:us("--danger","#d6544b")})),this.shadowMaterial=new ee({color:"#1e2a24",transparent:!0,opacity:.22,depthWrite:!1}),this.ring=new O(new zt(.55,.68,40),new ee({color:"#ffffff",transparent:!0,opacity:.85,depthWrite:!1})),this.ring.rotation.x=-Math.PI/2,this.ring.visible=!1,this.scene.add(this.ring),i.addEventListener("pointerdown",this.onDown),i.addEventListener("pointerup",this.onUp),i.addEventListener("pointermove",this.onMove),i.addEventListener("pointerleave",this.onLeave),i.addEventListener("webglcontextlost",this.onContextLost),document.addEventListener("visibilitychange",this.onVisibility),window.addEventListener("keydown",this.onKeyDown),window.addEventListener("keyup",this.onKeyUp),window.addEventListener("blur",this.onBlur),this.resize=new ResizeObserver(()=>this.fit()),this.resize.observe(e),this.fit(),this.start()}host;events;reducedMotion;weatherChoice="auto";rain=new yn;setWeather(e){this.weatherChoice=e,this.hourAt=-1}renderer;scene=new ri;camera=new ci(38,1,.1,1400);controls;hemi=new li("#fff0f6","#bda2b3",1.4);sun=new hi("#fff4e2",2.6);gardenBeds=new Map;society=zi();scenery=null;sceneryKey="";buildingLights=new _s({interior:!0});buildingLightsKey="";cache=new di;placed=new Map;robots=new Map;proxies=new he;sim;nav;island=null;residents=[];bubbles;frame=0;last=0;clock=0;hourAt=-1;hour=12;hourOverride=null;sky=hs(12);selected=null;following=!1;held=new Set;flight=null;labels=null;hovered=null;pointer=new Me;pointerAt=null;raycaster=new ui;faded=new Map;fadedMaterials=new Map;ring;shadowGeometry=new ws(.42,24);shadowMaterial;proxyGeometry=new ht(1.3,1.6,1.3);resize;firstLoad=!0;lost=!1;canvas;tiled=new Set;setLabels(e,t){this.labels={hover:e,selected:t}}setReducedMotion(e){this.reducedMotion=e}setHourOverride(e){this.hourOverride=e,this.hourAt=-1}fit(){const e=Math.max(1,this.host.clientWidth),t=Math.max(1,this.host.clientHeight);this.renderer.setSize(e,t,!1),this.camera.aspect=e/t,this.camera.fov=this.camera.aspect<1?Math.min(62,38/Math.sqrt(this.camera.aspect)):38,this.camera.updateProjectionMatrix()}start(){this.frame||this.lost||document.hidden||(this.last=performance.now(),this.frame=requestAnimationFrame(this.draw))}stop(){cancelAnimationFrame(this.frame),this.frame=0}onVisibility=()=>{document.hidden?this.stop():this.start()};onContextLost=e=>{e.preventDefault(),this.lost=!0,this.stop(),this.events.onLost?.()};setIsland(e,t){const s=zs(e,t);e=s.island,t=s.residents;const i=new Set(this.residents.map(f=>f.key));this.island=e,this.residents=t;const n=new Map(e.assets.map(f=>[f.id,f])),a=new Map(e.plots.map(f=>[f.id,f])),r=JSON.stringify([e.radius,e.seed,e.plots.map(f=>[f.id,f.q,f.r,f.x,f.z,f.facing,f.radius,f.owner.kind,gs(f,t)])]);if(r!==this.sceneryKey||!this.scenery){this.scenery&&(this.scene.remove(this.scenery.group),this.scenery.dispose()),this.scenery=pn({radius:e.radius,seed:e.seed,plots:e.plots,residents:t,shadows:!0}),this.scene.add(this.scenery.group),this.sceneryKey=r;const f=Math.max(2,...e.plots.map(_=>_.ring));this.tiled=new Set;for(let _=1;_<=f;_++)for(const[L,A]of Mt(_))this.tiled.add(`${L},${A}`);const E=e.radius+8,z=this.sun.shadow.camera;z.left=-E,z.right=E,z.top=E,z.bottom=-E,z.near=1,z.far=260,z.updateProjectionMatrix(),this.controls.maxDistance=Math.max(60,e.radius*2.6)}const l=this.scenery;l.setLetters(e.wishes.filter(f=>f.state==="open").length);const h=new Set,m=[...l.solids,...this.society.solids],p=[],c=[...l.seats],d=[];for(const f of e.placed){const E=a.get(f.plot),z=n.get(f.asset);if(!E||!z||z.kind==="accessory")continue;h.add(f.id);const _=[z.id,z.rev,f.x,f.z,f.y,f.turn,E.x,E.z,E.facing].join(":");let L=this.placed.get(f.id);if(!L||L.signature!==_){L&&this.scene.remove(L.object);const N=Vt(this.cache.get(z),{shadows:!0}),$=Ce(E,f.x,f.z);N.position.set($.x,ce+f.y,$.z),N.rotation.y=(E.facing+f.turn)*tt,N.userData.placement=f.id,N.userData.kind=z.kind,this.scene.add(N),L={object:N,signature:_},this.placed.set(f.id,L)}m.push(...Mn(z,E,f)),z.kind==="building"&&d.push({asset:z,view:L});const A=_i(z,E,f);A&&p.push(A);const S=zn(z,E,f);S&&(S.owner=s.deskOwners.get(f.id),S.key+=`:${S.x}:${S.z}:${S.y}:${S.face}`,c.push(S))}for(const[f,E]of[...this.placed])h.has(f)||(this.scene.remove(E.object),this.placed.delete(f));const g=d.map(({view:f})=>`${f.object.userData.placement}:${f.signature}`).join("|");g!==this.buildingLightsKey&&(this.buildingLights.replace(d.flatMap(({asset:f,view:E})=>(E.object.updateMatrix(),Bi(f).map(z=>({...z,transform:E.object.matrix}))))),this.buildingLightsKey=g),this.nav=new is(e.radius,m,1.5,l.walkways);for(const f of p)if(!(this.nav.isFree(f)&&this.nav.path({x:0,z:0},f)))for(let E=.5;E<=7;E+=.5){let z=!1;for(let _=0;_<8;_++){const L=_*Math.PI/4,A={x:f.x+Math.sin(L)*E,z:f.z+Math.cos(L)*E};if(this.nav.isFree(A)&&this.nav.path({x:0,z:0},A)){f.face=Math.atan2(f.x-A.x,f.z-A.z),Object.assign(f,A),z=!0;break}}if(z)break}for(const[f,E]of this.gardenBeds){const z=p.find(_=>_.key===f&&_.activity==="garden");z?E.root.position.set(z.x+Math.sin(z.face)*.65,ce+.02,z.z+Math.cos(z.face)*.65):(this.scene.remove(E.root),E.dispose(),this.gardenBeds.delete(f))}const j={seats:c,activities:p,plots:new Map(t.filter(f=>f.plot).map(f=>{const E=f.plot,z=Ce(E,0,0),_=Ce(E,0,E.radius*Math.sqrt(3)/2-1.2);return[f.key,{id:E.id,center:z,door:_,front:{..._,face:E.facing*tt}}]})),tree:{x:0,z:0},plaza:wt,radius:e.radius,playground:l.playground.anchors},b=this.clock;if(this.sim.reset(this.nav,j,t,b),this.sim.setWishQueue(e.wishes.filter(f=>f.state==="queued").sort((f,E)=>f.madeAt-E.madeAt||f.id.localeCompare(E.id)).map(f=>({id:f.id,key:`agent:${f.who.id}`}))),this.firstLoad)this.frameEveryone(e.plots);else for(const f of t)i.has(f.key)||f.owner.kind!=="bot"||this.sim.landAt(f.key,l.dock,b);this.firstLoad=!1;const k=new Set;for(const f of t){const E=JSON.stringify({...f.look,worn:void 0}),z=Ht.map(L=>{const A=f.look.worn[L],S=A?n.get(A):void 0;return S&&S.kind==="accessory"&&k.add(S.id),S&&S.kind==="accessory"?`${L}:${S.id}:${S.rev}`:""}).join("|");let _=this.robots.get(f.key);if(_&&_.look!==E&&(this.dropRobot(f.key),_=void 0),_||(_=this.addRobot(f.key,f,E)),_.atmosphere.aura.visible=!!f.agent?.leader,_.worn!==z){for(const L of Ht){const A=f.look.worn[L],S=A?n.get(A):void 0;_.rig.wear(L,S&&S.kind==="accessory"?this.accessory(S,L):null)}_.worn=z}}for(const f of[...this.robots.keys()])t.some(E=>E.key===f)||this.dropRobot(f);this.selected&&!this.robots.has(this.selected)&&this.select(null),this.cache.prune(new Set([...e.placed.map(f=>f.asset),...k]))}accessory(e,t){const s=Vt(this.cache.get(e),{shadows:!1});return s.name=`worn-${t}`,s}addRobot(e,t,s){const i=ys(t.look);i.root.userData.robot=e;const n=new O(this.shadowGeometry,this.shadowMaterial);n.rotation.x=-Math.PI/2;const a=new O(this.proxyGeometry,this.shadowMaterial);a.userData.robot=e;const r=new pi;r.scale.set(.6,.6,1),r.visible=!1,this.scene.add(i.root,n,r),this.proxies.add(a);const l=gn(t.look.trim);i.root.add(l.umbrella,l.aura);const h=Pi();this.scene.add(h.root);const m=Si();i.anchors.hand.add(m.root);const p={activity:m,concert:h,rig:i,atmosphere:l,look:s,worn:"",shadow:n,proxy:a,bubble:r,bubbleKey:""};return this.robots.set(e,p),p}dropRobot(e){const t=this.robots.get(e);t&&(this.scene.remove(t.rig.root,t.shadow,t.bubble),this.proxies.remove(t.proxy),t.rig.dispose(),t.atmosphere.dispose(),t.activity.dispose(),this.scene.remove(t.concert.root),t.concert.dispose(),this.robots.delete(e))}setModes(e){this.sim.setModes(e,this.clock)}event(e,t){this.sim.event(e,t,this.clock)}homeChanged(e){this.sim.buildHome(e,this.clock)}describe(e){return this.sim.describe(e)}mood(e){const t=this.sim.mood(e);return t?{...t,said:this.sim.said(e)}:null}select(e,t=!0){if(this.selected=e,this.following=!!e,this.ring.visible=!!e,!e){this.restoreFaded(),this.labels&&(this.labels.selected.hidden=!0);return}const s=this.sim.robots.get(e);s&&t&&this.flyTo(new oe(s.x,.6,s.z),13)}frameEveryone(e){const t=[{x:0,z:0},...e.map(r=>({x:r.x,z:r.z}))],s={x:t.reduce((r,l)=>r+l.x,0)/t.length,z:t.reduce((r,l)=>r+l.z,0)/t.length},i=Math.max(14,...t.map(r=>Math.hypot(r.x-s.x,r.z-s.z)+7)),n=Math.min(this.controls.maxDistance,i*1.85),a=new oe(22,31,33).setLength(n);this.controls.target.set(s.x,0,s.z),this.camera.position.copy(this.controls.target).add(a),this.controls.update()}recenter(){this.select(null),this.flyTo(new oe(0,0,0),Math.max(46,(this.island?.radius??40)*1.15))}flyTo(e,t){const s=this.camera.position.distanceTo(this.controls.target);if(this.reducedMotion){const i=this.camera.position.clone().sub(this.controls.target).setLength(t);this.controls.target.copy(e),this.camera.position.copy(e).add(i),this.flight=null;return}this.flight={from:this.controls.target.clone(),to:e,fromDistance:s,toDistance:t,start:this.clock,seconds:.9}}robotAt(e,t){const s=this.canvas.getBoundingClientRect();return this.pointer.set((e-s.left)/s.width*2-1,-((t-s.top)/s.height)*2+1),this.raycaster.setFromCamera(this.pointer,this.camera),this.proxies.updateMatrixWorld(!0),this.raycaster.intersectObjects(this.proxies.children,!1)[0]?.object.userData.robot??null}assetAt(e,t){const s=this.canvas.getBoundingClientRect();this.pointer.set((e-s.left)/s.width*2-1,-((t-s.top)/s.height)*2+1),this.raycaster.setFromCamera(this.pointer,this.camera);for(const i of this.raycaster.intersectObjects([...this.placed.values()].map(n=>n.object),!0))for(const[n,a]of this.placed){let r=i.object;for(;r;){if(r===a.object)return n;r=r.parent}}return null}onDown=e=>{this.pointerAt={x:e.clientX,y:e.clientY,time:performance.now()}};onUp=e=>{const t=this.pointerAt;if(this.pointerAt=null,!t||Math.hypot(e.clientX-t.x,e.clientY-t.y)>6||performance.now()-t.time>500)return;const i=this.robotAt(e.clientX,e.clientY);if(i){this.events.onPick(i);return}const n=this.assetAt(e.clientX,e.clientY);if(n){const a=this.sim.useAsset(n);a&&this.events.onPick(a);return}this.events.onPick(null)};onMove=e=>{if(e.pointerType!=="mouse"||e.buttons)return;const t=this.robotAt(e.clientX,e.clientY);this.hovered=t,this.canvas.style.cursor=t||this.assetAt(e.clientX,e.clientY)?"pointer":""};onLeave=()=>{this.hovered=null,this.canvas.style.cursor=""};draw=e=>{this.frame=requestAnimationFrame(this.draw);const t=Math.min(.1,Math.max(0,(e-this.last)/1e3));this.last=e,this.clock+=t;const s=this.clock;if(Math.floor(s)!==this.hourAt){this.hourAt=Math.floor(s);const p=new Date;this.hour=this.hourOverride??p.getHours()+p.getMinutes()/60+p.getSeconds()/3600,this.sky=hs(this.hour),fi(this.sky.night),this.buildingLights.update(this.sky.night),this.sun.position.copy(this.sky.sun),this.sun.color.copy(this.sky.sunColor);const c=ds(this.island?.seed??1,Date.now(),this.weatherChoice);this.sun.intensity=this.sky.sunIntensity*(c==="rain"?.35:c==="cloudy"?.65:1),this.hemi.intensity=this.sky.hemi,this.hemi.color.copy(new H("#fff0f6").lerp(new H("#a695cf"),this.sky.night)),this.scene.fog.color.copy(this.sky.horizon)}this.sim.update(t,s,this.hour);const i=this.reducedMotion,n=this.island?.radius??40,a=ds(this.island?.seed??1,Date.now(),this.weatherChoice);this.rain.update(t,a,this.controls.target.x,this.controls.target.z,i),this.scenery?.playground.setMotion(this.sim.motion);const r=new Set;for(const[p,c]of this.robots){const d=this.sim.robots.get(p);if(!d)continue;const g=this.groundAt(d.x,d.z,n),j=Jt.has(d.pose),b=d.perched?Math.max(d.y,g):g;c.rig.root.position.set(d.x,b,d.z),c.rig.root.rotation.y=d.heading,c.concert.root.position.set(d.x,g,d.z),c.concert.root.rotation.y=d.heading,c.concert.update(d.pose==="dance"&&this.sim.audience(p)>0,t,s,i);const k=d.plan.act;c.activity.show(k.kind==="wish-register"?"register":k.kind==="interact"&&!d.path.length?k.site.activity:null);const f=k.kind==="work"&&k.seat?.kind==="desk"&&!d.path.length;if(xs(c.rig,d.pose,s+ps(p)%97*.13,{stride:d.stride,calm:i,console:!f&&k.kind!=="interact",lean:d.lean,bored:d.boredom>.72}),k.kind==="interact"&&!d.path.length){if(k.site.activity==="read")c.rig.head.rotation.x=.18,c.rig.arms.forEach(_=>{_.shoulder.rotation.x=-.65,_.elbow.rotation.x=-.85});else if(k.site.activity==="garden"||k.site.activity==="paint"){if(k.site.activity==="garden"){r.add(k.site.key);let _=this.gardenBeds.get(k.site.key);_||(_=bi(),_.root.position.set(k.site.x+Math.sin(k.site.face)*.65,ce+.02,k.site.z+Math.cos(k.site.face)*.65),this.scene.add(_.root),this.gardenBeds.set(k.site.key,_))}c.rig.arms[0].shoulder.rotation.x=-.7,c.rig.arms[0].elbow.rotation.x=-.5+(i?0:Math.sin(s*3)*.16),c.activity.root.rotation.z=k.site.activity==="garden"?-.35:0}}else c.activity.root.rotation.z=0;const E=mn(a,d.pose);c.atmosphere.umbrella.visible=E,c.atmosphere.umbrella.position.y=j?-At:0,E&&(c.rig.arms[1].shoulder.rotation.set(-.5,0,-.35),c.rig.arms[1].elbow.rotation.x=-.7),c.atmosphere.aura.scale.setScalar(i?1:1+Math.sin(s*1.6)*.06),c.atmosphere.aura.position.y=g-b+.035,c.shadow.position.set(d.x,g+.025,d.z),c.shadow.scale.setScalar(d.perched&&b-g>.15?.7:1),c.proxy.position.set(d.x,b+(j?.45:.6),d.z),c.proxy.rotation.y=d.heading;const z=d.bubble;if(z){const _=`${z.tone}:${z.text}`;if(_!==c.bubbleKey){const S=this.bubbles.material(z);S&&(c.bubble.material=S.material,c.bubble.scale.set(.6*S.aspect,.6,1)),c.bubbleKey=_}const L=b+(j?1-At:1),A=i?0:Math.sin(s*2.4+ps(p))*.03;c.bubble.position.set(d.x,L+.55+A,d.z),c.bubble.visible=!0}else c.bubble.visible=!1}for(const[p,c]of this.gardenBeds)c.update(t,r.has(p));if(this.scenery?.update(i?0:s,this.sky.night,this.sky,this.sky.sea),this.flight){const p=Math.min(1,(s-this.flight.start)/this.flight.seconds),c=1-Math.pow(1-p,3),d=this.flight.from.clone().lerp(this.flight.to,c),g=this.flight.fromDistance+(this.flight.toDistance-this.flight.fromDistance)*c,j=this.camera.position.clone().sub(this.controls.target).setLength(g);this.controls.target.copy(d),this.camera.position.copy(d).add(j),p>=1&&(this.flight=null)}this.panByKeys(t);const l=this.selected?this.sim.robots.get(this.selected):void 0;if(l){if(this.following){const p=new oe(l.x,.6,l.z);if(this.flight)this.flight.to.copy(p);else{const c=p.sub(this.controls.target).multiplyScalar(Math.min(1,t*3));this.controls.target.add(c),this.camera.position.add(c)}}this.ring.position.set(l.x,this.groundAt(l.x,l.z,n)+.03,l.z),this.ring.scale.setScalar(i?1:1+Math.sin(s*2)*.04),Math.floor(s*8)!==Math.floor((s-t)*8)&&this.fadeOccluders(l.x,l.z)}const h=this.controls.target,m=Math.hypot(h.x,h.z);m>n+4&&h.multiplyScalar((n+4)/m),h.y=Math.max(0,Math.min(2,h.y)),this.controls.update(),this.placeLabels(),this.renderer.render(this.scene,this.camera)};onKeyDown=e=>{const t=e.key.toLowerCase();!bn.has(t)||e.metaKey||e.ctrlKey||e.altKey||kn(e.target)||this.held.add(t)};onKeyUp=e=>{this.held.delete(e.key.toLowerCase()),e.key==="Shift"&&this.held.delete("shift")};onBlur=()=>this.held.clear();panByKeys(e){if(!this.held.size)return;const t=this.controls.target.clone().sub(this.camera.position);if(t.y=0,t.lengthSq()<1e-6)return;t.normalize();const s=new oe(-t.z,0,t.x),i=new oe;if(this.held.has("w")&&i.add(t),this.held.has("s")&&i.sub(t),this.held.has("d")&&i.add(s),this.held.has("a")&&i.sub(s),i.lengthSq()<1e-6)return;const n=this.camera.position.distanceTo(this.controls.target),a=Math.min(28,Math.max(4,n*.4))*(this.shift?2.2:1);i.normalize().multiplyScalar(a*e),this.controls.target.add(i),this.camera.position.add(i),this.flight=null,this.following=!1}get shift(){return this.held.has("shift")}groundAt(e,t,s){const i=this.scenery;if(i&&fn(e,t,i.walkways))return i.deck;const[n,a]=Ws(e,t);return n===0&&a===0?Math.hypot(e,t)<wt-.6?ce:0:this.tiled.has(`${n},${a}`)&&Lt(e,t)?ce:Qe(Math.hypot(e,t),s)}placeLabels(){if(!this.labels)return;const e=(t,s)=>{const i=s?this.sim.robots.get(s):void 0,n=s?this.robots.get(s):void 0;if(!i||!n){t.hidden=!0;return}const a=Jt.has(i.pose),r=n.rig.root.position.y-(a?At:0),l=new oe(i.x,r,i.z).project(this.camera);if(l.z>1){t.hidden=!0;return}const h=this.canvas.getBoundingClientRect(),m=(l.x*.5+.5)*h.width,p=(-l.y*.5+.5)*h.height;t.hidden=!1;const c=this.residents.find(d=>d.key===s)?.name??"";t.textContent!==c&&(t.textContent=c),t.style.transform=`translate(${m.toFixed(1)}px, ${p.toFixed(1)}px) translate(-50%, 6px)`};e(this.labels.selected,this.selected),e(this.labels.hover,this.hovered&&this.hovered!==this.selected?this.hovered:null)}fadeOccluders(e,t){const s=new oe(e,.8,t),i=this.camera.position.clone(),n=s.clone().sub(i),a=n.length();this.raycaster.set(i,n.normalize()),this.raycaster.far=a-.4;const r=[...this.placed.values()].map(m=>m.object),l=this.raycaster.intersectObjects(r,!0);this.raycaster.far=1/0;const h=new Set;for(const m of l){const p=m.object.parent;if(p)for(const c of p.children)c instanceof O&&h.add(c)}for(const[m,p]of[...this.faded])h.has(m)||(m.material=p,this.faded.delete(m));for(const m of h)this.faded.has(m)||(this.faded.set(m,m.material),m.material=this.fadedOf(m.material))}fadedOf(e){let t=this.fadedMaterials.get(e);return t||(t=e.clone(),t.transparent=!0,t.opacity=.2,t.depthWrite=!1,this.fadedMaterials.set(e,t)),t}restoreFaded(){for(const[e,t]of this.faded)e.material=t;this.faded.clear()}dispose(){this.stop(),this.resize.disconnect(),this.canvas.removeEventListener("pointerdown",this.onDown),this.canvas.removeEventListener("pointerup",this.onUp),this.canvas.removeEventListener("pointermove",this.onMove),this.canvas.removeEventListener("pointerleave",this.onLeave),this.canvas.removeEventListener("webglcontextlost",this.onContextLost),document.removeEventListener("visibilitychange",this.onVisibility),window.removeEventListener("keydown",this.onKeyDown),window.removeEventListener("keyup",this.onKeyUp),window.removeEventListener("blur",this.onBlur),this.controls.dispose(),this.restoreFaded();for(const e of[...this.robots.keys()])this.dropRobot(e);for(const e of this.placed.values())this.scene.remove(e.object);this.placed.clear(),this.cache.dispose(),this.buildingLights.dispose(),this.scenery?.dispose(),this.bubbles.dispose(),this.rain.dispose(),this.society.dispose();for(const e of this.gardenBeds.values())this.scene.remove(e.root),e.dispose();this.gardenBeds.clear(),this.fadedMaterials.forEach(e=>e.dispose()),this.shadowGeometry.dispose(),this.shadowMaterial.dispose(),this.proxyGeometry.dispose(),this.ring.geometry.dispose(),this.ring.material.dispose(),this.renderer.dispose(),this.renderer.forceContextLoss(),this.canvas.remove()}}const bn=new Set(["w","a","s","d","shift"]);function kn(o){const e=o;return!e||typeof e.closest!="function"?!1:!!e.closest("input, textarea, select, [contenteditable]:not([contenteditable='false'])")}function ps(o){let e=0;for(const t of o)e=e*31+(t.codePointAt(0)??0)>>>0;return e%1e3}function Mn(o,e,t){const s=[],i=(e.facing+t.turn)*tt,n=t.turn*tt;for(const a of o.parts){const r=ct(a),l=r.min[1]+t.y,h=r.max[1]+t.y;if(l>.55||h<.16)continue;const m=(r.min[0]+r.max[0])/2,p=(r.min[2]+r.max[2])/2,c=t.x+m*Math.cos(n)+p*Math.sin(n),d=t.z-m*Math.sin(n)+p*Math.cos(n),g=Ce(e,c,d);s.push({cx:g.x,cz:g.z,hx:(r.max[0]-r.min[0])/2,hz:(r.max[2]-r.min[2])/2,yaw:i})}return s}function zn(o,e,t){const s=o.name.toLowerCase(),i=o.use??(/\b(chair|bench|stool)\b|椅|凳/.test(s)?"seat":/\bbed\b|床/.test(s)?"bed":/\b(table|desk|workbench)\b|桌|工作台/.test(s)?"desk":void 0);if(!i||!["seat","desk","bed"].includes(i)||o.kind!=="furniture"&&o.kind!=="decor")return null;let n=o.spot;if(!n){const d=o.parts.map(ct),g=Math.max(...d.map(k=>k.max[2])),j=d.filter(k=>k.max[1]<(i==="seat"?.65:.9)),b=j.length?Math.max(...j.map(k=>k.max[1])):.3;n=i==="desk"?{at:[0,0,g+.45],face:180}:{at:[0,b+.03,0],face:0}}const a=t.turn*tt,[r,l,h]=n.at,m=t.x+r*Math.cos(a)+h*Math.sin(a),p=t.z-r*Math.sin(a)+h*Math.cos(a),c=Ce(e,m,p);return{key:`${t.id}:${o.id}`,kind:i==="desk"?"desk":i==="bed"?"bed":"seat",x:c.x,z:c.z,y:ce+t.y+l,face:(e.facing+t.turn+n.face)*tt,plot:e.id,name:o.name}}const fs=[{id:"often",label:"Often"},{id:"sometimes",label:"Sometimes"},{id:"rarely",label:"Rarely"},{id:"never",label:"Never"}],vn={cozy:"Cozy",curious:"Curious",sporty:"Sporty",artsy:"Artsy",tinkerer:"Tinkerer",dreamy:"Dreamy",foodie:"Foodie",gardener:"Gardener"};function Dn({connected:o,snapshot:e,projects:t,running:s,busy:i,waitingOn:n,held:a,chatTitle:r,chatExists:l,onAsk:h,onOpenChat:m,onClose:p}){const c=yi(o),{rows:d,team:g,teams:j}=$s({connected:o,snapshot:e,projects:t,running:s,busy:i,waitingOn:n,held:a,chatTitle:r,chatExists:l}),b=Us(),k=I.useMemo(()=>(g??[]).map(y=>({id:y.id,name:y.name,agent:y.agent,model:y.model,avatar:y.avatar,teamId:y.teamId,teamName:j.find(C=>C.id===y.teamId)?.name,leader:!y.reportsTo||(g??[]).some(C=>C.reportsTo===y.id)})),[g,j]),f=I.useMemo(()=>c.island?Bs(c.island,k):[],[c.island,k]),E=I.useMemo(()=>c.island?zs(c.island,f).residents:[],[c.island,f]),z=c.island?.wishes.filter(y=>y.state==="queued").length??0,_=I.useMemo(()=>c.island?Fs(c.island):[],[c.island]),L=I.useMemo(()=>xi(d),[d]),A=I.useMemo(()=>JSON.stringify([...L]),[L]),S=I.useRef(null),N=I.useRef(null),$=I.useRef(null),W=I.useRef(null),[X,Y]=I.useState("starting"),[F,V]=I.useState(null),[ve,ne]=I.useState(null),[fe,q]=I.useState(null),[Ee,Ae]=I.useState(()=>typeof window<"u"&&window.innerWidth>860),[de,Ne]=I.useState(null),[Be,Fe]=I.useState(null),[U,me]=I.useState(!1),[_e,De]=I.useState(0),[ue,T]=I.useState("auto");I.useEffect(()=>{W.current?.setWeather(ue)},[ue,X]);const B=JSON.stringify([...i].filter(y=>y.startsWith("chat:island-wish-")).sort());I.useEffect(()=>{o&&c.reload()},[o,B,c.reload]),I.useEffect(()=>{const y=S.current;if(!y)return;const C=window.matchMedia?.("(prefers-reduced-motion: reduce)");let J;try{J=new wn(y,{onPick:ke=>V(ke),onLost:()=>Y("lost"),onWishGiveUp:ke=>{qe.invoke("island_wish_withdraw",{id:ke}).catch(()=>{})},onWishRegister:ke=>{qe.invoke("island_wish_register",{id:ke}).catch(()=>{})}},!!C?.matches)}catch{Y("no");return}N.current&&$.current&&J.setLabels(N.current,$.current),W.current=J,Y("yes");const le=()=>J.setReducedMotion(!!C?.matches);return C?.addEventListener?.("change",le),()=>{C?.removeEventListener?.("change",le),J.dispose(),W.current=null}},[_e]),I.useEffect(()=>{c.island&&W.current&&W.current.setIsland(c.island,f)},[c.island,f,X]);const te=I.useRef(L);te.current=L,I.useEffect(()=>{W.current?.setModes(te.current)},[A,X,f]);const ge=I.useRef(0);I.useEffect(()=>{const y=c.change,C=c.island;if(!(!y||!C||C.rev<y.rev||ge.current>=y.rev)){if(ge.current=y.rev,y.what==="grant"&&y.id){const J=C.wishes.find(ke=>ke.id===y.id),le=J&&Et(J,f);le&&W.current?.event("gift",le.key)}y.what==="home"&&y.id&&W.current?.homeChanged(y.id)}},[c.change,c.island,f]),I.useEffect(()=>{W.current?.select(F)},[F]),I.useEffect(()=>{if(!F){ne(null),q(null);return}const y=()=>{ne(W.current?.describe(F)??null);const J=W.current?.mood(F)??null;q(le=>le&&J&&Math.round(le.boredom*100)===Math.round(J.boredom*100)&&le.excited===J.excited&&le.said===J.said?le:J)};y();const C=window.setInterval(y,500);return()=>window.clearInterval(C)},[F]),I.useEffect(()=>{const y=C=>{C.key==="Escape"&&F&&V(null)};return document.addEventListener("keydown",y),()=>document.removeEventListener("keydown",y)},[F]);const ye=async(y,C)=>{if(!de){Ne(y),Fe(null);try{await C()}catch(J){Fe(String(J?.message??J))}finally{Ne(null)}}},se=F?E.find(y=>y.key===F):void 0,re=se?.agent?d.find(y=>y.id===se.agent.id):void 0,be=y=>_.find(C=>C.who.kind===y.owner.kind&&C.who.id===y.owner.id),Se=I.useMemo(()=>(c.island?.wishes??[]).filter(y=>y.state==="granted").sort((y,C)=>(C.closedAt??C.madeAt)-(y.closedAt??y.madeAt)).slice(0,20),[c.island]),Ie=y=>Et(y,f)?.name??"A robot who left",Oe=y=>{ye(`grant:${y.id}`,()=>c.grantWish(y.id))},pe=y=>de===`grant:${y.id}`||i.has(`chat:island-wish-${y.id}`)||y.execution?.state==="building",dt=y=>y?.activities.find(C=>C.chatKey)?.chatKey??y?.recent?.chatKey??null,ut=x.jsxs(x.Fragment,{children:[x.jsxs("button",{type:"button",className:"projects-page-secondary island-wishes-button","aria-expanded":Ee,"aria-controls":"island-panel",onClick:()=>Ae(y=>!y),title:_.length?`${_.length} open ${_.length===1?"wish":"wishes"}`:"Wishes and residents",children:[x.jsx(ms,{}),x.jsx("span",{children:"Wishes"}),_.length>0&&x.jsx("span",{className:"island-count",children:_.length})]}),x.jsxs("button",{type:"button",className:"projects-page-secondary island-compact",onClick:()=>{V(null),W.current?.recenter()},disabled:X!=="yes","aria-label":"See the whole island",title:"See the whole island",children:[x.jsx(En,{}),x.jsx("span",{children:"Whole island"})]})]});return x.jsxs("section",{className:"projects-page island-page","aria-label":"Island",children:[x.jsx(Gs,{root:!0,back:{label:"Chat",ariaLabel:"Back to chat",onClick:p},title:x.jsx("h1",{children:"Island"}),actions:ut}),Be&&x.jsx("p",{className:"island-error",role:"alert",children:Be}),x.jsxs("div",{className:`island-body${Ee?" has-panel":""}`,children:[x.jsxs("div",{className:"island-stage",ref:S,role:"img","aria-label":`The island in 3D, with ${f.length} robots. Use the panel's list to find someone.`,children:[x.jsx("div",{className:"island-name",ref:N,hidden:!0}),x.jsx("div",{className:"island-name is-selected",ref:$,hidden:!0}),X==="no"&&x.jsx("p",{className:"island-note",role:"status",children:"This browser cannot draw the island in 3D here. The wishes and residents are in the panel."}),X==="lost"&&x.jsxs("div",{className:"island-note",role:"status",children:[x.jsx("p",{children:"The 3D view stopped."}),x.jsx("button",{type:"button",className:"projects-page-secondary",onClick:()=>{Y("starting"),De(y=>y+1)},children:"Draw it again"})]}),!c.island&&!c.error&&X!=="no"&&x.jsx("p",{className:"island-note is-quiet",role:"status",children:"Sailing to the island…"}),c.error&&!c.island&&x.jsxs("div",{className:"island-note",role:"alert",children:[x.jsx("p",{children:c.error}),x.jsx("button",{type:"button",className:"projects-page-secondary",onClick:c.reload,children:"Try again"})]}),se&&x.jsx(Pn,{resident:se,row:re,status:ve,mood:fe,housemates:se.plot?E.filter(y=>y.plot?.id===se.plot?.id&&y.key!==se.key).map(y=>y.name):[],wish:be(se),busy:!!de||!o,onGrant:Oe,building:!!be(se)&&pe(be(se)),onOpenChat:y=>m(y),chatKey:dt(re),onAsk:se.agent?()=>h(se.agent.id,"On the OctiqFlow island, build yourself "):void 0,onFarewell:se.owner.kind==="bot"?async()=>{await b({title:`Say goodbye to ${se.name}?`,body:`${se.name} sails away. Its plot, what stands on it and its open wish go with it.`,confirmLabel:"Say goodbye",danger:!0})&&(V(null),await ye("farewell",()=>c.farewell(se.owner.id)))}:void 0,onClose:()=>V(null)})]}),Ee&&x.jsxs("aside",{id:"island-panel",className:"island-panel","aria-label":"Wishes and residents",children:[x.jsxs("div",{className:"island-panel-head",children:[x.jsx("h2",{children:"Wishes"}),x.jsx("button",{type:"button",className:"island-close","aria-label":"Close the panel",title:"Close",onClick:()=>Ae(!1),children:x.jsx(Ps,{})})]}),z>0&&x.jsxs("p",{className:"island-meta",children:[z," waiting to register at BOT Society"]}),_.length===0?x.jsx("p",{className:"island-empty",children:"No wishes right now. Robots make one now and then."}):x.jsx("ul",{className:"island-wishes",children:_.map(y=>{const C=Et(y,f);return x.jsxs("li",{className:"island-wish",children:[x.jsxs("button",{type:"button",className:"island-wish-who",onClick:()=>C&&V(C.key),disabled:!C,title:C?`Show ${C.name}`:void 0,children:[x.jsx(Ct,{resident:C}),x.jsx("bdi",{children:Ie(y)}),x.jsx("span",{className:"island-meta",children:wi(y.madeAt)})]}),x.jsxs("p",{className:"island-wish-text",children:["wishes for ",x.jsx("bdi",{children:y.text})]}),y.execution?.state==="unfinished"&&!pe(y)&&x.jsx("p",{className:"island-meta",role:"status",children:"The present is not finished. Retry to continue."}),x.jsxs("div",{className:"island-wish-actions",children:[x.jsx("button",{type:"button",className:"projects-page-primary island-grant",onClick:()=>Oe(y),disabled:!!de||pe(y)||!o,title:"Build this present in the background",children:pe(y)?"Building…":y.execution?"Retry":"Grant"}),x.jsx("button",{type:"button",className:"projects-page-secondary",disabled:!!de,onClick:()=>{ye(`dismiss:${y.id}`,()=>c.dismissWish(y.id))},children:"Dismiss"})]})]},y.id)})}),x.jsxs("div",{className:"island-pace",children:[x.jsx("label",{htmlFor:"island-weather",children:"Island weather"}),x.jsxs("select",{id:"island-weather",value:ue,onChange:y=>T(y.target.value),children:[x.jsx("option",{value:"auto",children:"Automatic"}),x.jsx("option",{value:"sunny",children:"Sunny"}),x.jsx("option",{value:"cloudy",children:"Cloudy"}),x.jsx("option",{value:"rain",children:"Rain"})]}),x.jsx("label",{htmlFor:"island-building",children:"Autonomous building"}),x.jsx("select",{id:"island-building",value:c.island?.settings.buildPace??"sometimes",disabled:!c.island||!!de,onChange:y=>{ye("building",()=>c.setBuildPace(y.target.value))},children:fs.map(y=>x.jsx("option",{value:y.id,children:y.label},y.id))}),x.jsx("label",{htmlFor:"island-pace",children:"New wishes"}),x.jsx("select",{id:"island-pace",value:c.island?.settings.wishPace??"sometimes",disabled:!c.island||!!de,onChange:y=>{ye("pace",()=>c.setPace(y.target.value))},children:fs.map(y=>x.jsx("option",{value:y.id,children:y.label},y.id))}),x.jsx("button",{type:"button",className:"projects-page-secondary",disabled:!c.island||!!de,onClick:()=>{ye("roll",c.rollWish)},children:"Ask for a wish"})]}),Se.length>0&&x.jsxs("div",{className:"island-granted",children:[x.jsxs("button",{type:"button",className:"island-disclosure","aria-expanded":U,onClick:()=>me(y=>!y),children:[x.jsx(An,{open:U}),"Granted · ",Se.length]}),U&&x.jsx("ul",{children:Se.map(y=>x.jsxs("li",{children:[x.jsx("bdi",{children:Ie(y)})," got ",x.jsx("bdi",{children:y.text}),y.grant?.by.name&&x.jsxs("span",{className:"island-meta",children:[" · from ",x.jsx("bdi",{children:y.grant.by.name})]})]},y.id))})]}),x.jsx("h2",{className:"island-panel-sub",children:"Who lives here"}),x.jsx("ul",{className:"island-residents",children:f.map(y=>{const C=y.agent?d.find(J=>J.id===y.agent.id):void 0;return x.jsx("li",{children:x.jsxs("button",{type:"button","aria-pressed":F===y.key,onClick:()=>V(y.key),children:[x.jsx(Ct,{resident:y}),x.jsx("bdi",{className:"island-resident-name",children:y.name}),x.jsx("span",{className:"island-meta",children:y.agent?Sn(C):Ss(y)}),be(y)&&x.jsx("span",{className:"island-has-wish",title:"Has a wish",children:x.jsx(ms,{})})]})},y.key)})})]})]})]})}function _n(o){return o.length<=1?o[0]??"":`${o.slice(0,-1).join(", ")} & ${o[o.length-1]}`}function Ss(o){const e=vn[o.trait??""];return e?`${e} 波特`:"波特"}function Sn(o){switch(o?.state){case"working":return"Working";case"needs_you":return"Needs you";case"failed":return"Failed";default:return"Agent"}}function Pn({resident:o,row:e,status:t,mood:s,housemates:i,wish:n,busy:a,building:r,chatKey:l,onGrant:h,onOpenChat:m,onAsk:p,onFarewell:c,onClose:d}){const g=o.agent,j=e?.state==="needs_you"?"decide":e?.state==="failed"?"danger":void 0;return x.jsxs("div",{className:"island-card",role:"dialog","aria-label":o.name,children:[x.jsxs("div",{className:"island-card-head",children:[g?x.jsx(Ks,{name:g.name,id:g.id,avatar:g.avatar,size:30,decorative:!0}):x.jsx(Ct,{resident:o,large:!0}),x.jsxs("div",{className:"island-card-who",children:[x.jsx("bdi",{className:"island-card-name",children:o.name}),x.jsx("span",{className:"island-meta",children:g?"Agent":Ss(o)})]}),x.jsx("button",{type:"button",className:"island-close","aria-label":"Stop following",title:"Stop following",onClick:d,children:x.jsx(Ps,{})})]}),t&&x.jsx("p",{className:"island-card-status","data-tone":j,children:t}),!!o.hobbies?.length&&x.jsxs("p",{className:"island-meta",children:["Interests: ",o.hobbies.join(", ")]}),o.plot?.officeName&&x.jsxs("p",{className:"island-meta",children:[o.plot.officeName," · Personal desk"]}),i.length>0&&x.jsxs("p",{className:"island-meta island-card-home",children:["Office with ",x.jsx("bdi",{children:_n(i)})]}),s?.said&&x.jsxs("p",{className:"island-card-said",children:["“",x.jsx("bdi",{children:s.said}),"”"]}),s&&x.jsx(jn,{boredom:s.boredom,excited:s.excited}),n&&x.jsxs("div",{className:"island-card-wish",children:[x.jsxs("p",{children:["Wishes for ",x.jsx("bdi",{children:n.text})]}),n.execution?.state==="unfinished"&&!r&&x.jsx("p",{className:"island-meta",role:"status",children:"The present is not finished. Retry to continue."}),x.jsx("button",{type:"button",className:"projects-page-primary island-grant",disabled:a||r,onClick:()=>h(n),children:r?"Building…":n.execution?"Retry":"Grant"})]}),x.jsxs("div",{className:"island-card-actions",children:[l&&x.jsx("button",{type:"button",className:"projects-page-secondary",onClick:()=>m(l),children:"Open chat"}),p&&x.jsx("button",{type:"button",className:"projects-page-secondary",onClick:p,title:"Start a chat with this agent about something to build for itself",children:"Ask to build"}),c&&x.jsx("button",{type:"button",className:"projects-page-secondary",disabled:a,onClick:c,children:"Say goodbye"})]})]})}function jn({boredom:o,excited:e}){const t=Math.round(o*100);return x.jsxs("div",{className:"island-boredom",children:[x.jsx("span",{className:"island-meta",children:e?"Excited: work came!":"Boredom"}),x.jsx("span",{className:"island-boredom-bar",role:"meter","aria-label":"Boredom","aria-valuemin":0,"aria-valuemax":100,"aria-valuenow":t,children:x.jsx("span",{style:{width:`${t}%`}})}),x.jsxs("span",{className:"island-meta island-boredom-value",children:[t,"%"]})]})}function Ct({resident:o,large:e=!1}){const t=o?{"--robot-shell":o.look.shell,"--robot-trim":o.look.trim,"--robot-glow":o.look.glow}:void 0;return x.jsx("span",{className:`island-dot${e?" is-large":""}`,style:t,"aria-hidden":"true",children:x.jsx("span",{})})}function ms(){return x.jsxs("svg",{width:"15",height:"15",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"1.8",strokeLinecap:"round",strokeLinejoin:"round","aria-hidden":"true",children:[x.jsx("rect",{x:"3",y:"8",width:"18",height:"4",rx:"1"}),x.jsx("path",{d:"M12 8v13M19 12v7a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2v-7"}),x.jsx("path",{d:"M7.5 8a2.5 2.5 0 0 1 0-5C9 3 12 8 12 8s3-5 4.5-5a2.5 2.5 0 0 1 0 5"})]})}function En(){return x.jsxs("svg",{width:"15",height:"15",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"1.8",strokeLinecap:"round",strokeLinejoin:"round","aria-hidden":"true",children:[x.jsx("path",{d:"M2 18c3 0 3-1.5 5-1.5S10 18 12 18s3-1.5 5-1.5 2 1.5 5 1.5"}),x.jsx("path",{d:"M5 15c2-3 12-3 14 0"}),x.jsx("path",{d:"M12 13V6M12 6c-1.5-2-4-2-5.5-.5M12 6c1.5-2 4-2 5.5-.5M12 6c-.5-2 .5-3.5 2-4"})]})}function Ps(){return x.jsx("svg",{width:"14",height:"14",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round","aria-hidden":"true",children:x.jsx("path",{d:"M18 6 6 18M6 6l12 12"})})}function An({open:o}){return x.jsx("svg",{className:`island-chevron${o?" is-open":""}`,width:"12",height:"12",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round","aria-hidden":"true",children:x.jsx("path",{d:"m9 6 6 6-6 6"})})}export{Dn as default};
|
|
Binary file
|
|
Binary file
|