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