mudlet-map-renderer 0.15.0-konva → 0.16.0-konva

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