mudlet-map-renderer 0.11.3-konva → 0.12.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.
@@ -24,6 +24,8 @@ type AreaNode = {
24
24
  height: number;
25
25
  connections: AreaConnection[];
26
26
  roomCount: number;
27
+ realCenterX: number;
28
+ realCenterY: number;
27
29
  };
28
30
  type ConnectionGroup = {
29
31
  fromAreaId: number;
@@ -35,6 +37,11 @@ type ConnectionGroup = {
35
37
  y: number;
36
38
  };
37
39
  };
40
+ export type AreaDomainInfo = {
41
+ isIshtar: boolean;
42
+ isEmpire: boolean;
43
+ };
44
+ export type DomainFilter = "ishtar" | "empire" | "interdomain" | "all";
38
45
  export declare class AreaMapSettings {
39
46
  static areaWidth: number;
40
47
  static areaHeight: number;
@@ -49,6 +56,7 @@ export declare class AreaMapSettings {
49
56
  }
50
57
  export declare class AreaMapRenderer {
51
58
  private readonly stage;
59
+ private readonly backgroundLayer;
52
60
  private readonly areaLayer;
53
61
  private readonly connectionLayer;
54
62
  private readonly mapReader;
@@ -56,12 +64,36 @@ export declare class AreaMapRenderer {
56
64
  private connectionGroups;
57
65
  private currentZoom;
58
66
  private highlightedArea?;
67
+ private domainInfo;
68
+ private domainFilter;
69
+ private backgroundImage?;
70
+ private backgroundConfig?;
71
+ private dotsMode;
59
72
  constructor(container: HTMLDivElement, mapReader: MapReader);
60
73
  private initResize;
61
74
  private initScaling;
62
75
  setZoom(zoom: number): void;
63
76
  getZoom(): number;
77
+ setDomainInfo(domainInfo: Record<number, AreaDomainInfo>): void;
78
+ setDomainFilter(filter: DomainFilter): void;
79
+ getDomainFilter(): DomainFilter;
80
+ setBackgroundImage(config: {
81
+ url: string;
82
+ x: number;
83
+ y: number;
84
+ width: number;
85
+ height: number;
86
+ opacity?: number;
87
+ }): void;
88
+ clearBackgroundImage(): void;
89
+ redrawBackground(): void;
90
+ setDotsMode(enabled: boolean): void;
91
+ getDotsMode(): boolean;
92
+ redraw(): void;
93
+ private isAreaInDomain;
94
+ private areAreasInSameDomain;
64
95
  render(): void;
96
+ private drawBackground;
65
97
  private analyzeConnections;
66
98
  private getLockedDirections;
67
99
  private createConnection;
@@ -73,7 +105,10 @@ export declare class AreaMapRenderer {
73
105
  private findConnectedComponents;
74
106
  private forceDirectedLayout;
75
107
  private getDirectionOffset;
108
+ private applyClusterForces;
76
109
  private applyForces;
110
+ private closestPointOnSegment;
111
+ private edgesIntersect;
77
112
  private drawConnections;
78
113
  private getEdgePoint;
79
114
  private drawAreas;
@@ -214,6 +214,7 @@ export declare class Renderer {
214
214
  */
215
215
  refresh(): void;
216
216
  setPosition(roomId: number): void;
217
+ centerOn(roomId: number): void;
217
218
  renderPath(locations: number[], color?: string): import('konva/lib/shapes/Line').Line<{
218
219
  points: number[];
219
220
  stroke: string;
@@ -225,6 +226,7 @@ export declare class Renderer {
225
226
  private refreshHighlights;
226
227
  private createHighlightShape;
227
228
  private centerOnRoom;
229
+ private centerOnRoomView;
228
230
  private renderRooms;
229
231
  private scheduleRoomCulling;
230
232
  private updateRoomCulling;
package/dist/index.cjs CHANGED
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const m=require("konva"),it=["north","south","east","west","northeast","northwest","southeast","southwest"],O={north:"n",south:"s",east:"e",west:"w",northeast:"ne",northwest:"nw",southeast:"se",southwest:"sw",up:"u",down:"d",in:"i",out:"o"},Q={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}},K=["north","south","east","west","northeast","northwest","southeast","southwest"],gt={north:"south",south:"north",east:"west",west:"east",northeast:"southwest",northwest:"southeast",southeast:"northwest",southwest:"northeast"};function ft(f){return f?Object.prototype.hasOwnProperty.call(Q,f):!1}function C(f,t,e,s=1){if(!ft(e))return{x:f,y:t};const i=Q[e];return{x:f+i.x*s,y:t+i.y*s}}function yt(f,t,e,s=1){if(!ft(e))return{x:f,y:t};const i=Q[e],o=Math.atan2(i.y,i.x);return{x:f+Math.cos(o)*s,y:t+Math.sin(o)*s}}const Y={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)"},wt={1:"north",2:"northeast",3:"northwest",4:"east",5:"west",6:"south",7:"southeast",8:"southwest",9:"up",10:"down",11:"in",12:"out"},Rt=["up","down","in","out"];function bt(f){switch(f){case 1:return Y.OPEN_DOOR;case 2:return Y.CLOSED_DOOR;default:return Y.LOCKED_DOOR}}class vt{constructor(t,e){this.mapReader=t,this.mapRenderer=e}getRoomEdgePoint(t,e,s,i){return h.roomShape==="circle"?yt(t,e,s,i):C(t,e,s,i)}render(t,e){return this.renderWithColor(t,h.lineColor,e)}renderWithColor(t,e,s){return t.aDir&&t.bDir?this.renderTwoWayExit(t,e,s):this.renderOneWayExit(t,e)}renderTwoWayExit(t,e,s){const i=this.mapReader.getRoom(t.a),o=this.mapReader.getRoom(t.b);if(!i||!o||!t.aDir||!t.bDir||!it.includes(t.aDir)||!it.includes(t.bDir)||i.customLines[O[t.aDir]]&&o.customLines[O[t.bDir]]||i.z!==o.z&&(s!==o.z&&i.customLines[O[t.aDir]]||s!==i.z&&o.customLines[O[t.bDir]]))return;const r=new m.Group,n=[];if(n.push(...Object.values(this.getRoomEdgePoint(i.x,i.y,t.aDir,h.roomSize/2))),n.push(...Object.values(this.getRoomEdgePoint(o.x,o.y,t.bDir,h.roomSize/2))),i.doors[O[t.aDir]]||o.doors[O[t.bDir]]){const d=this.renderDoor(n,i.doors[O[t.aDir]]??o.doors[O[t.bDir]]);r.add(d)}const a=new m.Line({points:n,stroke:e,strokeWidth:h.lineWidth,perfectDrawEnabled:!1});return r.add(a),r}renderOneWayExit(t,e){const s=t.aDir?this.mapReader.getRoom(t.a):this.mapReader.getRoom(t.b),i=t.aDir?this.mapReader.getRoom(t.b):this.mapReader.getRoom(t.a),o=t.aDir?t.aDir:t.bDir;if(!o||!s||!i||s.customLines[O[o]||o])return;if(s.area!=i.area&&o)return this.renderAreaExit(s,o,e);let r={x:i.x,y:i.y};(i.area!==s.area||i.z!==s.z)&&(r=C(s.x,s.y,o,h.roomSize/2));const n=C(s.x,s.y,o,.3),a=n.x-(n.x-r.x)/2,d=n.y-(n.y-r.y)/2,l=new m.Group,c=[];c.push(...Object.values(this.getRoomEdgePoint(s.x,s.y,o,h.roomSize/2))),c.push(r.x,r.y);const u=new m.Line({points:c,stroke:e,strokeWidth:h.lineWidth,dashEnabled:!0,dash:[.1,.05],perfectDrawEnabled:!1});l.add(u);const g=new m.Arrow({points:[c[0],c[1],a,d],pointerLength:.5,pointerWidth:.35,strokeWidth:h.lineWidth*1.4,stroke:e,fill:Y.ONE_WAY_FILL,dashEnabled:!0,dash:[.1,.05]});return l.add(g),l}renderAreaExit(t,e,s){const i=this.getRoomEdgePoint(t.x,t.y,e,h.roomSize/2),o=C(t.x,t.y,e,h.roomSize*1.5),r=s??this.mapReader.getColorValue(t.env);return new m.Arrow({points:[i.x,i.y,o.x,o.y],pointerLength:.3,pointerWidth:.3,strokeWidth:h.lineWidth*1.4,stroke:r,fill:r})}renderSpecialExits(t,e){return Object.entries(t.customLines).map(([s,i])=>{const o=[t.x,t.y];i.points.reduce((l,c)=>(l.push(c.x,-c.y),l),o);const r=i.attributes.arrow?m.Arrow:m.Line,n=e??`rgb(${i.attributes.color.r}, ${i.attributes.color.g}, ${i.attributes.color.b})`,a=new r({points:o,strokeWidth:h.lineWidth,stroke:n,fill:e??`rgb(${i.attributes.color.r}, ${i.attributes.color.g} , ${i.attributes.color.b})`,pointerLength:.3,pointerWidth:.2,perfectDrawEnabled:!1});let d=i.attributes.style;return d==="dot line"?(a.dash([.05,.05]),a.dashOffset(.1)):d==="dash line"?a.dash([.4,.2]):d==="solid line"||d!==void 0&&console.log("Brak opisu stylu: "+d),a})}renderStubs(t,e=h.lineColor){return t.stubs.map(s=>{const i=wt[s],o=this.getRoomEdgePoint(t.x,t.y,i,h.roomSize/2),r=C(t.x,t.y,i,h.roomSize/2+.5),n=[o.x,o.y,r.x,r.y];return new m.Line({points:n,stroke:e,strokeWidth:h.lineWidth})})}renderInnerExits(t){return Rt.map(e=>{if(t.exits[e]){const s=new m.Group,i=new m.RegularPolygon({x:t.x,y:t.y,sides:3,fill:this.mapReader.getSymbolColor(t.env,.6),stroke:this.mapReader.getSymbolColor(t.env),strokeWidth:h.lineWidth,radius:h.roomSize/5,scaleX:1.4,scaleY:.8,perfectDrawEnabled:!1});s.add(i);let o=t.doors[e];if(o!==void 0)switch(o){case 1:i.stroke(Y.OPEN_DOOR);break;case 2:i.stroke(Y.CLOSED_DOOR);break;default:i.stroke(Y.LOCKED_DOOR)}switch(e){case"up":i.position(C(t.x,t.y,"south",h.roomSize/4));break;case"down":i.rotation(180),i.position(C(t.x,t.y,"north",h.roomSize/4));break;case"in":const r=i.clone();r.rotation(-90),r.position(C(t.x,t.y,"east",h.roomSize/4)),s.add(r),i.rotation(90),i.position(C(t.x,t.y,"west",h.roomSize/4));break;case"out":const n=i.clone();n.rotation(90),n.position(C(t.x,t.y,"east",h.roomSize/4)),s.add(n),i.rotation(-90),i.position(C(t.x,t.y,"west",h.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 m.Rect({x:s.x-h.roomSize/4,y:s.y-h.roomSize/4,width:h.roomSize/2,height:h.roomSize/2,stroke:bt(e),strokeWidth:h.lineWidth})}}class mt{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 _{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 mt(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),r=Math.max(t,e),n=`${o}-${r}`;let a=this.exits.get(n);a||(a={a:o,b:r,zIndex:[s]}),o==t?a.aDir=i:a.bDir=i,a.zIndex.push(s),this.exits.set(n,a)}}class ot extends mt{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 B extends _{constructor(t,e){super(t),this.planeCache=new WeakMap,this.visitedRooms=e instanceof Set?e:new Set(e??[]),this.areaRoomIds=new Set(t.rooms.map(s=>s.id))}getPlane(t){const e=super.getPlane(t);if(!e)return e;let s=this.planeCache.get(e);return s||(s=new ot(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 ot(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}}class Et{constructor(t,e){this.paths=[],this.mapReader=t,this.overlayLayer=e}renderPath(t,e,s,i="#66E64D"){if(e===void 0||s===void 0)return;const o=t.map(c=>this.mapReader.getRoom(c)).filter(c=>c!==void 0),r=[];let n=null;const a=()=>{n&&(n.length<4&&r.pop(),n=null)},d=()=>(n||(n=[],r.push(n)),n);o.forEach((c,u)=>{if(!this.isRoomVisible(c,e,s))return;const g=u>0?o[u-1]:void 0,y=u<o.length-1?o[u+1]:void 0;if(this.isRoomVisible(g,e,s))d();else{a();const x=d();if(g){const w=this.getDirectionTowards(c,g);if(w){const I=C(c.x,c.y,w,h.roomSize);x.push(I.x,I.y)}}}if(n?.push(c.x,c.y),!this.isRoomVisible(y,e,s)&&y){const x=this.getDirectionTowards(c,y);if(x){const w=C(c.x,c.y,x,h.roomSize);n?.push(w.x,w.y)}a()}}),a();const l=r.filter(c=>c.length>=4).map(c=>new m.Line({points:c,stroke:i,strokeWidth:h.lineWidth*4}));return l.forEach(c=>{this.overlayLayer.add(c),this.paths.push(c)}),l[0]}clearPaths(){this.paths.forEach(t=>{t.destroy()}),this.paths=[]}isRoomVisible(t,e,s){return t?t.area===e&&t.z===s:!1}getDirectionTowards(t,e){for(const s of K)if(t.exits[s]===e.id)return s;for(const s of K)if(e.exits[s]===t.id)return gt[s]}}const St=.6,X=75,Ct=.025,kt="rgb(225, 255, 225)",Z="rgb(120, 72, 0)";function rt(f,t){const e=parseInt(f.slice(1,3),16),s=parseInt(f.slice(3,5),16),i=parseInt(f.slice(5,7),16);return`rgba(${e}, ${s}, ${i}, ${t})`}const k=class k{};k.roomSize=St,k.lineWidth=Ct,k.lineColor=kt,k.instantMapMove=!1,k.highlightCurrentRoom=!0,k.cullingEnabled=!0,k.cullingMode="indexed",k.cullingBounds=null,k.labelRenderMode="image",k.roomShape="rectangle",k.playerMarker={strokeColor:"#00e5b2",strokeAlpha:1,fillColor:"#00e5b2",fillAlpha:0,strokeWidth:.1,sizeFactor:1.7,dash:[.05,.05],dashEnabled:!0};let h=k;class It{constructor(t,e){this.highlights=new Map,this.currentZoom=1,this.currentRoomOverlay=[],this.roomNodes=new Map,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 m.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 m.Layer({listening:!1}),this.stage.add(this.linkLayer),this.roomLayer=new m.Layer,this.stage.add(this.roomLayer),this.positionLayer=new m.Layer({listening:!1}),this.stage.add(this.positionLayer),this.overlayLayer=new m.Layer({listening:!1}),this.stage.add(this.overlayLayer),this.mapReader=e,this.exitRenderer=new vt(e,this),this.pathRenderer=new Et(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.currentRoomId&&this.centerOnRoom(this.mapReader.getRoom(this.currentRoomId),!1),this.stage.batchDraw(),this.scheduleRoomCulling()}initScaling(t){m.hitOnDragEnabled=!0;let e,s=!1,i=!1;this.stage.on("touchstart",o=>{const r=o.evt.touches;r&&r.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 r=o.evt.touches;(!r||r.length<=1)&&(i=!1,this.stage.draggable(!0))}),this.stage.on("wheel",o=>{o.evt.preventDefault();const r=this.stage.scaleX(),n=this.stage.getPointerPosition();if(!n)return;const a={x:(n.x-this.stage.x())/r,y:(n.y-this.stage.y())/r};let d=o.evt.deltaY>0?-1:1;o.evt.ctrlKey&&(d=-d);const l=d>0?this.currentZoom*t:this.currentZoom/t,c=l*X,u=this.setZoom(l),g={x:n.x-a.x*c,y:n.y-a.y*c};this.stage.position(g),this.scheduleRoomCulling(),u&&this.emitZoomChangeEvent()}),this.stage.on("touchmove",o=>{const r=o.evt.touches,n=r?.[0],a=r?.[1];if(a||i&&(i=!1,this.stage.draggable(!0)),n&&!a&&s&&!this.stage.isDragging()&&(this.stage.startDrag(),s=!1),!n||!a){e=void 0;return}o.evt.preventDefault(),this.stage.isDragging()&&(this.stage.stopDrag(),s=!0),i||(i=!0,this.stage.draggable(!1));const d=this.stage.container().getBoundingClientRect(),l={x:n.clientX-d.left,y:n.clientY-d.top},c={x:a.clientX-d.left,y:a.clientY-d.top},u=Math.hypot(l.x-c.x,l.y-c.y);if(e===void 0){e=u;return}if(e===0)return;const g=this.stage.scaleX(),y=this.stage.x(),R=this.stage.y(),p={x:this.stage.width()/2,y:this.stage.height()/2},x={x:(p.x-y)/g,y:(p.y-R)/g},w=this.currentZoom*(u/e),I=this.setZoom(w),z=this.stage.scaleX(),V={x:p.x-x.x*z,y:p.y-x.y*z};this.stage.position(V),this.stage.batchDraw(),this.scheduleRoomCulling(),e=u,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:X*this.currentZoom,y:X*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(h.roomSize*10,5)}getBucketKey(t,e){return`${t},${e}`}forEachBucket(t,e,s,i,o){const r=this.spatialBucketSize,n=Math.min(t,s),a=Math.max(t,s),d=Math.min(e,i),l=Math.max(e,i),c=Math.floor(n/r),u=Math.floor(a/r),g=Math.floor(d/r),y=Math.floor(l/r);for(let R=c;R<=u;R++)for(let p=g;p<=y;p++)o(this.getBucketKey(R,p))}addRoomToSpatialIndex(t){const e=h.roomSize/2,s=t.room.x-e,i=t.room.x+e,o=t.room.y-e,r=t.room.y+e;this.forEachBucket(s,o,i,r,n=>{let a=this.roomSpatialIndex.get(n);a||(a=new Set,this.roomSpatialIndex.set(n,a)),a.add(t)})}addStandaloneExitToSpatialIndex(t){const{bounds:e}=t,s=e.x,i=e.x+e.width,o=e.y,r=e.y+e.height;this.forEachBucket(s,o,i,r,n=>{let a=this.exitSpatialIndex.get(n);a||(a=new Set,this.exitSpatialIndex.set(n,a)),a.add(t)})}collectRoomCandidates(t,e,s,i){const o=new Set;return this.forEachBucket(t,e,s,i,r=>{this.roomSpatialIndex.get(r)?.forEach(a=>o.add(a))}),o}collectStandaloneExitCandidates(t,e,s,i){const o=new Set;return this.forEachBucket(t,e,s,i,r=>{this.exitSpatialIndex.get(r)?.forEach(a=>o.add(a))}),o}refreshStandaloneExitBoundsIfNeeded(){this.standaloneExitBoundsRoomSize!==h.roomSize&&(this.exitSpatialIndex.clear(),this.standaloneExitNodes.forEach(t=>{t.bounds=t.node.getClientRect({relativeTo:this.linkLayer}),this.addStandaloneExitToSpatialIndex(t)}),this.standaloneExitBoundsRoomSize=h.roomSize)}emitRoomContextEvent(t,e,s){const i=this.stage.container(),o=i.getBoundingClientRect(),r={roomId:t,position:{x:e-o.left,y:s-o.top}},n=new CustomEvent("roomcontextmenu",{detail:r});i.dispatchEvent(n)}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:X*t,y:X*t}),this.scheduleRoomCulling(),!0)}getZoom(){return this.currentZoom}setCullingMode(t){h.cullingMode=t,h.cullingEnabled=t!=="none",this.scheduleRoomCulling()}getCullingMode(){return h.cullingMode}getCurrentArea(){return this.currentArea?this.mapReader.getArea(this.currentArea):void 0}refreshCurrentRoomOverlay(){if(this.currentRoomId!==void 0){const t=this.mapReader.getRoom(this.currentRoomId);t&&this.updateCurrentRoomOverlay(t)}}refresh(){this.currentRoomId!==void 0&&this.currentArea!==void 0&&this.currentZIndex!==void 0&&(this.drawArea(this.currentArea,this.currentZIndex),this.setPosition(this.currentRoomId))}setPosition(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.centerOnRoom(e,o),this.updateCurrentRoomOverlay(e);const r=rt(h.playerMarker.strokeColor,h.playerMarker.strokeAlpha),n=rt(h.playerMarker.fillColor,h.playerMarker.fillAlpha),a=h.roomSize/2*h.playerMarker.sizeFactor;this.positionRender?(this.positionRender.radius(a),this.positionRender.stroke(r),this.positionRender.fill(n),this.positionRender.strokeWidth(h.playerMarker.strokeWidth),this.positionRender.dash(h.playerMarker.dash??[]),this.positionRender.dashEnabled(h.playerMarker.dashEnabled)):(this.positionRender=new m.Circle({x:e.x,y:e.y,radius:a,stroke:r,fill:n,strokeWidth:h.playerMarker.strokeWidth,dash:h.playerMarker.dash,dashEnabled:h.playerMarker.dashEnabled}),this.positionLayer.add(this.positionRender))}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 r=this.createHighlightShape(s,e);return this.overlayLayer.add(r),o.shape=r,this.overlayLayer.batchDraw(),r}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 h.roomShape==="circle"?new m.Circle({x:t.x,y:t.y,radius:h.roomSize/2*1.5,stroke:e,strokeWidth:.1,dash:[.05,.05],dashEnabled:!0,listening:!1}):new m.Rect({x:t.x-h.roomSize/2*1.5,y:t.y-h.roomSize/2*1.5,width:h.roomSize*1.5,height:h.roomSize*1.5,stroke:e,strokeWidth:.1,dash:[.05,.05],dashEnabled:!0,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),r={x:this.stage.width()/2,y:this.stage.height()/2},n=r.x-o.x,a=r.y-o.y;this.currentTransition&&(this.currentTransition.pause(),this.currentTransition.destroy(),delete this.currentTransition),e||h.instantMapMove?(this.stage.position({x:this.stage.x()+n,y:this.stage.y()+a}),this.scheduleRoomCulling()):(this.currentTransition=new m.Tween({node:this.stage,x:this.stage.x()+n,y:this.stage.y()+a,duration:.2,easing:m.Easings.EaseInOut,onUpdate:()=>this.scheduleRoomCulling(),onFinish:()=>this.scheduleRoomCulling()}),this.currentTransition.play())}renderRooms(t){t.forEach(e=>{const s=new m.Group({x:e.x-h.roomSize/2,y:e.y-h.roomSize/2}),i=this.mapReader.getColorValue(e.env),o=h.lineColor,n=h.roomShape==="circle"?new m.Circle({x:h.roomSize/2,y:h.roomSize/2,radius:h.roomSize/2,fill:i,strokeWidth:h.lineWidth,stroke:o,perfectDrawEnabled:!1}):new m.Rect({x:0,y:0,width:h.roomSize,height:h.roomSize,fill:i,strokeWidth:h.lineWidth,stroke:o,perfectDrawEnabled:!1}),a=(p,x)=>this.emitRoomContextEvent(e.id,p,x);s.on("mouseenter",()=>{this.stage.container().style.cursor="pointer"}),s.on("mouseleave",()=>{this.stage.container().style.cursor="auto"}),s.on("contextmenu",p=>{p.evt.preventDefault();const x=p.evt;a(x.clientX,x.clientY)});let d,l,c;const u=()=>{c!==void 0&&(this.stage.draggable(c),c=void 0)},g=()=>{d!==void 0&&(window.clearTimeout(d),d=void 0),l=void 0,u()};s.on("touchstart",p=>{if(g(),p.evt.touches&&p.evt.touches.length>1)return;const x=p.evt.touches?.[0];x&&(l={clientX:x.clientX,clientY:x.clientY},c=this.stage.draggable(),this.stage.draggable(!1),d=window.setTimeout(()=>{l&&a(l.clientX,l.clientY),g()},500))}),s.on("touchend",g),s.on("touchmove",p=>{if(!l)return;const x=p.evt.touches?.[0];if(!x){g();return}const w=x.clientX-l.clientX,I=x.clientY-l.clientY,z=w*w+I*I,V=10;if(z>V*V){const T=c;g(),T&&this.stage.startDrag()}}),s.on("touchcancel",g),s.add(n),this.renderSymbol(e,s),this.roomLayer.add(s);const y=[];this.exitRenderer.renderSpecialExits(e).forEach(p=>{this.linkLayer.add(p);const x=p.getClientRect({relativeTo:this.linkLayer}),w={node:p,bounds:x};this.standaloneExitNodes.push(w),this.addStandaloneExitToSpatialIndex(w)}),this.exitRenderer.renderStubs(e).forEach(p=>{this.linkLayer.add(p),y.push(p)}),this.exitRenderer.renderInnerExits(e).forEach(p=>{this.roomLayer.add(p)});const R={room:e,group:s,linkNodes:y};this.roomNodes.set(e.id,R),this.addRoomToSpatialIndex(R)})}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=h.roomSize/2,i=h.cullingBounds,o=i?i.x:0,r=i?i.x+i.width:this.stage.width(),n=i?i.y:0,a=i?i.y+i.height:this.stage.height(),d=Math.min(o,r),l=Math.max(o,r),c=Math.min(n,a),u=Math.max(n,a),g=(d-e.x)/t,y=(l-e.x)/t,R=(c-e.y)/t,p=(u-e.y)/t;let x=!1,w=!1;const I=h.cullingEnabled?h.cullingMode??"indexed":"none",z=g-s,V=y+s,T=R-s,U=p+s;if(this.refreshStandaloneExitBoundsIfNeeded(),I==="none"){this.roomNodes.forEach(b=>{b.group.visible()||(b.group.visible(!0),x=!0),b.linkNodes.forEach(S=>{S.visible()||(S.visible(!0),w=!0)})}),this.standaloneExitNodes.forEach(b=>{const{node:S}=b;S.visible()||(w=!0,S.visible(!0))}),x&&this.roomLayer.batchDraw(),w&&this.linkLayer.batchDraw(),this.visibleRooms=new Set(this.roomNodes.values()),this.visibleStandaloneExitNodes=new Set(this.standaloneExitNodes);return}if(I==="basic"){const b=new Set;this.roomNodes.forEach(E=>{const A=E.room.x-s,M=E.room.x+s,L=E.room.y-s,P=E.room.y+s,N=M>=g&&A<=y&&P>=R&&L<=p;E.group.visible()!==N&&(E.group.visible(N),x=!0),E.linkNodes.forEach(W=>{W.visible()!==N&&(W.visible(N),w=!0)}),N&&b.add(E)});const S=new Set;this.standaloneExitNodes.forEach(E=>{const{node:A,bounds:M}=E,L=M.x,P=M.x+M.width,N=M.y,W=M.y+M.height,F=P>=g&&L<=y&&W>=R&&N<=p;A.visible()!==F&&(A.visible(F),w=!0),F&&S.add(E)}),this.visibleRooms=b,this.visibleStandaloneExitNodes=S,x&&this.roomLayer.batchDraw(),w&&this.linkLayer.batchDraw();return}const pt=this.collectRoomCandidates(z,T,V,U),J=new Set,tt=new Set;pt.forEach(b=>{J.add(b);const S=b.room.x-s,E=b.room.x+s,A=b.room.y-s,M=b.room.y+s,L=E>=g&&S<=y&&M>=R&&A<=p;b.group.visible()!==L&&(b.group.visible(L),x=!0),b.linkNodes.forEach(P=>{P.visible()!==L&&(P.visible(L),w=!0)}),L&&tt.add(b)}),this.visibleRooms.forEach(b=>{J.has(b)||(b.group.visible()&&(b.group.visible(!1),x=!0),b.linkNodes.forEach(S=>{S.visible()&&(S.visible(!1),w=!0)}))}),this.visibleRooms=tt;const xt=this.collectStandaloneExitCandidates(z,T,V,U),et=new Set,st=new Set;xt.forEach(b=>{et.add(b);const{node:S,bounds:E}=b,A=E.x,M=E.x+E.width,L=E.y,P=E.y+E.height,N=M>=g&&A<=y&&P>=R&&L<=p;S.visible()!==N&&(S.visible(N),w=!0),N&&st.add(b)}),this.visibleStandaloneExitNodes.forEach(b=>{const{node:S}=b;!et.has(b)&&S.visible()&&(S.visible(!1),w=!0)}),this.visibleStandaloneExitNodes=st,x&&this.roomLayer.batchDraw(),w&&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 B?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 d=h.highlightCurrentRoom?this.exitRenderer.renderWithColor(a,Z,this.currentZIndex):this.exitRenderer.render(a,this.currentZIndex);d&&s.push(d)});const o=h.highlightCurrentRoom?Z:void 0;this.exitRenderer.renderSpecialExits(t,o).forEach(n=>{s.push(n)}),(h.highlightCurrentRoom?this.exitRenderer.renderStubs(t,Z):this.exitRenderer.renderStubs(t)).forEach(n=>{s.push(n)}),[...Object.values(t.exits),...Object.values(t.specialExits)].forEach(n=>{const a=this.mapReader.getRoom(n),d=!i||i.hasVisitedRoom(n);a&&a.area===this.currentArea&&a.z===this.currentZIndex&&d&&e.set(n,a)}),s.forEach(n=>{this.positionLayer.add(n),this.currentRoomOverlay.push(n)}),e.forEach((n,a)=>{const d=a===t.id,l=this.createOverlayRoomGroup(n,{stroke:d&&h.highlightCurrentRoom?Z:h.lineColor});this.positionLayer.add(l),this.currentRoomOverlay.push(l),this.exitRenderer.renderInnerExits(n).forEach(c=>{this.positionLayer.add(c),this.currentRoomOverlay.push(c)})}),this.positionRender&&this.positionRender.moveToTop(),this.positionLayer.batchDraw()}createOverlayRoomGroup(t,e){const s=new m.Group({x:t.x-h.roomSize/2,y:t.y-h.roomSize/2,listening:!1}),i=this.mapReader.getColorValue(t.env),o=e.stroke,r=h.roomShape==="circle"?new m.Circle({x:h.roomSize/2,y:h.roomSize/2,radius:h.roomSize/2,fill:i,stroke:o,strokeWidth:h.lineWidth}):new m.Rect({x:0,y:0,width:h.roomSize,height:h.roomSize,fill:i,stroke:o,strokeWidth:h.lineWidth});return s.add(r),this.renderSymbol(t,s),s}renderSymbol(t,e){if(t.roomChar!==void 0){const s=h.roomSize*.75,i=new m.Text({x:0,y:0,text:t.roomChar,fontSize:s,fontStyle:"bold",fill:this.mapReader.getSymbolColor(t.env),align:"center",verticalAlign:"middle",width:h.roomSize,height:h.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=h.roomSize}renderLabels(t){t.forEach(e=>{if(h.labelRenderMode==="image"){if(!e.pixMap)return;const s=new Image;s.src=`data:image/png;base64,${e.pixMap}`;const i=new m.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 m.Group({listening:!1}),s=new m.Rect({x:t.X,y:-t.Y,width:t.Width,height:t.Height,listening:!1});(t.BgColor?.alpha??0)>0&&!h.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))),r=new m.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(r),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 nt={rgbValue:"rgb(114, 1, 0)",symbolColor:[225,225,225]};function at(f){const t=f[0]/255,e=f[1]/255,s=f[2]/255,i=Math.max(t,e,s),o=Math.min(t,e,s);return(i+o)/2}class Mt{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 _(s),this.areaSources[i]=s}),this.colors=e.reduce((s,i)=>({...s,[i.envId]:{rgb:i.colors,rgbValue:`rgb(${i.colors.join(",")})`,symbolColor:at(i.colors)>.41?[25,25,25]:[225,255,255],symbolColorValue:at(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 B)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 B(e,this.visitedRooms)})}decorateWithExploration(t){return t!==void 0?this.setVisitedRooms(t):this.ensureVisitedRooms(),this.applyExplorationDecoration(),this.explorationEnabled=!0,this.visitedRooms}getVisitedRooms(){return this.visitedRooms}clearExplorationDecoration(){Object.entries(this.areaSources).forEach(([t,e])=>{const s=parseInt(t,10);this.areas[s]=new _(e)}),this.explorationEnabled=!1}isExplorationEnabled(){return this.explorationEnabled}setVisitedRooms(t){return this.visitedRooms=t instanceof Set?t:new Set(t),this.explorationEnabled&&this.applyExplorationDecoration(),this.visitedRooms}addVisitedRoom(t){if(this.explorationEnabled){const i=this.getRoom(t);if(i){const 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 r=this.getRoom(i);if(r){const n=this.getExplorationArea(r.area);if(n){n.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??nt.rgbValue}getSymbolColor(t,e){const s=this.colors[t]?.symbolColor??nt.symbolColor,i=Math.min(Math.max(e??1,0),1),o=s.join(",");return i!=1?`rgba(${o}, ${i})`:`rgba(${o})`}}function Dt(f){return f&&f.__esModule&&Object.prototype.hasOwnProperty.call(f,"default")?f.default:f}var $,ht;function Lt(){if(ht)return $;ht=1;class f{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 $=f,$}var G,ct;function Nt(){if(ct)return G;ct=1;function f(t,e){const s=new Map;for(const[i,o]of t)i!==e&&o instanceof Map?s.set(i,f(o,e)):i!==e&&s.set(i,o);return s}return G=f,G}var j,dt;function zt(){if(dt)return j;dt=1;function f(e){const s=Number(e);return!(isNaN(s)||s<=0)}function t(e){const s=new Map;return Object.keys(e).forEach(o=>{const r=e[o];if(r!==null&&typeof r=="object"&&!Array.isArray(r))return s.set(o,t(r));if(!f(r))throw new Error(`Could not add node at key "${o}", make sure it's a valid node`,r);return s.set(o,Number(r))}),s}return j=t,j}var q,lt;function Ot(){if(lt)return q;lt=1;function f(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){f(e);return}if(typeof e!="number"||e<=0)throw new Error(`Values must be numbers greater than 0. Found value ${e} at ${s}`)})}return q=f,q}var H,ut;function At(){if(ut)return H;ut=1;const f=Lt(),t=Nt(),e=zt(),s=Ot();class i{constructor(r){r instanceof Map?(s(r),this.graph=r):r?this.graph=e(r):this.graph=new Map}addNode(r,n){let a;return n instanceof Map?(s(n),a=n):a=e(n),this.graph.set(r,a),this}addVertex(r,n){return this.addNode(r,n)}removeNode(r){return this.graph=t(this.graph,r),this}path(r,n,a={}){if(!this.graph.size)return a.cost?{path:null,cost:0}:null;const d=new Set,l=new f,c=new Map;let u=[],g=0,y=[];if(a.avoid&&(y=[].concat(a.avoid)),y.includes(r))throw new Error(`Starting node (${r}) cannot be avoided`);if(y.includes(n))throw new Error(`Ending node (${n}) cannot be avoided`);for(l.set(r,0);!l.isEmpty();){const R=l.next();if(R.key===n){g=R.priority;let x=R.key;for(;c.has(x);)u.push(x),x=c.get(x);break}d.add(R.key),(this.graph.get(R.key)||new Map).forEach((x,w)=>{if(d.has(w)||y.includes(w))return null;if(!l.has(w))return c.set(w,R.key),l.set(w,R.priority+x);const I=l.get(w).priority,z=R.priority+x;return z<I?(c.set(w,R.key),l.set(w,z)):null})}return u.length?(a.trim?u.shift():u=u.concat([r]),a.reverse||(u=u.reverse()),a.cost?{path:u,cost:g}:u):a.cost?{path:null,cost:0}:null}shortestPath(...r){return this.path(...r)}}return H=i,H}var Pt=At();const Vt=Dt(Pt),Yt={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 Xt{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(r=>Yt[r]).filter(r=>!!r)),o=new Set(e.mSpecialExitLocks??[]);Object.entries(e.exits??{}).forEach(([r,n])=>{i.has(r)||this.mapReader.getRoom(n)&&(s[n.toString()]=1)}),Object.values(e.specialExits??{}).forEach(r=>{o.has(r)||this.mapReader.getRoom(r)&&(s[r.toString()]=1)}),t[e.id.toString()]=s}),new Vt(t)}findPath(t,e){const s=`${t}->${e}`;if(this.cache.has(s))return this.cache.get(s);if(t===e){const n=this.mapReader.getRoom(t)?[t]:null;return this.cache.set(s,n),n}if(!this.mapReader.getRoom(t)||!this.mapReader.getRoom(e))return this.cache.set(s,null),null;const i=this.graph.path(t.toString(),e.toString()),o=Array.isArray(i)?i:i?.path,r=o?o.map(n=>Number(n)):null;return this.cache.set(s,r),r}}const 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"},D=class D{};D.areaWidth=150,D.areaHeight=80,D.areaSpacing=100,D.fontSize=14,D.connectionLineWidth=2,D.areaFillColor="#2a2a3e",D.areaStrokeColor="#4a4a6e",D.textColor="#e0e0e0",D.connectionColor="#6a6a8e",D.highlightColor="#ff9900";let v=D;class Wt{constructor(t,e){this.areaNodes=new Map,this.connectionGroups=[],this.currentZoom=1,this.stage=new m.Stage({container:t,width:t.clientWidth,height:t.clientHeight,draggable:!0}),this.connectionLayer=new m.Layer({listening:!1}),this.stage.add(this.connectionLayer),this.areaLayer=new m.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},n=(e.evt.deltaY>0?-1:1)>0?this.currentZoom*1.1:this.currentZoom/1.1;this.setZoom(n);const a=this.stage.scaleX(),d={x:i.x-o.x*a,y:i.y-o.y*a};this.stage.position(d),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}render(){this.analyzeConnections(),this.layoutAreas(),this.drawConnections(),this.drawAreas(),this.centerView(),this.stage.batchDraw()}analyzeConnections(){this.areaNodes.clear(),this.connectionGroups=[];const t=this.mapReader.getRooms(),e=this.mapReader.getAreas();for(const i of e){const o=i.getAreaId(),r=i.getRooms().length;this.areaNodes.set(o,{areaId:o,name:i.getAreaName(),x:0,y:0,width:v.areaWidth,height:v.areaHeight,connections:[],roomCount:r})}const s=new Map;for(const i of t){const o=i.area,r=this.getLockedDirections(i),n=new Set(i.mSpecialExitLocks??[]);for(const[a,d]of Object.entries(i.exits??{})){if(r.has(a))continue;const l=this.mapReader.getRoom(d);if(!l||l.area===o)continue;const c=this.createConnection(i,l,a);c&&this.addConnection(s,c)}for(const[a,d]of Object.entries(i.specialExits??{})){if(n.has(d))continue;const l=this.mapReader.getRoom(d);if(!l||l.area===o)continue;const c=this.parseDirection(a),u=this.createConnection(i,l,c);u&&this.addConnection(s,u)}}for(const[i,o]of s){const[r,n]=i.split("-").map(Number),a=this.createConnectionGroup(r,n,o);this.connectionGroups.push(a);const d=this.areaNodes.get(r),l=this.areaNodes.get(n);if(d&&d.connections.push(...o),l)for(const c of o)l.connections.push({...c,fromAreaId:c.toAreaId,toAreaId:c.fromAreaId,fromRoomId:c.toRoomId,toRoomId:c.fromRoomId,direction:c.direction?gt[c.direction]:null,fromRoomPosition:c.toRoomPosition,toRoomPosition:c.fromRoomPosition})}}getLockedDirections(t){return new Set((t.exitLocks??[]).map(e=>Tt[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,r=0;for(const d of s)d.direction&&i.set(d.direction,(i.get(d.direction)??0)+1),o+=d.toRoomPosition.x-d.fromRoomPosition.x,r+=d.toRoomPosition.y-d.fromRoomPosition.y;let n=null,a=0;for(const[d,l]of i)l>a&&(a=l,n=d);return{fromAreaId:t,toAreaId:e,connections:s,primaryDirection:n,averageOffset:{x:o/s.length,y:r/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&&K.includes(t)?t:null}layoutAreas(){if(Array.from(this.areaNodes.values()).length===0)return;const e=this.findConnectedComponents();let s=0;const i=v.areaWidth*3;for(const o of e)if(o.length===1){const r=this.areaNodes.get(o[0]);r.x=s,r.y=0,s+=v.areaWidth+i}else{const r=this.forceDirectedLayout(o);for(const n of o){const a=this.areaNodes.get(n);a.x-=r.minX,a.x+=s,a.y-=r.minY}s+=r.maxX-r.minX+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 r=o.shift();if(t.has(r))continue;t.add(r),i.push(r);const n=this.areaNodes.get(r);if(n)for(const a of n.connections)t.has(a.toAreaId)||o.push(a.toAreaId)}e.push(i)}return e}forceDirectedLayout(t){const e=new Set,s=[],i=t[0],o=this.areaNodes.get(i);for(o.x=0,o.y=0,e.add(i),s.push(i);s.length>0;){const l=s.shift(),c=this.areaNodes.get(l);for(const u of c.connections){if(e.has(u.toAreaId))continue;const g=this.areaNodes.get(u.toAreaId);if(!g)continue;const y=this.getDirectionOffset(u.direction);g.x=c.x+y.x*(v.areaWidth+v.areaSpacing),g.y=c.y+y.y*(v.areaHeight+v.areaSpacing),e.add(u.toAreaId),s.push(u.toAreaId)}}this.applyForces(t,50);let r=1/0,n=1/0,a=-1/0,d=-1/0;for(const l of t){const c=this.areaNodes.get(l);r=Math.min(r,c.x),n=Math.min(n,c.y),a=Math.max(a,c.x+c.width),d=Math.max(d,c.y+c.height)}return{minX:r,minY:n,maxX:a,maxY:d}}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:.7,y:-.7},northwest:{x:-.7,y:-.7},southeast:{x:.7,y:.7},southwest:{x:-.7,y:.7}};return t&&e[t]?e[t]:{x:1,y:0}}applyForces(t,e){const r=new Map;for(const n of t)r.set(n,{vx:0,vy:0});for(let n=0;n<e;n++){for(const a of t){const d=this.areaNodes.get(a),l=r.get(a);for(const c of t){if(a===c)continue;const u=this.areaNodes.get(c),g=d.x-u.x,y=d.y-u.y,R=g*g+y*y,p=Math.sqrt(R)||1,x=5e3/R;l.vx+=g/p*x,l.vy+=y/p*x}for(const c of d.connections){const u=this.areaNodes.get(c.toAreaId);if(!u)continue;const g=this.getDirectionOffset(c.direction),y=d.x+g.x*(v.areaWidth+v.areaSpacing),R=d.y+g.y*(v.areaHeight+v.areaSpacing),p=r.get(c.toAreaId);p&&(p.vx+=(y-u.x)*.01,p.vy+=(R-u.y)*.01)}}for(const a of t){const d=this.areaNodes.get(a),l=r.get(a);d.x+=l.vx,d.y+=l.vy,l.vx*=.9,l.vy*=.9}}}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)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},r=this.getEdgePoint(e,o),n=this.getEdgePoint(s,i),a=new m.Line({points:[r.x,r.y,n.x,n.y],stroke:v.connectionColor,strokeWidth:Math.min(v.connectionLineWidth,1+t.connections.length*.5),lineCap:"round",listening:!1});this.connectionLayer.add(a);const d=(r.x+n.x)/2,l=(r.y+n.y)/2;if(t.connections.length>1){const c=new m.Group({x:d,y:l,listening:!1}),u=new m.Circle({radius:12,fill:v.areaFillColor,stroke:v.connectionColor,strokeWidth:1});c.add(u);const g=new m.Text({text:String(t.connections.length),fontSize:10,fill:v.textColor,align:"center",verticalAlign:"middle"});g.x(-g.width()/2),g.y(-g.height()/2),c.add(g),this.connectionLayer.add(c)}}}getEdgePoint(t,e){const s=t.x+t.width/2,i=t.y+t.height/2,o=e.x-s,r=e.y-i,n=t.width/2,a=t.height/2;if(o===0&&r===0)return{x:s,y:i};const d=Math.abs(o),l=Math.abs(r);let c;return d/n>l/a?c=n/d:c=a/l,{x:s+o*c,y:i+r*c}}drawAreas(){this.areaLayer.destroyChildren();for(const[,t]of this.areaNodes){const e=new m.Group({x:t.x,y:t.y}),s=t.areaId===this.highlightedArea,i=new m.Rect({width:t.width,height:t.height,fill:v.areaFillColor,stroke:s?v.highlightColor:v.areaStrokeColor,strokeWidth:s?3:2,cornerRadius:8}),o=new m.Text({text:t.name,fontSize:v.fontSize,fill:v.textColor,width:t.width-10,height:t.height-20,x:5,y:10,align:"center",verticalAlign:"middle",ellipsis:!0,wrap:"word"}),r=new m.Text({text:`${t.roomCount} rooms`,fontSize:10,fill:v.connectionColor,width:t.width-10,x:5,y:t.height-18,align:"center"});e.add(i),e.add(o),e.add(r),e.on("click tap",()=>{this.emitAreaClickEvent(t.areaId)}),e.on("mouseenter",()=>{this.stage.container().style.cursor="pointer",i.stroke(v.highlightColor),this.areaLayer.batchDraw()}),e.on("mouseleave",()=>{this.stage.container().style.cursor="auto",i.stroke(s?v.highlightColor:v.areaStrokeColor),this.areaLayer.batchDraw()}),this.areaLayer.add(e)}}centerView(){let t=1/0,e=1/0,s=-1/0,i=-1/0;for(const[,y]of this.areaNodes)t=Math.min(t,y.x),e=Math.min(e,y.y),s=Math.max(s,y.x+y.width),i=Math.max(i,y.y+y.height);if(!isFinite(t))return;const o=s-t,r=i-e,n=t+o/2,a=e+r/2,d=50,l=(this.stage.width()-d*2)/o,c=(this.stage.height()-d*2)/r,u=Math.min(l,c,1.5);this.setZoom(u);const g=this.stage.scaleX();this.stage.position({x:this.stage.width()/2-n*g,y:this.stage.height()/2-a*g})}highlightArea(t){this.highlightedArea=t,this.drawAreas(),this.stage.batchDraw()}centerOnArea(t){const e=this.areaNodes.get(t);if(!e)return;const s=this.stage.scaleX(),i=e.x+e.width/2,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=Wt;exports.AreaMapSettings=v;exports.ExplorationArea=B;exports.MapReader=Mt;exports.PathFinder=Xt;exports.Renderer=It;exports.Settings=h;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const R=require("konva"),H=["north","south","east","west","northeast","northwest","southeast","southwest"],j={north:"n",south:"s",east:"e",west:"w",northeast:"ne",northwest:"nw",southeast:"se",southwest:"sw",up:"u",down:"d",in:"i",out:"o"},nt={north:{x:0,y:-1},south:{x:0,y:1},east:{x:1,y:0},west:{x:-1,y:0},northeast:{x:1,y:-1},northwest:{x:-1,y:-1},southeast:{x:1,y:1},southwest:{x:-1,y:1}},ot=["north","south","east","west","northeast","northwest","southeast","southwest"],pt={north:"south",south:"north",east:"west",west:"east",northeast:"southwest",northwest:"southeast",southeast:"northwest",southwest:"northeast"};function xt(C){return C?Object.prototype.hasOwnProperty.call(nt,C):!1}function F(C,t,e,s=1){if(!xt(e))return{x:C,y:t};const o=nt[e];return{x:C+o.x*s,y:t+o.y*s}}function wt(C,t,e,s=1){if(!xt(e))return{x:C,y:t};const o=nt[e],n=Math.atan2(o.y,o.x);return{x:C+Math.cos(n)*s,y:t+Math.sin(n)*s}}const q={OPEN_DOOR:"rgb(10, 155, 10)",CLOSED_DOOR:"rgb(226, 205, 59)",LOCKED_DOOR:"rgb(155, 10, 10)",ONE_WAY_FILL:"rgb(155, 10, 10)"},bt={1:"north",2:"northeast",3:"northwest",4:"east",5:"west",6:"south",7:"southeast",8:"southwest",9:"up",10:"down",11:"in",12:"out"},Rt=["up","down","in","out"];function vt(C){switch(C){case 1:return q.OPEN_DOOR;case 2:return q.CLOSED_DOOR;default:return q.LOCKED_DOOR}}class Et{constructor(t,e){this.mapReader=t,this.mapRenderer=e}getRoomEdgePoint(t,e,s,o){return d.roomShape==="circle"?wt(t,e,s,o):F(t,e,s,o)}render(t,e){return this.renderWithColor(t,d.lineColor,e)}renderWithColor(t,e,s){return t.aDir&&t.bDir&&H.includes(t.aDir)&&H.includes(t.bDir)?this.renderTwoWayExit(t,e,s):this.renderOneWayExit(t,e)}renderTwoWayExit(t,e,s){const o=this.mapReader.getRoom(t.a),n=this.mapReader.getRoom(t.b);if(!o||!n||!t.aDir||!t.bDir||!H.includes(t.aDir)||!H.includes(t.bDir)||o.customLines[j[t.aDir]]&&n.customLines[j[t.bDir]]||o.z!==n.z&&(s!==n.z&&o.customLines[j[t.aDir]]||s!==o.z&&n.customLines[j[t.bDir]]))return;const i=new R.Group,r=[];if(r.push(...Object.values(this.getRoomEdgePoint(o.x,o.y,t.aDir,d.roomSize/2))),r.push(...Object.values(this.getRoomEdgePoint(n.x,n.y,t.bDir,d.roomSize/2))),o.doors[j[t.aDir]]||n.doors[j[t.bDir]]){const c=this.renderDoor(r,o.doors[j[t.aDir]]??n.doors[j[t.bDir]]);i.add(c)}const a=new R.Line({points:r,stroke:e,strokeWidth:d.lineWidth,perfectDrawEnabled:!1});return i.add(a),i}renderOneWayExit(t,e){const s=t.aDir?this.mapReader.getRoom(t.a):this.mapReader.getRoom(t.b),o=t.aDir?this.mapReader.getRoom(t.b):this.mapReader.getRoom(t.a),n=t.aDir?t.aDir:t.bDir;if(!n||!s||!o||!H.includes(n)||s.customLines[j[n]||n])return;if(s.area!=o.area&&n){const u=this.mapReader.getColorValue(o.env);return this.renderAreaExit(s,n,u)}let i={x:o.x,y:o.y};(o.area!==s.area||o.z!==s.z)&&(i=F(s.x,s.y,n,d.roomSize/2));const r=F(s.x,s.y,n,.3),a=r.x-(r.x-i.x)/2,c=r.y-(r.y-i.y)/2,l=new R.Group,h=[];h.push(...Object.values(this.getRoomEdgePoint(s.x,s.y,n,d.roomSize/2))),h.push(i.x,i.y);const g=new R.Line({points:h,stroke:e,strokeWidth:d.lineWidth,dashEnabled:!0,dash:[.1,.05],perfectDrawEnabled:!1});l.add(g);const f=new R.Arrow({points:[h[0],h[1],a,c],pointerLength:.5,pointerWidth:.35,strokeWidth:d.lineWidth*1.4,stroke:e,fill:q.ONE_WAY_FILL,dashEnabled:!0,dash:[.1,.05]});return l.add(f),l}renderAreaExit(t,e,s){const o=this.getRoomEdgePoint(t.x,t.y,e,d.roomSize/2),n=F(t.x,t.y,e,d.roomSize*1.5),i=s??this.mapReader.getColorValue(t.env);return new R.Arrow({points:[o.x,o.y,n.x,n.y],pointerLength:.3,pointerWidth:.3,strokeWidth:d.lineWidth*1.4,stroke:i,fill:i})}renderSpecialExits(t,e){return Object.entries(t.customLines).map(([s,o])=>{const n=[t.x,t.y];o.points.reduce((l,h)=>(l.push(h.x,-h.y),l),n);const i=o.attributes.arrow?R.Arrow:R.Line,r=e??`rgb(${o.attributes.color.r}, ${o.attributes.color.g}, ${o.attributes.color.b})`,a=new i({points:n,strokeWidth:d.lineWidth,stroke:r,fill:e??`rgb(${o.attributes.color.r}, ${o.attributes.color.g} , ${o.attributes.color.b})`,pointerLength:.3,pointerWidth:.2,perfectDrawEnabled:!1});let c=o.attributes.style;return c==="dot line"?(a.dash([.05,.05]),a.dashOffset(.1)):c==="dash line"?a.dash([.4,.2]):c==="solid line"||c!==void 0&&console.log("Brak opisu stylu: "+c),a})}renderStubs(t,e=d.lineColor){return t.stubs.map(s=>{const o=bt[s],n=this.getRoomEdgePoint(t.x,t.y,o,d.roomSize/2),i=F(t.x,t.y,o,d.roomSize/2+.5),r=[n.x,n.y,i.x,i.y];return new R.Line({points:r,stroke:e,strokeWidth:d.lineWidth})})}renderInnerExits(t){return Rt.map(e=>{if(t.exits[e]){const s=new R.Group,o=new R.RegularPolygon({x:t.x,y:t.y,sides:3,fill:this.mapReader.getSymbolColor(t.env,.6),stroke:this.mapReader.getSymbolColor(t.env),strokeWidth:d.lineWidth,radius:d.roomSize/5,scaleX:1.4,scaleY:.8,perfectDrawEnabled:!1});s.add(o);let n=t.doors[e];if(n!==void 0)switch(n){case 1:o.stroke(q.OPEN_DOOR);break;case 2:o.stroke(q.CLOSED_DOOR);break;default:o.stroke(q.LOCKED_DOOR)}switch(e){case"up":o.position(F(t.x,t.y,"south",d.roomSize/4));break;case"down":o.rotation(180),o.position(F(t.x,t.y,"north",d.roomSize/4));break;case"in":const i=o.clone();i.rotation(-90),i.position(F(t.x,t.y,"east",d.roomSize/4)),s.add(i),o.rotation(90),o.position(F(t.x,t.y,"west",d.roomSize/4));break;case"out":const r=o.clone();r.rotation(90),r.position(F(t.x,t.y,"east",d.roomSize/4)),s.add(r),o.rotation(-90),o.position(F(t.x,t.y,"west",d.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 R.Rect({x:s.x-d.roomSize/4,y:s.y-d.roomSize/4,width:d.roomSize/2,height:d.roomSize/2,stroke:vt(e),strokeWidth:d.lineWidth})}}class yt{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 it{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,o])=>(e[+s]=new yt(o,this.area.labels.filter(n=>n.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,o){if(t===e)return;const n=Math.min(t,e),i=Math.max(t,e),r=`${n}-${i}`;let a=this.exits.get(r);a||(a={a:n,b:i,zIndex:[s]}),n==t?a.aDir=o:a.bDir=o,a.zIndex.push(s),this.exits.set(r,a)}}class at extends yt{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 Q extends it{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 at(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 at(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 o=this.visitedRooms.has(s);this.visitedRooms.add(s),!o&&this.areaRoomIds.has(s)&&e++}return e>0&&this.markDirty(),e}}class Ct{constructor(t,e){this.paths=[],this.mapReader=t,this.overlayLayer=e}renderPath(t,e,s,o="#66E64D"){if(e===void 0||s===void 0)return;const n=t.map(h=>this.mapReader.getRoom(h)).filter(h=>h!==void 0),i=[];let r=null;const a=()=>{r&&(r.length<4&&i.pop(),r=null)},c=()=>(r||(r=[],i.push(r)),r);n.forEach((h,g)=>{if(!this.isRoomVisible(h,e,s))return;const f=g>0?n[g-1]:void 0,u=g<n.length-1?n[g+1]:void 0;if(this.isRoomVisible(f,e,s))c();else{a();const x=c();if(f){const y=this.getDirectionTowards(h,f);if(y){const I=F(h.x,h.y,y,d.roomSize);x.push(I.x,I.y)}}}if(r?.push(h.x,h.y),!this.isRoomVisible(u,e,s)&&u){const x=this.getDirectionTowards(h,u);if(x){const y=F(h.x,h.y,x,d.roomSize);r?.push(y.x,y.y)}a()}}),a();const l=i.filter(h=>h.length>=4).map(h=>new R.Line({points:h,stroke:o,strokeWidth:d.lineWidth*4}));return l.forEach(h=>{this.overlayLayer.add(h),this.paths.push(h)}),l[0]}clearPaths(){this.paths.forEach(t=>{t.destroy()}),this.paths=[]}isRoomVisible(t,e,s){return t?t.area===e&&t.z===s:!1}getDirectionTowards(t,e){for(const s of ot)if(t.exits[s]===e.id)return s;for(const s of ot)if(e.exits[s]===t.id)return pt[s]}}const St=.6,K=75,kt=.025,It="rgb(225, 255, 225)",_="rgb(120, 72, 0)";function ht(C,t){const e=parseInt(C.slice(1,3),16),s=parseInt(C.slice(3,5),16),o=parseInt(C.slice(5,7),16);return`rgba(${e}, ${s}, ${o}, ${t})`}const B=class B{};B.roomSize=St,B.lineWidth=kt,B.lineColor=It,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 d=B;class Mt{constructor(t,e){this.highlights=new Map,this.currentZoom=1,this.currentRoomOverlay=[],this.roomNodes=new Map,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 R.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 R.Layer({listening:!1}),this.stage.add(this.linkLayer),this.roomLayer=new R.Layer,this.stage.add(this.roomLayer),this.positionLayer=new R.Layer({listening:!1}),this.stage.add(this.positionLayer),this.overlayLayer=new R.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.currentRoomId&&this.centerOnRoom(this.mapReader.getRoom(this.currentRoomId),!1),this.stage.batchDraw(),this.scheduleRoomCulling()}initScaling(t){R.hitOnDragEnabled=!0;let e,s=!1,o=!1;this.stage.on("touchstart",n=>{const i=n.evt.touches;i&&i.length>1?(o=!0,this.stage.isDragging()&&(this.stage.stopDrag(),s=!0),this.stage.draggable(!1)):(o=!1,this.stage.draggable(!0))}),this.stage.on("touchend touchcancel",n=>{e=void 0;const i=n.evt.touches;(!i||i.length<=1)&&(o=!1,this.stage.draggable(!0))}),this.stage.on("wheel",n=>{n.evt.preventDefault();const i=this.stage.scaleX(),r=this.stage.getPointerPosition();if(!r)return;const a={x:(r.x-this.stage.x())/i,y:(r.y-this.stage.y())/i};let c=n.evt.deltaY>0?-1:1;n.evt.ctrlKey&&(c=-c);const l=c>0?this.currentZoom*t:this.currentZoom/t,h=l*K,g=this.setZoom(l),f={x:r.x-a.x*h,y:r.y-a.y*h};this.stage.position(f),this.scheduleRoomCulling(),g&&this.emitZoomChangeEvent()}),this.stage.on("touchmove",n=>{const i=n.evt.touches,r=i?.[0],a=i?.[1];if(a||o&&(o=!1,this.stage.draggable(!0)),r&&!a&&s&&!this.stage.isDragging()&&(this.stage.startDrag(),s=!1),!r||!a){e=void 0;return}n.evt.preventDefault(),this.stage.isDragging()&&(this.stage.stopDrag(),s=!0),o||(o=!0,this.stage.draggable(!1));const c=this.stage.container().getBoundingClientRect(),l={x:r.clientX-c.left,y:r.clientY-c.top},h={x:a.clientX-c.left,y:a.clientY-c.top},g=Math.hypot(l.x-h.x,l.y-h.y);if(e===void 0){e=g;return}if(e===0)return;const f=this.stage.scaleX(),u=this.stage.x(),p=this.stage.y(),m={x:this.stage.width()/2,y:this.stage.height()/2},x={x:(m.x-u)/f,y:(m.y-p)/f},y=this.currentZoom*(g/e),I=this.setZoom(y),A=this.stage.scaleX(),O={x:m.x-x.x*A,y:m.y-x.y*A};this.stage.position(O),this.stage.batchDraw(),this.scheduleRoomCulling(),e=g,I&&this.emitZoomChangeEvent()})}drawArea(t,e){const s=this.mapReader.getArea(t);if(!s)return;const o=s.getPlane(e);o&&(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:K*this.currentZoom,y:K*this.currentZoom}),this.renderLabels(o.getLabels()),this.renderExits(s.getLinkExits(e)),this.renderRooms(o.getRooms()??[]),this.refreshHighlights(),this.stage.batchDraw(),this.scheduleRoomCulling())}computeSpatialBucketSize(){return Math.max(d.roomSize*10,5)}getBucketKey(t,e){return`${t},${e}`}forEachBucket(t,e,s,o,n){const i=this.spatialBucketSize,r=Math.min(t,s),a=Math.max(t,s),c=Math.min(e,o),l=Math.max(e,o),h=Math.floor(r/i),g=Math.floor(a/i),f=Math.floor(c/i),u=Math.floor(l/i);for(let p=h;p<=g;p++)for(let m=f;m<=u;m++)n(this.getBucketKey(p,m))}addRoomToSpatialIndex(t){const e=d.roomSize/2,s=t.room.x-e,o=t.room.x+e,n=t.room.y-e,i=t.room.y+e;this.forEachBucket(s,n,o,i,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,o=e.x+e.width,n=e.y,i=e.y+e.height;this.forEachBucket(s,n,o,i,r=>{let a=this.exitSpatialIndex.get(r);a||(a=new Set,this.exitSpatialIndex.set(r,a)),a.add(t)})}collectRoomCandidates(t,e,s,o){const n=new Set;return this.forEachBucket(t,e,s,o,i=>{this.roomSpatialIndex.get(i)?.forEach(a=>n.add(a))}),n}collectStandaloneExitCandidates(t,e,s,o){const n=new Set;return this.forEachBucket(t,e,s,o,i=>{this.exitSpatialIndex.get(i)?.forEach(a=>n.add(a))}),n}refreshStandaloneExitBoundsIfNeeded(){this.standaloneExitBoundsRoomSize!==d.roomSize&&(this.exitSpatialIndex.clear(),this.standaloneExitNodes.forEach(t=>{t.bounds=t.node.getClientRect({relativeTo:this.linkLayer}),this.addStandaloneExitToSpatialIndex(t)}),this.standaloneExitBoundsRoomSize=d.roomSize)}emitRoomContextEvent(t,e,s){const o=this.stage.container(),n=o.getBoundingClientRect(),i={roomId:t,position:{x:e-n.left,y:s-n.top}},r=new CustomEvent("roomcontextmenu",{detail:i});o.dispatchEvent(r)}emitZoomChangeEvent(){const t=new CustomEvent("zoom",{detail:{zoom:this.currentZoom}});this.stage.container().dispatchEvent(t)}setZoom(t){return this.currentZoom===t?!1:(this.currentZoom=t,this.stage.scale({x:K*t,y:K*t}),this.scheduleRoomCulling(),!0)}getZoom(){return this.currentZoom}setCullingMode(t){d.cullingMode=t,d.cullingEnabled=t!=="none",this.scheduleRoomCulling()}getCullingMode(){return d.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))}setPosition(t){const e=this.mapReader.getRoom(t);if(!e)return;const s=this.mapReader.getArea(e.area),o=s?.getVersion();let n=this.currentArea!==e.area||this.currentZIndex!==e.z;(this.currentArea!==e.area||this.currentZIndex!==e.z||o!==void 0&&this.currentAreaVersion!==o||s!==void 0&&this.currentAreaInstance!==s)&&this.drawArea(e.area,e.z),this.centerOnRoom(e,n),this.updateCurrentRoomOverlay(e);const i=ht(d.playerMarker.strokeColor,d.playerMarker.strokeAlpha),r=ht(d.playerMarker.fillColor,d.playerMarker.fillAlpha),a=d.roomSize/2*d.playerMarker.sizeFactor;this.positionRender?(this.positionRender.radius(a),this.positionRender.stroke(i),this.positionRender.fill(r),this.positionRender.strokeWidth(d.playerMarker.strokeWidth),this.positionRender.dash(d.playerMarker.dash??[]),this.positionRender.dashEnabled(d.playerMarker.dashEnabled)):(this.positionRender=new R.Circle({x:e.x,y:e.y,radius:a,stroke:i,fill:r,strokeWidth:d.playerMarker.strokeWidth,dash:d.playerMarker.dash,dashEnabled:d.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),o=s?.getVersion();let n=this.currentArea!==e.area||this.currentZIndex!==e.z;(this.currentArea!==e.area||this.currentZIndex!==e.z||o!==void 0&&this.currentAreaVersion!==o||s!==void 0&&this.currentAreaInstance!==s)&&this.drawArea(e.area,e.z),this.centerOnRoomView(e,n)}renderPath(t,e){return this.pathRenderer.renderPath(t,this.currentArea,this.currentZIndex,e)}clearPaths(){this.pathRenderer.clearPaths()}renderHighlight(t,e){const s=this.mapReader.getRoom(t);if(!s)return;const o=this.highlights.get(t);o?.shape&&(o.shape.destroy(),delete o.shape);const n={color:e,area:s.area,z:s.z};if(this.highlights.set(t,n),s.area===this.currentArea&&s.z===this.currentZIndex){const i=this.createHighlightShape(s,e);return this.overlayLayer.add(i),n.shape=i,this.overlayLayer.batchDraw(),i}return n.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 o=this.createHighlightShape(s,t.color);this.overlayLayer.add(o),t.shape=o}),this.overlayLayer.batchDraw()}createHighlightShape(t,e){return d.roomShape==="circle"?new R.Circle({x:t.x,y:t.y,radius:d.roomSize/2*1.5,stroke:e,strokeWidth:.1,dash:[.05,.05],dashEnabled:!0,listening:!1}):new R.Rect({x:t.x-d.roomSize/2*1.5,y:t.y-d.roomSize/2*1.5,width:d.roomSize*1.5,height:d.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 n=this.stage.getAbsoluteTransform().point(s),i={x:this.stage.width()/2,y:this.stage.height()/2},r=i.x-n.x,a=i.y-n.y;this.currentTransition&&(this.currentTransition.pause(),this.currentTransition.destroy(),delete this.currentTransition),e||d.instantMapMove?(this.stage.position({x:this.stage.x()+r,y:this.stage.y()+a}),this.scheduleRoomCulling()):(this.currentTransition=new R.Tween({node:this.stage,x:this.stage.x()+r,y:this.stage.y()+a,duration:.2,easing:R.Easings.EaseInOut,onUpdate:()=>this.scheduleRoomCulling(),onFinish:()=>this.scheduleRoomCulling()}),this.currentTransition.play())}centerOnRoomView(t,e=!1){const s={x:t.x,y:t.y},n=this.stage.getAbsoluteTransform().point(s),i={x:this.stage.width()/2,y:this.stage.height()/2},r=i.x-n.x,a=i.y-n.y;this.currentTransition&&(this.currentTransition.pause(),this.currentTransition.destroy(),delete this.currentTransition),e||d.instantMapMove?(this.stage.position({x:this.stage.x()+r,y:this.stage.y()+a}),this.scheduleRoomCulling()):(this.currentTransition=new R.Tween({node:this.stage,x:this.stage.x()+r,y:this.stage.y()+a,duration:.2,easing:R.Easings.EaseInOut,onUpdate:()=>this.scheduleRoomCulling(),onFinish:()=>this.scheduleRoomCulling()}),this.currentTransition.play())}renderRooms(t){t.forEach(e=>{const s=new R.Group({x:e.x-d.roomSize/2,y:e.y-d.roomSize/2}),o=this.mapReader.getColorValue(e.env),n=d.lineColor,r=d.roomShape==="circle"?new R.Circle({x:d.roomSize/2,y:d.roomSize/2,radius:d.roomSize/2,fill:o,strokeWidth:d.lineWidth,stroke:n,perfectDrawEnabled:!1}):new R.Rect({x:0,y:0,width:d.roomSize,height:d.roomSize,fill:o,strokeWidth:d.lineWidth,stroke:n,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 c,l,h;const g=()=>{h!==void 0&&(this.stage.draggable(h),h=void 0)},f=()=>{c!==void 0&&(window.clearTimeout(c),c=void 0),l=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&&(l={clientX:x.clientX,clientY:x.clientY},h=this.stage.draggable(),this.stage.draggable(!1),c=window.setTimeout(()=>{l&&a(l.clientX,l.clientY),f()},500))}),s.on("touchend",f),s.on("touchmove",m=>{if(!l)return;const x=m.evt.touches?.[0];if(!x){f();return}const y=x.clientX-l.clientX,I=x.clientY-l.clientY,A=y*y+I*I,O=10;if(A>O*O){const T=h;f(),T&&this.stage.startDrag()}}),s.on("touchcancel",f),s.add(r),this.renderSymbol(e,s),this.roomLayer.add(s);const u=[];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),u.push(m)}),this.exitRenderer.renderInnerExits(e).forEach(m=>{this.roomLayer.add(m)});const p={room:e,group:s,linkNodes:u};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=d.roomSize/2,o=d.cullingBounds,n=o?o.x:0,i=o?o.x+o.width:this.stage.width(),r=o?o.y:0,a=o?o.y+o.height:this.stage.height(),c=Math.min(n,i),l=Math.max(n,i),h=Math.min(r,a),g=Math.max(r,a),f=(c-e.x)/t,u=(l-e.x)/t,p=(h-e.y)/t,m=(g-e.y)/t;let x=!1,y=!1;const I=d.cullingEnabled?d.cullingMode??"indexed":"none",A=f-s,O=u+s,T=p-s,w=m+s;if(this.refreshStandaloneExitBoundsIfNeeded(),I==="none"){this.roomNodes.forEach(v=>{v.group.visible()||(v.group.visible(!0),x=!0),v.linkNodes.forEach(k=>{k.visible()||(k.visible(!0),y=!0)})}),this.standaloneExitNodes.forEach(v=>{const{node:k}=v;k.visible()||(y=!0,k.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 Y=M.room.x-s,X=M.room.x+s,W=M.room.y-s,V=M.room.y+s,P=X>=f&&Y<=u&&V>=p&&W<=m;M.group.visible()!==P&&(M.group.visible(P),x=!0),M.linkNodes.forEach($=>{$.visible()!==P&&($.visible(P),y=!0)}),P&&v.add(M)});const k=new Set;this.standaloneExitNodes.forEach(M=>{const{node:Y,bounds:X}=M,W=X.x,V=X.x+X.width,P=X.y,$=X.y+X.height,G=V>=f&&W<=u&&$>=p&&P<=m;Y.visible()!==G&&(Y.visible(G),y=!0),G&&k.add(M)}),this.visibleRooms=v,this.visibleStandaloneExitNodes=k,x&&this.roomLayer.batchDraw(),y&&this.linkLayer.batchDraw();return}const b=this.collectRoomCandidates(A,T,O,w),S=new Set,D=new Set;b.forEach(v=>{S.add(v);const k=v.room.x-s,M=v.room.x+s,Y=v.room.y-s,X=v.room.y+s,W=M>=f&&k<=u&&X>=p&&Y<=m;v.group.visible()!==W&&(v.group.visible(W),x=!0),v.linkNodes.forEach(V=>{V.visible()!==W&&(V.visible(W),y=!0)}),W&&D.add(v)}),this.visibleRooms.forEach(v=>{S.has(v)||(v.group.visible()&&(v.group.visible(!1),x=!0),v.linkNodes.forEach(k=>{k.visible()&&(k.visible(!1),y=!0)}))}),this.visibleRooms=D;const E=this.collectStandaloneExitCandidates(A,T,O,w),N=new Set,L=new Set;E.forEach(v=>{N.add(v);const{node:k,bounds:M}=v,Y=M.x,X=M.x+M.width,W=M.y,V=M.y+M.height,P=X>=f&&Y<=u&&V>=p&&W<=m;k.visible()!==P&&(k.visible(P),y=!0),P&&L.add(v)}),this.visibleStandaloneExitNodes.forEach(v=>{const{node:k}=v;!N.has(v)&&k.visible()&&(k.visible(!1),y=!0)}),this.visibleStandaloneExitNodes=L,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=[],o=this.currentAreaInstance instanceof Q?this.currentAreaInstance:void 0;this.currentAreaInstance&&this.currentZIndex!==void 0&&this.currentAreaInstance.getLinkExits(this.currentZIndex).filter(a=>a.a===t.id||a.b===t.id).forEach(a=>{const c=d.highlightCurrentRoom?this.exitRenderer.renderWithColor(a,_,this.currentZIndex):this.exitRenderer.render(a,this.currentZIndex);c&&s.push(c)});const n=d.highlightCurrentRoom?_:void 0;this.exitRenderer.renderSpecialExits(t,n).forEach(r=>{s.push(r)}),(d.highlightCurrentRoom?this.exitRenderer.renderStubs(t,_):this.exitRenderer.renderStubs(t)).forEach(r=>{s.push(r)}),[...Object.values(t.exits),...Object.values(t.specialExits)].forEach(r=>{const a=this.mapReader.getRoom(r),c=!o||o.hasVisitedRoom(r);a&&a.area===this.currentArea&&a.z===this.currentZIndex&&c&&e.set(r,a)}),s.forEach(r=>{this.positionLayer.add(r),this.currentRoomOverlay.push(r)}),e.forEach((r,a)=>{const c=a===t.id,l=this.createOverlayRoomGroup(r,{stroke:c&&d.highlightCurrentRoom?_:d.lineColor});this.positionLayer.add(l),this.currentRoomOverlay.push(l),this.exitRenderer.renderInnerExits(r).forEach(h=>{this.positionLayer.add(h),this.currentRoomOverlay.push(h)})}),this.positionRender&&this.positionRender.moveToTop(),this.positionLayer.batchDraw()}createOverlayRoomGroup(t,e){const s=new R.Group({x:t.x-d.roomSize/2,y:t.y-d.roomSize/2,listening:!1}),o=this.mapReader.getColorValue(t.env),n=e.stroke,i=d.roomShape==="circle"?new R.Circle({x:d.roomSize/2,y:d.roomSize/2,radius:d.roomSize/2,fill:o,stroke:n,strokeWidth:d.lineWidth}):new R.Rect({x:0,y:0,width:d.roomSize,height:d.roomSize,fill:o,stroke:n,strokeWidth:d.lineWidth});return s.add(i),this.renderSymbol(t,s),s}renderSymbol(t,e){if(t.roomChar!==void 0){const s=d.roomSize*.75,o=new R.Text({x:0,y:0,text:t.roomChar,fontSize:s,fontStyle:"bold",fill:this.mapReader.getSymbolColor(t.env),align:"center",verticalAlign:"middle",width:d.roomSize,height:d.roomSize});e.add(o)}}renderExits(t){t.forEach(e=>{const s=this.exitRenderer.render(e,this.currentZIndex);if(!s)return;this.linkLayer.add(s);const o=s.getClientRect({relativeTo:this.linkLayer}),n={node:s,bounds:o};this.standaloneExitNodes.push(n),this.addStandaloneExitToSpatialIndex(n)}),this.standaloneExitBoundsRoomSize=d.roomSize}renderLabels(t){t.forEach(e=>{if(d.labelRenderMode==="image"){if(!e.pixMap)return;const s=new Image;s.src=`data:image/png;base64,${e.pixMap}`;const o=new R.Image({x:e.X,y:-e.Y,width:e.Width,height:e.Height,image:s,listening:!1});this.linkLayer.add(o);return}this.renderLabelAsData(e)})}renderLabelAsData(t){const e=new R.Group({listening:!1}),s=new R.Rect({x:t.X,y:-t.Y,width:t.Width,height:t.Height,listening:!1});(t.BgColor?.alpha??0)>0&&!d.transparentLabels?s.fill(this.getLabelColor(t.BgColor)):s.fillEnabled(!1),e.add(s);const o=Math.min(.75,t.Width/Math.max(t.Text.length/2,1)),n=Math.max(.1,Math.min(o,Math.max(t.Height*.9,.1))),i=new R.Text({x:t.X,y:-t.Y,width:t.Width,height:t.Height,text:t.Text,fontSize:n,fillEnabled:!0,fill:this.getLabelColor(t.FgColor),align:"center",verticalAlign:"middle",listening:!1});e.add(i),this.linkLayer.add(e)}getLabelColor(t){const e=(t?.alpha??255)/255,s=o=>Math.min(255,Math.max(0,o??0));return`rgba(${s(t?.r)}, ${s(t?.g)}, ${s(t?.b)}, ${e})`}}const ct={rgbValue:"rgb(114, 1, 0)",symbolColor:[225,225,225]};function dt(C){const t=C[0]/255,e=C[1]/255,s=C[2]/255,o=Math.max(t,e,s),n=Math.min(t,e,s);return(o+n)/2}class Dt{constructor(t,e){this.rooms={},this.areas={},this.areaSources={},this.explorationEnabled=!1,this.colors={},t.forEach(s=>{s.rooms.forEach(n=>{n.y=-n.y,this.rooms[n.id]=n});const o=parseInt(s.areaId);this.areas[o]=new it(s),this.areaSources[o]=s}),this.colors=e.reduce((s,o)=>({...s,[o.envId]:{rgb:o.colors,rgbValue:`rgb(${o.colors.join(",")})`,symbolColor:dt(o.colors)>.41?[25,25,25]:[225,255,255],symbolColorValue:dt(o.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 Q)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 Q(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 it(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 o=this.getRoom(t);if(o){const n=this.getExplorationArea(o.area);if(n)return n.addVisitedRoom(t)}}const e=this.ensureVisitedRooms(),s=e.has(t);return e.add(t),!s}addVisitedRooms(t){const e=this.ensureVisitedRooms();let s=0;for(const o of t){if(this.explorationEnabled){const i=this.getRoom(o);if(i){const r=this.getExplorationArea(i.area);if(r){r.addVisitedRoom(o)&&s++;continue}}}const n=e.has(o);e.add(o),n||s++}return s}hasVisitedRoom(t){return this.visitedRooms?.has(t)??!1}getColorValue(t){return this.colors[t]?.rgbValue??ct.rgbValue}getSymbolColor(t,e){const s=this.colors[t]?.symbolColor??ct.symbolColor,o=Math.min(Math.max(e??1,0),1),n=s.join(",");return o!=1?`rgba(${n}, ${o})`:`rgba(${n})`}}function Nt(C){return C&&C.__esModule&&Object.prototype.hasOwnProperty.call(C,"default")?C.default:C}var U,lt;function Lt(){if(lt)return U;lt=1;class C{constructor(){this.keys=new Set,this.queue=[]}sort(){this.queue.sort((e,s)=>e.priority-s.priority)}set(e,s){const o=Number(s);if(isNaN(o))throw new TypeError('"priority" must be a number');return this.keys.has(e)?this.queue.map(n=>(n.key===e&&Object.assign(n,{priority:o}),n)):(this.keys.add(e),this.queue.push({key:e,priority:o})),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 U=C,U}var J,ut;function zt(){if(ut)return J;ut=1;function C(t,e){const s=new Map;for(const[o,n]of t)o!==e&&n instanceof Map?s.set(o,C(n,e)):o!==e&&s.set(o,n);return s}return J=C,J}var tt,ft;function At(){if(ft)return tt;ft=1;function C(e){const s=Number(e);return!(isNaN(s)||s<=0)}function t(e){const s=new Map;return Object.keys(e).forEach(n=>{const i=e[n];if(i!==null&&typeof i=="object"&&!Array.isArray(i))return s.set(n,t(i));if(!C(i))throw new Error(`Could not add node at key "${n}", make sure it's a valid node`,i);return s.set(n,Number(i))}),s}return tt=t,tt}var et,gt;function Xt(){if(gt)return et;gt=1;function C(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){C(e);return}if(typeof e!="number"||e<=0)throw new Error(`Values must be numbers greater than 0. Found value ${e} at ${s}`)})}return et=C,et}var st,mt;function Ot(){if(mt)return st;mt=1;const C=Lt(),t=zt(),e=At(),s=Xt();class o{constructor(i){i instanceof Map?(s(i),this.graph=i):i?this.graph=e(i):this.graph=new Map}addNode(i,r){let a;return r instanceof Map?(s(r),a=r):a=e(r),this.graph.set(i,a),this}addVertex(i,r){return this.addNode(i,r)}removeNode(i){return this.graph=t(this.graph,i),this}path(i,r,a={}){if(!this.graph.size)return a.cost?{path:null,cost:0}:null;const c=new Set,l=new C,h=new Map;let g=[],f=0,u=[];if(a.avoid&&(u=[].concat(a.avoid)),u.includes(i))throw new Error(`Starting node (${i}) cannot be avoided`);if(u.includes(r))throw new Error(`Ending node (${r}) cannot be avoided`);for(l.set(i,0);!l.isEmpty();){const p=l.next();if(p.key===r){f=p.priority;let x=p.key;for(;h.has(x);)g.push(x),x=h.get(x);break}c.add(p.key),(this.graph.get(p.key)||new Map).forEach((x,y)=>{if(c.has(y)||u.includes(y))return null;if(!l.has(y))return h.set(y,p.key),l.set(y,p.priority+x);const I=l.get(y).priority,A=p.priority+x;return A<I?(h.set(y,p.key),l.set(y,A)):null})}return g.length?(a.trim?g.shift():g=g.concat([i]),a.reverse||(g=g.reverse()),a.cost?{path:g,cost:f}:g):a.cost?{path:null,cost:0}:null}shortestPath(...i){return this.path(...i)}}return st=o,st}var Yt=Ot();const Pt=Nt(Yt),Vt={1:"north",2:"northeast",3:"northwest",4:"east",5:"west",6:"south",7:"southeast",8:"southwest",9:"up",10:"down",11:"in",12:"out"};class Tt{constructor(t){this.cache=new Map,this.mapReader=t,this.graph=this.buildGraph()}buildGraph(){const t={};return this.mapReader.getRooms().forEach(e=>{const s={},o=new Set((e.exitLocks??[]).map(i=>Vt[i]).filter(i=>!!i)),n=new Set(e.mSpecialExitLocks??[]);Object.entries(e.exits??{}).forEach(([i,r])=>{o.has(i)||this.mapReader.getRoom(r)&&(s[r.toString()]=1)}),Object.values(e.specialExits??{}).forEach(i=>{n.has(i)||this.mapReader.getRoom(i)&&(s[i.toString()]=1)}),t[e.id.toString()]=s}),new Pt(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 o=this.graph.path(t.toString(),e.toString()),n=Array.isArray(o)?o:o?.path,i=n?n.map(r=>Number(r)):null;return this.cache.set(s,i),i}}const Wt={1:"north",2:"northeast",3:"northwest",4:"east",5:"west",6:"south",7:"southeast",8:"southwest",9:"up",10:"down",11:"in",12:"out"},Z=class Z{};Z.areaWidth=150,Z.areaHeight=80,Z.areaSpacing=50,Z.fontSize=14,Z.connectionLineWidth=2,Z.areaFillColor="#2a2a3e",Z.areaStrokeColor="#4a4a6e",Z.textColor="#e0e0e0",Z.connectionColor="#6a6a8e",Z.highlightColor="#ff9900";let z=Z;class Ft{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 R.Stage({container:t,width:t.clientWidth,height:t.clientHeight,draggable:!0}),this.backgroundLayer=new R.Layer({listening:!1}),this.stage.add(this.backgroundLayer),this.connectionLayer=new R.Layer({listening:!1}),this.stage.add(this.connectionLayer),this.areaLayer=new R.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(),o=this.stage.getPointerPosition();if(!o)return;const n={x:(o.x-this.stage.x())/s,y:(o.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(),c={x:o.x-n.x*a,y:o.y-n.y*a};this.stage.position(c),this.stage.batchDraw()})}setZoom(t){this.currentZoom=Math.max(.1,Math.min(5,t)),this.stage.scale({x:this.currentZoom,y:this.currentZoom})}getZoom(){return this.currentZoom}setDomainInfo(t){this.domainInfo.clear();for(const[e,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),o=this.domainInfo.get(e);return!s||!o?!1:!!(s.isIshtar&&o.isIshtar||s.isEmpire&&o.isEmpire||!s.isIshtar&&!s.isEmpire&&!o.isIshtar&&!o.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 R.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 c of e){const l=c.getAreaId(),h=c.getRooms();if(h.length===0)continue;let g=1/0,f=-1/0,u=1/0,p=-1/0,m=0;for(const I of h)I.z===0&&(m++,g=Math.min(g,I.x),f=Math.max(f,I.x),u=Math.min(u,I.y),p=Math.max(p,I.y));if(m===0)for(const I of h)g=Math.min(g,I.x),f=Math.max(f,I.x),u=Math.min(u,I.y),p=Math.max(p,I.y);const x=(g+f)/2,y=(u+p)/2;s.set(l,{minX:g,maxX:f,minY:u,maxY:p,centerX:x,centerY:y,roomCount:h.length})}let o=1;for(const c of s.values()){const l=c.maxX-c.minX,h=c.maxY-c.minY;o=Math.max(o,l,h)}const n=200,i=100,r=n/o;for(const c of e){const l=c.getAreaId(),h=s.get(l);if(!h||!this.isAreaInDomain(l))continue;const g=h.maxX-h.minX,f=h.maxY-h.minY;let u=Math.max(i,g*r),p=Math.max(i,f*r);const m=u/p;m>3?p=u/3:m<1/3&&(u=p/3),this.areaNodes.set(l,{areaId:l,name:c.getAreaName(),x:0,y:0,width:u,height:p,connections:[],roomCount:h.roomCount,realCenterX:h.centerX,realCenterY:h.centerY})}const a=new Map;for(const c of t){const l=c.area;if(!this.areaNodes.has(l))continue;const h=this.getLockedDirections(c),g=new Set(c.mSpecialExitLocks??[]);for(const[f,u]of Object.entries(c.exits??{})){if(h.has(f))continue;const p=this.mapReader.getRoom(u);if(!p||p.area===l||!this.areaNodes.has(p.area)||!this.areAreasInSameDomain(l,p.area))continue;const m=this.createConnection(c,p,f);m&&this.addConnection(a,m)}for(const[f,u]of Object.entries(c.specialExits??{})){if(g.has(u))continue;const p=this.mapReader.getRoom(u);if(!p||p.area===l||!this.areaNodes.has(p.area)||!this.areAreasInSameDomain(l,p.area))continue;const m=this.parseDirection(f),x=this.createConnection(c,p,m);x&&this.addConnection(a,x)}}for(const[c,l]of a){const[h,g]=c.split("-").map(Number),f=this.createConnectionGroup(h,g,l);this.connectionGroups.push(f);const u=this.areaNodes.get(h),p=this.areaNodes.get(g);if(u&&u.connections.push(...l),p)for(const m of l)p.connections.push({...m,fromAreaId:m.toAreaId,toAreaId:m.fromAreaId,fromRoomId:m.toRoomId,toRoomId:m.fromRoomId,direction:m.direction?pt[m.direction]:null,fromRoomPosition:m.toRoomPosition,toRoomPosition:m.fromRoomPosition})}}getLockedDirections(t){return new Set((t.exitLocks??[]).map(e=>Wt[e]).filter(e=>!!e))}createConnection(t,e,s){const o=this.toPlanarDirection(s);return{fromAreaId:t.area,toAreaId:e.area,fromRoomId:t.id,toRoomId:e.id,direction:o,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 o=new Map;let n=0,i=0;for(const c of s)c.direction&&o.set(c.direction,(o.get(c.direction)??0)+1),n+=c.toRoomPosition.x-c.fromRoomPosition.x,i+=c.toRoomPosition.y-c.fromRoomPosition.y;let r=null,a=0;for(const[c,l]of o)l>a&&(a=l,r=c);return{fromAreaId:t,toAreaId:e,connections:s,primaryDirection:r,averageOffset:{x:n/s.length,y:i/s.length}}}parseDirection(t){const e=t.toLowerCase().trim();return{n:"north",north:"north",s:"south",south:"south",e:"east",east:"east",w:"west",west:"west",ne:"northeast",northeast:"northeast",nw:"northwest",northwest:"northwest",se:"southeast",southeast:"southeast",sw:"southwest",southwest:"southwest",u:"up",up:"up",d:"down",down:"down",i:"in",in:"in",o:"out",out:"out"}[e]??null}toPlanarDirection(t){return t&&ot.includes(t)?t:null}layoutAreas(){if(Array.from(this.areaNodes.values()).length===0)return;const e=this.findConnectedComponents();let s=0;const o=z.areaWidth*3;for(const n of e)if(n.length===1){const i=this.areaNodes.get(n[0]);i&&(i.x=s,i.y=0),s+=z.areaWidth+o}else{const i=this.forceDirectedLayout(n);for(const a of n){const c=this.areaNodes.get(a);c&&isFinite(i.minX)&&isFinite(i.minY)&&(c.x-=i.minX,c.x+=s,c.y-=i.minY)}const r=isFinite(i.maxX-i.minX)?i.maxX-i.minX:z.areaWidth;s+=r+o}}findConnectedComponents(){const t=new Set,e=[];for(const[s]of this.areaNodes){if(t.has(s))continue;const o=[],n=[s];for(;n.length>0;){const i=n.shift();if(t.has(i))continue;t.add(i),o.push(i);const r=this.areaNodes.get(i);if(r)for(const a of r.connections)t.has(a.toAreaId)||n.push(a.toAreaId)}e.push(o)}return e}forceDirectedLayout(t){const e=new Map;for(const w of t){const b=this.areaNodes.get(w);if(!b)continue;const S=new Set(b.connections.map(D=>D.toAreaId));e.set(w,S)}const s=new Set,o=new Set;for(const[w,b]of e)b.size>=3&&s.add(w);for(const[w,b]of e){if(s.has(w)||o.has(w)||b.size>2)continue;const S=[w];o.add(w);const D=Array.from(b);for(const N of D){let L=N,v=w;for(;L&&!o.has(L)&&!s.has(L);){const k=e.get(L);if(!k)break;if(k.size>=3){s.add(L);break}S.push(L),o.add(L);let M=!1;for(const Y of k)if(Y!==v&&!o.has(Y)){v=L,L=Y,M=!0;break}if(!M)break}}let E=!1;for(const N of S){const L=e.get(N);if(L){for(const v of L)if(s.has(v)){E=!0;break}}if(E)break}if(!E&&S.length>0){let N=S[0],L=e.get(S[0])?.size??0;for(const v of S){const k=e.get(v)?.size??0;k>L&&(L=k,N=v)}s.add(N),o.delete(N)}}for(const w of t){const b=e.get(w);(!b||b.size===0)&&s.add(w)}const n=new Map,i=new Map;for(const w of s)n.set(w,w),i.set(w,[]);const r=new Set(s);for(const w of s){const b=e.get(w)??new Set;for(const S of b){if(r.has(S))continue;const D=[];let E=S,N=w;for(;E&&!r.has(E);){D.push(E),n.set(E,w),r.add(E);const L=e.get(E)??new Set;let v;for(const k of L)if(k!==N&&!r.has(k)){v=k;break}N=E,E=v}D.length>0&&i.get(w).push(D)}}const a=new Set,c=[],l=s.values().next().value,h=l!==void 0?l:t[0];if(h!==void 0){const w=this.areaNodes.get(h);w&&(w.x=0,w.y=0,a.add(h),c.push(h))}for(;c.length>0;){const w=c.shift(),b=this.areaNodes.get(w),S=new Map;for(const D of b.connections){const E=D.toAreaId;if(a.has(E)||!s.has(E))continue;const N=this.areaNodes.get(E);if(!N)continue;const L=D.direction??"none";S.has(L)||S.set(L,[]),S.get(L).push({id:E,node:N,conn:D})}for(const[D,E]of S){const N=this.getDirectionOffset(D==="none"?null:D);E.sort((k,M)=>Math.abs(N.x)>Math.abs(N.y)?M.node.realCenterY-k.node.realCenterY:k.node.realCenterX-M.node.realCenterX);const L=z.areaWidth+z.areaSpacing,v=z.areaHeight+z.areaSpacing;E.forEach((k,M)=>{if(k.node.x=b.x+N.x*L,k.node.y=b.y+N.y*v,E.length>1){const Y=(M-(E.length-1)/2)*.5;Math.abs(N.x)>Math.abs(N.y)?k.node.y+=Y*v:k.node.x+=Y*L}a.add(k.id),c.push(k.id)})}}const g=Array.from(s);g.length>1&&this.applyForces(g,80);const f=z.areaWidth+z.areaSpacing+30,u=z.areaHeight+z.areaSpacing+30,p=new Map,m=["east","west","north","south","northeast","northwest","southeast","southwest"];for(const[w,b]of i){const S=this.areaNodes.get(w);if(!S)continue;let D=0;const E=new Map;for(const N of b){let L=w,v=S.x,k=S.y,M=null;for(const Y of N){const X=this.areaNodes.get(Y);if(!X)continue;const W=this.areaNodes.get(L);let V=null;if(W){for(const G of W.connections)if(G.toAreaId===Y){V=G.direction;break}}!V&&L===w?(M=m[D%m.length],D++,V=M):!V&&M&&(V=M);const P=this.getDirectionOffset(V);let $=0;if(L===w&&V){const G=V,rt=E.get(G)??0;E.set(G,rt+1),$=rt}X.x=v+P.x*f,X.y=k+P.y*u,$>0&&(P.x!==0&&P.y===0?X.y+=$*u*1.2:P.y!==0&&P.x===0?X.x+=$*f*1.2:(X.x+=$*f*1.2,X.y-=$*u*1.2)),p.set(Y,{dx:X.x-S.x,dy:X.y-S.y,hubId:w}),L=Y,v=X.x,k=X.y}}}const x=new Map,y=new Map;for(const w of s){const b=this.areaNodes.get(w);if(!b)continue;let S=b.x,D=b.y,E=b.x+b.width,N=b.y+b.height;const L=i.get(w)??[];for(const v of L)for(const k of v){const M=this.areaNodes.get(k);M&&(S=Math.min(S,M.x),D=Math.min(D,M.y),E=Math.max(E,M.x+M.width),N=Math.max(N,M.y+M.height))}x.set(w,{minX:S,minY:D,maxX:E,maxY:N}),y.set(w,{dx:S-b.x,dy:D-b.y})}this.applyClusterForces(g,x,y,60);for(const[w,b]of p){const S=this.areaNodes.get(w),D=this.areaNodes.get(b.hubId);!S||!D||(S.x=D.x+b.dx,S.y=D.y+b.dy)}let I=1/0,A=1/0,O=-1/0,T=-1/0;for(const w of t){const b=this.areaNodes.get(w);I=Math.min(I,b.x),A=Math.min(A,b.y),O=Math.max(O,b.x+b.width),T=Math.max(T,b.y+b.height)}return{minX:I,minY:A,maxX:O,maxY:T}}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,o){const r=new Map;for(const a of t)r.set(a,{vx:0,vy:0});for(let a=0;a<o;a++){for(const c of t){const l=this.areaNodes.get(c),h=e.get(c),g=s.get(c);if(!l||!h||!g)continue;const f=h.maxX-h.minX,u=h.maxY-h.minY;h.minX=l.x+g.dx,h.minY=l.y+g.dy,h.maxX=h.minX+f,h.maxY=h.minY+u}for(const c of t){const l=this.areaNodes.get(c),h=r.get(c),g=e.get(c);if(!(!l||!h||!g)){for(const f of t){if(c===f)continue;const u=e.get(f);if(!u)continue;const p=(g.minX+g.maxX)/2,m=(g.minY+g.maxY)/2,x=(u.minX+u.maxX)/2,y=(u.minY+u.maxY)/2,I=p-x,A=m-y,O=(g.maxX-g.minX)/2,T=(g.maxY-g.minY)/2,w=(u.maxX-u.minX)/2,b=(u.maxY-u.minY)/2,S=O+w+50,D=T+b+50,E=S-Math.abs(I),N=D-Math.abs(A);if(E>0&&N>0)if(E<N){const L=E*(I>=0?1:-1)*.5;h.vx+=L}else{const L=N*(A>=0?1:-1)*.5;h.vy+=L}}for(const f of l.connections){const u=this.areaNodes.get(f.toAreaId);if(!u||!t.includes(f.toAreaId))continue;const p=u.x-l.x,m=u.y-l.y,x=Math.sqrt(p*p+m*m)||1,y=z.areaWidth+z.areaSpacing+50,A=(x-y)*.015;h.vx+=p/x*A,h.vy+=m/x*A}}}for(const c of t){const l=this.areaNodes.get(c),h=r.get(c);!l||!h||(l.x+=h.vx,l.y+=h.vy,h.vx*=.8,h.vy*=.8)}}}applyForces(t,e){const n=z.areaWidth+z.areaSpacing,i=z.areaWidth/2+60,r=new Set(t),a=[],c=new Set;for(const h of t){const g=this.areaNodes.get(h);if(g)for(const f of g.connections){if(!r.has(f.toAreaId))continue;const u=Math.min(h,f.toAreaId)+"-"+Math.max(h,f.toAreaId);c.has(u)||(c.add(u),a.push({from:h,to:f.toAreaId}))}}const l=new Map;for(const h of t)l.set(h,{vx:0,vy:0});for(let h=0;h<e;h++){for(const g of t){const f=this.areaNodes.get(g),u=l.get(g);if(!f||!u)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,O=f.x+f.width/2,T=f.y+f.height/2,w=y.x+y.width/2,b=y.y+y.height/2,S=O-w,D=T-b,E=I-Math.abs(S),N=A-Math.abs(D);E>0&&N>0&&(E<N?u.vx+=(S>=0?1:-1)*E*.5:u.vy+=(D>=0?1:-1)*N*.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,O=y.y+y.height/2,T=I.x+I.width/2,w=I.y+I.height/2,b=this.closestPointOnSegment(p,m,A,O,T,w),S=p-b.x,D=m-b.y,E=Math.sqrt(S*S+D*D)||1;if(E<i){const N=(i-E)*.6;u.vx+=S/E*N,u.vy+=D/E*N}}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,O=Math.sqrt(I*I+A*A)||1,w=(O-n)*.03;u.vx+=I/O*w,u.vy+=A/O*w;const b=this.getDirectionOffset(x.direction),S=f.x+b.x*n,D=f.y+b.y*n,E=l.get(x.toAreaId);E&&(E.vx+=(S-y.x)*.01,E.vy+=(D-y.y)*.01)}}for(const g of t){const f=this.areaNodes.get(g),u=l.get(g);!f||!u||(f.x+=u.vx,f.y+=u.vy,u.vx*=.8,u.vy*=.8)}}}closestPointOnSegment(t,e,s,o,n,i){const r=n-s,a=i-o,c=t-s,l=e-o,h=r*r+a*a;if(h===0)return{x:s,y:o};let g=(c*r+l*a)/h;return g=Math.max(0,Math.min(1,g)),{x:s+g*r,y:o+g*a}}edgesIntersect(t,e,s,o,n,i,r,a){const c=(l,h,g,f,u,p)=>(p-h)*(g-l)>(f-h)*(u-l);return c(t,e,n,i,r,a)!==c(s,o,n,i,r,a)&&c(t,e,s,o,n,i)!==c(t,e,s,o,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 o={x:e.x+e.width/2,y:e.y+e.height/2},n={x:s.x+s.width/2,y:s.y+s.height/2};let i,r;if(this.dotsMode?(i=o,r=n):(i=this.getEdgePoint(e,n),r=this.getEdgePoint(s,o)),!isFinite(i.x)||!isFinite(i.y)||!isFinite(r.x)||!isFinite(r.y))continue;const a=this.dotsMode?"#ffffff":z.connectionColor,c=this.dotsMode?1:Math.min(z.connectionLineWidth,1+t.connections.length*.5),l=new R.Line({points:[i.x,i.y,r.x,r.y],stroke:a,strokeWidth:c,lineCap:"round",listening:!1});this.connectionLayer.add(l)}}getEdgePoint(t,e){const s=t.x+t.width/2,o=t.y+t.height/2,n=e.x-s,i=e.y-o,r=t.width/2,a=t.height/2;if(n===0&&i===0)return{x:s,y:o};const c=Math.abs(n),l=Math.abs(i);let h;return c/r>l/a?h=r/c:h=a/l,{x:s+n*h,y:o+i*h}}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 o=t.x+t.width/2,n=t.y+t.height/2,i=new R.Group({x:o,y:n,draggable:!0}),r=new R.Circle({radius:6,fill:e?z.highlightColor:"#ffffff",stroke:e?z.highlightColor:"#ffffff",strokeWidth:1}),a=new R.Text({text:t.name,fontSize:10,fill:"#ffffff",x:10,y:-5});i.add(r),i.add(a),i.on("click tap",()=>{this.emitAreaClickEvent(t.areaId)}),i.on("mouseenter",()=>{this.stage.container().style.cursor="pointer",r.fill(z.highlightColor),r.stroke(z.highlightColor),this.areaLayer.batchDraw()}),i.on("mouseleave",()=>{this.stage.container().style.cursor="auto",r.fill(e?z.highlightColor:"#ffffff"),r.stroke(e?z.highlightColor:"#ffffff"),this.areaLayer.batchDraw()}),i.on("dragmove",()=>{t.x=i.x()-t.width/2,t.y=i.y()-t.height/2,this.drawConnections(),this.connectionLayer.batchDraw()}),i.on("dragstart",()=>{this.stage.container().style.cursor="grabbing"}),i.on("dragend",()=>{this.stage.container().style.cursor="pointer"}),this.areaLayer.add(i)}else{const s=new R.Group({x:t.x,y:t.y,draggable:!0}),o=new R.Rect({width:t.width,height:t.height,fill:z.areaFillColor,stroke:e?z.highlightColor:z.areaStrokeColor,strokeWidth:e?3:2,cornerRadius:8}),n=new R.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"}),i=new R.Text({text:`${t.roomCount} rooms`,fontSize:10,fill:z.connectionColor,width:t.width-10,x:5,y:t.height-18,align:"center"});s.add(o),s.add(n),s.add(i),s.on("click tap",()=>{this.emitAreaClickEvent(t.areaId)}),s.on("mouseenter",()=>{this.stage.container().style.cursor="pointer",o.stroke(z.highlightColor),this.areaLayer.batchDraw()}),s.on("mouseleave",()=>{this.stage.container().style.cursor="auto",o.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,o=-1/0;for(const[,u]of this.areaNodes)t=Math.min(t,u.x),e=Math.min(e,u.y),s=Math.max(s,u.x+u.width),o=Math.max(o,u.y+u.height);if(!isFinite(t))return;const n=s-t,i=o-e,r=t+n/2,a=e+i/2,c=50,l=(this.stage.width()-c*2)/n,h=(this.stage.height()-c*2)/i,g=Math.min(l,h,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(),o=e.x+e.width/2,n=e.y+e.height/2;this.stage.position({x:this.stage.width()/2-o*s,y:this.stage.height()/2-n*s}),this.stage.batchDraw()}emitAreaClickEvent(t){const e=new CustomEvent("areaclick",{detail:{areaId:t}});this.stage.container().dispatchEvent(e)}getAreaNode(t){return this.areaNodes.get(t)}getConnectionGroups(){return this.connectionGroups}destroy(){this.stage.destroy()}}exports.AreaMapRenderer=Ft;exports.AreaMapSettings=z;exports.ExplorationArea=Q;exports.MapReader=Dt;exports.PathFinder=Tt;exports.Renderer=Mt;exports.Settings=d;
2
2
  //# sourceMappingURL=index.cjs.map