mudlet-map-renderer 0.16.0-konva → 0.18.0-konva
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/Renderer.d.ts +23 -1
- package/dist/directions.d.ts +9 -0
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +839 -797
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/Renderer.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { default as MapReader } from './reader/MapReader';
|
|
|
2
2
|
import { default as Area } from './reader/Area';
|
|
3
3
|
export type LabelRenderMode = "image" | "data";
|
|
4
4
|
export type CullingMode = "none" | "basic" | "indexed";
|
|
5
|
-
export type RoomShape = "rectangle" | "circle";
|
|
5
|
+
export type RoomShape = "rectangle" | "circle" | "roundedRectangle";
|
|
6
6
|
export type RoomContextMenuEventDetail = {
|
|
7
7
|
roomId: number;
|
|
8
8
|
position: {
|
|
@@ -151,9 +151,30 @@ export declare class Settings {
|
|
|
151
151
|
* Default configuration creates a cyan-green dashed circle that's 1.7x the room size.
|
|
152
152
|
*/
|
|
153
153
|
static playerMarker: PlayerMarkerStyle;
|
|
154
|
+
/**
|
|
155
|
+
* Whether to render a subtle background grid behind the map.
|
|
156
|
+
* Default: false
|
|
157
|
+
*/
|
|
158
|
+
static gridEnabled: boolean;
|
|
159
|
+
/**
|
|
160
|
+
* Grid line spacing in map units (1 = every integer coordinate).
|
|
161
|
+
* Default: 1
|
|
162
|
+
*/
|
|
163
|
+
static gridSize: number;
|
|
164
|
+
/**
|
|
165
|
+
* Color of the grid lines as a CSS color string.
|
|
166
|
+
* Default: 'rgba(255, 255, 255, 0.07)' (very subtle white)
|
|
167
|
+
*/
|
|
168
|
+
static gridColor: string;
|
|
169
|
+
/**
|
|
170
|
+
* Width of grid lines in map units.
|
|
171
|
+
* Default: 0.02
|
|
172
|
+
*/
|
|
173
|
+
static gridLineWidth: number;
|
|
154
174
|
}
|
|
155
175
|
export declare class Renderer {
|
|
156
176
|
private readonly stage;
|
|
177
|
+
private readonly gridLayer;
|
|
157
178
|
private readonly roomLayer;
|
|
158
179
|
private readonly linkLayer;
|
|
159
180
|
private readonly overlayLayer;
|
|
@@ -238,6 +259,7 @@ export declare class Renderer {
|
|
|
238
259
|
private renderRooms;
|
|
239
260
|
private scheduleRoomCulling;
|
|
240
261
|
private updateRoomCulling;
|
|
262
|
+
private renderGrid;
|
|
241
263
|
private clearCurrentRoomOverlay;
|
|
242
264
|
private updateCurrentRoomOverlay;
|
|
243
265
|
private createOverlayRoomGroup;
|
package/dist/directions.d.ts
CHANGED
|
@@ -5,6 +5,15 @@ export declare function movePoint(x: number, y: number, direction?: MapData.dire
|
|
|
5
5
|
x: number;
|
|
6
6
|
y: number;
|
|
7
7
|
};
|
|
8
|
+
/**
|
|
9
|
+
* Calculate the edge point of a rounded rectangle for a given direction.
|
|
10
|
+
* Cardinal directions use the flat edge (same as rectangle).
|
|
11
|
+
* Diagonal directions intersect the corner arc.
|
|
12
|
+
*/
|
|
13
|
+
export declare function movePointRoundedRect(x: number, y: number, direction?: MapData.direction, distance?: number, cornerRadius?: number): {
|
|
14
|
+
x: number;
|
|
15
|
+
y: number;
|
|
16
|
+
};
|
|
8
17
|
/**
|
|
9
18
|
* Calculate the edge point of a circle for a given direction
|
|
10
19
|
* For circles, we need to calculate the exact point on the circle's circumference
|
package/dist/index.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const w=require("konva"),K=["north","south","east","west","northeast","northwest","southeast","southwest"],Z={north:"n",south:"s",east:"e",west:"w",northeast:"ne",northwest:"nw",southeast:"se",southwest:"sw",up:"u",down:"d",in:"i",out:"o"},at={north:{x:0,y:-1},south:{x:0,y:1},east:{x:1,y:0},west:{x:-1,y:0},northeast:{x:1,y:-1},northwest:{x:-1,y:-1},southeast:{x:1,y:1},southwest:{x:-1,y:1}},nt=["north","south","east","west","northeast","northwest","southeast","southwest"],xt={north:"south",south:"north",east:"west",west:"east",northeast:"southwest",northwest:"southeast",southeast:"northwest",southwest:"northeast"};function yt(E){return E?Object.prototype.hasOwnProperty.call(at,E):!1}function Y(E,t,e,s=1){if(!yt(e))return{x:E,y:t};const i=at[e];return{x:E+i.x*s,y:t+i.y*s}}function bt(E,t,e,s=1){if(!yt(e))return{x:E,y:t};const i=at[e],o=Math.atan2(i.y,i.x);return{x:E+Math.cos(o)*s,y:t+Math.sin(o)*s}}const H={OPEN_DOOR:"rgb(10, 155, 10)",CLOSED_DOOR:"rgb(226, 205, 59)",LOCKED_DOOR:"rgb(155, 10, 10)",ONE_WAY_FILL:"rgb(155, 10, 10)"},Rt={1:"north",2:"northeast",3:"northwest",4:"east",5:"west",6:"south",7:"southeast",8:"southwest",9:"up",10:"down",11:"in",12:"out"},vt=["up","down","in","out"];function kt(E){switch(E){case 1:return H.OPEN_DOOR;case 2:return H.CLOSED_DOOR;default:return H.LOCKED_DOOR}}class Et{constructor(t,e){this.mapReader=t,this.mapRenderer=e}getRoomEdgePoint(t,e,s,i){return c.roomShape==="circle"?bt(t,e,s,i):Y(t,e,s,i)}render(t,e){return this.renderWithColor(t,c.lineColor,e)}renderWithColor(t,e,s){const i=t.aDir&&K.includes(t.aDir),o=t.bDir&&K.includes(t.bDir);if(i&&o)return this.renderTwoWayExit(t,e,s);if(i||o){const n=i?"a":"b";return this.renderOneWayExit(t,e,n)}}renderTwoWayExit(t,e,s){const i=this.mapReader.getRoom(t.a),o=this.mapReader.getRoom(t.b);if(!i||!o||!t.aDir||!t.bDir||i.customLines[Z[t.aDir]]&&o.customLines[Z[t.bDir]]||i.z!==o.z&&(s!==o.z&&i.customLines[Z[t.aDir]]||s!==i.z&&o.customLines[Z[t.bDir]]))return;const n=new w.Group,r=[];if(r.push(...Object.values(this.getRoomEdgePoint(i.x,i.y,t.aDir,c.roomSize/2))),r.push(...Object.values(this.getRoomEdgePoint(o.x,o.y,t.bDir,c.roomSize/2))),i.doors[Z[t.aDir]]||o.doors[Z[t.bDir]]){const h=this.renderDoor(r,i.doors[Z[t.aDir]]??o.doors[Z[t.bDir]]);n.add(h)}const a=new w.Line({points:r,stroke:e,strokeWidth:c.lineWidth,perfectDrawEnabled:!1});return n.add(a),n}renderOneWayExit(t,e,s){const i=s==="a"||!s&&t.aDir,o=i?this.mapReader.getRoom(t.a):this.mapReader.getRoom(t.b),n=i?this.mapReader.getRoom(t.b):this.mapReader.getRoom(t.a),r=i?t.aDir:t.bDir;if(!r||!o||!n||!K.includes(r)||o.customLines[Z[r]||r])return;if(o.area!=n.area&&r){const m=this.mapReader.getColorValue(n.env);return this.renderAreaExit(o,r,m)}let a={x:n.x,y:n.y};(n.area!==o.area||n.z!==o.z)&&(a=Y(o.x,o.y,r,c.roomSize/2));const h=Y(o.x,o.y,r,.3),u=h.x-(h.x-a.x)/2,d=h.y-(h.y-a.y)/2,g=new w.Group,f=[];f.push(...Object.values(this.getRoomEdgePoint(o.x,o.y,r,c.roomSize/2))),f.push(a.x,a.y);const l=new w.Line({points:f,stroke:e,strokeWidth:c.lineWidth,dashEnabled:!0,dash:[.1,.05],perfectDrawEnabled:!1});g.add(l);const p=new w.Arrow({points:[f[0],f[1],u,d],pointerLength:.5,pointerWidth:.35,strokeWidth:c.lineWidth*1.4,stroke:e,fill:H.ONE_WAY_FILL,dashEnabled:!0,dash:[.1,.05]});return g.add(p),g}renderAreaExit(t,e,s){const i=this.getRoomEdgePoint(t.x,t.y,e,c.roomSize/2),o=Y(t.x,t.y,e,c.roomSize*1.5),n=s??this.mapReader.getColorValue(t.env);return new w.Arrow({points:[i.x,i.y,o.x,o.y],pointerLength:.3,pointerWidth:.3,strokeWidth:c.lineWidth*1.4,stroke:n,fill:n})}renderSpecialExits(t,e){return Object.entries(t.customLines).map(([s,i])=>{const o=[t.x,t.y];i.points.reduce((u,d)=>(u.push(d.x,-d.y),u),o);const n=i.attributes.arrow?w.Arrow:w.Line,r=e??`rgb(${i.attributes.color.r}, ${i.attributes.color.g}, ${i.attributes.color.b})`,a=new n({points:o,strokeWidth:c.lineWidth,stroke:r,fill:e??`rgb(${i.attributes.color.r}, ${i.attributes.color.g} , ${i.attributes.color.b})`,pointerLength:.3,pointerWidth:.2,perfectDrawEnabled:!1});let h=i.attributes.style;return h==="dot line"?(a.dash([.05,.05]),a.dashOffset(.1)):h==="dash line"?a.dash([.4,.2]):h==="solid line"||h!==void 0&&console.log("Brak opisu stylu: "+h),a})}renderStubs(t,e=c.lineColor){return t.stubs.map(s=>{const i=Rt[s],o=this.getRoomEdgePoint(t.x,t.y,i,c.roomSize/2),n=Y(t.x,t.y,i,c.roomSize/2+.5),r=[o.x,o.y,n.x,n.y];return new w.Line({points:r,stroke:e,strokeWidth:c.lineWidth})})}renderInnerExits(t){return vt.map(e=>{if(t.exits[e]){const s=new w.Group,i=new w.RegularPolygon({x:t.x,y:t.y,sides:3,fill:this.mapReader.getSymbolColor(t.env,.6),stroke:this.mapReader.getSymbolColor(t.env),strokeWidth:c.lineWidth,radius:c.roomSize/5,scaleX:1.4,scaleY:.8,perfectDrawEnabled:!1});s.add(i);let o=t.doors[e];if(o!==void 0)switch(o){case 1:i.stroke(H.OPEN_DOOR);break;case 2:i.stroke(H.CLOSED_DOOR);break;default:i.stroke(H.LOCKED_DOOR)}switch(e){case"up":i.position(Y(t.x,t.y,"south",c.roomSize/4));break;case"down":i.rotation(180),i.position(Y(t.x,t.y,"north",c.roomSize/4));break;case"in":const n=i.clone();n.rotation(-90),n.position(Y(t.x,t.y,"east",c.roomSize/4)),s.add(n),i.rotation(90),i.position(Y(t.x,t.y,"west",c.roomSize/4));break;case"out":const r=i.clone();r.rotation(90),r.position(Y(t.x,t.y,"east",c.roomSize/4)),s.add(r),i.rotation(-90),i.position(Y(t.x,t.y,"west",c.roomSize/4));break}return s}}).filter(e=>e!==void 0)}renderDoor(t,e){const s={x:t[0]+(t[2]-t[0])/2,y:t[1]+(t[3]-t[1])/2};return new w.Rect({x:s.x-c.roomSize/4,y:s.y-c.roomSize/4,width:c.roomSize/2,height:c.roomSize/2,stroke:kt(e),strokeWidth:c.lineWidth})}}class wt{constructor(t,e){this.rooms=[],this.labels=[],this.rooms=t,this.bounds=this.createBounds(),this.labels=e}getRooms(){return this.rooms}getLabels(){return this.labels}getBounds(){return this.bounds}createBounds(){return this.rooms.reduce((t,e)=>({minX:Math.min(t.minX,e.x),maxX:Math.max(t.maxX,e.x),minY:Math.min(t.minY,e.y),maxY:Math.max(t.maxY,e.y)}),{minX:Number.POSITIVE_INFINITY,maxX:Number.NEGATIVE_INFINITY,minY:Number.POSITIVE_INFINITY,maxY:Number.NEGATIVE_INFINITY})}}class rt{constructor(t){this.planes={},this.exits=new Map,this.version=0,this.area=t,this.planes=this.createPlanes(),this.createExits()}getAreaName(){return this.area.areaName}getAreaId(){return parseInt(this.area.areaId)}getVersion(){return this.version}markDirty(){this.version++}getPlane(t){return this.planes[t]}getPlanes(){return Object.values(this.planes)}getRooms(){return this.area.rooms}getLinkExits(t){return Array.from(this.exits.values()).filter(e=>e.zIndex.includes(t))}createPlanes(){const t=this.area.rooms.reduce((e,s)=>(e[s.z]||(e[s.z]=[]),e[s.z].push(s),e),{});return Object.entries(t).reduce((e,[s,i])=>(e[+s]=new wt(i,this.area.labels.filter(o=>o.Z===+s)),e),{})}createExits(){this.area.rooms.forEach(t=>{Object.entries(t.specialExits).forEach(([e,s])=>this.createHalfExit(t.id,s,t.z,e)),Object.entries(t.exits).forEach(([e,s])=>this.createHalfExit(t.id,s,t.z,e))})}createHalfExit(t,e,s,i){if(t===e)return;const o=Math.min(t,e),n=Math.max(t,e),r=`${o}-${n}`;let a=this.exits.get(r);a||(a={a:o,b:n,zIndex:[s]}),o==t?a.aDir=i:a.bDir=i,a.zIndex.push(s),this.exits.set(r,a)}}class ct extends wt{constructor(t,e){super(t.getRooms(),t.getLabels()),this.basePlane=t,this.visitedRooms=e}getRooms(){return this.basePlane.getRooms().filter(t=>this.visitedRooms.has(t.id))}getLabels(){return this.basePlane.getLabels()}getBounds(){const t=this.getRooms();return t.length?t.reduce((e,s)=>({minX:Math.min(e.minX,s.x),maxX:Math.max(e.maxX,s.x),minY:Math.min(e.minY,s.y),maxY:Math.max(e.maxY,s.y)}),{minX:Number.POSITIVE_INFINITY,maxX:Number.NEGATIVE_INFINITY,minY:Number.POSITIVE_INFINITY,maxY:Number.NEGATIVE_INFINITY}):this.basePlane.getBounds()}}class J extends rt{constructor(t,e){super(t),this.planeCache=new WeakMap,this.visitedRooms=e instanceof Set?e:new Set(e??[]),this.areaRoomIds=new Set(t.rooms.map(s=>s.id))}getPlane(t){const e=super.getPlane(t);if(!e)return e;let s=this.planeCache.get(e);return s||(s=new ct(e,this.visitedRooms),this.planeCache.set(e,s)),s}getPlanes(){return super.getPlanes().map(t=>{let e=this.planeCache.get(t);return e||(e=new ct(t,this.visitedRooms),this.planeCache.set(t,e)),e})}getLinkExits(t){return super.getLinkExits(t).filter(e=>this.visitedRooms.has(e.a)||this.visitedRooms.has(e.b))}getVisitedRoomCount(){return super.getRooms().reduce((t,e)=>t+(this.visitedRooms.has(e.id)?1:0),0)}getTotalRoomCount(){return this.areaRoomIds.size}hasVisitedRoom(t){return this.areaRoomIds.has(t)&&this.visitedRooms.has(t)}getVisitedRoomIds(){return super.getRooms().filter(t=>this.visitedRooms.has(t.id)).map(t=>t.id)}addVisitedRoom(t){const e=this.visitedRooms.has(t);this.visitedRooms.add(t);const s=!e&&this.areaRoomIds.has(t);return s&&this.markDirty(),s}addVisitedRooms(t){let e=0;for(const s of t){const i=this.visitedRooms.has(s);this.visitedRooms.add(s),!i&&this.areaRoomIds.has(s)&&e++}return e>0&&this.markDirty(),e}}const _=["up","down","in","out"];class Ct{constructor(t,e){this.paths=[],this.mapReader=t,this.overlayLayer=e}getRoomEdgePoint(t,e,s,i){return c.roomShape==="circle"?bt(t,e,s,i):Y(t,e,s,i)}findConnection(t,e){for(const[s,i]of Object.entries(t.exits))if(i===e.id){const o=s;if(_.includes(o)){const a=Z[o],h=t.customLines[a]?a:t.customLines[o]?o:void 0;return{type:"inner",fromDir:o,customLineKey:h,fromRoom:t,toRoom:e}}const n=Z[o];if(t.customLines[n])return{type:"special",fromDir:o,customLineKey:n,fromRoom:t,toRoom:e};if(t.customLines[o])return{type:"special",fromDir:o,customLineKey:o,fromRoom:t,toRoom:e};const r=this.findExitDirection(e,t.id);return{type:"regular",fromDir:o,toDir:r,fromRoom:t,toRoom:e}}for(const[s,i]of Object.entries(t.specialExits))if(i===e.id)return t.customLines[s]?{type:"special",customLineKey:s,fromRoom:t,toRoom:e}:{type:"inner",fromRoom:t,toRoom:e};for(const[s,i]of Object.entries(e.exits))if(i===t.id){const o=s;if(_.includes(o)){const r=Z[o],a=e.customLines[r]?r:e.customLines[o]?o:void 0;return{type:"inner",toDir:o,customLineKey:a,fromRoom:t,toRoom:e}}const n=Z[o];return e.customLines[n]?{type:"special",toDir:o,customLineKey:n,fromRoom:t,toRoom:e}:e.customLines[o]?{type:"special",toDir:o,customLineKey:o,fromRoom:t,toRoom:e}:{type:"regular",toDir:o,fromRoom:t,toRoom:e}}for(const[s,i]of Object.entries(e.specialExits))if(i===t.id)return e.customLines[s]?{type:"special",customLineKey:s,fromRoom:t,toRoom:e}:{type:"inner",fromRoom:t,toRoom:e};return{type:"none",fromRoom:t,toRoom:e}}findExitDirection(t,e){for(const[s,i]of Object.entries(t.exits))if(i===e)return s}createStrokedLine(t,e){const s=new w.Group;return s.opacity(.8),s.add(new w.Line({points:t,stroke:"black",strokeWidth:c.lineWidth*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;
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const b=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"},tt={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}},rt=["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 ht(v){return v?Object.prototype.hasOwnProperty.call(tt,v):!1}function X(v,t,e,i=1){if(!ht(e))return{x:v,y:t};const s=tt[e];return{x:v+s.x*i,y:t+s.y*i}}function bt(v,t,e,i=1,s=0){if(!ht(e))return{x:v,y:t};const o=tt[e];if(!(o.x!==0&&o.y!==0)||s<=0)return X(v,t,e,i);const r=i-s+s/Math.SQRT2;return{x:v+o.x*r,y:t+o.y*r}}function wt(v,t,e,i=1){if(!ht(e))return{x:v,y:t};const s=tt[e],o=Math.atan2(s.y,s.x);return{x:v+Math.cos(o)*i,y:t+Math.sin(o)*i}}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)"},vt={1:"north",2:"northeast",3:"northwest",4:"east",5:"west",6:"south",7:"southeast",8:"southwest",9:"up",10:"down",11:"in",12:"out"},kt=["up","down","in","out"];function Et(v){switch(v){case 1:return H.OPEN_DOOR;case 2:return H.CLOSED_DOOR;default:return H.LOCKED_DOOR}}class St{constructor(t,e){this.mapReader=t,this.mapRenderer=e}getRoomEdgePoint(t,e,i,s){return h.roomShape==="circle"?wt(t,e,i,s):h.roomShape==="roundedRectangle"?bt(t,e,i,s,h.roomSize*.2):X(t,e,i,s)}render(t,e){return this.renderWithColor(t,h.lineColor,e)}renderWithColor(t,e,i){const s=t.aDir&&K.includes(t.aDir),o=t.bDir&&K.includes(t.bDir);if(s&&o)return this.renderTwoWayExit(t,e,i);if(s||o){const n=s?"a":"b";return this.renderOneWayExit(t,e,n)}}renderTwoWayExit(t,e,i){const s=this.mapReader.getRoom(t.a),o=this.mapReader.getRoom(t.b);if(!s||!o||!t.aDir||!t.bDir||s.customLines[Z[t.aDir]]&&o.customLines[Z[t.bDir]]||s.z!==o.z&&(i!==o.z&&s.customLines[Z[t.aDir]]||i!==s.z&&o.customLines[Z[t.bDir]]))return;const n=new b.Group,r=[];if(r.push(...Object.values(this.getRoomEdgePoint(s.x,s.y,t.aDir,h.roomSize/2))),r.push(...Object.values(this.getRoomEdgePoint(o.x,o.y,t.bDir,h.roomSize/2))),s.doors[Z[t.aDir]]||o.doors[Z[t.bDir]]){const c=this.renderDoor(r,s.doors[Z[t.aDir]]??o.doors[Z[t.bDir]]);n.add(c)}const a=new b.Line({points:r,stroke:e,strokeWidth:h.lineWidth,perfectDrawEnabled:!1});return n.add(a),n}renderOneWayExit(t,e,i){const s=i==="a"||!i&&t.aDir,o=s?this.mapReader.getRoom(t.a):this.mapReader.getRoom(t.b),n=s?this.mapReader.getRoom(t.b):this.mapReader.getRoom(t.a),r=s?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=X(o.x,o.y,r,h.roomSize/2));const c=X(o.x,o.y,r,.3),u=c.x-(c.x-a.x)/2,d=c.y-(c.y-a.y)/2,g=new b.Group,f=[];f.push(...Object.values(this.getRoomEdgePoint(o.x,o.y,r,h.roomSize/2))),f.push(a.x,a.y);const l=new b.Line({points:f,stroke:e,strokeWidth:h.lineWidth,dashEnabled:!0,dash:[.1,.05],perfectDrawEnabled:!1});g.add(l);const p=new b.Arrow({points:[f[0],f[1],u,d],pointerLength:.5,pointerWidth:.35,strokeWidth:h.lineWidth*1.4,stroke:e,fill:H.ONE_WAY_FILL,dashEnabled:!0,dash:[.1,.05]});return g.add(p),g}renderAreaExit(t,e,i){const s=this.getRoomEdgePoint(t.x,t.y,e,h.roomSize/2),o=X(t.x,t.y,e,h.roomSize*1.5),n=i??this.mapReader.getColorValue(t.env);return new b.Arrow({points:[s.x,s.y,o.x,o.y],pointerLength:.3,pointerWidth:.3,strokeWidth:h.lineWidth*1.4,stroke:n,fill:n})}renderSpecialExits(t,e){return Object.entries(t.customLines).map(([i,s])=>{const o=[t.x,t.y];s.points.reduce((u,d)=>(u.push(d.x,-d.y),u),o);const n=s.attributes.arrow?b.Arrow:b.Line,r=e??`rgb(${s.attributes.color.r}, ${s.attributes.color.g}, ${s.attributes.color.b})`,a=new n({points:o,strokeWidth:h.lineWidth,stroke:r,fill:e??`rgb(${s.attributes.color.r}, ${s.attributes.color.g} , ${s.attributes.color.b})`,pointerLength:.3,pointerWidth:.2,perfectDrawEnabled:!1});let c=s.attributes.style;return c==="dot line"?(a.dash([.05,.05]),a.dashOffset(.1)):c==="dash line"?a.dash([.4,.2]):c==="solid line"||c!==void 0&&console.log("Brak opisu stylu: "+c),a})}renderStubs(t,e=h.lineColor){return t.stubs.map(i=>{const s=vt[i],o=this.getRoomEdgePoint(t.x,t.y,s,h.roomSize/2),n=X(t.x,t.y,s,h.roomSize/2+.5),r=[o.x,o.y,n.x,n.y];return new b.Line({points:r,stroke:e,strokeWidth:h.lineWidth})})}renderInnerExits(t){return kt.map(e=>{if(t.exits[e]){const i=new b.Group,s=new b.RegularPolygon({x:t.x,y:t.y,sides:3,fill:this.mapReader.getSymbolColor(t.env,.6),stroke:this.mapReader.getSymbolColor(t.env),strokeWidth:h.lineWidth,radius:h.roomSize/5,scaleX:1.4,scaleY:.8,perfectDrawEnabled:!1});i.add(s);let o=t.doors[e];if(o!==void 0)switch(o){case 1:s.stroke(H.OPEN_DOOR);break;case 2:s.stroke(H.CLOSED_DOOR);break;default:s.stroke(H.LOCKED_DOOR)}switch(e){case"up":s.position(X(t.x,t.y,"south",h.roomSize/4));break;case"down":s.rotation(180),s.position(X(t.x,t.y,"north",h.roomSize/4));break;case"in":const n=s.clone();n.rotation(-90),n.position(X(t.x,t.y,"east",h.roomSize/4)),i.add(n),s.rotation(90),s.position(X(t.x,t.y,"west",h.roomSize/4));break;case"out":const r=s.clone();r.rotation(90),r.position(X(t.x,t.y,"east",h.roomSize/4)),i.add(r),s.rotation(-90),s.position(X(t.x,t.y,"west",h.roomSize/4));break}return i}}).filter(e=>e!==void 0)}renderDoor(t,e){const i={x:t[0]+(t[2]-t[0])/2,y:t[1]+(t[3]-t[1])/2};return new b.Rect({x:i.x-h.roomSize/4,y:i.y-h.roomSize/4,width:h.roomSize/2,height:h.roomSize/2,stroke:Et(e),strokeWidth:h.lineWidth})}}class Rt{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 at{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,i)=>(e[i.z]||(e[i.z]=[]),e[i.z].push(i),e),{});return Object.entries(t).reduce((e,[i,s])=>(e[+i]=new Rt(s,this.area.labels.filter(o=>o.Z===+i)),e),{})}createExits(){this.area.rooms.forEach(t=>{Object.entries(t.specialExits).forEach(([e,i])=>this.createHalfExit(t.id,i,t.z,e)),Object.entries(t.exits).forEach(([e,i])=>this.createHalfExit(t.id,i,t.z,e))})}createHalfExit(t,e,i,s){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:[i]}),o==t?a.aDir=s:a.bDir=s,a.zIndex.push(i),this.exits.set(r,a)}}class dt extends Rt{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,i)=>({minX:Math.min(e.minX,i.x),maxX:Math.max(e.maxX,i.x),minY:Math.min(e.minY,i.y),maxY:Math.max(e.maxY,i.y)}),{minX:Number.POSITIVE_INFINITY,maxX:Number.NEGATIVE_INFINITY,minY:Number.POSITIVE_INFINITY,maxY:Number.NEGATIVE_INFINITY}):this.basePlane.getBounds()}}class J extends at{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(i=>i.id))}getPlane(t){const e=super.getPlane(t);if(!e)return e;let i=this.planeCache.get(e);return i||(i=new dt(e,this.visitedRooms),this.planeCache.set(e,i)),i}getPlanes(){return super.getPlanes().map(t=>{let e=this.planeCache.get(t);return e||(e=new dt(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 i=!e&&this.areaRoomIds.has(t);return i&&this.markDirty(),i}addVisitedRooms(t){let e=0;for(const i of t){const s=this.visitedRooms.has(i);this.visitedRooms.add(i),!s&&this.areaRoomIds.has(i)&&e++}return e>0&&this.markDirty(),e}}const Q=["up","down","in","out"];class Ct{constructor(t,e){this.paths=[],this.mapReader=t,this.overlayLayer=e}getRoomEdgePoint(t,e,i,s){return h.roomShape==="circle"?wt(t,e,i,s):h.roomShape==="roundedRectangle"?bt(t,e,i,s,h.roomSize*.2):X(t,e,i,s)}findConnection(t,e){for(const[i,s]of Object.entries(t.exits))if(s===e.id){const o=i;if(Q.includes(o)){const a=Z[o],c=t.customLines[a]?a:t.customLines[o]?o:void 0;return{type:"inner",fromDir:o,customLineKey:c,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[i,s]of Object.entries(t.specialExits))if(s===e.id)return t.customLines[i]?{type:"special",customLineKey:i,fromRoom:t,toRoom:e}:{type:"inner",fromRoom:t,toRoom:e};for(const[i,s]of Object.entries(e.exits))if(s===t.id){const o=i;if(Q.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[i,s]of Object.entries(e.specialExits))if(s===t.id)return e.customLines[i]?{type:"special",customLineKey:i,fromRoom:t,toRoom:e}:{type:"inner",fromRoom:t,toRoom:e};return{type:"none",fromRoom:t,toRoom:e}}findExitDirection(t,e){for(const[i,s]of Object.entries(t.exits))if(s===e)return i}createStrokedLine(t,e){const i=new b.Group;return i.opacity(.8),i.add(new b.Line({points:t,stroke:"black",strokeWidth:h.lineWidth*8,lineCap:"round",lineJoin:"round"})),i.add(new b.Line({points:t,stroke:e,strokeWidth:h.lineWidth*4,lineCap:"round",lineJoin:"round"})),i}renderInnerExitMarker(t,e,i){const s=new b.Group;s.opacity(.8);const o=new b.RegularPolygon({x:t.x,y:t.y,sides:3,fill:i,stroke:"black",strokeWidth:h.lineWidth*2,radius:h.roomSize/5,scaleX:1.4,scaleY:.8});switch(e){case"up":o.position(X(t.x,t.y,"south",h.roomSize/4));break;case"down":o.rotation(180),o.position(X(t.x,t.y,"north",h.roomSize/4));break;case"in":const n=o.clone();n.rotation(-90),n.position(X(t.x,t.y,"east",h.roomSize/4)),s.add(n),o.rotation(90),o.position(X(t.x,t.y,"west",h.roomSize/4));break;case"out":const r=o.clone();r.rotation(90),r.position(X(t.x,t.y,"east",h.roomSize/4)),s.add(r),o.rotation(-90),o.position(X(t.x,t.y,"west",h.roomSize/4));break}return s.add(o),s}renderPath(t,e,i,s="#66E64D"){if(e===void 0||i===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,s);this.overlayLayer.add(a),this.paths.push(a)}n=[]};for(let a=0;a<o.length-1;a++){const c=o[a],u=o[a+1],d=this.isRoomVisible(c,e,i),g=this.isRoomVisible(u,e,i);if(!d&&!g){r();continue}const f=this.findConnection(c,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,s);break;case"none":n.length===0&&n.push(c.x,c.y),n.push(u.x,u.y);break}else{const l=d?c:u,p=d?u:c,m=this.getExitToRoom(l,p);if(m){if(Q.includes(m.direction)){r();const y=this.renderInnerExitMarker(l,m.direction,s);this.overlayLayer.add(y),this.paths.push(y)}else if(K.includes(m.direction)){n.length===0&&n.push(l.x,l.y);const y=this.getRoomEdgePoint(l.x,l.y,m.direction,h.roomSize/2),x=X(l.x,l.y,m.direction,h.roomSize);n.push(y.x,y.y,x.x,x.y),r()}}else{const y=this.getDirectionTowards(l,p);if(y){n.length===0&&n.push(l.x,l.y);const x=this.getRoomEdgePoint(l.x,l.y,y,h.roomSize/2),I=X(l.x,l.y,y,h.roomSize);n.push(x.x,x.y,I.x,I.y),r()}}}}return r(),this.paths[0]}addRegularConnectionPoints(t,e){const{fromRoom:i,toRoom:s,fromDir:o,toDir:n}=t;if(e.length===0&&e.push(i.x,i.y),o&&K.includes(o)){const r=this.getRoomEdgePoint(i.x,i.y,o,h.roomSize/2);e.push(r.x,r.y)}if(n&&K.includes(n)){const r=this.getRoomEdgePoint(s.x,s.y,n,h.roomSize/2);e.push(r.x,r.y)}e.push(s.x,s.y)}addSpecialConnectionPoints(t,e){const{fromRoom:i,toRoom:s,customLineKey:o}=t;let n=i,r;o&&(r=i.customLines[o],r||(r=s.customLines[o],n=s)),e.length===0&&e.push(n.x,n.y),r&&r.points.forEach(a=>{e.push(a.x,-a.y)}),e.push(s.x,s.y)}renderInnerConnection(t,e){const{fromRoom:i,toRoom:s,fromDir:o,toDir:n,customLineKey:r}=t;if(r){let a=i,c=i.customLines[r];if(c||(c=s.customLines[r],a=s),c){const u=[a.x,a.y];c.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&&Q.includes(o)){const a=this.renderInnerExitMarker(i,o,e);this.overlayLayer.add(a),this.paths.push(a)}if(n&&Q.includes(n)){const a=this.renderInnerExitMarker(s,n,e);this.overlayLayer.add(a),this.paths.push(a)}}clearPaths(){this.paths.forEach(t=>{t.destroy()}),this.paths=[]}isRoomVisible(t,e,i){return t?t.area===e&&t.z===i:!1}getExitToRoom(t,e){for(const[i,s]of Object.entries(t.exits))if(s===e.id)return{direction:i};for(const[i,s]of Object.entries(t.specialExits))if(s===e.id)return}getDirectionTowards(t,e){for(const i of rt)if(t.exits[i]===e.id)return i;for(const i of rt)if(e.exits[i]===t.id)return xt[i]}}const It=.6,q=75,Mt=.025,Dt="rgb(225, 255, 225)",_="rgb(120, 72, 0)";function U(v,t){const e=parseInt(v.slice(1,3),16),i=parseInt(v.slice(3,5),16),s=parseInt(v.slice(5,7),16);return`rgba(${e}, ${i}, ${s}, ${t})`}const V=class V{};V.roomSize=It,V.lineWidth=Mt,V.lineColor=Dt,V.instantMapMove=!1,V.highlightCurrentRoom=!0,V.cullingEnabled=!0,V.cullingMode="indexed",V.cullingBounds=null,V.labelRenderMode="image",V.roomShape="rectangle",V.playerMarker={strokeColor:"#00e5b2",strokeAlpha:1,fillColor:"#00e5b2",fillAlpha:0,strokeWidth:.1,sizeFactor:1.7,dash:[.05,.05],dashEnabled:!0},V.gridEnabled=!1,V.gridSize=1,V.gridColor="rgba(255, 255, 255, 0.07)",V.gridLineWidth=.02;let h=V;class Lt{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 b.Stage({container:t,width:t.clientWidth,height:t.clientHeight,draggable:!0}),window.addEventListener("resize",()=>{this.onResize(t)}),t.addEventListener("resize",()=>{this.onResize(t)}),this.gridLayer=new b.Layer({listening:!1}),this.stage.add(this.gridLayer),this.linkLayer=new b.Layer({listening:!1}),this.stage.add(this.linkLayer),this.roomLayer=new b.Layer,this.stage.add(this.roomLayer),this.positionLayer=new b.Layer({listening:!1}),this.stage.add(this.positionLayer),this.overlayLayer=new b.Layer({listening:!1}),this.stage.add(this.overlayLayer),this.mapReader=e,this.exitRenderer=new St(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){b.hitOnDragEnabled=!0;let e,i=!1,s=!1;this.stage.on("touchstart",o=>{const n=o.evt.touches;n&&n.length>1?(s=!0,this.stage.isDragging()&&(this.stage.stopDrag(),i=!0),this.stage.draggable(!1)):(s=!1,this.stage.draggable(!0))}),this.stage.on("touchend touchcancel",o=>{e=void 0;const n=o.evt.touches;(!n||n.length<=1)&&(s=!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 c=o.evt.deltaY>0?-1:1;o.evt.ctrlKey&&(c=-c);const u=c>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||s&&(s=!1,this.stage.draggable(!0)),r&&!a&&i&&!this.stage.isDragging()&&(this.stage.startDrag(),i=!1),!r||!a){e=void 0;return}o.evt.preventDefault(),this.stage.isDragging()&&(this.stage.stopDrag(),i=!0),s||(s=!0,this.stage.draggable(!1));const c=this.stage.container().getBoundingClientRect(),u={x:r.clientX-c.left,y:r.clientY-c.top},d={x:a.clientX-c.left,y:a.clientY-c.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},y={x:(m.x-l)/f,y:(m.y-p)/f},x=this.currentZoom*(g/e),I=this.setZoom(x),A=this.stage.scaleX(),P={x:m.x-y.x*A,y:m.y-y.y*A};this.stage.position(P),this.stage.batchDraw(),this.scheduleRoomCulling(),e=g,I&&this.emitZoomChangeEvent()})}drawArea(t,e){const i=this.mapReader.getArea(t);if(!i)return;const s=i.getPlane(e);s&&(this.currentArea=t,this.currentAreaInstance=i,this.currentZIndex=e,this.currentAreaVersion=i.getVersion(),this.clearCurrentRoomOverlay(),this.gridLayer.destroyChildren(),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.renderGrid(),this.renderLabels(s.getLabels()),this.renderExits(i.getLinkExits(e)),this.renderRooms(s.getRooms()??[]),this.refreshHighlights(),this.stage.batchDraw(),this.scheduleRoomCulling())}computeSpatialBucketSize(){return Math.max(h.roomSize*10,5)}getBucketKey(t,e){return`${t},${e}`}forEachBucket(t,e,i,s,o){const n=this.spatialBucketSize,r=Math.min(t,i),a=Math.max(t,i),c=Math.min(e,s),u=Math.max(e,s),d=Math.floor(r/n),g=Math.floor(a/n),f=Math.floor(c/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=h.roomSize/2,i=t.room.x-e,s=t.room.x+e,o=t.room.y-e,n=t.room.y+e;this.forEachBucket(i,o,s,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,i=e.x,s=e.x+e.width,o=e.y,n=e.y+e.height;this.forEachBucket(i,o,s,n,r=>{let a=this.exitSpatialIndex.get(r);a||(a=new Set,this.exitSpatialIndex.set(r,a)),a.add(t)})}collectRoomCandidates(t,e,i,s){const o=new Set;return this.forEachBucket(t,e,i,s,n=>{this.roomSpatialIndex.get(n)?.forEach(a=>o.add(a))}),o}collectStandaloneExitCandidates(t,e,i,s){const o=new Set;return this.forEachBucket(t,e,i,s,n=>{this.exitSpatialIndex.get(n)?.forEach(a=>o.add(a))}),o}refreshStandaloneExitBoundsIfNeeded(){this.standaloneExitBoundsRoomSize!==h.roomSize&&(this.exitSpatialIndex.clear(),this.standaloneExitNodes.forEach(t=>{t.bounds=t.node.getClientRect({relativeTo:this.linkLayer}),this.addStandaloneExitToSpatialIndex(t)}),this.standaloneExitBoundsRoomSize=h.roomSize)}emitRoomContextEvent(t,e,i){const s=this.stage.container(),o=s.getBoundingClientRect(),n={roomId:t,position:{x:e-o.left,y:i-o.top}},r=new CustomEvent("roomcontextmenu",{detail:n});s.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(),i=this.stage.width(),s=this.stage.height(),o=i/2,n=s/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 c={x:o-r.x*a,y:n-r.y*a};return this.stage.position(c),this.stage.batchDraw(),this.scheduleRoomCulling(),!0}getZoom(){return this.currentZoom}setCullingMode(t){h.cullingMode=t,h.cullingEnabled=t!=="none",this.scheduleRoomCulling()}getCullingMode(){return h.cullingMode}getCurrentArea(){return this.currentArea?this.mapReader.getArea(this.currentArea):void 0}refreshCurrentRoomOverlay(){if(this.currentRoomId!==void 0){const t=this.mapReader.getRoom(this.currentRoomId);t&&this.updateCurrentRoomOverlay(t)}}refresh(){this.currentRoomId!==void 0&&this.currentArea!==void 0&&this.currentZIndex!==void 0&&(this.drawArea(this.currentArea,this.currentZIndex),this.setPosition(this.currentRoomId))}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 i=U(h.playerMarker.strokeColor,h.playerMarker.strokeAlpha),s=U(h.playerMarker.fillColor,h.playerMarker.fillAlpha),o=h.roomSize/2*h.playerMarker.sizeFactor;this.positionRender?(this.positionRender.position({x:e.x,y:e.y}),this.positionRender.radius(o),this.positionRender.stroke(i),this.positionRender.fill(s),this.positionRender.strokeWidth(h.playerMarker.strokeWidth),this.positionRender.dash(h.playerMarker.dash??[]),this.positionRender.dashEnabled(h.playerMarker.dashEnabled),this.positionRender.show()):(this.positionRender=new b.Circle({x:e.x,y:e.y,radius:o,stroke:i,fill:s,strokeWidth:h.playerMarker.strokeWidth,dash:h.playerMarker.dash,dashEnabled:h.playerMarker.dashEnabled}),this.positionLayer.add(this.positionRender)),this.positionLayer.batchDraw()}setPosition(t,e=!0){const i=this.mapReader.getRoom(t);if(!i)return;const s=this.mapReader.getArea(i.area),o=s?.getVersion();let n=this.currentArea!==i.area||this.currentZIndex!==i.z;(this.currentArea!==i.area||this.currentZIndex!==i.z||o!==void 0&&this.currentAreaVersion!==o||s!==void 0&&this.currentAreaInstance!==s)&&this.drawArea(i.area,i.z),e?this.centerOnRoom(i,n):this.currentRoomId=t,this.updateCurrentRoomOverlay(i);const r=U(h.playerMarker.strokeColor,h.playerMarker.strokeAlpha),a=U(h.playerMarker.fillColor,h.playerMarker.fillAlpha),c=h.roomSize/2*h.playerMarker.sizeFactor;this.positionRender?(this.positionRender.radius(c),this.positionRender.stroke(r),this.positionRender.fill(a),this.positionRender.strokeWidth(h.playerMarker.strokeWidth),this.positionRender.dash(h.playerMarker.dash??[]),this.positionRender.dashEnabled(h.playerMarker.dashEnabled)):(this.positionRender=new b.Circle({x:i.x,y:i.y,radius:c,stroke:r,fill:a,strokeWidth:h.playerMarker.strokeWidth,dash:h.playerMarker.dash,dashEnabled:h.playerMarker.dashEnabled}),this.positionLayer.add(this.positionRender))}centerOn(t){const e=this.mapReader.getRoom(t);if(!e)return;const i=this.mapReader.getArea(e.area),s=i?.getVersion();let o=this.currentArea!==e.area||this.currentZIndex!==e.z;(this.currentArea!==e.area||this.currentZIndex!==e.z||s!==void 0&&this.currentAreaVersion!==s||i!==void 0&&this.currentAreaInstance!==i)&&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 i=this.mapReader.getRoom(t);if(!i)return;const s=this.highlights.get(t);s?.shape&&(s.shape.destroy(),delete s.shape);const o={color:e,area:i.area,z:i.z};if(this.highlights.set(t,o),i.area===this.currentArea&&i.z===this.currentZIndex){const n=this.createHighlightShape(i,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 i=this.mapReader.getRoom(e);if(!i)return;const s=this.createHighlightShape(i,t.color);this.overlayLayer.add(s),t.shape=s}),this.overlayLayer.batchDraw()}createHighlightShape(t,e){return h.roomShape==="circle"?new b.Circle({x:t.x,y:t.y,radius:h.roomSize/2*1.5,stroke:e,strokeWidth:.1,dash:[.05,.05],dashEnabled:!0,listening:!1}):new b.Rect({x:t.x-h.roomSize/2*1.5,y:t.y-h.roomSize/2*1.5,width:h.roomSize*1.5,height:h.roomSize*1.5,stroke:e,strokeWidth:.1,dash:[.05,.05],dashEnabled:!0,cornerRadius:h.roomShape==="roundedRectangle"?h.roomSize*1.5*.2:0,listening:!1})}centerOnRoom(t,e=!1){this.currentRoomId=t.id;const i={x:t.x,y:t.y};this.positionRender?.position(t);const o=this.stage.getAbsoluteTransform().point(i),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||h.instantMapMove?(this.stage.position({x:this.stage.x()+r,y:this.stage.y()+a}),this.scheduleRoomCulling()):(this.currentTransition=new b.Tween({node:this.stage,x:this.stage.x()+r,y:this.stage.y()+a,duration:.2,easing:b.Easings.EaseInOut,onUpdate:()=>this.scheduleRoomCulling(),onFinish:()=>this.scheduleRoomCulling()}),this.currentTransition.play())}centerOnRoomView(t,e=!1){const i={x:t.x,y:t.y},o=this.stage.getAbsoluteTransform().point(i),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||h.instantMapMove?(this.stage.position({x:this.stage.x()+r,y:this.stage.y()+a}),this.scheduleRoomCulling()):(this.currentTransition=new b.Tween({node:this.stage,x:this.stage.x()+r,y:this.stage.y()+a,duration:.2,easing:b.Easings.EaseInOut,onUpdate:()=>this.scheduleRoomCulling(),onFinish:()=>this.scheduleRoomCulling()}),this.currentTransition.play())}renderRooms(t){t.forEach(e=>{const i=new b.Group({x:e.x-h.roomSize/2,y:e.y-h.roomSize/2}),s=this.mapReader.getColorValue(e.env),o=h.lineColor,r=h.roomShape==="circle"?new b.Circle({x:h.roomSize/2,y:h.roomSize/2,radius:h.roomSize/2,fill:s,strokeWidth:h.lineWidth,stroke:o,perfectDrawEnabled:!1}):new b.Rect({x:0,y:0,width:h.roomSize,height:h.roomSize,fill:s,strokeWidth:h.lineWidth,stroke:o,cornerRadius:h.roomShape==="roundedRectangle"?h.roomSize*.2:0,perfectDrawEnabled:!1}),a=(m,y)=>this.emitRoomContextEvent(e.id,m,y);i.on("mouseenter",()=>{this.stage.container().style.cursor="pointer"}),i.on("mouseleave",()=>{this.stage.container().style.cursor="auto"}),i.on("contextmenu",m=>{m.evt.preventDefault();const y=m.evt;a(y.clientX,y.clientY)});let c,u,d;const g=()=>{d!==void 0&&(this.stage.draggable(d),d=void 0)},f=()=>{c!==void 0&&(window.clearTimeout(c),c=void 0),u=void 0,g()};i.on("touchstart",m=>{if(f(),m.evt.touches&&m.evt.touches.length>1)return;const y=m.evt.touches?.[0];y&&(u={clientX:y.clientX,clientY:y.clientY},d=this.stage.draggable(),this.stage.draggable(!1),c=window.setTimeout(()=>{u&&a(u.clientX,u.clientY),f()},500))}),i.on("touchend",f),i.on("touchmove",m=>{if(!u)return;const y=m.evt.touches?.[0];if(!y){f();return}const x=y.clientX-u.clientX,I=y.clientY-u.clientY,A=x*x+I*I,P=10;if(A>P*P){const F=d;f(),F&&this.stage.startDrag()}}),i.on("touchcancel",f),i.add(r),this.renderSymbol(e,i),this.roomLayer.add(i);const l=[];this.exitRenderer.renderSpecialExits(e).forEach(m=>{this.linkLayer.add(m);const y=m.getClientRect({relativeTo:this.linkLayer}),x={node:m,bounds:y};this.standaloneExitNodes.push(x),this.addStandaloneExitToSpatialIndex(x)}),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:i,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(),i=h.roomSize/2,s=h.cullingBounds,o=s?s.x:0,n=s?s.x+s.width:this.stage.width(),r=s?s.y:0,a=s?s.y+s.height:this.stage.height(),c=Math.min(o,n),u=Math.max(o,n),d=Math.min(r,a),g=Math.max(r,a),f=(c-e.x)/t,l=(u-e.x)/t,p=(d-e.y)/t,m=(g-e.y)/t;let y=!1,x=!1;const I=h.cullingEnabled?h.cullingMode??"indexed":"none",A=f-i,P=l+i,F=p-i,w=m+i;if(this.refreshStandaloneExitBoundsIfNeeded(),I==="none"){this.roomNodes.forEach(k=>{k.group.visible()||(k.group.visible(!0),y=!0),k.linkNodes.forEach(C=>{C.visible()||(C.visible(!0),x=!0)})}),this.standaloneExitNodes.forEach(k=>{const{node:C}=k;C.visible()||(x=!0,C.visible(!0))}),y&&this.roomLayer.batchDraw(),x&&this.linkLayer.batchDraw(),this.visibleRooms=new Set(this.roomNodes.values()),this.visibleStandaloneExitNodes=new Set(this.standaloneExitNodes);return}if(I==="basic"){const k=new Set;this.roomNodes.forEach(M=>{const Y=M.room.x-i,O=M.room.x+i,B=M.room.y-i,T=M.room.y+i,W=O>=f&&Y<=l&&T>=p&&B<=m;M.group.visible()!==W&&(M.group.visible(W),y=!0),M.linkNodes.forEach(G=>{G.visible()!==W&&(G.visible(W),x=!0)}),W&&k.add(M)});const C=new Set;this.standaloneExitNodes.forEach(M=>{const{node:Y,bounds:O}=M,B=O.x,T=O.x+O.width,W=O.y,G=O.y+O.height,$=T>=f&&B<=l&&G>=p&&W<=m;Y.visible()!==$&&(Y.visible($),x=!0),$&&C.add(M)}),this.visibleRooms=k,this.visibleStandaloneExitNodes=C,y&&this.roomLayer.batchDraw(),x&&this.linkLayer.batchDraw();return}const R=this.collectRoomCandidates(A,F,P,w),S=new Set,D=new Set;R.forEach(k=>{S.add(k);const C=k.room.x-i,M=k.room.x+i,Y=k.room.y-i,O=k.room.y+i,B=M>=f&&C<=l&&O>=p&&Y<=m;k.group.visible()!==B&&(k.group.visible(B),y=!0),k.linkNodes.forEach(T=>{T.visible()!==B&&(T.visible(B),x=!0)}),B&&D.add(k)}),this.visibleRooms.forEach(k=>{S.has(k)||(k.group.visible()&&(k.group.visible(!1),y=!0),k.linkNodes.forEach(C=>{C.visible()&&(C.visible(!1),x=!0)}))}),this.visibleRooms=D;const E=this.collectStandaloneExitCandidates(A,F,P,w),L=new Set,z=new Set;E.forEach(k=>{L.add(k);const{node:C,bounds:M}=k,Y=M.x,O=M.x+M.width,B=M.y,T=M.y+M.height,W=O>=f&&Y<=l&&T>=p&&B<=m;C.visible()!==W&&(C.visible(W),x=!0),W&&z.add(k)}),this.visibleStandaloneExitNodes.forEach(k=>{const{node:C}=k;!L.has(k)&&C.visible()&&(C.visible(!1),x=!0)}),this.visibleStandaloneExitNodes=z,y&&this.roomLayer.batchDraw(),x&&this.linkLayer.batchDraw(),this.renderGrid()}renderGrid(){if(this.gridLayer.destroyChildren(),!h.gridEnabled){this.gridLayer.batchDraw();return}const t=this.stage.scaleX();if(!t)return;const e=this.stage.position(),i=this.stage.width(),s=this.stage.height(),o=(0-e.x)/t,n=(i-e.x)/t,r=(0-e.y)/t,a=(s-e.y)/t,c=h.gridSize*2,u=Math.floor((Math.min(o,n)-c)/h.gridSize)*h.gridSize,d=Math.ceil((Math.max(o,n)+c)/h.gridSize)*h.gridSize,g=Math.floor((Math.min(r,a)-c)/h.gridSize)*h.gridSize,f=Math.ceil((Math.max(r,a)+c)/h.gridSize)*h.gridSize;for(let l=u;l<=d;l+=h.gridSize)this.gridLayer.add(new b.Line({points:[l,g,l,f],stroke:h.gridColor,strokeWidth:h.gridLineWidth,listening:!1,perfectDrawEnabled:!1}));for(let l=g;l<=f;l+=h.gridSize)this.gridLayer.add(new b.Line({points:[u,l,d,l],stroke:h.gridColor,strokeWidth:h.gridLineWidth,listening:!1,perfectDrawEnabled:!1}));this.gridLayer.batchDraw()}clearCurrentRoomOverlay(){this.currentRoomOverlay.forEach(t=>t.destroy()),this.currentRoomOverlay=[],this.positionLayer.batchDraw()}updateCurrentRoomOverlay(t){if(this.clearCurrentRoomOverlay(),t.area!==this.currentArea||t.z!==this.currentZIndex){this.positionLayer.batchDraw();return}const e=new Map;e.set(t.id,t);const i=[],s=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 c=h.highlightCurrentRoom?this.exitRenderer.renderWithColor(a,_,this.currentZIndex):this.exitRenderer.render(a,this.currentZIndex);c&&i.push(c)});const o=h.highlightCurrentRoom?_:void 0;this.exitRenderer.renderSpecialExits(t,o).forEach(r=>{i.push(r)}),(h.highlightCurrentRoom?this.exitRenderer.renderStubs(t,_):this.exitRenderer.renderStubs(t)).forEach(r=>{i.push(r)}),[...Object.values(t.exits),...Object.values(t.specialExits)].forEach(r=>{const a=this.mapReader.getRoom(r),c=!s||s.hasVisitedRoom(r);a&&a.area===this.currentArea&&a.z===this.currentZIndex&&c&&e.set(r,a)}),i.forEach(r=>{this.positionLayer.add(r),this.currentRoomOverlay.push(r)}),e.forEach((r,a)=>{const c=a===t.id,u=this.createOverlayRoomGroup(r,{stroke:c&&h.highlightCurrentRoom?_:h.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 i=new b.Group({x:t.x-h.roomSize/2,y:t.y-h.roomSize/2,listening:!1}),s=this.mapReader.getColorValue(t.env),o=e.stroke,n=h.roomShape==="circle"?new b.Circle({x:h.roomSize/2,y:h.roomSize/2,radius:h.roomSize/2,fill:s,stroke:o,strokeWidth:h.lineWidth}):new b.Rect({x:0,y:0,width:h.roomSize,height:h.roomSize,fill:s,stroke:o,strokeWidth:h.lineWidth,cornerRadius:h.roomShape==="roundedRectangle"?h.roomSize*.2:0});return i.add(n),this.renderSymbol(t,i),i}renderSymbol(t,e){if(t.roomChar!==void 0){const i=h.roomSize*.75,s=new b.Text({x:0,y:0,text:t.roomChar,fontSize:i,fontStyle:"bold",fill:this.mapReader.getSymbolColor(t.env),align:"center",verticalAlign:"middle",width:h.roomSize,height:h.roomSize});e.add(s)}}renderExits(t){t.forEach(e=>{const i=this.exitRenderer.render(e,this.currentZIndex);if(!i)return;this.linkLayer.add(i);const s=i.getClientRect({relativeTo:this.linkLayer}),o={node:i,bounds:s};this.standaloneExitNodes.push(o),this.addStandaloneExitToSpatialIndex(o)}),this.standaloneExitBoundsRoomSize=h.roomSize}renderLabels(t){t.forEach(e=>{if(h.labelRenderMode==="image"){if(!e.pixMap)return;const i=new Image;i.src=`data:image/png;base64,${e.pixMap}`;const s=new b.Image({x:e.X,y:-e.Y,width:e.Width,height:e.Height,image:i,listening:!1});this.linkLayer.add(s);return}this.renderLabelAsData(e)})}renderLabelAsData(t){const e=new b.Group({listening:!1}),i=new b.Rect({x:t.X,y:-t.Y,width:t.Width,height:t.Height,listening:!1});(t.BgColor?.alpha??0)>0&&!h.transparentLabels?i.fill(this.getLabelColor(t.BgColor)):i.fillEnabled(!1),e.add(i);const s=Math.min(.75,t.Width/Math.max(t.Text.length/2,1)),o=Math.max(.1,Math.min(s,Math.max(t.Height*.9,.1))),n=new b.Text({x:t.X,y:-t.Y,width:t.Width,height:t.Height,text:t.Text,fontSize:o,fillEnabled:!0,fill:this.getLabelColor(t.FgColor),align:"center",verticalAlign:"middle",listening:!1});e.add(n),this.linkLayer.add(e)}getLabelColor(t){const e=(t?.alpha??255)/255,i=s=>Math.min(255,Math.max(0,s??0));return`rgba(${i(t?.r)}, ${i(t?.g)}, ${i(t?.b)}, ${e})`}}const lt={rgbValue:"rgb(114, 1, 0)",symbolColor:[225,225,225]};function ut(v){const t=v[0]/255,e=v[1]/255,i=v[2]/255,s=Math.max(t,e,i),o=Math.min(t,e,i);return(s+o)/2}class zt{constructor(t,e){this.rooms={},this.areas={},this.areaSources={},this.explorationEnabled=!1,this.colors={},t.forEach(i=>{i.rooms.forEach(o=>{o.y=-o.y,this.rooms[o.id]=o});const s=parseInt(i.areaId);this.areas[s]=new at(i),this.areaSources[s]=i}),this.colors=e.reduce((i,s)=>({...i,[s.envId]:{rgb:s.colors,rgbValue:`rgb(${s.colors.join(",")})`,symbolColor:ut(s.colors)>.41?[25,25,25]:[225,255,255],symbolColorValue:ut(s.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 i=parseInt(t,10);this.areas[i]=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 i=parseInt(t,10);this.areas[i]=new at(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 s=this.getRoom(t);if(s){const o=this.getExplorationArea(s.area);if(o)return o.addVisitedRoom(t)}}const e=this.ensureVisitedRooms(),i=e.has(t);return e.add(t),!i}addVisitedRooms(t){const e=this.ensureVisitedRooms();let i=0;for(const s of t){if(this.explorationEnabled){const n=this.getRoom(s);if(n){const r=this.getExplorationArea(n.area);if(r){r.addVisitedRoom(s)&&i++;continue}}}const o=e.has(s);e.add(s),o||i++}return i}hasVisitedRoom(t){return this.visitedRooms?.has(t)??!1}getColorValue(t){return this.colors[t]?.rgbValue??lt.rgbValue}getSymbolColor(t,e){const i=this.colors[t]?.symbolColor??lt.symbolColor,s=Math.min(Math.max(e??1,0),1),o=i.join(",");return s!=1?`rgba(${o}, ${s})`:`rgba(${o})`}}function Nt(v){return v&&v.__esModule&&Object.prototype.hasOwnProperty.call(v,"default")?v.default:v}var et,ft;function At(){if(ft)return et;ft=1;class v{constructor(){this.keys=new Set,this.queue=[]}sort(){this.queue.sort((e,i)=>e.priority-i.priority)}set(e,i){const s=Number(i);if(isNaN(s))throw new TypeError('"priority" must be a number');return this.keys.has(e)?this.queue.map(o=>(o.key===e&&Object.assign(o,{priority:s}),o)):(this.keys.add(e),this.queue.push({key:e,priority:s})),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(i=>i.key===e)}}return et=v,et}var it,gt;function Ot(){if(gt)return it;gt=1;function v(t,e){const i=new Map;for(const[s,o]of t)s!==e&&o instanceof Map?i.set(s,v(o,e)):s!==e&&i.set(s,o);return i}return it=v,it}var st,mt;function Pt(){if(mt)return st;mt=1;function v(e){const i=Number(e);return!(isNaN(i)||i<=0)}function t(e){const i=new Map;return Object.keys(e).forEach(o=>{const n=e[o];if(n!==null&&typeof n=="object"&&!Array.isArray(n))return i.set(o,t(n));if(!v(n))throw new Error(`Could not add node at key "${o}", make sure it's a valid node`,n);return i.set(o,Number(n))}),i}return st=t,st}var ot,pt;function Xt(){if(pt)return ot;pt=1;function v(t){if(!(t instanceof Map))throw new Error(`Invalid graph: Expected Map instead found ${typeof t}`);t.forEach((e,i)=>{if(typeof e=="object"&&e instanceof Map){v(e);return}if(typeof e!="number"||e<=0)throw new Error(`Values must be numbers greater than 0. Found value ${e} at ${i}`)})}return ot=v,ot}var nt,yt;function Yt(){if(yt)return nt;yt=1;const v=At(),t=Ot(),e=Pt(),i=Xt();class s{constructor(n){n instanceof Map?(i(n),this.graph=n):n?this.graph=e(n):this.graph=new Map}addNode(n,r){let a;return r instanceof Map?(i(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 c=new Set,u=new v,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 y=p.key;for(;d.has(y);)g.push(y),y=d.get(y);break}c.add(p.key),(this.graph.get(p.key)||new Map).forEach((y,x)=>{if(c.has(x)||l.includes(x))return null;if(!u.has(x))return d.set(x,p.key),u.set(x,p.priority+y);const I=u.get(x).priority,A=p.priority+y;return A<I?(d.set(x,p.key),u.set(x,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 nt=s,nt}var Wt=Yt();const Tt=Nt(Wt),Vt={1:"north",2:"northeast",3:"northwest",4:"east",5:"west",6:"south",7:"southeast",8:"southwest",9:"up",10:"down",11:"in",12:"out"};class Ft{constructor(t){this.cache=new Map,this.mapReader=t,this.graph=this.buildGraph()}buildGraph(){const t={};return this.mapReader.getRooms().forEach(e=>{const i={},s=new Set((e.exitLocks??[]).map(n=>Vt[n]).filter(n=>!!n)),o=new Set(e.mSpecialExitLocks??[]);Object.entries(e.exits??{}).forEach(([n,r])=>{s.has(n)||this.mapReader.getRoom(r)&&(i[r.toString()]=1)}),Object.values(e.specialExits??{}).forEach(n=>{o.has(n)||this.mapReader.getRoom(n)&&(i[n.toString()]=1)}),t[e.id.toString()]=i}),new Tt(t)}findPath(t,e){const i=`${t}->${e}`;if(this.cache.has(i))return this.cache.get(i);if(t===e){const r=this.mapReader.getRoom(t)?[t]:null;return this.cache.set(i,r),r}if(!this.mapReader.getRoom(t)||!this.mapReader.getRoom(e))return this.cache.set(i,null),null;const s=this.graph.path(t.toString(),e.toString()),o=Array.isArray(s)?s:s?.path,n=o?o.map(r=>Number(r)):null;return this.cache.set(i,n),n}}const Bt={1:"north",2:"northeast",3:"northwest",4:"east",5:"west",6:"south",7:"southeast",8:"southwest",9:"up",10:"down",11:"in",12:"out"},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 N=j;class Zt{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 b.Stage({container:t,width:t.clientWidth,height:t.clientHeight,draggable:!0}),this.backgroundLayer=new b.Layer({listening:!1}),this.stage.add(this.backgroundLayer),this.connectionLayer=new b.Layer({listening:!1}),this.stage.add(this.connectionLayer),this.areaLayer=new b.Layer,this.stage.add(this.areaLayer),this.mapReader=e,this.initScaling(),this.initResize(t)}initResize(t){new ResizeObserver(()=>{this.stage.width(t.clientWidth),this.stage.height(t.clientHeight),this.stage.batchDraw()}).observe(t)}initScaling(){this.stage.on("wheel",e=>{e.evt.preventDefault();const i=this.stage.scaleX(),s=this.stage.getPointerPosition();if(!s)return;const o={x:(s.x-this.stage.x())/i,y:(s.y-this.stage.y())/i},r=(e.evt.deltaY>0?-1:1)>0?this.currentZoom*1.1:this.currentZoom/1.1;this.setZoom(r);const a=this.stage.scaleX(),c={x:s.x-o.x*a,y:s.y-o.y*a};this.stage.position(c),this.stage.batchDraw()})}setZoom(t){this.currentZoom=Math.max(.1,Math.min(5,t)),this.stage.scale({x:this.currentZoom,y:this.currentZoom})}getZoom(){return this.currentZoom}setDomainInfo(t){this.domainInfo.clear();for(const[e,i]of Object.entries(t))this.domainInfo.set(Number(e),i)}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 i=this.domainInfo.get(t),s=this.domainInfo.get(e);return!i||!s?!1:!!(i.isIshtar&&s.isIshtar||i.isEmpire&&s.isEmpire||!i.isIshtar&&!i.isEmpire&&!s.isIshtar&&!s.isEmpire)}render(){this.analyzeConnections(),this.layoutAreas(),this.drawBackground(),this.drawConnections(),this.drawAreas(),this.centerView(),this.stage.batchDraw()}drawBackground(){if(this.backgroundLayer.destroyChildren(),!this.backgroundConfig)return;const t=new Image;t.crossOrigin="anonymous",t.onload=()=>{this.backgroundImage=new b.Image({x:this.backgroundConfig.x,y:this.backgroundConfig.y,image:t,width:this.backgroundConfig.width,height:this.backgroundConfig.height,opacity:this.backgroundConfig.opacity,listening:!1}),this.backgroundLayer.add(this.backgroundImage),this.backgroundLayer.batchDraw()},t.onerror=()=>{console.error("Failed to load background image:",this.backgroundConfig?.url)},t.src=this.backgroundConfig.url}analyzeConnections(){this.areaNodes.clear(),this.connectionGroups=[];const t=this.mapReader.getRooms(),e=this.mapReader.getAreas(),i=new Map;for(const c of e){const u=c.getAreaId(),d=c.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 y=(g+f)/2,x=(l+p)/2;i.set(u,{minX:g,maxX:f,minY:l,maxY:p,centerX:y,centerY:x,roomCount:d.length})}let s=1;for(const c of i.values()){const u=c.maxX-c.minX,d=c.maxY-c.minY;s=Math.max(s,u,d)}const o=200,n=100,r=o/s;for(const c of e){const u=c.getAreaId(),d=i.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:c.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 c of t){const u=c.area;if(!this.areaNodes.has(u))continue;const d=this.getLockedDirections(c),g=new Set(c.mSpecialExitLocks??[]);for(const[f,l]of Object.entries(c.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(c,p,f);m&&this.addConnection(a,m)}for(const[f,l]of Object.entries(c.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),y=this.createConnection(c,p,m);y&&this.addConnection(a,y)}}for(const[c,u]of a){const[d,g]=c.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=>Bt[e]).filter(e=>!!e))}createConnection(t,e,i){const s=this.toPlanarDirection(i);return{fromAreaId:t.area,toAreaId:e.area,fromRoomId:t.id,toRoomId:e.id,direction:s,fromRoomPosition:{x:t.x,y:t.y},toRoomPosition:{x:e.x,y:e.y}}}addConnection(t,e){const i=e.fromAreaId<e.toAreaId?`${e.fromAreaId}-${e.toAreaId}`:`${e.toAreaId}-${e.fromAreaId}`;t.has(i)||t.set(i,[]),t.get(i).push(e)}createConnectionGroup(t,e,i){const s=new Map;let o=0,n=0;for(const c of i)c.direction&&s.set(c.direction,(s.get(c.direction)??0)+1),o+=c.toRoomPosition.x-c.fromRoomPosition.x,n+=c.toRoomPosition.y-c.fromRoomPosition.y;let r=null,a=0;for(const[c,u]of s)u>a&&(a=u,r=c);return{fromAreaId:t,toAreaId:e,connections:i,primaryDirection:r,averageOffset:{x:o/i.length,y:n/i.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&&rt.includes(t)?t:null}layoutAreas(){if(Array.from(this.areaNodes.values()).length===0)return;const e=this.findConnectedComponents();let i=0;const s=N.areaWidth*3;for(const o of e)if(o.length===1){const n=this.areaNodes.get(o[0]);n&&(n.x=i,n.y=0),i+=N.areaWidth+s}else{const n=this.forceDirectedLayout(o);for(const a of o){const c=this.areaNodes.get(a);c&&isFinite(n.minX)&&isFinite(n.minY)&&(c.x-=n.minX,c.x+=i,c.y-=n.minY)}const r=isFinite(n.maxX-n.minX)?n.maxX-n.minX:N.areaWidth;i+=r+s}}findConnectedComponents(){const t=new Set,e=[];for(const[i]of this.areaNodes){if(t.has(i))continue;const s=[],o=[i];for(;o.length>0;){const n=o.shift();if(t.has(n))continue;t.add(n),s.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(s)}return e}forceDirectedLayout(t){const e=new Map;for(const w of t){const R=this.areaNodes.get(w);if(!R)continue;const S=new Set(R.connections.map(D=>D.toAreaId));e.set(w,S)}const i=new Set,s=new Set;for(const[w,R]of e)R.size>=3&&i.add(w);for(const[w,R]of e){if(i.has(w)||s.has(w)||R.size>2)continue;const S=[w];s.add(w);const D=Array.from(R);for(const L of D){let z=L,k=w;for(;z&&!s.has(z)&&!i.has(z);){const C=e.get(z);if(!C)break;if(C.size>=3){i.add(z);break}S.push(z),s.add(z);let M=!1;for(const Y of C)if(Y!==k&&!s.has(Y)){k=z,z=Y,M=!0;break}if(!M)break}}let E=!1;for(const L of S){const z=e.get(L);if(z){for(const k of z)if(i.has(k)){E=!0;break}}if(E)break}if(!E&&S.length>0){let L=S[0],z=e.get(S[0])?.size??0;for(const k of S){const C=e.get(k)?.size??0;C>z&&(z=C,L=k)}i.add(L),s.delete(L)}}for(const w of t){const R=e.get(w);(!R||R.size===0)&&i.add(w)}const o=new Map,n=new Map;for(const w of i)o.set(w,w),n.set(w,[]);const r=new Set(i);for(const w of i){const R=e.get(w)??new Set;for(const S of R){if(r.has(S))continue;const D=[];let E=S,L=w;for(;E&&!r.has(E);){D.push(E),o.set(E,w),r.add(E);const z=e.get(E)??new Set;let k;for(const C of z)if(C!==L&&!r.has(C)){k=C;break}L=E,E=k}D.length>0&&n.get(w).push(D)}}const a=new Set,c=[],u=i.values().next().value,d=u!==void 0?u:t[0];if(d!==void 0){const w=this.areaNodes.get(d);w&&(w.x=0,w.y=0,a.add(d),c.push(d))}for(;c.length>0;){const w=c.shift(),R=this.areaNodes.get(w),S=new Map;for(const D of R.connections){const E=D.toAreaId;if(a.has(E)||!i.has(E))continue;const L=this.areaNodes.get(E);if(!L)continue;const z=D.direction??"none";S.has(z)||S.set(z,[]),S.get(z).push({id:E,node:L,conn:D})}for(const[D,E]of S){const L=this.getDirectionOffset(D==="none"?null:D);E.sort((C,M)=>Math.abs(L.x)>Math.abs(L.y)?M.node.realCenterY-C.node.realCenterY:C.node.realCenterX-M.node.realCenterX);const z=N.areaWidth+N.areaSpacing,k=N.areaHeight+N.areaSpacing;E.forEach((C,M)=>{if(C.node.x=R.x+L.x*z,C.node.y=R.y+L.y*k,E.length>1){const Y=(M-(E.length-1)/2)*.5;Math.abs(L.x)>Math.abs(L.y)?C.node.y+=Y*k:C.node.x+=Y*z}a.add(C.id),c.push(C.id)})}}const g=Array.from(i);g.length>1&&this.applyForces(g,80);const f=N.areaWidth+N.areaSpacing+30,l=N.areaHeight+N.areaSpacing+30,p=new Map,m=["east","west","north","south","northeast","northwest","southeast","southwest"];for(const[w,R]of n){const S=this.areaNodes.get(w);if(!S)continue;let D=0;const E=new Map;for(const L of R){let z=w,k=S.x,C=S.y,M=null;for(const Y of L){const O=this.areaNodes.get(Y);if(!O)continue;const B=this.areaNodes.get(z);let T=null;if(B){for(const $ of B.connections)if($.toAreaId===Y){T=$.direction;break}}!T&&z===w?(M=m[D%m.length],D++,T=M):!T&&M&&(T=M);const W=this.getDirectionOffset(T);let G=0;if(z===w&&T){const $=T,ct=E.get($)??0;E.set($,ct+1),G=ct}O.x=k+W.x*f,O.y=C+W.y*l,G>0&&(W.x!==0&&W.y===0?O.y+=G*l*1.2:W.y!==0&&W.x===0?O.x+=G*f*1.2:(O.x+=G*f*1.2,O.y-=G*l*1.2)),p.set(Y,{dx:O.x-S.x,dy:O.y-S.y,hubId:w}),z=Y,k=O.x,C=O.y}}}const y=new Map,x=new Map;for(const w of i){const R=this.areaNodes.get(w);if(!R)continue;let S=R.x,D=R.y,E=R.x+R.width,L=R.y+R.height;const z=n.get(w)??[];for(const k of z)for(const C of k){const M=this.areaNodes.get(C);M&&(S=Math.min(S,M.x),D=Math.min(D,M.y),E=Math.max(E,M.x+M.width),L=Math.max(L,M.y+M.height))}y.set(w,{minX:S,minY:D,maxX:E,maxY:L}),x.set(w,{dx:S-R.x,dy:D-R.y})}this.applyClusterForces(g,y,x,60);for(const[w,R]of p){const S=this.areaNodes.get(w),D=this.areaNodes.get(R.hubId);!S||!D||(S.x=D.x+R.dx,S.y=D.y+R.dy)}let I=1/0,A=1/0,P=-1/0,F=-1/0;for(const w of t){const R=this.areaNodes.get(w);I=Math.min(I,R.x),A=Math.min(A,R.y),P=Math.max(P,R.x+R.width),F=Math.max(F,R.y+R.height)}return{minX:I,minY:A,maxX:P,maxY:F}}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,i,s){const r=new Map;for(const a of t)r.set(a,{vx:0,vy:0});for(let a=0;a<s;a++){for(const c of t){const u=this.areaNodes.get(c),d=e.get(c),g=i.get(c);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 c of t){const u=this.areaNodes.get(c),d=r.get(c),g=e.get(c);if(!(!u||!d||!g)){for(const f of t){if(c===f)continue;const l=e.get(f);if(!l)continue;const p=(g.minX+g.maxX)/2,m=(g.minY+g.maxY)/2,y=(l.minX+l.maxX)/2,x=(l.minY+l.maxY)/2,I=p-y,A=m-x,P=(g.maxX-g.minX)/2,F=(g.maxY-g.minY)/2,w=(l.maxX-l.minX)/2,R=(l.maxY-l.minY)/2,S=P+w+50,D=F+R+50,E=S-Math.abs(I),L=D-Math.abs(A);if(E>0&&L>0)if(E<L){const z=E*(I>=0?1:-1)*.5;d.vx+=z}else{const z=L*(A>=0?1:-1)*.5;d.vy+=z}}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,y=Math.sqrt(p*p+m*m)||1,x=N.areaWidth+N.areaSpacing+50,A=(y-x)*.015;d.vx+=p/y*A,d.vy+=m/y*A}}}for(const c of t){const u=this.areaNodes.get(c),d=r.get(c);!u||!d||(u.x+=d.vx,u.y+=d.vy,d.vx*=.8,d.vy*=.8)}}}applyForces(t,e){const o=N.areaWidth+N.areaSpacing,n=N.areaWidth/2+60,r=new Set(t),a=[],c=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);c.has(l)||(c.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 y of t){if(g===y)continue;const x=this.areaNodes.get(y);if(!x)continue;const I=(f.width+x.width)/2+20,A=(f.height+x.height)/2+20,P=f.x+f.width/2,F=f.y+f.height/2,w=x.x+x.width/2,R=x.y+x.height/2,S=P-w,D=F-R,E=I-Math.abs(S),L=A-Math.abs(D);E>0&&L>0&&(E<L?l.vx+=(S>=0?1:-1)*E*.5:l.vy+=(D>=0?1:-1)*L*.5)}for(const y of a){if(y.from===g||y.to===g)continue;const x=this.areaNodes.get(y.from),I=this.areaNodes.get(y.to);if(!x||!I)continue;const A=x.x+x.width/2,P=x.y+x.height/2,F=I.x+I.width/2,w=I.y+I.height/2,R=this.closestPointOnSegment(p,m,A,P,F,w),S=p-R.x,D=m-R.y,E=Math.sqrt(S*S+D*D)||1;if(E<n){const L=(n-E)*.6;l.vx+=S/E*L,l.vy+=D/E*L}}for(const y of f.connections){if(!r.has(y.toAreaId))continue;const x=this.areaNodes.get(y.toAreaId);if(!x)continue;const I=x.x-f.x,A=x.y-f.y,P=Math.sqrt(I*I+A*A)||1,w=(P-o)*.03;l.vx+=I/P*w,l.vy+=A/P*w;const R=this.getDirectionOffset(y.direction),S=f.x+R.x*o,D=f.y+R.y*o,E=u.get(y.toAreaId);E&&(E.vx+=(S-x.x)*.01,E.vy+=(D-x.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,i,s,o,n){const r=o-i,a=n-s,c=t-i,u=e-s,d=r*r+a*a;if(d===0)return{x:i,y:s};let g=(c*r+u*a)/d;return g=Math.max(0,Math.min(1,g)),{x:i+g*r,y:s+g*a}}edgesIntersect(t,e,i,s,o,n,r,a){const c=(u,d,g,f,l,p)=>(p-d)*(g-u)>(f-d)*(l-u);return c(t,e,o,n,r,a)!==c(i,s,o,n,r,a)&&c(t,e,i,s,o,n)!==c(t,e,i,s,r,a)}drawConnections(){this.connectionLayer.destroyChildren();for(const t of this.connectionGroups){const e=this.areaNodes.get(t.fromAreaId),i=this.areaNodes.get(t.toAreaId);if(!e||!i||!isFinite(e.x)||!isFinite(e.y)||!isFinite(i.x)||!isFinite(i.y))continue;const s={x:e.x+e.width/2,y:e.y+e.height/2},o={x:i.x+i.width/2,y:i.y+i.height/2};let n,r;if(this.dotsMode?(n=s,r=o):(n=this.getEdgePoint(e,o),r=this.getEdgePoint(i,s)),!isFinite(n.x)||!isFinite(n.y)||!isFinite(r.x)||!isFinite(r.y))continue;const a=this.dotsMode?"#ffffff":N.connectionColor,c=this.dotsMode?1:Math.min(N.connectionLineWidth,1+t.connections.length*.5),u=new b.Line({points:[n.x,n.y,r.x,r.y],stroke:a,strokeWidth:c,lineCap:"round",listening:!1});this.connectionLayer.add(u)}}getEdgePoint(t,e){const i=t.x+t.width/2,s=t.y+t.height/2,o=e.x-i,n=e.y-s,r=t.width/2,a=t.height/2;if(o===0&&n===0)return{x:i,y:s};const c=Math.abs(o),u=Math.abs(n);let d;return c/r>u/a?d=r/c:d=a/u,{x:i+o*d,y:s+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 s=t.x+t.width/2,o=t.y+t.height/2,n=new b.Group({x:s,y:o,draggable:!0}),r=new b.Circle({radius:6,fill:e?N.highlightColor:"#ffffff",stroke:e?N.highlightColor:"#ffffff",strokeWidth:1}),a=new b.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(N.highlightColor),r.stroke(N.highlightColor),this.areaLayer.batchDraw()}),n.on("mouseleave",()=>{this.stage.container().style.cursor="auto",r.fill(e?N.highlightColor:"#ffffff"),r.stroke(e?N.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 i=new b.Group({x:t.x,y:t.y,draggable:!0}),s=new b.Rect({width:t.width,height:t.height,fill:N.areaFillColor,stroke:e?N.highlightColor:N.areaStrokeColor,strokeWidth:e?3:2,cornerRadius:8}),o=new b.Text({text:t.name,fontSize:N.fontSize,fill:N.textColor,width:t.width-10,height:t.height-20,x:5,y:10,align:"center",verticalAlign:"middle",ellipsis:!0,wrap:"word"}),n=new b.Text({text:`${t.roomCount} rooms`,fontSize:10,fill:N.connectionColor,width:t.width-10,x:5,y:t.height-18,align:"center"});i.add(s),i.add(o),i.add(n),i.on("click tap",()=>{this.emitAreaClickEvent(t.areaId)}),i.on("mouseenter",()=>{this.stage.container().style.cursor="pointer",s.stroke(N.highlightColor),this.areaLayer.batchDraw()}),i.on("mouseleave",()=>{this.stage.container().style.cursor="auto",s.stroke(e?N.highlightColor:N.areaStrokeColor),this.areaLayer.batchDraw()}),i.on("dragmove",()=>{t.x=i.x(),t.y=i.y(),this.drawConnections(),this.connectionLayer.batchDraw()}),i.on("dragstart",()=>{this.stage.container().style.cursor="grabbing"}),i.on("dragend",()=>{this.stage.container().style.cursor="pointer"}),this.areaLayer.add(i)}}}centerView(){let t=1/0,e=1/0,i=-1/0,s=-1/0;for(const[,l]of this.areaNodes)t=Math.min(t,l.x),e=Math.min(e,l.y),i=Math.max(i,l.x+l.width),s=Math.max(s,l.y+l.height);if(!isFinite(t))return;const o=i-t,n=s-e,r=t+o/2,a=e+n/2,c=50,u=(this.stage.width()-c*2)/o,d=(this.stage.height()-c*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 i=this.stage.scaleX(),s=e.x+e.width/2,o=e.y+e.height/2;this.stage.position({x:this.stage.width()/2-s*i,y:this.stage.height()/2-o*i}),this.stage.batchDraw()}emitAreaClickEvent(t){const e=new CustomEvent("areaclick",{detail:{areaId:t}});this.stage.container().dispatchEvent(e)}getAreaNode(t){return this.areaNodes.get(t)}getConnectionGroups(){return this.connectionGroups}destroy(){this.stage.destroy()}}exports.AreaMapRenderer=Zt;exports.AreaMapSettings=N;exports.ExplorationArea=J;exports.MapReader=zt;exports.PathFinder=Ft;exports.Renderer=Lt;exports.Settings=h;
|
|
2
2
|
//# sourceMappingURL=index.cjs.map
|