mudlet-map-renderer 0.22.0-konva → 0.22.1-konva

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const y=require("konva"),H=["north","south","east","west","northeast","northwest","southeast","southwest"],T={north:"n",south:"s",east:"e",west:"w",northeast:"ne",northwest:"nw",southeast:"se",southwest:"sw",up:"u",down:"d",in:"i",out:"o"},it={north:{x:0,y:-1},south:{x:0,y:1},east:{x:1,y:0},west:{x:-1,y:0},northeast:{x:1,y:-1},northwest:{x:-1,y:-1},southeast:{x:1,y:1},southwest:{x:-1,y:1}},ct=["north","south","east","west","northeast","northwest","southeast","southwest"],wt={north:"south",south:"north",east:"west",west:"east",northeast:"southwest",northwest:"southeast",southeast:"northwest",southwest:"northeast"};function dt(E){return E?Object.prototype.hasOwnProperty.call(it,E):!1}function A(E,t,e,i=1){if(!dt(e))return{x:E,y:t};const s=it[e];return{x:E+s.x*i,y:t+s.y*i}}function Rt(E,t,e,i=1,s=0){if(!dt(e))return{x:E,y:t};const o=it[e];if(!(o.x!==0&&o.y!==0)||s<=0)return A(E,t,e,i);const r=i-s+s/Math.SQRT2;return{x:E+o.x*r,y:t+o.y*r}}function vt(E,t,e,i=1){if(!dt(e))return{x:E,y:t};const s=it[e],o=Math.atan2(s.y,s.x);return{x:E+Math.cos(o)*i,y:t+Math.sin(o)*i}}const q={OPEN_DOOR:"rgb(10, 155, 10)",CLOSED_DOOR:"rgb(226, 205, 59)",LOCKED_DOOR:"rgb(155, 10, 10)",ONE_WAY_FILL:"rgb(155, 10, 10)"},St={1:"north",2:"northeast",3:"northwest",4:"east",5:"west",6:"south",7:"southeast",8:"southwest",9:"up",10:"down",11:"in",12:"out"},kt=["up","down","in","out"];function lt(E){switch(E){case 1:return q.OPEN_DOOR;case 2:return q.CLOSED_DOOR;default:return q.LOCKED_DOOR}}class Ct{constructor(t,e){this.mapReader=t,this.mapRenderer=e}getRoomEdgePoint(t,e,i,s){return h.roomShape==="circle"?vt(t,e,i,s):h.roomShape==="roundedRectangle"?Rt(t,e,i,s,h.roomSize*.2):A(t,e,i,s)}renderData(t,e){return this.renderDataWithColor(t,h.lineColor,e)}renderDataWithColor(t,e,i){const s=t.aDir&&H.includes(t.aDir),o=t.bDir&&H.includes(t.bDir);if(s&&o)return this.renderTwoWayExitData(t,e,i);if(s||o){const n=s?"a":"b";return this.renderOneWayExitData(t,e,n)}}renderTwoWayExitData(t,e,i){const s=this.mapReader.getRoom(t.a),o=this.mapReader.getRoom(t.b);if(!s||!o||!t.aDir||!t.bDir||s.customLines[T[t.aDir]]&&o.customLines[T[t.bDir]]||s.z!==o.z&&(i!==o.z&&s.customLines[T[t.aDir]]||i!==s.z&&o.customLines[T[t.bDir]]))return;const n=this.getRoomEdgePoint(s.x,s.y,t.aDir,h.roomSize/2),r=this.getRoomEdgePoint(o.x,o.y,t.bDir,h.roomSize/2),a=[n.x,n.y,r.x,r.y],c=[{points:a,stroke:e,strokeWidth:h.lineWidth}],l=[],d=s.doors[T[t.aDir]]??o.doors[T[t.bDir]];if(d){const p=a[0]+(a[2]-a[0])/2,w=a[1]+(a[3]-a[1])/2;l.push({x:p-h.roomSize/4,y:w-h.roomSize/4,width:h.roomSize/2,height:h.roomSize/2,stroke:lt(d),strokeWidth:h.lineWidth})}const u=Math.min(a[0],a[2]),g=Math.max(a[0],a[2]),f=Math.min(a[1],a[3]),m=Math.max(a[1],a[3]);return{lines:c,arrows:[],doors:l,bounds:{x:u,y:f,width:g-u,height:m-f}}}renderOneWayExitData(t,e,i){const s=i==="a"||!i&&t.aDir,o=s?this.mapReader.getRoom(t.a):this.mapReader.getRoom(t.b),n=s?this.mapReader.getRoom(t.b):this.mapReader.getRoom(t.a),r=s?t.aDir:t.bDir;if(!r||!o||!n||!H.includes(r)||o.customLines[T[r]||r])return;if(o.area!=n.area&&r){const P=this.mapReader.getColorValue(n.env),X=this.getRoomEdgePoint(o.x,o.y,r,h.roomSize/2),Y=A(o.x,o.y,r,h.roomSize*1.5),x=P;return{lines:[],arrows:[{points:[X.x,X.y,Y.x,Y.y],pointerLength:.3,pointerWidth:.3,strokeWidth:h.lineWidth*1.4,stroke:x,fill:x}],doors:[],bounds:{x:Math.min(X.x,Y.x),y:Math.min(X.y,Y.y),width:Math.abs(Y.x-X.x),height:Math.abs(Y.y-X.y)}}}let a={x:n.x,y:n.y};(n.area!==o.area||n.z!==o.z)&&(a=A(o.x,o.y,r,h.roomSize/2));const c=A(o.x,o.y,r,.3),l=c.x-(c.x-a.x)/2,d=c.y-(c.y-a.y)/2,u=this.getRoomEdgePoint(o.x,o.y,r,h.roomSize/2),g=[u.x,u.y,a.x,a.y],f=[u.x,a.x,l],m=[u.y,a.y,d],p=Math.min(...f),w=Math.max(...f),R=Math.min(...m),k=Math.max(...m);return{lines:[{points:g,stroke:e,strokeWidth:h.lineWidth,dash:[.1,.05]}],arrows:[{points:[g[0],g[1],l,d],pointerLength:.5,pointerWidth:.35,strokeWidth:h.lineWidth*1.4,stroke:e,fill:q.ONE_WAY_FILL,dash:[.1,.05]}],doors:[],bounds:{x:p,y:R,width:w-p,height:k-R}}}render(t,e){return this.renderWithColor(t,h.lineColor,e)}renderWithColor(t,e,i){const s=t.aDir&&H.includes(t.aDir),o=t.bDir&&H.includes(t.bDir);if(s&&o)return this.renderTwoWayExit(t,e,i);if(s||o){const n=s?"a":"b";return this.renderOneWayExit(t,e,n)}}renderTwoWayExit(t,e,i){const s=this.mapReader.getRoom(t.a),o=this.mapReader.getRoom(t.b);if(!s||!o||!t.aDir||!t.bDir||s.customLines[T[t.aDir]]&&o.customLines[T[t.bDir]]||s.z!==o.z&&(i!==o.z&&s.customLines[T[t.aDir]]||i!==s.z&&o.customLines[T[t.bDir]]))return;const n=new y.Group({listening:!1}),r=[];if(r.push(...Object.values(this.getRoomEdgePoint(s.x,s.y,t.aDir,h.roomSize/2))),r.push(...Object.values(this.getRoomEdgePoint(o.x,o.y,t.bDir,h.roomSize/2))),s.doors[T[t.aDir]]||o.doors[T[t.bDir]]){const c=this.renderDoor(r,s.doors[T[t.aDir]]??o.doors[T[t.bDir]]);n.add(c)}const a=new y.Line({points:r,stroke:e,strokeWidth:h.lineWidth,perfectDrawEnabled:!1,listening:!1});return n.add(a),n}renderOneWayExit(t,e,i){const s=i==="a"||!i&&t.aDir,o=s?this.mapReader.getRoom(t.a):this.mapReader.getRoom(t.b),n=s?this.mapReader.getRoom(t.b):this.mapReader.getRoom(t.a),r=s?t.aDir:t.bDir;if(!r||!o||!n||!H.includes(r)||o.customLines[T[r]||r])return;if(o.area!=n.area&&r){const p=this.mapReader.getColorValue(n.env);return this.renderAreaExit(o,r,p)}let a={x:n.x,y:n.y};(n.area!==o.area||n.z!==o.z)&&(a=A(o.x,o.y,r,h.roomSize/2));const c=A(o.x,o.y,r,.3),l=c.x-(c.x-a.x)/2,d=c.y-(c.y-a.y)/2,u=new y.Group({listening:!1}),g=[];g.push(...Object.values(this.getRoomEdgePoint(o.x,o.y,r,h.roomSize/2))),g.push(a.x,a.y);const f=new y.Line({points:g,stroke:e,strokeWidth:h.lineWidth,dashEnabled:!0,dash:[.1,.05],perfectDrawEnabled:!1,listening:!1});u.add(f);const m=new y.Arrow({points:[g[0],g[1],l,d],pointerLength:.5,pointerWidth:.35,strokeWidth:h.lineWidth*1.4,stroke:e,fill:q.ONE_WAY_FILL,dashEnabled:!0,dash:[.1,.05],perfectDrawEnabled:!1,listening:!1});return u.add(m),u}renderAreaExit(t,e,i){const s=this.getRoomEdgePoint(t.x,t.y,e,h.roomSize/2),o=A(t.x,t.y,e,h.roomSize*1.5),n=i??this.mapReader.getColorValue(t.env);return new y.Arrow({points:[s.x,s.y,o.x,o.y],pointerLength:.3,pointerWidth:.3,strokeWidth:h.lineWidth*1.4,stroke:n,fill:n,perfectDrawEnabled:!1,listening:!1})}renderSpecialExits(t,e){return Object.entries(t.customLines).flatMap(([i,s])=>{const o=[t.x,t.y];s.points.reduce((u,g)=>(u.push(g.x,-g.y),u),o);const n=s.attributes.arrow?y.Arrow:y.Line,r=e??`rgb(${s.attributes.color.r}, ${s.attributes.color.g}, ${s.attributes.color.b})`,a=new n({points:o,strokeWidth:h.lineWidth,stroke:r,fill:e??`rgb(${s.attributes.color.r}, ${s.attributes.color.g} , ${s.attributes.color.b})`,pointerLength:.3,pointerWidth:.2,perfectDrawEnabled:!1,listening:!1});let c=s.attributes.style;c==="dot line"?(a.dash([.05,.05]),a.dashOffset(.1)):c==="dash line"?a.dash([.4,.2]):c==="solid line"||c!==void 0&&console.log("Brak opisu stylu: "+c);const l=[a],d=t.doors[i];return d&&o.length>=4&&l.push(this.renderDoor(o,d)),l})}renderStubs(t,e=h.lineColor){return t.stubs.map(i=>{const s=St[i],o=this.getRoomEdgePoint(t.x,t.y,s,h.roomSize/2),n=A(t.x,t.y,s,h.roomSize/2+.5),r=[o.x,o.y,n.x,n.y];return new y.Line({points:r,stroke:e,strokeWidth:h.lineWidth,perfectDrawEnabled:!1,listening:!1})})}renderInnerExits(t){return kt.map(e=>{if(t.exits[e]){const i=new y.Group({listening:!1}),s=new y.RegularPolygon({x:t.x,y:t.y,sides:3,fill:this.mapReader.getSymbolColor(t.env,.6),stroke:this.mapReader.getSymbolColor(t.env),strokeWidth:h.lineWidth,radius:h.roomSize/5,scaleX:1.4,scaleY:.8,perfectDrawEnabled:!1,listening:!1});i.add(s);let o=t.doors[e];if(o!==void 0)switch(o){case 1:s.stroke(q.OPEN_DOOR);break;case 2:s.stroke(q.CLOSED_DOOR);break;default:s.stroke(q.LOCKED_DOOR)}const n=s.stroke();switch(e){case"up":s.position(A(t.x,t.y,"south",h.roomSize/4));break;case"down":s.rotation(180),s.position(A(t.x,t.y,"north",h.roomSize/4));break;case"in":{s.rotation(90),s.position(A(t.x,t.y,"west",h.roomSize/4));const r=A(t.x,t.y,"east",h.roomSize/4);i.add(new y.RegularPolygon({x:r.x,y:r.y,sides:3,fill:s.fill(),stroke:n,strokeWidth:h.lineWidth,radius:h.roomSize/5,scaleX:1.4,scaleY:.8,rotation:-90,perfectDrawEnabled:!1,listening:!1}));break}case"out":{s.rotation(-90),s.position(A(t.x,t.y,"west",h.roomSize/4));const r=A(t.x,t.y,"east",h.roomSize/4);i.add(new y.RegularPolygon({x:r.x,y:r.y,sides:3,fill:s.fill(),stroke:n,strokeWidth:h.lineWidth,radius:h.roomSize/5,scaleX:1.4,scaleY:.8,rotation:90,perfectDrawEnabled:!1,listening:!1}));break}}return i}}).filter(e=>e!==void 0)}renderDoor(t,e){const i={x:t[0]+(t[2]-t[0])/2,y:t[1]+(t[3]-t[1])/2};return new y.Rect({x:i.x-h.roomSize/4,y:i.y-h.roomSize/4,width:h.roomSize/2,height:h.roomSize/2,stroke:lt(e),strokeWidth:h.lineWidth,perfectDrawEnabled:!1,listening:!1})}}class Et{constructor(t,e){this.rooms=[],this.labels=[],this.rooms=t,this.bounds=this.createBounds(),this.labels=e}getRooms(){return this.rooms}getLabels(){return this.labels}getBounds(){return this.bounds}createBounds(){return this.rooms.reduce((t,e)=>({minX:Math.min(t.minX,e.x),maxX:Math.max(t.maxX,e.x),minY:Math.min(t.minY,e.y),maxY:Math.max(t.maxY,e.y)}),{minX:Number.POSITIVE_INFINITY,maxX:Number.NEGATIVE_INFINITY,minY:Number.POSITIVE_INFINITY,maxY:Number.NEGATIVE_INFINITY})}}const et=class et{constructor(t){this.planes={},this.exits=new Map,this.version=0,this.area=t,this.planes=this.createPlanes(),this.createExits()}getAreaName(){return this.area.areaName}getAreaId(){return parseInt(this.area.areaId)}getVersion(){return this.version}markDirty(){this.version++}getPlane(t){return this.planes[t]}getPlanes(){return Object.values(this.planes)}getRooms(){return this.area.rooms}getLinkExits(t){return Array.from(this.exits.values()).filter(e=>e.zIndex.includes(t))}createPlanes(){const t=this.area.rooms.reduce((e,i)=>(e[i.z]||(e[i.z]=[]),e[i.z].push(i),e),{});return Object.entries(t).reduce((e,[i,s])=>(e[+i]=new Et(s,this.area.labels.filter(o=>o.Z===+i)),e),{})}createExits(){const t=new Map;this.area.rooms.forEach(e=>{Object.entries(e.exits).forEach(([i,s])=>{if(e.id===s)return;const o=Math.min(e.id,s),n=Math.max(e.id,s),r=`${o}-${n}`;t.has(r)||t.set(r,[]),t.get(r).push({origin:e.id,target:s,z:e.z,dir:i})})});for(const[e,i]of t){const[s,o]=e.split("-"),n=parseInt(s),r=parseInt(o),a=i.filter(d=>d.origin===n),c=i.filter(d=>d.origin===r),l=new Set;for(const d of a){let u=-1;for(let g=0;g<c.length;g++)if(!l.has(g)){if(c[g].dir===et.oppositeDir[d.dir]){u=g;break}u===-1&&(u=g)}if(u!==-1){l.add(u);const g=c[u];this.exits.set(`${e}-${d.dir}`,{a:n,b:r,aDir:d.dir,bDir:g.dir,zIndex:[d.z,g.z]})}else this.exits.set(`${e}-a:${d.dir}`,{a:n,b:r,aDir:d.dir,zIndex:[d.z]})}for(let d=0;d<c.length;d++)if(!l.has(d)){const u=c[d];this.exits.set(`${e}-b:${u.dir}`,{a:n,b:r,bDir:u.dir,zIndex:[u.z]})}}}};et.oppositeDir={north:"south",south:"north",east:"west",west:"east",northeast:"southwest",southwest:"northeast",northwest:"southeast",southeast:"northwest",up:"down",down:"up",in:"out",out:"in"};let _=et;class ut extends Et{constructor(t,e){super(t.getRooms(),t.getLabels()),this.basePlane=t,this.visitedRooms=e}getRooms(){return this.basePlane.getRooms().filter(t=>this.visitedRooms.has(t.id))}getLabels(){return this.basePlane.getLabels()}getBounds(){const t=this.getRooms();return t.length?t.reduce((e,i)=>({minX:Math.min(e.minX,i.x),maxX:Math.max(e.maxX,i.x),minY:Math.min(e.minY,i.y),maxY:Math.max(e.maxY,i.y)}),{minX:Number.POSITIVE_INFINITY,maxX:Number.NEGATIVE_INFINITY,minY:Number.POSITIVE_INFINITY,maxY:Number.NEGATIVE_INFINITY}):this.basePlane.getBounds()}}class tt extends _{constructor(t,e){super(t),this.planeCache=new WeakMap,this.visitedRooms=e instanceof Set?e:new Set(e??[]),this.areaRoomIds=new Set(t.rooms.map(i=>i.id))}getPlane(t){const e=super.getPlane(t);if(!e)return e;let i=this.planeCache.get(e);return i||(i=new ut(e,this.visitedRooms),this.planeCache.set(e,i)),i}getPlanes(){return super.getPlanes().map(t=>{let e=this.planeCache.get(t);return e||(e=new ut(t,this.visitedRooms),this.planeCache.set(t,e)),e})}getLinkExits(t){return super.getLinkExits(t).filter(e=>this.visitedRooms.has(e.a)||this.visitedRooms.has(e.b))}getVisitedRoomCount(){return super.getRooms().reduce((t,e)=>t+(this.visitedRooms.has(e.id)?1:0),0)}getTotalRoomCount(){return this.areaRoomIds.size}hasVisitedRoom(t){return this.areaRoomIds.has(t)&&this.visitedRooms.has(t)}getVisitedRoomIds(){return super.getRooms().filter(t=>this.visitedRooms.has(t.id)).map(t=>t.id)}addVisitedRoom(t){const e=this.visitedRooms.has(t);this.visitedRooms.add(t);const i=!e&&this.areaRoomIds.has(t);return i&&this.markDirty(),i}addVisitedRooms(t){let e=0;for(const i of t){const s=this.visitedRooms.has(i);this.visitedRooms.add(i),!s&&this.areaRoomIds.has(i)&&e++}return e>0&&this.markDirty(),e}}const Q=["up","down","in","out"];class Mt{constructor(t,e){this.paths=[],this.mapReader=t,this.overlayLayer=e}getRoomEdgePoint(t,e,i,s){return h.roomShape==="circle"?vt(t,e,i,s):h.roomShape==="roundedRectangle"?Rt(t,e,i,s,h.roomSize*.2):A(t,e,i,s)}findConnection(t,e){for(const[i,s]of Object.entries(t.exits))if(s===e.id){const o=i;if(Q.includes(o)){const a=T[o],c=t.customLines[a]?a:t.customLines[o]?o:void 0;return{type:"inner",fromDir:o,customLineKey:c,fromRoom:t,toRoom:e}}const n=T[o];if(t.customLines[n])return{type:"special",fromDir:o,customLineKey:n,fromRoom:t,toRoom:e};if(t.customLines[o])return{type:"special",fromDir:o,customLineKey:o,fromRoom:t,toRoom:e};const r=this.findExitDirection(e,t.id);return{type:"regular",fromDir:o,toDir:r,fromRoom:t,toRoom:e}}for(const[i,s]of Object.entries(t.specialExits))if(s===e.id)return t.customLines[i]?{type:"special",customLineKey:i,fromRoom:t,toRoom:e}:{type:"inner",fromRoom:t,toRoom:e};for(const[i,s]of Object.entries(e.exits))if(s===t.id){const o=i;if(Q.includes(o)){const r=T[o],a=e.customLines[r]?r:e.customLines[o]?o:void 0;return{type:"inner",toDir:o,customLineKey:a,fromRoom:t,toRoom:e}}const n=T[o];return e.customLines[n]?{type:"special",toDir:o,customLineKey:n,fromRoom:t,toRoom:e}:e.customLines[o]?{type:"special",toDir:o,customLineKey:o,fromRoom:t,toRoom:e}:{type:"regular",toDir:o,fromRoom:t,toRoom:e}}for(const[i,s]of Object.entries(e.specialExits))if(s===t.id)return e.customLines[i]?{type:"special",customLineKey:i,fromRoom:t,toRoom:e}:{type:"inner",fromRoom:t,toRoom:e};return{type:"none",fromRoom:t,toRoom:e}}findExitDirection(t,e){for(const[i,s]of Object.entries(t.exits))if(s===e)return i}createStrokedLine(t,e){const i=new y.Group;return i.opacity(.8),i.add(new y.Line({points:t,stroke:"black",strokeWidth:h.lineWidth*8,lineCap:"round",lineJoin:"round"})),i.add(new y.Line({points:t,stroke:e,strokeWidth:h.lineWidth*4,lineCap:"round",lineJoin:"round"})),i}renderInnerExitMarker(t,e,i){const s=new y.Group;s.opacity(.8);const o=new y.RegularPolygon({x:t.x,y:t.y,sides:3,fill:i,stroke:"black",strokeWidth:h.lineWidth*2,radius:h.roomSize/5,scaleX:1.4,scaleY:.8});switch(e){case"up":o.position(A(t.x,t.y,"south",h.roomSize/4));break;case"down":o.rotation(180),o.position(A(t.x,t.y,"north",h.roomSize/4));break;case"in":const n=o.clone();n.rotation(-90),n.position(A(t.x,t.y,"east",h.roomSize/4)),s.add(n),o.rotation(90),o.position(A(t.x,t.y,"west",h.roomSize/4));break;case"out":const r=o.clone();r.rotation(90),r.position(A(t.x,t.y,"east",h.roomSize/4)),s.add(r),o.rotation(-90),o.position(A(t.x,t.y,"west",h.roomSize/4));break}return s.add(o),s}renderPath(t,e,i,s="#66E64D"){if(e===void 0||i===void 0)return;const o=t.map(a=>this.mapReader.getRoom(a)).filter(a=>a!==void 0);let n=[];const r=()=>{if(n.length>=4){const a=this.createStrokedLine(n,s);this.overlayLayer.add(a),this.paths.push(a)}n=[]};for(let a=0;a<o.length-1;a++){const c=o[a],l=o[a+1],d=this.isRoomVisible(c,e,i),u=this.isRoomVisible(l,e,i);if(!d&&!u){r();continue}const g=this.findConnection(c,l);if(d&&u)switch(g.type){case"regular":this.addRegularConnectionPoints(g,n);break;case"special":this.addSpecialConnectionPoints(g,n);break;case"inner":r(),this.renderInnerConnection(g,s);break;case"none":n.length===0&&n.push(c.x,c.y),n.push(l.x,l.y);break}else{const f=d?c:l,m=d?l:c,p=this.getExitToRoom(f,m);if(p){if(Q.includes(p.direction)){r();const w=this.renderInnerExitMarker(f,p.direction,s);this.overlayLayer.add(w),this.paths.push(w)}else if(H.includes(p.direction)){n.length===0&&n.push(f.x,f.y);const w=this.getRoomEdgePoint(f.x,f.y,p.direction,h.roomSize/2),R=A(f.x,f.y,p.direction,h.roomSize);n.push(w.x,w.y,R.x,R.y),r()}}else{const w=this.getDirectionTowards(f,m);if(w){n.length===0&&n.push(f.x,f.y);const R=this.getRoomEdgePoint(f.x,f.y,w,h.roomSize/2),k=A(f.x,f.y,w,h.roomSize);n.push(R.x,R.y,k.x,k.y),r()}}}}return r(),this.paths[0]}addRegularConnectionPoints(t,e){const{fromRoom:i,toRoom:s,fromDir:o,toDir:n}=t;if(e.length===0&&e.push(i.x,i.y),o&&H.includes(o)){const r=this.getRoomEdgePoint(i.x,i.y,o,h.roomSize/2);e.push(r.x,r.y)}if(n&&H.includes(n)){const r=this.getRoomEdgePoint(s.x,s.y,n,h.roomSize/2);e.push(r.x,r.y)}e.push(s.x,s.y)}addSpecialConnectionPoints(t,e){const{fromRoom:i,toRoom:s,customLineKey:o}=t;let n=i,r;o&&(r=i.customLines[o],r||(r=s.customLines[o],n=s)),e.length===0&&e.push(n.x,n.y),r&&r.points.forEach(a=>{e.push(a.x,-a.y)}),e.push(s.x,s.y)}renderInnerConnection(t,e){const{fromRoom:i,toRoom:s,fromDir:o,toDir:n,customLineKey:r}=t;if(r){let a=i,c=i.customLines[r];if(c||(c=s.customLines[r],a=s),c){const l=[a.x,a.y];c.points.forEach(u=>{l.push(u.x,-u.y)});const d=this.createStrokedLine(l,e);this.overlayLayer.add(d),this.paths.push(d)}}if(o&&Q.includes(o)){const a=this.renderInnerExitMarker(i,o,e);this.overlayLayer.add(a),this.paths.push(a)}if(n&&Q.includes(n)){const a=this.renderInnerExitMarker(s,n,e);this.overlayLayer.add(a),this.paths.push(a)}}clearPaths(){this.paths.forEach(t=>{t.destroy()}),this.paths=[]}isRoomVisible(t,e,i){return t?t.area===e&&t.z===i:!1}getExitToRoom(t,e){for(const[i,s]of Object.entries(t.exits))if(s===e.id)return{direction:i};for(const[i,s]of Object.entries(t.specialExits))if(s===e.id)return}getDirectionTowards(t,e){for(const i of ct)if(t.exits[i]===e.id)return i;for(const i of ct)if(e.exits[i]===t.id)return wt[i]}}const Dt=.6,K=75,It=.025,Lt="rgb(225, 255, 225)",U="rgb(120, 72, 0)";class zt{constructor(t=60){this.samples=[],this.lastCullingTime=0,this.callback=null,this.windowSize=t}setCallback(t){t!==this.callback&&(this.callback=t,this.samples=[])}record(t){this.callback&&(this.samples.push(t),this.samples.length>=this.windowSize&&this.flush())}computeFps(){const t=performance.now(),e=t-this.lastCullingTime;return this.lastCullingTime=t,e>0?1e3/e:0}flush(){const t=this.samples.length;if(t===0)return;const e={cullingMs:0,gridMs:0,visibleRooms:0,totalRooms:0,visibleExits:0,fps:0};for(const i of this.samples)e.cullingMs+=i.cullingMs,e.gridMs+=i.gridMs,e.visibleRooms+=i.visibleRooms,e.totalRooms+=i.totalRooms,e.visibleExits+=i.visibleExits,e.fps+=i.fps;e.cullingMs/=t,e.gridMs/=t,e.visibleRooms=Math.round(e.visibleRooms/t),e.totalRooms=Math.round(e.totalRooms/t),e.visibleExits=Math.round(e.visibleExits/t),e.fps=Math.round(e.fps),this.callback(e),this.samples=[]}}function J(E,t){const e=parseInt(E.slice(1,3),16),i=parseInt(E.slice(3,5),16),s=parseInt(E.slice(5,7),16);return`rgba(${e}, ${i}, ${s}, ${t})`}const F=class F{};F.roomSize=Dt,F.lineWidth=It,F.lineColor=Lt,F.instantMapMove=!1,F.highlightCurrentRoom=!0,F.cullingEnabled=!0,F.cullingMode="indexed",F.cullingBounds=null,F.labelRenderMode="image",F.roomShape="rectangle",F.playerMarker={strokeColor:"#00e5b2",strokeAlpha:1,fillColor:"#00e5b2",fillAlpha:0,strokeWidth:.1,sizeFactor:1.7,dash:[.05,.05],dashEnabled:!0},F.gridEnabled=!1,F.gridSize=1,F.gridColor="rgba(255, 255, 255, 0.07)",F.gridLineWidth=.02,F.perfCallback=null;let h=F;class Nt{constructor(t,e){this.highlights=new Map,this.currentZoom=1,this.currentRoomOverlay=[],this.roomNodes=new Map,this.centerOnResize=!0,this.standaloneExitNodes=[],this.spatialBucketSize=5,this.roomSpatialIndex=new Map,this.exitSpatialIndex=new Map,this.visibleRooms=new Set,this.visibleStandaloneExitNodes=new Set,this.bufferRoomSet=new Set,this.bufferExitSet=new Set,this.bufferRoomCandidates=new Set,this.bufferExitCandidates=new Set,this.cullingScheduled=!1,this.perfMonitor=new zt,this.visibleExitDrawData=[],this.cachedGridBounds=null,this.stage=new y.Stage({container:t,width:t.clientWidth,height:t.clientHeight,draggable:!0}),window.addEventListener("resize",()=>{this.onResize(t)}),t.addEventListener("resize",()=>{this.onResize(t)}),this.gridLayer=new y.Layer({listening:!1,hitGraphEnabled:!1}),this.stage.add(this.gridLayer),this.linkLayer=new y.Layer({listening:!1,hitGraphEnabled:!1}),this.stage.add(this.linkLayer),this.roomLayer=new y.Layer({hitGraphEnabled:!1}),this.stage.add(this.roomLayer),this.positionLayer=new y.Layer({listening:!1,hitGraphEnabled:!1}),this.stage.add(this.positionLayer),this.overlayLayer=new y.Layer({listening:!1,hitGraphEnabled:!1}),this.stage.add(this.overlayLayer),this.mapReader=e,this.exitRenderer=new Ct(e,this),this.pathRenderer=new Mt(e,this.overlayLayer),this.initScaling(1.1),this.stage.on("dragmove",()=>this.scheduleRoomCulling()),this.stage.on("dragend",()=>this.scheduleRoomCulling()),this.initRoomHitDetection()}clientToMapPoint(t,e){const s=this.stage.container().getBoundingClientRect(),o=t-s.left,n=e-s.top,r=this.stage.scaleX();if(!r)return null;const a=this.stage.position();return{x:(o-a.x)/r,y:(n-a.y)/r}}findRoomAtClientPoint(t,e){const i=this.clientToMapPoint(t,e);if(!i)return null;const s=h.roomSize/2,o=this.getBucketKey(Math.floor(i.x/this.spatialBucketSize),Math.floor(i.y/this.spatialBucketSize)),n=this.roomSpatialIndex.get(o);if(!n)return null;for(const r of n){const a=i.x-r.room.x,c=i.y-r.room.y;if(a>=-s&&a<=s&&c>=-s&&c<=s)return r.room}return null}initRoomHitDetection(){const t=this.stage.container();let e=null;t.addEventListener("mousemove",a=>{const c=this.findRoomAtClientPoint(a.clientX,a.clientY);c!==e&&(e=c,t.style.cursor=c?"pointer":"auto")}),t.addEventListener("mouseleave",()=>{e=null,t.style.cursor="auto"}),t.addEventListener("contextmenu",a=>{const c=this.findRoomAtClientPoint(a.clientX,a.clientY);c&&(a.preventDefault(),this.emitRoomContextEvent(c.id,a.clientX,a.clientY))});let i,s,o;const n=()=>{o!==void 0&&(this.stage.draggable(o),o=void 0)},r=()=>{i!==void 0&&(window.clearTimeout(i),i=void 0),s=void 0,n()};t.addEventListener("touchstart",a=>{if(r(),a.touches.length>1)return;const c=a.touches[0];!c||!this.findRoomAtClientPoint(c.clientX,c.clientY)||(s={clientX:c.clientX,clientY:c.clientY},o=this.stage.draggable(),this.stage.draggable(!1),i=window.setTimeout(()=>{if(s){const d=this.findRoomAtClientPoint(s.clientX,s.clientY);d&&this.emitRoomContextEvent(d.id,s.clientX,s.clientY)}r()},500))},{passive:!0}),t.addEventListener("touchend",()=>r(),{passive:!0}),t.addEventListener("touchcancel",()=>r(),{passive:!0}),t.addEventListener("touchmove",a=>{if(!s)return;const c=a.touches[0];if(!c){r();return}const l=c.clientX-s.clientX,d=c.clientY-s.clientY;if(l*l+d*d>100){const u=o;r(),u&&this.stage.startDrag()}},{passive:!0})}onResize(t){this.stage.width(t.clientWidth),this.stage.height(t.clientHeight),this.centerOnResize&&this.currentRoomId&&this.centerOnRoom(this.mapReader.getRoom(this.currentRoomId),!1),this.stage.batchDraw(),this.scheduleRoomCulling()}initScaling(t){let e,i=!1,s=!1;this.stage.on("touchstart",o=>{const n=o.evt.touches;n&&n.length>1?(s=!0,this.stage.isDragging()&&(this.stage.stopDrag(),i=!0),this.stage.draggable(!1)):(s=!1,this.stage.draggable(!0))}),this.stage.on("touchend touchcancel",o=>{e=void 0;const n=o.evt.touches;(!n||n.length<=1)&&(s=!1,this.stage.draggable(!0))}),this.stage.on("wheel",o=>{o.evt.preventDefault();const n=this.stage.scaleX(),r=this.stage.getPointerPosition();if(!r)return;const a={x:(r.x-this.stage.x())/n,y:(r.y-this.stage.y())/n};let c=o.evt.deltaY>0?-1:1;o.evt.ctrlKey&&(c=-c);const l=c>0?this.currentZoom*t:this.currentZoom/t,d=l*K,u=this.setZoom(l),g={x:r.x-a.x*d,y:r.y-a.y*d};this.stage.position(g),this.scheduleRoomCulling(),u&&this.emitZoomChangeEvent()}),this.stage.on("touchmove",o=>{const n=o.evt.touches,r=n?.[0],a=n?.[1];if(a||s&&(s=!1,this.stage.draggable(!0)),r&&!a&&i&&!this.stage.isDragging()&&(this.stage.startDrag(),i=!1),!r||!a){e=void 0;return}o.evt.preventDefault(),this.stage.isDragging()&&(this.stage.stopDrag(),i=!0),s||(s=!0,this.stage.draggable(!1));const c=this.stage.container().getBoundingClientRect(),l={x:r.clientX-c.left,y:r.clientY-c.top},d={x:a.clientX-c.left,y:a.clientY-c.top},u=Math.hypot(l.x-d.x,l.y-d.y);if(e===void 0){e=u;return}if(e===0)return;const g=this.stage.scaleX(),f=this.stage.x(),m=this.stage.y(),p={x:this.stage.width()/2,y:this.stage.height()/2},w={x:(p.x-f)/g,y:(p.y-m)/g},R=this.currentZoom*(u/e),k=this.setZoom(R),P=this.stage.scaleX(),X={x:p.x-w.x*P,y:p.y-w.y*P};this.stage.position(X),this.stage.batchDraw(),this.scheduleRoomCulling(),e=u,k&&this.emitZoomChangeEvent()})}drawArea(t,e){const i=this.mapReader.getArea(t);if(!i)return;const s=i.getPlane(e);s&&(this.currentArea=t,this.currentAreaInstance=i,this.currentZIndex=e,this.currentAreaVersion=i.getVersion(),this.clearCurrentRoomOverlay(),this.gridLayer.destroyChildren(),this.invalidateGridCache(),this.roomLayer.destroyChildren(),this.linkLayer.destroyChildren(),this.roomNodes.clear(),this.standaloneExitNodes=[],this.standaloneExitBoundsRoomSize=void 0,this.roomSpatialIndex.clear(),this.exitSpatialIndex.clear(),this.visibleRooms.clear(),this.visibleStandaloneExitNodes.clear(),this.visibleExitDrawData.length=0,this.exitBatchShape=void 0,this.spatialBucketSize=this.computeSpatialBucketSize(),this.stage.scale({x:K*this.currentZoom,y:K*this.currentZoom}),this.renderGrid(),this.renderLabels(s.getLabels()),this.renderExits(i.getLinkExits(e)),this.renderRooms(s.getRooms()??[]),this.refreshHighlights(),this.stage.batchDraw(),this.scheduleRoomCulling())}computeSpatialBucketSize(){return Math.max(h.roomSize*10,5)}getBucketKey(t,e){return t*1000003+e}forEachBucket(t,e,i,s,o){const n=this.spatialBucketSize,r=Math.min(t,i),a=Math.max(t,i),c=Math.min(e,s),l=Math.max(e,s),d=Math.floor(r/n),u=Math.floor(a/n),g=Math.floor(c/n),f=Math.floor(l/n);for(let m=d;m<=u;m++)for(let p=g;p<=f;p++)o(this.getBucketKey(m,p))}addRoomToSpatialIndex(t){const e=h.roomSize/2,i=t.room.x-e,s=t.room.x+e,o=t.room.y-e,n=t.room.y+e;this.forEachBucket(i,o,s,n,r=>{let a=this.roomSpatialIndex.get(r);a||(a=new Set,this.roomSpatialIndex.set(r,a)),a.add(t)})}addStandaloneExitToSpatialIndex(t){const{bounds:e}=t,i=e.x,s=e.x+e.width,o=e.y,n=e.y+e.height;this.forEachBucket(i,o,s,n,r=>{let a=this.exitSpatialIndex.get(r);a||(a=new Set,this.exitSpatialIndex.set(r,a)),a.add(t)})}collectRoomCandidates(t,e,i,s){const o=this.bufferRoomCandidates;return o.clear(),this.forEachBucket(t,e,i,s,n=>{this.roomSpatialIndex.get(n)?.forEach(a=>o.add(a))}),o}collectStandaloneExitCandidates(t,e,i,s){const o=this.bufferExitCandidates;return o.clear(),this.forEachBucket(t,e,i,s,n=>{this.exitSpatialIndex.get(n)?.forEach(a=>o.add(a))}),o}refreshStandaloneExitBoundsIfNeeded(){this.standaloneExitBoundsRoomSize!==h.roomSize&&(this.exitSpatialIndex.clear(),this.standaloneExitNodes.forEach(t=>{this.addStandaloneExitToSpatialIndex(t)}),this.standaloneExitBoundsRoomSize=h.roomSize)}emitRoomContextEvent(t,e,i){const s=this.stage.container(),o=s.getBoundingClientRect(),n={roomId:t,position:{x:e-o.left,y:i-o.top}},r=new CustomEvent("roomcontextmenu",{detail:n});s.dispatchEvent(r)}emitZoomChangeEvent(){const t=new CustomEvent("zoom",{detail:{zoom:this.currentZoom}});this.stage.container().dispatchEvent(t)}setZoom(t){return this.currentZoom===t?!1:(this.currentZoom=t,this.stage.scale({x:K*t,y:K*t}),this.scheduleRoomCulling(),!0)}zoomToCenter(t){if(this.currentZoom===t)return!1;const e=this.stage.scaleX(),i=this.stage.width(),s=this.stage.height(),o=i/2,n=s/2,r={x:(o-this.stage.x())/e,y:(n-this.stage.y())/e};this.currentZoom=t;const a=K*t;this.stage.scale({x:a,y:a});const c={x:o-r.x*a,y:n-r.y*a};return this.stage.position(c),this.stage.batchDraw(),this.scheduleRoomCulling(),!0}getZoom(){return this.currentZoom}setCullingMode(t){h.cullingMode=t,h.cullingEnabled=t!=="none",this.scheduleRoomCulling()}getCullingMode(){return h.cullingMode}getCurrentArea(){return this.currentArea?this.mapReader.getArea(this.currentArea):void 0}refreshCurrentRoomOverlay(){if(this.currentRoomId!==void 0){const t=this.mapReader.getRoom(this.currentRoomId);t&&this.updateCurrentRoomOverlay(t)}}refresh(){this.currentRoomId!==void 0&&this.currentArea!==void 0&&this.currentZIndex!==void 0&&(this.drawArea(this.currentArea,this.currentZIndex),this.setPosition(this.currentRoomId))}updatePositionMarker(t){const e=this.mapReader.getRoom(t);if(!e)return;if(e.area!==this.currentArea||e.z!==this.currentZIndex){this.positionRender&&(this.positionRender.hide(),this.positionLayer.batchDraw());return}this.currentRoomId=t,this.updateCurrentRoomOverlay(e);const i=J(h.playerMarker.strokeColor,h.playerMarker.strokeAlpha),s=J(h.playerMarker.fillColor,h.playerMarker.fillAlpha),o=h.roomSize/2*h.playerMarker.sizeFactor;this.positionRender?(this.positionRender.position({x:e.x,y:e.y}),this.positionRender.radius(o),this.positionRender.stroke(i),this.positionRender.fill(s),this.positionRender.strokeWidth(h.playerMarker.strokeWidth),this.positionRender.dash(h.playerMarker.dash??[]),this.positionRender.dashEnabled(h.playerMarker.dashEnabled),this.positionRender.show()):(this.positionRender=new y.Circle({x:e.x,y:e.y,radius:o,stroke:i,fill:s,strokeWidth:h.playerMarker.strokeWidth,dash:h.playerMarker.dash,dashEnabled:h.playerMarker.dashEnabled}),this.positionLayer.add(this.positionRender)),this.positionLayer.batchDraw()}setPosition(t,e=!0){const i=this.mapReader.getRoom(t);if(!i)return;const s=this.mapReader.getArea(i.area),o=s?.getVersion();let n=this.currentArea!==i.area||this.currentZIndex!==i.z;(this.currentArea!==i.area||this.currentZIndex!==i.z||o!==void 0&&this.currentAreaVersion!==o||s!==void 0&&this.currentAreaInstance!==s)&&this.drawArea(i.area,i.z),e?this.centerOnRoom(i,n):this.currentRoomId=t,this.updateCurrentRoomOverlay(i);const r=J(h.playerMarker.strokeColor,h.playerMarker.strokeAlpha),a=J(h.playerMarker.fillColor,h.playerMarker.fillAlpha),c=h.roomSize/2*h.playerMarker.sizeFactor;this.positionRender?(this.positionRender.radius(c),this.positionRender.stroke(r),this.positionRender.fill(a),this.positionRender.strokeWidth(h.playerMarker.strokeWidth),this.positionRender.dash(h.playerMarker.dash??[]),this.positionRender.dashEnabled(h.playerMarker.dashEnabled)):(this.positionRender=new y.Circle({x:i.x,y:i.y,radius:c,stroke:r,fill:a,strokeWidth:h.playerMarker.strokeWidth,dash:h.playerMarker.dash,dashEnabled:h.playerMarker.dashEnabled}),this.positionLayer.add(this.positionRender))}centerOn(t){const e=this.mapReader.getRoom(t);if(!e)return;const i=this.mapReader.getArea(e.area),s=i?.getVersion();let o=this.currentArea!==e.area||this.currentZIndex!==e.z;(this.currentArea!==e.area||this.currentZIndex!==e.z||s!==void 0&&this.currentAreaVersion!==s||i!==void 0&&this.currentAreaInstance!==i)&&this.drawArea(e.area,e.z),this.centerOnRoomView(e,o)}renderPath(t,e){return this.pathRenderer.renderPath(t,this.currentArea,this.currentZIndex,e)}clearPaths(){this.pathRenderer.clearPaths()}renderHighlight(t,e){const i=this.mapReader.getRoom(t);if(!i)return;const s=this.highlights.get(t);s?.shape&&(s.shape.destroy(),delete s.shape);const o={color:e,area:i.area,z:i.z};if(this.highlights.set(t,o),i.area===this.currentArea&&i.z===this.currentZIndex){const n=this.createHighlightShape(i,e);return this.overlayLayer.add(n),o.shape=n,this.overlayLayer.batchDraw(),n}return o.shape}clearHighlights(){this.highlights.forEach(({shape:t})=>t?.destroy()),this.highlights.clear(),this.overlayLayer.batchDraw()}refreshHighlights(){this.highlights.forEach((t,e)=>{if(t.shape?.destroy(),delete t.shape,t.area!==this.currentArea||t.z!==this.currentZIndex)return;const i=this.mapReader.getRoom(e);if(!i)return;const s=this.createHighlightShape(i,t.color);this.overlayLayer.add(s),t.shape=s}),this.overlayLayer.batchDraw()}createHighlightShape(t,e){return h.roomShape==="circle"?new y.Circle({x:t.x,y:t.y,radius:h.roomSize/2*1.5,stroke:e,strokeWidth:.1,dash:[.05,.05],dashEnabled:!0,listening:!1}):new y.Rect({x:t.x-h.roomSize/2*1.5,y:t.y-h.roomSize/2*1.5,width:h.roomSize*1.5,height:h.roomSize*1.5,stroke:e,strokeWidth:.1,dash:[.05,.05],dashEnabled:!0,cornerRadius:h.roomShape==="roundedRectangle"?h.roomSize*1.5*.2:0,listening:!1})}centerOnRoom(t,e=!1){this.currentRoomId=t.id;const i={x:t.x,y:t.y};this.positionRender?.position(t);const o=this.stage.getAbsoluteTransform().point(i),n={x:this.stage.width()/2,y:this.stage.height()/2},r=n.x-o.x,a=n.y-o.y;this.currentTransition&&(this.currentTransition.pause(),this.currentTransition.destroy(),delete this.currentTransition),e||h.instantMapMove?(this.stage.position({x:this.stage.x()+r,y:this.stage.y()+a}),this.scheduleRoomCulling()):(this.currentTransition=new y.Tween({node:this.stage,x:this.stage.x()+r,y:this.stage.y()+a,duration:.2,easing:y.Easings.EaseInOut,onUpdate:()=>this.scheduleRoomCulling(),onFinish:()=>this.scheduleRoomCulling()}),this.currentTransition.play())}centerOnRoomView(t,e=!1){const i={x:t.x,y:t.y},o=this.stage.getAbsoluteTransform().point(i),n={x:this.stage.width()/2,y:this.stage.height()/2},r=n.x-o.x,a=n.y-o.y;this.currentTransition&&(this.currentTransition.pause(),this.currentTransition.destroy(),delete this.currentTransition),e||h.instantMapMove?(this.stage.position({x:this.stage.x()+r,y:this.stage.y()+a}),this.scheduleRoomCulling()):(this.currentTransition=new y.Tween({node:this.stage,x:this.stage.x()+r,y:this.stage.y()+a,duration:.2,easing:y.Easings.EaseInOut,onUpdate:()=>this.scheduleRoomCulling(),onFinish:()=>this.scheduleRoomCulling()}),this.currentTransition.play())}renderRooms(t){t.forEach(e=>{const i=new y.Group({x:e.x-h.roomSize/2,y:e.y-h.roomSize/2,listening:!1}),s=this.mapReader.getColorValue(e.env),o=h.lineColor,n=h.roomShape==="circle"?new y.Circle({x:h.roomSize/2,y:h.roomSize/2,radius:h.roomSize/2,fill:s,strokeWidth:h.lineWidth,stroke:o,perfectDrawEnabled:!1,listening:!1}):new y.Rect({x:0,y:0,width:h.roomSize,height:h.roomSize,fill:s,strokeWidth:h.lineWidth,stroke:o,cornerRadius:h.roomShape==="roundedRectangle"?h.roomSize*.2:0,perfectDrawEnabled:!1,listening:!1});i.add(n),this.renderSymbol(e,i),this.roomLayer.add(i),this.exitRenderer.renderSpecialExits(e).forEach(l=>{this.linkLayer.add(l)});const r=e.x-h.roomSize/2,a=e.y-h.roomSize/2;this.exitRenderer.renderStubs(e).forEach(l=>{const d=l.points();for(let u=0;u<d.length;u+=2)d[u]-=r,d[u+1]-=a;l.points(d),i.add(l)}),this.exitRenderer.renderInnerExits(e).forEach(l=>{l.position({x:-r,y:-a}),i.add(l)});const c={room:e,group:i};this.roomNodes.set(e.id,c),this.addRoomToSpatialIndex(c)})}scheduleRoomCulling(){this.cullingScheduled||(this.cullingScheduled=!0,window.requestAnimationFrame(()=>{this.cullingScheduled=!1,this.updateRoomCulling()}))}updateRoomCulling(){if(this.roomNodes.size===0&&this.standaloneExitNodes.length===0)return;const t=this.stage.scaleX();if(!t)return;this.syncPerfMonitor();const e=h.perfCallback?performance.now():0,i=this.stage.position(),s=h.roomSize/2,o=h.cullingBounds,n=o?o.x:0,r=o?o.x+o.width:this.stage.width(),a=o?o.y:0,c=o?o.y+o.height:this.stage.height(),l=Math.min(n,r),d=Math.max(n,r),u=Math.min(a,c),g=Math.max(a,c),f=(l-i.x)/t,m=(d-i.x)/t,p=(u-i.y)/t,w=(g-i.y)/t;let R=!1,k=!1;const P=h.cullingEnabled?h.cullingMode??"indexed":"none",X=f-s,Y=m+s,x=p-s,v=w+s;if(this.refreshStandaloneExitBoundsIfNeeded(),P==="none"){if(this.roomNodes.forEach(b=>{b.group.visible()||(b.group.visible(!0),R=!0)}),this.visibleExitDrawData.length!==this.standaloneExitNodes.length){this.visibleExitDrawData.length=0;for(const b of this.standaloneExitNodes)this.visibleExitDrawData.push(b.data);k=!0}R&&this.roomLayer.batchDraw(),k&&this.linkLayer.batchDraw(),this.visibleRooms.clear(),this.roomNodes.forEach(b=>this.visibleRooms.add(b)),this.visibleStandaloneExitNodes.clear(),this.standaloneExitNodes.forEach(b=>this.visibleStandaloneExitNodes.add(b));return}if(P==="basic"){const b=this.bufferRoomSet;b.clear(),this.roomNodes.forEach(N=>{const B=N.room.x-s,V=N.room.x+s,$=N.room.y-s,j=N.room.y+s,Z=V>=f&&B<=m&&j>=p&&$<=w;N.group.visible()!==Z&&(N.group.visible(Z),R=!0),Z&&b.add(N)});const L=this.bufferExitSet;L.clear();let W=!1;this.standaloneExitNodes.forEach(N=>{const{bounds:B}=N,V=B.x,$=B.x+B.width,j=B.y,Z=B.y+B.height;$>=f&&V<=m&&Z>=p&&j<=w&&(L.add(N),this.visibleStandaloneExitNodes.has(N)||(W=!0))}),!W&&L.size!==this.visibleStandaloneExitNodes.size&&(W=!0),this.bufferRoomSet=this.visibleRooms,this.visibleRooms=b,this.bufferExitSet=this.visibleStandaloneExitNodes,this.visibleStandaloneExitNodes=L,W&&(this.visibleExitDrawData.length=0,this.visibleStandaloneExitNodes.forEach(N=>this.visibleExitDrawData.push(N.data)),k=!0),R&&this.roomLayer.batchDraw(),k&&this.linkLayer.batchDraw();return}const C=this.collectRoomCandidates(X,x,Y,v),D=this.bufferRoomSet;D.clear(),C.forEach(b=>{const L=b.room.x-s,W=b.room.x+s,N=b.room.y-s,B=b.room.y+s,V=W>=f&&L<=m&&B>=p&&N<=w;b.group.visible()!==V&&(b.group.visible(V),R=!0),V&&D.add(b)}),this.visibleRooms.forEach(b=>{C.has(b)||b.group.visible()&&(b.group.visible(!1),R=!0)}),this.bufferRoomSet=this.visibleRooms,this.visibleRooms=D;const S=this.collectStandaloneExitCandidates(X,x,Y,v),M=this.bufferExitSet;M.clear();let I=!1;S.forEach(b=>{const{bounds:L}=b,W=L.x,N=L.x+L.width,B=L.y,V=L.y+L.height;N>=f&&W<=m&&V>=p&&B<=w&&(M.add(b),this.visibleStandaloneExitNodes.has(b)||(I=!0))}),!I&&M.size!==this.visibleStandaloneExitNodes.size&&(I=!0),this.bufferExitSet=this.visibleStandaloneExitNodes,this.visibleStandaloneExitNodes=M,I&&(this.visibleExitDrawData.length=0,this.visibleStandaloneExitNodes.forEach(b=>this.visibleExitDrawData.push(b.data)),k=!0),R&&this.roomLayer.batchDraw(),k&&this.linkLayer.batchDraw();const O=h.perfCallback?performance.now():0;if(this.renderGrid(),h.perfCallback){const b=performance.now()-O,L=performance.now()-e;this.perfMonitor.record({cullingMs:L,gridMs:b,visibleRooms:this.visibleRooms.size,totalRooms:this.roomNodes.size,visibleExits:this.visibleStandaloneExitNodes.size,fps:this.perfMonitor.computeFps()})}}syncPerfMonitor(){this.perfMonitor.setCallback(h.perfCallback)}invalidateGridCache(){this.cachedGridBounds=null}renderGrid(){if(!h.gridEnabled){this.cachedGridBounds!==null&&(this.gridLayer.destroyChildren(),this.gridLayer.batchDraw(),this.cachedGridBounds=null);return}const t=this.stage.scaleX();if(!t)return;const e=this.stage.position(),i=this.stage.width(),s=this.stage.height(),o=(0-e.x)/t,n=(i-e.x)/t,r=(0-e.y)/t,a=(s-e.y)/t,c=h.gridSize*2,l=Math.floor((Math.min(o,n)-c)/h.gridSize)*h.gridSize,d=Math.ceil((Math.max(o,n)+c)/h.gridSize)*h.gridSize,u=Math.floor((Math.min(r,a)-c)/h.gridSize)*h.gridSize,g=Math.ceil((Math.max(r,a)+c)/h.gridSize)*h.gridSize,f=this.cachedGridBounds;if(!(f&&f.left===l&&f.right===d&&f.top===u&&f.bottom===g)){this.gridLayer.destroyChildren();for(let m=l;m<=d;m+=h.gridSize)this.gridLayer.add(new y.Line({points:[m,u,m,g],stroke:h.gridColor,strokeWidth:h.gridLineWidth,listening:!1,perfectDrawEnabled:!1}));for(let m=u;m<=g;m+=h.gridSize)this.gridLayer.add(new y.Line({points:[l,m,d,m],stroke:h.gridColor,strokeWidth:h.gridLineWidth,listening:!1,perfectDrawEnabled:!1}));this.cachedGridBounds={left:l,right:d,top:u,bottom:g},this.gridLayer.batchDraw()}}clearCurrentRoomOverlay(){this.currentRoomOverlay.forEach(t=>t.destroy()),this.currentRoomOverlay=[],this.positionLayer.batchDraw()}updateCurrentRoomOverlay(t){if(this.clearCurrentRoomOverlay(),t.area!==this.currentArea||t.z!==this.currentZIndex){this.positionLayer.batchDraw();return}const e=new Map;e.set(t.id,t);const i=[],s=this.currentAreaInstance instanceof tt?this.currentAreaInstance:void 0;this.currentAreaInstance&&this.currentZIndex!==void 0&&this.currentAreaInstance.getLinkExits(this.currentZIndex).filter(a=>a.a===t.id||a.b===t.id).forEach(a=>{const c=h.highlightCurrentRoom?this.exitRenderer.renderWithColor(a,U,this.currentZIndex):this.exitRenderer.render(a,this.currentZIndex);c&&i.push(c)});const o=h.highlightCurrentRoom?U:void 0;this.exitRenderer.renderSpecialExits(t,o).forEach(r=>{i.push(r)}),(h.highlightCurrentRoom?this.exitRenderer.renderStubs(t,U):this.exitRenderer.renderStubs(t)).forEach(r=>{i.push(r)}),[...Object.values(t.exits),...Object.values(t.specialExits)].forEach(r=>{const a=this.mapReader.getRoom(r),c=!s||s.hasVisitedRoom(r);a&&a.area===this.currentArea&&a.z===this.currentZIndex&&c&&e.set(r,a)}),i.forEach(r=>{this.positionLayer.add(r),this.currentRoomOverlay.push(r)}),e.forEach((r,a)=>{const c=a===t.id,l=this.createOverlayRoomGroup(r,{stroke:c&&h.highlightCurrentRoom?U:h.lineColor});this.positionLayer.add(l),this.currentRoomOverlay.push(l),this.exitRenderer.renderInnerExits(r).forEach(d=>{this.positionLayer.add(d),this.currentRoomOverlay.push(d)})}),this.positionRender&&this.positionRender.moveToTop(),this.positionLayer.batchDraw()}createOverlayRoomGroup(t,e){const i=new y.Group({x:t.x-h.roomSize/2,y:t.y-h.roomSize/2,listening:!1}),s=this.mapReader.getColorValue(t.env),o=e.stroke,n=h.roomShape==="circle"?new y.Circle({x:h.roomSize/2,y:h.roomSize/2,radius:h.roomSize/2,fill:s,stroke:o,strokeWidth:h.lineWidth}):new y.Rect({x:0,y:0,width:h.roomSize,height:h.roomSize,fill:s,stroke:o,strokeWidth:h.lineWidth,cornerRadius:h.roomShape==="roundedRectangle"?h.roomSize*.2:0});return i.add(n),this.renderSymbol(t,i),i}renderSymbol(t,e){if(t.roomChar!==void 0){const i=h.roomSize*.75,s=new y.Text({x:0,y:0,text:t.roomChar,fontSize:i,fontStyle:"bold",fill:this.mapReader.getSymbolColor(t.env),align:"center",verticalAlign:"middle",width:h.roomSize,height:h.roomSize,perfectDrawEnabled:!1,listening:!1});e.add(s)}}renderExits(t){t.forEach(e=>{const i=this.exitRenderer.renderData(e,this.currentZIndex);if(!i)return;const s={data:i,bounds:i.bounds};this.standaloneExitNodes.push(s),this.addStandaloneExitToSpatialIndex(s)}),this.standaloneExitBoundsRoomSize=h.roomSize,this.exitBatchShape=new y.Shape({listening:!1,perfectDrawEnabled:!1,sceneFunc:e=>{const i=e._context;for(const s of this.visibleExitDrawData)this.drawExitData(i,s)}}),this.linkLayer.add(this.exitBatchShape)}drawExitData(t,e){for(const i of e.lines){t.beginPath(),t.moveTo(i.points[0],i.points[1]);for(let s=2;s<i.points.length;s+=2)t.lineTo(i.points[s],i.points[s+1]);t.strokeStyle=i.stroke,t.lineWidth=i.strokeWidth,i.dash?t.setLineDash(i.dash):t.setLineDash([]),t.stroke()}for(const i of e.arrows){t.beginPath(),t.moveTo(i.points[0],i.points[1]);for(let u=2;u<i.points.length;u+=2)t.lineTo(i.points[u],i.points[u+1]);t.strokeStyle=i.stroke,t.lineWidth=i.strokeWidth,i.dash?t.setLineDash(i.dash):t.setLineDash([]),t.stroke();const s=i.points.length-2,o=i.points[s],n=i.points[s+1],r=i.points[s-2],a=i.points[s-1],c=Math.atan2(n-a,o-r),l=i.pointerLength,d=i.pointerWidth/2;t.beginPath(),t.setLineDash([]),t.moveTo(o,n),t.lineTo(o-l*Math.cos(c-Math.atan2(d,l)),n-l*Math.sin(c-Math.atan2(d,l))),t.lineTo(o-l*Math.cos(c+Math.atan2(d,l)),n-l*Math.sin(c+Math.atan2(d,l))),t.closePath(),t.fillStyle=i.fill,t.fill(),t.strokeStyle=i.stroke,t.lineWidth=i.strokeWidth,t.stroke()}for(const i of e.doors)t.beginPath(),t.rect(i.x,i.y,i.width,i.height),t.strokeStyle=i.stroke,t.lineWidth=i.strokeWidth,t.setLineDash([]),t.stroke()}renderLabels(t){t.forEach(e=>{if(h.labelRenderMode==="image"){if(!e.pixMap)return;const i=new Image;i.src=`data:image/png;base64,${e.pixMap}`;const s=new y.Image({x:e.X,y:-e.Y,width:e.Width,height:e.Height,image:i,listening:!1});this.linkLayer.add(s);return}this.renderLabelAsData(e)})}renderLabelAsData(t){const e=new y.Group({listening:!1}),i=new y.Rect({x:t.X,y:-t.Y,width:t.Width,height:t.Height,listening:!1});(t.BgColor?.alpha??0)>0&&!h.transparentLabels?i.fill(this.getLabelColor(t.BgColor)):i.fillEnabled(!1),e.add(i);const s=Math.min(.75,t.Width/Math.max(t.Text.length/2,1)),o=Math.max(.1,Math.min(s,Math.max(t.Height*.9,.1))),n=new y.Text({x:t.X,y:-t.Y,width:t.Width,height:t.Height,text:t.Text,fontSize:o,fillEnabled:!0,fill:this.getLabelColor(t.FgColor),align:"center",verticalAlign:"middle",listening:!1});e.add(n),this.linkLayer.add(e)}getLabelColor(t){const e=(t?.alpha??255)/255,i=s=>Math.min(255,Math.max(0,s??0));return`rgba(${i(t?.r)}, ${i(t?.g)}, ${i(t?.b)}, ${e})`}}const ft={rgbValue:"rgb(114, 1, 0)",symbolColor:[225,225,225]};function gt(E){const t=E[0]/255,e=E[1]/255,i=E[2]/255,s=Math.max(t,e,i),o=Math.min(t,e,i);return(s+o)/2}class Pt{constructor(t,e){this.rooms={},this.areas={},this.areaSources={},this.explorationEnabled=!1,this.colors={},t.forEach(i=>{i.rooms.forEach(o=>{o.y=-o.y,this.rooms[o.id]=o});const s=parseInt(i.areaId);this.areas[s]=new _(i),this.areaSources[s]=i}),this.colors=e.reduce((i,s)=>({...i,[s.envId]:{rgb:s.colors,rgbValue:`rgb(${s.colors.join(",")})`,symbolColor:gt(s.colors)>.41?[25,25,25]:[225,255,255],symbolColorValue:gt(s.colors)>.41?"rgb(25,25,25)":"rgb(225,255,255)"}}),{})}getArea(t){return this.areas[t]}getExplorationArea(t){const e=this.areas[t];if(e instanceof tt)return e}getAreas(){return Object.values(this.areas)}getRooms(){return Object.values(this.rooms)}getRoom(t){return this.rooms[t]}ensureVisitedRooms(){return this.visitedRooms||(this.visitedRooms=new Set),this.visitedRooms}applyExplorationDecoration(){this.visitedRooms&&Object.entries(this.areaSources).forEach(([t,e])=>{const i=parseInt(t,10);this.areas[i]=new tt(e,this.visitedRooms)})}decorateWithExploration(t){return t!==void 0?this.setVisitedRooms(t):this.ensureVisitedRooms(),this.applyExplorationDecoration(),this.explorationEnabled=!0,this.visitedRooms}getVisitedRooms(){return this.visitedRooms}clearExplorationDecoration(){Object.entries(this.areaSources).forEach(([t,e])=>{const i=parseInt(t,10);this.areas[i]=new _(e)}),this.explorationEnabled=!1}isExplorationEnabled(){return this.explorationEnabled}setVisitedRooms(t){return this.visitedRooms=t instanceof Set?t:new Set(t),this.explorationEnabled&&this.applyExplorationDecoration(),this.visitedRooms}addVisitedRoom(t){if(this.explorationEnabled){const s=this.getRoom(t);if(s){const o=this.getExplorationArea(s.area);if(o)return o.addVisitedRoom(t)}}const e=this.ensureVisitedRooms(),i=e.has(t);return e.add(t),!i}addVisitedRooms(t){const e=this.ensureVisitedRooms();let i=0;for(const s of t){if(this.explorationEnabled){const n=this.getRoom(s);if(n){const r=this.getExplorationArea(n.area);if(r){r.addVisitedRoom(s)&&i++;continue}}}const o=e.has(s);e.add(s),o||i++}return i}hasVisitedRoom(t){return this.visitedRooms?.has(t)??!1}getColorValue(t){return this.colors[t]?.rgbValue??ft.rgbValue}getSymbolColor(t,e){const i=this.colors[t]?.symbolColor??ft.symbolColor,s=Math.min(Math.max(e??1,0),1),o=i.join(",");return s!=1?`rgba(${o}, ${s})`:`rgba(${o})`}}function Xt(E){return E&&E.__esModule&&Object.prototype.hasOwnProperty.call(E,"default")?E.default:E}var ot,mt;function At(){if(mt)return ot;mt=1;class E{constructor(){this.keys=new Set,this.queue=[]}sort(){this.queue.sort((e,i)=>e.priority-i.priority)}set(e,i){const s=Number(i);if(isNaN(s))throw new TypeError('"priority" must be a number');return this.keys.has(e)?this.queue.map(o=>(o.key===e&&Object.assign(o,{priority:s}),o)):(this.keys.add(e),this.queue.push({key:e,priority:s})),this.sort(),this.queue.length}next(){const e=this.queue.shift();return this.keys.delete(e.key),e}isEmpty(){return this.queue.length===0}has(e){return this.keys.has(e)}get(e){return this.queue.find(i=>i.key===e)}}return ot=E,ot}var nt,pt;function Yt(){if(pt)return nt;pt=1;function E(t,e){const i=new Map;for(const[s,o]of t)s!==e&&o instanceof Map?i.set(s,E(o,e)):s!==e&&i.set(s,o);return i}return nt=E,nt}var rt,yt;function Ot(){if(yt)return rt;yt=1;function E(e){const i=Number(e);return!(isNaN(i)||i<=0)}function t(e){const i=new Map;return Object.keys(e).forEach(o=>{const n=e[o];if(n!==null&&typeof n=="object"&&!Array.isArray(n))return i.set(o,t(n));if(!E(n))throw new Error(`Could not add node at key "${o}", make sure it's a valid node`,n);return i.set(o,Number(n))}),i}return rt=t,rt}var at,xt;function Wt(){if(xt)return at;xt=1;function E(t){if(!(t instanceof Map))throw new Error(`Invalid graph: Expected Map instead found ${typeof t}`);t.forEach((e,i)=>{if(typeof e=="object"&&e instanceof Map){E(e);return}if(typeof e!="number"||e<=0)throw new Error(`Values must be numbers greater than 0. Found value ${e} at ${i}`)})}return at=E,at}var ht,bt;function Tt(){if(bt)return ht;bt=1;const E=At(),t=Yt(),e=Ot(),i=Wt();class s{constructor(n){n instanceof Map?(i(n),this.graph=n):n?this.graph=e(n):this.graph=new Map}addNode(n,r){let a;return r instanceof Map?(i(r),a=r):a=e(r),this.graph.set(n,a),this}addVertex(n,r){return this.addNode(n,r)}removeNode(n){return this.graph=t(this.graph,n),this}path(n,r,a={}){if(!this.graph.size)return a.cost?{path:null,cost:0}:null;const c=new Set,l=new E,d=new Map;let u=[],g=0,f=[];if(a.avoid&&(f=[].concat(a.avoid)),f.includes(n))throw new Error(`Starting node (${n}) cannot be avoided`);if(f.includes(r))throw new Error(`Ending node (${r}) cannot be avoided`);for(l.set(n,0);!l.isEmpty();){const m=l.next();if(m.key===r){g=m.priority;let w=m.key;for(;d.has(w);)u.push(w),w=d.get(w);break}c.add(m.key),(this.graph.get(m.key)||new Map).forEach((w,R)=>{if(c.has(R)||f.includes(R))return null;if(!l.has(R))return d.set(R,m.key),l.set(R,m.priority+w);const k=l.get(R).priority,P=m.priority+w;return P<k?(d.set(R,m.key),l.set(R,P)):null})}return u.length?(a.trim?u.shift():u=u.concat([n]),a.reverse||(u=u.reverse()),a.cost?{path:u,cost:g}:u):a.cost?{path:null,cost:0}:null}shortestPath(...n){return this.path(...n)}}return ht=s,ht}var Vt=Tt();const Ft=Xt(Vt),Bt={1:"north",2:"northeast",3:"northwest",4:"east",5:"west",6:"south",7:"southeast",8:"southwest",9:"up",10:"down",11:"in",12:"out"};class Zt{constructor(t){this.cache=new Map,this.mapReader=t,this.graph=this.buildGraph()}buildGraph(){const t={};return this.mapReader.getRooms().forEach(e=>{const i={},s=new Set((e.exitLocks??[]).map(n=>Bt[n]).filter(n=>!!n)),o=new Set(e.mSpecialExitLocks??[]);Object.entries(e.exits??{}).forEach(([n,r])=>{s.has(n)||this.mapReader.getRoom(r)&&(i[r.toString()]=1)}),Object.values(e.specialExits??{}).forEach(n=>{o.has(n)||this.mapReader.getRoom(n)&&(i[n.toString()]=1)}),t[e.id.toString()]=i}),new Ft(t)}findPath(t,e){const i=`${t}->${e}`;if(this.cache.has(i))return this.cache.get(i);if(t===e){const r=this.mapReader.getRoom(t)?[t]:null;return this.cache.set(i,r),r}if(!this.mapReader.getRoom(t)||!this.mapReader.getRoom(e))return this.cache.set(i,null),null;const s=this.graph.path(t.toString(),e.toString()),o=Array.isArray(s)?s:s?.path,n=o?o.map(r=>Number(r)):null;return this.cache.set(i,n),n}}const Gt={1:"north",2:"northeast",3:"northwest",4:"east",5:"west",6:"south",7:"southeast",8:"southwest",9:"up",10:"down",11:"in",12:"out"},G=class G{};G.areaWidth=150,G.areaHeight=80,G.areaSpacing=50,G.fontSize=14,G.connectionLineWidth=2,G.areaFillColor="#2a2a3e",G.areaStrokeColor="#4a4a6e",G.textColor="#e0e0e0",G.connectionColor="#6a6a8e",G.highlightColor="#ff9900";let z=G;class $t{constructor(t,e){this.areaNodes=new Map,this.connectionGroups=[],this.currentZoom=1,this.domainInfo=new Map,this.domainFilter="all",this.dotsMode=!1,this.stage=new y.Stage({container:t,width:t.clientWidth,height:t.clientHeight,draggable:!0}),this.backgroundLayer=new y.Layer({listening:!1}),this.stage.add(this.backgroundLayer),this.connectionLayer=new y.Layer({listening:!1}),this.stage.add(this.connectionLayer),this.areaLayer=new y.Layer,this.stage.add(this.areaLayer),this.mapReader=e,this.initScaling(),this.initResize(t)}initResize(t){new ResizeObserver(()=>{this.stage.width(t.clientWidth),this.stage.height(t.clientHeight),this.stage.batchDraw()}).observe(t)}initScaling(){this.stage.on("wheel",e=>{e.evt.preventDefault();const i=this.stage.scaleX(),s=this.stage.getPointerPosition();if(!s)return;const o={x:(s.x-this.stage.x())/i,y:(s.y-this.stage.y())/i},r=(e.evt.deltaY>0?-1:1)>0?this.currentZoom*1.1:this.currentZoom/1.1;this.setZoom(r);const a=this.stage.scaleX(),c={x:s.x-o.x*a,y:s.y-o.y*a};this.stage.position(c),this.stage.batchDraw()})}setZoom(t){this.currentZoom=Math.max(.1,Math.min(5,t)),this.stage.scale({x:this.currentZoom,y:this.currentZoom})}getZoom(){return this.currentZoom}setDomainInfo(t){this.domainInfo.clear();for(const[e,i]of Object.entries(t))this.domainInfo.set(Number(e),i)}setDomainFilter(t){this.domainFilter=t}getDomainFilter(){return this.domainFilter}setBackgroundImage(t){this.backgroundConfig={url:t.url,x:t.x,y:t.y,width:t.width,height:t.height,opacity:t.opacity??.3}}clearBackgroundImage(){this.backgroundConfig=void 0,this.backgroundImage=void 0,this.backgroundLayer.destroyChildren(),this.backgroundLayer.batchDraw()}redrawBackground(){this.drawBackground()}setDotsMode(t){this.dotsMode=t}getDotsMode(){return this.dotsMode}redraw(){this.drawBackground(),this.drawConnections(),this.drawAreas(),this.stage.batchDraw()}isAreaInDomain(t){const e=this.domainInfo.get(t);if(!e)return this.domainFilter==="interdomain"||this.domainFilter==="all";switch(this.domainFilter){case"ishtar":return e.isIshtar;case"empire":return e.isEmpire;case"interdomain":return!e.isIshtar&&!e.isEmpire;case"all":return!0}}areAreasInSameDomain(t,e){const i=this.domainInfo.get(t),s=this.domainInfo.get(e);return!i||!s?!1:!!(i.isIshtar&&s.isIshtar||i.isEmpire&&s.isEmpire||!i.isIshtar&&!i.isEmpire&&!s.isIshtar&&!s.isEmpire)}render(){this.analyzeConnections(),this.layoutAreas(),this.drawBackground(),this.drawConnections(),this.drawAreas(),this.centerView(),this.stage.batchDraw()}drawBackground(){if(this.backgroundLayer.destroyChildren(),!this.backgroundConfig)return;const t=new Image;t.crossOrigin="anonymous",t.onload=()=>{this.backgroundImage=new y.Image({x:this.backgroundConfig.x,y:this.backgroundConfig.y,image:t,width:this.backgroundConfig.width,height:this.backgroundConfig.height,opacity:this.backgroundConfig.opacity,listening:!1}),this.backgroundLayer.add(this.backgroundImage),this.backgroundLayer.batchDraw()},t.onerror=()=>{console.error("Failed to load background image:",this.backgroundConfig?.url)},t.src=this.backgroundConfig.url}analyzeConnections(){this.areaNodes.clear(),this.connectionGroups=[];const t=this.mapReader.getRooms(),e=this.mapReader.getAreas(),i=new Map;for(const c of e){const l=c.getAreaId(),d=c.getRooms();if(d.length===0)continue;let u=1/0,g=-1/0,f=1/0,m=-1/0,p=0;for(const k of d)k.z===0&&(p++,u=Math.min(u,k.x),g=Math.max(g,k.x),f=Math.min(f,k.y),m=Math.max(m,k.y));if(p===0)for(const k of d)u=Math.min(u,k.x),g=Math.max(g,k.x),f=Math.min(f,k.y),m=Math.max(m,k.y);const w=(u+g)/2,R=(f+m)/2;i.set(l,{minX:u,maxX:g,minY:f,maxY:m,centerX:w,centerY:R,roomCount:d.length})}let s=1;for(const c of i.values()){const l=c.maxX-c.minX,d=c.maxY-c.minY;s=Math.max(s,l,d)}const o=200,n=100,r=o/s;for(const c of e){const l=c.getAreaId(),d=i.get(l);if(!d||!this.isAreaInDomain(l))continue;const u=d.maxX-d.minX,g=d.maxY-d.minY;let f=Math.max(n,u*r),m=Math.max(n,g*r);const p=f/m;p>3?m=f/3:p<1/3&&(f=m/3),this.areaNodes.set(l,{areaId:l,name:c.getAreaName(),x:0,y:0,width:f,height:m,connections:[],roomCount:d.roomCount,realCenterX:d.centerX,realCenterY:d.centerY})}const a=new Map;for(const c of t){const l=c.area;if(!this.areaNodes.has(l))continue;const d=this.getLockedDirections(c),u=new Set(c.mSpecialExitLocks??[]);for(const[g,f]of Object.entries(c.exits??{})){if(d.has(g))continue;const m=this.mapReader.getRoom(f);if(!m||m.area===l||!this.areaNodes.has(m.area)||!this.areAreasInSameDomain(l,m.area))continue;const p=this.createConnection(c,m,g);p&&this.addConnection(a,p)}for(const[g,f]of Object.entries(c.specialExits??{})){if(u.has(f))continue;const m=this.mapReader.getRoom(f);if(!m||m.area===l||!this.areaNodes.has(m.area)||!this.areAreasInSameDomain(l,m.area))continue;const p=this.parseDirection(g),w=this.createConnection(c,m,p);w&&this.addConnection(a,w)}}for(const[c,l]of a){const[d,u]=c.split("-").map(Number),g=this.createConnectionGroup(d,u,l);this.connectionGroups.push(g);const f=this.areaNodes.get(d),m=this.areaNodes.get(u);if(f&&f.connections.push(...l),m)for(const p of l)m.connections.push({...p,fromAreaId:p.toAreaId,toAreaId:p.fromAreaId,fromRoomId:p.toRoomId,toRoomId:p.fromRoomId,direction:p.direction?wt[p.direction]:null,fromRoomPosition:p.toRoomPosition,toRoomPosition:p.fromRoomPosition})}}getLockedDirections(t){return new Set((t.exitLocks??[]).map(e=>Gt[e]).filter(e=>!!e))}createConnection(t,e,i){const s=this.toPlanarDirection(i);return{fromAreaId:t.area,toAreaId:e.area,fromRoomId:t.id,toRoomId:e.id,direction:s,fromRoomPosition:{x:t.x,y:t.y},toRoomPosition:{x:e.x,y:e.y}}}addConnection(t,e){const i=e.fromAreaId<e.toAreaId?`${e.fromAreaId}-${e.toAreaId}`:`${e.toAreaId}-${e.fromAreaId}`;t.has(i)||t.set(i,[]),t.get(i).push(e)}createConnectionGroup(t,e,i){const s=new Map;let o=0,n=0;for(const c of i)c.direction&&s.set(c.direction,(s.get(c.direction)??0)+1),o+=c.toRoomPosition.x-c.fromRoomPosition.x,n+=c.toRoomPosition.y-c.fromRoomPosition.y;let r=null,a=0;for(const[c,l]of s)l>a&&(a=l,r=c);return{fromAreaId:t,toAreaId:e,connections:i,primaryDirection:r,averageOffset:{x:o/i.length,y:n/i.length}}}parseDirection(t){const e=t.toLowerCase().trim();return{n:"north",north:"north",s:"south",south:"south",e:"east",east:"east",w:"west",west:"west",ne:"northeast",northeast:"northeast",nw:"northwest",northwest:"northwest",se:"southeast",southeast:"southeast",sw:"southwest",southwest:"southwest",u:"up",up:"up",d:"down",down:"down",i:"in",in:"in",o:"out",out:"out"}[e]??null}toPlanarDirection(t){return t&&ct.includes(t)?t:null}layoutAreas(){if(Array.from(this.areaNodes.values()).length===0)return;const e=this.findConnectedComponents();let i=0;const s=z.areaWidth*3;for(const o of e)if(o.length===1){const n=this.areaNodes.get(o[0]);n&&(n.x=i,n.y=0),i+=z.areaWidth+s}else{const n=this.forceDirectedLayout(o);for(const a of o){const c=this.areaNodes.get(a);c&&isFinite(n.minX)&&isFinite(n.minY)&&(c.x-=n.minX,c.x+=i,c.y-=n.minY)}const r=isFinite(n.maxX-n.minX)?n.maxX-n.minX:z.areaWidth;i+=r+s}}findConnectedComponents(){const t=new Set,e=[];for(const[i]of this.areaNodes){if(t.has(i))continue;const s=[],o=[i];for(;o.length>0;){const n=o.shift();if(t.has(n))continue;t.add(n),s.push(n);const r=this.areaNodes.get(n);if(r)for(const a of r.connections)t.has(a.toAreaId)||o.push(a.toAreaId)}e.push(s)}return e}forceDirectedLayout(t){const e=new Map;for(const x of t){const v=this.areaNodes.get(x);if(!v)continue;const C=new Set(v.connections.map(D=>D.toAreaId));e.set(x,C)}const i=new Set,s=new Set;for(const[x,v]of e)v.size>=3&&i.add(x);for(const[x,v]of e){if(i.has(x)||s.has(x)||v.size>2)continue;const C=[x];s.add(x);const D=Array.from(v);for(const M of D){let I=M,O=x;for(;I&&!s.has(I)&&!i.has(I);){const b=e.get(I);if(!b)break;if(b.size>=3){i.add(I);break}C.push(I),s.add(I);let L=!1;for(const W of b)if(W!==O&&!s.has(W)){O=I,I=W,L=!0;break}if(!L)break}}let S=!1;for(const M of C){const I=e.get(M);if(I){for(const O of I)if(i.has(O)){S=!0;break}}if(S)break}if(!S&&C.length>0){let M=C[0],I=e.get(C[0])?.size??0;for(const O of C){const b=e.get(O)?.size??0;b>I&&(I=b,M=O)}i.add(M),s.delete(M)}}for(const x of t){const v=e.get(x);(!v||v.size===0)&&i.add(x)}const o=new Map,n=new Map;for(const x of i)o.set(x,x),n.set(x,[]);const r=new Set(i);for(const x of i){const v=e.get(x)??new Set;for(const C of v){if(r.has(C))continue;const D=[];let S=C,M=x;for(;S&&!r.has(S);){D.push(S),o.set(S,x),r.add(S);const I=e.get(S)??new Set;let O;for(const b of I)if(b!==M&&!r.has(b)){O=b;break}M=S,S=O}D.length>0&&n.get(x).push(D)}}const a=new Set,c=[],l=i.values().next().value,d=l!==void 0?l:t[0];if(d!==void 0){const x=this.areaNodes.get(d);x&&(x.x=0,x.y=0,a.add(d),c.push(d))}for(;c.length>0;){const x=c.shift(),v=this.areaNodes.get(x),C=new Map;for(const D of v.connections){const S=D.toAreaId;if(a.has(S)||!i.has(S))continue;const M=this.areaNodes.get(S);if(!M)continue;const I=D.direction??"none";C.has(I)||C.set(I,[]),C.get(I).push({id:S,node:M,conn:D})}for(const[D,S]of C){const M=this.getDirectionOffset(D==="none"?null:D);S.sort((b,L)=>Math.abs(M.x)>Math.abs(M.y)?L.node.realCenterY-b.node.realCenterY:b.node.realCenterX-L.node.realCenterX);const I=z.areaWidth+z.areaSpacing,O=z.areaHeight+z.areaSpacing;S.forEach((b,L)=>{if(b.node.x=v.x+M.x*I,b.node.y=v.y+M.y*O,S.length>1){const W=(L-(S.length-1)/2)*.5;Math.abs(M.x)>Math.abs(M.y)?b.node.y+=W*O:b.node.x+=W*I}a.add(b.id),c.push(b.id)})}}const u=Array.from(i);u.length>1&&this.applyForces(u,80);const g=z.areaWidth+z.areaSpacing+30,f=z.areaHeight+z.areaSpacing+30,m=new Map,p=["east","west","north","south","northeast","northwest","southeast","southwest"];for(const[x,v]of n){const C=this.areaNodes.get(x);if(!C)continue;let D=0;const S=new Map;for(const M of v){let I=x,O=C.x,b=C.y,L=null;for(const W of M){const N=this.areaNodes.get(W);if(!N)continue;const B=this.areaNodes.get(I);let V=null;if(B){for(const Z of B.connections)if(Z.toAreaId===W){V=Z.direction;break}}!V&&I===x?(L=p[D%p.length],D++,V=L):!V&&L&&(V=L);const $=this.getDirectionOffset(V);let j=0;if(I===x&&V){const Z=V,st=S.get(Z)??0;S.set(Z,st+1),j=st}N.x=O+$.x*g,N.y=b+$.y*f,j>0&&($.x!==0&&$.y===0?N.y+=j*f*1.2:$.y!==0&&$.x===0?N.x+=j*g*1.2:(N.x+=j*g*1.2,N.y-=j*f*1.2)),m.set(W,{dx:N.x-C.x,dy:N.y-C.y,hubId:x}),I=W,O=N.x,b=N.y}}}const w=new Map,R=new Map;for(const x of i){const v=this.areaNodes.get(x);if(!v)continue;let C=v.x,D=v.y,S=v.x+v.width,M=v.y+v.height;const I=n.get(x)??[];for(const O of I)for(const b of O){const L=this.areaNodes.get(b);L&&(C=Math.min(C,L.x),D=Math.min(D,L.y),S=Math.max(S,L.x+L.width),M=Math.max(M,L.y+L.height))}w.set(x,{minX:C,minY:D,maxX:S,maxY:M}),R.set(x,{dx:C-v.x,dy:D-v.y})}this.applyClusterForces(u,w,R,60);for(const[x,v]of m){const C=this.areaNodes.get(x),D=this.areaNodes.get(v.hubId);!C||!D||(C.x=D.x+v.dx,C.y=D.y+v.dy)}let k=1/0,P=1/0,X=-1/0,Y=-1/0;for(const x of t){const v=this.areaNodes.get(x);k=Math.min(k,v.x),P=Math.min(P,v.y),X=Math.max(X,v.x+v.width),Y=Math.max(Y,v.y+v.height)}return{minX:k,minY:P,maxX:X,maxY:Y}}getDirectionOffset(t){const e={north:{x:0,y:-1},south:{x:0,y:1},east:{x:1,y:0},west:{x:-1,y:0},northeast:{x:.75,y:-.75},northwest:{x:-.75,y:-.75},southeast:{x:.75,y:.75},southwest:{x:-.75,y:.75}};return t&&e[t]?e[t]:{x:1,y:0}}applyClusterForces(t,e,i,s){const r=new Map;for(const a of t)r.set(a,{vx:0,vy:0});for(let a=0;a<s;a++){for(const c of t){const l=this.areaNodes.get(c),d=e.get(c),u=i.get(c);if(!l||!d||!u)continue;const g=d.maxX-d.minX,f=d.maxY-d.minY;d.minX=l.x+u.dx,d.minY=l.y+u.dy,d.maxX=d.minX+g,d.maxY=d.minY+f}for(const c of t){const l=this.areaNodes.get(c),d=r.get(c),u=e.get(c);if(!(!l||!d||!u)){for(const g of t){if(c===g)continue;const f=e.get(g);if(!f)continue;const m=(u.minX+u.maxX)/2,p=(u.minY+u.maxY)/2,w=(f.minX+f.maxX)/2,R=(f.minY+f.maxY)/2,k=m-w,P=p-R,X=(u.maxX-u.minX)/2,Y=(u.maxY-u.minY)/2,x=(f.maxX-f.minX)/2,v=(f.maxY-f.minY)/2,C=X+x+50,D=Y+v+50,S=C-Math.abs(k),M=D-Math.abs(P);if(S>0&&M>0)if(S<M){const I=S*(k>=0?1:-1)*.5;d.vx+=I}else{const I=M*(P>=0?1:-1)*.5;d.vy+=I}}for(const g of l.connections){const f=this.areaNodes.get(g.toAreaId);if(!f||!t.includes(g.toAreaId))continue;const m=f.x-l.x,p=f.y-l.y,w=Math.sqrt(m*m+p*p)||1,R=z.areaWidth+z.areaSpacing+50,P=(w-R)*.015;d.vx+=m/w*P,d.vy+=p/w*P}}}for(const c of t){const l=this.areaNodes.get(c),d=r.get(c);!l||!d||(l.x+=d.vx,l.y+=d.vy,d.vx*=.8,d.vy*=.8)}}}applyForces(t,e){const o=z.areaWidth+z.areaSpacing,n=z.areaWidth/2+60,r=new Set(t),a=[],c=new Set;for(const d of t){const u=this.areaNodes.get(d);if(u)for(const g of u.connections){if(!r.has(g.toAreaId))continue;const f=Math.min(d,g.toAreaId)+"-"+Math.max(d,g.toAreaId);c.has(f)||(c.add(f),a.push({from:d,to:g.toAreaId}))}}const l=new Map;for(const d of t)l.set(d,{vx:0,vy:0});for(let d=0;d<e;d++){for(const u of t){const g=this.areaNodes.get(u),f=l.get(u);if(!g||!f)continue;const m=g.x+g.width/2,p=g.y+g.height/2;for(const w of t){if(u===w)continue;const R=this.areaNodes.get(w);if(!R)continue;const k=(g.width+R.width)/2+20,P=(g.height+R.height)/2+20,X=g.x+g.width/2,Y=g.y+g.height/2,x=R.x+R.width/2,v=R.y+R.height/2,C=X-x,D=Y-v,S=k-Math.abs(C),M=P-Math.abs(D);S>0&&M>0&&(S<M?f.vx+=(C>=0?1:-1)*S*.5:f.vy+=(D>=0?1:-1)*M*.5)}for(const w of a){if(w.from===u||w.to===u)continue;const R=this.areaNodes.get(w.from),k=this.areaNodes.get(w.to);if(!R||!k)continue;const P=R.x+R.width/2,X=R.y+R.height/2,Y=k.x+k.width/2,x=k.y+k.height/2,v=this.closestPointOnSegment(m,p,P,X,Y,x),C=m-v.x,D=p-v.y,S=Math.sqrt(C*C+D*D)||1;if(S<n){const M=(n-S)*.6;f.vx+=C/S*M,f.vy+=D/S*M}}for(const w of g.connections){if(!r.has(w.toAreaId))continue;const R=this.areaNodes.get(w.toAreaId);if(!R)continue;const k=R.x-g.x,P=R.y-g.y,X=Math.sqrt(k*k+P*P)||1,x=(X-o)*.03;f.vx+=k/X*x,f.vy+=P/X*x;const v=this.getDirectionOffset(w.direction),C=g.x+v.x*o,D=g.y+v.y*o,S=l.get(w.toAreaId);S&&(S.vx+=(C-R.x)*.01,S.vy+=(D-R.y)*.01)}}for(const u of t){const g=this.areaNodes.get(u),f=l.get(u);!g||!f||(g.x+=f.vx,g.y+=f.vy,f.vx*=.8,f.vy*=.8)}}}closestPointOnSegment(t,e,i,s,o,n){const r=o-i,a=n-s,c=t-i,l=e-s,d=r*r+a*a;if(d===0)return{x:i,y:s};let u=(c*r+l*a)/d;return u=Math.max(0,Math.min(1,u)),{x:i+u*r,y:s+u*a}}edgesIntersect(t,e,i,s,o,n,r,a){const c=(l,d,u,g,f,m)=>(m-d)*(u-l)>(g-d)*(f-l);return c(t,e,o,n,r,a)!==c(i,s,o,n,r,a)&&c(t,e,i,s,o,n)!==c(t,e,i,s,r,a)}drawConnections(){this.connectionLayer.destroyChildren();for(const t of this.connectionGroups){const e=this.areaNodes.get(t.fromAreaId),i=this.areaNodes.get(t.toAreaId);if(!e||!i||!isFinite(e.x)||!isFinite(e.y)||!isFinite(i.x)||!isFinite(i.y))continue;const s={x:e.x+e.width/2,y:e.y+e.height/2},o={x:i.x+i.width/2,y:i.y+i.height/2};let n,r;if(this.dotsMode?(n=s,r=o):(n=this.getEdgePoint(e,o),r=this.getEdgePoint(i,s)),!isFinite(n.x)||!isFinite(n.y)||!isFinite(r.x)||!isFinite(r.y))continue;const a=this.dotsMode?"#ffffff":z.connectionColor,c=this.dotsMode?1:Math.min(z.connectionLineWidth,1+t.connections.length*.5),l=new y.Line({points:[n.x,n.y,r.x,r.y],stroke:a,strokeWidth:c,lineCap:"round",listening:!1});this.connectionLayer.add(l)}}getEdgePoint(t,e){const i=t.x+t.width/2,s=t.y+t.height/2,o=e.x-i,n=e.y-s,r=t.width/2,a=t.height/2;if(o===0&&n===0)return{x:i,y:s};const c=Math.abs(o),l=Math.abs(n);let d;return c/r>l/a?d=r/c:d=a/l,{x:i+o*d,y:s+n*d}}drawAreas(){this.areaLayer.destroyChildren();for(const[,t]of this.areaNodes){if(!isFinite(t.x)||!isFinite(t.y))continue;const e=t.areaId===this.highlightedArea;if(this.dotsMode){const s=t.x+t.width/2,o=t.y+t.height/2,n=new y.Group({x:s,y:o,draggable:!0}),r=new y.Circle({radius:6,fill:e?z.highlightColor:"#ffffff",stroke:e?z.highlightColor:"#ffffff",strokeWidth:1}),a=new y.Text({text:t.name,fontSize:10,fill:"#ffffff",x:10,y:-5});n.add(r),n.add(a),n.on("click tap",()=>{this.emitAreaClickEvent(t.areaId)}),n.on("mouseenter",()=>{this.stage.container().style.cursor="pointer",r.fill(z.highlightColor),r.stroke(z.highlightColor),this.areaLayer.batchDraw()}),n.on("mouseleave",()=>{this.stage.container().style.cursor="auto",r.fill(e?z.highlightColor:"#ffffff"),r.stroke(e?z.highlightColor:"#ffffff"),this.areaLayer.batchDraw()}),n.on("dragmove",()=>{t.x=n.x()-t.width/2,t.y=n.y()-t.height/2,this.drawConnections(),this.connectionLayer.batchDraw()}),n.on("dragstart",()=>{this.stage.container().style.cursor="grabbing"}),n.on("dragend",()=>{this.stage.container().style.cursor="pointer"}),this.areaLayer.add(n)}else{const i=new y.Group({x:t.x,y:t.y,draggable:!0}),s=new y.Rect({width:t.width,height:t.height,fill:z.areaFillColor,stroke:e?z.highlightColor:z.areaStrokeColor,strokeWidth:e?3:2,cornerRadius:8}),o=new y.Text({text:t.name,fontSize:z.fontSize,fill:z.textColor,width:t.width-10,height:t.height-20,x:5,y:10,align:"center",verticalAlign:"middle",ellipsis:!0,wrap:"word"}),n=new y.Text({text:`${t.roomCount} rooms`,fontSize:10,fill:z.connectionColor,width:t.width-10,x:5,y:t.height-18,align:"center"});i.add(s),i.add(o),i.add(n),i.on("click tap",()=>{this.emitAreaClickEvent(t.areaId)}),i.on("mouseenter",()=>{this.stage.container().style.cursor="pointer",s.stroke(z.highlightColor),this.areaLayer.batchDraw()}),i.on("mouseleave",()=>{this.stage.container().style.cursor="auto",s.stroke(e?z.highlightColor:z.areaStrokeColor),this.areaLayer.batchDraw()}),i.on("dragmove",()=>{t.x=i.x(),t.y=i.y(),this.drawConnections(),this.connectionLayer.batchDraw()}),i.on("dragstart",()=>{this.stage.container().style.cursor="grabbing"}),i.on("dragend",()=>{this.stage.container().style.cursor="pointer"}),this.areaLayer.add(i)}}}centerView(){let t=1/0,e=1/0,i=-1/0,s=-1/0;for(const[,f]of this.areaNodes)t=Math.min(t,f.x),e=Math.min(e,f.y),i=Math.max(i,f.x+f.width),s=Math.max(s,f.y+f.height);if(!isFinite(t))return;const o=i-t,n=s-e,r=t+o/2,a=e+n/2,c=50,l=(this.stage.width()-c*2)/o,d=(this.stage.height()-c*2)/n,u=Math.min(l,d,1.5);this.setZoom(u);const g=this.stage.scaleX();this.stage.position({x:this.stage.width()/2-r*g,y:this.stage.height()/2-a*g})}highlightArea(t){this.highlightedArea=t,this.drawAreas(),this.stage.batchDraw()}centerOnArea(t){const e=this.areaNodes.get(t);if(!e)return;const i=this.stage.scaleX(),s=e.x+e.width/2,o=e.y+e.height/2;this.stage.position({x:this.stage.width()/2-s*i,y:this.stage.height()/2-o*i}),this.stage.batchDraw()}emitAreaClickEvent(t){const e=new CustomEvent("areaclick",{detail:{areaId:t}});this.stage.container().dispatchEvent(e)}getAreaNode(t){return this.areaNodes.get(t)}getConnectionGroups(){return this.connectionGroups}destroy(){this.stage.destroy()}}exports.AreaMapRenderer=$t;exports.AreaMapSettings=z;exports.ExplorationArea=tt;exports.MapReader=Pt;exports.PathFinder=Zt;exports.Renderer=Nt;exports.Settings=h;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const y=require("konva"),H=["north","south","east","west","northeast","northwest","southeast","southwest"],T={north:"n",south:"s",east:"e",west:"w",northeast:"ne",northwest:"nw",southeast:"se",southwest:"sw",up:"u",down:"d",in:"i",out:"o"},it={north:{x:0,y:-1},south:{x:0,y:1},east:{x:1,y:0},west:{x:-1,y:0},northeast:{x:1,y:-1},northwest:{x:-1,y:-1},southeast:{x:1,y:1},southwest:{x:-1,y:1}},ct=["north","south","east","west","northeast","northwest","southeast","southwest"],wt={north:"south",south:"north",east:"west",west:"east",northeast:"southwest",northwest:"southeast",southeast:"northwest",southwest:"northeast"};function dt(E){return E?Object.prototype.hasOwnProperty.call(it,E):!1}function A(E,t,e,i=1){if(!dt(e))return{x:E,y:t};const s=it[e];return{x:E+s.x*i,y:t+s.y*i}}function Rt(E,t,e,i=1,s=0){if(!dt(e))return{x:E,y:t};const o=it[e];if(!(o.x!==0&&o.y!==0)||s<=0)return A(E,t,e,i);const r=i-s+s/Math.SQRT2;return{x:E+o.x*r,y:t+o.y*r}}function vt(E,t,e,i=1){if(!dt(e))return{x:E,y:t};const s=it[e],o=Math.atan2(s.y,s.x);return{x:E+Math.cos(o)*i,y:t+Math.sin(o)*i}}const q={OPEN_DOOR:"rgb(10, 155, 10)",CLOSED_DOOR:"rgb(226, 205, 59)",LOCKED_DOOR:"rgb(155, 10, 10)",ONE_WAY_FILL:"rgb(155, 10, 10)"},St={1:"north",2:"northeast",3:"northwest",4:"east",5:"west",6:"south",7:"southeast",8:"southwest",9:"up",10:"down",11:"in",12:"out"},kt=["up","down","in","out"];function lt(E){switch(E){case 1:return q.OPEN_DOOR;case 2:return q.CLOSED_DOOR;default:return q.LOCKED_DOOR}}class Ct{constructor(t,e){this.mapReader=t,this.mapRenderer=e}getRoomEdgePoint(t,e,i,s){return h.roomShape==="circle"?vt(t,e,i,s):h.roomShape==="roundedRectangle"?Rt(t,e,i,s,h.roomSize*.2):A(t,e,i,s)}renderData(t,e){return this.renderDataWithColor(t,h.lineColor,e)}renderDataWithColor(t,e,i){const s=t.aDir&&H.includes(t.aDir),o=t.bDir&&H.includes(t.bDir);if(s&&o)return this.renderTwoWayExitData(t,e,i);if(s||o){const n=s?"a":"b";return this.renderOneWayExitData(t,e,n)}}renderTwoWayExitData(t,e,i){const s=this.mapReader.getRoom(t.a),o=this.mapReader.getRoom(t.b);if(!s||!o||!t.aDir||!t.bDir||s.customLines[T[t.aDir]]&&o.customLines[T[t.bDir]]||s.z!==o.z&&(i!==o.z&&s.customLines[T[t.aDir]]||i!==s.z&&o.customLines[T[t.bDir]]))return;const n=this.getRoomEdgePoint(s.x,s.y,t.aDir,h.roomSize/2),r=this.getRoomEdgePoint(o.x,o.y,t.bDir,h.roomSize/2),a=[n.x,n.y,r.x,r.y],c=[{points:a,stroke:e,strokeWidth:h.lineWidth}],l=[],d=s.doors[T[t.aDir]]??o.doors[T[t.bDir]];if(d){const p=a[0]+(a[2]-a[0])/2,w=a[1]+(a[3]-a[1])/2;l.push({x:p-h.roomSize/4,y:w-h.roomSize/4,width:h.roomSize/2,height:h.roomSize/2,stroke:lt(d),strokeWidth:h.lineWidth})}const u=Math.min(a[0],a[2]),g=Math.max(a[0],a[2]),f=Math.min(a[1],a[3]),m=Math.max(a[1],a[3]);return{lines:c,arrows:[],doors:l,bounds:{x:u,y:f,width:g-u,height:m-f}}}renderOneWayExitData(t,e,i){const s=i==="a"||!i&&t.aDir,o=s?this.mapReader.getRoom(t.a):this.mapReader.getRoom(t.b),n=s?this.mapReader.getRoom(t.b):this.mapReader.getRoom(t.a),r=s?t.aDir:t.bDir;if(!r||!o||!n||!H.includes(r)||o.customLines[T[r]||r])return;if(o.area!=n.area&&r){const P=this.mapReader.getColorValue(n.env),X=this.getRoomEdgePoint(o.x,o.y,r,h.roomSize/2),Y=A(o.x,o.y,r,h.roomSize*1.5),x=P;return{lines:[],arrows:[{points:[X.x,X.y,Y.x,Y.y],pointerLength:.3,pointerWidth:.3,strokeWidth:h.lineWidth*1.4,stroke:x,fill:x}],doors:[],bounds:{x:Math.min(X.x,Y.x),y:Math.min(X.y,Y.y),width:Math.abs(Y.x-X.x),height:Math.abs(Y.y-X.y)}}}let a={x:n.x,y:n.y};(n.area!==o.area||n.z!==o.z)&&(a=A(o.x,o.y,r,h.roomSize/2));const c=A(o.x,o.y,r,.3),l=c.x-(c.x-a.x)/2,d=c.y-(c.y-a.y)/2,u=this.getRoomEdgePoint(o.x,o.y,r,h.roomSize/2),g=[u.x,u.y,a.x,a.y],f=[u.x,a.x,l],m=[u.y,a.y,d],p=Math.min(...f),w=Math.max(...f),R=Math.min(...m),k=Math.max(...m);return{lines:[{points:g,stroke:e,strokeWidth:h.lineWidth,dash:[.1,.05]}],arrows:[{points:[g[0],g[1],l,d],pointerLength:.5,pointerWidth:.35,strokeWidth:h.lineWidth*1.4,stroke:e,fill:q.ONE_WAY_FILL,dash:[.1,.05]}],doors:[],bounds:{x:p,y:R,width:w-p,height:k-R}}}render(t,e){return this.renderWithColor(t,h.lineColor,e)}renderWithColor(t,e,i){const s=t.aDir&&H.includes(t.aDir),o=t.bDir&&H.includes(t.bDir);if(s&&o)return this.renderTwoWayExit(t,e,i);if(s||o){const n=s?"a":"b";return this.renderOneWayExit(t,e,n)}}renderTwoWayExit(t,e,i){const s=this.mapReader.getRoom(t.a),o=this.mapReader.getRoom(t.b);if(!s||!o||!t.aDir||!t.bDir||s.customLines[T[t.aDir]]&&o.customLines[T[t.bDir]]||s.z!==o.z&&(i!==o.z&&s.customLines[T[t.aDir]]||i!==s.z&&o.customLines[T[t.bDir]]))return;const n=new y.Group({listening:!1}),r=[];if(r.push(...Object.values(this.getRoomEdgePoint(s.x,s.y,t.aDir,h.roomSize/2))),r.push(...Object.values(this.getRoomEdgePoint(o.x,o.y,t.bDir,h.roomSize/2))),s.doors[T[t.aDir]]||o.doors[T[t.bDir]]){const c=this.renderDoor(r,s.doors[T[t.aDir]]??o.doors[T[t.bDir]]);n.add(c)}const a=new y.Line({points:r,stroke:e,strokeWidth:h.lineWidth,perfectDrawEnabled:!1,listening:!1});return n.add(a),n}renderOneWayExit(t,e,i){const s=i==="a"||!i&&t.aDir,o=s?this.mapReader.getRoom(t.a):this.mapReader.getRoom(t.b),n=s?this.mapReader.getRoom(t.b):this.mapReader.getRoom(t.a),r=s?t.aDir:t.bDir;if(!r||!o||!n||!H.includes(r)||o.customLines[T[r]||r])return;if(o.area!=n.area&&r){const p=this.mapReader.getColorValue(n.env);return this.renderAreaExit(o,r,p)}let a={x:n.x,y:n.y};(n.area!==o.area||n.z!==o.z)&&(a=A(o.x,o.y,r,h.roomSize/2));const c=A(o.x,o.y,r,.3),l=c.x-(c.x-a.x)/2,d=c.y-(c.y-a.y)/2,u=new y.Group({listening:!1}),g=[];g.push(...Object.values(this.getRoomEdgePoint(o.x,o.y,r,h.roomSize/2))),g.push(a.x,a.y);const f=new y.Line({points:g,stroke:e,strokeWidth:h.lineWidth,dashEnabled:!0,dash:[.1,.05],perfectDrawEnabled:!1,listening:!1});u.add(f);const m=new y.Arrow({points:[g[0],g[1],l,d],pointerLength:.5,pointerWidth:.35,strokeWidth:h.lineWidth*1.4,stroke:e,fill:q.ONE_WAY_FILL,dashEnabled:!0,dash:[.1,.05],perfectDrawEnabled:!1,listening:!1});return u.add(m),u}renderAreaExit(t,e,i){const s=this.getRoomEdgePoint(t.x,t.y,e,h.roomSize/2),o=A(t.x,t.y,e,h.roomSize*1.5),n=i??this.mapReader.getColorValue(t.env);return new y.Arrow({points:[s.x,s.y,o.x,o.y],pointerLength:.3,pointerWidth:.3,strokeWidth:h.lineWidth*1.4,stroke:n,fill:n,perfectDrawEnabled:!1,listening:!1})}renderSpecialExits(t,e){return Object.entries(t.customLines).flatMap(([i,s])=>{const o=[t.x,t.y];s.points.reduce((u,g)=>(u.push(g.x,-g.y),u),o);const n=s.attributes.arrow?y.Arrow:y.Line,r=e??`rgb(${s.attributes.color.r}, ${s.attributes.color.g}, ${s.attributes.color.b})`,a=new n({points:o,strokeWidth:h.lineWidth,stroke:r,fill:e??`rgb(${s.attributes.color.r}, ${s.attributes.color.g} , ${s.attributes.color.b})`,pointerLength:.3,pointerWidth:.2,perfectDrawEnabled:!1,listening:!1});let c=s.attributes.style;c==="dot line"?(a.dash([.05,.05]),a.dashOffset(.1)):c==="dash line"?a.dash([.4,.2]):c==="solid line"||c!==void 0&&console.log("Brak opisu stylu: "+c);const l=[a],d=t.doors[i];return d&&o.length>=4&&l.push(this.renderDoor(o,d)),l})}renderStubs(t,e=h.lineColor){return t.stubs.map(i=>{const s=St[i],o=this.getRoomEdgePoint(t.x,t.y,s,h.roomSize/2),n=A(t.x,t.y,s,h.roomSize/2+.5),r=[o.x,o.y,n.x,n.y];return new y.Line({points:r,stroke:e,strokeWidth:h.lineWidth,perfectDrawEnabled:!1,listening:!1})})}renderInnerExits(t){return kt.map(e=>{if(t.exits[e]){const i=new y.Group({listening:!1}),s=new y.RegularPolygon({x:t.x,y:t.y,sides:3,fill:this.mapReader.getSymbolColor(t.env,.6),stroke:this.mapReader.getSymbolColor(t.env),strokeWidth:h.lineWidth,radius:h.roomSize/5,scaleX:1.4,scaleY:.8,perfectDrawEnabled:!1,listening:!1});i.add(s);let o=t.doors[e];if(o!==void 0)switch(o){case 1:s.stroke(q.OPEN_DOOR);break;case 2:s.stroke(q.CLOSED_DOOR);break;default:s.stroke(q.LOCKED_DOOR)}const n=s.stroke();switch(e){case"up":s.position(A(t.x,t.y,"south",h.roomSize/4));break;case"down":s.rotation(180),s.position(A(t.x,t.y,"north",h.roomSize/4));break;case"in":{s.rotation(90),s.position(A(t.x,t.y,"west",h.roomSize/4));const r=A(t.x,t.y,"east",h.roomSize/4);i.add(new y.RegularPolygon({x:r.x,y:r.y,sides:3,fill:s.fill(),stroke:n,strokeWidth:h.lineWidth,radius:h.roomSize/5,scaleX:1.4,scaleY:.8,rotation:-90,perfectDrawEnabled:!1,listening:!1}));break}case"out":{s.rotation(-90),s.position(A(t.x,t.y,"west",h.roomSize/4));const r=A(t.x,t.y,"east",h.roomSize/4);i.add(new y.RegularPolygon({x:r.x,y:r.y,sides:3,fill:s.fill(),stroke:n,strokeWidth:h.lineWidth,radius:h.roomSize/5,scaleX:1.4,scaleY:.8,rotation:90,perfectDrawEnabled:!1,listening:!1}));break}}return i}}).filter(e=>e!==void 0)}renderDoor(t,e){const i={x:t[0]+(t[2]-t[0])/2,y:t[1]+(t[3]-t[1])/2};return new y.Rect({x:i.x-h.roomSize/4,y:i.y-h.roomSize/4,width:h.roomSize/2,height:h.roomSize/2,stroke:lt(e),strokeWidth:h.lineWidth,perfectDrawEnabled:!1,listening:!1})}}class Et{constructor(t,e){this.rooms=[],this.labels=[],this.rooms=t,this.bounds=this.createBounds(),this.labels=e}getRooms(){return this.rooms}getLabels(){return this.labels}getBounds(){return this.bounds}createBounds(){return this.rooms.reduce((t,e)=>({minX:Math.min(t.minX,e.x),maxX:Math.max(t.maxX,e.x),minY:Math.min(t.minY,e.y),maxY:Math.max(t.maxY,e.y)}),{minX:Number.POSITIVE_INFINITY,maxX:Number.NEGATIVE_INFINITY,minY:Number.POSITIVE_INFINITY,maxY:Number.NEGATIVE_INFINITY})}}const et=class et{constructor(t){this.planes={},this.exits=new Map,this.version=0,this.area=t,this.planes=this.createPlanes(),this.createExits()}getAreaName(){return this.area.areaName}getAreaId(){return parseInt(this.area.areaId)}getVersion(){return this.version}markDirty(){this.version++}getPlane(t){return this.planes[t]}getPlanes(){return Object.values(this.planes)}getRooms(){return this.area.rooms}getLinkExits(t){return Array.from(this.exits.values()).filter(e=>e.zIndex.includes(t))}createPlanes(){const t=this.area.rooms.reduce((e,i)=>(e[i.z]||(e[i.z]=[]),e[i.z].push(i),e),{});return Object.entries(t).reduce((e,[i,s])=>(e[+i]=new Et(s,this.area.labels.filter(o=>o.Z===+i)),e),{})}createExits(){const t=new Map;this.area.rooms.forEach(e=>{Object.entries(e.exits).forEach(([i,s])=>{if(e.id===s)return;const o=Math.min(e.id,s),n=Math.max(e.id,s),r=`${o}-${n}`;t.has(r)||t.set(r,[]),t.get(r).push({origin:e.id,target:s,z:e.z,dir:i})})});for(const[e,i]of t){const[s,o]=e.split("-"),n=parseInt(s),r=parseInt(o),a=i.filter(d=>d.origin===n),c=i.filter(d=>d.origin===r),l=new Set;for(const d of a){let u=-1;for(let g=0;g<c.length;g++)if(!l.has(g)){if(c[g].dir===et.oppositeDir[d.dir]){u=g;break}u===-1&&(u=g)}if(u!==-1){l.add(u);const g=c[u];this.exits.set(`${e}-${d.dir}`,{a:n,b:r,aDir:d.dir,bDir:g.dir,zIndex:[d.z,g.z]})}else this.exits.set(`${e}-a:${d.dir}`,{a:n,b:r,aDir:d.dir,zIndex:[d.z]})}for(let d=0;d<c.length;d++)if(!l.has(d)){const u=c[d];this.exits.set(`${e}-b:${u.dir}`,{a:n,b:r,bDir:u.dir,zIndex:[u.z]})}}}};et.oppositeDir={north:"south",south:"north",east:"west",west:"east",northeast:"southwest",southwest:"northeast",northwest:"southeast",southeast:"northwest",up:"down",down:"up",in:"out",out:"in"};let _=et;class ut extends Et{constructor(t,e){super(t.getRooms(),t.getLabels()),this.basePlane=t,this.visitedRooms=e}getRooms(){return this.basePlane.getRooms().filter(t=>this.visitedRooms.has(t.id))}getLabels(){return this.basePlane.getLabels()}getBounds(){const t=this.getRooms();return t.length?t.reduce((e,i)=>({minX:Math.min(e.minX,i.x),maxX:Math.max(e.maxX,i.x),minY:Math.min(e.minY,i.y),maxY:Math.max(e.maxY,i.y)}),{minX:Number.POSITIVE_INFINITY,maxX:Number.NEGATIVE_INFINITY,minY:Number.POSITIVE_INFINITY,maxY:Number.NEGATIVE_INFINITY}):this.basePlane.getBounds()}}class tt extends _{constructor(t,e){super(t),this.planeCache=new WeakMap,this.visitedRooms=e instanceof Set?e:new Set(e??[]),this.areaRoomIds=new Set(t.rooms.map(i=>i.id))}getPlane(t){const e=super.getPlane(t);if(!e)return e;let i=this.planeCache.get(e);return i||(i=new ut(e,this.visitedRooms),this.planeCache.set(e,i)),i}getPlanes(){return super.getPlanes().map(t=>{let e=this.planeCache.get(t);return e||(e=new ut(t,this.visitedRooms),this.planeCache.set(t,e)),e})}getLinkExits(t){return super.getLinkExits(t).filter(e=>this.visitedRooms.has(e.a)||this.visitedRooms.has(e.b))}getVisitedRoomCount(){return super.getRooms().reduce((t,e)=>t+(this.visitedRooms.has(e.id)?1:0),0)}getTotalRoomCount(){return this.areaRoomIds.size}hasVisitedRoom(t){return this.areaRoomIds.has(t)&&this.visitedRooms.has(t)}getVisitedRoomIds(){return super.getRooms().filter(t=>this.visitedRooms.has(t.id)).map(t=>t.id)}addVisitedRoom(t){const e=this.visitedRooms.has(t);this.visitedRooms.add(t);const i=!e&&this.areaRoomIds.has(t);return i&&this.markDirty(),i}addVisitedRooms(t){let e=0;for(const i of t){const s=this.visitedRooms.has(i);this.visitedRooms.add(i),!s&&this.areaRoomIds.has(i)&&e++}return e>0&&this.markDirty(),e}}const Q=["up","down","in","out"];class Mt{constructor(t,e){this.paths=[],this.mapReader=t,this.overlayLayer=e}getRoomEdgePoint(t,e,i,s){return h.roomShape==="circle"?vt(t,e,i,s):h.roomShape==="roundedRectangle"?Rt(t,e,i,s,h.roomSize*.2):A(t,e,i,s)}findConnection(t,e){for(const[i,s]of Object.entries(t.exits))if(s===e.id){const o=i;if(Q.includes(o)){const a=T[o],c=t.customLines[a]?a:t.customLines[o]?o:void 0;return{type:"inner",fromDir:o,customLineKey:c,fromRoom:t,toRoom:e}}const n=T[o];if(t.customLines[n])return{type:"special",fromDir:o,customLineKey:n,fromRoom:t,toRoom:e};if(t.customLines[o])return{type:"special",fromDir:o,customLineKey:o,fromRoom:t,toRoom:e};const r=this.findExitDirection(e,t.id);return{type:"regular",fromDir:o,toDir:r,fromRoom:t,toRoom:e}}for(const[i,s]of Object.entries(t.specialExits))if(s===e.id)return t.customLines[i]?{type:"special",customLineKey:i,fromRoom:t,toRoom:e}:{type:"inner",fromRoom:t,toRoom:e};for(const[i,s]of Object.entries(e.exits))if(s===t.id){const o=i;if(Q.includes(o)){const r=T[o],a=e.customLines[r]?r:e.customLines[o]?o:void 0;return{type:"inner",toDir:o,customLineKey:a,fromRoom:t,toRoom:e}}const n=T[o];return e.customLines[n]?{type:"special",toDir:o,customLineKey:n,fromRoom:t,toRoom:e}:e.customLines[o]?{type:"special",toDir:o,customLineKey:o,fromRoom:t,toRoom:e}:{type:"regular",toDir:o,fromRoom:t,toRoom:e}}for(const[i,s]of Object.entries(e.specialExits))if(s===t.id)return e.customLines[i]?{type:"special",customLineKey:i,fromRoom:t,toRoom:e}:{type:"inner",fromRoom:t,toRoom:e};return{type:"none",fromRoom:t,toRoom:e}}findExitDirection(t,e){for(const[i,s]of Object.entries(t.exits))if(s===e)return i}createStrokedLine(t,e){const i=new y.Group;return i.opacity(.8),i.add(new y.Line({points:t,stroke:"black",strokeWidth:h.lineWidth*8,lineCap:"round",lineJoin:"round"})),i.add(new y.Line({points:t,stroke:e,strokeWidth:h.lineWidth*4,lineCap:"round",lineJoin:"round"})),i}renderInnerExitMarker(t,e,i){const s=new y.Group;s.opacity(.8);const o=new y.RegularPolygon({x:t.x,y:t.y,sides:3,fill:i,stroke:"black",strokeWidth:h.lineWidth*2,radius:h.roomSize/5,scaleX:1.4,scaleY:.8});switch(e){case"up":o.position(A(t.x,t.y,"south",h.roomSize/4));break;case"down":o.rotation(180),o.position(A(t.x,t.y,"north",h.roomSize/4));break;case"in":const n=o.clone();n.rotation(-90),n.position(A(t.x,t.y,"east",h.roomSize/4)),s.add(n),o.rotation(90),o.position(A(t.x,t.y,"west",h.roomSize/4));break;case"out":const r=o.clone();r.rotation(90),r.position(A(t.x,t.y,"east",h.roomSize/4)),s.add(r),o.rotation(-90),o.position(A(t.x,t.y,"west",h.roomSize/4));break}return s.add(o),s}renderPath(t,e,i,s="#66E64D"){if(e===void 0||i===void 0)return;const o=t.map(a=>this.mapReader.getRoom(a)).filter(a=>a!==void 0);let n=[];const r=()=>{if(n.length>=4){const a=this.createStrokedLine(n,s);this.overlayLayer.add(a),this.paths.push(a)}n=[]};for(let a=0;a<o.length-1;a++){const c=o[a],l=o[a+1],d=this.isRoomVisible(c,e,i),u=this.isRoomVisible(l,e,i);if(!d&&!u){r();continue}const g=this.findConnection(c,l);if(d&&u)switch(g.type){case"regular":this.addRegularConnectionPoints(g,n);break;case"special":this.addSpecialConnectionPoints(g,n);break;case"inner":r(),this.renderInnerConnection(g,s);break;case"none":n.length===0&&n.push(c.x,c.y),n.push(l.x,l.y);break}else{const f=d?c:l,m=d?l:c,p=this.getExitToRoom(f,m);if(p){if(Q.includes(p.direction)){r();const w=this.renderInnerExitMarker(f,p.direction,s);this.overlayLayer.add(w),this.paths.push(w)}else if(H.includes(p.direction)){n.length===0&&n.push(f.x,f.y);const w=this.getRoomEdgePoint(f.x,f.y,p.direction,h.roomSize/2),R=A(f.x,f.y,p.direction,h.roomSize);n.push(w.x,w.y,R.x,R.y),r()}}else{const w=this.getDirectionTowards(f,m);if(w){n.length===0&&n.push(f.x,f.y);const R=this.getRoomEdgePoint(f.x,f.y,w,h.roomSize/2),k=A(f.x,f.y,w,h.roomSize);n.push(R.x,R.y,k.x,k.y),r()}}}}return r(),this.paths[0]}addRegularConnectionPoints(t,e){const{fromRoom:i,toRoom:s,fromDir:o,toDir:n}=t;if(e.length===0&&e.push(i.x,i.y),o&&H.includes(o)){const r=this.getRoomEdgePoint(i.x,i.y,o,h.roomSize/2);e.push(r.x,r.y)}if(n&&H.includes(n)){const r=this.getRoomEdgePoint(s.x,s.y,n,h.roomSize/2);e.push(r.x,r.y)}e.push(s.x,s.y)}addSpecialConnectionPoints(t,e){const{fromRoom:i,toRoom:s,customLineKey:o}=t;let n=i,r;o&&(r=i.customLines[o],r||(r=s.customLines[o],n=s)),e.length===0&&e.push(n.x,n.y),r&&r.points.forEach(a=>{e.push(a.x,-a.y)}),e.push(s.x,s.y)}renderInnerConnection(t,e){const{fromRoom:i,toRoom:s,fromDir:o,toDir:n,customLineKey:r}=t;if(r){let a=i,c=i.customLines[r];if(c||(c=s.customLines[r],a=s),c){const l=[a.x,a.y];c.points.forEach(u=>{l.push(u.x,-u.y)});const d=this.createStrokedLine(l,e);this.overlayLayer.add(d),this.paths.push(d)}}if(o&&Q.includes(o)){const a=this.renderInnerExitMarker(i,o,e);this.overlayLayer.add(a),this.paths.push(a)}if(n&&Q.includes(n)){const a=this.renderInnerExitMarker(s,n,e);this.overlayLayer.add(a),this.paths.push(a)}}clearPaths(){this.paths.forEach(t=>{t.destroy()}),this.paths=[]}isRoomVisible(t,e,i){return t?t.area===e&&t.z===i:!1}getExitToRoom(t,e){for(const[i,s]of Object.entries(t.exits))if(s===e.id)return{direction:i};for(const[i,s]of Object.entries(t.specialExits))if(s===e.id)return}getDirectionTowards(t,e){for(const i of ct)if(t.exits[i]===e.id)return i;for(const i of ct)if(e.exits[i]===t.id)return wt[i]}}const Dt=.6,K=75,It=.025,Lt="rgb(225, 255, 225)",U="rgb(120, 72, 0)";class zt{constructor(t=60){this.samples=[],this.lastCullingTime=0,this.callback=null,this.windowSize=t}setCallback(t){t!==this.callback&&(this.callback=t,this.samples=[])}record(t){this.callback&&(this.samples.push(t),this.samples.length>=this.windowSize&&this.flush())}computeFps(){const t=performance.now(),e=t-this.lastCullingTime;return this.lastCullingTime=t,e>0?1e3/e:0}flush(){const t=this.samples.length;if(t===0)return;const e={cullingMs:0,gridMs:0,visibleRooms:0,totalRooms:0,visibleExits:0,fps:0};for(const i of this.samples)e.cullingMs+=i.cullingMs,e.gridMs+=i.gridMs,e.visibleRooms+=i.visibleRooms,e.totalRooms+=i.totalRooms,e.visibleExits+=i.visibleExits,e.fps+=i.fps;e.cullingMs/=t,e.gridMs/=t,e.visibleRooms=Math.round(e.visibleRooms/t),e.totalRooms=Math.round(e.totalRooms/t),e.visibleExits=Math.round(e.visibleExits/t),e.fps=Math.round(e.fps),this.callback(e),this.samples=[]}}function J(E,t){const e=parseInt(E.slice(1,3),16),i=parseInt(E.slice(3,5),16),s=parseInt(E.slice(5,7),16);return`rgba(${e}, ${i}, ${s}, ${t})`}const F=class F{};F.roomSize=Dt,F.lineWidth=It,F.lineColor=Lt,F.instantMapMove=!1,F.highlightCurrentRoom=!0,F.cullingEnabled=!0,F.cullingMode="indexed",F.cullingBounds=null,F.labelRenderMode="image",F.roomShape="rectangle",F.playerMarker={strokeColor:"#00e5b2",strokeAlpha:1,fillColor:"#00e5b2",fillAlpha:0,strokeWidth:.1,sizeFactor:1.7,dash:[.05,.05],dashEnabled:!0},F.gridEnabled=!1,F.gridSize=1,F.gridColor="rgba(255, 255, 255, 0.07)",F.gridLineWidth=.02,F.perfCallback=null;let h=F;class Nt{constructor(t,e){this.highlights=new Map,this.currentZoom=1,this.currentRoomOverlay=[],this.roomNodes=new Map,this.centerOnResize=!0,this.standaloneExitNodes=[],this.spatialBucketSize=5,this.roomSpatialIndex=new Map,this.exitSpatialIndex=new Map,this.visibleRooms=new Set,this.visibleStandaloneExitNodes=new Set,this.bufferRoomSet=new Set,this.bufferExitSet=new Set,this.bufferRoomCandidates=new Set,this.bufferExitCandidates=new Set,this.cullingScheduled=!1,this.perfMonitor=new zt,this.visibleExitDrawData=[],this.cachedGridBounds=null,this.stage=new y.Stage({container:t,width:t.clientWidth,height:t.clientHeight,draggable:!0}),window.addEventListener("resize",()=>{this.onResize(t)}),t.addEventListener("resize",()=>{this.onResize(t)}),this.gridLayer=new y.Layer({listening:!1,hitGraphEnabled:!1}),this.stage.add(this.gridLayer),this.linkLayer=new y.Layer({listening:!1,hitGraphEnabled:!1}),this.stage.add(this.linkLayer),this.roomLayer=new y.Layer({hitGraphEnabled:!1}),this.stage.add(this.roomLayer),this.positionLayer=new y.Layer({listening:!1,hitGraphEnabled:!1}),this.stage.add(this.positionLayer),this.overlayLayer=new y.Layer({listening:!1,hitGraphEnabled:!1}),this.stage.add(this.overlayLayer),this.mapReader=e,this.exitRenderer=new Ct(e,this),this.pathRenderer=new Mt(e,this.overlayLayer),this.initScaling(1.1),this.stage.on("dragmove",()=>this.scheduleRoomCulling()),this.stage.on("dragend",()=>this.scheduleRoomCulling()),this.initRoomHitDetection()}clientToMapPoint(t,e){const s=this.stage.container().getBoundingClientRect(),o=t-s.left,n=e-s.top,r=this.stage.scaleX();if(!r)return null;const a=this.stage.position();return{x:(o-a.x)/r,y:(n-a.y)/r}}findRoomAtClientPoint(t,e){const i=this.clientToMapPoint(t,e);if(!i)return null;const s=h.roomSize/2,o=this.getBucketKey(Math.floor(i.x/this.spatialBucketSize),Math.floor(i.y/this.spatialBucketSize)),n=this.roomSpatialIndex.get(o);if(!n)return null;for(const r of n){const a=i.x-r.room.x,c=i.y-r.room.y;if(a>=-s&&a<=s&&c>=-s&&c<=s)return r.room}return null}initRoomHitDetection(){const t=this.stage.container();let e=null;t.addEventListener("mousemove",a=>{const c=this.findRoomAtClientPoint(a.clientX,a.clientY);c!==e&&(e=c,t.style.cursor=c?"pointer":"auto")}),t.addEventListener("mouseleave",()=>{e=null,t.style.cursor="auto"}),t.addEventListener("contextmenu",a=>{const c=this.findRoomAtClientPoint(a.clientX,a.clientY);c&&(a.preventDefault(),this.emitRoomContextEvent(c.id,a.clientX,a.clientY))});let i,s,o;const n=()=>{o!==void 0&&(this.stage.draggable(o),o=void 0)},r=()=>{i!==void 0&&(window.clearTimeout(i),i=void 0),s=void 0,n()};t.addEventListener("touchstart",a=>{if(r(),a.touches.length>1)return;const c=a.touches[0];!c||!this.findRoomAtClientPoint(c.clientX,c.clientY)||(s={clientX:c.clientX,clientY:c.clientY},o=this.stage.draggable(),this.stage.draggable(!1),i=window.setTimeout(()=>{if(s){const d=this.findRoomAtClientPoint(s.clientX,s.clientY);d&&this.emitRoomContextEvent(d.id,s.clientX,s.clientY)}r()},500))},{passive:!0}),t.addEventListener("touchend",()=>r(),{passive:!0}),t.addEventListener("touchcancel",()=>r(),{passive:!0}),t.addEventListener("touchmove",a=>{if(!s)return;const c=a.touches[0];if(!c){r();return}const l=c.clientX-s.clientX,d=c.clientY-s.clientY;if(l*l+d*d>100){const u=o;r(),u&&this.stage.startDrag()}},{passive:!0})}onResize(t){this.stage.width(t.clientWidth),this.stage.height(t.clientHeight),this.centerOnResize&&this.currentRoomId&&this.centerOnRoom(this.mapReader.getRoom(this.currentRoomId),!1),this.stage.batchDraw(),this.scheduleRoomCulling()}initScaling(t){let e,i=!1,s=!1;this.stage.on("touchstart",o=>{const n=o.evt.touches;n&&n.length>1?(s=!0,this.stage.isDragging()&&(this.stage.stopDrag(),i=!0),this.stage.draggable(!1)):(s=!1,this.stage.draggable(!0))}),this.stage.on("touchend touchcancel",o=>{e=void 0;const n=o.evt.touches;(!n||n.length<=1)&&(s=!1,this.stage.draggable(!0))}),this.stage.on("wheel",o=>{o.evt.preventDefault();const n=this.stage.scaleX(),r=this.stage.getPointerPosition();if(!r)return;const a={x:(r.x-this.stage.x())/n,y:(r.y-this.stage.y())/n};let c=o.evt.deltaY>0?-1:1;o.evt.ctrlKey&&(c=-c);const l=c>0?this.currentZoom*t:this.currentZoom/t,d=l*K,u=this.setZoom(l),g={x:r.x-a.x*d,y:r.y-a.y*d};this.stage.position(g),this.scheduleRoomCulling(),u&&this.emitZoomChangeEvent()}),this.stage.on("touchmove",o=>{const n=o.evt.touches,r=n?.[0],a=n?.[1];if(a||s&&(s=!1,this.stage.draggable(!0)),r&&!a&&i&&!this.stage.isDragging()&&(this.stage.startDrag(),i=!1),!r||!a){e=void 0;return}o.evt.preventDefault(),this.stage.isDragging()&&(this.stage.stopDrag(),i=!0),s||(s=!0,this.stage.draggable(!1));const c=this.stage.container().getBoundingClientRect(),l={x:r.clientX-c.left,y:r.clientY-c.top},d={x:a.clientX-c.left,y:a.clientY-c.top},u=Math.hypot(l.x-d.x,l.y-d.y);if(e===void 0){e=u;return}if(e===0||u===0){e=u;return}const g=this.stage.scaleX(),f=this.stage.x(),m=this.stage.y(),p={x:this.stage.width()/2,y:this.stage.height()/2},w={x:(p.x-f)/g,y:(p.y-m)/g},R=this.currentZoom*(u/e),k=this.setZoom(R),P=this.stage.scaleX(),X={x:p.x-w.x*P,y:p.y-w.y*P};this.stage.position(X),this.stage.batchDraw(),this.scheduleRoomCulling(),e=u,k&&this.emitZoomChangeEvent()})}drawArea(t,e){const i=this.mapReader.getArea(t);if(!i)return;const s=i.getPlane(e);s&&(this.currentArea=t,this.currentAreaInstance=i,this.currentZIndex=e,this.currentAreaVersion=i.getVersion(),this.clearCurrentRoomOverlay(),this.gridLayer.destroyChildren(),this.invalidateGridCache(),this.roomLayer.destroyChildren(),this.linkLayer.destroyChildren(),this.roomNodes.clear(),this.standaloneExitNodes=[],this.standaloneExitBoundsRoomSize=void 0,this.roomSpatialIndex.clear(),this.exitSpatialIndex.clear(),this.visibleRooms.clear(),this.visibleStandaloneExitNodes.clear(),this.visibleExitDrawData.length=0,this.exitBatchShape=void 0,this.spatialBucketSize=this.computeSpatialBucketSize(),this.stage.scale({x:K*this.currentZoom,y:K*this.currentZoom}),this.renderGrid(),this.renderLabels(s.getLabels()),this.renderExits(i.getLinkExits(e)),this.renderRooms(s.getRooms()??[]),this.refreshHighlights(),this.stage.batchDraw(),this.scheduleRoomCulling())}computeSpatialBucketSize(){return Math.max(h.roomSize*10,5)}getBucketKey(t,e){return t*1000003+e}forEachBucket(t,e,i,s,o){const n=this.spatialBucketSize,r=Math.min(t,i),a=Math.max(t,i),c=Math.min(e,s),l=Math.max(e,s),d=Math.floor(r/n),u=Math.floor(a/n),g=Math.floor(c/n),f=Math.floor(l/n);for(let m=d;m<=u;m++)for(let p=g;p<=f;p++)o(this.getBucketKey(m,p))}addRoomToSpatialIndex(t){const e=h.roomSize/2,i=t.room.x-e,s=t.room.x+e,o=t.room.y-e,n=t.room.y+e;this.forEachBucket(i,o,s,n,r=>{let a=this.roomSpatialIndex.get(r);a||(a=new Set,this.roomSpatialIndex.set(r,a)),a.add(t)})}addStandaloneExitToSpatialIndex(t){const{bounds:e}=t,i=e.x,s=e.x+e.width,o=e.y,n=e.y+e.height;this.forEachBucket(i,o,s,n,r=>{let a=this.exitSpatialIndex.get(r);a||(a=new Set,this.exitSpatialIndex.set(r,a)),a.add(t)})}collectRoomCandidates(t,e,i,s){const o=this.bufferRoomCandidates;return o.clear(),this.forEachBucket(t,e,i,s,n=>{this.roomSpatialIndex.get(n)?.forEach(a=>o.add(a))}),o}collectStandaloneExitCandidates(t,e,i,s){const o=this.bufferExitCandidates;return o.clear(),this.forEachBucket(t,e,i,s,n=>{this.exitSpatialIndex.get(n)?.forEach(a=>o.add(a))}),o}refreshStandaloneExitBoundsIfNeeded(){this.standaloneExitBoundsRoomSize!==h.roomSize&&(this.exitSpatialIndex.clear(),this.standaloneExitNodes.forEach(t=>{this.addStandaloneExitToSpatialIndex(t)}),this.standaloneExitBoundsRoomSize=h.roomSize)}emitRoomContextEvent(t,e,i){const s=this.stage.container(),o=s.getBoundingClientRect(),n={roomId:t,position:{x:e-o.left,y:i-o.top}},r=new CustomEvent("roomcontextmenu",{detail:n});s.dispatchEvent(r)}emitZoomChangeEvent(){const t=new CustomEvent("zoom",{detail:{zoom:this.currentZoom}});this.stage.container().dispatchEvent(t)}setZoom(t){return this.currentZoom===t?!1:(this.currentZoom=Math.max(.1,Math.min(5,t)),this.stage.scale({x:K*this.currentZoom,y:K*this.currentZoom}),this.scheduleRoomCulling(),!0)}zoomToCenter(t){if(this.currentZoom===t)return!1;const e=this.stage.scaleX(),i=this.stage.width(),s=this.stage.height(),o=i/2,n=s/2,r={x:(o-this.stage.x())/e,y:(n-this.stage.y())/e};this.currentZoom=t;const a=K*t;this.stage.scale({x:a,y:a});const c={x:o-r.x*a,y:n-r.y*a};return this.stage.position(c),this.stage.batchDraw(),this.scheduleRoomCulling(),!0}getZoom(){return this.currentZoom}setCullingMode(t){h.cullingMode=t,h.cullingEnabled=t!=="none",this.scheduleRoomCulling()}getCullingMode(){return h.cullingMode}getCurrentArea(){return this.currentArea?this.mapReader.getArea(this.currentArea):void 0}refreshCurrentRoomOverlay(){if(this.currentRoomId!==void 0){const t=this.mapReader.getRoom(this.currentRoomId);t&&this.updateCurrentRoomOverlay(t)}}refresh(){this.currentRoomId!==void 0&&this.currentArea!==void 0&&this.currentZIndex!==void 0&&(this.drawArea(this.currentArea,this.currentZIndex),this.setPosition(this.currentRoomId))}updatePositionMarker(t){const e=this.mapReader.getRoom(t);if(!e)return;if(e.area!==this.currentArea||e.z!==this.currentZIndex){this.positionRender&&(this.positionRender.hide(),this.positionLayer.batchDraw());return}this.currentRoomId=t,this.updateCurrentRoomOverlay(e);const i=J(h.playerMarker.strokeColor,h.playerMarker.strokeAlpha),s=J(h.playerMarker.fillColor,h.playerMarker.fillAlpha),o=h.roomSize/2*h.playerMarker.sizeFactor;this.positionRender?(this.positionRender.position({x:e.x,y:e.y}),this.positionRender.radius(o),this.positionRender.stroke(i),this.positionRender.fill(s),this.positionRender.strokeWidth(h.playerMarker.strokeWidth),this.positionRender.dash(h.playerMarker.dash??[]),this.positionRender.dashEnabled(h.playerMarker.dashEnabled),this.positionRender.show()):(this.positionRender=new y.Circle({x:e.x,y:e.y,radius:o,stroke:i,fill:s,strokeWidth:h.playerMarker.strokeWidth,dash:h.playerMarker.dash,dashEnabled:h.playerMarker.dashEnabled}),this.positionLayer.add(this.positionRender)),this.positionLayer.batchDraw()}setPosition(t,e=!0){const i=this.mapReader.getRoom(t);if(!i)return;const s=this.mapReader.getArea(i.area),o=s?.getVersion();let n=this.currentArea!==i.area||this.currentZIndex!==i.z;(this.currentArea!==i.area||this.currentZIndex!==i.z||o!==void 0&&this.currentAreaVersion!==o||s!==void 0&&this.currentAreaInstance!==s)&&this.drawArea(i.area,i.z),e?this.centerOnRoom(i,n):this.currentRoomId=t,this.updateCurrentRoomOverlay(i);const r=J(h.playerMarker.strokeColor,h.playerMarker.strokeAlpha),a=J(h.playerMarker.fillColor,h.playerMarker.fillAlpha),c=h.roomSize/2*h.playerMarker.sizeFactor;this.positionRender?(this.positionRender.radius(c),this.positionRender.stroke(r),this.positionRender.fill(a),this.positionRender.strokeWidth(h.playerMarker.strokeWidth),this.positionRender.dash(h.playerMarker.dash??[]),this.positionRender.dashEnabled(h.playerMarker.dashEnabled)):(this.positionRender=new y.Circle({x:i.x,y:i.y,radius:c,stroke:r,fill:a,strokeWidth:h.playerMarker.strokeWidth,dash:h.playerMarker.dash,dashEnabled:h.playerMarker.dashEnabled}),this.positionLayer.add(this.positionRender))}centerOn(t){const e=this.mapReader.getRoom(t);if(!e)return;const i=this.mapReader.getArea(e.area),s=i?.getVersion();let o=this.currentArea!==e.area||this.currentZIndex!==e.z;(this.currentArea!==e.area||this.currentZIndex!==e.z||s!==void 0&&this.currentAreaVersion!==s||i!==void 0&&this.currentAreaInstance!==i)&&this.drawArea(e.area,e.z),this.centerOnRoomView(e,o)}renderPath(t,e){return this.pathRenderer.renderPath(t,this.currentArea,this.currentZIndex,e)}clearPaths(){this.pathRenderer.clearPaths()}renderHighlight(t,e){const i=this.mapReader.getRoom(t);if(!i)return;const s=this.highlights.get(t);s?.shape&&(s.shape.destroy(),delete s.shape);const o={color:e,area:i.area,z:i.z};if(this.highlights.set(t,o),i.area===this.currentArea&&i.z===this.currentZIndex){const n=this.createHighlightShape(i,e);return this.overlayLayer.add(n),o.shape=n,this.overlayLayer.batchDraw(),n}return o.shape}clearHighlights(){this.highlights.forEach(({shape:t})=>t?.destroy()),this.highlights.clear(),this.overlayLayer.batchDraw()}refreshHighlights(){this.highlights.forEach((t,e)=>{if(t.shape?.destroy(),delete t.shape,t.area!==this.currentArea||t.z!==this.currentZIndex)return;const i=this.mapReader.getRoom(e);if(!i)return;const s=this.createHighlightShape(i,t.color);this.overlayLayer.add(s),t.shape=s}),this.overlayLayer.batchDraw()}createHighlightShape(t,e){return h.roomShape==="circle"?new y.Circle({x:t.x,y:t.y,radius:h.roomSize/2*1.5,stroke:e,strokeWidth:.1,dash:[.05,.05],dashEnabled:!0,listening:!1}):new y.Rect({x:t.x-h.roomSize/2*1.5,y:t.y-h.roomSize/2*1.5,width:h.roomSize*1.5,height:h.roomSize*1.5,stroke:e,strokeWidth:.1,dash:[.05,.05],dashEnabled:!0,cornerRadius:h.roomShape==="roundedRectangle"?h.roomSize*1.5*.2:0,listening:!1})}centerOnRoom(t,e=!1){this.currentRoomId=t.id;const i={x:t.x,y:t.y};this.positionRender?.position(t);const o=this.stage.getAbsoluteTransform().point(i),n={x:this.stage.width()/2,y:this.stage.height()/2},r=n.x-o.x,a=n.y-o.y;this.currentTransition&&(this.currentTransition.pause(),this.currentTransition.destroy(),delete this.currentTransition),e||h.instantMapMove?(this.stage.position({x:this.stage.x()+r,y:this.stage.y()+a}),this.scheduleRoomCulling()):(this.currentTransition=new y.Tween({node:this.stage,x:this.stage.x()+r,y:this.stage.y()+a,duration:.2,easing:y.Easings.EaseInOut,onUpdate:()=>this.scheduleRoomCulling(),onFinish:()=>this.scheduleRoomCulling()}),this.currentTransition.play())}centerOnRoomView(t,e=!1){const i={x:t.x,y:t.y},o=this.stage.getAbsoluteTransform().point(i),n={x:this.stage.width()/2,y:this.stage.height()/2},r=n.x-o.x,a=n.y-o.y;this.currentTransition&&(this.currentTransition.pause(),this.currentTransition.destroy(),delete this.currentTransition),e||h.instantMapMove?(this.stage.position({x:this.stage.x()+r,y:this.stage.y()+a}),this.scheduleRoomCulling()):(this.currentTransition=new y.Tween({node:this.stage,x:this.stage.x()+r,y:this.stage.y()+a,duration:.2,easing:y.Easings.EaseInOut,onUpdate:()=>this.scheduleRoomCulling(),onFinish:()=>this.scheduleRoomCulling()}),this.currentTransition.play())}renderRooms(t){t.forEach(e=>{const i=new y.Group({x:e.x-h.roomSize/2,y:e.y-h.roomSize/2,listening:!1}),s=this.mapReader.getColorValue(e.env),o=h.lineColor,n=h.roomShape==="circle"?new y.Circle({x:h.roomSize/2,y:h.roomSize/2,radius:h.roomSize/2,fill:s,strokeWidth:h.lineWidth,stroke:o,perfectDrawEnabled:!1,listening:!1}):new y.Rect({x:0,y:0,width:h.roomSize,height:h.roomSize,fill:s,strokeWidth:h.lineWidth,stroke:o,cornerRadius:h.roomShape==="roundedRectangle"?h.roomSize*.2:0,perfectDrawEnabled:!1,listening:!1});i.add(n),this.renderSymbol(e,i),this.roomLayer.add(i),this.exitRenderer.renderSpecialExits(e).forEach(l=>{this.linkLayer.add(l)});const r=e.x-h.roomSize/2,a=e.y-h.roomSize/2;this.exitRenderer.renderStubs(e).forEach(l=>{const d=l.points();for(let u=0;u<d.length;u+=2)d[u]-=r,d[u+1]-=a;l.points(d),i.add(l)}),this.exitRenderer.renderInnerExits(e).forEach(l=>{l.position({x:-r,y:-a}),i.add(l)});const c={room:e,group:i};this.roomNodes.set(e.id,c),this.addRoomToSpatialIndex(c)})}scheduleRoomCulling(){this.cullingScheduled||(this.cullingScheduled=!0,window.requestAnimationFrame(()=>{this.cullingScheduled=!1,this.updateRoomCulling()}))}updateRoomCulling(){if(this.roomNodes.size===0&&this.standaloneExitNodes.length===0)return;const t=this.stage.scaleX();if(!t)return;this.syncPerfMonitor();const e=h.perfCallback?performance.now():0,i=this.stage.position(),s=h.roomSize/2,o=h.cullingBounds,n=o?o.x:0,r=o?o.x+o.width:this.stage.width(),a=o?o.y:0,c=o?o.y+o.height:this.stage.height(),l=Math.min(n,r),d=Math.max(n,r),u=Math.min(a,c),g=Math.max(a,c),f=(l-i.x)/t,m=(d-i.x)/t,p=(u-i.y)/t,w=(g-i.y)/t;let R=!1,k=!1;const P=h.cullingEnabled?h.cullingMode??"indexed":"none",X=f-s,Y=m+s,x=p-s,v=w+s;if(this.refreshStandaloneExitBoundsIfNeeded(),P==="none"){if(this.roomNodes.forEach(b=>{b.group.visible()||(b.group.visible(!0),R=!0)}),this.visibleExitDrawData.length!==this.standaloneExitNodes.length){this.visibleExitDrawData.length=0;for(const b of this.standaloneExitNodes)this.visibleExitDrawData.push(b.data);k=!0}R&&this.roomLayer.batchDraw(),k&&this.linkLayer.batchDraw(),this.visibleRooms.clear(),this.roomNodes.forEach(b=>this.visibleRooms.add(b)),this.visibleStandaloneExitNodes.clear(),this.standaloneExitNodes.forEach(b=>this.visibleStandaloneExitNodes.add(b));return}if(P==="basic"){const b=this.bufferRoomSet;b.clear(),this.roomNodes.forEach(N=>{const B=N.room.x-s,V=N.room.x+s,$=N.room.y-s,j=N.room.y+s,Z=V>=f&&B<=m&&j>=p&&$<=w;N.group.visible()!==Z&&(N.group.visible(Z),R=!0),Z&&b.add(N)});const L=this.bufferExitSet;L.clear();let W=!1;this.standaloneExitNodes.forEach(N=>{const{bounds:B}=N,V=B.x,$=B.x+B.width,j=B.y,Z=B.y+B.height;$>=f&&V<=m&&Z>=p&&j<=w&&(L.add(N),this.visibleStandaloneExitNodes.has(N)||(W=!0))}),!W&&L.size!==this.visibleStandaloneExitNodes.size&&(W=!0),this.bufferRoomSet=this.visibleRooms,this.visibleRooms=b,this.bufferExitSet=this.visibleStandaloneExitNodes,this.visibleStandaloneExitNodes=L,W&&(this.visibleExitDrawData.length=0,this.visibleStandaloneExitNodes.forEach(N=>this.visibleExitDrawData.push(N.data)),k=!0),R&&this.roomLayer.batchDraw(),k&&this.linkLayer.batchDraw();return}const C=this.collectRoomCandidates(X,x,Y,v),D=this.bufferRoomSet;D.clear(),C.forEach(b=>{const L=b.room.x-s,W=b.room.x+s,N=b.room.y-s,B=b.room.y+s,V=W>=f&&L<=m&&B>=p&&N<=w;b.group.visible()!==V&&(b.group.visible(V),R=!0),V&&D.add(b)}),this.visibleRooms.forEach(b=>{C.has(b)||b.group.visible()&&(b.group.visible(!1),R=!0)}),this.bufferRoomSet=this.visibleRooms,this.visibleRooms=D;const S=this.collectStandaloneExitCandidates(X,x,Y,v),M=this.bufferExitSet;M.clear();let I=!1;S.forEach(b=>{const{bounds:L}=b,W=L.x,N=L.x+L.width,B=L.y,V=L.y+L.height;N>=f&&W<=m&&V>=p&&B<=w&&(M.add(b),this.visibleStandaloneExitNodes.has(b)||(I=!0))}),!I&&M.size!==this.visibleStandaloneExitNodes.size&&(I=!0),this.bufferExitSet=this.visibleStandaloneExitNodes,this.visibleStandaloneExitNodes=M,I&&(this.visibleExitDrawData.length=0,this.visibleStandaloneExitNodes.forEach(b=>this.visibleExitDrawData.push(b.data)),k=!0),R&&this.roomLayer.batchDraw(),k&&this.linkLayer.batchDraw();const O=h.perfCallback?performance.now():0;if(this.renderGrid(),h.perfCallback){const b=performance.now()-O,L=performance.now()-e;this.perfMonitor.record({cullingMs:L,gridMs:b,visibleRooms:this.visibleRooms.size,totalRooms:this.roomNodes.size,visibleExits:this.visibleStandaloneExitNodes.size,fps:this.perfMonitor.computeFps()})}}syncPerfMonitor(){this.perfMonitor.setCallback(h.perfCallback)}invalidateGridCache(){this.cachedGridBounds=null}renderGrid(){if(!h.gridEnabled){this.cachedGridBounds!==null&&(this.gridLayer.destroyChildren(),this.gridLayer.batchDraw(),this.cachedGridBounds=null);return}const t=this.stage.scaleX();if(!t)return;const e=this.stage.position(),i=this.stage.width(),s=this.stage.height(),o=(0-e.x)/t,n=(i-e.x)/t,r=(0-e.y)/t,a=(s-e.y)/t,c=h.gridSize*2,l=Math.floor((Math.min(o,n)-c)/h.gridSize)*h.gridSize,d=Math.ceil((Math.max(o,n)+c)/h.gridSize)*h.gridSize,u=Math.floor((Math.min(r,a)-c)/h.gridSize)*h.gridSize,g=Math.ceil((Math.max(r,a)+c)/h.gridSize)*h.gridSize,f=this.cachedGridBounds;if(!(f&&f.left===l&&f.right===d&&f.top===u&&f.bottom===g)){this.gridLayer.destroyChildren();for(let m=l;m<=d;m+=h.gridSize)this.gridLayer.add(new y.Line({points:[m,u,m,g],stroke:h.gridColor,strokeWidth:h.gridLineWidth,listening:!1,perfectDrawEnabled:!1}));for(let m=u;m<=g;m+=h.gridSize)this.gridLayer.add(new y.Line({points:[l,m,d,m],stroke:h.gridColor,strokeWidth:h.gridLineWidth,listening:!1,perfectDrawEnabled:!1}));this.cachedGridBounds={left:l,right:d,top:u,bottom:g},this.gridLayer.batchDraw()}}clearCurrentRoomOverlay(){this.currentRoomOverlay.forEach(t=>t.destroy()),this.currentRoomOverlay=[],this.positionLayer.batchDraw()}updateCurrentRoomOverlay(t){if(this.clearCurrentRoomOverlay(),t.area!==this.currentArea||t.z!==this.currentZIndex){this.positionLayer.batchDraw();return}const e=new Map;e.set(t.id,t);const i=[],s=this.currentAreaInstance instanceof tt?this.currentAreaInstance:void 0;this.currentAreaInstance&&this.currentZIndex!==void 0&&this.currentAreaInstance.getLinkExits(this.currentZIndex).filter(a=>a.a===t.id||a.b===t.id).forEach(a=>{const c=h.highlightCurrentRoom?this.exitRenderer.renderWithColor(a,U,this.currentZIndex):this.exitRenderer.render(a,this.currentZIndex);c&&i.push(c)});const o=h.highlightCurrentRoom?U:void 0;this.exitRenderer.renderSpecialExits(t,o).forEach(r=>{i.push(r)}),(h.highlightCurrentRoom?this.exitRenderer.renderStubs(t,U):this.exitRenderer.renderStubs(t)).forEach(r=>{i.push(r)}),[...Object.values(t.exits),...Object.values(t.specialExits)].forEach(r=>{const a=this.mapReader.getRoom(r),c=!s||s.hasVisitedRoom(r);a&&a.area===this.currentArea&&a.z===this.currentZIndex&&c&&e.set(r,a)}),i.forEach(r=>{this.positionLayer.add(r),this.currentRoomOverlay.push(r)}),e.forEach((r,a)=>{const c=a===t.id,l=this.createOverlayRoomGroup(r,{stroke:c&&h.highlightCurrentRoom?U:h.lineColor});this.positionLayer.add(l),this.currentRoomOverlay.push(l),this.exitRenderer.renderInnerExits(r).forEach(d=>{this.positionLayer.add(d),this.currentRoomOverlay.push(d)})}),this.positionRender&&this.positionRender.moveToTop(),this.positionLayer.batchDraw()}createOverlayRoomGroup(t,e){const i=new y.Group({x:t.x-h.roomSize/2,y:t.y-h.roomSize/2,listening:!1}),s=this.mapReader.getColorValue(t.env),o=e.stroke,n=h.roomShape==="circle"?new y.Circle({x:h.roomSize/2,y:h.roomSize/2,radius:h.roomSize/2,fill:s,stroke:o,strokeWidth:h.lineWidth}):new y.Rect({x:0,y:0,width:h.roomSize,height:h.roomSize,fill:s,stroke:o,strokeWidth:h.lineWidth,cornerRadius:h.roomShape==="roundedRectangle"?h.roomSize*.2:0});return i.add(n),this.renderSymbol(t,i),i}renderSymbol(t,e){if(t.roomChar!==void 0){const i=h.roomSize*.75,s=new y.Text({x:0,y:0,text:t.roomChar,fontSize:i,fontStyle:"bold",fill:this.mapReader.getSymbolColor(t.env),align:"center",verticalAlign:"middle",width:h.roomSize,height:h.roomSize,perfectDrawEnabled:!1,listening:!1});e.add(s)}}renderExits(t){t.forEach(e=>{const i=this.exitRenderer.renderData(e,this.currentZIndex);if(!i)return;const s={data:i,bounds:i.bounds};this.standaloneExitNodes.push(s),this.addStandaloneExitToSpatialIndex(s)}),this.standaloneExitBoundsRoomSize=h.roomSize,this.exitBatchShape=new y.Shape({listening:!1,perfectDrawEnabled:!1,sceneFunc:e=>{const i=e._context;for(const s of this.visibleExitDrawData)this.drawExitData(i,s)}}),this.linkLayer.add(this.exitBatchShape)}drawExitData(t,e){for(const i of e.lines){t.beginPath(),t.moveTo(i.points[0],i.points[1]);for(let s=2;s<i.points.length;s+=2)t.lineTo(i.points[s],i.points[s+1]);t.strokeStyle=i.stroke,t.lineWidth=i.strokeWidth,i.dash?t.setLineDash(i.dash):t.setLineDash([]),t.stroke()}for(const i of e.arrows){t.beginPath(),t.moveTo(i.points[0],i.points[1]);for(let u=2;u<i.points.length;u+=2)t.lineTo(i.points[u],i.points[u+1]);t.strokeStyle=i.stroke,t.lineWidth=i.strokeWidth,i.dash?t.setLineDash(i.dash):t.setLineDash([]),t.stroke();const s=i.points.length-2,o=i.points[s],n=i.points[s+1],r=i.points[s-2],a=i.points[s-1],c=Math.atan2(n-a,o-r),l=i.pointerLength,d=i.pointerWidth/2;t.beginPath(),t.setLineDash([]),t.moveTo(o,n),t.lineTo(o-l*Math.cos(c-Math.atan2(d,l)),n-l*Math.sin(c-Math.atan2(d,l))),t.lineTo(o-l*Math.cos(c+Math.atan2(d,l)),n-l*Math.sin(c+Math.atan2(d,l))),t.closePath(),t.fillStyle=i.fill,t.fill(),t.strokeStyle=i.stroke,t.lineWidth=i.strokeWidth,t.stroke()}for(const i of e.doors)t.beginPath(),t.rect(i.x,i.y,i.width,i.height),t.strokeStyle=i.stroke,t.lineWidth=i.strokeWidth,t.setLineDash([]),t.stroke()}renderLabels(t){t.forEach(e=>{if(h.labelRenderMode==="image"){if(!e.pixMap)return;const i=new Image;i.src=`data:image/png;base64,${e.pixMap}`;const s=new y.Image({x:e.X,y:-e.Y,width:e.Width,height:e.Height,image:i,listening:!1});this.linkLayer.add(s);return}this.renderLabelAsData(e)})}renderLabelAsData(t){const e=new y.Group({listening:!1}),i=new y.Rect({x:t.X,y:-t.Y,width:t.Width,height:t.Height,listening:!1});(t.BgColor?.alpha??0)>0&&!h.transparentLabels?i.fill(this.getLabelColor(t.BgColor)):i.fillEnabled(!1),e.add(i);const s=Math.min(.75,t.Width/Math.max(t.Text.length/2,1)),o=Math.max(.1,Math.min(s,Math.max(t.Height*.9,.1))),n=new y.Text({x:t.X,y:-t.Y,width:t.Width,height:t.Height,text:t.Text,fontSize:o,fillEnabled:!0,fill:this.getLabelColor(t.FgColor),align:"center",verticalAlign:"middle",listening:!1});e.add(n),this.linkLayer.add(e)}getLabelColor(t){const e=(t?.alpha??255)/255,i=s=>Math.min(255,Math.max(0,s??0));return`rgba(${i(t?.r)}, ${i(t?.g)}, ${i(t?.b)}, ${e})`}}const ft={rgbValue:"rgb(114, 1, 0)",symbolColor:[225,225,225]};function gt(E){const t=E[0]/255,e=E[1]/255,i=E[2]/255,s=Math.max(t,e,i),o=Math.min(t,e,i);return(s+o)/2}class Pt{constructor(t,e){this.rooms={},this.areas={},this.areaSources={},this.explorationEnabled=!1,this.colors={},t.forEach(i=>{i.rooms.forEach(o=>{o.y=-o.y,this.rooms[o.id]=o});const s=parseInt(i.areaId);this.areas[s]=new _(i),this.areaSources[s]=i}),this.colors=e.reduce((i,s)=>({...i,[s.envId]:{rgb:s.colors,rgbValue:`rgb(${s.colors.join(",")})`,symbolColor:gt(s.colors)>.41?[25,25,25]:[225,255,255],symbolColorValue:gt(s.colors)>.41?"rgb(25,25,25)":"rgb(225,255,255)"}}),{})}getArea(t){return this.areas[t]}getExplorationArea(t){const e=this.areas[t];if(e instanceof tt)return e}getAreas(){return Object.values(this.areas)}getRooms(){return Object.values(this.rooms)}getRoom(t){return this.rooms[t]}ensureVisitedRooms(){return this.visitedRooms||(this.visitedRooms=new Set),this.visitedRooms}applyExplorationDecoration(){this.visitedRooms&&Object.entries(this.areaSources).forEach(([t,e])=>{const i=parseInt(t,10);this.areas[i]=new tt(e,this.visitedRooms)})}decorateWithExploration(t){return t!==void 0?this.setVisitedRooms(t):this.ensureVisitedRooms(),this.applyExplorationDecoration(),this.explorationEnabled=!0,this.visitedRooms}getVisitedRooms(){return this.visitedRooms}clearExplorationDecoration(){Object.entries(this.areaSources).forEach(([t,e])=>{const i=parseInt(t,10);this.areas[i]=new _(e)}),this.explorationEnabled=!1}isExplorationEnabled(){return this.explorationEnabled}setVisitedRooms(t){return this.visitedRooms=t instanceof Set?t:new Set(t),this.explorationEnabled&&this.applyExplorationDecoration(),this.visitedRooms}addVisitedRoom(t){if(this.explorationEnabled){const s=this.getRoom(t);if(s){const o=this.getExplorationArea(s.area);if(o)return o.addVisitedRoom(t)}}const e=this.ensureVisitedRooms(),i=e.has(t);return e.add(t),!i}addVisitedRooms(t){const e=this.ensureVisitedRooms();let i=0;for(const s of t){if(this.explorationEnabled){const n=this.getRoom(s);if(n){const r=this.getExplorationArea(n.area);if(r){r.addVisitedRoom(s)&&i++;continue}}}const o=e.has(s);e.add(s),o||i++}return i}hasVisitedRoom(t){return this.visitedRooms?.has(t)??!1}getColorValue(t){return this.colors[t]?.rgbValue??ft.rgbValue}getSymbolColor(t,e){const i=this.colors[t]?.symbolColor??ft.symbolColor,s=Math.min(Math.max(e??1,0),1),o=i.join(",");return s!=1?`rgba(${o}, ${s})`:`rgba(${o})`}}function Xt(E){return E&&E.__esModule&&Object.prototype.hasOwnProperty.call(E,"default")?E.default:E}var ot,mt;function At(){if(mt)return ot;mt=1;class E{constructor(){this.keys=new Set,this.queue=[]}sort(){this.queue.sort((e,i)=>e.priority-i.priority)}set(e,i){const s=Number(i);if(isNaN(s))throw new TypeError('"priority" must be a number');return this.keys.has(e)?this.queue.map(o=>(o.key===e&&Object.assign(o,{priority:s}),o)):(this.keys.add(e),this.queue.push({key:e,priority:s})),this.sort(),this.queue.length}next(){const e=this.queue.shift();return this.keys.delete(e.key),e}isEmpty(){return this.queue.length===0}has(e){return this.keys.has(e)}get(e){return this.queue.find(i=>i.key===e)}}return ot=E,ot}var nt,pt;function Yt(){if(pt)return nt;pt=1;function E(t,e){const i=new Map;for(const[s,o]of t)s!==e&&o instanceof Map?i.set(s,E(o,e)):s!==e&&i.set(s,o);return i}return nt=E,nt}var rt,yt;function Ot(){if(yt)return rt;yt=1;function E(e){const i=Number(e);return!(isNaN(i)||i<=0)}function t(e){const i=new Map;return Object.keys(e).forEach(o=>{const n=e[o];if(n!==null&&typeof n=="object"&&!Array.isArray(n))return i.set(o,t(n));if(!E(n))throw new Error(`Could not add node at key "${o}", make sure it's a valid node`,n);return i.set(o,Number(n))}),i}return rt=t,rt}var at,xt;function Wt(){if(xt)return at;xt=1;function E(t){if(!(t instanceof Map))throw new Error(`Invalid graph: Expected Map instead found ${typeof t}`);t.forEach((e,i)=>{if(typeof e=="object"&&e instanceof Map){E(e);return}if(typeof e!="number"||e<=0)throw new Error(`Values must be numbers greater than 0. Found value ${e} at ${i}`)})}return at=E,at}var ht,bt;function Tt(){if(bt)return ht;bt=1;const E=At(),t=Yt(),e=Ot(),i=Wt();class s{constructor(n){n instanceof Map?(i(n),this.graph=n):n?this.graph=e(n):this.graph=new Map}addNode(n,r){let a;return r instanceof Map?(i(r),a=r):a=e(r),this.graph.set(n,a),this}addVertex(n,r){return this.addNode(n,r)}removeNode(n){return this.graph=t(this.graph,n),this}path(n,r,a={}){if(!this.graph.size)return a.cost?{path:null,cost:0}:null;const c=new Set,l=new E,d=new Map;let u=[],g=0,f=[];if(a.avoid&&(f=[].concat(a.avoid)),f.includes(n))throw new Error(`Starting node (${n}) cannot be avoided`);if(f.includes(r))throw new Error(`Ending node (${r}) cannot be avoided`);for(l.set(n,0);!l.isEmpty();){const m=l.next();if(m.key===r){g=m.priority;let w=m.key;for(;d.has(w);)u.push(w),w=d.get(w);break}c.add(m.key),(this.graph.get(m.key)||new Map).forEach((w,R)=>{if(c.has(R)||f.includes(R))return null;if(!l.has(R))return d.set(R,m.key),l.set(R,m.priority+w);const k=l.get(R).priority,P=m.priority+w;return P<k?(d.set(R,m.key),l.set(R,P)):null})}return u.length?(a.trim?u.shift():u=u.concat([n]),a.reverse||(u=u.reverse()),a.cost?{path:u,cost:g}:u):a.cost?{path:null,cost:0}:null}shortestPath(...n){return this.path(...n)}}return ht=s,ht}var Vt=Tt();const Ft=Xt(Vt),Bt={1:"north",2:"northeast",3:"northwest",4:"east",5:"west",6:"south",7:"southeast",8:"southwest",9:"up",10:"down",11:"in",12:"out"};class Zt{constructor(t){this.cache=new Map,this.mapReader=t,this.graph=this.buildGraph()}buildGraph(){const t={};return this.mapReader.getRooms().forEach(e=>{const i={},s=new Set((e.exitLocks??[]).map(n=>Bt[n]).filter(n=>!!n)),o=new Set(e.mSpecialExitLocks??[]);Object.entries(e.exits??{}).forEach(([n,r])=>{s.has(n)||this.mapReader.getRoom(r)&&(i[r.toString()]=1)}),Object.values(e.specialExits??{}).forEach(n=>{o.has(n)||this.mapReader.getRoom(n)&&(i[n.toString()]=1)}),t[e.id.toString()]=i}),new Ft(t)}findPath(t,e){const i=`${t}->${e}`;if(this.cache.has(i))return this.cache.get(i);if(t===e){const r=this.mapReader.getRoom(t)?[t]:null;return this.cache.set(i,r),r}if(!this.mapReader.getRoom(t)||!this.mapReader.getRoom(e))return this.cache.set(i,null),null;const s=this.graph.path(t.toString(),e.toString()),o=Array.isArray(s)?s:s?.path,n=o?o.map(r=>Number(r)):null;return this.cache.set(i,n),n}}const Gt={1:"north",2:"northeast",3:"northwest",4:"east",5:"west",6:"south",7:"southeast",8:"southwest",9:"up",10:"down",11:"in",12:"out"},G=class G{};G.areaWidth=150,G.areaHeight=80,G.areaSpacing=50,G.fontSize=14,G.connectionLineWidth=2,G.areaFillColor="#2a2a3e",G.areaStrokeColor="#4a4a6e",G.textColor="#e0e0e0",G.connectionColor="#6a6a8e",G.highlightColor="#ff9900";let z=G;class $t{constructor(t,e){this.areaNodes=new Map,this.connectionGroups=[],this.currentZoom=1,this.domainInfo=new Map,this.domainFilter="all",this.dotsMode=!1,this.stage=new y.Stage({container:t,width:t.clientWidth,height:t.clientHeight,draggable:!0}),this.backgroundLayer=new y.Layer({listening:!1}),this.stage.add(this.backgroundLayer),this.connectionLayer=new y.Layer({listening:!1}),this.stage.add(this.connectionLayer),this.areaLayer=new y.Layer,this.stage.add(this.areaLayer),this.mapReader=e,this.initScaling(),this.initResize(t)}initResize(t){new ResizeObserver(()=>{this.stage.width(t.clientWidth),this.stage.height(t.clientHeight),this.stage.batchDraw()}).observe(t)}initScaling(){this.stage.on("wheel",e=>{e.evt.preventDefault();const i=this.stage.scaleX(),s=this.stage.getPointerPosition();if(!s)return;const o={x:(s.x-this.stage.x())/i,y:(s.y-this.stage.y())/i},r=(e.evt.deltaY>0?-1:1)>0?this.currentZoom*1.1:this.currentZoom/1.1;this.setZoom(r);const a=this.stage.scaleX(),c={x:s.x-o.x*a,y:s.y-o.y*a};this.stage.position(c),this.stage.batchDraw()})}setZoom(t){this.currentZoom=Math.max(.1,Math.min(5,t)),this.stage.scale({x:this.currentZoom,y:this.currentZoom})}getZoom(){return this.currentZoom}setDomainInfo(t){this.domainInfo.clear();for(const[e,i]of Object.entries(t))this.domainInfo.set(Number(e),i)}setDomainFilter(t){this.domainFilter=t}getDomainFilter(){return this.domainFilter}setBackgroundImage(t){this.backgroundConfig={url:t.url,x:t.x,y:t.y,width:t.width,height:t.height,opacity:t.opacity??.3}}clearBackgroundImage(){this.backgroundConfig=void 0,this.backgroundImage=void 0,this.backgroundLayer.destroyChildren(),this.backgroundLayer.batchDraw()}redrawBackground(){this.drawBackground()}setDotsMode(t){this.dotsMode=t}getDotsMode(){return this.dotsMode}redraw(){this.drawBackground(),this.drawConnections(),this.drawAreas(),this.stage.batchDraw()}isAreaInDomain(t){const e=this.domainInfo.get(t);if(!e)return this.domainFilter==="interdomain"||this.domainFilter==="all";switch(this.domainFilter){case"ishtar":return e.isIshtar;case"empire":return e.isEmpire;case"interdomain":return!e.isIshtar&&!e.isEmpire;case"all":return!0}}areAreasInSameDomain(t,e){const i=this.domainInfo.get(t),s=this.domainInfo.get(e);return!i||!s?!1:!!(i.isIshtar&&s.isIshtar||i.isEmpire&&s.isEmpire||!i.isIshtar&&!i.isEmpire&&!s.isIshtar&&!s.isEmpire)}render(){this.analyzeConnections(),this.layoutAreas(),this.drawBackground(),this.drawConnections(),this.drawAreas(),this.centerView(),this.stage.batchDraw()}drawBackground(){if(this.backgroundLayer.destroyChildren(),!this.backgroundConfig)return;const t=new Image;t.crossOrigin="anonymous",t.onload=()=>{this.backgroundImage=new y.Image({x:this.backgroundConfig.x,y:this.backgroundConfig.y,image:t,width:this.backgroundConfig.width,height:this.backgroundConfig.height,opacity:this.backgroundConfig.opacity,listening:!1}),this.backgroundLayer.add(this.backgroundImage),this.backgroundLayer.batchDraw()},t.onerror=()=>{console.error("Failed to load background image:",this.backgroundConfig?.url)},t.src=this.backgroundConfig.url}analyzeConnections(){this.areaNodes.clear(),this.connectionGroups=[];const t=this.mapReader.getRooms(),e=this.mapReader.getAreas(),i=new Map;for(const c of e){const l=c.getAreaId(),d=c.getRooms();if(d.length===0)continue;let u=1/0,g=-1/0,f=1/0,m=-1/0,p=0;for(const k of d)k.z===0&&(p++,u=Math.min(u,k.x),g=Math.max(g,k.x),f=Math.min(f,k.y),m=Math.max(m,k.y));if(p===0)for(const k of d)u=Math.min(u,k.x),g=Math.max(g,k.x),f=Math.min(f,k.y),m=Math.max(m,k.y);const w=(u+g)/2,R=(f+m)/2;i.set(l,{minX:u,maxX:g,minY:f,maxY:m,centerX:w,centerY:R,roomCount:d.length})}let s=1;for(const c of i.values()){const l=c.maxX-c.minX,d=c.maxY-c.minY;s=Math.max(s,l,d)}const o=200,n=100,r=o/s;for(const c of e){const l=c.getAreaId(),d=i.get(l);if(!d||!this.isAreaInDomain(l))continue;const u=d.maxX-d.minX,g=d.maxY-d.minY;let f=Math.max(n,u*r),m=Math.max(n,g*r);const p=f/m;p>3?m=f/3:p<1/3&&(f=m/3),this.areaNodes.set(l,{areaId:l,name:c.getAreaName(),x:0,y:0,width:f,height:m,connections:[],roomCount:d.roomCount,realCenterX:d.centerX,realCenterY:d.centerY})}const a=new Map;for(const c of t){const l=c.area;if(!this.areaNodes.has(l))continue;const d=this.getLockedDirections(c),u=new Set(c.mSpecialExitLocks??[]);for(const[g,f]of Object.entries(c.exits??{})){if(d.has(g))continue;const m=this.mapReader.getRoom(f);if(!m||m.area===l||!this.areaNodes.has(m.area)||!this.areAreasInSameDomain(l,m.area))continue;const p=this.createConnection(c,m,g);p&&this.addConnection(a,p)}for(const[g,f]of Object.entries(c.specialExits??{})){if(u.has(f))continue;const m=this.mapReader.getRoom(f);if(!m||m.area===l||!this.areaNodes.has(m.area)||!this.areAreasInSameDomain(l,m.area))continue;const p=this.parseDirection(g),w=this.createConnection(c,m,p);w&&this.addConnection(a,w)}}for(const[c,l]of a){const[d,u]=c.split("-").map(Number),g=this.createConnectionGroup(d,u,l);this.connectionGroups.push(g);const f=this.areaNodes.get(d),m=this.areaNodes.get(u);if(f&&f.connections.push(...l),m)for(const p of l)m.connections.push({...p,fromAreaId:p.toAreaId,toAreaId:p.fromAreaId,fromRoomId:p.toRoomId,toRoomId:p.fromRoomId,direction:p.direction?wt[p.direction]:null,fromRoomPosition:p.toRoomPosition,toRoomPosition:p.fromRoomPosition})}}getLockedDirections(t){return new Set((t.exitLocks??[]).map(e=>Gt[e]).filter(e=>!!e))}createConnection(t,e,i){const s=this.toPlanarDirection(i);return{fromAreaId:t.area,toAreaId:e.area,fromRoomId:t.id,toRoomId:e.id,direction:s,fromRoomPosition:{x:t.x,y:t.y},toRoomPosition:{x:e.x,y:e.y}}}addConnection(t,e){const i=e.fromAreaId<e.toAreaId?`${e.fromAreaId}-${e.toAreaId}`:`${e.toAreaId}-${e.fromAreaId}`;t.has(i)||t.set(i,[]),t.get(i).push(e)}createConnectionGroup(t,e,i){const s=new Map;let o=0,n=0;for(const c of i)c.direction&&s.set(c.direction,(s.get(c.direction)??0)+1),o+=c.toRoomPosition.x-c.fromRoomPosition.x,n+=c.toRoomPosition.y-c.fromRoomPosition.y;let r=null,a=0;for(const[c,l]of s)l>a&&(a=l,r=c);return{fromAreaId:t,toAreaId:e,connections:i,primaryDirection:r,averageOffset:{x:o/i.length,y:n/i.length}}}parseDirection(t){const e=t.toLowerCase().trim();return{n:"north",north:"north",s:"south",south:"south",e:"east",east:"east",w:"west",west:"west",ne:"northeast",northeast:"northeast",nw:"northwest",northwest:"northwest",se:"southeast",southeast:"southeast",sw:"southwest",southwest:"southwest",u:"up",up:"up",d:"down",down:"down",i:"in",in:"in",o:"out",out:"out"}[e]??null}toPlanarDirection(t){return t&&ct.includes(t)?t:null}layoutAreas(){if(Array.from(this.areaNodes.values()).length===0)return;const e=this.findConnectedComponents();let i=0;const s=z.areaWidth*3;for(const o of e)if(o.length===1){const n=this.areaNodes.get(o[0]);n&&(n.x=i,n.y=0),i+=z.areaWidth+s}else{const n=this.forceDirectedLayout(o);for(const a of o){const c=this.areaNodes.get(a);c&&isFinite(n.minX)&&isFinite(n.minY)&&(c.x-=n.minX,c.x+=i,c.y-=n.minY)}const r=isFinite(n.maxX-n.minX)?n.maxX-n.minX:z.areaWidth;i+=r+s}}findConnectedComponents(){const t=new Set,e=[];for(const[i]of this.areaNodes){if(t.has(i))continue;const s=[],o=[i];for(;o.length>0;){const n=o.shift();if(t.has(n))continue;t.add(n),s.push(n);const r=this.areaNodes.get(n);if(r)for(const a of r.connections)t.has(a.toAreaId)||o.push(a.toAreaId)}e.push(s)}return e}forceDirectedLayout(t){const e=new Map;for(const x of t){const v=this.areaNodes.get(x);if(!v)continue;const C=new Set(v.connections.map(D=>D.toAreaId));e.set(x,C)}const i=new Set,s=new Set;for(const[x,v]of e)v.size>=3&&i.add(x);for(const[x,v]of e){if(i.has(x)||s.has(x)||v.size>2)continue;const C=[x];s.add(x);const D=Array.from(v);for(const M of D){let I=M,O=x;for(;I&&!s.has(I)&&!i.has(I);){const b=e.get(I);if(!b)break;if(b.size>=3){i.add(I);break}C.push(I),s.add(I);let L=!1;for(const W of b)if(W!==O&&!s.has(W)){O=I,I=W,L=!0;break}if(!L)break}}let S=!1;for(const M of C){const I=e.get(M);if(I){for(const O of I)if(i.has(O)){S=!0;break}}if(S)break}if(!S&&C.length>0){let M=C[0],I=e.get(C[0])?.size??0;for(const O of C){const b=e.get(O)?.size??0;b>I&&(I=b,M=O)}i.add(M),s.delete(M)}}for(const x of t){const v=e.get(x);(!v||v.size===0)&&i.add(x)}const o=new Map,n=new Map;for(const x of i)o.set(x,x),n.set(x,[]);const r=new Set(i);for(const x of i){const v=e.get(x)??new Set;for(const C of v){if(r.has(C))continue;const D=[];let S=C,M=x;for(;S&&!r.has(S);){D.push(S),o.set(S,x),r.add(S);const I=e.get(S)??new Set;let O;for(const b of I)if(b!==M&&!r.has(b)){O=b;break}M=S,S=O}D.length>0&&n.get(x).push(D)}}const a=new Set,c=[],l=i.values().next().value,d=l!==void 0?l:t[0];if(d!==void 0){const x=this.areaNodes.get(d);x&&(x.x=0,x.y=0,a.add(d),c.push(d))}for(;c.length>0;){const x=c.shift(),v=this.areaNodes.get(x),C=new Map;for(const D of v.connections){const S=D.toAreaId;if(a.has(S)||!i.has(S))continue;const M=this.areaNodes.get(S);if(!M)continue;const I=D.direction??"none";C.has(I)||C.set(I,[]),C.get(I).push({id:S,node:M,conn:D})}for(const[D,S]of C){const M=this.getDirectionOffset(D==="none"?null:D);S.sort((b,L)=>Math.abs(M.x)>Math.abs(M.y)?L.node.realCenterY-b.node.realCenterY:b.node.realCenterX-L.node.realCenterX);const I=z.areaWidth+z.areaSpacing,O=z.areaHeight+z.areaSpacing;S.forEach((b,L)=>{if(b.node.x=v.x+M.x*I,b.node.y=v.y+M.y*O,S.length>1){const W=(L-(S.length-1)/2)*.5;Math.abs(M.x)>Math.abs(M.y)?b.node.y+=W*O:b.node.x+=W*I}a.add(b.id),c.push(b.id)})}}const u=Array.from(i);u.length>1&&this.applyForces(u,80);const g=z.areaWidth+z.areaSpacing+30,f=z.areaHeight+z.areaSpacing+30,m=new Map,p=["east","west","north","south","northeast","northwest","southeast","southwest"];for(const[x,v]of n){const C=this.areaNodes.get(x);if(!C)continue;let D=0;const S=new Map;for(const M of v){let I=x,O=C.x,b=C.y,L=null;for(const W of M){const N=this.areaNodes.get(W);if(!N)continue;const B=this.areaNodes.get(I);let V=null;if(B){for(const Z of B.connections)if(Z.toAreaId===W){V=Z.direction;break}}!V&&I===x?(L=p[D%p.length],D++,V=L):!V&&L&&(V=L);const $=this.getDirectionOffset(V);let j=0;if(I===x&&V){const Z=V,st=S.get(Z)??0;S.set(Z,st+1),j=st}N.x=O+$.x*g,N.y=b+$.y*f,j>0&&($.x!==0&&$.y===0?N.y+=j*f*1.2:$.y!==0&&$.x===0?N.x+=j*g*1.2:(N.x+=j*g*1.2,N.y-=j*f*1.2)),m.set(W,{dx:N.x-C.x,dy:N.y-C.y,hubId:x}),I=W,O=N.x,b=N.y}}}const w=new Map,R=new Map;for(const x of i){const v=this.areaNodes.get(x);if(!v)continue;let C=v.x,D=v.y,S=v.x+v.width,M=v.y+v.height;const I=n.get(x)??[];for(const O of I)for(const b of O){const L=this.areaNodes.get(b);L&&(C=Math.min(C,L.x),D=Math.min(D,L.y),S=Math.max(S,L.x+L.width),M=Math.max(M,L.y+L.height))}w.set(x,{minX:C,minY:D,maxX:S,maxY:M}),R.set(x,{dx:C-v.x,dy:D-v.y})}this.applyClusterForces(u,w,R,60);for(const[x,v]of m){const C=this.areaNodes.get(x),D=this.areaNodes.get(v.hubId);!C||!D||(C.x=D.x+v.dx,C.y=D.y+v.dy)}let k=1/0,P=1/0,X=-1/0,Y=-1/0;for(const x of t){const v=this.areaNodes.get(x);k=Math.min(k,v.x),P=Math.min(P,v.y),X=Math.max(X,v.x+v.width),Y=Math.max(Y,v.y+v.height)}return{minX:k,minY:P,maxX:X,maxY:Y}}getDirectionOffset(t){const e={north:{x:0,y:-1},south:{x:0,y:1},east:{x:1,y:0},west:{x:-1,y:0},northeast:{x:.75,y:-.75},northwest:{x:-.75,y:-.75},southeast:{x:.75,y:.75},southwest:{x:-.75,y:.75}};return t&&e[t]?e[t]:{x:1,y:0}}applyClusterForces(t,e,i,s){const r=new Map;for(const a of t)r.set(a,{vx:0,vy:0});for(let a=0;a<s;a++){for(const c of t){const l=this.areaNodes.get(c),d=e.get(c),u=i.get(c);if(!l||!d||!u)continue;const g=d.maxX-d.minX,f=d.maxY-d.minY;d.minX=l.x+u.dx,d.minY=l.y+u.dy,d.maxX=d.minX+g,d.maxY=d.minY+f}for(const c of t){const l=this.areaNodes.get(c),d=r.get(c),u=e.get(c);if(!(!l||!d||!u)){for(const g of t){if(c===g)continue;const f=e.get(g);if(!f)continue;const m=(u.minX+u.maxX)/2,p=(u.minY+u.maxY)/2,w=(f.minX+f.maxX)/2,R=(f.minY+f.maxY)/2,k=m-w,P=p-R,X=(u.maxX-u.minX)/2,Y=(u.maxY-u.minY)/2,x=(f.maxX-f.minX)/2,v=(f.maxY-f.minY)/2,C=X+x+50,D=Y+v+50,S=C-Math.abs(k),M=D-Math.abs(P);if(S>0&&M>0)if(S<M){const I=S*(k>=0?1:-1)*.5;d.vx+=I}else{const I=M*(P>=0?1:-1)*.5;d.vy+=I}}for(const g of l.connections){const f=this.areaNodes.get(g.toAreaId);if(!f||!t.includes(g.toAreaId))continue;const m=f.x-l.x,p=f.y-l.y,w=Math.sqrt(m*m+p*p)||1,R=z.areaWidth+z.areaSpacing+50,P=(w-R)*.015;d.vx+=m/w*P,d.vy+=p/w*P}}}for(const c of t){const l=this.areaNodes.get(c),d=r.get(c);!l||!d||(l.x+=d.vx,l.y+=d.vy,d.vx*=.8,d.vy*=.8)}}}applyForces(t,e){const o=z.areaWidth+z.areaSpacing,n=z.areaWidth/2+60,r=new Set(t),a=[],c=new Set;for(const d of t){const u=this.areaNodes.get(d);if(u)for(const g of u.connections){if(!r.has(g.toAreaId))continue;const f=Math.min(d,g.toAreaId)+"-"+Math.max(d,g.toAreaId);c.has(f)||(c.add(f),a.push({from:d,to:g.toAreaId}))}}const l=new Map;for(const d of t)l.set(d,{vx:0,vy:0});for(let d=0;d<e;d++){for(const u of t){const g=this.areaNodes.get(u),f=l.get(u);if(!g||!f)continue;const m=g.x+g.width/2,p=g.y+g.height/2;for(const w of t){if(u===w)continue;const R=this.areaNodes.get(w);if(!R)continue;const k=(g.width+R.width)/2+20,P=(g.height+R.height)/2+20,X=g.x+g.width/2,Y=g.y+g.height/2,x=R.x+R.width/2,v=R.y+R.height/2,C=X-x,D=Y-v,S=k-Math.abs(C),M=P-Math.abs(D);S>0&&M>0&&(S<M?f.vx+=(C>=0?1:-1)*S*.5:f.vy+=(D>=0?1:-1)*M*.5)}for(const w of a){if(w.from===u||w.to===u)continue;const R=this.areaNodes.get(w.from),k=this.areaNodes.get(w.to);if(!R||!k)continue;const P=R.x+R.width/2,X=R.y+R.height/2,Y=k.x+k.width/2,x=k.y+k.height/2,v=this.closestPointOnSegment(m,p,P,X,Y,x),C=m-v.x,D=p-v.y,S=Math.sqrt(C*C+D*D)||1;if(S<n){const M=(n-S)*.6;f.vx+=C/S*M,f.vy+=D/S*M}}for(const w of g.connections){if(!r.has(w.toAreaId))continue;const R=this.areaNodes.get(w.toAreaId);if(!R)continue;const k=R.x-g.x,P=R.y-g.y,X=Math.sqrt(k*k+P*P)||1,x=(X-o)*.03;f.vx+=k/X*x,f.vy+=P/X*x;const v=this.getDirectionOffset(w.direction),C=g.x+v.x*o,D=g.y+v.y*o,S=l.get(w.toAreaId);S&&(S.vx+=(C-R.x)*.01,S.vy+=(D-R.y)*.01)}}for(const u of t){const g=this.areaNodes.get(u),f=l.get(u);!g||!f||(g.x+=f.vx,g.y+=f.vy,f.vx*=.8,f.vy*=.8)}}}closestPointOnSegment(t,e,i,s,o,n){const r=o-i,a=n-s,c=t-i,l=e-s,d=r*r+a*a;if(d===0)return{x:i,y:s};let u=(c*r+l*a)/d;return u=Math.max(0,Math.min(1,u)),{x:i+u*r,y:s+u*a}}edgesIntersect(t,e,i,s,o,n,r,a){const c=(l,d,u,g,f,m)=>(m-d)*(u-l)>(g-d)*(f-l);return c(t,e,o,n,r,a)!==c(i,s,o,n,r,a)&&c(t,e,i,s,o,n)!==c(t,e,i,s,r,a)}drawConnections(){this.connectionLayer.destroyChildren();for(const t of this.connectionGroups){const e=this.areaNodes.get(t.fromAreaId),i=this.areaNodes.get(t.toAreaId);if(!e||!i||!isFinite(e.x)||!isFinite(e.y)||!isFinite(i.x)||!isFinite(i.y))continue;const s={x:e.x+e.width/2,y:e.y+e.height/2},o={x:i.x+i.width/2,y:i.y+i.height/2};let n,r;if(this.dotsMode?(n=s,r=o):(n=this.getEdgePoint(e,o),r=this.getEdgePoint(i,s)),!isFinite(n.x)||!isFinite(n.y)||!isFinite(r.x)||!isFinite(r.y))continue;const a=this.dotsMode?"#ffffff":z.connectionColor,c=this.dotsMode?1:Math.min(z.connectionLineWidth,1+t.connections.length*.5),l=new y.Line({points:[n.x,n.y,r.x,r.y],stroke:a,strokeWidth:c,lineCap:"round",listening:!1});this.connectionLayer.add(l)}}getEdgePoint(t,e){const i=t.x+t.width/2,s=t.y+t.height/2,o=e.x-i,n=e.y-s,r=t.width/2,a=t.height/2;if(o===0&&n===0)return{x:i,y:s};const c=Math.abs(o),l=Math.abs(n);let d;return c/r>l/a?d=r/c:d=a/l,{x:i+o*d,y:s+n*d}}drawAreas(){this.areaLayer.destroyChildren();for(const[,t]of this.areaNodes){if(!isFinite(t.x)||!isFinite(t.y))continue;const e=t.areaId===this.highlightedArea;if(this.dotsMode){const s=t.x+t.width/2,o=t.y+t.height/2,n=new y.Group({x:s,y:o,draggable:!0}),r=new y.Circle({radius:6,fill:e?z.highlightColor:"#ffffff",stroke:e?z.highlightColor:"#ffffff",strokeWidth:1}),a=new y.Text({text:t.name,fontSize:10,fill:"#ffffff",x:10,y:-5});n.add(r),n.add(a),n.on("click tap",()=>{this.emitAreaClickEvent(t.areaId)}),n.on("mouseenter",()=>{this.stage.container().style.cursor="pointer",r.fill(z.highlightColor),r.stroke(z.highlightColor),this.areaLayer.batchDraw()}),n.on("mouseleave",()=>{this.stage.container().style.cursor="auto",r.fill(e?z.highlightColor:"#ffffff"),r.stroke(e?z.highlightColor:"#ffffff"),this.areaLayer.batchDraw()}),n.on("dragmove",()=>{t.x=n.x()-t.width/2,t.y=n.y()-t.height/2,this.drawConnections(),this.connectionLayer.batchDraw()}),n.on("dragstart",()=>{this.stage.container().style.cursor="grabbing"}),n.on("dragend",()=>{this.stage.container().style.cursor="pointer"}),this.areaLayer.add(n)}else{const i=new y.Group({x:t.x,y:t.y,draggable:!0}),s=new y.Rect({width:t.width,height:t.height,fill:z.areaFillColor,stroke:e?z.highlightColor:z.areaStrokeColor,strokeWidth:e?3:2,cornerRadius:8}),o=new y.Text({text:t.name,fontSize:z.fontSize,fill:z.textColor,width:t.width-10,height:t.height-20,x:5,y:10,align:"center",verticalAlign:"middle",ellipsis:!0,wrap:"word"}),n=new y.Text({text:`${t.roomCount} rooms`,fontSize:10,fill:z.connectionColor,width:t.width-10,x:5,y:t.height-18,align:"center"});i.add(s),i.add(o),i.add(n),i.on("click tap",()=>{this.emitAreaClickEvent(t.areaId)}),i.on("mouseenter",()=>{this.stage.container().style.cursor="pointer",s.stroke(z.highlightColor),this.areaLayer.batchDraw()}),i.on("mouseleave",()=>{this.stage.container().style.cursor="auto",s.stroke(e?z.highlightColor:z.areaStrokeColor),this.areaLayer.batchDraw()}),i.on("dragmove",()=>{t.x=i.x(),t.y=i.y(),this.drawConnections(),this.connectionLayer.batchDraw()}),i.on("dragstart",()=>{this.stage.container().style.cursor="grabbing"}),i.on("dragend",()=>{this.stage.container().style.cursor="pointer"}),this.areaLayer.add(i)}}}centerView(){let t=1/0,e=1/0,i=-1/0,s=-1/0;for(const[,f]of this.areaNodes)t=Math.min(t,f.x),e=Math.min(e,f.y),i=Math.max(i,f.x+f.width),s=Math.max(s,f.y+f.height);if(!isFinite(t))return;const o=i-t,n=s-e,r=t+o/2,a=e+n/2,c=50,l=(this.stage.width()-c*2)/o,d=(this.stage.height()-c*2)/n,u=Math.min(l,d,1.5);this.setZoom(u);const g=this.stage.scaleX();this.stage.position({x:this.stage.width()/2-r*g,y:this.stage.height()/2-a*g})}highlightArea(t){this.highlightedArea=t,this.drawAreas(),this.stage.batchDraw()}centerOnArea(t){const e=this.areaNodes.get(t);if(!e)return;const i=this.stage.scaleX(),s=e.x+e.width/2,o=e.y+e.height/2;this.stage.position({x:this.stage.width()/2-s*i,y:this.stage.height()/2-o*i}),this.stage.batchDraw()}emitAreaClickEvent(t){const e=new CustomEvent("areaclick",{detail:{areaId:t}});this.stage.container().dispatchEvent(e)}getAreaNode(t){return this.areaNodes.get(t)}getConnectionGroups(){return this.connectionGroups}destroy(){this.stage.destroy()}}exports.AreaMapRenderer=$t;exports.AreaMapSettings=z;exports.ExplorationArea=tt;exports.MapReader=Pt;exports.PathFinder=Zt;exports.Renderer=Nt;exports.Settings=h;
2
2
  //# sourceMappingURL=index.cjs.map