mudlet-map-renderer 0.14.0-konva → 0.16.0-konva

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