mudlet-map-renderer 0.26.0-konva → 0.26.1-konva

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -1,3 +1,3 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const b=require("konva"),Z=["north","south","east","west","northeast","northwest","southeast","southwest"],At={n:"north",s:"south",e:"east",w:"west",ne:"northeast",nw:"northwest",se:"southeast",sw:"southwest"},N={north:"n",south:"s",east:"e",west:"w",northeast:"ne",northwest:"nw",southeast:"se",southwest:"sw",up:"u",down:"d",in:"i",out:"o"},st={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}},ut=["north","south","east","west","northeast","northwest","southeast","southwest"],Lt={north:"south",south:"north",east:"west",west:"east",northeast:"southwest",northwest:"southeast",southeast:"northwest",southwest:"northeast"};function ft(m){return m?Object.prototype.hasOwnProperty.call(st,m):!1}function L(m,t,s,e=1){if(!ft(s))return{x:m,y:t};const i=st[s];return{x:m+i.x*e,y:t+i.y*e}}function it(m,t,s,e=1,i=0){if(!ft(s))return{x:m,y:t};const o=st[s];if(!(o.x!==0&&o.y!==0)||i<=0)return L(m,t,s,e);const r=e-i+i/Math.SQRT2;return{x:m+o.x*r,y:t+o.y*r}}function ot(m,t,s,e=1){if(!ft(s))return{x:m,y:t};const i=st[s],o=Math.atan2(i.y,i.x);return{x:m+Math.cos(o)*e,y:t+Math.sin(o)*e}}const H={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)"},Xt={1:"north",2:"northeast",3:"northwest",4:"east",5:"west",6:"south",7:"southeast",8:"southwest",9:"up",10:"down",11:"in",12:"out"},Wt=["up","down","in","out"];function xt(m){switch(m){case 1:return H.OPEN_DOOR;case 2:return H.CLOSED_DOOR;default:return H.LOCKED_DOOR}}class mt{constructor(t,s,e){this.mapReader=t,this.mapRenderer=s,this.settings=e}getRoomEdgePoint(t,s,e,i){return this.settings.roomShape==="circle"?ot(t,s,e,i):this.settings.roomShape==="roundedRectangle"?it(t,s,e,i,this.settings.roomSize*.2):L(t,s,e,i)}renderData(t,s){return this.renderDataWithColor(t,this.settings.lineColor,s)}renderDataWithColor(t,s,e){const i=t.aDir&&Z.includes(t.aDir),o=t.bDir&&Z.includes(t.bDir);if(i&&o)return this.renderTwoWayExitData(t,s,e);if(i||o){const n=i?"a":"b";return this.renderOneWayExitData(t,s,n)}}renderTwoWayExitData(t,s,e){const i=this.mapReader.getRoom(t.a),o=this.mapReader.getRoom(t.b);if(!i||!o||!t.aDir||!t.bDir||i.customLines[N[t.aDir]]&&o.customLines[N[t.bDir]]||i.z!==o.z&&(e!==o.z&&i.customLines[N[t.aDir]]||e!==i.z&&o.customLines[N[t.bDir]]))return;const n=this.getRoomEdgePoint(i.x,i.y,t.aDir,this.settings.roomSize/2),r=this.getRoomEdgePoint(o.x,o.y,t.bDir,this.settings.roomSize/2),h=[n.x,n.y,r.x,r.y],a=[{points:h,stroke:s,strokeWidth:this.settings.lineWidth}],c=[],l=i.doors[N[t.aDir]]??o.doors[N[t.bDir]];if(l){const p=h[0]+(h[2]-h[0])/2,x=h[1]+(h[3]-h[1])/2;c.push({x:p-this.settings.roomSize/4,y:x-this.settings.roomSize/4,width:this.settings.roomSize/2,height:this.settings.roomSize/2,stroke:xt(l),strokeWidth:this.settings.lineWidth})}const d=Math.min(h[0],h[2]),g=Math.max(h[0],h[2]),u=Math.min(h[1],h[3]),f=Math.max(h[1],h[3]),y=i.z!==o.z?i.z===e?o.id:i.id:void 0;return{lines:a,arrows:[],doors:c,bounds:{x:d,y:u,width:g-d,height:f-u},targetRoomId:y}}renderOneWayExitData(t,s,e){const i=e==="a"||!e&&t.aDir,o=i?this.mapReader.getRoom(t.a):this.mapReader.getRoom(t.b),n=i?this.mapReader.getRoom(t.b):this.mapReader.getRoom(t.a),r=i?t.aDir:t.bDir;if(!r||!o||!n||!Z.includes(r)||o.customLines[N[r]||r])return;if(o.area!=n.area&&r){const $=this.mapReader.getColorValue(n.env),X=this.getRoomEdgePoint(o.x,o.y,r,this.settings.roomSize/2),w=L(o.x,o.y,r,this.settings.roomSize*1.5),R=$;return{lines:[],arrows:[{points:[X.x,X.y,w.x,w.y],pointerLength:.3,pointerWidth:.3,strokeWidth:this.settings.lineWidth*1.4,stroke:R,fill:R}],doors:[],bounds:{x:Math.min(X.x,w.x),y:Math.min(X.y,w.y),width:Math.abs(w.x-X.x),height:Math.abs(w.y-X.y)},targetRoomId:n.id}}const h=n.area!==o.area||n.z!==o.z;let a={x:n.x,y:n.y};h&&(a=L(o.x,o.y,r,this.settings.roomSize/2));const c=L(o.x,o.y,r,.3),l=c.x-(c.x-a.x)/2,d=c.y-(c.y-a.y)/2,g=this.getRoomEdgePoint(o.x,o.y,r,this.settings.roomSize/2),u=[g.x,g.y,a.x,a.y],f=[g.x,a.x,l],y=[g.y,a.y,d],p=Math.min(...f),x=Math.max(...f),k=Math.min(...y),D=Math.max(...y);return{lines:[{points:u,stroke:s,strokeWidth:this.settings.lineWidth,dash:[.1,.05]}],arrows:[{points:[u[0],u[1],l,d],pointerLength:.5,pointerWidth:.35,strokeWidth:this.settings.lineWidth*1.4,stroke:s,fill:H.ONE_WAY_FILL,dash:[.1,.05]}],doors:[],bounds:{x:p,y:k,width:x-p,height:D-k},...h?{targetRoomId:n.id}:{}}}render(t,s){return this.renderWithColor(t,this.settings.lineColor,s)}renderWithColor(t,s,e){const i=t.aDir&&Z.includes(t.aDir),o=t.bDir&&Z.includes(t.bDir);if(i&&o)return this.renderTwoWayExit(t,s,e);if(i||o){const n=i?"a":"b";return this.renderOneWayExit(t,s,n)}}renderTwoWayExit(t,s,e){const i=this.mapReader.getRoom(t.a),o=this.mapReader.getRoom(t.b);if(!i||!o||!t.aDir||!t.bDir||i.customLines[N[t.aDir]]&&o.customLines[N[t.bDir]]||i.z!==o.z&&(e!==o.z&&i.customLines[N[t.aDir]]||e!==i.z&&o.customLines[N[t.bDir]]))return;const n=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(o.x,o.y,t.bDir,this.settings.roomSize/2))),i.doors[N[t.aDir]]||o.doors[N[t.bDir]]){const a=this.renderDoor(r,i.doors[N[t.aDir]]??o.doors[N[t.bDir]]);n.add(a)}const h=new b.Line({points:r,stroke:s,strokeWidth:this.settings.lineWidth,perfectDrawEnabled:!1,listening:!1});return n.add(h),n}renderOneWayExit(t,s,e){const i=e==="a"||!e&&t.aDir,o=i?this.mapReader.getRoom(t.a):this.mapReader.getRoom(t.b),n=i?this.mapReader.getRoom(t.b):this.mapReader.getRoom(t.a),r=i?t.aDir:t.bDir;if(!r||!o||!n||!Z.includes(r)||o.customLines[N[r]||r])return;if(o.area!=n.area&&r){const y=this.mapReader.getColorValue(n.env);return this.renderAreaExit(o,r,y)}let h={x:n.x,y:n.y};(n.area!==o.area||n.z!==o.z)&&(h=L(o.x,o.y,r,this.settings.roomSize/2));const a=L(o.x,o.y,r,.3),c=a.x-(a.x-h.x)/2,l=a.y-(a.y-h.y)/2,d=new b.Group({listening:!1}),g=[];g.push(...Object.values(this.getRoomEdgePoint(o.x,o.y,r,this.settings.roomSize/2))),g.push(h.x,h.y);const u=new b.Line({points:g,stroke:s,strokeWidth:this.settings.lineWidth,dashEnabled:!0,dash:[.1,.05],perfectDrawEnabled:!1,listening:!1});d.add(u);const f=new b.Arrow({points:[g[0],g[1],c,l],pointerLength:.5,pointerWidth:.35,strokeWidth:this.settings.lineWidth*1.4,stroke:s,fill:H.ONE_WAY_FILL,dashEnabled:!0,dash:[.1,.05],perfectDrawEnabled:!1,listening:!1});return d.add(f),d}renderAreaExit(t,s,e){const i=this.getRoomEdgePoint(t.x,t.y,s,this.settings.roomSize/2),o=L(t.x,t.y,s,this.settings.roomSize*1.5),n=e??this.mapReader.getColorValue(t.env);return new b.Arrow({points:[i.x,i.y,o.x,o.y],pointerLength:.3,pointerWidth:.3,strokeWidth:this.settings.lineWidth*1.4,stroke:n,fill:n,perfectDrawEnabled:!1,listening:!1})}renderSpecialExits(t,s){return Object.entries(t.customLines).flatMap(([e,i])=>{const o=[t.x,t.y];i.points.reduce((d,g)=>(d.push(g.x,-g.y),d),o);const n=i.attributes.arrow?b.Arrow:b.Line,r=s??`rgb(${i.attributes.color.r}, ${i.attributes.color.g}, ${i.attributes.color.b})`,h=new n({points:o,strokeWidth:this.settings.lineWidth,stroke:r,fill:s??`rgb(${i.attributes.color.r}, ${i.attributes.color.g} , ${i.attributes.color.b})`,pointerLength:.3,pointerWidth:.2,perfectDrawEnabled:!1,listening:!1});let a=i.attributes.style;a==="dot line"?(h.dash([.05,.05]),h.dashOffset(.1)):a==="dash line"?h.dash([.4,.2]):a==="solid line"||a!==void 0&&console.log("Brak opisu stylu: "+a);const c=[h],l=t.doors[e];return l&&o.length>=4&&c.push(this.renderDoor(o,l)),c})}getSpecialExitAreaTargets(t){const s=[];for(const[e,i]of Object.entries(t.customLines)){let o=t.specialExits[e];if(o===void 0){const d=At[e];d&&(o=t.exits[d]??t.specialExits[d])}if(o===void 0)continue;const n=this.mapReader.getRoom(o);if(!n||n.area===t.area&&n.z===t.z)continue;const r=[t.x,t.y];i.points.reduce((d,g)=>(d.push(g.x,-g.y),d),r);let h=1/0,a=1/0,c=-1/0,l=-1/0;for(let d=0;d<r.length;d+=2)h=Math.min(h,r[d]),c=Math.max(c,r[d]),a=Math.min(a,r[d+1]),l=Math.max(l,r[d+1]);s.push({bounds:{x:h,y:a,width:c-h,height:l-a},targetRoomId:o})}return s}renderStubs(t,s=this.settings.lineColor){return t.stubs.map(e=>{const i=Xt[e],o=this.getRoomEdgePoint(t.x,t.y,i,this.settings.roomSize/2),n=L(t.x,t.y,i,this.settings.roomSize/2+.5),r=[o.x,o.y,n.x,n.y];return new b.Line({points:r,stroke:s,strokeWidth:this.settings.lineWidth,perfectDrawEnabled:!1,listening:!1})})}getSymbolColor(t,s){return this.settings.frameMode?this.mapReader.getColorValue(t):this.mapReader.getSymbolColor(t,s)}renderInnerExits(t){return Wt.map(s=>{if(t.exits[s]){const e=new b.Group({listening:!1}),i=new b.RegularPolygon({x:t.x,y:t.y,sides:3,fill:this.getSymbolColor(t.env,.6),stroke:this.getSymbolColor(t.env),strokeWidth:this.settings.lineWidth,radius:this.settings.roomSize/5,scaleX:1.4,scaleY:.8,perfectDrawEnabled:!1,listening:!1});e.add(i);let o=t.doors[s];if(o!==void 0)switch(o){case 1:i.stroke(H.OPEN_DOOR);break;case 2:i.stroke(H.CLOSED_DOOR);break;default:i.stroke(H.LOCKED_DOOR)}const n=i.stroke();switch(s){case"up":i.position(L(t.x,t.y,"south",this.settings.roomSize/4));break;case"down":i.rotation(180),i.position(L(t.x,t.y,"north",this.settings.roomSize/4));break;case"in":{i.rotation(90),i.position(L(t.x,t.y,"west",this.settings.roomSize/4));const r=L(t.x,t.y,"east",this.settings.roomSize/4);e.add(new b.RegularPolygon({x:r.x,y:r.y,sides:3,fill:i.fill(),stroke:n,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(L(t.x,t.y,"west",this.settings.roomSize/4));const r=L(t.x,t.y,"east",this.settings.roomSize/4);e.add(new b.RegularPolygon({x:r.x,y:r.y,sides:3,fill:i.fill(),stroke:n,strokeWidth:this.settings.lineWidth,radius:this.settings.roomSize/5,scaleX:1.4,scaleY:.8,rotation:90,perfectDrawEnabled:!1,listening:!1}));break}}return e}}).filter(s=>s!==void 0)}renderDoor(t,s){const e={x:t[0]+(t[2]-t[0])/2,y:t[1]+(t[3]-t[1])/2};return new b.Rect({x:e.x-this.settings.roomSize/4,y:e.y-this.settings.roomSize/4,width:this.settings.roomSize/2,height:this.settings.roomSize/2,stroke:xt(s),strokeWidth:this.settings.lineWidth,perfectDrawEnabled:!1,listening:!1})}}class zt{constructor(t,s){this.rooms=[],this.labels=[],this.rooms=t,this.labels=s,this.bounds=this.createBounds()}getRooms(){return this.rooms}getLabels(){return this.labels}getBounds(){return this.bounds}createBounds(){const t=this.rooms.reduce((s,e)=>({minX:Math.min(s.minX,e.x),maxX:Math.max(s.maxX,e.x),minY:Math.min(s.minY,e.y),maxY:Math.max(s.maxY,e.y)}),{minX:Number.POSITIVE_INFINITY,maxX:Number.NEGATIVE_INFINITY,minY:Number.POSITIVE_INFINITY,maxY:Number.NEGATIVE_INFINITY});for(const s of this.labels){const e=s.X,i=-s.Y;t.minX=Math.min(t.minX,e),t.maxX=Math.max(t.maxX,e+s.Width),t.minY=Math.min(t.minY,i),t.maxY=Math.max(t.maxY,i+s.Height)}return t}}const et=class et{constructor(t){this.planes={},this.exits=new Map,this.version=0,this.area=t,this.planes=this.createPlanes(),this.createExits()}getAreaName(){return this.area.areaName}getAreaId(){return parseInt(this.area.areaId)}getVersion(){return this.version}markDirty(){this.version++}getPlane(t){return this.planes[t]}getPlanes(){return Object.values(this.planes)}getZLevels(){return Object.keys(this.planes).map(Number).sort((t,s)=>t-s)}getRooms(){return this.area.rooms}getFullBounds(){return this.getPlanes().reduce((t,s)=>{const e=s.getBounds();return{minX:Math.min(t.minX,e.minX),maxX:Math.max(t.maxX,e.maxX),minY:Math.min(t.minY,e.minY),maxY:Math.max(t.maxY,e.maxY)}},{minX:1/0,maxX:-1/0,minY:1/0,maxY:-1/0})}getLinkExits(t){return Array.from(this.exits.values()).filter(s=>s.zIndex.includes(t))}createPlanes(){const t=this.area.rooms.reduce((s,e)=>(s[e.z]||(s[e.z]=[]),s[e.z].push(e),s),{});return Object.entries(t).reduce((s,[e,i])=>(s[+e]=new zt(i,this.area.labels.filter(o=>o.Z===+e)),s),{})}createExits(){const t=new Map;this.area.rooms.forEach(s=>{Object.entries(s.exits).forEach(([e,i])=>{if(s.id===i)return;const o=Math.min(s.id,i),n=Math.max(s.id,i),r=`${o}-${n}`;t.has(r)||t.set(r,[]),t.get(r).push({origin:s.id,target:i,z:s.z,dir:e})})});for(const[s,e]of t){const[i,o]=s.split("-"),n=parseInt(i),r=parseInt(o),h=e.filter(l=>l.origin===n),a=e.filter(l=>l.origin===r),c=new Set;for(const l of h){let d=-1;for(let g=0;g<a.length;g++)if(!c.has(g)){if(a[g].dir===et.oppositeDir[l.dir]){d=g;break}d===-1&&(d=g)}if(d!==-1){c.add(d);const g=a[d];this.exits.set(`${s}-${l.dir}`,{a:n,b:r,aDir:l.dir,bDir:g.dir,zIndex:[l.z,g.z]})}else this.exits.set(`${s}-a:${l.dir}`,{a:n,b:r,aDir:l.dir,zIndex:[l.z]})}for(let l=0;l<a.length;l++)if(!c.has(l)){const d=a[l];this.exits.set(`${s}-b:${d.dir}`,{a:n,b:r,bDir:d.dir,zIndex:[d.z]})}}}};et.oppositeDir={north:"south",south:"north",east:"west",west:"east",northeast:"southwest",southwest:"northeast",northwest:"southeast",southeast:"northwest",up:"down",down:"up",in:"out",out:"in"};let _=et;class bt extends zt{constructor(t,s){super(t.getRooms(),t.getLabels()),this.basePlane=t,this.visitedRooms=s}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((s,e)=>({minX:Math.min(s.minX,e.x),maxX:Math.max(s.maxX,e.x),minY:Math.min(s.minY,e.y),maxY:Math.max(s.maxY,e.y)}),{minX:Number.POSITIVE_INFINITY,maxX:Number.NEGATIVE_INFINITY,minY:Number.POSITIVE_INFINITY,maxY:Number.NEGATIVE_INFINITY}):this.basePlane.getBounds()}}class J extends _{constructor(t,s){super(t),this.planeCache=new WeakMap,this.visitedRooms=s instanceof Set?s:new Set(s??[]),this.areaRoomIds=new Set(t.rooms.map(e=>e.id))}getPlane(t){const s=super.getPlane(t);if(!s)return s;let e=this.planeCache.get(s);return e||(e=new bt(s,this.visitedRooms),this.planeCache.set(s,e)),e}getPlanes(){return super.getPlanes().map(t=>{let s=this.planeCache.get(t);return s||(s=new bt(t,this.visitedRooms),this.planeCache.set(t,s)),s})}getLinkExits(t){return super.getLinkExits(t).filter(s=>this.visitedRooms.has(s.a)||this.visitedRooms.has(s.b))}getVisitedRoomCount(){return super.getRooms().reduce((t,s)=>t+(this.visitedRooms.has(s.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 s=this.visitedRooms.has(t);this.visitedRooms.add(t);const e=!s&&this.areaRoomIds.has(t);return e&&this.markDirty(),e}addVisitedRooms(t){let s=0;for(const e of t){const i=this.visitedRooms.has(e);this.visitedRooms.add(e),!i&&this.areaRoomIds.has(e)&&s++}return s>0&&this.markDirty(),s}}const G=["up","down","in","out"];function tt(m,t,s,e,i){return m.roomShape==="circle"?ot(t,s,e,i):m.roomShape==="roundedRectangle"?it(t,s,e,i,m.roomSize*.2):L(t,s,e,i)}function Yt(m,t,s){for(const[e,i]of Object.entries(t.exits))if(i===s.id){const o=e;if(G.includes(o)){const h=N[o],a=t.customLines[h]?h:t.customLines[o]?o:void 0;return{type:"inner",fromDir:o,customLineKey:a,fromRoom:t,toRoom:s}}const n=N[o];if(t.customLines[n])return{type:"special",fromDir:o,customLineKey:n,fromRoom:t,toRoom:s};if(t.customLines[o])return{type:"special",fromDir:o,customLineKey:o,fromRoom:t,toRoom:s};const r=Nt(s,t.id);return{type:"regular",fromDir:o,toDir:r,fromRoom:t,toRoom:s}}for(const[e,i]of Object.entries(t.specialExits))if(i===s.id)return t.customLines[e]?{type:"special",customLineKey:e,fromRoom:t,toRoom:s}:{type:"inner",fromRoom:t,toRoom:s};for(const[e,i]of Object.entries(s.exits))if(i===t.id){const o=e;if(G.includes(o)){const r=N[o],h=s.customLines[r]?r:s.customLines[o]?o:void 0;return{type:"inner",toDir:o,customLineKey:h,fromRoom:t,toRoom:s}}const n=N[o];return s.customLines[n]?{type:"special",toDir:o,customLineKey:n,fromRoom:t,toRoom:s}:s.customLines[o]?{type:"special",toDir:o,customLineKey:o,fromRoom:t,toRoom:s}:{type:"regular",toDir:o,fromRoom:t,toRoom:s}}for(const[e,i]of Object.entries(s.specialExits))if(i===t.id)return s.customLines[e]?{type:"special",customLineKey:e,fromRoom:t,toRoom:s}:{type:"inner",fromRoom:t,toRoom:s};return{type:"none",fromRoom:t,toRoom:s}}function Nt(m,t){for(const[s,e]of Object.entries(m.exits))if(e===t)return s}function wt(m,t,s){return m?m.area===t&&m.z===s:!1}function Tt(m,t){for(const[s,e]of Object.entries(m.exits))if(e===t.id)return{direction:s};for(const[s,e]of Object.entries(m.specialExits))if(e===t.id)return}function Ot(m,t){for(const s of ut)if(m.exits[s]===t.id)return s;for(const s of ut)if(t.exits[s]===m.id)return Lt[s]}function Bt(m,t,s){const{fromRoom:e,toRoom:i,fromDir:o,toDir:n}=t;if(s.length===0&&s.push(e.x,e.y),o&&Z.includes(o)){const r=tt(m,e.x,e.y,o,m.roomSize/2);s.push(r.x,r.y)}if(n&&Z.includes(n)){const r=tt(m,i.x,i.y,n,m.roomSize/2);s.push(r.x,r.y)}s.push(i.x,i.y)}function Ft(m,t){const{fromRoom:s,toRoom:e,customLineKey:i}=m;let o=s,n;i&&(n=s.customLines[i],n||(n=e.customLines[i],o=e)),t.length===0&&t.push(o.x,o.y),n&&n.points.forEach(r=>{t.push(r.x,-r.y)}),t.push(e.x,e.y)}function nt(m,t,s,e,i){const o=[],n=[],r=[],h=s.map(d=>m.getRoom(d)).filter(d=>d!==void 0);let a=[];const c=()=>{a.length>=4&&o.push({points:[...a]}),a=[]},l=d=>{const{fromRoom:g,toRoom:u,fromDir:f,toDir:y,customLineKey:p}=d;if(p){let x=g,k=g.customLines[p];if(k||(k=u.customLines[p],x=u),k){const D=[x.x,x.y];k.points.forEach($=>{D.push($.x,-$.y)}),r.push({points:D})}}f&&G.includes(f)&&n.push({room:g,direction:f}),y&&G.includes(y)&&n.push({room:u,direction:y})};for(let d=0;d<h.length-1;d++){const g=h[d],u=h[d+1],f=wt(g,e,i),y=wt(u,e,i);if(!f&&!y){c();continue}if(f&&y){const p=Yt(m,g,u);switch(p.type){case"regular":Bt(t,p,a);break;case"special":Ft(p,a);break;case"inner":c(),l(p);break;case"none":a.length===0&&a.push(g.x,g.y),a.push(u.x,u.y);break}}else{const p=f?g:u,x=f?u:g,k=Tt(p,x);if(k){if(G.includes(k.direction))c(),n.push({room:p,direction:k.direction});else if(Z.includes(k.direction)){a.length===0&&a.push(p.x,p.y);const D=tt(t,p.x,p.y,k.direction,t.roomSize/2),$=L(p.x,p.y,k.direction,t.roomSize);a.push(D.x,D.y,$.x,$.y),c()}}else{const D=Ot(p,x);if(D){a.length===0&&a.push(p.x,p.y);const $=tt(t,p.x,p.y,D,t.roomSize/2),X=L(p.x,p.y,D,t.roomSize);a.push($.x,$.y,X.x,X.y),c()}}}}return c(),{segments:o,innerMarkers:n,customLines:r}}class Vt{constructor(t,s,e){this.paths=[],this.mapReader=t,this.overlayLayer=s,this.settings=e}createStrokedLine(t,s){const e=new b.Group;return e.opacity(.8),e.add(new b.Line({points:t,stroke:"black",strokeWidth:this.settings.lineWidth*8,lineCap:"round",lineJoin:"round"})),e.add(new b.Line({points:t,stroke:s,strokeWidth:this.settings.lineWidth*4,lineCap:"round",lineJoin:"round"})),e}renderInnerExitMarker(t,s,e){const i=new b.Group;i.opacity(.8);const o=new b.RegularPolygon({x:t.x,y:t.y,sides:3,fill:e,stroke:"black",strokeWidth:this.settings.lineWidth*2,radius:this.settings.roomSize/5,scaleX:1.4,scaleY:.8});switch(s){case"up":o.position(L(t.x,t.y,"south",this.settings.roomSize/4));break;case"down":o.rotation(180),o.position(L(t.x,t.y,"north",this.settings.roomSize/4));break;case"in":{const n=o.clone();n.rotation(-90),n.position(L(t.x,t.y,"east",this.settings.roomSize/4)),i.add(n),o.rotation(90),o.position(L(t.x,t.y,"west",this.settings.roomSize/4));break}case"out":{const n=o.clone();n.rotation(90),n.position(L(t.x,t.y,"east",this.settings.roomSize/4)),i.add(n),o.rotation(-90),o.position(L(t.x,t.y,"west",this.settings.roomSize/4));break}}return i.add(o),i}renderPath(t,s,e,i="#66E64D"){if(s===void 0||e===void 0)return;const o=nt(this.mapReader,this.settings,t,s,e);for(const n of o.segments){const r=this.createStrokedLine(n.points,i);this.overlayLayer.add(r),this.paths.push(r)}for(const n of o.customLines){const r=this.createStrokedLine(n.points,i);this.overlayLayer.add(r),this.paths.push(r)}for(const n of o.innerMarkers){const r=this.renderInnerExitMarker(n.room,n.direction,i);this.overlayLayer.add(r),this.paths.push(r)}return this.paths[0]}clearPaths(){this.paths.forEach(t=>{t.destroy()}),this.paths=[]}}const Zt={1:"north",2:"northeast",3:"northwest",4:"east",5:"west",6:"south",7:"southeast",8:"southwest",9:"up",10:"down",11:"in",12:"out"},jt=["up","down","in","out"],at={OPEN:"rgb(10, 155, 10)",CLOSED:"rgb(226, 205, 59)",LOCKED:"rgb(155, 10, 10)"};function vt(m){switch(m){case 1:return at.OPEN;case 2:return at.CLOSED;default:return at.LOCKED}}function A(m){return m.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#39;")}class pt{constructor(t,s){this.mapReader=t,this.settings=s,this.exitRenderer=new mt(t,null,s)}getSymbolColor(t,s){return this.settings.frameMode?this.mapReader.getColorValue(t):this.mapReader.getSymbolColor(t,s)}export(t,s,e){const i=this.mapReader.getArea(t);if(!i)throw new Error(`Area ${t} not found`);const o=i.getPlane(s);if(!o)throw new Error(`Plane z=${s} not found in area ${t}`);const n=e?.padding??3,r=this.computeBounds(i,o,e?.roomId,n),h=[];h.push(`<svg xmlns="http://www.w3.org/2000/svg" viewBox="${r.x} ${r.y} ${r.w} ${r.h}">`),h.push(`<rect x="${r.x}" y="${r.y}" width="${r.w}" height="${r.h}" fill="${A(this.settings.backgroundColor)}"/>`),this.settings.gridEnabled&&this.renderGrid(h,r),this.renderLabels(h,o.getLabels()),this.renderLinkExits(h,i,s);const a=o.getRooms();this.renderSpecialExits(h,a),this.renderStubs(h,a),this.renderRooms(h,a),this.renderInnerExits(h,a);const c=e?.overlays;if(c){if(c.paths)for(const l of c.paths)this.renderPathOverlay(h,l.locations,l.color,t,s);if(c.highlights)for(const l of c.highlights)this.renderHighlightOverlay(h,l.roomId,l.color);c.position&&this.renderPositionMarker(h,c.position.roomId)}if(this.settings.areaName){const l=i.getAreaName();if(l){const d=this.getEffectiveBounds(i,o);h.push(`<text x="${d.minX-3.5}" y="${d.minY-2}" font-size="2.5" font-family="${A(this.settings.fontFamily)}" fill="white">${A(l)}</text>`)}}return h.push("</svg>"),h.join(`
2
- `)}computeBounds(t,s,e,i){if(e!==void 0){const g=this.mapReader.getRoom(e);if(!g)throw new Error(`Room ${e} not found`);return{x:g.x-i,y:g.y-i,w:i*2,h:i*2}}const o=this.getEffectiveBounds(t,s),n=this.settings.areaName?t.getAreaName():void 0,r=n?7:0,h=n?3.5:0,a=o.minX-h,c=o.minY-r,l=n?o.minX-3.5+n.length*2.5*.6:-1/0,d=Math.max(o.maxX,l);return{x:a-i,y:c-i,w:d-a+i*2,h:o.maxY-c+i*2}}getEffectiveBounds(t,s){return this.settings.uniformLevelSize?t.getFullBounds():s.getBounds()}getRoomEdgePoint(t,s,e,i){return this.settings.roomShape==="circle"?ot(t,s,e,i):this.settings.roomShape==="roundedRectangle"?it(t,s,e,i,this.settings.roomSize*.2):L(t,s,e,i)}renderGrid(t,s){const e=this.settings.gridSize,i=Math.floor(s.x/e)*e,o=Math.ceil((s.x+s.w)/e)*e,n=Math.floor(s.y/e)*e,r=Math.ceil((s.y+s.h)/e)*e,h=A(this.settings.gridColor),a=this.settings.gridLineWidth;for(let c=i;c<=o;c+=e)t.push(`<line x1="${c}" y1="${n}" x2="${c}" y2="${r}" stroke="${h}" stroke-width="${a}"/>`);for(let c=n;c<=r;c+=e)t.push(`<line x1="${i}" y1="${c}" x2="${o}" y2="${c}" stroke="${h}" stroke-width="${a}"/>`)}renderLabels(t,s){for(const e of s){const i=e.X,o=-e.Y;if(this.settings.labelRenderMode==="image"&&e.pixMap){t.push(`<image x="${i}" y="${o}" width="${e.Width}" height="${e.Height}" href="data:image/png;base64,${e.pixMap}"/>`);continue}if((e.BgColor?.alpha??0)>0&&!this.settings.transparentLabels){const n=this.labelColor(e.BgColor);t.push(`<rect x="${i}" y="${o}" width="${e.Width}" height="${e.Height}" fill="${n}"/>`)}if(e.Text){const n=this.labelColor(e.FgColor),r=Math.min(.75,e.Width/Math.max(e.Text.length/2,1)),h=Math.max(.1,Math.min(r,Math.max(e.Height*.9,.1)));t.push(`<text x="${i+e.Width/2}" y="${o+e.Height/2}" font-size="${h}" font-family="${A(this.settings.fontFamily)}" fill="${n}" text-anchor="middle" dominant-baseline="central">${A(e.Text)}</text>`)}}}labelColor(t){const s=(t?.alpha??255)/255,e=i=>Math.min(255,Math.max(0,i??0));return`rgba(${e(t?.r)}, ${e(t?.g)}, ${e(t?.b)}, ${s})`}renderLinkExits(t,s,e){const i=s.getLinkExits(e);for(const o of i){const n=this.exitRenderer.renderData(o,e);n&&this.renderExitData(t,n)}}renderExitData(t,s){for(const e of s.lines)this.renderSvgLine(t,e);for(const e of s.arrows)this.renderSvgArrow(t,e);for(const e of s.doors)this.renderSvgDoor(t,e)}renderSvgLine(t,s){if(s.points.length<4)return;const e=s.points.map(o=>o.toString()).join(" "),i=s.dash?` stroke-dasharray="${s.dash.join(" ")}"`:"";t.push(`<polyline points="${e}" stroke="${A(s.stroke)}" stroke-width="${s.strokeWidth}" fill="none"${i}/>`)}renderSvgArrow(t,s){if(s.points.length<4)return;const e=s.points.map(p=>p.toString()).join(" "),i=s.dash?` stroke-dasharray="${s.dash.join(" ")}"`:"";t.push(`<polyline points="${e}" stroke="${A(s.stroke)}" stroke-width="${s.strokeWidth}" fill="none"${i}/>`);const o=s.points.length-2,n=s.points[o],r=s.points[o+1],h=s.points[o-2],a=s.points[o-1],c=Math.atan2(r-a,n-h),l=s.pointerLength,d=s.pointerWidth/2,g=n-l*Math.cos(c-Math.atan2(d,l)),u=r-l*Math.sin(c-Math.atan2(d,l)),f=n-l*Math.cos(c+Math.atan2(d,l)),y=r-l*Math.sin(c+Math.atan2(d,l));t.push(`<polygon points="${n},${r} ${g},${u} ${f},${y}" fill="${A(s.fill)}" stroke="${A(s.stroke)}" stroke-width="${s.strokeWidth}"/>`)}renderSvgDoor(t,s){t.push(`<rect x="${s.x}" y="${s.y}" width="${s.width}" height="${s.height}" stroke="${A(s.stroke)}" stroke-width="${s.strokeWidth}" fill="none"/>`)}renderStubs(t,s){const e=this.settings.lineColor;for(const i of s)for(const o of i.stubs){const n=Zt[o];if(!n)continue;const r=this.getRoomEdgePoint(i.x,i.y,n,this.settings.roomSize/2),h=L(i.x,i.y,n,this.settings.roomSize/2+.5);t.push(`<line x1="${r.x}" y1="${r.y}" x2="${h.x}" y2="${h.y}" stroke="${A(e)}" stroke-width="${this.settings.lineWidth}"/>`)}}renderSpecialExits(t,s){for(const e of s)for(const[i,o]of Object.entries(e.customLines)){const n=[e.x,e.y];for(const l of o.points)n.push(l.x,-l.y);const r=`rgb(${o.attributes.color.r}, ${o.attributes.color.g}, ${o.attributes.color.b})`;let h="";o.attributes.style==="dot line"?h=' stroke-dasharray="0.05 0.05"':o.attributes.style==="dash line"&&(h=' stroke-dasharray="0.4 0.2"');const a=n.map(l=>l.toString()).join(" ");if(o.attributes.arrow&&n.length>=4){t.push(`<polyline points="${a}" stroke="${A(r)}" stroke-width="${this.settings.lineWidth}" fill="none"${h}/>`);const l=n.length-2,d=n[l],g=n[l+1],u=n[l-2],f=n[l-1],y=Math.atan2(g-f,d-u),p=.3,x=.1,k=d-p*Math.cos(y-Math.atan2(x,p)),D=g-p*Math.sin(y-Math.atan2(x,p)),$=d-p*Math.cos(y+Math.atan2(x,p)),X=g-p*Math.sin(y+Math.atan2(x,p));t.push(`<polygon points="${d},${g} ${k},${D} ${$},${X}" fill="${A(r)}" stroke="${A(r)}" stroke-width="${this.settings.lineWidth}"/>`)}else t.push(`<polyline points="${a}" stroke="${A(r)}" stroke-width="${this.settings.lineWidth}" fill="none"${h}/>`);const c=e.doors[i];if(c&&n.length>=4){const l=n[0]+(n[2]-n[0])/2,d=n[1]+(n[3]-n[1])/2,g=this.settings.roomSize/2;t.push(`<rect x="${l-g/2}" y="${d-g/2}" width="${g}" height="${g}" stroke="${vt(c)}" stroke-width="${this.settings.lineWidth}" fill="none"/>`)}}}renderRooms(t,s){const e=this.settings.roomSize,i=e/2;for(const o of s){const n=this.mapReader.getColorValue(o.env),r=this.settings.frameMode?this.settings.backgroundColor:n,h=this.settings.frameMode?n:this.settings.lineColor;if(this.settings.roomShape==="circle")t.push(`<circle cx="${o.x}" cy="${o.y}" r="${i}" fill="${A(r)}" stroke="${A(h)}" stroke-width="${this.settings.lineWidth}"/>`);else{const a=o.x-i,c=o.y-i,l=this.settings.roomShape==="roundedRectangle"?e*.2:0,d=l>0?` rx="${l}" ry="${l}"`:"";if(t.push(`<rect x="${a}" y="${c}" width="${e}" height="${e}" fill="${A(r)}" stroke="${A(h)}" stroke-width="${this.settings.lineWidth}"${d}/>`),this.settings.emboss){const g=q(this.settings.lineColor)>.41,u=g?"#000000":"#ffffff",f=g?`${a},${c} ${a+e},${c} ${a+e},${c+e}`:`${a},${c} ${a},${c+e} ${a+e},${c+e}`;t.push(`<polyline points="${f}" stroke="${u}" stroke-width="${this.settings.lineWidth}" fill="none"/>`)}}if(o.roomChar){const a=this.getSymbolColor(o.env),c=e*.75;t.push(`<text x="${o.x}" y="${o.y}" dy="0.35em" font-size="${c}" font-weight="bold" font-family="${A(this.settings.fontFamily)}" fill="${A(a)}" text-anchor="middle">${A(o.roomChar)}</text>`)}}}renderInnerExits(t,s){const e=this.settings.roomSize,i=e/5;for(const o of s)for(const n of jt){if(!o.exits[n])continue;const r=this.getSymbolColor(o.env),h=this.getSymbolColor(o.env,.6);let a;const c=o.doors[n];c!==void 0&&(a=vt(c));const l=a??r;switch(n){case"up":{const d=L(o.x,o.y,"south",e/4);t.push(this.svgTriangle(d.x,d.y,i,0,h,l));break}case"down":{const d=L(o.x,o.y,"north",e/4);t.push(this.svgTriangle(d.x,d.y,i,180,h,l));break}case"in":{const d=L(o.x,o.y,"west",e/4),g=L(o.x,o.y,"east",e/4);t.push(this.svgTriangle(d.x,d.y,i,90,h,l)),t.push(this.svgTriangle(g.x,g.y,i,-90,h,l));break}case"out":{const d=L(o.x,o.y,"west",e/4),g=L(o.x,o.y,"east",e/4);t.push(this.svgTriangle(d.x,d.y,i,-90,h,l)),t.push(this.svgTriangle(g.x,g.y,i,90,h,l));break}}}}svgTriangle(t,s,e,i,o,n){const a=i*Math.PI/180,c=[];for(let l=0;l<3;l++){const d=2*Math.PI*l/3-Math.PI/2;let g=Math.cos(d)*e*1.4,u=Math.sin(d)*e*.8;const f=g*Math.cos(a)-u*Math.sin(a),y=g*Math.sin(a)+u*Math.cos(a);c.push(`${t+f},${s+y}`)}return`<polygon points="${c.join(" ")}" fill="${A(o)}" stroke="${A(n)}" stroke-width="${this.settings.lineWidth}"/>`}renderPathOverlay(t,s,e,i,o){const n=nt(this.mapReader,this.settings,s,i,o),r=this.settings.lineWidth;for(const a of n.segments){const c=a.points.map(l=>l.toString()).join(" ");t.push(`<polyline points="${c}" stroke="black" stroke-width="${r*8}" stroke-linecap="round" stroke-linejoin="round" fill="none" opacity="0.8"/>`),t.push(`<polyline points="${c}" stroke="${A(e)}" stroke-width="${r*4}" stroke-linecap="round" stroke-linejoin="round" fill="none" opacity="0.8"/>`)}for(const a of n.customLines){const c=a.points.map(l=>l.toString()).join(" ");t.push(`<polyline points="${c}" stroke="black" stroke-width="${r*8}" stroke-linecap="round" stroke-linejoin="round" fill="none" opacity="0.8"/>`),t.push(`<polyline points="${c}" stroke="${A(e)}" stroke-width="${r*4}" stroke-linecap="round" stroke-linejoin="round" fill="none" opacity="0.8"/>`)}const h=this.settings.roomSize/5;for(const a of n.innerMarkers)t.push(this.svgTriangle(a.room.x,a.room.y,h,this.innerExitRotation(a.direction),e,"black"))}innerExitRotation(t){switch(t){case"up":return 0;case"down":return 180;case"in":return 90;case"out":return-90;default:return 0}}renderHighlightOverlay(t,s,e){const i=this.mapReader.getRoom(s);if(!i)return;const o=1.5,n=this.settings.roomSize,r="0.05 0.05";if(this.settings.roomShape==="circle")t.push(`<circle cx="${i.x}" cy="${i.y}" r="${n/2*o}" stroke="${A(e)}" stroke-width="0.1" stroke-dasharray="${r}" fill="none"/>`);else{const h=n*o;t.push(`<rect x="${i.x-h/2}" y="${i.y-h/2}" width="${h}" height="${h}" stroke="${A(e)}" stroke-width="0.1" stroke-dasharray="${r}" fill="none"/>`)}}renderPositionMarker(t,s){const e=this.mapReader.getRoom(s);if(!e)return;const i=this.settings.playerMarker,n=this.settings.roomSize*i.sizeFactor,r=i.dashEnabled&&i.dash?` stroke-dasharray="${i.dash.join(" ")}"`:"",h=i.fillAlpha>0?` fill="${i.fillColor}" fill-opacity="${i.fillAlpha}"`:' fill="none"';t.push(`<circle cx="${e.x}" cy="${e.y}" r="${n/2}" stroke="${i.strokeColor}" stroke-width="${i.strokeWidth}" stroke-opacity="${i.strokeAlpha}"${r}${h}/>`)}}const Ht=.6,j=75,Gt=.025,_t="rgb(225, 255, 225)",K="rgb(120, 72, 0)";function q(m){let t,s,e;const i=m.match(/(\d+)\s*,\s*(\d+)\s*,\s*(\d+)/);if(i)t=parseInt(i[1])/255,s=parseInt(i[2])/255,e=parseInt(i[3])/255;else if(m.startsWith("#")&&m.length>=7)t=parseInt(m.slice(1,3),16)/255,s=parseInt(m.slice(3,5),16)/255,e=parseInt(m.slice(5,7),16)/255;else return .5;return(Math.max(t,s,e)+Math.min(t,s,e))/2}class qt{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(),s=t-this.lastCullingTime;return this.lastCullingTime=t,s>0?1e3/s:0}flush(){const t=this.samples.length;if(t===0)return;const s={cullingMs:0,gridMs:0,visibleRooms:0,totalRooms:0,visibleExits:0,fps:0};for(const e of this.samples)s.cullingMs+=e.cullingMs,s.gridMs+=e.gridMs,s.visibleRooms+=e.visibleRooms,s.totalRooms+=e.totalRooms,s.visibleExits+=e.visibleExits,s.fps+=e.fps;s.cullingMs/=t,s.gridMs/=t,s.visibleRooms=Math.round(s.visibleRooms/t),s.totalRooms=Math.round(s.totalRooms/t),s.visibleExits=Math.round(s.visibleExits/t),s.fps=Math.round(s.fps),this.callback(s),this.samples=[]}}function Q(m,t){const s=parseInt(m.slice(1,3),16),e=parseInt(m.slice(3,5),16),i=parseInt(m.slice(5,7),16);return`rgba(${s}, ${e}, ${i}, ${t})`}function yt(){return{roomSize:Ht,lineWidth:Gt,lineColor:_t,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(200, 200, 200, 0.15)",gridLineWidth:.03,perfCallback:null,borders:!0,frameMode:!1,emboss:!1,areaName:!0,fontFamily:"sans-serif",uniformLevelSize:!1}}class Kt{constructor(t,s,e){this.highlights=new Map,this.currentZoom=1,this.currentRoomOverlay=[],this.roomNodes=new Map,this.centerOnResize=!0,this.minZoom=.05,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 qt,this.areaExitHitZones=[],this.visibleExitDrawData=[],this.cachedGridBounds=null,this.settings=e??yt(),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=s,this.exitRenderer=new mt(s,this,this.settings),this.pathRenderer=new Vt(s,this.overlayLayer,this.settings),this.initScaling(1.1),this.stage.on("dragmove",()=>{this.scheduleRoomCulling(),this.emitPanEvent()}),this.stage.on("dragend",()=>{this.scheduleRoomCulling(),this.emitPanEvent()}),this.initRoomHitDetection()}clientToMapPoint(t,s){const i=this.stage.container().getBoundingClientRect(),o=t-i.left,n=s-i.top,r=this.stage.scaleX();if(!r)return null;const h=this.stage.position();return{x:(o-h.x)/r,y:(n-h.y)/r}}findRoomAtClientPoint(t,s){const e=this.clientToMapPoint(t,s);if(!e)return null;const i=this.settings.roomSize/2,o=this.getBucketKey(Math.floor(e.x/this.spatialBucketSize),Math.floor(e.y/this.spatialBucketSize)),n=this.roomSpatialIndex.get(o);if(!n)return null;for(const r of n){const h=e.x-r.room.x,a=e.y-r.room.y;if(h>=-i&&h<=i&&a>=-i&&a<=i)return r.room}return null}initRoomHitDetection(){const t=this.stage.container();let s=null;t.addEventListener("mousemove",a=>{const c=this.findRoomAtClientPoint(a.clientX,a.clientY);if(c!==s&&(s=c,c)){t.style.cursor="pointer";return}if(!s){const d=this.findAreaExitAtClientPoint(a.clientX,a.clientY)!==null;t.style.cursor=d?"pointer":"auto"}}),t.addEventListener("mouseleave",()=>{s=null,t.style.cursor="auto"});let e=null;t.addEventListener("mousedown",a=>{a.button===0&&(e={x:a.clientX,y:a.clientY})}),t.addEventListener("mouseup",a=>{if(a.button!==0||!e)return;const c=a.clientX-e.x,l=a.clientY-e.y;if(e=null,c*c+l*l>25)return;const d=this.findRoomAtClientPoint(a.clientX,a.clientY);if(d){this.emitRoomClickEvent(d.id,a.clientX,a.clientY);return}const g=this.findAreaExitAtClientPoint(a.clientX,a.clientY);if(g){this.emitAreaExitClickEvent(g.targetRoomId,a.clientX,a.clientY);return}this.emitMapClickEvent()}),t.addEventListener("contextmenu",a=>{const c=this.findRoomAtClientPoint(a.clientX,a.clientY);c&&(a.preventDefault(),this.emitRoomContextEvent(c.id,a.clientX,a.clientY))});let i,o,n;const r=()=>{n!==void 0&&(this.stage.draggable(n),n=void 0)},h=()=>{i!==void 0&&(window.clearTimeout(i),i=void 0),o=void 0,r()};t.addEventListener("touchstart",a=>{if(h(),a.touches.length>1)return;const c=a.touches[0];!c||!this.findRoomAtClientPoint(c.clientX,c.clientY)||(o={clientX:c.clientX,clientY:c.clientY},n=this.stage.draggable(),this.stage.draggable(!1),i=window.setTimeout(()=>{if(o){const d=this.findRoomAtClientPoint(o.clientX,o.clientY);d&&this.emitRoomContextEvent(d.id,o.clientX,o.clientY)}h()},500))},{passive:!0}),t.addEventListener("touchend",()=>h(),{passive:!0}),t.addEventListener("touchcancel",()=>h(),{passive:!0}),t.addEventListener("touchmove",a=>{if(!o)return;const c=a.touches[0];if(!c){h();return}const l=c.clientX-o.clientX,d=c.clientY-o.clientY;if(l*l+d*d>100){const g=n;h(),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 s,e=!1,i=!1;this.stage.on("touchstart",o=>{const n=o.evt.touches;n&&n.length>1?(i=!0,this.stage.isDragging()&&(this.stage.stopDrag(),e=!0),this.stage.draggable(!1)):(i=!1,this.stage.draggable(!0))}),this.stage.on("touchend touchcancel",o=>{s=void 0;const n=o.evt.touches;(!n||n.length<=1)&&(i=!1,this.stage.draggable(!0))}),this.stage.on("wheel",o=>{o.evt.preventDefault();const n=this.stage.scaleX(),r=this.stage.getPointerPosition();if(!r)return;const h={x:(r.x-this.stage.x())/n,y:(r.y-this.stage.y())/n};let a=o.evt.deltaY>0?-1:1;o.evt.ctrlKey&&(a=-a);const c=a>0?this.currentZoom*t:this.currentZoom/t;if(this.setZoom(c)){const d=this.stage.scaleX(),g={x:r.x-h.x*d,y:r.y-h.y*d};this.stage.position(g),this.scheduleRoomCulling(),this.emitZoomChangeEvent()}}),this.stage.on("touchmove",o=>{const n=o.evt.touches,r=n?.[0],h=n?.[1];if(h||i&&(i=!1,this.stage.draggable(!0)),r&&!h&&e&&!this.stage.isDragging()&&(this.stage.startDrag(),e=!1),!r||!h){s=void 0;return}o.evt.preventDefault(),this.stage.isDragging()&&(this.stage.stopDrag(),e=!0),i||(i=!0,this.stage.draggable(!1));const a=this.stage.container().getBoundingClientRect(),c={x:r.clientX-a.left,y:r.clientY-a.top},l={x:h.clientX-a.left,y:h.clientY-a.top},d=Math.hypot(c.x-l.x,c.y-l.y);if(s===void 0){s=d;return}if(s===0||d===0){s=d;return}const g=this.stage.scaleX(),u=this.stage.x(),f=this.stage.y(),y={x:this.stage.width()/2,y:this.stage.height()/2},p={x:(y.x-u)/g,y:(y.y-f)/g},x=this.currentZoom*(d/s);if(this.setZoom(x)){const D=this.stage.scaleX(),$={x:y.x-p.x*D,y:y.y-p.y*D};this.stage.position($),this.stage.batchDraw(),this.scheduleRoomCulling(),this.emitZoomChangeEvent()}s=d})}drawArea(t,s){const e=this.mapReader.getArea(t);if(!e)return;const i=e.getPlane(s);i&&(this.currentArea=t,this.currentAreaInstance=e,this.currentZIndex=s,this.currentAreaVersion=e.getVersion(),this.clearCurrentRoomOverlay(),this.positionRender&&(this.positionRender.destroy(),this.positionRender=void 0),this.positionLayer.destroyChildren(),this.gridLayer.destroyChildren(),this.invalidateGridCache(),this.roomLayer.destroyChildren(),this.linkLayer.destroyChildren(),this.roomNodes.clear(),this.standaloneExitNodes=[],this.areaExitHitZones=[],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(e.getLinkExits(s)),this.renderRooms(i.getRooms()??[]),this.renderAreaName(e,i),this.refreshHighlights(),this.updateRoomCulling(),this.stage.batchDraw())}exportSvg(t){return this.currentArea===void 0||this.currentZIndex===void 0?void 0:new pt(this.mapReader,this.settings).export(this.currentArea,this.currentZIndex,t)}exportPng(t){if(this.currentArea===void 0||this.currentZIndex===void 0)return;const s=t?.pixelRatio??1,e=this.stage.toCanvas({pixelRatio:s}),i=document.createElement("canvas");i.width=e.width,i.height=e.height;const o=i.getContext("2d");return o.fillStyle=this.settings.backgroundColor,o.fillRect(0,0,i.width,i.height),o.drawImage(e,0,0),i.toDataURL("image/png")}exportPngBlob(t){if(this.currentArea===void 0||this.currentZIndex===void 0)return;const s=t?.pixelRatio??1,e=this.stage.toCanvas({pixelRatio:s}),i=document.createElement("canvas");i.width=e.width,i.height=e.height;const o=i.getContext("2d");return o.fillStyle=this.settings.backgroundColor,o.fillRect(0,0,i.width,i.height),o.drawImage(e,0,0),new Promise(n=>{i.toBlob(r=>{r&&n(r)},"image/png")})}computeSpatialBucketSize(){return Math.max(this.settings.roomSize*10,5)}getBucketKey(t,s){return t*1000003+s}forEachBucket(t,s,e,i,o){const n=this.spatialBucketSize,r=Math.min(t,e),h=Math.max(t,e),a=Math.min(s,i),c=Math.max(s,i),l=Math.floor(r/n),d=Math.floor(h/n),g=Math.floor(a/n),u=Math.floor(c/n);for(let f=l;f<=d;f++)for(let y=g;y<=u;y++)o(this.getBucketKey(f,y))}addRoomToSpatialIndex(t){const s=this.settings.roomSize/2,e=t.room.x-s,i=t.room.x+s,o=t.room.y-s,n=t.room.y+s;this.forEachBucket(e,o,i,n,r=>{let h=this.roomSpatialIndex.get(r);h||(h=new Set,this.roomSpatialIndex.set(r,h)),h.add(t)})}addStandaloneExitToSpatialIndex(t){const{bounds:s}=t,e=s.x,i=s.x+s.width,o=s.y,n=s.y+s.height;this.forEachBucket(e,o,i,n,r=>{let h=this.exitSpatialIndex.get(r);h||(h=new Set,this.exitSpatialIndex.set(r,h)),h.add(t)})}collectRoomCandidates(t,s,e,i){const o=this.bufferRoomCandidates;return o.clear(),this.forEachBucket(t,s,e,i,n=>{this.roomSpatialIndex.get(n)?.forEach(h=>o.add(h))}),o}collectStandaloneExitCandidates(t,s,e,i){const o=this.bufferExitCandidates;return o.clear(),this.forEachBucket(t,s,e,i,n=>{this.exitSpatialIndex.get(n)?.forEach(h=>o.add(h))}),o}refreshStandaloneExitBoundsIfNeeded(){this.standaloneExitBoundsRoomSize!==this.settings.roomSize&&(this.exitSpatialIndex.clear(),this.standaloneExitNodes.forEach(t=>{this.addStandaloneExitToSpatialIndex(t)}),this.standaloneExitBoundsRoomSize=this.settings.roomSize)}emitRoomContextEvent(t,s,e){const i=this.stage.container(),o=i.getBoundingClientRect(),n={roomId:t,position:{x:s-o.left,y:e-o.top}},r=new CustomEvent("roomcontextmenu",{detail:n});i.dispatchEvent(r)}emitRoomClickEvent(t,s,e){const i=this.stage.container(),o=i.getBoundingClientRect(),n={roomId:t,position:{x:s-o.left,y:e-o.top}},r=new CustomEvent("roomclick",{detail:n});i.dispatchEvent(r)}findAreaExitAtClientPoint(t,s){const e=this.clientToMapPoint(t,s);if(!e)return null;for(const i of this.areaExitHitZones){const o=i.bounds,n=this.settings.roomSize*.5;if(e.x>=o.x-n&&e.x<=o.x+o.width+n&&e.y>=o.y-n&&e.y<=o.y+o.height+n)return i}return null}emitAreaExitClickEvent(t,s,e){const i=this.stage.container(),o=i.getBoundingClientRect(),n={targetRoomId:t,position:{x:s-o.left,y:e-o.top}},r=new CustomEvent("areaexitclick",{detail:n});i.dispatchEvent(r)}emitZoomChangeEvent(){const t=new CustomEvent("zoom",{detail:{zoom:this.currentZoom}});this.stage.container().dispatchEvent(t)}emitPanEvent(){const t=new CustomEvent("pan",{detail:this.getViewportBounds()});this.stage.container().dispatchEvent(t)}emitMapClickEvent(){const t=new CustomEvent("mapclick");this.stage.container().dispatchEvent(t)}setZoom(t){const s=Math.max(this.minZoom,Math.min(5,t));return this.currentZoom===s?!1:(this.currentZoom=s,this.stage.scale({x:j*this.currentZoom,y:j*this.currentZoom}),this.scheduleRoomCulling(),this.emitPanEvent(),!0)}zoomToCenter(t){const s=Math.max(this.minZoom,Math.min(5,t));if(this.currentZoom===s)return!1;const e=this.stage.scaleX(),i=this.stage.width(),o=this.stage.height(),n=i/2,r=o/2,h={x:(n-this.stage.x())/e,y:(r-this.stage.y())/e};this.currentZoom=s;const a=j*s;this.stage.scale({x:a,y:a});const c={x:n-h.x*a,y:r-h.y*a};return this.stage.position(c),this.stage.batchDraw(),this.scheduleRoomCulling(),!0}getZoom(){return this.currentZoom}getViewportBounds(){const t=this.stage.scaleX(),s=this.stage.position();return{minX:(0-s.x)/t,maxX:(this.stage.width()-s.x)/t,minY:(0-s.y)/t,maxY:(this.stage.height()-s.y)/t}}getAreaBounds(){if(!this.currentAreaInstance||this.currentZIndex===void 0)return null;const t=this.currentAreaInstance.getPlane(this.currentZIndex);if(!t)return null;const s=this.getEffectiveBounds(this.currentAreaInstance,t),e=this.settings.areaName&&this.currentAreaInstance.getAreaName();return{minX:e?s.minX-4:s.minX,maxX:s.maxX,minY:e?s.minY-7:s.minY,maxY:s.maxY}}fitArea(){if(this.currentArea===void 0||this.currentZIndex===void 0||!this.currentAreaInstance)return;const t=this.currentAreaInstance.getPlane(this.currentZIndex);if(!t)return;const s=this.getEffectiveBounds(this.currentAreaInstance,t),e=this.settings.areaName&&this.currentAreaInstance.getAreaName(),i=e?s.minY-7:s.minY,o=e?s.minX-4:s.minX,n=s.maxX-o,r=s.maxY-i;if(n<=0||r<=0)return;const h=this.stage.width(),a=this.stage.height(),c=2,l=h/((n+c*2)*j),d=a/((r+c*2)*j),g=Math.min(l,d);this.currentZoom=Math.max(.05,Math.min(5,g)),this.minZoom=this.currentZoom;const u=j*this.currentZoom;this.stage.scale({x:u,y:u});const f=(o+s.maxX)/2,y=(i+s.maxY)/2;this.stage.position({x:h/2-f*u,y:a/2-y*u}),this.stage.batchDraw(),this.scheduleRoomCulling()}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.currentArea!==void 0&&this.currentZIndex!==void 0&&(this.drawArea(this.currentArea,this.currentZIndex),this.currentRoomId!==void 0&&this.setPosition(this.currentRoomId))}updatePositionMarker(t){const s=this.mapReader.getRoom(t);if(!s)return;if(s.area!==this.currentArea||s.z!==this.currentZIndex){this.positionRender&&(this.positionRender.hide(),this.positionLayer.batchDraw());return}this.currentRoomId=t,this.updateCurrentRoomOverlay(s);const e=Q(this.settings.playerMarker.strokeColor,this.settings.playerMarker.strokeAlpha),i=Q(this.settings.playerMarker.fillColor,this.settings.playerMarker.fillAlpha),o=this.settings.roomSize/2*this.settings.playerMarker.sizeFactor;this.positionRender?(this.positionRender.position({x:s.x,y:s.y}),this.positionRender.radius(o),this.positionRender.stroke(e),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:s.x,y:s.y,radius:o,stroke:e,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,s=!0){const e=this.mapReader.getRoom(t);if(!e)return;const i=this.mapReader.getArea(e.area),o=i?.getVersion();let n=this.currentArea!==e.area||this.currentZIndex!==e.z;(this.currentArea!==e.area||this.currentZIndex!==e.z||o!==void 0&&this.currentAreaVersion!==o||i!==void 0&&this.currentAreaInstance!==i)&&this.drawArea(e.area,e.z),s?this.centerOnRoom(e,n):this.currentRoomId=t,this.updateCurrentRoomOverlay(e);const r=Q(this.settings.playerMarker.strokeColor,this.settings.playerMarker.strokeAlpha),h=Q(this.settings.playerMarker.fillColor,this.settings.playerMarker.fillAlpha),a=this.settings.roomSize/2*this.settings.playerMarker.sizeFactor;this.positionRender?(this.positionRender.radius(a),this.positionRender.stroke(r),this.positionRender.fill(h),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:e.x,y:e.y,radius:a,stroke:r,fill:h,strokeWidth:this.settings.playerMarker.strokeWidth,dash:this.settings.playerMarker.dash,dashEnabled:this.settings.playerMarker.dashEnabled}),this.positionLayer.add(this.positionRender))}clearPosition(){this.currentRoomId=void 0,this.positionRender&&(this.positionRender.destroy(),this.positionRender=void 0),this.positionLayer.batchDraw(),this.currentRoomOverlay.forEach(t=>t.destroy()),this.currentRoomOverlay=[],this.overlayLayer.batchDraw()}centerOn(t,s){const e=this.mapReader.getRoom(t);if(!e)return;const i=this.mapReader.getArea(e.area),o=i?.getVersion(),n=this.currentArea!==e.area||this.currentZIndex!==e.z;(n||o!==void 0&&this.currentAreaVersion!==o||i!==void 0&&this.currentAreaInstance!==i)&&this.drawArea(e.area,e.z),this.centerOnRoomView(e,s??n)}renderPath(t,s){return this.pathRenderer.renderPath(t,this.currentArea,this.currentZIndex,s)}clearPaths(){this.pathRenderer.clearPaths()}renderHighlight(t,s){const e=this.mapReader.getRoom(t);if(!e)return;const i=this.highlights.get(t);i?.shape&&(i.shape.destroy(),delete i.shape);const o={color:s,area:e.area,z:e.z};if(this.highlights.set(t,o),e.area===this.currentArea&&e.z===this.currentZIndex){const n=this.createHighlightShape(e,s);return this.overlayLayer.add(n),o.shape=n,this.overlayLayer.batchDraw(),n}return o.shape}removeHighlight(t){const s=this.highlights.get(t);s&&(s.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,s)=>{if(t.shape?.destroy(),delete t.shape,t.area!==this.currentArea||t.z!==this.currentZIndex)return;const e=this.mapReader.getRoom(s);if(!e)return;const i=this.createHighlightShape(e,t.color);this.overlayLayer.add(i),t.shape=i}),this.overlayLayer.batchDraw()}createHighlightShape(t,s){return this.settings.roomShape==="circle"?new b.Circle({x:t.x,y:t.y,radius:this.settings.roomSize/2*1.5,stroke:s,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:s,strokeWidth:.1,dash:[.05,.05],dashEnabled:!0,cornerRadius:this.settings.roomShape==="roundedRectangle"?this.settings.roomSize*1.5*.2:0,listening:!1})}centerOnRoom(t,s=!1){this.currentRoomId=t.id;const e={x:t.x,y:t.y};this.positionRender?.position(t);const o=this.stage.getAbsoluteTransform().point(e),n={x:this.stage.width()/2,y:this.stage.height()/2},r=n.x-o.x,h=n.y-o.y;this.currentTransition&&(this.currentTransition.pause(),this.currentTransition.destroy(),delete this.currentTransition),s||this.settings.instantMapMove?(this.stage.position({x:this.stage.x()+r,y:this.stage.y()+h}),this.scheduleRoomCulling()):(this.currentTransition=new b.Tween({node:this.stage,x:this.stage.x()+r,y:this.stage.y()+h,duration:.2,easing:b.Easings.EaseInOut,onUpdate:()=>this.scheduleRoomCulling(),onFinish:()=>this.scheduleRoomCulling()}),this.currentTransition.play())}centerOnRoomView(t,s=!1){const e={x:t.x,y:t.y},o=this.stage.getAbsoluteTransform().point(e),n={x:this.stage.width()/2,y:this.stage.height()/2},r=n.x-o.x,h=n.y-o.y;this.currentTransition&&(this.currentTransition.pause(),this.currentTransition.destroy(),delete this.currentTransition),s||this.settings.instantMapMove?(this.stage.position({x:this.stage.x()+r,y:this.stage.y()+h}),this.scheduleRoomCulling(),this.emitPanEvent()):(this.currentTransition=new b.Tween({node:this.stage,x:this.stage.x()+r,y:this.stage.y()+h,duration:.2,easing:b.Easings.EaseInOut,onUpdate:()=>this.scheduleRoomCulling(),onFinish:()=>{this.scheduleRoomCulling(),this.emitPanEvent()}}),this.currentTransition.play())}getEffectiveBounds(t,s){return this.settings.uniformLevelSize?t.getFullBounds():s.getBounds()}renderAreaName(t,s){if(!this.settings.areaName)return;const e=t.getAreaName();if(!e)return;const i=this.getEffectiveBounds(t,s);this.roomLayer.add(new b.Text({x:i.minX-3.5,y:i.minY-4.5,text:e,fontSize:2.5,fontFamily:this.settings.fontFamily,fill:"white",listening:!1,perfectDrawEnabled:!1}))}renderRooms(t){t.forEach(s=>{const e=new b.Group({x:s.x-this.settings.roomSize/2,y:s.y-this.settings.roomSize/2,listening:!1}),i=this.mapReader.getColorValue(s.env),o=this.settings.frameMode?this.settings.backgroundColor:i,n=this.settings.frameMode?i:this.settings.lineColor,r=this.settings.borders?this.settings.lineWidth:0,h=this.settings.roomShape==="circle"?new b.Circle({x:this.settings.roomSize/2,y:this.settings.roomSize/2,radius:this.settings.roomSize/2,fill:o,strokeWidth:r,stroke:n,perfectDrawEnabled:!1,listening:!1}):new b.Rect({x:0,y:0,width:this.settings.roomSize,height:this.settings.roomSize,fill:o,strokeWidth:r,stroke:n,cornerRadius:this.settings.roomShape==="roundedRectangle"?this.settings.roomSize*.2:0,perfectDrawEnabled:!1,listening:!1});if(e.add(h),this.settings.emboss&&this.settings.roomShape!=="circle"){const d=this.settings.roomSize,g=q(this.settings.lineColor)>.41;e.add(new b.Line({points:g?[0,0,d,0,d,d]:[0,0,0,d,d,d],stroke:g?"#000000":"#ffffff",strokeWidth:this.settings.lineWidth,perfectDrawEnabled:!1,listening:!1}))}this.renderSymbol(s,e),this.roomLayer.add(e),this.exitRenderer.renderSpecialExits(s).forEach(d=>{this.linkLayer.add(d)}),this.exitRenderer.getSpecialExitAreaTargets(s).forEach(d=>{this.areaExitHitZones.push(d)});const a=s.x-this.settings.roomSize/2,c=s.y-this.settings.roomSize/2;this.exitRenderer.renderStubs(s).forEach(d=>{const g=d.points();for(let u=0;u<g.length;u+=2)g[u]-=a,g[u+1]-=c;d.points(g),e.add(d)}),this.exitRenderer.renderInnerExits(s).forEach(d=>{d.position({x:-a,y:-c}),e.add(d)});const l={room:s,group:e};this.roomNodes.set(s.id,l),this.addRoomToSpatialIndex(l)})}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 s=this.settings.perfCallback?performance.now():0,e=this.stage.position(),i=this.settings.roomSize/2,o=this.settings.cullingBounds,n=o?o.x:0,r=o?o.x+o.width:this.stage.width(),h=o?o.y:0,a=o?o.y+o.height:this.stage.height(),c=Math.min(n,r),l=Math.max(n,r),d=Math.min(h,a),g=Math.max(h,a),u=(c-e.x)/t,f=(l-e.x)/t,y=(d-e.y)/t,p=(g-e.y)/t;let x=!1,k=!1;const D=this.settings.cullingEnabled?this.settings.cullingMode??"indexed":"none",$=u-i,X=f+i,w=y-i,R=p+i;if(this.refreshStandaloneExitBoundsIfNeeded(),D==="none"){if(this.roomNodes.forEach(v=>{v.group.visible()||(v.group.visible(!0),x=!0)}),this.visibleExitDrawData.length!==this.standaloneExitNodes.length){this.visibleExitDrawData.length=0;for(const v of this.standaloneExitNodes)this.visibleExitDrawData.push(v.data);k=!0}x&&this.roomLayer.batchDraw(),k&&this.linkLayer.batchDraw(),this.visibleRooms.clear(),this.roomNodes.forEach(v=>this.visibleRooms.add(v)),this.visibleStandaloneExitNodes.clear(),this.standaloneExitNodes.forEach(v=>this.visibleStandaloneExitNodes.add(v));return}if(D==="basic"){const v=this.bufferRoomSet;v.clear(),this.roomNodes.forEach(P=>{const O=P.room.x-i,T=P.room.x+i,F=P.room.y-i,V=P.room.y+i,B=T>=u&&O<=f&&V>=y&&F<=p;P.group.visible()!==B&&(P.group.visible(B),x=!0),B&&v.add(P)});const z=this.bufferExitSet;z.clear();let Y=!1;this.standaloneExitNodes.forEach(P=>{const{bounds:O}=P,T=O.x,F=O.x+O.width,V=O.y,B=O.y+O.height;F>=u&&T<=f&&B>=y&&V<=p&&(z.add(P),this.visibleStandaloneExitNodes.has(P)||(Y=!0))}),!Y&&z.size!==this.visibleStandaloneExitNodes.size&&(Y=!0),this.bufferRoomSet=this.visibleRooms,this.visibleRooms=v,this.bufferExitSet=this.visibleStandaloneExitNodes,this.visibleStandaloneExitNodes=z,Y&&(this.visibleExitDrawData.length=0,this.visibleStandaloneExitNodes.forEach(P=>this.visibleExitDrawData.push(P.data)),k=!0),x&&this.roomLayer.batchDraw(),k&&this.linkLayer.batchDraw();return}const E=this.collectRoomCandidates($,w,X,R),C=this.bufferRoomSet;C.clear(),E.forEach(v=>{const z=v.room.x-i,Y=v.room.x+i,P=v.room.y-i,O=v.room.y+i,T=Y>=u&&z<=f&&O>=y&&P<=p;v.group.visible()!==T&&(v.group.visible(T),x=!0),T&&C.add(v)}),this.visibleRooms.forEach(v=>{E.has(v)||v.group.visible()&&(v.group.visible(!1),x=!0)}),this.bufferRoomSet=this.visibleRooms,this.visibleRooms=C;const S=this.collectStandaloneExitCandidates($,w,X,R),M=this.bufferExitSet;M.clear();let I=!1;S.forEach(v=>{const{bounds:z}=v,Y=z.x,P=z.x+z.width,O=z.y,T=z.y+z.height;P>=u&&Y<=f&&T>=y&&O<=p&&(M.add(v),this.visibleStandaloneExitNodes.has(v)||(I=!0))}),!I&&M.size!==this.visibleStandaloneExitNodes.size&&(I=!0),this.bufferExitSet=this.visibleStandaloneExitNodes,this.visibleStandaloneExitNodes=M,I&&(this.visibleExitDrawData.length=0,this.visibleStandaloneExitNodes.forEach(v=>this.visibleExitDrawData.push(v.data)),k=!0),x&&this.roomLayer.batchDraw(),k&&this.linkLayer.batchDraw();const W=this.settings.perfCallback?performance.now():0;if(this.renderGrid(),this.settings.perfCallback){const v=performance.now()-W,z=performance.now()-s;this.perfMonitor.record({cullingMs:z,gridMs:v,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 s=this.stage.position(),e=this.stage.width(),i=this.stage.height(),o=(0-s.x)/t,n=(e-s.x)/t,r=(0-s.y)/t,h=(i-s.y)/t,a=this.settings.gridSize*2,c=Math.floor((Math.min(o,n)-a)/this.settings.gridSize)*this.settings.gridSize,l=Math.ceil((Math.max(o,n)+a)/this.settings.gridSize)*this.settings.gridSize,d=Math.floor((Math.min(r,h)-a)/this.settings.gridSize)*this.settings.gridSize,g=Math.ceil((Math.max(r,h)+a)/this.settings.gridSize)*this.settings.gridSize,u=this.cachedGridBounds;if(!(u&&u.left===c&&u.right===l&&u.top===d&&u.bottom===g)){this.gridLayer.destroyChildren();for(let f=c;f<=l;f+=this.settings.gridSize)this.gridLayer.add(new b.Line({points:[f,d,f,g],stroke:this.settings.gridColor,strokeWidth:this.settings.gridLineWidth,listening:!1,perfectDrawEnabled:!1}));for(let f=d;f<=g;f+=this.settings.gridSize)this.gridLayer.add(new b.Line({points:[c,f,l,f],stroke:this.settings.gridColor,strokeWidth:this.settings.gridLineWidth,listening:!1,perfectDrawEnabled:!1}));this.cachedGridBounds={left:c,right:l,top:d,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 s=new Map;s.set(t.id,t);const e=[],i=this.currentAreaInstance instanceof J?this.currentAreaInstance:void 0;this.currentAreaInstance&&this.currentZIndex!==void 0&&this.currentAreaInstance.getLinkExits(this.currentZIndex).filter(h=>h.a===t.id||h.b===t.id).forEach(h=>{const a=this.settings.highlightCurrentRoom?this.exitRenderer.renderWithColor(h,K,this.currentZIndex):this.exitRenderer.render(h,this.currentZIndex);a&&e.push(a)});const o=this.settings.highlightCurrentRoom?K:void 0;this.exitRenderer.renderSpecialExits(t,o).forEach(r=>{e.push(r)}),(this.settings.highlightCurrentRoom?this.exitRenderer.renderStubs(t,K):this.exitRenderer.renderStubs(t)).forEach(r=>{e.push(r)}),[...Object.values(t.exits),...Object.values(t.specialExits)].forEach(r=>{const h=this.mapReader.getRoom(r),a=!i||i.hasVisitedRoom(r);h&&h.area===this.currentArea&&h.z===this.currentZIndex&&a&&s.set(r,h)}),e.forEach(r=>{this.positionLayer.add(r),this.currentRoomOverlay.push(r)}),s.forEach((r,h)=>{const a=h===t.id,c=this.createOverlayRoomGroup(r,{stroke:a&&this.settings.highlightCurrentRoom?K:this.settings.lineColor});this.positionLayer.add(c),this.currentRoomOverlay.push(c),this.exitRenderer.renderInnerExits(r).forEach(l=>{this.positionLayer.add(l),this.currentRoomOverlay.push(l)})}),this.positionRender&&this.positionRender.moveToTop(),this.positionLayer.batchDraw()}createOverlayRoomGroup(t,s){const e=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),o=this.settings.frameMode?this.settings.backgroundColor:i,n=this.settings.frameMode?i:s.stroke,r=this.settings.borders?this.settings.lineWidth:0,h=this.settings.roomShape==="circle"?new b.Circle({x:this.settings.roomSize/2,y:this.settings.roomSize/2,radius:this.settings.roomSize/2,fill:o,stroke:n,strokeWidth:r}):new b.Rect({x:0,y:0,width:this.settings.roomSize,height:this.settings.roomSize,fill:o,stroke:n,strokeWidth:r,cornerRadius:this.settings.roomShape==="roundedRectangle"?this.settings.roomSize*.2:0});if(e.add(h),this.settings.emboss&&this.settings.roomShape!=="circle"){const a=this.settings.roomSize,c=q(this.settings.lineColor)>.41;e.add(new b.Line({points:c?[0,0,a,0,a,a]:[0,0,0,a,a,a],stroke:c?"#000000":"#ffffff",strokeWidth:this.settings.lineWidth,perfectDrawEnabled:!1,listening:!1}))}return this.renderSymbol(t,e),e}getSymbolColor(t,s){return this.settings.frameMode?this.mapReader.getColorValue(t):this.mapReader.getSymbolColor(t,s)}renderSymbol(t,s){if(t.roomChar!==void 0){const e=this.settings.roomSize*.75,i=new b.Text({x:0,y:0,text:t.roomChar,fontSize:e,fontStyle:"bold",fill:this.getSymbolColor(t.env),align:"center",verticalAlign:"middle",width:this.settings.roomSize,height:this.settings.roomSize,perfectDrawEnabled:!1,listening:!1});s.add(i)}}renderExits(t){t.forEach(s=>{const e=this.exitRenderer.renderData(s,this.currentZIndex);if(!e)return;const i={data:e,bounds:e.bounds,targetRoomId:e.targetRoomId};this.standaloneExitNodes.push(i),this.addStandaloneExitToSpatialIndex(i),e.targetRoomId!==void 0&&this.areaExitHitZones.push({bounds:e.bounds,targetRoomId:e.targetRoomId})}),this.standaloneExitBoundsRoomSize=this.settings.roomSize,this.exitBatchShape=new b.Shape({listening:!1,perfectDrawEnabled:!1,sceneFunc:s=>{const e=s._context;for(const i of this.visibleExitDrawData)this.drawExitData(e,i)}}),this.linkLayer.add(this.exitBatchShape)}drawExitData(t,s){for(const e of s.lines){t.beginPath(),t.moveTo(e.points[0],e.points[1]);for(let i=2;i<e.points.length;i+=2)t.lineTo(e.points[i],e.points[i+1]);t.strokeStyle=e.stroke,t.lineWidth=e.strokeWidth,e.dash?t.setLineDash(e.dash):t.setLineDash([]),t.stroke()}for(const e of s.arrows){t.beginPath(),t.moveTo(e.points[0],e.points[1]);for(let d=2;d<e.points.length;d+=2)t.lineTo(e.points[d],e.points[d+1]);t.strokeStyle=e.stroke,t.lineWidth=e.strokeWidth,e.dash?t.setLineDash(e.dash):t.setLineDash([]),t.stroke();const i=e.points.length-2,o=e.points[i],n=e.points[i+1],r=e.points[i-2],h=e.points[i-1],a=Math.atan2(n-h,o-r),c=e.pointerLength,l=e.pointerWidth/2;t.beginPath(),t.setLineDash([]),t.moveTo(o,n),t.lineTo(o-c*Math.cos(a-Math.atan2(l,c)),n-c*Math.sin(a-Math.atan2(l,c))),t.lineTo(o-c*Math.cos(a+Math.atan2(l,c)),n-c*Math.sin(a+Math.atan2(l,c))),t.closePath(),t.fillStyle=e.fill,t.fill(),t.strokeStyle=e.stroke,t.lineWidth=e.strokeWidth,t.stroke()}for(const e of s.doors)t.beginPath(),t.rect(e.x,e.y,e.width,e.height),t.strokeStyle=e.stroke,t.lineWidth=e.strokeWidth,t.setLineDash([]),t.stroke()}renderLabels(t){this.settings.labelRenderMode!=="none"&&t.forEach(s=>{if(this.settings.labelRenderMode==="image"){if(!s.pixMap)return;const e=new Image;e.src=`data:image/png;base64,${s.pixMap}`;const i=new b.Image({x:s.X,y:-s.Y,width:s.Width,height:s.Height,image:e,listening:!1});this.linkLayer.add(i);return}this.renderLabelAsData(s)})}renderLabelAsData(t){const s=new b.Group({listening:!1}),e=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?e.fill(this.getLabelColor(t.BgColor)):e.fillEnabled(!1),s.add(e);const i=Math.min(.75,t.Width/Math.max(t.Text.length/2,1)),o=Math.max(.1,Math.min(i,Math.max(t.Height*.9,.1))),n=new b.Text({x:t.X,y:-t.Y,width:t.Width,height:t.Height,text:t.Text,fontSize:o,fillEnabled:!0,fill:this.getLabelColor(t.FgColor),align:"center",verticalAlign:"middle",listening:!1});s.add(n),this.linkLayer.add(s)}getLabelColor(t){const s=(t?.alpha??255)/255,e=i=>Math.min(255,Math.max(0,i??0));return`rgba(${e(t?.r)}, ${e(t?.g)}, ${e(t?.b)}, ${s})`}}const kt={rgbValue:"rgb(114, 1, 0)",symbolColor:[225,225,225]};function Rt(m){const t=m[0]/255,s=m[1]/255,e=m[2]/255,i=Math.max(t,s,e),o=Math.min(t,s,e);return(i+o)/2}class Qt{constructor(t,s){this.rooms={},this.areas={},this.areaSources={},this.explorationEnabled=!1,this.colors={},t.forEach(e=>{e.rooms.forEach(o=>{o.y=-o.y,this.rooms[o.id]=o});const i=parseInt(e.areaId);this.areas[i]=new _(e),this.areaSources[i]=e}),this.colors=s.reduce((e,i)=>({...e,[i.envId]:{rgb:i.colors,rgbValue:`rgb(${i.colors.join(",")})`,symbolColor:Rt(i.colors)>.41?[25,25,25]:[225,255,255],symbolColorValue:Rt(i.colors)>.41?"rgb(25,25,25)":"rgb(225,255,255)"}}),{})}getArea(t){return this.areas[t]}getExplorationArea(t){const s=this.areas[t];if(s instanceof J)return s}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,s])=>{const e=parseInt(t,10);this.areas[e]=new J(s,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,s])=>{const e=parseInt(t,10);this.areas[e]=new _(s)}),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 o=this.getExplorationArea(i.area);if(o)return o.addVisitedRoom(t)}}const s=this.ensureVisitedRooms(),e=s.has(t);return s.add(t),!e}addVisitedRooms(t){const s=this.ensureVisitedRooms();let e=0;for(const i of t){if(this.explorationEnabled){const n=this.getRoom(i);if(n){const r=this.getExplorationArea(n.area);if(r){r.addVisitedRoom(i)&&e++;continue}}}const o=s.has(i);s.add(i),o||e++}return e}hasVisitedRoom(t){return this.visitedRooms?.has(t)??!1}getColorValue(t){return this.colors[t]?.rgbValue??kt.rgbValue}getSymbolColor(t,s){const e=this.colors[t]?.symbolColor??kt.symbolColor,i=Math.min(Math.max(s??1,0),1),o=e.join(",");return i!=1?`rgba(${o}, ${i})`:`rgba(${o})`}}function Ut(m){return m&&m.__esModule&&Object.prototype.hasOwnProperty.call(m,"default")?m.default:m}var ht,St;function Jt(){if(St)return ht;St=1;class m{constructor(){this.keys=new Set,this.queue=[]}sort(){this.queue.sort((s,e)=>s.priority-e.priority)}set(s,e){const i=Number(e);if(isNaN(i))throw new TypeError('"priority" must be a number');return this.keys.has(s)?this.queue.map(o=>(o.key===s&&Object.assign(o,{priority:i}),o)):(this.keys.add(s),this.queue.push({key:s,priority:i})),this.sort(),this.queue.length}next(){const s=this.queue.shift();return this.keys.delete(s.key),s}isEmpty(){return this.queue.length===0}has(s){return this.keys.has(s)}get(s){return this.queue.find(e=>e.key===s)}}return ht=m,ht}var ct,Et;function te(){if(Et)return ct;Et=1;function m(t,s){const e=new Map;for(const[i,o]of t)i!==s&&o instanceof Map?e.set(i,m(o,s)):i!==s&&e.set(i,o);return e}return ct=m,ct}var lt,Mt;function ee(){if(Mt)return lt;Mt=1;function m(s){const e=Number(s);return!(isNaN(e)||e<=0)}function t(s){const e=new Map;return Object.keys(s).forEach(o=>{const n=s[o];if(n!==null&&typeof n=="object"&&!Array.isArray(n))return e.set(o,t(n));if(!m(n))throw new Error(`Could not add node at key "${o}", make sure it's a valid node`,n);return e.set(o,Number(n))}),e}return lt=t,lt}var dt,Ct;function se(){if(Ct)return dt;Ct=1;function m(t){if(!(t instanceof Map))throw new Error(`Invalid graph: Expected Map instead found ${typeof t}`);t.forEach((s,e)=>{if(typeof s=="object"&&s instanceof Map){m(s);return}if(typeof s!="number"||s<=0)throw new Error(`Values must be numbers greater than 0. Found value ${s} at ${e}`)})}return dt=m,dt}var gt,Dt;function ie(){if(Dt)return gt;Dt=1;const m=Jt(),t=te(),s=ee(),e=se();class i{constructor(n){n instanceof Map?(e(n),this.graph=n):n?this.graph=s(n):this.graph=new Map}addNode(n,r){let h;return r instanceof Map?(e(r),h=r):h=s(r),this.graph.set(n,h),this}addVertex(n,r){return this.addNode(n,r)}removeNode(n){return this.graph=t(this.graph,n),this}path(n,r,h={}){if(!this.graph.size)return h.cost?{path:null,cost:0}:null;const a=new Set,c=new m,l=new Map;let d=[],g=0,u=[];if(h.avoid&&(u=[].concat(h.avoid)),u.includes(n))throw new Error(`Starting node (${n}) cannot be avoided`);if(u.includes(r))throw new Error(`Ending node (${r}) cannot be avoided`);for(c.set(n,0);!c.isEmpty();){const f=c.next();if(f.key===r){g=f.priority;let p=f.key;for(;l.has(p);)d.push(p),p=l.get(p);break}a.add(f.key),(this.graph.get(f.key)||new Map).forEach((p,x)=>{if(a.has(x)||u.includes(x))return null;if(!c.has(x))return l.set(x,f.key),c.set(x,f.priority+p);const k=c.get(x).priority,D=f.priority+p;return D<k?(l.set(x,f.key),c.set(x,D)):null})}return d.length?(h.trim?d.shift():d=d.concat([n]),h.reverse||(d=d.reverse()),h.cost?{path:d,cost:g}:d):h.cost?{path:null,cost:0}:null}shortestPath(...n){return this.path(...n)}}return gt=i,gt}var oe=ie();const ne=Ut(oe),re={1:"north",2:"northeast",3:"northwest",4:"east",5:"west",6:"south",7:"southeast",8:"southwest",9:"up",10:"down",11:"in",12:"out"},ae={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 It(m,t){m.push(t);let s=m.length-1;for(;s>0;){const e=s-1>>1;if(m[e].priority<=m[s].priority)break;[m[e],m[s]]=[m[s],m[e]],s=e}}function he(m){if(m.length===0)return;const t=m[0],s=m.pop();if(m.length>0){m[0]=s;let e=0;const i=m.length;for(;;){let o=e;const n=2*e+1,r=2*e+2;if(n<i&&m[n].priority<m[o].priority&&(o=n),r<i&&m[r].priority<m[o].priority&&(o=r),o===e)break;[m[e],m[o]]=[m[o],m[e]],e=o}}return t}function ce(m,t,s){const e=[s];let i=s;for(;i!==t;)i=m.get(i),e.push(i);return e.reverse(),e}function le(m,t,s){const e=m.path(t.toString(),s.toString()),i=Array.isArray(e)?e:e?.path;return i?i.map(o=>Number(o)):null}function de(m,t,s,e,i,o){const n=e.getRoom(s);if(!n)return null;const r=n.x,h=n.y,a=n.z,c=u=>{const f=e.getRoom(u);if(!f)return 0;const y=f.x-r,p=f.y-h,x=f.z-a;return Math.sqrt(y*y+p*p+x*x)/i*o},l=new Map,d=new Map,g=[];for(l.set(t,0),It(g,{id:t,priority:c(t)});g.length>0;){const{id:u}=he(g);if(u===s)return ce(d,t,s);const f=l.get(u)??1/0,y=m.get(u);if(y)for(const p of y){const x=f+p.weight;x<(l.get(p.id)??1/0)&&(l.set(p.id,x),d.set(p.id,u),It(g,{id:p.id,priority:x+c(p.id)}))}}return null}class ge{constructor(t,s="dijkstra"){this.cache=new Map,this.mapReader=t,this._algorithm=s;const{adj:e,maxEdgeDistance:i,minEdgeWeight:o,graphDefinition:n}=this.buildGraph();this.adj=e,this.graph=new ne(n),this.maxEdgeDistance=i,this.minEdgeWeight=o}get algorithm(){return this._algorithm}setAlgorithm(t){t!==this._algorithm&&(this._algorithm=t,this.cache.clear())}findPath(t,s){const e=`${t}->${s}`;if(this.cache.has(e))return this.cache.get(e);if(t===s){const o=this.mapReader.getRoom(t)?[t]:null;return this.cache.set(e,o),o}if(!this.mapReader.getRoom(t)||!this.mapReader.getRoom(s))return this.cache.set(e,null),null;let i;switch(this._algorithm){case"dijkstra":i=le(this.graph,t,s);break;case"astar":i=de(this.adj,t,s,this.mapReader,this.maxEdgeDistance,this.minEdgeWeight);break}return this.cache.set(e,i),i}resolveEdgeWeight(t,s,e){const i=t.exitWeights?.[s];return i!==void 0&&i>0?i:Math.max(e.weight,1)}buildGraph(){const t=new Map,s={};let e=1,i=1/0;return this.mapReader.getRooms().forEach(o=>{const n=[],r={},h=new Set((o.exitLocks??[]).map(c=>re[c]).filter(c=>!!c)),a=new Set(o.mSpecialExitLocks??[]);Object.entries(o.exits??{}).forEach(([c,l])=>{if(h.has(c))return;const d=this.mapReader.getRoom(l);if(d){const g=ae[c]??c,u=this.resolveEdgeWeight(o,g,d);n.push({id:l,weight:u}),r[l.toString()]=u,u<i&&(i=u);const f=d.x-o.x,y=d.y-o.y,p=d.z-o.z,x=Math.sqrt(f*f+y*y+p*p);x>e&&(e=x)}}),Object.entries(o.specialExits??{}).forEach(([c,l])=>{if(a.has(l))return;const d=this.mapReader.getRoom(l);if(d){const g=this.resolveEdgeWeight(o,c,d);n.push({id:l,weight:g}),r[l.toString()]=g,g<i&&(i=g);const u=d.x-o.x,f=d.y-o.y,y=d.z-o.z,p=Math.sqrt(u*u+f*f+y*y);p>e&&(e=p)}}),t.set(o.id,n),s[o.id.toString()]=r}),isFinite(i)||(i=1),{adj:t,maxEdgeDistance:e,minEdgeWeight:i,graphDefinition:s}}}const ue={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 $t(){return{areaWidth:150,areaHeight:80,areaSpacing:50,fontSize:14,connectionLineWidth:2,areaFillColor:"#2a2a3e",areaStrokeColor:"#4a4a6e",textColor:"#e0e0e0",connectionColor:"#6a6a8e",highlightColor:"#ff9900"}}class fe{constructor(t,s,e){this.areaNodes=new Map,this.connectionGroups=[],this.currentZoom=1,this.domainInfo=new Map,this.domainFilter="all",this.dotsMode=!1,this.settings=e??$t(),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=s,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",s=>{s.evt.preventDefault();const e=this.stage.scaleX(),i=this.stage.getPointerPosition();if(!i)return;const o={x:(i.x-this.stage.x())/e,y:(i.y-this.stage.y())/e},r=(s.evt.deltaY>0?-1:1)>0?this.currentZoom*1.1:this.currentZoom/1.1;if(this.setZoom(r)){const h=this.stage.scaleX(),a={x:i.x-o.x*h,y:i.y-o.y*h};this.stage.position(a),this.stage.batchDraw()}})}setZoom(t){const s=Math.max(.1,Math.min(5,t));return this.currentZoom===s?!1:(this.currentZoom=s,this.stage.scale({x:this.currentZoom,y:this.currentZoom}),!0)}getZoom(){return this.currentZoom}setDomainInfo(t){this.domainInfo.clear();for(const[s,e]of Object.entries(t))this.domainInfo.set(Number(s),e)}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 s=this.domainInfo.get(t);if(!s)return this.domainFilter==="interdomain"||this.domainFilter==="all";switch(this.domainFilter){case"ishtar":return s.isIshtar;case"empire":return s.isEmpire;case"interdomain":return!s.isIshtar&&!s.isEmpire;case"all":return!0}}areAreasInSameDomain(t,s){const e=this.domainInfo.get(t),i=this.domainInfo.get(s);return!e||!i?!1:e.isIshtar&&i.isIshtar||e.isEmpire&&i.isEmpire?!0:!e.isIshtar&&!e.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(),s=this.mapReader.getAreas(),e=new Map;for(const a of s){const c=a.getAreaId(),l=a.getRooms();if(l.length===0)continue;let d=1/0,g=-1/0,u=1/0,f=-1/0,y=0;for(const k of l)k.z===0&&(y++,d=Math.min(d,k.x),g=Math.max(g,k.x),u=Math.min(u,k.y),f=Math.max(f,k.y));if(y===0)for(const k of l)d=Math.min(d,k.x),g=Math.max(g,k.x),u=Math.min(u,k.y),f=Math.max(f,k.y);const p=(d+g)/2,x=(u+f)/2;e.set(c,{minX:d,maxX:g,minY:u,maxY:f,centerX:p,centerY:x,roomCount:l.length})}let i=1;for(const a of e.values()){const c=a.maxX-a.minX,l=a.maxY-a.minY;i=Math.max(i,c,l)}const o=200,n=100,r=o/i;for(const a of s){const c=a.getAreaId(),l=e.get(c);if(!l||!this.isAreaInDomain(c))continue;const d=l.maxX-l.minX,g=l.maxY-l.minY;let u=Math.max(n,d*r),f=Math.max(n,g*r);const y=u/f;y>3?f=u/3:y<1/3&&(u=f/3),this.areaNodes.set(c,{areaId:c,name:a.getAreaName(),x:0,y:0,width:u,height:f,connections:[],roomCount:l.roomCount,realCenterX:l.centerX,realCenterY:l.centerY})}const h=new Map;for(const a of t){const c=a.area;if(!this.areaNodes.has(c))continue;const l=this.getLockedDirections(a),d=new Set(a.mSpecialExitLocks??[]);for(const[g,u]of Object.entries(a.exits??{})){if(l.has(g))continue;const f=this.mapReader.getRoom(u);if(!f||f.area===c||!this.areaNodes.has(f.area)||!this.areAreasInSameDomain(c,f.area))continue;const y=this.createConnection(a,f,g);y&&this.addConnection(h,y)}for(const[g,u]of Object.entries(a.specialExits??{})){if(d.has(u))continue;const f=this.mapReader.getRoom(u);if(!f||f.area===c||!this.areaNodes.has(f.area)||!this.areAreasInSameDomain(c,f.area))continue;const y=this.parseDirection(g),p=this.createConnection(a,f,y);p&&this.addConnection(h,p)}}for(const[a,c]of h){const[l,d]=a.split("-").map(Number),g=this.createConnectionGroup(l,d,c);this.connectionGroups.push(g);const u=this.areaNodes.get(l),f=this.areaNodes.get(d);if(u&&u.connections.push(...c),f)for(const y of c)f.connections.push({...y,fromAreaId:y.toAreaId,toAreaId:y.fromAreaId,fromRoomId:y.toRoomId,toRoomId:y.fromRoomId,direction:y.direction?Lt[y.direction]:null,fromRoomPosition:y.toRoomPosition,toRoomPosition:y.fromRoomPosition})}}getLockedDirections(t){return new Set((t.exitLocks??[]).map(s=>ue[s]).filter(s=>!!s))}createConnection(t,s,e){const i=this.toPlanarDirection(e);return{fromAreaId:t.area,toAreaId:s.area,fromRoomId:t.id,toRoomId:s.id,direction:i,fromRoomPosition:{x:t.x,y:t.y},toRoomPosition:{x:s.x,y:s.y}}}addConnection(t,s){const e=s.fromAreaId<s.toAreaId?`${s.fromAreaId}-${s.toAreaId}`:`${s.toAreaId}-${s.fromAreaId}`;t.has(e)||t.set(e,[]),t.get(e).push(s)}createConnectionGroup(t,s,e){const i=new Map;let o=0,n=0;for(const a of e)a.direction&&i.set(a.direction,(i.get(a.direction)??0)+1),o+=a.toRoomPosition.x-a.fromRoomPosition.x,n+=a.toRoomPosition.y-a.fromRoomPosition.y;let r=null,h=0;for(const[a,c]of i)c>h&&(h=c,r=a);return{fromAreaId:t,toAreaId:s,connections:e,primaryDirection:r,averageOffset:{x:o/e.length,y:n/e.length}}}parseDirection(t){const s=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"}[s]??null}toPlanarDirection(t){return t&&ut.includes(t)?t:null}layoutAreas(){if(Array.from(this.areaNodes.values()).length===0)return;const s=this.findConnectedComponents();let e=0;const i=this.settings.areaWidth*3;for(const o of s)if(o.length===1){const n=this.areaNodes.get(o[0]);n&&(n.x=e,n.y=0),e+=this.settings.areaWidth+i}else{const n=this.forceDirectedLayout(o);for(const h of o){const a=this.areaNodes.get(h);a&&isFinite(n.minX)&&isFinite(n.minY)&&(a.x-=n.minX,a.x+=e,a.y-=n.minY)}const r=isFinite(n.maxX-n.minX)?n.maxX-n.minX:this.settings.areaWidth;e+=r+i}}findConnectedComponents(){const t=new Set,s=[];for(const[e]of this.areaNodes){if(t.has(e))continue;const i=[],o=[e];for(;o.length>0;){const n=o.shift();if(t.has(n))continue;t.add(n),i.push(n);const r=this.areaNodes.get(n);if(r)for(const h of r.connections)t.has(h.toAreaId)||o.push(h.toAreaId)}s.push(i)}return s}forceDirectedLayout(t){const s=new Map;for(const w of t){const R=this.areaNodes.get(w);if(!R)continue;const E=new Set(R.connections.map(C=>C.toAreaId));s.set(w,E)}const e=new Set,i=new Set;for(const[w,R]of s)R.size>=3&&e.add(w);for(const[w,R]of s){if(e.has(w)||i.has(w)||R.size>2)continue;const E=[w];i.add(w);const C=Array.from(R);for(const M of C){let I=M,W=w;for(;I&&!i.has(I)&&!e.has(I);){const v=s.get(I);if(!v)break;if(v.size>=3){e.add(I);break}E.push(I),i.add(I);let z=!1;for(const Y of v)if(Y!==W&&!i.has(Y)){W=I,I=Y,z=!0;break}if(!z)break}}let S=!1;for(const M of E){const I=s.get(M);if(I){for(const W of I)if(e.has(W)){S=!0;break}}if(S)break}if(!S&&E.length>0){let M=E[0],I=s.get(E[0])?.size??0;for(const W of E){const v=s.get(W)?.size??0;v>I&&(I=v,M=W)}e.add(M),i.delete(M)}}for(const w of t){const R=s.get(w);(!R||R.size===0)&&e.add(w)}const o=new Map,n=new Map;for(const w of e)o.set(w,w),n.set(w,[]);const r=new Set(e);for(const w of e){const R=s.get(w)??new Set;for(const E of R){if(r.has(E))continue;const C=[];let S=E,M=w;for(;S&&!r.has(S);){C.push(S),o.set(S,w),r.add(S);const I=s.get(S)??new Set;let W;for(const v of I)if(v!==M&&!r.has(v)){W=v;break}M=S,S=W}C.length>0&&n.get(w).push(C)}}const h=new Set,a=[],c=e.values().next().value,l=c!==void 0?c:t[0];if(l!==void 0){const w=this.areaNodes.get(l);w&&(w.x=0,w.y=0,h.add(l),a.push(l))}for(;a.length>0;){const w=a.shift(),R=this.areaNodes.get(w),E=new Map;for(const C of R.connections){const S=C.toAreaId;if(h.has(S)||!e.has(S))continue;const M=this.areaNodes.get(S);if(!M)continue;const I=C.direction??"none";E.has(I)||E.set(I,[]),E.get(I).push({id:S,node:M,conn:C})}for(const[C,S]of E){const M=this.getDirectionOffset(C==="none"?null:C);S.sort((v,z)=>Math.abs(M.x)>Math.abs(M.y)?z.node.realCenterY-v.node.realCenterY:v.node.realCenterX-z.node.realCenterX);const I=this.settings.areaWidth+this.settings.areaSpacing,W=this.settings.areaHeight+this.settings.areaSpacing;S.forEach((v,z)=>{if(v.node.x=R.x+M.x*I,v.node.y=R.y+M.y*W,S.length>1){const Y=(z-(S.length-1)/2)*.5;Math.abs(M.x)>Math.abs(M.y)?v.node.y+=Y*W:v.node.x+=Y*I}h.add(v.id),a.push(v.id)})}}const d=Array.from(e);d.length>1&&this.applyForces(d,80);const g=this.settings.areaWidth+this.settings.areaSpacing+30,u=this.settings.areaHeight+this.settings.areaSpacing+30,f=new Map,y=["east","west","north","south","northeast","northwest","southeast","southwest"];for(const[w,R]of n){const E=this.areaNodes.get(w);if(!E)continue;let C=0;const S=new Map;for(const M of R){let I=w,W=E.x,v=E.y,z=null;for(const Y of M){const P=this.areaNodes.get(Y);if(!P)continue;const O=this.areaNodes.get(I);let T=null;if(O){for(const B of O.connections)if(B.toAreaId===Y){T=B.direction;break}}!T&&I===w?(z=y[C%y.length],C++,T=z):!T&&z&&(T=z);const F=this.getDirectionOffset(T);let V=0;if(I===w&&T){const B=T,rt=S.get(B)??0;S.set(B,rt+1),V=rt}P.x=W+F.x*g,P.y=v+F.y*u,V>0&&(F.x!==0&&F.y===0?P.y+=V*u*1.2:F.y!==0&&F.x===0?P.x+=V*g*1.2:(P.x+=V*g*1.2,P.y-=V*u*1.2)),f.set(Y,{dx:P.x-E.x,dy:P.y-E.y,hubId:w}),I=Y,W=P.x,v=P.y}}}const p=new Map,x=new Map;for(const w of e){const R=this.areaNodes.get(w);if(!R)continue;let E=R.x,C=R.y,S=R.x+R.width,M=R.y+R.height;const I=n.get(w)??[];for(const W of I)for(const v of W){const z=this.areaNodes.get(v);z&&(E=Math.min(E,z.x),C=Math.min(C,z.y),S=Math.max(S,z.x+z.width),M=Math.max(M,z.y+z.height))}p.set(w,{minX:E,minY:C,maxX:S,maxY:M}),x.set(w,{dx:E-R.x,dy:C-R.y})}this.applyClusterForces(d,p,x,60);for(const[w,R]of f){const E=this.areaNodes.get(w),C=this.areaNodes.get(R.hubId);!E||!C||(E.x=C.x+R.dx,E.y=C.y+R.dy)}let k=1/0,D=1/0,$=-1/0,X=-1/0;for(const w of t){const R=this.areaNodes.get(w);k=Math.min(k,R.x),D=Math.min(D,R.y),$=Math.max($,R.x+R.width),X=Math.max(X,R.y+R.height)}return{minX:k,minY:D,maxX:$,maxY:X}}getDirectionOffset(t){const s={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&&s[t]?s[t]:{x:1,y:0}}applyClusterForces(t,s,e,i){const r=new Map;for(const h of t)r.set(h,{vx:0,vy:0});for(let h=0;h<i;h++){for(const a of t){const c=this.areaNodes.get(a),l=s.get(a),d=e.get(a);if(!c||!l||!d)continue;const g=l.maxX-l.minX,u=l.maxY-l.minY;l.minX=c.x+d.dx,l.minY=c.y+d.dy,l.maxX=l.minX+g,l.maxY=l.minY+u}for(const a of t){const c=this.areaNodes.get(a),l=r.get(a),d=s.get(a);if(!(!c||!l||!d)){for(const g of t){if(a===g)continue;const u=s.get(g);if(!u)continue;const f=(d.minX+d.maxX)/2,y=(d.minY+d.maxY)/2,p=(u.minX+u.maxX)/2,x=(u.minY+u.maxY)/2,k=f-p,D=y-x,$=(d.maxX-d.minX)/2,X=(d.maxY-d.minY)/2,w=(u.maxX-u.minX)/2,R=(u.maxY-u.minY)/2,E=$+w+50,C=X+R+50,S=E-Math.abs(k),M=C-Math.abs(D);if(S>0&&M>0)if(S<M){const I=S*(k>=0?1:-1)*.5;l.vx+=I}else{const I=M*(D>=0?1:-1)*.5;l.vy+=I}}for(const g of c.connections){const u=this.areaNodes.get(g.toAreaId);if(!u||!t.includes(g.toAreaId))continue;const f=u.x-c.x,y=u.y-c.y,p=Math.sqrt(f*f+y*y)||1,x=this.settings.areaWidth+this.settings.areaSpacing+50,D=(p-x)*.015;l.vx+=f/p*D,l.vy+=y/p*D}}}for(const a of t){const c=this.areaNodes.get(a),l=r.get(a);!c||!l||(c.x+=l.vx,c.y+=l.vy,l.vx*=.8,l.vy*=.8)}}}applyForces(t,s){const o=this.settings.areaWidth+this.settings.areaSpacing,n=this.settings.areaWidth/2+60,r=new Set(t),h=[],a=new Set;for(const l of t){const d=this.areaNodes.get(l);if(d)for(const g of d.connections){if(!r.has(g.toAreaId))continue;const u=Math.min(l,g.toAreaId)+"-"+Math.max(l,g.toAreaId);a.has(u)||(a.add(u),h.push({from:l,to:g.toAreaId}))}}const c=new Map;for(const l of t)c.set(l,{vx:0,vy:0});for(let l=0;l<s;l++){for(const d of t){const g=this.areaNodes.get(d),u=c.get(d);if(!g||!u)continue;const f=g.x+g.width/2,y=g.y+g.height/2;for(const p of t){if(d===p)continue;const x=this.areaNodes.get(p);if(!x)continue;const k=(g.width+x.width)/2+20,D=(g.height+x.height)/2+20,$=g.x+g.width/2,X=g.y+g.height/2,w=x.x+x.width/2,R=x.y+x.height/2,E=$-w,C=X-R,S=k-Math.abs(E),M=D-Math.abs(C);S>0&&M>0&&(S<M?u.vx+=(E>=0?1:-1)*S*.5:u.vy+=(C>=0?1:-1)*M*.5)}for(const p of h){if(p.from===d||p.to===d)continue;const x=this.areaNodes.get(p.from),k=this.areaNodes.get(p.to);if(!x||!k)continue;const D=x.x+x.width/2,$=x.y+x.height/2,X=k.x+k.width/2,w=k.y+k.height/2,R=this.closestPointOnSegment(f,y,D,$,X,w),E=f-R.x,C=y-R.y,S=Math.sqrt(E*E+C*C)||1;if(S<n){const M=(n-S)*.6;u.vx+=E/S*M,u.vy+=C/S*M}}for(const p of g.connections){if(!r.has(p.toAreaId))continue;const x=this.areaNodes.get(p.toAreaId);if(!x)continue;const k=x.x-g.x,D=x.y-g.y,$=Math.sqrt(k*k+D*D)||1,w=($-o)*.03;u.vx+=k/$*w,u.vy+=D/$*w;const R=this.getDirectionOffset(p.direction),E=g.x+R.x*o,C=g.y+R.y*o,S=c.get(p.toAreaId);S&&(S.vx+=(E-x.x)*.01,S.vy+=(C-x.y)*.01)}}for(const d of t){const g=this.areaNodes.get(d),u=c.get(d);!g||!u||(g.x+=u.vx,g.y+=u.vy,u.vx*=.8,u.vy*=.8)}}}closestPointOnSegment(t,s,e,i,o,n){const r=o-e,h=n-i,a=t-e,c=s-i,l=r*r+h*h;if(l===0)return{x:e,y:i};let d=(a*r+c*h)/l;return d=Math.max(0,Math.min(1,d)),{x:e+d*r,y:i+d*h}}edgesIntersect(t,s,e,i,o,n,r,h){const a=(c,l,d,g,u,f)=>(f-l)*(d-c)>(g-l)*(u-c);return a(t,s,o,n,r,h)!==a(e,i,o,n,r,h)&&a(t,s,e,i,o,n)!==a(t,s,e,i,r,h)}drawConnections(){this.connectionLayer.destroyChildren();for(const t of this.connectionGroups){const s=this.areaNodes.get(t.fromAreaId),e=this.areaNodes.get(t.toAreaId);if(!s||!e||!isFinite(s.x)||!isFinite(s.y)||!isFinite(e.x)||!isFinite(e.y))continue;const i={x:s.x+s.width/2,y:s.y+s.height/2},o={x:e.x+e.width/2,y:e.y+e.height/2};let n,r;if(this.dotsMode?(n=i,r=o):(n=this.getEdgePoint(s,o),r=this.getEdgePoint(e,i)),!isFinite(n.x)||!isFinite(n.y)||!isFinite(r.x)||!isFinite(r.y))continue;const h=this.dotsMode?"#ffffff":this.settings.connectionColor,a=this.dotsMode?1:Math.min(this.settings.connectionLineWidth,1+t.connections.length*.5),c=new b.Line({points:[n.x,n.y,r.x,r.y],stroke:h,strokeWidth:a,lineCap:"round",listening:!1});this.connectionLayer.add(c)}}getEdgePoint(t,s){const e=t.x+t.width/2,i=t.y+t.height/2,o=s.x-e,n=s.y-i,r=t.width/2,h=t.height/2;if(o===0&&n===0)return{x:e,y:i};const a=Math.abs(o),c=Math.abs(n);let l;return a/r>c/h?l=r/a:l=h/c,{x:e+o*l,y:i+n*l}}drawAreas(){this.areaLayer.destroyChildren();for(const[,t]of this.areaNodes){if(!isFinite(t.x)||!isFinite(t.y))continue;const s=t.areaId===this.highlightedArea;if(this.dotsMode){const i=t.x+t.width/2,o=t.y+t.height/2,n=new b.Group({x:i,y:o,draggable:!0}),r=new b.Circle({radius:6,fill:s?this.settings.highlightColor:"#ffffff",stroke:s?this.settings.highlightColor:"#ffffff",strokeWidth:1}),h=new b.Text({text:t.name,fontSize:10,fill:"#ffffff",x:10,y:-5});n.add(r),n.add(h),n.on("click tap",()=>{this.emitAreaClickEvent(t.areaId)}),n.on("mouseenter",()=>{this.stage.container().style.cursor="pointer",r.fill(this.settings.highlightColor),r.stroke(this.settings.highlightColor),this.areaLayer.batchDraw()}),n.on("mouseleave",()=>{this.stage.container().style.cursor="auto",r.fill(s?this.settings.highlightColor:"#ffffff"),r.stroke(s?this.settings.highlightColor:"#ffffff"),this.areaLayer.batchDraw()}),n.on("dragmove",()=>{t.x=n.x()-t.width/2,t.y=n.y()-t.height/2,this.drawConnections(),this.connectionLayer.batchDraw()}),n.on("dragstart",()=>{this.stage.container().style.cursor="grabbing"}),n.on("dragend",()=>{this.stage.container().style.cursor="pointer"}),this.areaLayer.add(n)}else{const e=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:s?this.settings.highlightColor:this.settings.areaStrokeColor,strokeWidth:s?3:2,cornerRadius:8}),o=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"}),n=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"});e.add(i),e.add(o),e.add(n),e.on("click tap",()=>{this.emitAreaClickEvent(t.areaId)}),e.on("mouseenter",()=>{this.stage.container().style.cursor="pointer",i.stroke(this.settings.highlightColor),this.areaLayer.batchDraw()}),e.on("mouseleave",()=>{this.stage.container().style.cursor="auto",i.stroke(s?this.settings.highlightColor:this.settings.areaStrokeColor),this.areaLayer.batchDraw()}),e.on("dragmove",()=>{t.x=e.x(),t.y=e.y(),this.drawConnections(),this.connectionLayer.batchDraw()}),e.on("dragstart",()=>{this.stage.container().style.cursor="grabbing"}),e.on("dragend",()=>{this.stage.container().style.cursor="pointer"}),this.areaLayer.add(e)}}}centerView(){let t=1/0,s=1/0,e=-1/0,i=-1/0;for(const[,u]of this.areaNodes)t=Math.min(t,u.x),s=Math.min(s,u.y),e=Math.max(e,u.x+u.width),i=Math.max(i,u.y+u.height);if(!isFinite(t))return;const o=e-t,n=i-s,r=t+o/2,h=s+n/2,a=50,c=(this.stage.width()-a*2)/o,l=(this.stage.height()-a*2)/n,d=Math.min(c,l,1.5);this.setZoom(d);const g=this.stage.scaleX();this.stage.position({x:this.stage.width()/2-r*g,y:this.stage.height()/2-h*g})}highlightArea(t){this.highlightedArea=t,this.drawAreas(),this.stage.batchDraw()}centerOnArea(t){const s=this.areaNodes.get(t);if(!s)return;const e=this.stage.scaleX(),i=s.x+s.width/2,o=s.y+s.height/2;this.stage.position({x:this.stage.width()/2-i*e,y:this.stage.height()/2-o*e}),this.stage.batchDraw()}emitAreaClickEvent(t){const s=new CustomEvent("areaclick",{detail:{areaId:t}});this.stage.container().dispatchEvent(s)}getAreaNode(t){return this.areaNodes.get(t)}getConnectionGroups(){return this.connectionGroups}destroy(){this.stage.destroy()}}const me={1:"north",2:"northeast",3:"northwest",4:"east",5:"west",6:"south",7:"southeast",8:"southwest",9:"up",10:"down",11:"in",12:"out"},pe=["up","down","in","out"],U={1:"rgb(10, 155, 10)",2:"rgb(226, 205, 59)",3:"rgb(155, 10, 10)"};class Pt{constructor(t,s){this.mapReader=t,this.settings=s,this.exitRenderer=new mt(t,null,s)}getSymbolColor(t,s){return this.settings.frameMode?this.mapReader.getColorValue(t):this.mapReader.getSymbolColor(t,s)}render(t,s,e,i){const o=this.mapReader.getArea(s);if(!o)throw new Error(`Area ${s} not found`);const n=o.getPlane(e);if(!n)throw new Error(`Plane z=${e} not found in area ${s}`);const r=i.padding??3,h=this.computeBounds(o,n,i.roomId,r),a=i.width/h.w,c=i.height/h.h,l=Math.min(a,c);t.save(),t.fillStyle=this.settings.backgroundColor,t.fillRect(0,0,i.width,i.height);const d=h.w*l,g=h.h*l;if(t.translate((i.width-d)/2,(i.height-g)/2),t.scale(l,l),t.translate(-h.x,-h.y),this.settings.gridEnabled){const f=(i.width-d)/2,y=(i.height-g)/2,p={x:h.x-f/l,y:h.y-y/l,w:i.width/l,h:i.height/l};this.renderGrid(t,p)}this.renderLabels(t,n.getLabels()),this.renderLinkExits(t,o,e),this.renderSpecialExits(t,n.getRooms()),this.renderStubs(t,n.getRooms()),this.renderRooms(t,n.getRooms()),this.renderInnerExits(t,n.getRooms());const u=i.overlays;if(u){if(u.paths)for(const f of u.paths)this.renderPathOverlay(t,f.locations,f.color,s,e);if(u.highlights)for(const f of u.highlights)this.renderHighlightOverlay(t,f.roomId,f.color);u.position&&this.renderPositionMarker(t,u.position.roomId)}if(this.settings.areaName){const f=o.getAreaName();if(f){const y=this.getEffectiveBounds(o,n);t.fillStyle="white",t.font=`2.5px ${this.settings.fontFamily}`,t.textAlign="left",t.textBaseline="bottom",t.fillText(f,y.minX-3.5,y.minY-2)}}t.restore()}computeBounds(t,s,e,i){if(e!==void 0){const g=this.mapReader.getRoom(e);if(!g)throw new Error(`Room ${e} not found`);return{x:g.x-i,y:g.y-i,w:i*2,h:i*2}}const o=this.getEffectiveBounds(t,s),n=this.settings.areaName?t.getAreaName():void 0,r=n?7:0,h=n?3.5:0,a=o.minX-h,c=o.minY-r,l=n?o.minX-3.5+n.length*2.5*.6:-1/0,d=Math.max(o.maxX,l);return{x:a-i,y:c-i,w:d-a+i*2,h:o.maxY-c+i*2}}getEffectiveBounds(t,s){return this.settings.uniformLevelSize?t.getFullBounds():s.getBounds()}getRoomEdgePoint(t,s,e,i){return this.settings.roomShape==="circle"?ot(t,s,e,i):this.settings.roomShape==="roundedRectangle"?it(t,s,e,i,this.settings.roomSize*.2):L(t,s,e,i)}renderGrid(t,s){const e=this.settings.gridSize,i=Math.floor(s.x/e)*e,o=Math.ceil((s.x+s.w)/e)*e,n=Math.floor(s.y/e)*e,r=Math.ceil((s.y+s.h)/e)*e;t.strokeStyle=this.settings.gridColor,t.lineWidth=this.settings.gridLineWidth,t.setLineDash([]);for(let h=i;h<=o;h+=e)t.beginPath(),t.moveTo(h,n),t.lineTo(h,r),t.stroke();for(let h=n;h<=r;h+=e)t.beginPath(),t.moveTo(i,h),t.lineTo(o,h),t.stroke()}renderLabels(t,s){for(const e of s){const i=e.X,o=-e.Y;if((e.BgColor?.alpha??0)>0&&!this.settings.transparentLabels){const n=(e.BgColor.alpha??255)/255;t.fillStyle=`rgba(${e.BgColor.r},${e.BgColor.g},${e.BgColor.b},${n})`,t.fillRect(i,o,e.Width,e.Height)}if(e.Text){const n=(e.FgColor?.alpha??255)/255;t.fillStyle=`rgba(${e.FgColor?.r??0},${e.FgColor?.g??0},${e.FgColor?.b??0},${n})`;const r=Math.min(.75,e.Width/Math.max(e.Text.length/2,1)),h=Math.max(.1,Math.min(r,Math.max(e.Height*.9,.1)));t.font=`${h}px ${this.settings.fontFamily}`,t.textAlign="center",t.textBaseline="middle",t.fillText(e.Text,i+e.Width/2,o+e.Height/2)}}}renderLinkExits(t,s,e){const i=s.getLinkExits(e);for(const o of i){const n=this.exitRenderer.renderData(o,e);n&&this.drawExitData(t,n)}}drawExitData(t,s){for(const e of s.lines){t.beginPath(),t.moveTo(e.points[0],e.points[1]);for(let i=2;i<e.points.length;i+=2)t.lineTo(e.points[i],e.points[i+1]);t.strokeStyle=e.stroke,t.lineWidth=e.strokeWidth,t.setLineDash(e.dash??[]),t.stroke()}for(const e of s.arrows){t.beginPath(),t.moveTo(e.points[0],e.points[1]);for(let d=2;d<e.points.length;d+=2)t.lineTo(e.points[d],e.points[d+1]);t.strokeStyle=e.stroke,t.lineWidth=e.strokeWidth,t.setLineDash(e.dash??[]),t.stroke();const i=e.points.length-2,o=e.points[i],n=e.points[i+1],r=e.points[i-2],h=e.points[i-1],a=Math.atan2(n-h,o-r),c=e.pointerLength,l=e.pointerWidth/2;t.beginPath(),t.setLineDash([]),t.moveTo(o,n),t.lineTo(o-c*Math.cos(a-Math.atan2(l,c)),n-c*Math.sin(a-Math.atan2(l,c))),t.lineTo(o-c*Math.cos(a+Math.atan2(l,c)),n-c*Math.sin(a+Math.atan2(l,c))),t.closePath(),t.fillStyle=e.fill,t.fill(),t.strokeStyle=e.stroke,t.lineWidth=e.strokeWidth,t.stroke()}for(const e of s.doors)t.beginPath(),t.rect(e.x,e.y,e.width,e.height),t.strokeStyle=e.stroke,t.lineWidth=e.strokeWidth,t.setLineDash([]),t.stroke()}renderStubs(t,s){t.strokeStyle=this.settings.lineColor,t.lineWidth=this.settings.lineWidth,t.setLineDash([]);for(const e of s)for(const i of e.stubs){const o=me[i];if(!o)continue;const n=this.getRoomEdgePoint(e.x,e.y,o,this.settings.roomSize/2),r=L(e.x,e.y,o,this.settings.roomSize/2+.5);t.beginPath(),t.moveTo(n.x,n.y),t.lineTo(r.x,r.y),t.stroke()}}renderSpecialExits(t,s){for(const e of s)for(const[i,o]of Object.entries(e.customLines)){const n=[e.x,e.y];for(const a of o.points)n.push(a.x,-a.y);const r=`rgb(${o.attributes.color.r}, ${o.attributes.color.g}, ${o.attributes.color.b})`;t.strokeStyle=r,t.lineWidth=this.settings.lineWidth,o.attributes.style==="dot line"?t.setLineDash([.05,.05]):o.attributes.style==="dash line"?t.setLineDash([.4,.2]):t.setLineDash([]),t.beginPath(),t.moveTo(n[0],n[1]);for(let a=2;a<n.length;a+=2)t.lineTo(n[a],n[a+1]);if(t.stroke(),o.attributes.arrow&&n.length>=4){const a=n.length-2,c=n[a],l=n[a+1],d=n[a-2],g=n[a-1],u=Math.atan2(l-g,c-d),f=.3,y=.1;t.beginPath(),t.setLineDash([]),t.moveTo(c,l),t.lineTo(c-f*Math.cos(u-Math.atan2(y,f)),l-f*Math.sin(u-Math.atan2(y,f))),t.lineTo(c-f*Math.cos(u+Math.atan2(y,f)),l-f*Math.sin(u+Math.atan2(y,f))),t.closePath(),t.fillStyle=r,t.fill()}const h=e.doors[i];if(h&&n.length>=4){const a=n[0]+(n[2]-n[0])/2,c=n[1]+(n[3]-n[1])/2,l=this.settings.roomSize/2;t.beginPath(),t.rect(a-l/2,c-l/2,l,l),t.strokeStyle=U[h]??U[3],t.lineWidth=this.settings.lineWidth,t.setLineDash([]),t.stroke()}}}renderRooms(t,s){const e=this.settings.roomSize,i=e/2;for(const o of s){const n=this.mapReader.getColorValue(o.env),r=this.settings.frameMode?this.settings.backgroundColor:n,h=this.settings.frameMode?n:this.settings.lineColor;if(t.fillStyle=r,t.strokeStyle=h,t.lineWidth=this.settings.lineWidth,t.setLineDash([]),this.settings.roomShape==="circle")t.beginPath(),t.arc(o.x,o.y,i,0,Math.PI*2),t.fill(),t.stroke();else{const a=o.x-i,c=o.y-i,l=this.settings.roomShape==="roundedRectangle"?e*.2:0;if(l>0?(this.roundRect(t,a,c,e,e,l),t.fill(),t.stroke()):(t.fillRect(a,c,e,e),t.strokeRect(a,c,e,e)),this.settings.emboss){const d=q(this.settings.lineColor)>.41;t.beginPath(),d?(t.moveTo(a,c),t.lineTo(a+e,c),t.lineTo(a+e,c+e)):(t.moveTo(a,c),t.lineTo(a,c+e),t.lineTo(a+e,c+e)),t.strokeStyle=d?"#000000":"#ffffff",t.lineWidth=this.settings.lineWidth,t.stroke()}}if(o.roomChar){const a=this.getSymbolColor(o.env),c=e*.75;t.fillStyle=a,t.font=`bold ${c}px ${this.settings.fontFamily}`,t.textAlign="left",t.textBaseline="alphabetic";const l=t.measureText(o.roomChar);t.fillText(o.roomChar,o.x-l.width/2,o.y+c*.35)}}}roundRect(t,s,e,i,o,n){t.beginPath(),t.moveTo(s+n,e),t.lineTo(s+i-n,e),t.arcTo(s+i,e,s+i,e+n,n),t.lineTo(s+i,e+o-n),t.arcTo(s+i,e+o,s+i-n,e+o,n),t.lineTo(s+n,e+o),t.arcTo(s,e+o,s,e+o-n,n),t.lineTo(s,e+n),t.arcTo(s,e,s+n,e,n),t.closePath()}renderInnerExits(t,s){const e=this.settings.roomSize,i=e/5;for(const o of s)for(const n of pe){if(!o.exits[n])continue;const r=this.getSymbolColor(o.env),h=this.getSymbolColor(o.env,.6),a=o.doors[n],c=a!==void 0?U[a]??U[3]:r;switch(n){case"up":{const l=L(o.x,o.y,"south",e/4);this.drawTriangle(t,l.x,l.y,i,0,h,c);break}case"down":{const l=L(o.x,o.y,"north",e/4);this.drawTriangle(t,l.x,l.y,i,180,h,c);break}case"in":{const l=L(o.x,o.y,"west",e/4),d=L(o.x,o.y,"east",e/4);this.drawTriangle(t,l.x,l.y,i,90,h,c),this.drawTriangle(t,d.x,d.y,i,-90,h,c);break}case"out":{const l=L(o.x,o.y,"west",e/4),d=L(o.x,o.y,"east",e/4);this.drawTriangle(t,l.x,l.y,i,-90,h,c),this.drawTriangle(t,d.x,d.y,i,90,h,c);break}}}}drawTriangle(t,s,e,i,o,n,r){const c=o*Math.PI/180;t.beginPath();for(let l=0;l<3;l++){const d=2*Math.PI*l/3-Math.PI/2;let g=Math.cos(d)*i*1.4,u=Math.sin(d)*i*.8;const f=g*Math.cos(c)-u*Math.sin(c),y=g*Math.sin(c)+u*Math.cos(c);l===0?t.moveTo(s+f,e+y):t.lineTo(s+f,e+y)}t.closePath(),t.fillStyle=n,t.fill(),t.strokeStyle=r,t.lineWidth=this.settings.lineWidth,t.stroke()}renderPathOverlay(t,s,e,i,o){const n=nt(this.mapReader,this.settings,s,i,o),r=this.settings.lineWidth;t.save(),t.globalAlpha=.8,t.lineCap="round",t.lineJoin="round",t.setLineDash([]);const h=c=>{if(!(c.length<4)){t.beginPath(),t.moveTo(c[0],c[1]);for(let l=2;l<c.length;l+=2)t.lineTo(c[l],c[l+1]);t.strokeStyle="black",t.lineWidth=r*8,t.stroke(),t.beginPath(),t.moveTo(c[0],c[1]);for(let l=2;l<c.length;l+=2)t.lineTo(c[l],c[l+1]);t.strokeStyle=e,t.lineWidth=r*4,t.stroke()}};for(const c of n.segments)h(c.points);for(const c of n.customLines)h(c.points);const a=this.settings.roomSize/5;for(const c of n.innerMarkers){const l=c.direction==="up"?0:c.direction==="down"?180:c.direction==="in"?90:-90;this.drawTriangle(t,c.room.x,c.room.y,a,l,e,"black")}t.restore()}renderHighlightOverlay(t,s,e){const i=this.mapReader.getRoom(s);if(!i)return;const o=1.5,n=this.settings.roomSize;if(t.strokeStyle=e,t.lineWidth=.1,t.setLineDash([.05,.05]),this.settings.roomShape==="circle")t.beginPath(),t.arc(i.x,i.y,n/2*o,0,Math.PI*2),t.stroke();else{const r=n*o;t.strokeRect(i.x-r/2,i.y-r/2,r,r)}t.setLineDash([])}renderPositionMarker(t,s){const e=this.mapReader.getRoom(s);if(!e)return;const i=this.settings.playerMarker,o=this.settings.roomSize*i.sizeFactor;t.save(),t.globalAlpha=i.strokeAlpha,t.strokeStyle=i.strokeColor,t.lineWidth=i.strokeWidth,t.setLineDash(i.dashEnabled&&i.dash?i.dash:[]),t.beginPath(),t.arc(e.x,e.y,o/2,0,Math.PI*2),t.stroke(),i.fillAlpha>0&&(t.globalAlpha=i.fillAlpha,t.fillStyle=i.fillColor,t.fill()),t.restore()}}class ye{constructor(t,s){this.highlights=new Map,this.paths=[],this.mapReader=t,this.settings=s??yt()}drawArea(t,s){const e=this.mapReader.getArea(t);!e||!e.getPlane(s)||(this.currentArea=t,this.currentAreaInstance=e,this.currentZIndex=s)}getCurrentArea(){return this.currentAreaInstance}setPosition(t){this.positionRoomId=t}clearPosition(){this.positionRoomId=void 0}renderPath(t,s="#66E64D"){this.paths.push({locations:t,color:s})}clearPaths(){this.paths=[]}renderHighlight(t,s){const e=this.mapReader.getRoom(t);e&&this.highlights.set(t,{color:s,area:e.area,z:e.z})}removeHighlight(t){this.highlights.delete(t)}hasHighlight(t){return this.highlights.has(t)}clearHighlights(){this.highlights.clear()}exportSvg(t){if(this.currentArea===void 0||this.currentZIndex===void 0)return;const s={...t,overlays:this.buildOverlays(t?.overlays)};return new pt(this.mapReader,this.settings).export(this.currentArea,this.currentZIndex,s)}renderToCanvas(t,s){if(this.currentArea===void 0||this.currentZIndex===void 0)return;const e={...s,overlays:this.buildOverlays(s?.overlays)};new Pt(this.mapReader,this.settings).render(t,this.currentArea,this.currentZIndex,e)}buildOverlays(t){const s={...t};if(this.positionRoomId!==void 0){const o=this.mapReader.getRoom(this.positionRoomId);o&&o.area===this.currentArea&&o.z===this.currentZIndex&&(s.position={roomId:this.positionRoomId})}const e=[...t?.highlights??[]];for(const[o,n]of this.highlights)n.area===this.currentArea&&n.z===this.currentZIndex&&e.push({roomId:o,color:n.color});e.length>0&&(s.highlights=e);const i=[...t?.paths??[]];return i.push(...this.paths),i.length>0&&(s.paths=i),s}}exports.AreaMapRenderer=fe;exports.CanvasExporter=Pt;exports.ExplorationArea=J;exports.HeadlessRenderer=ye;exports.MapReader=Qt;exports.PathFinder=ge;exports.Renderer=Kt;exports.SvgExporter=pt;exports.colorLightness=q;exports.computePathData=nt;exports.createAreaMapSettings=$t;exports.createSettings=yt;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const b=require("konva"),V=["north","south","east","west","northeast","northwest","southeast","southwest"],At={n:"north",s:"south",e:"east",w:"west",ne:"northeast",nw:"northwest",se:"southeast",sw:"southwest"},N={north:"n",south:"s",east:"e",west:"w",northeast:"ne",northwest:"nw",southeast:"se",southwest:"sw",up:"u",down:"d",in:"i",out:"o"},st={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}},ut=["north","south","east","west","northeast","northwest","southeast","southwest"],Lt={north:"south",south:"north",east:"west",west:"east",northeast:"southwest",northwest:"southeast",southeast:"northwest",southwest:"northeast"};function ft(m){return m?Object.prototype.hasOwnProperty.call(st,m):!1}function L(m,t,s,e=1){if(!ft(s))return{x:m,y:t};const i=st[s];return{x:m+i.x*e,y:t+i.y*e}}function it(m,t,s,e=1,i=0){if(!ft(s))return{x:m,y:t};const o=st[s];if(!(o.x!==0&&o.y!==0)||i<=0)return L(m,t,s,e);const r=e-i+i/Math.SQRT2;return{x:m+o.x*r,y:t+o.y*r}}function ot(m,t,s,e=1){if(!ft(s))return{x:m,y:t};const i=st[s],o=Math.atan2(i.y,i.x);return{x:m+Math.cos(o)*e,y:t+Math.sin(o)*e}}const H={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)"},Xt={1:"north",2:"northeast",3:"northwest",4:"east",5:"west",6:"south",7:"southeast",8:"southwest",9:"up",10:"down",11:"in",12:"out"},Wt=["up","down","in","out"];function xt(m){switch(m){case 1:return H.OPEN_DOOR;case 2:return H.CLOSED_DOOR;default:return H.LOCKED_DOOR}}class mt{constructor(t,s,e){this.mapReader=t,this.mapRenderer=s,this.settings=e}getRoomEdgePoint(t,s,e,i){return this.settings.roomShape==="circle"?ot(t,s,e,i):this.settings.roomShape==="roundedRectangle"?it(t,s,e,i,this.settings.roomSize*.2):L(t,s,e,i)}renderData(t,s){return this.renderDataWithColor(t,this.settings.lineColor,s)}renderDataWithColor(t,s,e){const i=t.aDir&&V.includes(t.aDir),o=t.bDir&&V.includes(t.bDir);if(i&&o)return this.renderTwoWayExitData(t,s,e);if(i||o){const n=i?"a":"b";return this.renderOneWayExitData(t,s,n)}}renderTwoWayExitData(t,s,e){const i=this.mapReader.getRoom(t.a),o=this.mapReader.getRoom(t.b);if(!i||!o||!t.aDir||!t.bDir||i.customLines[N[t.aDir]]&&o.customLines[N[t.bDir]]||i.z!==o.z&&(e!==o.z&&i.customLines[N[t.aDir]]||e!==i.z&&o.customLines[N[t.bDir]]))return;const n=this.getRoomEdgePoint(i.x,i.y,t.aDir,this.settings.roomSize/2),r=this.getRoomEdgePoint(o.x,o.y,t.bDir,this.settings.roomSize/2),h=[n.x,n.y,r.x,r.y],a=[{points:h,stroke:s,strokeWidth:this.settings.lineWidth}],c=[],l=i.doors[N[t.aDir]]??o.doors[N[t.bDir]];if(l){const p=h[0]+(h[2]-h[0])/2,x=h[1]+(h[3]-h[1])/2;c.push({x:p-this.settings.roomSize/4,y:x-this.settings.roomSize/4,width:this.settings.roomSize/2,height:this.settings.roomSize/2,stroke:xt(l),strokeWidth:this.settings.lineWidth})}const d=Math.min(h[0],h[2]),g=Math.max(h[0],h[2]),u=Math.min(h[1],h[3]),f=Math.max(h[1],h[3]),y=i.z!==o.z?i.z===e?o.id:i.id:void 0;return{lines:a,arrows:[],doors:c,bounds:{x:d,y:u,width:g-d,height:f-u},targetRoomId:y}}renderOneWayExitData(t,s,e){const i=e==="a"||!e&&t.aDir,o=i?this.mapReader.getRoom(t.a):this.mapReader.getRoom(t.b),n=i?this.mapReader.getRoom(t.b):this.mapReader.getRoom(t.a),r=i?t.aDir:t.bDir;if(!r||!o||!n||!V.includes(r)||o.customLines[N[r]||r])return;if(o.area!=n.area&&r){const $=this.mapReader.getColorValue(n.env),X=this.getRoomEdgePoint(o.x,o.y,r,this.settings.roomSize/2),w=L(o.x,o.y,r,this.settings.roomSize*1.5),R=$;return{lines:[],arrows:[{points:[X.x,X.y,w.x,w.y],pointerLength:.3,pointerWidth:.3,strokeWidth:this.settings.lineWidth*1.4,stroke:R,fill:R}],doors:[],bounds:{x:Math.min(X.x,w.x),y:Math.min(X.y,w.y),width:Math.abs(w.x-X.x),height:Math.abs(w.y-X.y)},targetRoomId:n.id}}const h=n.area!==o.area||n.z!==o.z;let a={x:n.x,y:n.y};h&&(a=L(o.x,o.y,r,this.settings.roomSize/2));const c=L(o.x,o.y,r,.3),l=c.x-(c.x-a.x)/2,d=c.y-(c.y-a.y)/2,g=this.getRoomEdgePoint(o.x,o.y,r,this.settings.roomSize/2),u=[g.x,g.y,a.x,a.y],f=[g.x,a.x,l],y=[g.y,a.y,d],p=Math.min(...f),x=Math.max(...f),k=Math.min(...y),D=Math.max(...y);return{lines:[{points:u,stroke:s,strokeWidth:this.settings.lineWidth,dash:[.1,.05]}],arrows:[{points:[u[0],u[1],l,d],pointerLength:.5,pointerWidth:.35,strokeWidth:this.settings.lineWidth*1.4,stroke:s,fill:H.ONE_WAY_FILL,dash:[.1,.05]}],doors:[],bounds:{x:p,y:k,width:x-p,height:D-k},...h?{targetRoomId:n.id}:{}}}render(t,s){return this.renderWithColor(t,this.settings.lineColor,s)}renderWithColor(t,s,e){const i=t.aDir&&V.includes(t.aDir),o=t.bDir&&V.includes(t.bDir);if(i&&o)return this.renderTwoWayExit(t,s,e);if(i||o){const n=i?"a":"b";return this.renderOneWayExit(t,s,n)}}renderTwoWayExit(t,s,e){const i=this.mapReader.getRoom(t.a),o=this.mapReader.getRoom(t.b);if(!i||!o||!t.aDir||!t.bDir||i.customLines[N[t.aDir]]&&o.customLines[N[t.bDir]]||i.z!==o.z&&(e!==o.z&&i.customLines[N[t.aDir]]||e!==i.z&&o.customLines[N[t.bDir]]))return;const n=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(o.x,o.y,t.bDir,this.settings.roomSize/2))),i.doors[N[t.aDir]]||o.doors[N[t.bDir]]){const a=this.renderDoor(r,i.doors[N[t.aDir]]??o.doors[N[t.bDir]]);n.add(a)}const h=new b.Line({points:r,stroke:s,strokeWidth:this.settings.lineWidth,perfectDrawEnabled:!1,listening:!1});return n.add(h),n}renderOneWayExit(t,s,e){const i=e==="a"||!e&&t.aDir,o=i?this.mapReader.getRoom(t.a):this.mapReader.getRoom(t.b),n=i?this.mapReader.getRoom(t.b):this.mapReader.getRoom(t.a),r=i?t.aDir:t.bDir;if(!r||!o||!n||!V.includes(r)||o.customLines[N[r]||r])return;if(o.area!=n.area&&r){const y=this.mapReader.getColorValue(n.env);return this.renderAreaExit(o,r,y)}let h={x:n.x,y:n.y};(n.area!==o.area||n.z!==o.z)&&(h=L(o.x,o.y,r,this.settings.roomSize/2));const a=L(o.x,o.y,r,.3),c=a.x-(a.x-h.x)/2,l=a.y-(a.y-h.y)/2,d=new b.Group({listening:!1}),g=[];g.push(...Object.values(this.getRoomEdgePoint(o.x,o.y,r,this.settings.roomSize/2))),g.push(h.x,h.y);const u=new b.Line({points:g,stroke:s,strokeWidth:this.settings.lineWidth,dashEnabled:!0,dash:[.1,.05],perfectDrawEnabled:!1,listening:!1});d.add(u);const f=new b.Arrow({points:[g[0],g[1],c,l],pointerLength:.5,pointerWidth:.35,strokeWidth:this.settings.lineWidth*1.4,stroke:s,fill:H.ONE_WAY_FILL,dashEnabled:!0,dash:[.1,.05],perfectDrawEnabled:!1,listening:!1});return d.add(f),d}renderAreaExit(t,s,e){const i=this.getRoomEdgePoint(t.x,t.y,s,this.settings.roomSize/2),o=L(t.x,t.y,s,this.settings.roomSize*1.5),n=e??this.mapReader.getColorValue(t.env);return new b.Arrow({points:[i.x,i.y,o.x,o.y],pointerLength:.3,pointerWidth:.3,strokeWidth:this.settings.lineWidth*1.4,stroke:n,fill:n,perfectDrawEnabled:!1,listening:!1})}renderSpecialExits(t,s){return Object.entries(t.customLines).flatMap(([e,i])=>{const o=[t.x,t.y];i.points.reduce((d,g)=>(d.push(g.x,-g.y),d),o);const n=i.attributes.arrow?b.Arrow:b.Line,r=s??`rgb(${i.attributes.color.r}, ${i.attributes.color.g}, ${i.attributes.color.b})`,h=new n({points:o,strokeWidth:this.settings.lineWidth,stroke:r,fill:s??`rgb(${i.attributes.color.r}, ${i.attributes.color.g} , ${i.attributes.color.b})`,pointerLength:.3,pointerWidth:.2,perfectDrawEnabled:!1,listening:!1});let a=i.attributes.style;a==="dot line"?(h.dash([.05,.05]),h.dashOffset(.1)):a==="dash line"?h.dash([.4,.2]):a==="solid line"||a!==void 0&&console.log("Brak opisu stylu: "+a);const c=[h],l=t.doors[e];return l&&o.length>=4&&c.push(this.renderDoor(o,l)),c})}getSpecialExitAreaTargets(t){const s=[];for(const[e,i]of Object.entries(t.customLines)){let o=t.specialExits[e];if(o===void 0){const d=At[e];d&&(o=t.exits[d]??t.specialExits[d])}if(o===void 0)continue;const n=this.mapReader.getRoom(o);if(!n||n.area===t.area&&n.z===t.z)continue;const r=[t.x,t.y];i.points.reduce((d,g)=>(d.push(g.x,-g.y),d),r);let h=1/0,a=1/0,c=-1/0,l=-1/0;for(let d=0;d<r.length;d+=2)h=Math.min(h,r[d]),c=Math.max(c,r[d]),a=Math.min(a,r[d+1]),l=Math.max(l,r[d+1]);s.push({bounds:{x:h,y:a,width:c-h,height:l-a},targetRoomId:o})}return s}renderStubs(t,s=this.settings.lineColor){return t.stubs.map(e=>{const i=Xt[e],o=this.getRoomEdgePoint(t.x,t.y,i,this.settings.roomSize/2),n=L(t.x,t.y,i,this.settings.roomSize/2+.5),r=[o.x,o.y,n.x,n.y];return new b.Line({points:r,stroke:s,strokeWidth:this.settings.lineWidth,perfectDrawEnabled:!1,listening:!1})})}getSymbolColor(t,s){return this.settings.frameMode?this.mapReader.getColorValue(t):this.mapReader.getSymbolColor(t,s)}renderInnerExits(t){return Wt.map(s=>{if(t.exits[s]){const e=new b.Group({listening:!1}),i=new b.RegularPolygon({x:t.x,y:t.y,sides:3,fill:this.getSymbolColor(t.env,.6),stroke:this.getSymbolColor(t.env),strokeWidth:this.settings.lineWidth,radius:this.settings.roomSize/5,scaleX:1.4,scaleY:.8,perfectDrawEnabled:!1,listening:!1});e.add(i);let o=t.doors[s];if(o!==void 0)switch(o){case 1:i.stroke(H.OPEN_DOOR);break;case 2:i.stroke(H.CLOSED_DOOR);break;default:i.stroke(H.LOCKED_DOOR)}const n=i.stroke();switch(s){case"up":i.position(L(t.x,t.y,"south",this.settings.roomSize/4));break;case"down":i.rotation(180),i.position(L(t.x,t.y,"north",this.settings.roomSize/4));break;case"in":{i.rotation(90),i.position(L(t.x,t.y,"west",this.settings.roomSize/4));const r=L(t.x,t.y,"east",this.settings.roomSize/4);e.add(new b.RegularPolygon({x:r.x,y:r.y,sides:3,fill:i.fill(),stroke:n,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(L(t.x,t.y,"west",this.settings.roomSize/4));const r=L(t.x,t.y,"east",this.settings.roomSize/4);e.add(new b.RegularPolygon({x:r.x,y:r.y,sides:3,fill:i.fill(),stroke:n,strokeWidth:this.settings.lineWidth,radius:this.settings.roomSize/5,scaleX:1.4,scaleY:.8,rotation:90,perfectDrawEnabled:!1,listening:!1}));break}}return e}}).filter(s=>s!==void 0)}renderDoor(t,s){const e={x:t[0]+(t[2]-t[0])/2,y:t[1]+(t[3]-t[1])/2};return new b.Rect({x:e.x-this.settings.roomSize/4,y:e.y-this.settings.roomSize/4,width:this.settings.roomSize/2,height:this.settings.roomSize/2,stroke:xt(s),strokeWidth:this.settings.lineWidth,perfectDrawEnabled:!1,listening:!1})}}class zt{constructor(t,s){this.rooms=[],this.labels=[],this.rooms=t,this.labels=s,this.bounds=this.createBounds()}getRooms(){return this.rooms}getLabels(){return this.labels}getBounds(){return this.bounds}createBounds(){const t=this.rooms.reduce((s,e)=>({minX:Math.min(s.minX,e.x),maxX:Math.max(s.maxX,e.x),minY:Math.min(s.minY,e.y),maxY:Math.max(s.maxY,e.y)}),{minX:Number.POSITIVE_INFINITY,maxX:Number.NEGATIVE_INFINITY,minY:Number.POSITIVE_INFINITY,maxY:Number.NEGATIVE_INFINITY});for(const s of this.labels){const e=s.X,i=-s.Y;t.minX=Math.min(t.minX,e),t.maxX=Math.max(t.maxX,e+s.Width),t.minY=Math.min(t.minY,i),t.maxY=Math.max(t.maxY,i+s.Height)}return t}}const et=class et{constructor(t){this.planes={},this.exits=new Map,this.version=0,this.area=t,this.planes=this.createPlanes(),this.createExits()}getAreaName(){return this.area.areaName}getAreaId(){return parseInt(this.area.areaId)}getVersion(){return this.version}markDirty(){this.version++}getPlane(t){return this.planes[t]}getPlanes(){return Object.values(this.planes)}getZLevels(){return Object.keys(this.planes).map(Number).sort((t,s)=>t-s)}getRooms(){return this.area.rooms}getFullBounds(){return this.getPlanes().reduce((t,s)=>{const e=s.getBounds();return{minX:Math.min(t.minX,e.minX),maxX:Math.max(t.maxX,e.maxX),minY:Math.min(t.minY,e.minY),maxY:Math.max(t.maxY,e.maxY)}},{minX:1/0,maxX:-1/0,minY:1/0,maxY:-1/0})}getLinkExits(t){return Array.from(this.exits.values()).filter(s=>s.zIndex.includes(t))}createPlanes(){const t=this.area.rooms.reduce((s,e)=>(s[e.z]||(s[e.z]=[]),s[e.z].push(e),s),{});return Object.entries(t).reduce((s,[e,i])=>(s[+e]=new zt(i,this.area.labels.filter(o=>o.Z===+e)),s),{})}createExits(){const t=new Map;this.area.rooms.forEach(s=>{Object.entries(s.exits).forEach(([e,i])=>{if(s.id===i)return;const o=Math.min(s.id,i),n=Math.max(s.id,i),r=`${o}-${n}`;t.has(r)||t.set(r,[]),t.get(r).push({origin:s.id,target:i,z:s.z,dir:e})})});for(const[s,e]of t){const[i,o]=s.split("-"),n=parseInt(i),r=parseInt(o),h=e.filter(l=>l.origin===n),a=e.filter(l=>l.origin===r),c=new Set;for(const l of h){let d=-1;for(let g=0;g<a.length;g++)if(!c.has(g)){if(a[g].dir===et.oppositeDir[l.dir]){d=g;break}d===-1&&(d=g)}if(d!==-1){c.add(d);const g=a[d];this.exits.set(`${s}-${l.dir}`,{a:n,b:r,aDir:l.dir,bDir:g.dir,zIndex:[l.z,g.z]})}else this.exits.set(`${s}-a:${l.dir}`,{a:n,b:r,aDir:l.dir,zIndex:[l.z]})}for(let l=0;l<a.length;l++)if(!c.has(l)){const d=a[l];this.exits.set(`${s}-b:${d.dir}`,{a:n,b:r,bDir:d.dir,zIndex:[d.z]})}}}};et.oppositeDir={north:"south",south:"north",east:"west",west:"east",northeast:"southwest",southwest:"northeast",northwest:"southeast",southeast:"northwest",up:"down",down:"up",in:"out",out:"in"};let _=et;class bt extends zt{constructor(t,s){super(t.getRooms(),t.getLabels()),this.basePlane=t,this.visitedRooms=s}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((s,e)=>({minX:Math.min(s.minX,e.x),maxX:Math.max(s.maxX,e.x),minY:Math.min(s.minY,e.y),maxY:Math.max(s.maxY,e.y)}),{minX:Number.POSITIVE_INFINITY,maxX:Number.NEGATIVE_INFINITY,minY:Number.POSITIVE_INFINITY,maxY:Number.NEGATIVE_INFINITY}):this.basePlane.getBounds()}}class J extends _{constructor(t,s){super(t),this.planeCache=new WeakMap,this.visitedRooms=s instanceof Set?s:new Set(s??[]),this.areaRoomIds=new Set(t.rooms.map(e=>e.id))}getPlane(t){const s=super.getPlane(t);if(!s)return s;let e=this.planeCache.get(s);return e||(e=new bt(s,this.visitedRooms),this.planeCache.set(s,e)),e}getPlanes(){return super.getPlanes().map(t=>{let s=this.planeCache.get(t);return s||(s=new bt(t,this.visitedRooms),this.planeCache.set(t,s)),s})}getLinkExits(t){return super.getLinkExits(t).filter(s=>this.visitedRooms.has(s.a)||this.visitedRooms.has(s.b))}getVisitedRoomCount(){return super.getRooms().reduce((t,s)=>t+(this.visitedRooms.has(s.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 s=this.visitedRooms.has(t);this.visitedRooms.add(t);const e=!s&&this.areaRoomIds.has(t);return e&&this.markDirty(),e}addVisitedRooms(t){let s=0;for(const e of t){const i=this.visitedRooms.has(e);this.visitedRooms.add(e),!i&&this.areaRoomIds.has(e)&&s++}return s>0&&this.markDirty(),s}}const G=["up","down","in","out"];function tt(m,t,s,e,i){return m.roomShape==="circle"?ot(t,s,e,i):m.roomShape==="roundedRectangle"?it(t,s,e,i,m.roomSize*.2):L(t,s,e,i)}function Yt(m,t,s){for(const[e,i]of Object.entries(t.exits))if(i===s.id){const o=e;if(G.includes(o)){const h=N[o],a=t.customLines[h]?h:t.customLines[o]?o:void 0;return{type:"inner",fromDir:o,customLineKey:a,fromRoom:t,toRoom:s}}const n=N[o];if(t.customLines[n])return{type:"special",fromDir:o,customLineKey:n,fromRoom:t,toRoom:s};if(t.customLines[o])return{type:"special",fromDir:o,customLineKey:o,fromRoom:t,toRoom:s};const r=Nt(s,t.id);return{type:"regular",fromDir:o,toDir:r,fromRoom:t,toRoom:s}}for(const[e,i]of Object.entries(t.specialExits))if(i===s.id)return t.customLines[e]?{type:"special",customLineKey:e,fromRoom:t,toRoom:s}:{type:"inner",fromRoom:t,toRoom:s};for(const[e,i]of Object.entries(s.exits))if(i===t.id){const o=e;if(G.includes(o)){const r=N[o],h=s.customLines[r]?r:s.customLines[o]?o:void 0;return{type:"inner",toDir:o,customLineKey:h,fromRoom:t,toRoom:s}}const n=N[o];return s.customLines[n]?{type:"special",toDir:o,customLineKey:n,fromRoom:t,toRoom:s}:s.customLines[o]?{type:"special",toDir:o,customLineKey:o,fromRoom:t,toRoom:s}:{type:"regular",toDir:o,fromRoom:t,toRoom:s}}for(const[e,i]of Object.entries(s.specialExits))if(i===t.id)return s.customLines[e]?{type:"special",customLineKey:e,fromRoom:t,toRoom:s}:{type:"inner",fromRoom:t,toRoom:s};return{type:"none",fromRoom:t,toRoom:s}}function Nt(m,t){for(const[s,e]of Object.entries(m.exits))if(e===t)return s}function wt(m,t,s){return m?m.area===t&&m.z===s:!1}function Tt(m,t){for(const[s,e]of Object.entries(m.exits))if(e===t.id)return{direction:s};for(const[s,e]of Object.entries(m.specialExits))if(e===t.id)return}function Ot(m,t){for(const s of ut)if(m.exits[s]===t.id)return s;for(const s of ut)if(t.exits[s]===m.id)return Lt[s]}function Bt(m,t,s){const{fromRoom:e,toRoom:i,fromDir:o,toDir:n}=t;if(s.length===0&&s.push(e.x,e.y),o&&V.includes(o)){const r=tt(m,e.x,e.y,o,m.roomSize/2);s.push(r.x,r.y)}if(n&&V.includes(n)){const r=tt(m,i.x,i.y,n,m.roomSize/2);s.push(r.x,r.y)}s.push(i.x,i.y)}function Ft(m,t){const{fromRoom:s,toRoom:e,customLineKey:i}=m;let o=s,n;i&&(n=s.customLines[i],n||(n=e.customLines[i],o=e)),t.length===0&&t.push(o.x,o.y),n&&n.points.forEach(r=>{t.push(r.x,-r.y)}),t.push(e.x,e.y)}function nt(m,t,s,e,i){const o=[],n=[],r=[],h=s.map(d=>m.getRoom(d)).filter(d=>d!==void 0);let a=[];const c=()=>{a.length>=4&&o.push({points:[...a]}),a=[]},l=d=>{const{fromRoom:g,toRoom:u,fromDir:f,toDir:y,customLineKey:p}=d;if(p){let x=g,k=g.customLines[p];if(k||(k=u.customLines[p],x=u),k){const D=[x.x,x.y];k.points.forEach($=>{D.push($.x,-$.y)}),r.push({points:D})}}f&&G.includes(f)&&n.push({room:g,direction:f}),y&&G.includes(y)&&n.push({room:u,direction:y})};for(let d=0;d<h.length-1;d++){const g=h[d],u=h[d+1],f=wt(g,e,i),y=wt(u,e,i);if(!f&&!y){c();continue}if(f&&y){const p=Yt(m,g,u);switch(p.type){case"regular":Bt(t,p,a);break;case"special":Ft(p,a);break;case"inner":c(),l(p);break;case"none":a.length===0&&a.push(g.x,g.y),a.push(u.x,u.y);break}}else{const p=f?g:u,x=f?u:g,k=Tt(p,x);if(k){if(G.includes(k.direction))c(),n.push({room:p,direction:k.direction});else if(V.includes(k.direction)){a.length===0&&a.push(p.x,p.y);const D=tt(t,p.x,p.y,k.direction,t.roomSize/2),$=L(p.x,p.y,k.direction,t.roomSize);a.push(D.x,D.y,$.x,$.y),c()}}else{const D=Ot(p,x);if(D){a.length===0&&a.push(p.x,p.y);const $=tt(t,p.x,p.y,D,t.roomSize/2),X=L(p.x,p.y,D,t.roomSize);a.push($.x,$.y,X.x,X.y),c()}}}}return c(),{segments:o,innerMarkers:n,customLines:r}}class Zt{constructor(t,s,e){this.paths=[],this.mapReader=t,this.overlayLayer=s,this.settings=e}createStrokedLine(t,s){const e=new b.Group;return e.opacity(.8),e.add(new b.Line({points:t,stroke:"black",strokeWidth:this.settings.lineWidth*8,lineCap:"round",lineJoin:"round"})),e.add(new b.Line({points:t,stroke:s,strokeWidth:this.settings.lineWidth*4,lineCap:"round",lineJoin:"round"})),e}renderInnerExitMarker(t,s,e){const i=new b.Group;i.opacity(.8);const o=new b.RegularPolygon({x:t.x,y:t.y,sides:3,fill:e,stroke:"black",strokeWidth:this.settings.lineWidth*2,radius:this.settings.roomSize/5,scaleX:1.4,scaleY:.8});switch(s){case"up":o.position(L(t.x,t.y,"south",this.settings.roomSize/4));break;case"down":o.rotation(180),o.position(L(t.x,t.y,"north",this.settings.roomSize/4));break;case"in":{const n=o.clone();n.rotation(-90),n.position(L(t.x,t.y,"east",this.settings.roomSize/4)),i.add(n),o.rotation(90),o.position(L(t.x,t.y,"west",this.settings.roomSize/4));break}case"out":{const n=o.clone();n.rotation(90),n.position(L(t.x,t.y,"east",this.settings.roomSize/4)),i.add(n),o.rotation(-90),o.position(L(t.x,t.y,"west",this.settings.roomSize/4));break}}return i.add(o),i}renderPath(t,s,e,i="#66E64D"){if(s===void 0||e===void 0)return;const o=nt(this.mapReader,this.settings,t,s,e);for(const n of o.segments){const r=this.createStrokedLine(n.points,i);this.overlayLayer.add(r),this.paths.push(r)}for(const n of o.customLines){const r=this.createStrokedLine(n.points,i);this.overlayLayer.add(r),this.paths.push(r)}for(const n of o.innerMarkers){const r=this.renderInnerExitMarker(n.room,n.direction,i);this.overlayLayer.add(r),this.paths.push(r)}return this.paths[0]}clearPaths(){this.paths.forEach(t=>{t.destroy()}),this.paths=[]}}const 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"},jt=["up","down","in","out"],at={OPEN:"rgb(10, 155, 10)",CLOSED:"rgb(226, 205, 59)",LOCKED:"rgb(155, 10, 10)"};function vt(m){switch(m){case 1:return at.OPEN;case 2:return at.CLOSED;default:return at.LOCKED}}function A(m){return m.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#39;")}class pt{constructor(t,s){this.mapReader=t,this.settings=s,this.exitRenderer=new mt(t,null,s)}getSymbolColor(t,s){return this.settings.frameMode?this.mapReader.getColorValue(t):this.mapReader.getSymbolColor(t,s)}export(t,s,e){const i=this.mapReader.getArea(t);if(!i)throw new Error(`Area ${t} not found`);const o=i.getPlane(s);if(!o)throw new Error(`Plane z=${s} not found in area ${t}`);const n=e?.padding??3,r=this.computeBounds(i,o,e?.roomId,n),h=[];h.push(`<svg xmlns="http://www.w3.org/2000/svg" viewBox="${r.x} ${r.y} ${r.w} ${r.h}">`),h.push(`<rect x="${r.x}" y="${r.y}" width="${r.w}" height="${r.h}" fill="${A(this.settings.backgroundColor)}"/>`),this.settings.gridEnabled&&this.renderGrid(h,r),this.renderLabels(h,o.getLabels()),this.renderLinkExits(h,i,s);const a=o.getRooms();this.renderSpecialExits(h,a),this.renderStubs(h,a),this.renderRooms(h,a),this.renderInnerExits(h,a);const c=e?.overlays;if(c){if(c.paths)for(const l of c.paths)this.renderPathOverlay(h,l.locations,l.color,t,s);if(c.highlights)for(const l of c.highlights)this.renderHighlightOverlay(h,l.roomId,l.color);c.position&&this.renderPositionMarker(h,c.position.roomId)}if(this.settings.areaName){const l=i.getAreaName();if(l){const d=this.getEffectiveBounds(i,o);h.push(`<text x="${d.minX-3.5}" y="${d.minY-2}" font-size="2.5" font-family="${A(this.settings.fontFamily)}" fill="white">${A(l)}</text>`)}}return h.push("</svg>"),h.join(`
2
+ `)}computeBounds(t,s,e,i){if(e!==void 0){const g=this.mapReader.getRoom(e);if(!g)throw new Error(`Room ${e} not found`);return{x:g.x-i,y:g.y-i,w:i*2,h:i*2}}const o=this.getEffectiveBounds(t,s),n=this.settings.areaName?t.getAreaName():void 0,r=n?7:0,h=n?3.5:0,a=o.minX-h,c=o.minY-r,l=n?o.minX-3.5+n.length*2.5*.6:-1/0,d=Math.max(o.maxX,l);return{x:a-i,y:c-i,w:d-a+i*2,h:o.maxY-c+i*2}}getEffectiveBounds(t,s){return this.settings.uniformLevelSize?t.getFullBounds():s.getBounds()}getRoomEdgePoint(t,s,e,i){return this.settings.roomShape==="circle"?ot(t,s,e,i):this.settings.roomShape==="roundedRectangle"?it(t,s,e,i,this.settings.roomSize*.2):L(t,s,e,i)}renderGrid(t,s){const e=this.settings.gridSize,i=Math.floor(s.x/e)*e,o=Math.ceil((s.x+s.w)/e)*e,n=Math.floor(s.y/e)*e,r=Math.ceil((s.y+s.h)/e)*e,h=A(this.settings.gridColor),a=this.settings.gridLineWidth;for(let c=i;c<=o;c+=e)t.push(`<line x1="${c}" y1="${n}" x2="${c}" y2="${r}" stroke="${h}" stroke-width="${a}"/>`);for(let c=n;c<=r;c+=e)t.push(`<line x1="${i}" y1="${c}" x2="${o}" y2="${c}" stroke="${h}" stroke-width="${a}"/>`)}renderLabels(t,s){for(const e of s){const i=e.X,o=-e.Y;if(this.settings.labelRenderMode==="image"&&e.pixMap){t.push(`<image x="${i}" y="${o}" width="${e.Width}" height="${e.Height}" href="data:image/png;base64,${e.pixMap}"/>`);continue}if((e.BgColor?.alpha??0)>0&&!this.settings.transparentLabels){const n=this.labelColor(e.BgColor);t.push(`<rect x="${i}" y="${o}" width="${e.Width}" height="${e.Height}" fill="${n}"/>`)}if(e.Text){const n=this.labelColor(e.FgColor),r=Math.min(.75,e.Width/Math.max(e.Text.length/2,1)),h=Math.max(.1,Math.min(r,Math.max(e.Height*.9,.1)));t.push(`<text x="${i+e.Width/2}" y="${o+e.Height/2}" font-size="${h}" font-family="${A(this.settings.fontFamily)}" fill="${n}" text-anchor="middle" dominant-baseline="central">${A(e.Text)}</text>`)}}}labelColor(t){const s=(t?.alpha??255)/255,e=i=>Math.min(255,Math.max(0,i??0));return`rgba(${e(t?.r)}, ${e(t?.g)}, ${e(t?.b)}, ${s})`}renderLinkExits(t,s,e){const i=s.getLinkExits(e);for(const o of i){const n=this.exitRenderer.renderData(o,e);n&&this.renderExitData(t,n)}}renderExitData(t,s){for(const e of s.lines)this.renderSvgLine(t,e);for(const e of s.arrows)this.renderSvgArrow(t,e);for(const e of s.doors)this.renderSvgDoor(t,e)}renderSvgLine(t,s){if(s.points.length<4)return;const e=s.points.map(o=>o.toString()).join(" "),i=s.dash?` stroke-dasharray="${s.dash.join(" ")}"`:"";t.push(`<polyline points="${e}" stroke="${A(s.stroke)}" stroke-width="${s.strokeWidth}" fill="none"${i}/>`)}renderSvgArrow(t,s){if(s.points.length<4)return;const e=s.points.map(p=>p.toString()).join(" "),i=s.dash?` stroke-dasharray="${s.dash.join(" ")}"`:"";t.push(`<polyline points="${e}" stroke="${A(s.stroke)}" stroke-width="${s.strokeWidth}" fill="none"${i}/>`);const o=s.points.length-2,n=s.points[o],r=s.points[o+1],h=s.points[o-2],a=s.points[o-1],c=Math.atan2(r-a,n-h),l=s.pointerLength,d=s.pointerWidth/2,g=n-l*Math.cos(c-Math.atan2(d,l)),u=r-l*Math.sin(c-Math.atan2(d,l)),f=n-l*Math.cos(c+Math.atan2(d,l)),y=r-l*Math.sin(c+Math.atan2(d,l));t.push(`<polygon points="${n},${r} ${g},${u} ${f},${y}" fill="${A(s.fill)}" stroke="${A(s.stroke)}" stroke-width="${s.strokeWidth}"/>`)}renderSvgDoor(t,s){t.push(`<rect x="${s.x}" y="${s.y}" width="${s.width}" height="${s.height}" stroke="${A(s.stroke)}" stroke-width="${s.strokeWidth}" fill="none"/>`)}renderStubs(t,s){const e=this.settings.lineColor;for(const i of s)for(const o of i.stubs){const n=Vt[o];if(!n)continue;const r=this.getRoomEdgePoint(i.x,i.y,n,this.settings.roomSize/2),h=L(i.x,i.y,n,this.settings.roomSize/2+.5);t.push(`<line x1="${r.x}" y1="${r.y}" x2="${h.x}" y2="${h.y}" stroke="${A(e)}" stroke-width="${this.settings.lineWidth}"/>`)}}renderSpecialExits(t,s){for(const e of s)for(const[i,o]of Object.entries(e.customLines)){const n=[e.x,e.y];for(const l of o.points)n.push(l.x,-l.y);const r=`rgb(${o.attributes.color.r}, ${o.attributes.color.g}, ${o.attributes.color.b})`;let h="";o.attributes.style==="dot line"?h=' stroke-dasharray="0.05 0.05"':o.attributes.style==="dash line"&&(h=' stroke-dasharray="0.4 0.2"');const a=n.map(l=>l.toString()).join(" ");if(o.attributes.arrow&&n.length>=4){t.push(`<polyline points="${a}" stroke="${A(r)}" stroke-width="${this.settings.lineWidth}" fill="none"${h}/>`);const l=n.length-2,d=n[l],g=n[l+1],u=n[l-2],f=n[l-1],y=Math.atan2(g-f,d-u),p=.3,x=.1,k=d-p*Math.cos(y-Math.atan2(x,p)),D=g-p*Math.sin(y-Math.atan2(x,p)),$=d-p*Math.cos(y+Math.atan2(x,p)),X=g-p*Math.sin(y+Math.atan2(x,p));t.push(`<polygon points="${d},${g} ${k},${D} ${$},${X}" fill="${A(r)}" stroke="${A(r)}" stroke-width="${this.settings.lineWidth}"/>`)}else t.push(`<polyline points="${a}" stroke="${A(r)}" stroke-width="${this.settings.lineWidth}" fill="none"${h}/>`);const c=e.doors[i];if(c&&n.length>=4){const l=n[0]+(n[2]-n[0])/2,d=n[1]+(n[3]-n[1])/2,g=this.settings.roomSize/2;t.push(`<rect x="${l-g/2}" y="${d-g/2}" width="${g}" height="${g}" stroke="${vt(c)}" stroke-width="${this.settings.lineWidth}" fill="none"/>`)}}}renderRooms(t,s){const e=this.settings.roomSize,i=e/2;for(const o of s){const n=this.mapReader.getColorValue(o.env),r=this.settings.frameMode?this.settings.backgroundColor:n,h=this.settings.frameMode?n:this.settings.lineColor;if(this.settings.roomShape==="circle")t.push(`<circle cx="${o.x}" cy="${o.y}" r="${i}" fill="${A(r)}" stroke="${A(h)}" stroke-width="${this.settings.lineWidth}"/>`);else{const a=o.x-i,c=o.y-i,l=this.settings.roomShape==="roundedRectangle"?e*.2:0,d=l>0?` rx="${l}" ry="${l}"`:"";if(t.push(`<rect x="${a}" y="${c}" width="${e}" height="${e}" fill="${A(r)}" stroke="${A(h)}" stroke-width="${this.settings.lineWidth}"${d}/>`),this.settings.emboss){const g=q(this.settings.lineColor)>.41,u=g?"#000000":"#ffffff",f=g?`${a},${c} ${a+e},${c} ${a+e},${c+e}`:`${a},${c} ${a},${c+e} ${a+e},${c+e}`;t.push(`<polyline points="${f}" stroke="${u}" stroke-width="${this.settings.lineWidth}" fill="none"/>`)}}if(o.roomChar){const a=this.getSymbolColor(o.env),c=e*.75;t.push(`<text x="${o.x}" y="${o.y}" dy="0.35em" font-size="${c}" font-weight="bold" font-family="${A(this.settings.fontFamily)}" fill="${A(a)}" text-anchor="middle">${A(o.roomChar)}</text>`)}}}renderInnerExits(t,s){const e=this.settings.roomSize,i=e/5;for(const o of s)for(const n of jt){if(!o.exits[n])continue;const r=this.getSymbolColor(o.env),h=this.getSymbolColor(o.env,.6);let a;const c=o.doors[n];c!==void 0&&(a=vt(c));const l=a??r;switch(n){case"up":{const d=L(o.x,o.y,"south",e/4);t.push(this.svgTriangle(d.x,d.y,i,0,h,l));break}case"down":{const d=L(o.x,o.y,"north",e/4);t.push(this.svgTriangle(d.x,d.y,i,180,h,l));break}case"in":{const d=L(o.x,o.y,"west",e/4),g=L(o.x,o.y,"east",e/4);t.push(this.svgTriangle(d.x,d.y,i,90,h,l)),t.push(this.svgTriangle(g.x,g.y,i,-90,h,l));break}case"out":{const d=L(o.x,o.y,"west",e/4),g=L(o.x,o.y,"east",e/4);t.push(this.svgTriangle(d.x,d.y,i,-90,h,l)),t.push(this.svgTriangle(g.x,g.y,i,90,h,l));break}}}}svgTriangle(t,s,e,i,o,n){const a=i*Math.PI/180,c=[];for(let l=0;l<3;l++){const d=2*Math.PI*l/3-Math.PI/2;let g=Math.cos(d)*e*1.4,u=Math.sin(d)*e*.8;const f=g*Math.cos(a)-u*Math.sin(a),y=g*Math.sin(a)+u*Math.cos(a);c.push(`${t+f},${s+y}`)}return`<polygon points="${c.join(" ")}" fill="${A(o)}" stroke="${A(n)}" stroke-width="${this.settings.lineWidth}"/>`}renderPathOverlay(t,s,e,i,o){const n=nt(this.mapReader,this.settings,s,i,o),r=this.settings.lineWidth;for(const a of n.segments){const c=a.points.map(l=>l.toString()).join(" ");t.push(`<polyline points="${c}" stroke="black" stroke-width="${r*8}" stroke-linecap="round" stroke-linejoin="round" fill="none" opacity="0.8"/>`),t.push(`<polyline points="${c}" stroke="${A(e)}" stroke-width="${r*4}" stroke-linecap="round" stroke-linejoin="round" fill="none" opacity="0.8"/>`)}for(const a of n.customLines){const c=a.points.map(l=>l.toString()).join(" ");t.push(`<polyline points="${c}" stroke="black" stroke-width="${r*8}" stroke-linecap="round" stroke-linejoin="round" fill="none" opacity="0.8"/>`),t.push(`<polyline points="${c}" stroke="${A(e)}" stroke-width="${r*4}" stroke-linecap="round" stroke-linejoin="round" fill="none" opacity="0.8"/>`)}const h=this.settings.roomSize/5;for(const a of n.innerMarkers)t.push(this.svgTriangle(a.room.x,a.room.y,h,this.innerExitRotation(a.direction),e,"black"))}innerExitRotation(t){switch(t){case"up":return 0;case"down":return 180;case"in":return 90;case"out":return-90;default:return 0}}renderHighlightOverlay(t,s,e){const i=this.mapReader.getRoom(s);if(!i)return;const o=1.5,n=this.settings.roomSize,r="0.05 0.05";if(this.settings.roomShape==="circle")t.push(`<circle cx="${i.x}" cy="${i.y}" r="${n/2*o}" stroke="${A(e)}" stroke-width="0.1" stroke-dasharray="${r}" fill="none"/>`);else{const h=n*o;t.push(`<rect x="${i.x-h/2}" y="${i.y-h/2}" width="${h}" height="${h}" stroke="${A(e)}" stroke-width="0.1" stroke-dasharray="${r}" fill="none"/>`)}}renderPositionMarker(t,s){const e=this.mapReader.getRoom(s);if(!e)return;const i=this.settings.playerMarker,n=this.settings.roomSize*i.sizeFactor,r=i.dashEnabled&&i.dash?` stroke-dasharray="${i.dash.join(" ")}"`:"",h=i.fillAlpha>0?` fill="${i.fillColor}" fill-opacity="${i.fillAlpha}"`:' fill="none"';t.push(`<circle cx="${e.x}" cy="${e.y}" r="${n/2}" stroke="${i.strokeColor}" stroke-width="${i.strokeWidth}" stroke-opacity="${i.strokeAlpha}"${r}${h}/>`)}}const Ht=.6,j=75,Gt=.025,_t="rgb(225, 255, 225)",K="rgb(120, 72, 0)";function q(m){let t,s,e;const i=m.match(/(\d+)\s*,\s*(\d+)\s*,\s*(\d+)/);if(i)t=parseInt(i[1])/255,s=parseInt(i[2])/255,e=parseInt(i[3])/255;else if(m.startsWith("#")&&m.length>=7)t=parseInt(m.slice(1,3),16)/255,s=parseInt(m.slice(3,5),16)/255,e=parseInt(m.slice(5,7),16)/255;else return .5;return(Math.max(t,s,e)+Math.min(t,s,e))/2}class qt{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(),s=t-this.lastCullingTime;return this.lastCullingTime=t,s>0?1e3/s:0}flush(){const t=this.samples.length;if(t===0)return;const s={cullingMs:0,gridMs:0,visibleRooms:0,totalRooms:0,visibleExits:0,fps:0};for(const e of this.samples)s.cullingMs+=e.cullingMs,s.gridMs+=e.gridMs,s.visibleRooms+=e.visibleRooms,s.totalRooms+=e.totalRooms,s.visibleExits+=e.visibleExits,s.fps+=e.fps;s.cullingMs/=t,s.gridMs/=t,s.visibleRooms=Math.round(s.visibleRooms/t),s.totalRooms=Math.round(s.totalRooms/t),s.visibleExits=Math.round(s.visibleExits/t),s.fps=Math.round(s.fps),this.callback(s),this.samples=[]}}function Q(m,t){const s=parseInt(m.slice(1,3),16),e=parseInt(m.slice(3,5),16),i=parseInt(m.slice(5,7),16);return`rgba(${s}, ${e}, ${i}, ${t})`}function yt(){return{roomSize:Ht,lineWidth:Gt,lineColor:_t,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(200, 200, 200, 0.15)",gridLineWidth:.03,perfCallback:null,borders:!0,frameMode:!1,emboss:!1,areaName:!0,fontFamily:"sans-serif",uniformLevelSize:!1}}class Kt{constructor(t,s,e){this.highlights=new Map,this.currentZoom=1,this.currentRoomOverlay=[],this.roomNodes=new Map,this.centerOnResize=!0,this.minZoom=.05,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 qt,this.areaExitHitZones=[],this.visibleExitDrawData=[],this.cachedGridBounds=null,this.settings=e??yt(),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}),this.stage.add(this.gridLayer),this.linkLayer=new b.Layer({listening:!1}),this.stage.add(this.linkLayer),this.roomLayer=new b.Layer,this.stage.add(this.roomLayer),this.positionLayer=new b.Layer({listening:!1}),this.stage.add(this.positionLayer),this.overlayLayer=new b.Layer({listening:!1}),this.stage.add(this.overlayLayer),this.mapReader=s,this.exitRenderer=new mt(s,this,this.settings),this.pathRenderer=new Zt(s,this.overlayLayer,this.settings),this.initScaling(1.1),this.stage.on("dragmove",()=>{this.scheduleRoomCulling(),this.emitPanEvent()}),this.stage.on("dragend",()=>{this.scheduleRoomCulling(),this.emitPanEvent()}),this.initRoomHitDetection()}clientToMapPoint(t,s){const i=this.stage.container().getBoundingClientRect(),o=t-i.left,n=s-i.top,r=this.stage.scaleX();if(!r)return null;const h=this.stage.position();return{x:(o-h.x)/r,y:(n-h.y)/r}}findRoomAtClientPoint(t,s){const e=this.clientToMapPoint(t,s);if(!e)return null;const i=this.settings.roomSize/2,o=this.getBucketKey(Math.floor(e.x/this.spatialBucketSize),Math.floor(e.y/this.spatialBucketSize)),n=this.roomSpatialIndex.get(o);if(!n)return null;for(const r of n){const h=e.x-r.room.x,a=e.y-r.room.y;if(h>=-i&&h<=i&&a>=-i&&a<=i)return r.room}return null}initRoomHitDetection(){const t=this.stage.container();let s=null;t.addEventListener("mousemove",a=>{const c=this.findRoomAtClientPoint(a.clientX,a.clientY);if(c!==s&&(s=c,c)){t.style.cursor="pointer";return}if(!s){const d=this.findAreaExitAtClientPoint(a.clientX,a.clientY)!==null;t.style.cursor=d?"pointer":"auto"}}),t.addEventListener("mouseleave",()=>{s=null,t.style.cursor="auto"});let e=null;t.addEventListener("mousedown",a=>{a.button===0&&(e={x:a.clientX,y:a.clientY})}),t.addEventListener("mouseup",a=>{if(a.button!==0||!e)return;const c=a.clientX-e.x,l=a.clientY-e.y;if(e=null,c*c+l*l>25)return;const d=this.findRoomAtClientPoint(a.clientX,a.clientY);if(d){this.emitRoomClickEvent(d.id,a.clientX,a.clientY);return}const g=this.findAreaExitAtClientPoint(a.clientX,a.clientY);if(g){this.emitAreaExitClickEvent(g.targetRoomId,a.clientX,a.clientY);return}this.emitMapClickEvent()}),t.addEventListener("contextmenu",a=>{const c=this.findRoomAtClientPoint(a.clientX,a.clientY);c&&(a.preventDefault(),this.emitRoomContextEvent(c.id,a.clientX,a.clientY))});let i,o,n;const r=()=>{n!==void 0&&(this.stage.draggable(n),n=void 0)},h=()=>{i!==void 0&&(window.clearTimeout(i),i=void 0),o=void 0,r()};t.addEventListener("touchstart",a=>{if(h(),a.touches.length>1)return;const c=a.touches[0];!c||!this.findRoomAtClientPoint(c.clientX,c.clientY)||(o={clientX:c.clientX,clientY:c.clientY},n=this.stage.draggable(),this.stage.draggable(!1),i=window.setTimeout(()=>{if(o){const d=this.findRoomAtClientPoint(o.clientX,o.clientY);d&&this.emitRoomContextEvent(d.id,o.clientX,o.clientY)}h()},500))},{passive:!0}),t.addEventListener("touchend",()=>h(),{passive:!0}),t.addEventListener("touchcancel",()=>h(),{passive:!0}),t.addEventListener("touchmove",a=>{if(!o)return;const c=a.touches[0];if(!c){h();return}const l=c.clientX-o.clientX,d=c.clientY-o.clientY;if(l*l+d*d>100){const g=n;h(),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 s,e=!1,i=!1;this.stage.on("touchstart",o=>{const n=o.evt.touches;n&&n.length>1?(i=!0,this.stage.isDragging()&&(this.stage.stopDrag(),e=!0),this.stage.draggable(!1)):(i=!1,this.stage.draggable(!0))}),this.stage.on("touchend touchcancel",o=>{s=void 0;const n=o.evt.touches;(!n||n.length<=1)&&(i=!1,this.stage.draggable(!0))}),this.stage.on("wheel",o=>{o.evt.preventDefault();const n=this.stage.scaleX(),r=this.stage.getPointerPosition();if(!r)return;const h={x:(r.x-this.stage.x())/n,y:(r.y-this.stage.y())/n};let a=o.evt.deltaY>0?-1:1;o.evt.ctrlKey&&(a=-a);const c=a>0?this.currentZoom*t:this.currentZoom/t;if(this.setZoom(c)){const d=this.stage.scaleX(),g={x:r.x-h.x*d,y:r.y-h.y*d};this.stage.position(g),this.scheduleRoomCulling(),this.emitZoomChangeEvent()}}),this.stage.on("touchmove",o=>{const n=o.evt.touches,r=n?.[0],h=n?.[1];if(h||i&&(i=!1,this.stage.draggable(!0)),r&&!h&&e&&!this.stage.isDragging()&&(this.stage.startDrag(),e=!1),!r||!h){s=void 0;return}o.evt.preventDefault(),this.stage.isDragging()&&(this.stage.stopDrag(),e=!0),i||(i=!0,this.stage.draggable(!1));const a=this.stage.container().getBoundingClientRect(),c={x:r.clientX-a.left,y:r.clientY-a.top},l={x:h.clientX-a.left,y:h.clientY-a.top},d=Math.hypot(c.x-l.x,c.y-l.y);if(s===void 0){s=d;return}if(s===0||d===0){s=d;return}const g=this.stage.scaleX(),u=this.stage.x(),f=this.stage.y(),y={x:this.stage.width()/2,y:this.stage.height()/2},p={x:(y.x-u)/g,y:(y.y-f)/g},x=this.currentZoom*(d/s);if(this.setZoom(x)){const D=this.stage.scaleX(),$={x:y.x-p.x*D,y:y.y-p.y*D};this.stage.position($),this.stage.batchDraw(),this.scheduleRoomCulling(),this.emitZoomChangeEvent()}s=d})}drawArea(t,s){const e=this.mapReader.getArea(t);if(!e)return;const i=e.getPlane(s);i&&(this.currentArea=t,this.currentAreaInstance=e,this.currentZIndex=s,this.currentAreaVersion=e.getVersion(),this.clearCurrentRoomOverlay(),this.positionRender&&(this.positionRender.destroy(),this.positionRender=void 0),this.positionLayer.destroyChildren(),this.gridLayer.destroyChildren(),this.invalidateGridCache(),this.roomLayer.destroyChildren(),this.linkLayer.destroyChildren(),this.roomNodes.clear(),this.standaloneExitNodes=[],this.areaExitHitZones=[],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(e.getLinkExits(s)),this.renderRooms(i.getRooms()??[]),this.renderAreaName(e,i),this.refreshHighlights(),this.updateRoomCulling(),this.stage.batchDraw())}exportSvg(t){return this.currentArea===void 0||this.currentZIndex===void 0?void 0:new pt(this.mapReader,this.settings).export(this.currentArea,this.currentZIndex,t)}exportPng(t){if(this.currentArea===void 0||this.currentZIndex===void 0)return;const s=t?.pixelRatio??1,e=this.stage.toCanvas({pixelRatio:s}),i=document.createElement("canvas");i.width=e.width,i.height=e.height;const o=i.getContext("2d");return o.fillStyle=this.settings.backgroundColor,o.fillRect(0,0,i.width,i.height),o.drawImage(e,0,0),i.toDataURL("image/png")}exportPngBlob(t){if(this.currentArea===void 0||this.currentZIndex===void 0)return;const s=t?.pixelRatio??1,e=this.stage.toCanvas({pixelRatio:s}),i=document.createElement("canvas");i.width=e.width,i.height=e.height;const o=i.getContext("2d");return o.fillStyle=this.settings.backgroundColor,o.fillRect(0,0,i.width,i.height),o.drawImage(e,0,0),new Promise(n=>{i.toBlob(r=>{r&&n(r)},"image/png")})}computeSpatialBucketSize(){return Math.max(this.settings.roomSize*10,5)}getBucketKey(t,s){return t*1000003+s}forEachBucket(t,s,e,i,o){const n=this.spatialBucketSize,r=Math.min(t,e),h=Math.max(t,e),a=Math.min(s,i),c=Math.max(s,i),l=Math.floor(r/n),d=Math.floor(h/n),g=Math.floor(a/n),u=Math.floor(c/n);for(let f=l;f<=d;f++)for(let y=g;y<=u;y++)o(this.getBucketKey(f,y))}addRoomToSpatialIndex(t){const s=this.settings.roomSize/2,e=t.room.x-s,i=t.room.x+s,o=t.room.y-s,n=t.room.y+s;this.forEachBucket(e,o,i,n,r=>{let h=this.roomSpatialIndex.get(r);h||(h=new Set,this.roomSpatialIndex.set(r,h)),h.add(t)})}addStandaloneExitToSpatialIndex(t){const{bounds:s}=t,e=s.x,i=s.x+s.width,o=s.y,n=s.y+s.height;this.forEachBucket(e,o,i,n,r=>{let h=this.exitSpatialIndex.get(r);h||(h=new Set,this.exitSpatialIndex.set(r,h)),h.add(t)})}collectRoomCandidates(t,s,e,i){const o=this.bufferRoomCandidates;return o.clear(),this.forEachBucket(t,s,e,i,n=>{this.roomSpatialIndex.get(n)?.forEach(h=>o.add(h))}),o}collectStandaloneExitCandidates(t,s,e,i){const o=this.bufferExitCandidates;return o.clear(),this.forEachBucket(t,s,e,i,n=>{this.exitSpatialIndex.get(n)?.forEach(h=>o.add(h))}),o}refreshStandaloneExitBoundsIfNeeded(){this.standaloneExitBoundsRoomSize!==this.settings.roomSize&&(this.exitSpatialIndex.clear(),this.standaloneExitNodes.forEach(t=>{this.addStandaloneExitToSpatialIndex(t)}),this.standaloneExitBoundsRoomSize=this.settings.roomSize)}emitRoomContextEvent(t,s,e){const i=this.stage.container(),o=i.getBoundingClientRect(),n={roomId:t,position:{x:s-o.left,y:e-o.top}},r=new CustomEvent("roomcontextmenu",{detail:n});i.dispatchEvent(r)}emitRoomClickEvent(t,s,e){const i=this.stage.container(),o=i.getBoundingClientRect(),n={roomId:t,position:{x:s-o.left,y:e-o.top}},r=new CustomEvent("roomclick",{detail:n});i.dispatchEvent(r)}findAreaExitAtClientPoint(t,s){const e=this.clientToMapPoint(t,s);if(!e)return null;for(const i of this.areaExitHitZones){const o=i.bounds,n=this.settings.roomSize*.5;if(e.x>=o.x-n&&e.x<=o.x+o.width+n&&e.y>=o.y-n&&e.y<=o.y+o.height+n)return i}return null}emitAreaExitClickEvent(t,s,e){const i=this.stage.container(),o=i.getBoundingClientRect(),n={targetRoomId:t,position:{x:s-o.left,y:e-o.top}},r=new CustomEvent("areaexitclick",{detail:n});i.dispatchEvent(r)}emitZoomChangeEvent(){const t=new CustomEvent("zoom",{detail:{zoom:this.currentZoom}});this.stage.container().dispatchEvent(t)}emitPanEvent(){const t=new CustomEvent("pan",{detail:this.getViewportBounds()});this.stage.container().dispatchEvent(t)}emitMapClickEvent(){const t=new CustomEvent("mapclick");this.stage.container().dispatchEvent(t)}setZoom(t){const s=Math.max(this.minZoom,Math.min(5,t));return this.currentZoom===s?!1:(this.currentZoom=s,this.stage.scale({x:j*this.currentZoom,y:j*this.currentZoom}),this.scheduleRoomCulling(),this.emitPanEvent(),!0)}zoomToCenter(t){const s=Math.max(this.minZoom,Math.min(5,t));if(this.currentZoom===s)return!1;const e=this.stage.scaleX(),i=this.stage.width(),o=this.stage.height(),n=i/2,r=o/2,h={x:(n-this.stage.x())/e,y:(r-this.stage.y())/e};this.currentZoom=s;const a=j*s;this.stage.scale({x:a,y:a});const c={x:n-h.x*a,y:r-h.y*a};return this.stage.position(c),this.stage.batchDraw(),this.scheduleRoomCulling(),this.emitZoomChangeEvent(),this.emitPanEvent(),!0}getZoom(){return this.currentZoom}getViewportBounds(){const t=this.stage.scaleX(),s=this.stage.position();return{minX:(0-s.x)/t,maxX:(this.stage.width()-s.x)/t,minY:(0-s.y)/t,maxY:(this.stage.height()-s.y)/t}}getAreaBounds(){if(!this.currentAreaInstance||this.currentZIndex===void 0)return null;const t=this.currentAreaInstance.getPlane(this.currentZIndex);if(!t)return null;const s=this.getEffectiveBounds(this.currentAreaInstance,t),e=this.settings.areaName&&this.currentAreaInstance.getAreaName();return{minX:e?s.minX-4:s.minX,maxX:s.maxX,minY:e?s.minY-7:s.minY,maxY:s.maxY}}fitArea(){if(this.currentArea===void 0||this.currentZIndex===void 0||!this.currentAreaInstance)return;const t=this.currentAreaInstance.getPlane(this.currentZIndex);if(!t)return;const s=this.getEffectiveBounds(this.currentAreaInstance,t),e=this.settings.areaName&&this.currentAreaInstance.getAreaName(),i=e?s.minY-7:s.minY,o=e?s.minX-4:s.minX,n=s.maxX-o,r=s.maxY-i;if(n<=0||r<=0)return;const h=this.stage.width(),a=this.stage.height(),c=2,l=h/((n+c*2)*j),d=a/((r+c*2)*j),g=Math.min(l,d);this.currentZoom=Math.max(.05,Math.min(5,g)),this.minZoom=this.currentZoom;const u=j*this.currentZoom;this.stage.scale({x:u,y:u});const f=(o+s.maxX)/2,y=(i+s.maxY)/2;this.stage.position({x:h/2-f*u,y:a/2-y*u}),this.stage.batchDraw(),this.scheduleRoomCulling()}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.currentArea!==void 0&&this.currentZIndex!==void 0&&(this.drawArea(this.currentArea,this.currentZIndex),this.currentRoomId!==void 0&&this.setPosition(this.currentRoomId))}updatePositionMarker(t){const s=this.mapReader.getRoom(t);if(!s)return;if(s.area!==this.currentArea||s.z!==this.currentZIndex){this.positionRender&&(this.positionRender.hide(),this.positionLayer.batchDraw());return}this.currentRoomId=t,this.updateCurrentRoomOverlay(s);const e=Q(this.settings.playerMarker.strokeColor,this.settings.playerMarker.strokeAlpha),i=Q(this.settings.playerMarker.fillColor,this.settings.playerMarker.fillAlpha),o=this.settings.roomSize/2*this.settings.playerMarker.sizeFactor;this.positionRender?(this.positionRender.position({x:s.x,y:s.y}),this.positionRender.radius(o),this.positionRender.stroke(e),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:s.x,y:s.y,radius:o,stroke:e,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,s=!0){const e=this.mapReader.getRoom(t);if(!e)return;const i=this.mapReader.getArea(e.area),o=i?.getVersion();let n=this.currentArea!==e.area||this.currentZIndex!==e.z;(this.currentArea!==e.area||this.currentZIndex!==e.z||o!==void 0&&this.currentAreaVersion!==o||i!==void 0&&this.currentAreaInstance!==i)&&this.drawArea(e.area,e.z),s?this.centerOnRoom(e,n):this.currentRoomId=t,this.updateCurrentRoomOverlay(e);const r=Q(this.settings.playerMarker.strokeColor,this.settings.playerMarker.strokeAlpha),h=Q(this.settings.playerMarker.fillColor,this.settings.playerMarker.fillAlpha),a=this.settings.roomSize/2*this.settings.playerMarker.sizeFactor;this.positionRender?(this.positionRender.radius(a),this.positionRender.stroke(r),this.positionRender.fill(h),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:e.x,y:e.y,radius:a,stroke:r,fill:h,strokeWidth:this.settings.playerMarker.strokeWidth,dash:this.settings.playerMarker.dash,dashEnabled:this.settings.playerMarker.dashEnabled}),this.positionLayer.add(this.positionRender))}clearPosition(){this.currentRoomId=void 0,this.positionRender&&(this.positionRender.destroy(),this.positionRender=void 0),this.positionLayer.batchDraw(),this.currentRoomOverlay.forEach(t=>t.destroy()),this.currentRoomOverlay=[],this.overlayLayer.batchDraw()}centerOn(t,s){const e=this.mapReader.getRoom(t);if(!e)return;const i=this.mapReader.getArea(e.area),o=i?.getVersion(),n=this.currentArea!==e.area||this.currentZIndex!==e.z;(n||o!==void 0&&this.currentAreaVersion!==o||i!==void 0&&this.currentAreaInstance!==i)&&this.drawArea(e.area,e.z),this.centerOnRoomView(e,s??n)}renderPath(t,s){return this.pathRenderer.renderPath(t,this.currentArea,this.currentZIndex,s)}clearPaths(){this.pathRenderer.clearPaths()}renderHighlight(t,s){const e=this.mapReader.getRoom(t);if(!e)return;const i=this.highlights.get(t);i?.shape&&(i.shape.destroy(),delete i.shape);const o={color:s,area:e.area,z:e.z};if(this.highlights.set(t,o),e.area===this.currentArea&&e.z===this.currentZIndex){const n=this.createHighlightShape(e,s);return this.overlayLayer.add(n),o.shape=n,this.overlayLayer.batchDraw(),n}return o.shape}removeHighlight(t){const s=this.highlights.get(t);s&&(s.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,s)=>{if(t.shape?.destroy(),delete t.shape,t.area!==this.currentArea||t.z!==this.currentZIndex)return;const e=this.mapReader.getRoom(s);if(!e)return;const i=this.createHighlightShape(e,t.color);this.overlayLayer.add(i),t.shape=i}),this.overlayLayer.batchDraw()}createHighlightShape(t,s){return this.settings.roomShape==="circle"?new b.Circle({x:t.x,y:t.y,radius:this.settings.roomSize/2*1.5,stroke:s,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:s,strokeWidth:.1,dash:[.05,.05],dashEnabled:!0,cornerRadius:this.settings.roomShape==="roundedRectangle"?this.settings.roomSize*1.5*.2:0,listening:!1})}centerOnRoom(t,s=!1){this.currentRoomId=t.id;const e={x:t.x,y:t.y};this.positionRender?.position(t);const o=this.stage.getAbsoluteTransform().point(e),n={x:this.stage.width()/2,y:this.stage.height()/2},r=n.x-o.x,h=n.y-o.y;this.currentTransition&&(this.currentTransition.pause(),this.currentTransition.destroy(),delete this.currentTransition),s||this.settings.instantMapMove?(this.stage.position({x:this.stage.x()+r,y:this.stage.y()+h}),this.scheduleRoomCulling()):(this.currentTransition=new b.Tween({node:this.stage,x:this.stage.x()+r,y:this.stage.y()+h,duration:.2,easing:b.Easings.EaseInOut,onUpdate:()=>this.scheduleRoomCulling(),onFinish:()=>this.scheduleRoomCulling()}),this.currentTransition.play())}centerOnRoomView(t,s=!1){const e={x:t.x,y:t.y},o=this.stage.getAbsoluteTransform().point(e),n={x:this.stage.width()/2,y:this.stage.height()/2},r=n.x-o.x,h=n.y-o.y;this.currentTransition&&(this.currentTransition.pause(),this.currentTransition.destroy(),delete this.currentTransition),s||this.settings.instantMapMove?(this.stage.position({x:this.stage.x()+r,y:this.stage.y()+h}),this.scheduleRoomCulling(),this.emitPanEvent()):(this.currentTransition=new b.Tween({node:this.stage,x:this.stage.x()+r,y:this.stage.y()+h,duration:.2,easing:b.Easings.EaseInOut,onUpdate:()=>this.scheduleRoomCulling(),onFinish:()=>{this.scheduleRoomCulling(),this.emitPanEvent()}}),this.currentTransition.play())}getEffectiveBounds(t,s){return this.settings.uniformLevelSize?t.getFullBounds():s.getBounds()}renderAreaName(t,s){if(!this.settings.areaName)return;const e=t.getAreaName();if(!e)return;const i=this.getEffectiveBounds(t,s);this.roomLayer.add(new b.Text({x:i.minX-3.5,y:i.minY-4.5,text:e,fontSize:2.5,fontFamily:this.settings.fontFamily,fill:"white",listening:!1,perfectDrawEnabled:!1}))}renderRooms(t){t.forEach(s=>{const e=new b.Group({x:s.x-this.settings.roomSize/2,y:s.y-this.settings.roomSize/2,listening:!1}),i=this.mapReader.getColorValue(s.env),o=this.settings.frameMode?this.settings.backgroundColor:i,n=this.settings.frameMode?i:this.settings.lineColor,r=this.settings.borders?this.settings.lineWidth:0,h=this.settings.roomShape==="circle"?new b.Circle({x:this.settings.roomSize/2,y:this.settings.roomSize/2,radius:this.settings.roomSize/2,fill:o,strokeWidth:r,stroke:n,perfectDrawEnabled:!1,listening:!1}):new b.Rect({x:0,y:0,width:this.settings.roomSize,height:this.settings.roomSize,fill:o,strokeWidth:r,stroke:n,cornerRadius:this.settings.roomShape==="roundedRectangle"?this.settings.roomSize*.2:0,perfectDrawEnabled:!1,listening:!1});if(e.add(h),this.settings.emboss&&this.settings.roomShape!=="circle"){const d=this.settings.roomSize,g=q(this.settings.lineColor)>.41;e.add(new b.Line({points:g?[0,0,d,0,d,d]:[0,0,0,d,d,d],stroke:g?"#000000":"#ffffff",strokeWidth:this.settings.lineWidth,perfectDrawEnabled:!1,listening:!1}))}this.renderSymbol(s,e),this.roomLayer.add(e),this.exitRenderer.renderSpecialExits(s).forEach(d=>{this.linkLayer.add(d)}),this.exitRenderer.getSpecialExitAreaTargets(s).forEach(d=>{this.areaExitHitZones.push(d)});const a=s.x-this.settings.roomSize/2,c=s.y-this.settings.roomSize/2;this.exitRenderer.renderStubs(s).forEach(d=>{const g=d.points();for(let u=0;u<g.length;u+=2)g[u]-=a,g[u+1]-=c;d.points(g),e.add(d)}),this.exitRenderer.renderInnerExits(s).forEach(d=>{d.position({x:-a,y:-c}),e.add(d)});const l={room:s,group:e};this.roomNodes.set(s.id,l),this.addRoomToSpatialIndex(l)})}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 s=this.settings.perfCallback?performance.now():0,e=this.stage.position(),i=this.settings.roomSize/2,o=this.settings.cullingBounds,n=o?o.x:0,r=o?o.x+o.width:this.stage.width(),h=o?o.y:0,a=o?o.y+o.height:this.stage.height(),c=Math.min(n,r),l=Math.max(n,r),d=Math.min(h,a),g=Math.max(h,a),u=(c-e.x)/t,f=(l-e.x)/t,y=(d-e.y)/t,p=(g-e.y)/t;let x=!1,k=!1;const D=this.settings.cullingEnabled?this.settings.cullingMode??"indexed":"none",$=u-i,X=f+i,w=y-i,R=p+i;if(this.refreshStandaloneExitBoundsIfNeeded(),D==="none"){if(this.roomNodes.forEach(v=>{v.group.visible()||(v.group.visible(!0),x=!0)}),this.visibleExitDrawData.length!==this.standaloneExitNodes.length){this.visibleExitDrawData.length=0;for(const v of this.standaloneExitNodes)this.visibleExitDrawData.push(v.data);k=!0}x&&this.roomLayer.batchDraw(),k&&this.linkLayer.batchDraw(),this.visibleRooms.clear(),this.roomNodes.forEach(v=>this.visibleRooms.add(v)),this.visibleStandaloneExitNodes.clear(),this.standaloneExitNodes.forEach(v=>this.visibleStandaloneExitNodes.add(v));return}if(D==="basic"){const v=this.bufferRoomSet;v.clear(),this.roomNodes.forEach(P=>{const O=P.room.x-i,T=P.room.x+i,F=P.room.y-i,Z=P.room.y+i,B=T>=u&&O<=f&&Z>=y&&F<=p;P.group.visible()!==B&&(P.group.visible(B),x=!0),B&&v.add(P)});const z=this.bufferExitSet;z.clear();let Y=!1;this.standaloneExitNodes.forEach(P=>{const{bounds:O}=P,T=O.x,F=O.x+O.width,Z=O.y,B=O.y+O.height;F>=u&&T<=f&&B>=y&&Z<=p&&(z.add(P),this.visibleStandaloneExitNodes.has(P)||(Y=!0))}),!Y&&z.size!==this.visibleStandaloneExitNodes.size&&(Y=!0),this.bufferRoomSet=this.visibleRooms,this.visibleRooms=v,this.bufferExitSet=this.visibleStandaloneExitNodes,this.visibleStandaloneExitNodes=z,Y&&(this.visibleExitDrawData.length=0,this.visibleStandaloneExitNodes.forEach(P=>this.visibleExitDrawData.push(P.data)),k=!0),x&&this.roomLayer.batchDraw(),k&&this.linkLayer.batchDraw();return}const E=this.collectRoomCandidates($,w,X,R),C=this.bufferRoomSet;C.clear(),E.forEach(v=>{const z=v.room.x-i,Y=v.room.x+i,P=v.room.y-i,O=v.room.y+i,T=Y>=u&&z<=f&&O>=y&&P<=p;v.group.visible()!==T&&(v.group.visible(T),x=!0),T&&C.add(v)}),this.visibleRooms.forEach(v=>{E.has(v)||v.group.visible()&&(v.group.visible(!1),x=!0)}),this.bufferRoomSet=this.visibleRooms,this.visibleRooms=C;const S=this.collectStandaloneExitCandidates($,w,X,R),M=this.bufferExitSet;M.clear();let I=!1;S.forEach(v=>{const{bounds:z}=v,Y=z.x,P=z.x+z.width,O=z.y,T=z.y+z.height;P>=u&&Y<=f&&T>=y&&O<=p&&(M.add(v),this.visibleStandaloneExitNodes.has(v)||(I=!0))}),!I&&M.size!==this.visibleStandaloneExitNodes.size&&(I=!0),this.bufferExitSet=this.visibleStandaloneExitNodes,this.visibleStandaloneExitNodes=M,I&&(this.visibleExitDrawData.length=0,this.visibleStandaloneExitNodes.forEach(v=>this.visibleExitDrawData.push(v.data)),k=!0),x&&this.roomLayer.batchDraw(),k&&this.linkLayer.batchDraw();const W=this.settings.perfCallback?performance.now():0;if(this.renderGrid(),this.settings.perfCallback){const v=performance.now()-W,z=performance.now()-s;this.perfMonitor.record({cullingMs:z,gridMs:v,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 s=this.stage.position(),e=this.stage.width(),i=this.stage.height(),o=(0-s.x)/t,n=(e-s.x)/t,r=(0-s.y)/t,h=(i-s.y)/t,a=this.settings.gridSize*2,c=Math.floor((Math.min(o,n)-a)/this.settings.gridSize)*this.settings.gridSize,l=Math.ceil((Math.max(o,n)+a)/this.settings.gridSize)*this.settings.gridSize,d=Math.floor((Math.min(r,h)-a)/this.settings.gridSize)*this.settings.gridSize,g=Math.ceil((Math.max(r,h)+a)/this.settings.gridSize)*this.settings.gridSize,u=this.cachedGridBounds;if(!(u&&u.left===c&&u.right===l&&u.top===d&&u.bottom===g)){this.gridLayer.destroyChildren();for(let f=c;f<=l;f+=this.settings.gridSize)this.gridLayer.add(new b.Line({points:[f,d,f,g],stroke:this.settings.gridColor,strokeWidth:this.settings.gridLineWidth,listening:!1,perfectDrawEnabled:!1}));for(let f=d;f<=g;f+=this.settings.gridSize)this.gridLayer.add(new b.Line({points:[c,f,l,f],stroke:this.settings.gridColor,strokeWidth:this.settings.gridLineWidth,listening:!1,perfectDrawEnabled:!1}));this.cachedGridBounds={left:c,right:l,top:d,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 s=new Map;s.set(t.id,t);const e=[],i=this.currentAreaInstance instanceof J?this.currentAreaInstance:void 0;this.currentAreaInstance&&this.currentZIndex!==void 0&&this.currentAreaInstance.getLinkExits(this.currentZIndex).filter(h=>h.a===t.id||h.b===t.id).forEach(h=>{const a=this.settings.highlightCurrentRoom?this.exitRenderer.renderWithColor(h,K,this.currentZIndex):this.exitRenderer.render(h,this.currentZIndex);a&&e.push(a)});const o=this.settings.highlightCurrentRoom?K:void 0;this.exitRenderer.renderSpecialExits(t,o).forEach(r=>{e.push(r)}),(this.settings.highlightCurrentRoom?this.exitRenderer.renderStubs(t,K):this.exitRenderer.renderStubs(t)).forEach(r=>{e.push(r)}),[...Object.values(t.exits),...Object.values(t.specialExits)].forEach(r=>{const h=this.mapReader.getRoom(r),a=!i||i.hasVisitedRoom(r);h&&h.area===this.currentArea&&h.z===this.currentZIndex&&a&&s.set(r,h)}),e.forEach(r=>{this.positionLayer.add(r),this.currentRoomOverlay.push(r)}),s.forEach((r,h)=>{const a=h===t.id,c=this.createOverlayRoomGroup(r,{stroke:a&&this.settings.highlightCurrentRoom?K:this.settings.lineColor});this.positionLayer.add(c),this.currentRoomOverlay.push(c),this.exitRenderer.renderInnerExits(r).forEach(l=>{this.positionLayer.add(l),this.currentRoomOverlay.push(l)})}),this.positionRender&&this.positionRender.moveToTop(),this.positionLayer.batchDraw()}createOverlayRoomGroup(t,s){const e=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),o=this.settings.frameMode?this.settings.backgroundColor:i,n=this.settings.frameMode?i:s.stroke,r=this.settings.borders?this.settings.lineWidth:0,h=this.settings.roomShape==="circle"?new b.Circle({x:this.settings.roomSize/2,y:this.settings.roomSize/2,radius:this.settings.roomSize/2,fill:o,stroke:n,strokeWidth:r}):new b.Rect({x:0,y:0,width:this.settings.roomSize,height:this.settings.roomSize,fill:o,stroke:n,strokeWidth:r,cornerRadius:this.settings.roomShape==="roundedRectangle"?this.settings.roomSize*.2:0});if(e.add(h),this.settings.emboss&&this.settings.roomShape!=="circle"){const a=this.settings.roomSize,c=q(this.settings.lineColor)>.41;e.add(new b.Line({points:c?[0,0,a,0,a,a]:[0,0,0,a,a,a],stroke:c?"#000000":"#ffffff",strokeWidth:this.settings.lineWidth,perfectDrawEnabled:!1,listening:!1}))}return this.renderSymbol(t,e),e}getSymbolColor(t,s){return this.settings.frameMode?this.mapReader.getColorValue(t):this.mapReader.getSymbolColor(t,s)}renderSymbol(t,s){if(t.roomChar!==void 0){const e=this.settings.roomSize*.75,i=new b.Text({x:0,y:0,text:t.roomChar,fontSize:e,fontStyle:"bold",fill:this.getSymbolColor(t.env),align:"center",verticalAlign:"middle",width:this.settings.roomSize,height:this.settings.roomSize,perfectDrawEnabled:!1,listening:!1});s.add(i)}}renderExits(t){t.forEach(s=>{const e=this.exitRenderer.renderData(s,this.currentZIndex);if(!e)return;const i={data:e,bounds:e.bounds,targetRoomId:e.targetRoomId};this.standaloneExitNodes.push(i),this.addStandaloneExitToSpatialIndex(i),e.targetRoomId!==void 0&&this.areaExitHitZones.push({bounds:e.bounds,targetRoomId:e.targetRoomId})}),this.standaloneExitBoundsRoomSize=this.settings.roomSize,this.exitBatchShape=new b.Shape({listening:!1,perfectDrawEnabled:!1,sceneFunc:s=>{const e=s._context;for(const i of this.visibleExitDrawData)this.drawExitData(e,i)}}),this.linkLayer.add(this.exitBatchShape)}drawExitData(t,s){for(const e of s.lines){t.beginPath(),t.moveTo(e.points[0],e.points[1]);for(let i=2;i<e.points.length;i+=2)t.lineTo(e.points[i],e.points[i+1]);t.strokeStyle=e.stroke,t.lineWidth=e.strokeWidth,e.dash?t.setLineDash(e.dash):t.setLineDash([]),t.stroke()}for(const e of s.arrows){t.beginPath(),t.moveTo(e.points[0],e.points[1]);for(let d=2;d<e.points.length;d+=2)t.lineTo(e.points[d],e.points[d+1]);t.strokeStyle=e.stroke,t.lineWidth=e.strokeWidth,e.dash?t.setLineDash(e.dash):t.setLineDash([]),t.stroke();const i=e.points.length-2,o=e.points[i],n=e.points[i+1],r=e.points[i-2],h=e.points[i-1],a=Math.atan2(n-h,o-r),c=e.pointerLength,l=e.pointerWidth/2;t.beginPath(),t.setLineDash([]),t.moveTo(o,n),t.lineTo(o-c*Math.cos(a-Math.atan2(l,c)),n-c*Math.sin(a-Math.atan2(l,c))),t.lineTo(o-c*Math.cos(a+Math.atan2(l,c)),n-c*Math.sin(a+Math.atan2(l,c))),t.closePath(),t.fillStyle=e.fill,t.fill(),t.strokeStyle=e.stroke,t.lineWidth=e.strokeWidth,t.stroke()}for(const e of s.doors)t.beginPath(),t.rect(e.x,e.y,e.width,e.height),t.strokeStyle=e.stroke,t.lineWidth=e.strokeWidth,t.setLineDash([]),t.stroke()}renderLabels(t){this.settings.labelRenderMode!=="none"&&t.forEach(s=>{if(this.settings.labelRenderMode==="image"){if(!s.pixMap)return;const e=new Image;e.src=`data:image/png;base64,${s.pixMap}`;const i=new b.Image({x:s.X,y:-s.Y,width:s.Width,height:s.Height,image:e,listening:!1});this.linkLayer.add(i);return}this.renderLabelAsData(s)})}renderLabelAsData(t){const s=new b.Group({listening:!1}),e=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?e.fill(this.getLabelColor(t.BgColor)):e.fillEnabled(!1),s.add(e);const i=Math.min(.75,t.Width/Math.max(t.Text.length/2,1)),o=Math.max(.1,Math.min(i,Math.max(t.Height*.9,.1))),n=new b.Text({x:t.X,y:-t.Y,width:t.Width,height:t.Height,text:t.Text,fontSize:o,fillEnabled:!0,fill:this.getLabelColor(t.FgColor),align:"center",verticalAlign:"middle",listening:!1});s.add(n),this.linkLayer.add(s)}getLabelColor(t){const s=(t?.alpha??255)/255,e=i=>Math.min(255,Math.max(0,i??0));return`rgba(${e(t?.r)}, ${e(t?.g)}, ${e(t?.b)}, ${s})`}}const kt={rgbValue:"rgb(114, 1, 0)",symbolColor:[225,225,225]};function Rt(m){const t=m[0]/255,s=m[1]/255,e=m[2]/255,i=Math.max(t,s,e),o=Math.min(t,s,e);return(i+o)/2}class Qt{constructor(t,s){this.rooms={},this.areas={},this.areaSources={},this.explorationEnabled=!1,this.colors={},t.forEach(e=>{e.rooms.forEach(o=>{o.y=-o.y,this.rooms[o.id]=o});const i=parseInt(e.areaId);this.areas[i]=new _(e),this.areaSources[i]=e}),this.colors=s.reduce((e,i)=>({...e,[i.envId]:{rgb:i.colors,rgbValue:`rgb(${i.colors.join(",")})`,symbolColor:Rt(i.colors)>.41?[25,25,25]:[225,255,255],symbolColorValue:Rt(i.colors)>.41?"rgb(25,25,25)":"rgb(225,255,255)"}}),{})}getArea(t){return this.areas[t]}getExplorationArea(t){const s=this.areas[t];if(s instanceof J)return s}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,s])=>{const e=parseInt(t,10);this.areas[e]=new J(s,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,s])=>{const e=parseInt(t,10);this.areas[e]=new _(s)}),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 o=this.getExplorationArea(i.area);if(o)return o.addVisitedRoom(t)}}const s=this.ensureVisitedRooms(),e=s.has(t);return s.add(t),!e}addVisitedRooms(t){const s=this.ensureVisitedRooms();let e=0;for(const i of t){if(this.explorationEnabled){const n=this.getRoom(i);if(n){const r=this.getExplorationArea(n.area);if(r){r.addVisitedRoom(i)&&e++;continue}}}const o=s.has(i);s.add(i),o||e++}return e}hasVisitedRoom(t){return this.visitedRooms?.has(t)??!1}getColorValue(t){return this.colors[t]?.rgbValue??kt.rgbValue}getSymbolColor(t,s){const e=this.colors[t]?.symbolColor??kt.symbolColor,i=Math.min(Math.max(s??1,0),1),o=e.join(",");return i!=1?`rgba(${o}, ${i})`:`rgba(${o})`}}function Ut(m){return m&&m.__esModule&&Object.prototype.hasOwnProperty.call(m,"default")?m.default:m}var ht,St;function Jt(){if(St)return ht;St=1;class m{constructor(){this.keys=new Set,this.queue=[]}sort(){this.queue.sort((s,e)=>s.priority-e.priority)}set(s,e){const i=Number(e);if(isNaN(i))throw new TypeError('"priority" must be a number');return this.keys.has(s)?this.queue.map(o=>(o.key===s&&Object.assign(o,{priority:i}),o)):(this.keys.add(s),this.queue.push({key:s,priority:i})),this.sort(),this.queue.length}next(){const s=this.queue.shift();return this.keys.delete(s.key),s}isEmpty(){return this.queue.length===0}has(s){return this.keys.has(s)}get(s){return this.queue.find(e=>e.key===s)}}return ht=m,ht}var ct,Et;function te(){if(Et)return ct;Et=1;function m(t,s){const e=new Map;for(const[i,o]of t)i!==s&&o instanceof Map?e.set(i,m(o,s)):i!==s&&e.set(i,o);return e}return ct=m,ct}var lt,Mt;function ee(){if(Mt)return lt;Mt=1;function m(s){const e=Number(s);return!(isNaN(e)||e<=0)}function t(s){const e=new Map;return Object.keys(s).forEach(o=>{const n=s[o];if(n!==null&&typeof n=="object"&&!Array.isArray(n))return e.set(o,t(n));if(!m(n))throw new Error(`Could not add node at key "${o}", make sure it's a valid node`,n);return e.set(o,Number(n))}),e}return lt=t,lt}var dt,Ct;function se(){if(Ct)return dt;Ct=1;function m(t){if(!(t instanceof Map))throw new Error(`Invalid graph: Expected Map instead found ${typeof t}`);t.forEach((s,e)=>{if(typeof s=="object"&&s instanceof Map){m(s);return}if(typeof s!="number"||s<=0)throw new Error(`Values must be numbers greater than 0. Found value ${s} at ${e}`)})}return dt=m,dt}var gt,Dt;function ie(){if(Dt)return gt;Dt=1;const m=Jt(),t=te(),s=ee(),e=se();class i{constructor(n){n instanceof Map?(e(n),this.graph=n):n?this.graph=s(n):this.graph=new Map}addNode(n,r){let h;return r instanceof Map?(e(r),h=r):h=s(r),this.graph.set(n,h),this}addVertex(n,r){return this.addNode(n,r)}removeNode(n){return this.graph=t(this.graph,n),this}path(n,r,h={}){if(!this.graph.size)return h.cost?{path:null,cost:0}:null;const a=new Set,c=new m,l=new Map;let d=[],g=0,u=[];if(h.avoid&&(u=[].concat(h.avoid)),u.includes(n))throw new Error(`Starting node (${n}) cannot be avoided`);if(u.includes(r))throw new Error(`Ending node (${r}) cannot be avoided`);for(c.set(n,0);!c.isEmpty();){const f=c.next();if(f.key===r){g=f.priority;let p=f.key;for(;l.has(p);)d.push(p),p=l.get(p);break}a.add(f.key),(this.graph.get(f.key)||new Map).forEach((p,x)=>{if(a.has(x)||u.includes(x))return null;if(!c.has(x))return l.set(x,f.key),c.set(x,f.priority+p);const k=c.get(x).priority,D=f.priority+p;return D<k?(l.set(x,f.key),c.set(x,D)):null})}return d.length?(h.trim?d.shift():d=d.concat([n]),h.reverse||(d=d.reverse()),h.cost?{path:d,cost:g}:d):h.cost?{path:null,cost:0}:null}shortestPath(...n){return this.path(...n)}}return gt=i,gt}var oe=ie();const ne=Ut(oe),re={1:"north",2:"northeast",3:"northwest",4:"east",5:"west",6:"south",7:"southeast",8:"southwest",9:"up",10:"down",11:"in",12:"out"},ae={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 It(m,t){m.push(t);let s=m.length-1;for(;s>0;){const e=s-1>>1;if(m[e].priority<=m[s].priority)break;[m[e],m[s]]=[m[s],m[e]],s=e}}function he(m){if(m.length===0)return;const t=m[0],s=m.pop();if(m.length>0){m[0]=s;let e=0;const i=m.length;for(;;){let o=e;const n=2*e+1,r=2*e+2;if(n<i&&m[n].priority<m[o].priority&&(o=n),r<i&&m[r].priority<m[o].priority&&(o=r),o===e)break;[m[e],m[o]]=[m[o],m[e]],e=o}}return t}function ce(m,t,s){const e=[s];let i=s;for(;i!==t;)i=m.get(i),e.push(i);return e.reverse(),e}function le(m,t,s){const e=m.path(t.toString(),s.toString()),i=Array.isArray(e)?e:e?.path;return i?i.map(o=>Number(o)):null}function de(m,t,s,e,i,o){const n=e.getRoom(s);if(!n)return null;const r=n.x,h=n.y,a=n.z,c=u=>{const f=e.getRoom(u);if(!f)return 0;const y=f.x-r,p=f.y-h,x=f.z-a;return Math.sqrt(y*y+p*p+x*x)/i*o},l=new Map,d=new Map,g=[];for(l.set(t,0),It(g,{id:t,priority:c(t)});g.length>0;){const{id:u}=he(g);if(u===s)return ce(d,t,s);const f=l.get(u)??1/0,y=m.get(u);if(y)for(const p of y){const x=f+p.weight;x<(l.get(p.id)??1/0)&&(l.set(p.id,x),d.set(p.id,u),It(g,{id:p.id,priority:x+c(p.id)}))}}return null}class ge{constructor(t,s="dijkstra"){this.cache=new Map,this.mapReader=t,this._algorithm=s;const{adj:e,maxEdgeDistance:i,minEdgeWeight:o,graphDefinition:n}=this.buildGraph();this.adj=e,this.graph=new ne(n),this.maxEdgeDistance=i,this.minEdgeWeight=o}get algorithm(){return this._algorithm}setAlgorithm(t){t!==this._algorithm&&(this._algorithm=t,this.cache.clear())}findPath(t,s){const e=`${t}->${s}`;if(this.cache.has(e))return this.cache.get(e);if(t===s){const o=this.mapReader.getRoom(t)?[t]:null;return this.cache.set(e,o),o}if(!this.mapReader.getRoom(t)||!this.mapReader.getRoom(s))return this.cache.set(e,null),null;let i;switch(this._algorithm){case"dijkstra":i=le(this.graph,t,s);break;case"astar":i=de(this.adj,t,s,this.mapReader,this.maxEdgeDistance,this.minEdgeWeight);break}return this.cache.set(e,i),i}resolveEdgeWeight(t,s,e){const i=t.exitWeights?.[s];return i!==void 0&&i>0?i:Math.max(e.weight,1)}buildGraph(){const t=new Map,s={};let e=1,i=1/0;return this.mapReader.getRooms().forEach(o=>{const n=[],r={},h=new Set((o.exitLocks??[]).map(c=>re[c]).filter(c=>!!c)),a=new Set(o.mSpecialExitLocks??[]);Object.entries(o.exits??{}).forEach(([c,l])=>{if(h.has(c))return;const d=this.mapReader.getRoom(l);if(d){const g=ae[c]??c,u=this.resolveEdgeWeight(o,g,d);n.push({id:l,weight:u}),r[l.toString()]=u,u<i&&(i=u);const f=d.x-o.x,y=d.y-o.y,p=d.z-o.z,x=Math.sqrt(f*f+y*y+p*p);x>e&&(e=x)}}),Object.entries(o.specialExits??{}).forEach(([c,l])=>{if(a.has(l))return;const d=this.mapReader.getRoom(l);if(d){const g=this.resolveEdgeWeight(o,c,d);n.push({id:l,weight:g}),r[l.toString()]=g,g<i&&(i=g);const u=d.x-o.x,f=d.y-o.y,y=d.z-o.z,p=Math.sqrt(u*u+f*f+y*y);p>e&&(e=p)}}),t.set(o.id,n),s[o.id.toString()]=r}),isFinite(i)||(i=1),{adj:t,maxEdgeDistance:e,minEdgeWeight:i,graphDefinition:s}}}const ue={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 $t(){return{areaWidth:150,areaHeight:80,areaSpacing:50,fontSize:14,connectionLineWidth:2,areaFillColor:"#2a2a3e",areaStrokeColor:"#4a4a6e",textColor:"#e0e0e0",connectionColor:"#6a6a8e",highlightColor:"#ff9900"}}class fe{constructor(t,s,e){this.areaNodes=new Map,this.connectionGroups=[],this.currentZoom=1,this.domainInfo=new Map,this.domainFilter="all",this.dotsMode=!1,this.settings=e??$t(),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=s,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",s=>{s.evt.preventDefault();const e=this.stage.scaleX(),i=this.stage.getPointerPosition();if(!i)return;const o={x:(i.x-this.stage.x())/e,y:(i.y-this.stage.y())/e},r=(s.evt.deltaY>0?-1:1)>0?this.currentZoom*1.1:this.currentZoom/1.1;if(this.setZoom(r)){const h=this.stage.scaleX(),a={x:i.x-o.x*h,y:i.y-o.y*h};this.stage.position(a),this.stage.batchDraw()}})}setZoom(t){const s=Math.max(.1,Math.min(5,t));return this.currentZoom===s?!1:(this.currentZoom=s,this.stage.scale({x:this.currentZoom,y:this.currentZoom}),!0)}getZoom(){return this.currentZoom}setDomainInfo(t){this.domainInfo.clear();for(const[s,e]of Object.entries(t))this.domainInfo.set(Number(s),e)}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 s=this.domainInfo.get(t);if(!s)return this.domainFilter==="interdomain"||this.domainFilter==="all";switch(this.domainFilter){case"ishtar":return s.isIshtar;case"empire":return s.isEmpire;case"interdomain":return!s.isIshtar&&!s.isEmpire;case"all":return!0}}areAreasInSameDomain(t,s){const e=this.domainInfo.get(t),i=this.domainInfo.get(s);return!e||!i?!1:e.isIshtar&&i.isIshtar||e.isEmpire&&i.isEmpire?!0:!e.isIshtar&&!e.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(),s=this.mapReader.getAreas(),e=new Map;for(const a of s){const c=a.getAreaId(),l=a.getRooms();if(l.length===0)continue;let d=1/0,g=-1/0,u=1/0,f=-1/0,y=0;for(const k of l)k.z===0&&(y++,d=Math.min(d,k.x),g=Math.max(g,k.x),u=Math.min(u,k.y),f=Math.max(f,k.y));if(y===0)for(const k of l)d=Math.min(d,k.x),g=Math.max(g,k.x),u=Math.min(u,k.y),f=Math.max(f,k.y);const p=(d+g)/2,x=(u+f)/2;e.set(c,{minX:d,maxX:g,minY:u,maxY:f,centerX:p,centerY:x,roomCount:l.length})}let i=1;for(const a of e.values()){const c=a.maxX-a.minX,l=a.maxY-a.minY;i=Math.max(i,c,l)}const o=200,n=100,r=o/i;for(const a of s){const c=a.getAreaId(),l=e.get(c);if(!l||!this.isAreaInDomain(c))continue;const d=l.maxX-l.minX,g=l.maxY-l.minY;let u=Math.max(n,d*r),f=Math.max(n,g*r);const y=u/f;y>3?f=u/3:y<1/3&&(u=f/3),this.areaNodes.set(c,{areaId:c,name:a.getAreaName(),x:0,y:0,width:u,height:f,connections:[],roomCount:l.roomCount,realCenterX:l.centerX,realCenterY:l.centerY})}const h=new Map;for(const a of t){const c=a.area;if(!this.areaNodes.has(c))continue;const l=this.getLockedDirections(a),d=new Set(a.mSpecialExitLocks??[]);for(const[g,u]of Object.entries(a.exits??{})){if(l.has(g))continue;const f=this.mapReader.getRoom(u);if(!f||f.area===c||!this.areaNodes.has(f.area)||!this.areAreasInSameDomain(c,f.area))continue;const y=this.createConnection(a,f,g);y&&this.addConnection(h,y)}for(const[g,u]of Object.entries(a.specialExits??{})){if(d.has(u))continue;const f=this.mapReader.getRoom(u);if(!f||f.area===c||!this.areaNodes.has(f.area)||!this.areAreasInSameDomain(c,f.area))continue;const y=this.parseDirection(g),p=this.createConnection(a,f,y);p&&this.addConnection(h,p)}}for(const[a,c]of h){const[l,d]=a.split("-").map(Number),g=this.createConnectionGroup(l,d,c);this.connectionGroups.push(g);const u=this.areaNodes.get(l),f=this.areaNodes.get(d);if(u&&u.connections.push(...c),f)for(const y of c)f.connections.push({...y,fromAreaId:y.toAreaId,toAreaId:y.fromAreaId,fromRoomId:y.toRoomId,toRoomId:y.fromRoomId,direction:y.direction?Lt[y.direction]:null,fromRoomPosition:y.toRoomPosition,toRoomPosition:y.fromRoomPosition})}}getLockedDirections(t){return new Set((t.exitLocks??[]).map(s=>ue[s]).filter(s=>!!s))}createConnection(t,s,e){const i=this.toPlanarDirection(e);return{fromAreaId:t.area,toAreaId:s.area,fromRoomId:t.id,toRoomId:s.id,direction:i,fromRoomPosition:{x:t.x,y:t.y},toRoomPosition:{x:s.x,y:s.y}}}addConnection(t,s){const e=s.fromAreaId<s.toAreaId?`${s.fromAreaId}-${s.toAreaId}`:`${s.toAreaId}-${s.fromAreaId}`;t.has(e)||t.set(e,[]),t.get(e).push(s)}createConnectionGroup(t,s,e){const i=new Map;let o=0,n=0;for(const a of e)a.direction&&i.set(a.direction,(i.get(a.direction)??0)+1),o+=a.toRoomPosition.x-a.fromRoomPosition.x,n+=a.toRoomPosition.y-a.fromRoomPosition.y;let r=null,h=0;for(const[a,c]of i)c>h&&(h=c,r=a);return{fromAreaId:t,toAreaId:s,connections:e,primaryDirection:r,averageOffset:{x:o/e.length,y:n/e.length}}}parseDirection(t){const s=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"}[s]??null}toPlanarDirection(t){return t&&ut.includes(t)?t:null}layoutAreas(){if(Array.from(this.areaNodes.values()).length===0)return;const s=this.findConnectedComponents();let e=0;const i=this.settings.areaWidth*3;for(const o of s)if(o.length===1){const n=this.areaNodes.get(o[0]);n&&(n.x=e,n.y=0),e+=this.settings.areaWidth+i}else{const n=this.forceDirectedLayout(o);for(const h of o){const a=this.areaNodes.get(h);a&&isFinite(n.minX)&&isFinite(n.minY)&&(a.x-=n.minX,a.x+=e,a.y-=n.minY)}const r=isFinite(n.maxX-n.minX)?n.maxX-n.minX:this.settings.areaWidth;e+=r+i}}findConnectedComponents(){const t=new Set,s=[];for(const[e]of this.areaNodes){if(t.has(e))continue;const i=[],o=[e];for(;o.length>0;){const n=o.shift();if(t.has(n))continue;t.add(n),i.push(n);const r=this.areaNodes.get(n);if(r)for(const h of r.connections)t.has(h.toAreaId)||o.push(h.toAreaId)}s.push(i)}return s}forceDirectedLayout(t){const s=new Map;for(const w of t){const R=this.areaNodes.get(w);if(!R)continue;const E=new Set(R.connections.map(C=>C.toAreaId));s.set(w,E)}const e=new Set,i=new Set;for(const[w,R]of s)R.size>=3&&e.add(w);for(const[w,R]of s){if(e.has(w)||i.has(w)||R.size>2)continue;const E=[w];i.add(w);const C=Array.from(R);for(const M of C){let I=M,W=w;for(;I&&!i.has(I)&&!e.has(I);){const v=s.get(I);if(!v)break;if(v.size>=3){e.add(I);break}E.push(I),i.add(I);let z=!1;for(const Y of v)if(Y!==W&&!i.has(Y)){W=I,I=Y,z=!0;break}if(!z)break}}let S=!1;for(const M of E){const I=s.get(M);if(I){for(const W of I)if(e.has(W)){S=!0;break}}if(S)break}if(!S&&E.length>0){let M=E[0],I=s.get(E[0])?.size??0;for(const W of E){const v=s.get(W)?.size??0;v>I&&(I=v,M=W)}e.add(M),i.delete(M)}}for(const w of t){const R=s.get(w);(!R||R.size===0)&&e.add(w)}const o=new Map,n=new Map;for(const w of e)o.set(w,w),n.set(w,[]);const r=new Set(e);for(const w of e){const R=s.get(w)??new Set;for(const E of R){if(r.has(E))continue;const C=[];let S=E,M=w;for(;S&&!r.has(S);){C.push(S),o.set(S,w),r.add(S);const I=s.get(S)??new Set;let W;for(const v of I)if(v!==M&&!r.has(v)){W=v;break}M=S,S=W}C.length>0&&n.get(w).push(C)}}const h=new Set,a=[],c=e.values().next().value,l=c!==void 0?c:t[0];if(l!==void 0){const w=this.areaNodes.get(l);w&&(w.x=0,w.y=0,h.add(l),a.push(l))}for(;a.length>0;){const w=a.shift(),R=this.areaNodes.get(w),E=new Map;for(const C of R.connections){const S=C.toAreaId;if(h.has(S)||!e.has(S))continue;const M=this.areaNodes.get(S);if(!M)continue;const I=C.direction??"none";E.has(I)||E.set(I,[]),E.get(I).push({id:S,node:M,conn:C})}for(const[C,S]of E){const M=this.getDirectionOffset(C==="none"?null:C);S.sort((v,z)=>Math.abs(M.x)>Math.abs(M.y)?z.node.realCenterY-v.node.realCenterY:v.node.realCenterX-z.node.realCenterX);const I=this.settings.areaWidth+this.settings.areaSpacing,W=this.settings.areaHeight+this.settings.areaSpacing;S.forEach((v,z)=>{if(v.node.x=R.x+M.x*I,v.node.y=R.y+M.y*W,S.length>1){const Y=(z-(S.length-1)/2)*.5;Math.abs(M.x)>Math.abs(M.y)?v.node.y+=Y*W:v.node.x+=Y*I}h.add(v.id),a.push(v.id)})}}const d=Array.from(e);d.length>1&&this.applyForces(d,80);const g=this.settings.areaWidth+this.settings.areaSpacing+30,u=this.settings.areaHeight+this.settings.areaSpacing+30,f=new Map,y=["east","west","north","south","northeast","northwest","southeast","southwest"];for(const[w,R]of n){const E=this.areaNodes.get(w);if(!E)continue;let C=0;const S=new Map;for(const M of R){let I=w,W=E.x,v=E.y,z=null;for(const Y of M){const P=this.areaNodes.get(Y);if(!P)continue;const O=this.areaNodes.get(I);let T=null;if(O){for(const B of O.connections)if(B.toAreaId===Y){T=B.direction;break}}!T&&I===w?(z=y[C%y.length],C++,T=z):!T&&z&&(T=z);const F=this.getDirectionOffset(T);let Z=0;if(I===w&&T){const B=T,rt=S.get(B)??0;S.set(B,rt+1),Z=rt}P.x=W+F.x*g,P.y=v+F.y*u,Z>0&&(F.x!==0&&F.y===0?P.y+=Z*u*1.2:F.y!==0&&F.x===0?P.x+=Z*g*1.2:(P.x+=Z*g*1.2,P.y-=Z*u*1.2)),f.set(Y,{dx:P.x-E.x,dy:P.y-E.y,hubId:w}),I=Y,W=P.x,v=P.y}}}const p=new Map,x=new Map;for(const w of e){const R=this.areaNodes.get(w);if(!R)continue;let E=R.x,C=R.y,S=R.x+R.width,M=R.y+R.height;const I=n.get(w)??[];for(const W of I)for(const v of W){const z=this.areaNodes.get(v);z&&(E=Math.min(E,z.x),C=Math.min(C,z.y),S=Math.max(S,z.x+z.width),M=Math.max(M,z.y+z.height))}p.set(w,{minX:E,minY:C,maxX:S,maxY:M}),x.set(w,{dx:E-R.x,dy:C-R.y})}this.applyClusterForces(d,p,x,60);for(const[w,R]of f){const E=this.areaNodes.get(w),C=this.areaNodes.get(R.hubId);!E||!C||(E.x=C.x+R.dx,E.y=C.y+R.dy)}let k=1/0,D=1/0,$=-1/0,X=-1/0;for(const w of t){const R=this.areaNodes.get(w);k=Math.min(k,R.x),D=Math.min(D,R.y),$=Math.max($,R.x+R.width),X=Math.max(X,R.y+R.height)}return{minX:k,minY:D,maxX:$,maxY:X}}getDirectionOffset(t){const s={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&&s[t]?s[t]:{x:1,y:0}}applyClusterForces(t,s,e,i){const r=new Map;for(const h of t)r.set(h,{vx:0,vy:0});for(let h=0;h<i;h++){for(const a of t){const c=this.areaNodes.get(a),l=s.get(a),d=e.get(a);if(!c||!l||!d)continue;const g=l.maxX-l.minX,u=l.maxY-l.minY;l.minX=c.x+d.dx,l.minY=c.y+d.dy,l.maxX=l.minX+g,l.maxY=l.minY+u}for(const a of t){const c=this.areaNodes.get(a),l=r.get(a),d=s.get(a);if(!(!c||!l||!d)){for(const g of t){if(a===g)continue;const u=s.get(g);if(!u)continue;const f=(d.minX+d.maxX)/2,y=(d.minY+d.maxY)/2,p=(u.minX+u.maxX)/2,x=(u.minY+u.maxY)/2,k=f-p,D=y-x,$=(d.maxX-d.minX)/2,X=(d.maxY-d.minY)/2,w=(u.maxX-u.minX)/2,R=(u.maxY-u.minY)/2,E=$+w+50,C=X+R+50,S=E-Math.abs(k),M=C-Math.abs(D);if(S>0&&M>0)if(S<M){const I=S*(k>=0?1:-1)*.5;l.vx+=I}else{const I=M*(D>=0?1:-1)*.5;l.vy+=I}}for(const g of c.connections){const u=this.areaNodes.get(g.toAreaId);if(!u||!t.includes(g.toAreaId))continue;const f=u.x-c.x,y=u.y-c.y,p=Math.sqrt(f*f+y*y)||1,x=this.settings.areaWidth+this.settings.areaSpacing+50,D=(p-x)*.015;l.vx+=f/p*D,l.vy+=y/p*D}}}for(const a of t){const c=this.areaNodes.get(a),l=r.get(a);!c||!l||(c.x+=l.vx,c.y+=l.vy,l.vx*=.8,l.vy*=.8)}}}applyForces(t,s){const o=this.settings.areaWidth+this.settings.areaSpacing,n=this.settings.areaWidth/2+60,r=new Set(t),h=[],a=new Set;for(const l of t){const d=this.areaNodes.get(l);if(d)for(const g of d.connections){if(!r.has(g.toAreaId))continue;const u=Math.min(l,g.toAreaId)+"-"+Math.max(l,g.toAreaId);a.has(u)||(a.add(u),h.push({from:l,to:g.toAreaId}))}}const c=new Map;for(const l of t)c.set(l,{vx:0,vy:0});for(let l=0;l<s;l++){for(const d of t){const g=this.areaNodes.get(d),u=c.get(d);if(!g||!u)continue;const f=g.x+g.width/2,y=g.y+g.height/2;for(const p of t){if(d===p)continue;const x=this.areaNodes.get(p);if(!x)continue;const k=(g.width+x.width)/2+20,D=(g.height+x.height)/2+20,$=g.x+g.width/2,X=g.y+g.height/2,w=x.x+x.width/2,R=x.y+x.height/2,E=$-w,C=X-R,S=k-Math.abs(E),M=D-Math.abs(C);S>0&&M>0&&(S<M?u.vx+=(E>=0?1:-1)*S*.5:u.vy+=(C>=0?1:-1)*M*.5)}for(const p of h){if(p.from===d||p.to===d)continue;const x=this.areaNodes.get(p.from),k=this.areaNodes.get(p.to);if(!x||!k)continue;const D=x.x+x.width/2,$=x.y+x.height/2,X=k.x+k.width/2,w=k.y+k.height/2,R=this.closestPointOnSegment(f,y,D,$,X,w),E=f-R.x,C=y-R.y,S=Math.sqrt(E*E+C*C)||1;if(S<n){const M=(n-S)*.6;u.vx+=E/S*M,u.vy+=C/S*M}}for(const p of g.connections){if(!r.has(p.toAreaId))continue;const x=this.areaNodes.get(p.toAreaId);if(!x)continue;const k=x.x-g.x,D=x.y-g.y,$=Math.sqrt(k*k+D*D)||1,w=($-o)*.03;u.vx+=k/$*w,u.vy+=D/$*w;const R=this.getDirectionOffset(p.direction),E=g.x+R.x*o,C=g.y+R.y*o,S=c.get(p.toAreaId);S&&(S.vx+=(E-x.x)*.01,S.vy+=(C-x.y)*.01)}}for(const d of t){const g=this.areaNodes.get(d),u=c.get(d);!g||!u||(g.x+=u.vx,g.y+=u.vy,u.vx*=.8,u.vy*=.8)}}}closestPointOnSegment(t,s,e,i,o,n){const r=o-e,h=n-i,a=t-e,c=s-i,l=r*r+h*h;if(l===0)return{x:e,y:i};let d=(a*r+c*h)/l;return d=Math.max(0,Math.min(1,d)),{x:e+d*r,y:i+d*h}}edgesIntersect(t,s,e,i,o,n,r,h){const a=(c,l,d,g,u,f)=>(f-l)*(d-c)>(g-l)*(u-c);return a(t,s,o,n,r,h)!==a(e,i,o,n,r,h)&&a(t,s,e,i,o,n)!==a(t,s,e,i,r,h)}drawConnections(){this.connectionLayer.destroyChildren();for(const t of this.connectionGroups){const s=this.areaNodes.get(t.fromAreaId),e=this.areaNodes.get(t.toAreaId);if(!s||!e||!isFinite(s.x)||!isFinite(s.y)||!isFinite(e.x)||!isFinite(e.y))continue;const i={x:s.x+s.width/2,y:s.y+s.height/2},o={x:e.x+e.width/2,y:e.y+e.height/2};let n,r;if(this.dotsMode?(n=i,r=o):(n=this.getEdgePoint(s,o),r=this.getEdgePoint(e,i)),!isFinite(n.x)||!isFinite(n.y)||!isFinite(r.x)||!isFinite(r.y))continue;const h=this.dotsMode?"#ffffff":this.settings.connectionColor,a=this.dotsMode?1:Math.min(this.settings.connectionLineWidth,1+t.connections.length*.5),c=new b.Line({points:[n.x,n.y,r.x,r.y],stroke:h,strokeWidth:a,lineCap:"round",listening:!1});this.connectionLayer.add(c)}}getEdgePoint(t,s){const e=t.x+t.width/2,i=t.y+t.height/2,o=s.x-e,n=s.y-i,r=t.width/2,h=t.height/2;if(o===0&&n===0)return{x:e,y:i};const a=Math.abs(o),c=Math.abs(n);let l;return a/r>c/h?l=r/a:l=h/c,{x:e+o*l,y:i+n*l}}drawAreas(){this.areaLayer.destroyChildren();for(const[,t]of this.areaNodes){if(!isFinite(t.x)||!isFinite(t.y))continue;const s=t.areaId===this.highlightedArea;if(this.dotsMode){const i=t.x+t.width/2,o=t.y+t.height/2,n=new b.Group({x:i,y:o,draggable:!0}),r=new b.Circle({radius:6,fill:s?this.settings.highlightColor:"#ffffff",stroke:s?this.settings.highlightColor:"#ffffff",strokeWidth:1}),h=new b.Text({text:t.name,fontSize:10,fill:"#ffffff",x:10,y:-5});n.add(r),n.add(h),n.on("click tap",()=>{this.emitAreaClickEvent(t.areaId)}),n.on("mouseenter",()=>{this.stage.container().style.cursor="pointer",r.fill(this.settings.highlightColor),r.stroke(this.settings.highlightColor),this.areaLayer.batchDraw()}),n.on("mouseleave",()=>{this.stage.container().style.cursor="auto",r.fill(s?this.settings.highlightColor:"#ffffff"),r.stroke(s?this.settings.highlightColor:"#ffffff"),this.areaLayer.batchDraw()}),n.on("dragmove",()=>{t.x=n.x()-t.width/2,t.y=n.y()-t.height/2,this.drawConnections(),this.connectionLayer.batchDraw()}),n.on("dragstart",()=>{this.stage.container().style.cursor="grabbing"}),n.on("dragend",()=>{this.stage.container().style.cursor="pointer"}),this.areaLayer.add(n)}else{const e=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:s?this.settings.highlightColor:this.settings.areaStrokeColor,strokeWidth:s?3:2,cornerRadius:8}),o=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"}),n=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"});e.add(i),e.add(o),e.add(n),e.on("click tap",()=>{this.emitAreaClickEvent(t.areaId)}),e.on("mouseenter",()=>{this.stage.container().style.cursor="pointer",i.stroke(this.settings.highlightColor),this.areaLayer.batchDraw()}),e.on("mouseleave",()=>{this.stage.container().style.cursor="auto",i.stroke(s?this.settings.highlightColor:this.settings.areaStrokeColor),this.areaLayer.batchDraw()}),e.on("dragmove",()=>{t.x=e.x(),t.y=e.y(),this.drawConnections(),this.connectionLayer.batchDraw()}),e.on("dragstart",()=>{this.stage.container().style.cursor="grabbing"}),e.on("dragend",()=>{this.stage.container().style.cursor="pointer"}),this.areaLayer.add(e)}}}centerView(){let t=1/0,s=1/0,e=-1/0,i=-1/0;for(const[,u]of this.areaNodes)t=Math.min(t,u.x),s=Math.min(s,u.y),e=Math.max(e,u.x+u.width),i=Math.max(i,u.y+u.height);if(!isFinite(t))return;const o=e-t,n=i-s,r=t+o/2,h=s+n/2,a=50,c=(this.stage.width()-a*2)/o,l=(this.stage.height()-a*2)/n,d=Math.min(c,l,1.5);this.setZoom(d);const g=this.stage.scaleX();this.stage.position({x:this.stage.width()/2-r*g,y:this.stage.height()/2-h*g})}highlightArea(t){this.highlightedArea=t,this.drawAreas(),this.stage.batchDraw()}centerOnArea(t){const s=this.areaNodes.get(t);if(!s)return;const e=this.stage.scaleX(),i=s.x+s.width/2,o=s.y+s.height/2;this.stage.position({x:this.stage.width()/2-i*e,y:this.stage.height()/2-o*e}),this.stage.batchDraw()}emitAreaClickEvent(t){const s=new CustomEvent("areaclick",{detail:{areaId:t}});this.stage.container().dispatchEvent(s)}getAreaNode(t){return this.areaNodes.get(t)}getConnectionGroups(){return this.connectionGroups}destroy(){this.stage.destroy()}}const me={1:"north",2:"northeast",3:"northwest",4:"east",5:"west",6:"south",7:"southeast",8:"southwest",9:"up",10:"down",11:"in",12:"out"},pe=["up","down","in","out"],U={1:"rgb(10, 155, 10)",2:"rgb(226, 205, 59)",3:"rgb(155, 10, 10)"};class Pt{constructor(t,s){this.mapReader=t,this.settings=s,this.exitRenderer=new mt(t,null,s)}getSymbolColor(t,s){return this.settings.frameMode?this.mapReader.getColorValue(t):this.mapReader.getSymbolColor(t,s)}render(t,s,e,i){const o=this.mapReader.getArea(s);if(!o)throw new Error(`Area ${s} not found`);const n=o.getPlane(e);if(!n)throw new Error(`Plane z=${e} not found in area ${s}`);const r=i.padding??3,h=this.computeBounds(o,n,i.roomId,r),a=i.width/h.w,c=i.height/h.h,l=Math.min(a,c);t.save(),t.fillStyle=this.settings.backgroundColor,t.fillRect(0,0,i.width,i.height);const d=h.w*l,g=h.h*l;if(t.translate((i.width-d)/2,(i.height-g)/2),t.scale(l,l),t.translate(-h.x,-h.y),this.settings.gridEnabled){const f=(i.width-d)/2,y=(i.height-g)/2,p={x:h.x-f/l,y:h.y-y/l,w:i.width/l,h:i.height/l};this.renderGrid(t,p)}this.renderLabels(t,n.getLabels()),this.renderLinkExits(t,o,e),this.renderSpecialExits(t,n.getRooms()),this.renderStubs(t,n.getRooms()),this.renderRooms(t,n.getRooms()),this.renderInnerExits(t,n.getRooms());const u=i.overlays;if(u){if(u.paths)for(const f of u.paths)this.renderPathOverlay(t,f.locations,f.color,s,e);if(u.highlights)for(const f of u.highlights)this.renderHighlightOverlay(t,f.roomId,f.color);u.position&&this.renderPositionMarker(t,u.position.roomId)}if(this.settings.areaName){const f=o.getAreaName();if(f){const y=this.getEffectiveBounds(o,n);t.fillStyle="white",t.font=`2.5px ${this.settings.fontFamily}`,t.textAlign="left",t.textBaseline="bottom",t.fillText(f,y.minX-3.5,y.minY-2)}}t.restore()}computeBounds(t,s,e,i){if(e!==void 0){const g=this.mapReader.getRoom(e);if(!g)throw new Error(`Room ${e} not found`);return{x:g.x-i,y:g.y-i,w:i*2,h:i*2}}const o=this.getEffectiveBounds(t,s),n=this.settings.areaName?t.getAreaName():void 0,r=n?7:0,h=n?3.5:0,a=o.minX-h,c=o.minY-r,l=n?o.minX-3.5+n.length*2.5*.6:-1/0,d=Math.max(o.maxX,l);return{x:a-i,y:c-i,w:d-a+i*2,h:o.maxY-c+i*2}}getEffectiveBounds(t,s){return this.settings.uniformLevelSize?t.getFullBounds():s.getBounds()}getRoomEdgePoint(t,s,e,i){return this.settings.roomShape==="circle"?ot(t,s,e,i):this.settings.roomShape==="roundedRectangle"?it(t,s,e,i,this.settings.roomSize*.2):L(t,s,e,i)}renderGrid(t,s){const e=this.settings.gridSize,i=Math.floor(s.x/e)*e,o=Math.ceil((s.x+s.w)/e)*e,n=Math.floor(s.y/e)*e,r=Math.ceil((s.y+s.h)/e)*e;t.strokeStyle=this.settings.gridColor,t.lineWidth=this.settings.gridLineWidth,t.setLineDash([]);for(let h=i;h<=o;h+=e)t.beginPath(),t.moveTo(h,n),t.lineTo(h,r),t.stroke();for(let h=n;h<=r;h+=e)t.beginPath(),t.moveTo(i,h),t.lineTo(o,h),t.stroke()}renderLabels(t,s){for(const e of s){const i=e.X,o=-e.Y;if((e.BgColor?.alpha??0)>0&&!this.settings.transparentLabels){const n=(e.BgColor.alpha??255)/255;t.fillStyle=`rgba(${e.BgColor.r},${e.BgColor.g},${e.BgColor.b},${n})`,t.fillRect(i,o,e.Width,e.Height)}if(e.Text){const n=(e.FgColor?.alpha??255)/255;t.fillStyle=`rgba(${e.FgColor?.r??0},${e.FgColor?.g??0},${e.FgColor?.b??0},${n})`;const r=Math.min(.75,e.Width/Math.max(e.Text.length/2,1)),h=Math.max(.1,Math.min(r,Math.max(e.Height*.9,.1)));t.font=`${h}px ${this.settings.fontFamily}`,t.textAlign="center",t.textBaseline="middle",t.fillText(e.Text,i+e.Width/2,o+e.Height/2)}}}renderLinkExits(t,s,e){const i=s.getLinkExits(e);for(const o of i){const n=this.exitRenderer.renderData(o,e);n&&this.drawExitData(t,n)}}drawExitData(t,s){for(const e of s.lines){t.beginPath(),t.moveTo(e.points[0],e.points[1]);for(let i=2;i<e.points.length;i+=2)t.lineTo(e.points[i],e.points[i+1]);t.strokeStyle=e.stroke,t.lineWidth=e.strokeWidth,t.setLineDash(e.dash??[]),t.stroke()}for(const e of s.arrows){t.beginPath(),t.moveTo(e.points[0],e.points[1]);for(let d=2;d<e.points.length;d+=2)t.lineTo(e.points[d],e.points[d+1]);t.strokeStyle=e.stroke,t.lineWidth=e.strokeWidth,t.setLineDash(e.dash??[]),t.stroke();const i=e.points.length-2,o=e.points[i],n=e.points[i+1],r=e.points[i-2],h=e.points[i-1],a=Math.atan2(n-h,o-r),c=e.pointerLength,l=e.pointerWidth/2;t.beginPath(),t.setLineDash([]),t.moveTo(o,n),t.lineTo(o-c*Math.cos(a-Math.atan2(l,c)),n-c*Math.sin(a-Math.atan2(l,c))),t.lineTo(o-c*Math.cos(a+Math.atan2(l,c)),n-c*Math.sin(a+Math.atan2(l,c))),t.closePath(),t.fillStyle=e.fill,t.fill(),t.strokeStyle=e.stroke,t.lineWidth=e.strokeWidth,t.stroke()}for(const e of s.doors)t.beginPath(),t.rect(e.x,e.y,e.width,e.height),t.strokeStyle=e.stroke,t.lineWidth=e.strokeWidth,t.setLineDash([]),t.stroke()}renderStubs(t,s){t.strokeStyle=this.settings.lineColor,t.lineWidth=this.settings.lineWidth,t.setLineDash([]);for(const e of s)for(const i of e.stubs){const o=me[i];if(!o)continue;const n=this.getRoomEdgePoint(e.x,e.y,o,this.settings.roomSize/2),r=L(e.x,e.y,o,this.settings.roomSize/2+.5);t.beginPath(),t.moveTo(n.x,n.y),t.lineTo(r.x,r.y),t.stroke()}}renderSpecialExits(t,s){for(const e of s)for(const[i,o]of Object.entries(e.customLines)){const n=[e.x,e.y];for(const a of o.points)n.push(a.x,-a.y);const r=`rgb(${o.attributes.color.r}, ${o.attributes.color.g}, ${o.attributes.color.b})`;t.strokeStyle=r,t.lineWidth=this.settings.lineWidth,o.attributes.style==="dot line"?t.setLineDash([.05,.05]):o.attributes.style==="dash line"?t.setLineDash([.4,.2]):t.setLineDash([]),t.beginPath(),t.moveTo(n[0],n[1]);for(let a=2;a<n.length;a+=2)t.lineTo(n[a],n[a+1]);if(t.stroke(),o.attributes.arrow&&n.length>=4){const a=n.length-2,c=n[a],l=n[a+1],d=n[a-2],g=n[a-1],u=Math.atan2(l-g,c-d),f=.3,y=.1;t.beginPath(),t.setLineDash([]),t.moveTo(c,l),t.lineTo(c-f*Math.cos(u-Math.atan2(y,f)),l-f*Math.sin(u-Math.atan2(y,f))),t.lineTo(c-f*Math.cos(u+Math.atan2(y,f)),l-f*Math.sin(u+Math.atan2(y,f))),t.closePath(),t.fillStyle=r,t.fill()}const h=e.doors[i];if(h&&n.length>=4){const a=n[0]+(n[2]-n[0])/2,c=n[1]+(n[3]-n[1])/2,l=this.settings.roomSize/2;t.beginPath(),t.rect(a-l/2,c-l/2,l,l),t.strokeStyle=U[h]??U[3],t.lineWidth=this.settings.lineWidth,t.setLineDash([]),t.stroke()}}}renderRooms(t,s){const e=this.settings.roomSize,i=e/2;for(const o of s){const n=this.mapReader.getColorValue(o.env),r=this.settings.frameMode?this.settings.backgroundColor:n,h=this.settings.frameMode?n:this.settings.lineColor;if(t.fillStyle=r,t.strokeStyle=h,t.lineWidth=this.settings.lineWidth,t.setLineDash([]),this.settings.roomShape==="circle")t.beginPath(),t.arc(o.x,o.y,i,0,Math.PI*2),t.fill(),t.stroke();else{const a=o.x-i,c=o.y-i,l=this.settings.roomShape==="roundedRectangle"?e*.2:0;if(l>0?(this.roundRect(t,a,c,e,e,l),t.fill(),t.stroke()):(t.fillRect(a,c,e,e),t.strokeRect(a,c,e,e)),this.settings.emboss){const d=q(this.settings.lineColor)>.41;t.beginPath(),d?(t.moveTo(a,c),t.lineTo(a+e,c),t.lineTo(a+e,c+e)):(t.moveTo(a,c),t.lineTo(a,c+e),t.lineTo(a+e,c+e)),t.strokeStyle=d?"#000000":"#ffffff",t.lineWidth=this.settings.lineWidth,t.stroke()}}if(o.roomChar){const a=this.getSymbolColor(o.env),c=e*.75;t.fillStyle=a,t.font=`bold ${c}px ${this.settings.fontFamily}`,t.textAlign="left",t.textBaseline="alphabetic";const l=t.measureText(o.roomChar);t.fillText(o.roomChar,o.x-l.width/2,o.y+c*.35)}}}roundRect(t,s,e,i,o,n){t.beginPath(),t.moveTo(s+n,e),t.lineTo(s+i-n,e),t.arcTo(s+i,e,s+i,e+n,n),t.lineTo(s+i,e+o-n),t.arcTo(s+i,e+o,s+i-n,e+o,n),t.lineTo(s+n,e+o),t.arcTo(s,e+o,s,e+o-n,n),t.lineTo(s,e+n),t.arcTo(s,e,s+n,e,n),t.closePath()}renderInnerExits(t,s){const e=this.settings.roomSize,i=e/5;for(const o of s)for(const n of pe){if(!o.exits[n])continue;const r=this.getSymbolColor(o.env),h=this.getSymbolColor(o.env,.6),a=o.doors[n],c=a!==void 0?U[a]??U[3]:r;switch(n){case"up":{const l=L(o.x,o.y,"south",e/4);this.drawTriangle(t,l.x,l.y,i,0,h,c);break}case"down":{const l=L(o.x,o.y,"north",e/4);this.drawTriangle(t,l.x,l.y,i,180,h,c);break}case"in":{const l=L(o.x,o.y,"west",e/4),d=L(o.x,o.y,"east",e/4);this.drawTriangle(t,l.x,l.y,i,90,h,c),this.drawTriangle(t,d.x,d.y,i,-90,h,c);break}case"out":{const l=L(o.x,o.y,"west",e/4),d=L(o.x,o.y,"east",e/4);this.drawTriangle(t,l.x,l.y,i,-90,h,c),this.drawTriangle(t,d.x,d.y,i,90,h,c);break}}}}drawTriangle(t,s,e,i,o,n,r){const c=o*Math.PI/180;t.beginPath();for(let l=0;l<3;l++){const d=2*Math.PI*l/3-Math.PI/2;let g=Math.cos(d)*i*1.4,u=Math.sin(d)*i*.8;const f=g*Math.cos(c)-u*Math.sin(c),y=g*Math.sin(c)+u*Math.cos(c);l===0?t.moveTo(s+f,e+y):t.lineTo(s+f,e+y)}t.closePath(),t.fillStyle=n,t.fill(),t.strokeStyle=r,t.lineWidth=this.settings.lineWidth,t.stroke()}renderPathOverlay(t,s,e,i,o){const n=nt(this.mapReader,this.settings,s,i,o),r=this.settings.lineWidth;t.save(),t.globalAlpha=.8,t.lineCap="round",t.lineJoin="round",t.setLineDash([]);const h=c=>{if(!(c.length<4)){t.beginPath(),t.moveTo(c[0],c[1]);for(let l=2;l<c.length;l+=2)t.lineTo(c[l],c[l+1]);t.strokeStyle="black",t.lineWidth=r*8,t.stroke(),t.beginPath(),t.moveTo(c[0],c[1]);for(let l=2;l<c.length;l+=2)t.lineTo(c[l],c[l+1]);t.strokeStyle=e,t.lineWidth=r*4,t.stroke()}};for(const c of n.segments)h(c.points);for(const c of n.customLines)h(c.points);const a=this.settings.roomSize/5;for(const c of n.innerMarkers){const l=c.direction==="up"?0:c.direction==="down"?180:c.direction==="in"?90:-90;this.drawTriangle(t,c.room.x,c.room.y,a,l,e,"black")}t.restore()}renderHighlightOverlay(t,s,e){const i=this.mapReader.getRoom(s);if(!i)return;const o=1.5,n=this.settings.roomSize;if(t.strokeStyle=e,t.lineWidth=.1,t.setLineDash([.05,.05]),this.settings.roomShape==="circle")t.beginPath(),t.arc(i.x,i.y,n/2*o,0,Math.PI*2),t.stroke();else{const r=n*o;t.strokeRect(i.x-r/2,i.y-r/2,r,r)}t.setLineDash([])}renderPositionMarker(t,s){const e=this.mapReader.getRoom(s);if(!e)return;const i=this.settings.playerMarker,o=this.settings.roomSize*i.sizeFactor;t.save(),t.globalAlpha=i.strokeAlpha,t.strokeStyle=i.strokeColor,t.lineWidth=i.strokeWidth,t.setLineDash(i.dashEnabled&&i.dash?i.dash:[]),t.beginPath(),t.arc(e.x,e.y,o/2,0,Math.PI*2),t.stroke(),i.fillAlpha>0&&(t.globalAlpha=i.fillAlpha,t.fillStyle=i.fillColor,t.fill()),t.restore()}}class ye{constructor(t,s){this.highlights=new Map,this.paths=[],this.mapReader=t,this.settings=s??yt()}drawArea(t,s){const e=this.mapReader.getArea(t);!e||!e.getPlane(s)||(this.currentArea=t,this.currentAreaInstance=e,this.currentZIndex=s)}getCurrentArea(){return this.currentAreaInstance}setPosition(t){this.positionRoomId=t}clearPosition(){this.positionRoomId=void 0}renderPath(t,s="#66E64D"){this.paths.push({locations:t,color:s})}clearPaths(){this.paths=[]}renderHighlight(t,s){const e=this.mapReader.getRoom(t);e&&this.highlights.set(t,{color:s,area:e.area,z:e.z})}removeHighlight(t){this.highlights.delete(t)}hasHighlight(t){return this.highlights.has(t)}clearHighlights(){this.highlights.clear()}exportSvg(t){if(this.currentArea===void 0||this.currentZIndex===void 0)return;const s={...t,overlays:this.buildOverlays(t?.overlays)};return new pt(this.mapReader,this.settings).export(this.currentArea,this.currentZIndex,s)}renderToCanvas(t,s){if(this.currentArea===void 0||this.currentZIndex===void 0)return;const e={...s,overlays:this.buildOverlays(s?.overlays)};new Pt(this.mapReader,this.settings).render(t,this.currentArea,this.currentZIndex,e)}buildOverlays(t){const s={...t};if(this.positionRoomId!==void 0){const o=this.mapReader.getRoom(this.positionRoomId);o&&o.area===this.currentArea&&o.z===this.currentZIndex&&(s.position={roomId:this.positionRoomId})}const e=[...t?.highlights??[]];for(const[o,n]of this.highlights)n.area===this.currentArea&&n.z===this.currentZIndex&&e.push({roomId:o,color:n.color});e.length>0&&(s.highlights=e);const i=[...t?.paths??[]];return i.push(...this.paths),i.length>0&&(s.paths=i),s}}exports.AreaMapRenderer=fe;exports.CanvasExporter=Pt;exports.ExplorationArea=J;exports.HeadlessRenderer=ye;exports.MapReader=Qt;exports.PathFinder=ge;exports.Renderer=Kt;exports.SvgExporter=pt;exports.colorLightness=q;exports.computePathData=nt;exports.createAreaMapSettings=$t;exports.createSettings=yt;
3
3
  //# sourceMappingURL=index.cjs.map