mudlet-map-renderer 0.13.1-konva → 0.14.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.
@@ -172,6 +172,8 @@ export declare class Renderer {
172
172
  private currentZoom;
173
173
  private currentRoomOverlay;
174
174
  private roomNodes;
175
+ /** When true, resizing the container will center on the current room. Set to false for static map views. */
176
+ centerOnResize: boolean;
175
177
  private standaloneExitNodes;
176
178
  private spatialBucketSize;
177
179
  private roomSpatialIndex;
@@ -195,6 +197,11 @@ export declare class Renderer {
195
197
  private emitRoomContextEvent;
196
198
  private emitZoomChangeEvent;
197
199
  setZoom(zoom: number): boolean;
200
+ /**
201
+ * Zooms relative to the center of the viewport.
202
+ * Use this for UI controls (buttons, menus) where there's no mouse position.
203
+ */
204
+ zoomToCenter(zoom: number): boolean;
198
205
  getZoom(): number;
199
206
  setCullingMode(mode: CullingMode): void;
200
207
  getCullingMode(): CullingMode;
@@ -218,7 +225,7 @@ export declare class Renderer {
218
225
  * Use this when you want to show where the player is without moving the viewport.
219
226
  */
220
227
  updatePositionMarker(roomId: number): void;
221
- setPosition(roomId: number): void;
228
+ setPosition(roomId: number, center?: boolean): void;
222
229
  renderPath(locations: number[], color?: string): import('konva/lib/shapes/Line').Line<{
223
230
  points: number[];
224
231
  stroke: string;
package/dist/index.cjs CHANGED
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const g=require("konva"),te=["north","south","east","west","northeast","northwest","southeast","southwest"],L={north:"n",south:"s",east:"e",west:"w",northeast:"ne",northwest:"nw",southeast:"se",southwest:"sw",up:"u",down:"d",in:"i",out:"o"},H={north:{x:0,y:-1},south:{x:0,y:1},east:{x:1,y:0},west:{x:-1,y:0},northeast:{x:1,y:-1},northwest:{x:-1,y:-1},southeast:{x:1,y:1},southwest:{x:-1,y:1}},se=["north","south","east","west","northeast","northwest","southeast","southwest"],ge={north:"south",south:"north",east:"west",west:"east",northeast:"southwest",northwest:"southeast",southeast:"northwest",southwest:"northeast"};function de(c){return c?Object.prototype.hasOwnProperty.call(H,c):!1}function S(c,e,t,s=1){if(!de(t))return{x:c,y:e};const i=H[t];return{x:c+i.x*s,y:e+i.y*s}}function fe(c,e,t,s=1){if(!de(t))return{x:c,y:e};const i=H[t],r=Math.atan2(i.y,i.x);return{x:c+Math.cos(r)*s,y:e+Math.sin(r)*s}}const V={OPEN_DOOR:"rgb(10, 155, 10)",CLOSED_DOOR:"rgb(226, 205, 59)",LOCKED_DOOR:"rgb(155, 10, 10)",ONE_WAY_FILL:"rgb(155, 10, 10)"},xe={1:"north",2:"northeast",3:"northwest",4:"east",5:"west",6:"south",7:"southeast",8:"southwest",9:"up",10:"down",11:"in",12:"out"},ye=["up","down","in","out"];function Re(c){switch(c){case 1:return V.OPEN_DOOR;case 2:return V.CLOSED_DOOR;default:return V.LOCKED_DOOR}}class be{constructor(e,t){this.mapReader=e,this.mapRenderer=t}getRoomEdgePoint(e,t,s,i){return n.roomShape==="circle"?fe(e,t,s,i):S(e,t,s,i)}render(e,t){return this.renderWithColor(e,n.lineColor,t)}renderWithColor(e,t,s){return e.aDir&&e.bDir?this.renderTwoWayExit(e,t,s):this.renderOneWayExit(e,t)}renderTwoWayExit(e,t,s){const i=this.mapReader.getRoom(e.a),r=this.mapReader.getRoom(e.b);if(!i||!r||!e.aDir||!e.bDir||!te.includes(e.aDir)||!te.includes(e.bDir)||i.customLines[L[e.aDir]]&&r.customLines[L[e.bDir]]||i.z!==r.z&&(s!==r.z&&i.customLines[L[e.aDir]]||s!==i.z&&r.customLines[L[e.bDir]]))return;const o=new g.Group,a=[];if(a.push(...Object.values(this.getRoomEdgePoint(i.x,i.y,e.aDir,n.roomSize/2))),a.push(...Object.values(this.getRoomEdgePoint(r.x,r.y,e.bDir,n.roomSize/2))),i.doors[L[e.aDir]]||r.doors[L[e.bDir]]){const d=this.renderDoor(a,i.doors[L[e.aDir]]??r.doors[L[e.bDir]]);o.add(d)}const h=new g.Line({points:a,stroke:t,strokeWidth:n.lineWidth,perfectDrawEnabled:!1});return o.add(h),o}renderOneWayExit(e,t){const s=e.aDir?this.mapReader.getRoom(e.a):this.mapReader.getRoom(e.b),i=e.aDir?this.mapReader.getRoom(e.b):this.mapReader.getRoom(e.a),r=e.aDir?e.aDir:e.bDir;if(!r||!s||!i||s.customLines[L[r]||r])return;if(s.area!=i.area&&r)return this.renderAreaExit(s,r,t);let o={x:i.x,y:i.y};(i.area!==s.area||i.z!==s.z)&&(o=S(s.x,s.y,r,n.roomSize/2));const a=S(s.x,s.y,r,.3),h=a.x-(a.x-o.x)/2,d=a.y-(a.y-o.y)/2,u=new g.Group,l=[];l.push(...Object.values(this.getRoomEdgePoint(s.x,s.y,r,n.roomSize/2))),l.push(o.x,o.y);const y=new g.Line({points:l,stroke:t,strokeWidth:n.lineWidth,dashEnabled:!0,dash:[.1,.05],perfectDrawEnabled:!1});u.add(y);const R=new g.Arrow({points:[l[0],l[1],h,d],pointerLength:.5,pointerWidth:.35,strokeWidth:n.lineWidth*1.4,stroke:t,fill:V.ONE_WAY_FILL,dashEnabled:!0,dash:[.1,.05]});return u.add(R),u}renderAreaExit(e,t,s){const i=this.getRoomEdgePoint(e.x,e.y,t,n.roomSize/2),r=S(e.x,e.y,t,n.roomSize*1.5),o=s??this.mapReader.getColorValue(e.env);return new g.Arrow({points:[i.x,i.y,r.x,r.y],pointerLength:.3,pointerWidth:.3,strokeWidth:n.lineWidth*1.4,stroke:o,fill:o})}renderSpecialExits(e,t){return Object.entries(e.customLines).map(([s,i])=>{const r=[e.x,e.y];i.points.reduce((u,l)=>(u.push(l.x,-l.y),u),r);const o=i.attributes.arrow?g.Arrow:g.Line,a=t??`rgb(${i.attributes.color.r}, ${i.attributes.color.g}, ${i.attributes.color.b})`,h=new o({points:r,strokeWidth:n.lineWidth,stroke:a,fill:t??`rgb(${i.attributes.color.r}, ${i.attributes.color.g} , ${i.attributes.color.b})`,pointerLength:.3,pointerWidth:.2,perfectDrawEnabled:!1});let d=i.attributes.style;return d==="dot line"?(h.dash([.05,.05]),h.dashOffset(.1)):d==="dash line"?h.dash([.4,.2]):d==="solid line"||d!==void 0&&console.log("Brak opisu stylu: "+d),h})}renderStubs(e,t=n.lineColor){return e.stubs.map(s=>{const i=xe[s],r=this.getRoomEdgePoint(e.x,e.y,i,n.roomSize/2),o=S(e.x,e.y,i,n.roomSize/2+.5),a=[r.x,r.y,o.x,o.y];return new g.Line({points:a,stroke:t,strokeWidth:n.lineWidth})})}renderInnerExits(e){return ye.map(t=>{if(e.exits[t]){const s=new g.Group,i=new g.RegularPolygon({x:e.x,y:e.y,sides:3,fill:this.mapReader.getSymbolColor(e.env,.6),stroke:this.mapReader.getSymbolColor(e.env),strokeWidth:n.lineWidth,radius:n.roomSize/5,scaleX:1.4,scaleY:.8,perfectDrawEnabled:!1});s.add(i);let r=e.doors[t];if(r!==void 0)switch(r){case 1:i.stroke(V.OPEN_DOOR);break;case 2:i.stroke(V.CLOSED_DOOR);break;default:i.stroke(V.LOCKED_DOOR)}switch(t){case"up":i.position(S(e.x,e.y,"south",n.roomSize/4));break;case"down":i.rotation(180),i.position(S(e.x,e.y,"north",n.roomSize/4));break;case"in":const o=i.clone();o.rotation(-90),o.position(S(e.x,e.y,"east",n.roomSize/4)),s.add(o),i.rotation(90),i.position(S(e.x,e.y,"west",n.roomSize/4));break;case"out":const a=i.clone();a.rotation(90),a.position(S(e.x,e.y,"east",n.roomSize/4)),s.add(a),i.rotation(-90),i.position(S(e.x,e.y,"west",n.roomSize/4));break}return s}}).filter(t=>t!==void 0)}renderDoor(e,t){const s={x:e[0]+(e[2]-e[0])/2,y:e[1]+(e[3]-e[1])/2};return new g.Rect({x:s.x-n.roomSize/4,y:s.y-n.roomSize/4,width:n.roomSize/2,height:n.roomSize/2,stroke:Re(t),strokeWidth:n.lineWidth})}}class ue{constructor(e,t){this.rooms=[],this.labels=[],this.rooms=e,this.bounds=this.createBounds(),this.labels=t}getRooms(){return this.rooms}getLabels(){return this.labels}getBounds(){return this.bounds}createBounds(){return this.rooms.reduce((e,t)=>({minX:Math.min(e.minX,t.x),maxX:Math.max(e.maxX,t.x),minY:Math.min(e.minY,t.y),maxY:Math.max(e.maxY,t.y)}),{minX:Number.POSITIVE_INFINITY,maxX:Number.NEGATIVE_INFINITY,minY:Number.POSITIVE_INFINITY,maxY:Number.NEGATIVE_INFINITY})}}class _{constructor(e){this.planes={},this.exits=new Map,this.version=0,this.area=e,this.planes=this.createPlanes(),this.createExits()}getAreaName(){return this.area.areaName}getAreaId(){return parseInt(this.area.areaId)}getVersion(){return this.version}markDirty(){this.version++}getPlane(e){return this.planes[e]}getPlanes(){return Object.values(this.planes)}getRooms(){return this.area.rooms}getLinkExits(e){return Array.from(this.exits.values()).filter(t=>t.zIndex.includes(e))}createPlanes(){const e=this.area.rooms.reduce((t,s)=>(t[s.z]||(t[s.z]=[]),t[s.z].push(s),t),{});return Object.entries(e).reduce((t,[s,i])=>(t[+s]=new ue(i,this.area.labels.filter(r=>r.Z===+s)),t),{})}createExits(){this.area.rooms.forEach(e=>{Object.entries(e.specialExits).forEach(([t,s])=>this.createHalfExit(e.id,s,e.z,t)),Object.entries(e.exits).forEach(([t,s])=>this.createHalfExit(e.id,s,e.z,t))})}createHalfExit(e,t,s,i){if(e===t)return;const r=Math.min(e,t),o=Math.max(e,t),a=`${r}-${o}`;let h=this.exits.get(a);h||(h={a:r,b:o,zIndex:[s]}),r==e?h.aDir=i:h.bDir=i,h.zIndex.push(s),this.exits.set(a,h)}}class ie extends ue{constructor(e,t){super(e.getRooms(),e.getLabels()),this.basePlane=e,this.visitedRooms=t}getRooms(){return this.basePlane.getRooms().filter(e=>this.visitedRooms.has(e.id))}getLabels(){return this.basePlane.getLabels()}getBounds(){const e=this.getRooms();return e.length?e.reduce((t,s)=>({minX:Math.min(t.minX,s.x),maxX:Math.max(t.maxX,s.x),minY:Math.min(t.minY,s.y),maxY:Math.max(t.maxY,s.y)}),{minX:Number.POSITIVE_INFINITY,maxX:Number.NEGATIVE_INFINITY,minY:Number.POSITIVE_INFINITY,maxY:Number.NEGATIVE_INFINITY}):this.basePlane.getBounds()}}class B extends _{constructor(e,t){super(e),this.planeCache=new WeakMap,this.visitedRooms=t instanceof Set?t:new Set(t??[]),this.areaRoomIds=new Set(e.rooms.map(s=>s.id))}getPlane(e){const t=super.getPlane(e);if(!t)return t;let s=this.planeCache.get(t);return s||(s=new ie(t,this.visitedRooms),this.planeCache.set(t,s)),s}getPlanes(){return super.getPlanes().map(e=>{let t=this.planeCache.get(e);return t||(t=new ie(e,this.visitedRooms),this.planeCache.set(e,t)),t})}getLinkExits(e){return super.getLinkExits(e).filter(t=>this.visitedRooms.has(t.a)||this.visitedRooms.has(t.b))}getVisitedRoomCount(){return super.getRooms().reduce((e,t)=>e+(this.visitedRooms.has(t.id)?1:0),0)}getTotalRoomCount(){return this.areaRoomIds.size}hasVisitedRoom(e){return this.areaRoomIds.has(e)&&this.visitedRooms.has(e)}getVisitedRoomIds(){return super.getRooms().filter(e=>this.visitedRooms.has(e.id)).map(e=>e.id)}addVisitedRoom(e){const t=this.visitedRooms.has(e);this.visitedRooms.add(e);const s=!t&&this.areaRoomIds.has(e);return s&&this.markDirty(),s}addVisitedRooms(e){let t=0;for(const s of e){const i=this.visitedRooms.has(s);this.visitedRooms.add(s),!i&&this.areaRoomIds.has(s)&&t++}return t>0&&this.markDirty(),t}}class we{constructor(e,t){this.paths=[],this.mapReader=e,this.overlayLayer=t}renderPath(e,t,s,i="#66E64D"){if(t===void 0||s===void 0)return;const r=e.map(l=>this.mapReader.getRoom(l)).filter(l=>l!==void 0),o=[];let a=null;const h=()=>{a&&(a.length<4&&o.pop(),a=null)},d=()=>(a||(a=[],o.push(a)),a);r.forEach((l,y)=>{if(!this.isRoomVisible(l,t,s))return;const R=y>0?r[y-1]:void 0,w=y<r.length-1?r[y+1]:void 0;if(this.isRoomVisible(R,t,s))d();else{h();const p=d();if(R){const f=this.getDirectionTowards(l,R);if(f){const M=S(l.x,l.y,f,n.roomSize);p.push(M.x,M.y)}}}if(a?.push(l.x,l.y),!this.isRoomVisible(w,t,s)&&w){const p=this.getDirectionTowards(l,w);if(p){const f=S(l.x,l.y,p,n.roomSize);a?.push(f.x,f.y)}h()}}),h();const u=o.filter(l=>l.length>=4).map(l=>new g.Line({points:l,stroke:i,strokeWidth:n.lineWidth*4}));return u.forEach(l=>{this.overlayLayer.add(l),this.paths.push(l)}),u[0]}clearPaths(){this.paths.forEach(e=>{e.destroy()}),this.paths=[]}isRoomVisible(e,t,s){return e?e.area===t&&e.z===s:!1}getDirectionTowards(e,t){for(const s of se)if(e.exits[s]===t.id)return s;for(const s of se)if(t.exits[s]===e.id)return ge[s]}}const ve=.6,A=75,Ee=.025,Se="rgb(225, 255, 225)",W="rgb(120, 72, 0)";function X(c,e){const t=parseInt(c.slice(1,3),16),s=parseInt(c.slice(3,5),16),i=parseInt(c.slice(5,7),16);return`rgba(${t}, ${s}, ${i}, ${e})`}const k=class k{};k.roomSize=ve,k.lineWidth=Ee,k.lineColor=Se,k.instantMapMove=!1,k.highlightCurrentRoom=!0,k.cullingEnabled=!0,k.cullingMode="indexed",k.cullingBounds=null,k.labelRenderMode="image",k.roomShape="rectangle",k.playerMarker={strokeColor:"#00e5b2",strokeAlpha:1,fillColor:"#00e5b2",fillAlpha:0,strokeWidth:.1,sizeFactor:1.7,dash:[.05,.05],dashEnabled:!0};let n=k;class ke{constructor(e,t){this.highlights=new Map,this.currentZoom=1,this.currentRoomOverlay=[],this.roomNodes=new Map,this.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 g.Stage({container:e,width:e.clientWidth,height:e.clientHeight,draggable:!0}),window.addEventListener("resize",()=>{this.onResize(e)}),e.addEventListener("resize",()=>{this.onResize(e)}),this.linkLayer=new g.Layer({listening:!1}),this.stage.add(this.linkLayer),this.roomLayer=new g.Layer,this.stage.add(this.roomLayer),this.positionLayer=new g.Layer({listening:!1}),this.stage.add(this.positionLayer),this.overlayLayer=new g.Layer({listening:!1}),this.stage.add(this.overlayLayer),this.mapReader=t,this.exitRenderer=new be(t,this),this.pathRenderer=new we(t,this.overlayLayer),this.initScaling(1.1),this.stage.on("dragmove",()=>this.scheduleRoomCulling()),this.stage.on("dragend",()=>this.scheduleRoomCulling())}onResize(e){this.stage.width(e.clientWidth),this.stage.height(e.clientHeight),this.currentRoomId&&this.centerOnRoom(this.mapReader.getRoom(this.currentRoomId),!1),this.stage.batchDraw(),this.scheduleRoomCulling()}initScaling(e){g.hitOnDragEnabled=!0;let t,s=!1,i=!1;this.stage.on("touchstart",r=>{const o=r.evt.touches;o&&o.length>1?(i=!0,this.stage.isDragging()&&(this.stage.stopDrag(),s=!0),this.stage.draggable(!1)):(i=!1,this.stage.draggable(!0))}),this.stage.on("touchend touchcancel",r=>{t=void 0;const o=r.evt.touches;(!o||o.length<=1)&&(i=!1,this.stage.draggable(!0))}),this.stage.on("wheel",r=>{r.evt.preventDefault();const o=this.stage.scaleX(),a=this.stage.getPointerPosition();if(!a)return;const h={x:(a.x-this.stage.x())/o,y:(a.y-this.stage.y())/o};let d=r.evt.deltaY>0?-1:1;r.evt.ctrlKey&&(d=-d);const u=d>0?this.currentZoom*e:this.currentZoom/e,l=u*A,y=this.setZoom(u),R={x:a.x-h.x*l,y:a.y-h.y*l};this.stage.position(R),this.scheduleRoomCulling(),y&&this.emitZoomChangeEvent()}),this.stage.on("touchmove",r=>{const o=r.evt.touches,a=o?.[0],h=o?.[1];if(h||i&&(i=!1,this.stage.draggable(!0)),a&&!h&&s&&!this.stage.isDragging()&&(this.stage.startDrag(),s=!1),!a||!h){t=void 0;return}r.evt.preventDefault(),this.stage.isDragging()&&(this.stage.stopDrag(),s=!0),i||(i=!0,this.stage.draggable(!1));const d=this.stage.container().getBoundingClientRect(),u={x:a.clientX-d.left,y:a.clientY-d.top},l={x:h.clientX-d.left,y:h.clientY-d.top},y=Math.hypot(u.x-l.x,u.y-l.y);if(t===void 0){t=y;return}if(t===0)return;const R=this.stage.scaleX(),w=this.stage.x(),b=this.stage.y(),m={x:this.stage.width()/2,y:this.stage.height()/2},p={x:(m.x-w)/R,y:(m.y-b)/R},f=this.currentZoom*(y/t),M=this.setZoom(f),I=this.stage.scaleX(),P={x:m.x-p.x*I,y:m.y-p.y*I};this.stage.position(P),this.stage.batchDraw(),this.scheduleRoomCulling(),t=y,M&&this.emitZoomChangeEvent()})}drawArea(e,t){const s=this.mapReader.getArea(e);if(!s)return;const i=s.getPlane(t);i&&(this.currentArea=e,this.currentAreaInstance=s,this.currentZIndex=t,this.currentAreaVersion=s.getVersion(),this.clearCurrentRoomOverlay(),this.roomLayer.destroyChildren(),this.linkLayer.destroyChildren(),this.roomNodes.clear(),this.standaloneExitNodes=[],this.standaloneExitBoundsRoomSize=void 0,this.roomSpatialIndex.clear(),this.exitSpatialIndex.clear(),this.visibleRooms.clear(),this.visibleStandaloneExitNodes.clear(),this.spatialBucketSize=this.computeSpatialBucketSize(),this.stage.scale({x:A*this.currentZoom,y:A*this.currentZoom}),this.renderLabels(i.getLabels()),this.renderExits(s.getLinkExits(t)),this.renderRooms(i.getRooms()??[]),this.refreshHighlights(),this.stage.batchDraw(),this.scheduleRoomCulling())}computeSpatialBucketSize(){return Math.max(n.roomSize*10,5)}getBucketKey(e,t){return`${e},${t}`}forEachBucket(e,t,s,i,r){const o=this.spatialBucketSize,a=Math.min(e,s),h=Math.max(e,s),d=Math.min(t,i),u=Math.max(t,i),l=Math.floor(a/o),y=Math.floor(h/o),R=Math.floor(d/o),w=Math.floor(u/o);for(let b=l;b<=y;b++)for(let m=R;m<=w;m++)r(this.getBucketKey(b,m))}addRoomToSpatialIndex(e){const t=n.roomSize/2,s=e.room.x-t,i=e.room.x+t,r=e.room.y-t,o=e.room.y+t;this.forEachBucket(s,r,i,o,a=>{let h=this.roomSpatialIndex.get(a);h||(h=new Set,this.roomSpatialIndex.set(a,h)),h.add(e)})}addStandaloneExitToSpatialIndex(e){const{bounds:t}=e,s=t.x,i=t.x+t.width,r=t.y,o=t.y+t.height;this.forEachBucket(s,r,i,o,a=>{let h=this.exitSpatialIndex.get(a);h||(h=new Set,this.exitSpatialIndex.set(a,h)),h.add(e)})}collectRoomCandidates(e,t,s,i){const r=new Set;return this.forEachBucket(e,t,s,i,o=>{this.roomSpatialIndex.get(o)?.forEach(h=>r.add(h))}),r}collectStandaloneExitCandidates(e,t,s,i){const r=new Set;return this.forEachBucket(e,t,s,i,o=>{this.exitSpatialIndex.get(o)?.forEach(h=>r.add(h))}),r}refreshStandaloneExitBoundsIfNeeded(){this.standaloneExitBoundsRoomSize!==n.roomSize&&(this.exitSpatialIndex.clear(),this.standaloneExitNodes.forEach(e=>{e.bounds=e.node.getClientRect({relativeTo:this.linkLayer}),this.addStandaloneExitToSpatialIndex(e)}),this.standaloneExitBoundsRoomSize=n.roomSize)}emitRoomContextEvent(e,t,s){const i=this.stage.container(),r=i.getBoundingClientRect(),o={roomId:e,position:{x:t-r.left,y:s-r.top}},a=new CustomEvent("roomcontextmenu",{detail:o});i.dispatchEvent(a)}emitZoomChangeEvent(){const e=new CustomEvent("zoom",{detail:{zoom:this.currentZoom}});this.stage.container().dispatchEvent(e)}setZoom(e){return this.currentZoom===e?!1:(this.currentZoom=e,this.stage.scale({x:A*e,y:A*e}),this.scheduleRoomCulling(),!0)}getZoom(){return this.currentZoom}setCullingMode(e){n.cullingMode=e,n.cullingEnabled=e!=="none",this.scheduleRoomCulling()}getCullingMode(){return n.cullingMode}getCurrentArea(){return this.currentArea?this.mapReader.getArea(this.currentArea):void 0}refreshCurrentRoomOverlay(){if(this.currentRoomId!==void 0){const e=this.mapReader.getRoom(this.currentRoomId);e&&this.updateCurrentRoomOverlay(e)}}refresh(){this.currentRoomId!==void 0&&this.currentArea!==void 0&&this.currentZIndex!==void 0&&(this.drawArea(this.currentArea,this.currentZIndex),this.setPosition(this.currentRoomId))}updatePositionMarker(e){const t=this.mapReader.getRoom(e);if(!t)return;if(t.area!==this.currentArea||t.z!==this.currentZIndex){this.positionRender&&(this.positionRender.hide(),this.positionLayer.batchDraw());return}this.currentRoomId=e,this.updateCurrentRoomOverlay(t);const s=X(n.playerMarker.strokeColor,n.playerMarker.strokeAlpha),i=X(n.playerMarker.fillColor,n.playerMarker.fillAlpha),r=n.roomSize/2*n.playerMarker.sizeFactor;this.positionRender?(this.positionRender.position({x:t.x,y:t.y}),this.positionRender.radius(r),this.positionRender.stroke(s),this.positionRender.fill(i),this.positionRender.strokeWidth(n.playerMarker.strokeWidth),this.positionRender.dash(n.playerMarker.dash??[]),this.positionRender.dashEnabled(n.playerMarker.dashEnabled),this.positionRender.show()):(this.positionRender=new g.Circle({x:t.x,y:t.y,radius:r,stroke:s,fill:i,strokeWidth:n.playerMarker.strokeWidth,dash:n.playerMarker.dash,dashEnabled:n.playerMarker.dashEnabled}),this.positionLayer.add(this.positionRender)),this.positionLayer.batchDraw()}setPosition(e){const t=this.mapReader.getRoom(e);if(!t)return;const s=this.mapReader.getArea(t.area),i=s?.getVersion();let r=this.currentArea!==t.area||this.currentZIndex!==t.z;(this.currentArea!==t.area||this.currentZIndex!==t.z||i!==void 0&&this.currentAreaVersion!==i||s!==void 0&&this.currentAreaInstance!==s)&&this.drawArea(t.area,t.z),this.centerOnRoom(t,r),this.updateCurrentRoomOverlay(t);const o=X(n.playerMarker.strokeColor,n.playerMarker.strokeAlpha),a=X(n.playerMarker.fillColor,n.playerMarker.fillAlpha),h=n.roomSize/2*n.playerMarker.sizeFactor;this.positionRender?(this.positionRender.radius(h),this.positionRender.stroke(o),this.positionRender.fill(a),this.positionRender.strokeWidth(n.playerMarker.strokeWidth),this.positionRender.dash(n.playerMarker.dash??[]),this.positionRender.dashEnabled(n.playerMarker.dashEnabled)):(this.positionRender=new g.Circle({x:t.x,y:t.y,radius:h,stroke:o,fill:a,strokeWidth:n.playerMarker.strokeWidth,dash:n.playerMarker.dash,dashEnabled:n.playerMarker.dashEnabled}),this.positionLayer.add(this.positionRender))}renderPath(e,t){return this.pathRenderer.renderPath(e,this.currentArea,this.currentZIndex,t)}clearPaths(){this.pathRenderer.clearPaths()}renderHighlight(e,t){const s=this.mapReader.getRoom(e);if(!s)return;const i=this.highlights.get(e);i?.shape&&(i.shape.destroy(),delete i.shape);const r={color:t,area:s.area,z:s.z};if(this.highlights.set(e,r),s.area===this.currentArea&&s.z===this.currentZIndex){const o=this.createHighlightShape(s,t);return this.overlayLayer.add(o),r.shape=o,this.overlayLayer.batchDraw(),o}return r.shape}clearHighlights(){this.highlights.forEach(({shape:e})=>e?.destroy()),this.highlights.clear(),this.overlayLayer.batchDraw()}refreshHighlights(){this.highlights.forEach((e,t)=>{if(e.shape?.destroy(),delete e.shape,e.area!==this.currentArea||e.z!==this.currentZIndex)return;const s=this.mapReader.getRoom(t);if(!s)return;const i=this.createHighlightShape(s,e.color);this.overlayLayer.add(i),e.shape=i}),this.overlayLayer.batchDraw()}createHighlightShape(e,t){return n.roomShape==="circle"?new g.Circle({x:e.x,y:e.y,radius:n.roomSize/2*1.5,stroke:t,strokeWidth:.1,dash:[.05,.05],dashEnabled:!0,listening:!1}):new g.Rect({x:e.x-n.roomSize/2*1.5,y:e.y-n.roomSize/2*1.5,width:n.roomSize*1.5,height:n.roomSize*1.5,stroke:t,strokeWidth:.1,dash:[.05,.05],dashEnabled:!0,listening:!1})}centerOnRoom(e,t=!1){this.currentRoomId=e.id;const s={x:e.x,y:e.y};this.positionRender?.position(e);const r=this.stage.getAbsoluteTransform().point(s),o={x:this.stage.width()/2,y:this.stage.height()/2},a=o.x-r.x,h=o.y-r.y;this.currentTransition&&(this.currentTransition.pause(),this.currentTransition.destroy(),delete this.currentTransition),t||n.instantMapMove?(this.stage.position({x:this.stage.x()+a,y:this.stage.y()+h}),this.scheduleRoomCulling()):(this.currentTransition=new g.Tween({node:this.stage,x:this.stage.x()+a,y:this.stage.y()+h,duration:.2,easing:g.Easings.EaseInOut,onUpdate:()=>this.scheduleRoomCulling(),onFinish:()=>this.scheduleRoomCulling()}),this.currentTransition.play())}renderRooms(e){e.forEach(t=>{const s=new g.Group({x:t.x-n.roomSize/2,y:t.y-n.roomSize/2}),i=this.mapReader.getColorValue(t.env),r=n.lineColor,a=n.roomShape==="circle"?new g.Circle({x:n.roomSize/2,y:n.roomSize/2,radius:n.roomSize/2,fill:i,strokeWidth:n.lineWidth,stroke:r,perfectDrawEnabled:!1}):new g.Rect({x:0,y:0,width:n.roomSize,height:n.roomSize,fill:i,strokeWidth:n.lineWidth,stroke:r,perfectDrawEnabled:!1}),h=(m,p)=>this.emitRoomContextEvent(t.id,m,p);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 p=m.evt;h(p.clientX,p.clientY)});let d,u,l;const y=()=>{l!==void 0&&(this.stage.draggable(l),l=void 0)},R=()=>{d!==void 0&&(window.clearTimeout(d),d=void 0),u=void 0,y()};s.on("touchstart",m=>{if(R(),m.evt.touches&&m.evt.touches.length>1)return;const p=m.evt.touches?.[0];p&&(u={clientX:p.clientX,clientY:p.clientY},l=this.stage.draggable(),this.stage.draggable(!1),d=window.setTimeout(()=>{u&&h(u.clientX,u.clientY),R()},500))}),s.on("touchend",R),s.on("touchmove",m=>{if(!u)return;const p=m.evt.touches?.[0];if(!p){R();return}const f=p.clientX-u.clientX,M=p.clientY-u.clientY,I=f*f+M*M,P=10;if(I>P*P){const T=l;R(),T&&this.stage.startDrag()}}),s.on("touchcancel",R),s.add(a),this.renderSymbol(t,s),this.roomLayer.add(s);const w=[];this.exitRenderer.renderSpecialExits(t).forEach(m=>{this.linkLayer.add(m);const p=m.getClientRect({relativeTo:this.linkLayer}),f={node:m,bounds:p};this.standaloneExitNodes.push(f),this.addStandaloneExitToSpatialIndex(f)}),this.exitRenderer.renderStubs(t).forEach(m=>{this.linkLayer.add(m),w.push(m)}),this.exitRenderer.renderInnerExits(t).forEach(m=>{this.roomLayer.add(m)});const b={room:t,group:s,linkNodes:w};this.roomNodes.set(t.id,b),this.addRoomToSpatialIndex(b)})}scheduleRoomCulling(){this.cullingScheduled||(this.cullingScheduled=!0,window.requestAnimationFrame(()=>{this.cullingScheduled=!1,this.updateRoomCulling()}))}updateRoomCulling(){if(this.roomNodes.size===0&&this.standaloneExitNodes.length===0)return;const e=this.stage.scaleX();if(!e)return;const t=this.stage.position(),s=n.roomSize/2,i=n.cullingBounds,r=i?i.x:0,o=i?i.x+i.width:this.stage.width(),a=i?i.y:0,h=i?i.y+i.height:this.stage.height(),d=Math.min(r,o),u=Math.max(r,o),l=Math.min(a,h),y=Math.max(a,h),R=(d-t.x)/e,w=(u-t.x)/e,b=(l-t.y)/e,m=(y-t.y)/e;let p=!1,f=!1;const M=n.cullingEnabled?n.cullingMode??"indexed":"none",I=R-s,P=w+s,T=b-s,K=m+s;if(this.refreshStandaloneExitBoundsIfNeeded(),M==="none"){this.roomNodes.forEach(x=>{x.group.visible()||(x.group.visible(!0),p=!0),x.linkNodes.forEach(E=>{E.visible()||(E.visible(!0),f=!0)})}),this.standaloneExitNodes.forEach(x=>{const{node:E}=x;E.visible()||(f=!0,E.visible(!0))}),p&&this.roomLayer.batchDraw(),f&&this.linkLayer.batchDraw(),this.visibleRooms=new Set(this.roomNodes.values()),this.visibleStandaloneExitNodes=new Set(this.standaloneExitNodes);return}if(M==="basic"){const x=new Set;this.roomNodes.forEach(v=>{const O=v.room.x-s,C=v.room.x+s,D=v.room.y-s,N=v.room.y+s,z=C>=R&&O<=w&&N>=b&&D<=m;v.group.visible()!==z&&(v.group.visible(z),p=!0),v.linkNodes.forEach(Y=>{Y.visible()!==z&&(Y.visible(z),f=!0)}),z&&x.add(v)});const E=new Set;this.standaloneExitNodes.forEach(v=>{const{node:O,bounds:C}=v,D=C.x,N=C.x+C.width,z=C.y,Y=C.y+C.height,Z=N>=R&&D<=w&&Y>=b&&z<=m;O.visible()!==Z&&(O.visible(Z),f=!0),Z&&E.add(v)}),this.visibleRooms=x,this.visibleStandaloneExitNodes=E,p&&this.roomLayer.batchDraw(),f&&this.linkLayer.batchDraw();return}const pe=this.collectRoomCandidates(I,T,P,K),Q=new Set,U=new Set;pe.forEach(x=>{Q.add(x);const E=x.room.x-s,v=x.room.x+s,O=x.room.y-s,C=x.room.y+s,D=v>=R&&E<=w&&C>=b&&O<=m;x.group.visible()!==D&&(x.group.visible(D),p=!0),x.linkNodes.forEach(N=>{N.visible()!==D&&(N.visible(D),f=!0)}),D&&U.add(x)}),this.visibleRooms.forEach(x=>{Q.has(x)||(x.group.visible()&&(x.group.visible(!1),p=!0),x.linkNodes.forEach(E=>{E.visible()&&(E.visible(!1),f=!0)}))}),this.visibleRooms=U;const me=this.collectStandaloneExitCandidates(I,T,P,K),J=new Set,ee=new Set;me.forEach(x=>{J.add(x);const{node:E,bounds:v}=x,O=v.x,C=v.x+v.width,D=v.y,N=v.y+v.height,z=C>=R&&O<=w&&N>=b&&D<=m;E.visible()!==z&&(E.visible(z),f=!0),z&&ee.add(x)}),this.visibleStandaloneExitNodes.forEach(x=>{const{node:E}=x;!J.has(x)&&E.visible()&&(E.visible(!1),f=!0)}),this.visibleStandaloneExitNodes=ee,p&&this.roomLayer.batchDraw(),f&&this.linkLayer.batchDraw()}clearCurrentRoomOverlay(){this.currentRoomOverlay.forEach(e=>e.destroy()),this.currentRoomOverlay=[],this.positionLayer.batchDraw()}updateCurrentRoomOverlay(e){if(this.clearCurrentRoomOverlay(),e.area!==this.currentArea||e.z!==this.currentZIndex){this.positionLayer.batchDraw();return}const t=new Map;t.set(e.id,e);const s=[],i=this.currentAreaInstance instanceof B?this.currentAreaInstance:void 0;this.currentAreaInstance&&this.currentZIndex!==void 0&&this.currentAreaInstance.getLinkExits(this.currentZIndex).filter(h=>h.a===e.id||h.b===e.id).forEach(h=>{const d=n.highlightCurrentRoom?this.exitRenderer.renderWithColor(h,W,this.currentZIndex):this.exitRenderer.render(h,this.currentZIndex);d&&s.push(d)});const r=n.highlightCurrentRoom?W:void 0;this.exitRenderer.renderSpecialExits(e,r).forEach(a=>{s.push(a)}),(n.highlightCurrentRoom?this.exitRenderer.renderStubs(e,W):this.exitRenderer.renderStubs(e)).forEach(a=>{s.push(a)}),[...Object.values(e.exits),...Object.values(e.specialExits)].forEach(a=>{const h=this.mapReader.getRoom(a),d=!i||i.hasVisitedRoom(a);h&&h.area===this.currentArea&&h.z===this.currentZIndex&&d&&t.set(a,h)}),s.forEach(a=>{this.positionLayer.add(a),this.currentRoomOverlay.push(a)}),t.forEach((a,h)=>{const d=h===e.id,u=this.createOverlayRoomGroup(a,{stroke:d&&n.highlightCurrentRoom?W:n.lineColor});this.positionLayer.add(u),this.currentRoomOverlay.push(u),this.exitRenderer.renderInnerExits(a).forEach(l=>{this.positionLayer.add(l),this.currentRoomOverlay.push(l)})}),this.positionRender&&this.positionRender.moveToTop(),this.positionLayer.batchDraw()}createOverlayRoomGroup(e,t){const s=new g.Group({x:e.x-n.roomSize/2,y:e.y-n.roomSize/2,listening:!1}),i=this.mapReader.getColorValue(e.env),r=t.stroke,o=n.roomShape==="circle"?new g.Circle({x:n.roomSize/2,y:n.roomSize/2,radius:n.roomSize/2,fill:i,stroke:r,strokeWidth:n.lineWidth}):new g.Rect({x:0,y:0,width:n.roomSize,height:n.roomSize,fill:i,stroke:r,strokeWidth:n.lineWidth});return s.add(o),this.renderSymbol(e,s),s}renderSymbol(e,t){if(e.roomChar!==void 0){const s=n.roomSize*.75,i=new g.Text({x:0,y:0,text:e.roomChar,fontSize:s,fontStyle:"bold",fill:this.mapReader.getSymbolColor(e.env),align:"center",verticalAlign:"middle",width:n.roomSize,height:n.roomSize});t.add(i)}}renderExits(e){e.forEach(t=>{const s=this.exitRenderer.render(t,this.currentZIndex);if(!s)return;this.linkLayer.add(s);const i=s.getClientRect({relativeTo:this.linkLayer}),r={node:s,bounds:i};this.standaloneExitNodes.push(r),this.addStandaloneExitToSpatialIndex(r)}),this.standaloneExitBoundsRoomSize=n.roomSize}renderLabels(e){e.forEach(t=>{if(n.labelRenderMode==="image"){if(!t.pixMap)return;const s=new Image;s.src=`data:image/png;base64,${t.pixMap}`;const i=new g.Image({x:t.X,y:-t.Y,width:t.Width,height:t.Height,image:s,listening:!1});this.linkLayer.add(i);return}this.renderLabelAsData(t)})}renderLabelAsData(e){const t=new g.Group({listening:!1}),s=new g.Rect({x:e.X,y:-e.Y,width:e.Width,height:e.Height,listening:!1});(e.BgColor?.alpha??0)>0&&!n.transparentLabels?s.fill(this.getLabelColor(e.BgColor)):s.fillEnabled(!1),t.add(s);const i=Math.min(.75,e.Width/Math.max(e.Text.length/2,1)),r=Math.max(.1,Math.min(i,Math.max(e.Height*.9,.1))),o=new g.Text({x:e.X,y:-e.Y,width:e.Width,height:e.Height,text:e.Text,fontSize:r,fillEnabled:!0,fill:this.getLabelColor(e.FgColor),align:"center",verticalAlign:"middle",listening:!1});t.add(o),this.linkLayer.add(t)}getLabelColor(e){const t=(e?.alpha??255)/255,s=i=>Math.min(255,Math.max(0,i??0));return`rgba(${s(e?.r)}, ${s(e?.g)}, ${s(e?.b)}, ${t})`}}const re={rgbValue:"rgb(114, 1, 0)",symbolColor:[225,225,225]};function oe(c){const e=c[0]/255,t=c[1]/255,s=c[2]/255,i=Math.max(e,t,s),r=Math.min(e,t,s);return(i+r)/2}class Me{constructor(e,t){this.rooms={},this.areas={},this.areaSources={},this.explorationEnabled=!1,this.colors={},e.forEach(s=>{s.rooms.forEach(r=>{r.y=-r.y,this.rooms[r.id]=r});const i=parseInt(s.areaId);this.areas[i]=new _(s),this.areaSources[i]=s}),this.colors=t.reduce((s,i)=>({...s,[i.envId]:{rgb:i.colors,rgbValue:`rgb(${i.colors.join(",")})`,symbolColor:oe(i.colors)>.41?[25,25,25]:[225,255,255],symbolColorValue:oe(i.colors)>.41?"rgb(25,25,25)":"rgb(225,255,255)"}}),{})}getArea(e){return this.areas[e]}getExplorationArea(e){const t=this.areas[e];if(t instanceof B)return t}getAreas(){return Object.values(this.areas)}getRooms(){return Object.values(this.rooms)}getRoom(e){return this.rooms[e]}ensureVisitedRooms(){return this.visitedRooms||(this.visitedRooms=new Set),this.visitedRooms}applyExplorationDecoration(){this.visitedRooms&&Object.entries(this.areaSources).forEach(([e,t])=>{const s=parseInt(e,10);this.areas[s]=new B(t,this.visitedRooms)})}decorateWithExploration(e){return e!==void 0?this.setVisitedRooms(e):this.ensureVisitedRooms(),this.applyExplorationDecoration(),this.explorationEnabled=!0,this.visitedRooms}getVisitedRooms(){return this.visitedRooms}clearExplorationDecoration(){Object.entries(this.areaSources).forEach(([e,t])=>{const s=parseInt(e,10);this.areas[s]=new _(t)}),this.explorationEnabled=!1}isExplorationEnabled(){return this.explorationEnabled}setVisitedRooms(e){return this.visitedRooms=e instanceof Set?e:new Set(e),this.explorationEnabled&&this.applyExplorationDecoration(),this.visitedRooms}addVisitedRoom(e){if(this.explorationEnabled){const i=this.getRoom(e);if(i){const r=this.getExplorationArea(i.area);if(r)return r.addVisitedRoom(e)}}const t=this.ensureVisitedRooms(),s=t.has(e);return t.add(e),!s}addVisitedRooms(e){const t=this.ensureVisitedRooms();let s=0;for(const i of e){if(this.explorationEnabled){const o=this.getRoom(i);if(o){const a=this.getExplorationArea(o.area);if(a){a.addVisitedRoom(i)&&s++;continue}}}const r=t.has(i);t.add(i),r||s++}return s}hasVisitedRoom(e){return this.visitedRooms?.has(e)??!1}getColorValue(e){return this.colors[e]?.rgbValue??re.rgbValue}getSymbolColor(e,t){const s=this.colors[e]?.symbolColor??re.symbolColor,i=Math.min(Math.max(t??1,0),1),r=s.join(",");return i!=1?`rgba(${r}, ${i})`:`rgba(${r})`}}function Ce(c){return c&&c.__esModule&&Object.prototype.hasOwnProperty.call(c,"default")?c.default:c}var F,ne;function De(){if(ne)return F;ne=1;class c{constructor(){this.keys=new Set,this.queue=[]}sort(){this.queue.sort((t,s)=>t.priority-s.priority)}set(t,s){const i=Number(s);if(isNaN(i))throw new TypeError('"priority" must be a number');return this.keys.has(t)?this.queue.map(r=>(r.key===t&&Object.assign(r,{priority:i}),r)):(this.keys.add(t),this.queue.push({key:t,priority:i})),this.sort(),this.queue.length}next(){const t=this.queue.shift();return this.keys.delete(t.key),t}isEmpty(){return this.queue.length===0}has(t){return this.keys.has(t)}get(t){return this.queue.find(s=>s.key===t)}}return F=c,F}var $,ae;function ze(){if(ae)return $;ae=1;function c(e,t){const s=new Map;for(const[i,r]of e)i!==t&&r instanceof Map?s.set(i,c(r,t)):i!==t&&s.set(i,r);return s}return $=c,$}var j,he;function Ie(){if(he)return j;he=1;function c(t){const s=Number(t);return!(isNaN(s)||s<=0)}function e(t){const s=new Map;return Object.keys(t).forEach(r=>{const o=t[r];if(o!==null&&typeof o=="object"&&!Array.isArray(o))return s.set(r,e(o));if(!c(o))throw new Error(`Could not add node at key "${r}", make sure it's a valid node`,o);return s.set(r,Number(o))}),s}return j=e,j}var q,le;function Le(){if(le)return q;le=1;function c(e){if(!(e instanceof Map))throw new Error(`Invalid graph: Expected Map instead found ${typeof e}`);e.forEach((t,s)=>{if(typeof t=="object"&&t instanceof Map){c(t);return}if(typeof t!="number"||t<=0)throw new Error(`Values must be numbers greater than 0. Found value ${t} at ${s}`)})}return q=c,q}var G,ce;function Oe(){if(ce)return G;ce=1;const c=De(),e=ze(),t=Ie(),s=Le();class i{constructor(o){o instanceof Map?(s(o),this.graph=o):o?this.graph=t(o):this.graph=new Map}addNode(o,a){let h;return a instanceof Map?(s(a),h=a):h=t(a),this.graph.set(o,h),this}addVertex(o,a){return this.addNode(o,a)}removeNode(o){return this.graph=e(this.graph,o),this}path(o,a,h={}){if(!this.graph.size)return h.cost?{path:null,cost:0}:null;const d=new Set,u=new c,l=new Map;let y=[],R=0,w=[];if(h.avoid&&(w=[].concat(h.avoid)),w.includes(o))throw new Error(`Starting node (${o}) cannot be avoided`);if(w.includes(a))throw new Error(`Ending node (${a}) cannot be avoided`);for(u.set(o,0);!u.isEmpty();){const b=u.next();if(b.key===a){R=b.priority;let p=b.key;for(;l.has(p);)y.push(p),p=l.get(p);break}d.add(b.key),(this.graph.get(b.key)||new Map).forEach((p,f)=>{if(d.has(f)||w.includes(f))return null;if(!u.has(f))return l.set(f,b.key),u.set(f,b.priority+p);const M=u.get(f).priority,I=b.priority+p;return I<M?(l.set(f,b.key),u.set(f,I)):null})}return y.length?(h.trim?y.shift():y=y.concat([o]),h.reverse||(y=y.reverse()),h.cost?{path:y,cost:R}:y):h.cost?{path:null,cost:0}:null}shortestPath(...o){return this.path(...o)}}return G=i,G}var Ne=Oe();const Pe=Ce(Ne),Ve={1:"north",2:"northeast",3:"northwest",4:"east",5:"west",6:"south",7:"southeast",8:"southwest",9:"up",10:"down",11:"in",12:"out"};class Ae{constructor(e){this.cache=new Map,this.mapReader=e,this.graph=this.buildGraph()}buildGraph(){const e={};return this.mapReader.getRooms().forEach(t=>{const s={},i=new Set((t.exitLocks??[]).map(o=>Ve[o]).filter(o=>!!o)),r=new Set(t.mSpecialExitLocks??[]);Object.entries(t.exits??{}).forEach(([o,a])=>{i.has(o)||this.mapReader.getRoom(a)&&(s[a.toString()]=1)}),Object.values(t.specialExits??{}).forEach(o=>{r.has(o)||this.mapReader.getRoom(o)&&(s[o.toString()]=1)}),e[t.id.toString()]=s}),new Pe(e)}findPath(e,t){const s=`${e}->${t}`;if(this.cache.has(s))return this.cache.get(s);if(e===t){const a=this.mapReader.getRoom(e)?[e]:null;return this.cache.set(s,a),a}if(!this.mapReader.getRoom(e)||!this.mapReader.getRoom(t))return this.cache.set(s,null),null;const i=this.graph.path(e.toString(),t.toString()),r=Array.isArray(i)?i:i?.path,o=r?r.map(a=>Number(a)):null;return this.cache.set(s,o),o}}exports.ExplorationArea=B;exports.MapReader=Me;exports.PathFinder=Ae;exports.Renderer=ke;exports.Settings=n;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const m=require("konva"),te=["north","south","east","west","northeast","northwest","southeast","southwest"],L={north:"n",south:"s",east:"e",west:"w",northeast:"ne",northwest:"nw",southeast:"se",southwest:"sw",up:"u",down:"d",in:"i",out:"o"},H={north:{x:0,y:-1},south:{x:0,y:1},east:{x:1,y:0},west:{x:-1,y:0},northeast:{x:1,y:-1},northwest:{x:-1,y:-1},southeast:{x:1,y:1},southwest:{x:-1,y:1}},se=["north","south","east","west","northeast","northwest","southeast","southwest"],me={north:"south",south:"north",east:"west",west:"east",northeast:"southwest",northwest:"southeast",southeast:"northwest",southwest:"northeast"};function de(c){return c?Object.prototype.hasOwnProperty.call(H,c):!1}function S(c,e,t,s=1){if(!de(t))return{x:c,y:e};const i=H[t];return{x:c+i.x*s,y:e+i.y*s}}function fe(c,e,t,s=1){if(!de(t))return{x:c,y:e};const i=H[t],r=Math.atan2(i.y,i.x);return{x:c+Math.cos(r)*s,y:e+Math.sin(r)*s}}const V={OPEN_DOOR:"rgb(10, 155, 10)",CLOSED_DOOR:"rgb(226, 205, 59)",LOCKED_DOOR:"rgb(155, 10, 10)",ONE_WAY_FILL:"rgb(155, 10, 10)"},xe={1:"north",2:"northeast",3:"northwest",4:"east",5:"west",6:"south",7:"southeast",8:"southwest",9:"up",10:"down",11:"in",12:"out"},ye=["up","down","in","out"];function Re(c){switch(c){case 1:return V.OPEN_DOOR;case 2:return V.CLOSED_DOOR;default:return V.LOCKED_DOOR}}class be{constructor(e,t){this.mapReader=e,this.mapRenderer=t}getRoomEdgePoint(e,t,s,i){return n.roomShape==="circle"?fe(e,t,s,i):S(e,t,s,i)}render(e,t){return this.renderWithColor(e,n.lineColor,t)}renderWithColor(e,t,s){return e.aDir&&e.bDir?this.renderTwoWayExit(e,t,s):this.renderOneWayExit(e,t)}renderTwoWayExit(e,t,s){const i=this.mapReader.getRoom(e.a),r=this.mapReader.getRoom(e.b);if(!i||!r||!e.aDir||!e.bDir||!te.includes(e.aDir)||!te.includes(e.bDir)||i.customLines[L[e.aDir]]&&r.customLines[L[e.bDir]]||i.z!==r.z&&(s!==r.z&&i.customLines[L[e.aDir]]||s!==i.z&&r.customLines[L[e.bDir]]))return;const o=new m.Group,a=[];if(a.push(...Object.values(this.getRoomEdgePoint(i.x,i.y,e.aDir,n.roomSize/2))),a.push(...Object.values(this.getRoomEdgePoint(r.x,r.y,e.bDir,n.roomSize/2))),i.doors[L[e.aDir]]||r.doors[L[e.bDir]]){const d=this.renderDoor(a,i.doors[L[e.aDir]]??r.doors[L[e.bDir]]);o.add(d)}const h=new m.Line({points:a,stroke:t,strokeWidth:n.lineWidth,perfectDrawEnabled:!1});return o.add(h),o}renderOneWayExit(e,t){const s=e.aDir?this.mapReader.getRoom(e.a):this.mapReader.getRoom(e.b),i=e.aDir?this.mapReader.getRoom(e.b):this.mapReader.getRoom(e.a),r=e.aDir?e.aDir:e.bDir;if(!r||!s||!i||s.customLines[L[r]||r])return;if(s.area!=i.area&&r)return this.renderAreaExit(s,r,t);let o={x:i.x,y:i.y};(i.area!==s.area||i.z!==s.z)&&(o=S(s.x,s.y,r,n.roomSize/2));const a=S(s.x,s.y,r,.3),h=a.x-(a.x-o.x)/2,d=a.y-(a.y-o.y)/2,u=new m.Group,l=[];l.push(...Object.values(this.getRoomEdgePoint(s.x,s.y,r,n.roomSize/2))),l.push(o.x,o.y);const y=new m.Line({points:l,stroke:t,strokeWidth:n.lineWidth,dashEnabled:!0,dash:[.1,.05],perfectDrawEnabled:!1});u.add(y);const R=new m.Arrow({points:[l[0],l[1],h,d],pointerLength:.5,pointerWidth:.35,strokeWidth:n.lineWidth*1.4,stroke:t,fill:V.ONE_WAY_FILL,dashEnabled:!0,dash:[.1,.05]});return u.add(R),u}renderAreaExit(e,t,s){const i=this.getRoomEdgePoint(e.x,e.y,t,n.roomSize/2),r=S(e.x,e.y,t,n.roomSize*1.5),o=s??this.mapReader.getColorValue(e.env);return new m.Arrow({points:[i.x,i.y,r.x,r.y],pointerLength:.3,pointerWidth:.3,strokeWidth:n.lineWidth*1.4,stroke:o,fill:o})}renderSpecialExits(e,t){return Object.entries(e.customLines).map(([s,i])=>{const r=[e.x,e.y];i.points.reduce((u,l)=>(u.push(l.x,-l.y),u),r);const o=i.attributes.arrow?m.Arrow:m.Line,a=t??`rgb(${i.attributes.color.r}, ${i.attributes.color.g}, ${i.attributes.color.b})`,h=new o({points:r,strokeWidth:n.lineWidth,stroke:a,fill:t??`rgb(${i.attributes.color.r}, ${i.attributes.color.g} , ${i.attributes.color.b})`,pointerLength:.3,pointerWidth:.2,perfectDrawEnabled:!1});let d=i.attributes.style;return d==="dot line"?(h.dash([.05,.05]),h.dashOffset(.1)):d==="dash line"?h.dash([.4,.2]):d==="solid line"||d!==void 0&&console.log("Brak opisu stylu: "+d),h})}renderStubs(e,t=n.lineColor){return e.stubs.map(s=>{const i=xe[s],r=this.getRoomEdgePoint(e.x,e.y,i,n.roomSize/2),o=S(e.x,e.y,i,n.roomSize/2+.5),a=[r.x,r.y,o.x,o.y];return new m.Line({points:a,stroke:t,strokeWidth:n.lineWidth})})}renderInnerExits(e){return ye.map(t=>{if(e.exits[t]){const s=new m.Group,i=new m.RegularPolygon({x:e.x,y:e.y,sides:3,fill:this.mapReader.getSymbolColor(e.env,.6),stroke:this.mapReader.getSymbolColor(e.env),strokeWidth:n.lineWidth,radius:n.roomSize/5,scaleX:1.4,scaleY:.8,perfectDrawEnabled:!1});s.add(i);let r=e.doors[t];if(r!==void 0)switch(r){case 1:i.stroke(V.OPEN_DOOR);break;case 2:i.stroke(V.CLOSED_DOOR);break;default:i.stroke(V.LOCKED_DOOR)}switch(t){case"up":i.position(S(e.x,e.y,"south",n.roomSize/4));break;case"down":i.rotation(180),i.position(S(e.x,e.y,"north",n.roomSize/4));break;case"in":const o=i.clone();o.rotation(-90),o.position(S(e.x,e.y,"east",n.roomSize/4)),s.add(o),i.rotation(90),i.position(S(e.x,e.y,"west",n.roomSize/4));break;case"out":const a=i.clone();a.rotation(90),a.position(S(e.x,e.y,"east",n.roomSize/4)),s.add(a),i.rotation(-90),i.position(S(e.x,e.y,"west",n.roomSize/4));break}return s}}).filter(t=>t!==void 0)}renderDoor(e,t){const s={x:e[0]+(e[2]-e[0])/2,y:e[1]+(e[3]-e[1])/2};return new m.Rect({x:s.x-n.roomSize/4,y:s.y-n.roomSize/4,width:n.roomSize/2,height:n.roomSize/2,stroke:Re(t),strokeWidth:n.lineWidth})}}class ue{constructor(e,t){this.rooms=[],this.labels=[],this.rooms=e,this.bounds=this.createBounds(),this.labels=t}getRooms(){return this.rooms}getLabels(){return this.labels}getBounds(){return this.bounds}createBounds(){return this.rooms.reduce((e,t)=>({minX:Math.min(e.minX,t.x),maxX:Math.max(e.maxX,t.x),minY:Math.min(e.minY,t.y),maxY:Math.max(e.maxY,t.y)}),{minX:Number.POSITIVE_INFINITY,maxX:Number.NEGATIVE_INFINITY,minY:Number.POSITIVE_INFINITY,maxY:Number.NEGATIVE_INFINITY})}}class _{constructor(e){this.planes={},this.exits=new Map,this.version=0,this.area=e,this.planes=this.createPlanes(),this.createExits()}getAreaName(){return this.area.areaName}getAreaId(){return parseInt(this.area.areaId)}getVersion(){return this.version}markDirty(){this.version++}getPlane(e){return this.planes[e]}getPlanes(){return Object.values(this.planes)}getRooms(){return this.area.rooms}getLinkExits(e){return Array.from(this.exits.values()).filter(t=>t.zIndex.includes(e))}createPlanes(){const e=this.area.rooms.reduce((t,s)=>(t[s.z]||(t[s.z]=[]),t[s.z].push(s),t),{});return Object.entries(e).reduce((t,[s,i])=>(t[+s]=new ue(i,this.area.labels.filter(r=>r.Z===+s)),t),{})}createExits(){this.area.rooms.forEach(e=>{Object.entries(e.specialExits).forEach(([t,s])=>this.createHalfExit(e.id,s,e.z,t)),Object.entries(e.exits).forEach(([t,s])=>this.createHalfExit(e.id,s,e.z,t))})}createHalfExit(e,t,s,i){if(e===t)return;const r=Math.min(e,t),o=Math.max(e,t),a=`${r}-${o}`;let h=this.exits.get(a);h||(h={a:r,b:o,zIndex:[s]}),r==e?h.aDir=i:h.bDir=i,h.zIndex.push(s),this.exits.set(a,h)}}class ie extends ue{constructor(e,t){super(e.getRooms(),e.getLabels()),this.basePlane=e,this.visitedRooms=t}getRooms(){return this.basePlane.getRooms().filter(e=>this.visitedRooms.has(e.id))}getLabels(){return this.basePlane.getLabels()}getBounds(){const e=this.getRooms();return e.length?e.reduce((t,s)=>({minX:Math.min(t.minX,s.x),maxX:Math.max(t.maxX,s.x),minY:Math.min(t.minY,s.y),maxY:Math.max(t.maxY,s.y)}),{minX:Number.POSITIVE_INFINITY,maxX:Number.NEGATIVE_INFINITY,minY:Number.POSITIVE_INFINITY,maxY:Number.NEGATIVE_INFINITY}):this.basePlane.getBounds()}}class B extends _{constructor(e,t){super(e),this.planeCache=new WeakMap,this.visitedRooms=t instanceof Set?t:new Set(t??[]),this.areaRoomIds=new Set(e.rooms.map(s=>s.id))}getPlane(e){const t=super.getPlane(e);if(!t)return t;let s=this.planeCache.get(t);return s||(s=new ie(t,this.visitedRooms),this.planeCache.set(t,s)),s}getPlanes(){return super.getPlanes().map(e=>{let t=this.planeCache.get(e);return t||(t=new ie(e,this.visitedRooms),this.planeCache.set(e,t)),t})}getLinkExits(e){return super.getLinkExits(e).filter(t=>this.visitedRooms.has(t.a)||this.visitedRooms.has(t.b))}getVisitedRoomCount(){return super.getRooms().reduce((e,t)=>e+(this.visitedRooms.has(t.id)?1:0),0)}getTotalRoomCount(){return this.areaRoomIds.size}hasVisitedRoom(e){return this.areaRoomIds.has(e)&&this.visitedRooms.has(e)}getVisitedRoomIds(){return super.getRooms().filter(e=>this.visitedRooms.has(e.id)).map(e=>e.id)}addVisitedRoom(e){const t=this.visitedRooms.has(e);this.visitedRooms.add(e);const s=!t&&this.areaRoomIds.has(e);return s&&this.markDirty(),s}addVisitedRooms(e){let t=0;for(const s of e){const i=this.visitedRooms.has(s);this.visitedRooms.add(s),!i&&this.areaRoomIds.has(s)&&t++}return t>0&&this.markDirty(),t}}class we{constructor(e,t){this.paths=[],this.mapReader=e,this.overlayLayer=t}renderPath(e,t,s,i="#66E64D"){if(t===void 0||s===void 0)return;const r=e.map(l=>this.mapReader.getRoom(l)).filter(l=>l!==void 0),o=[];let a=null;const h=()=>{a&&(a.length<4&&o.pop(),a=null)},d=()=>(a||(a=[],o.push(a)),a);r.forEach((l,y)=>{if(!this.isRoomVisible(l,t,s))return;const R=y>0?r[y-1]:void 0,w=y<r.length-1?r[y+1]:void 0;if(this.isRoomVisible(R,t,s))d();else{h();const p=d();if(R){const f=this.getDirectionTowards(l,R);if(f){const M=S(l.x,l.y,f,n.roomSize);p.push(M.x,M.y)}}}if(a?.push(l.x,l.y),!this.isRoomVisible(w,t,s)&&w){const p=this.getDirectionTowards(l,w);if(p){const f=S(l.x,l.y,p,n.roomSize);a?.push(f.x,f.y)}h()}}),h();const u=o.filter(l=>l.length>=4).map(l=>new m.Line({points:l,stroke:i,strokeWidth:n.lineWidth*4}));return u.forEach(l=>{this.overlayLayer.add(l),this.paths.push(l)}),u[0]}clearPaths(){this.paths.forEach(e=>{e.destroy()}),this.paths=[]}isRoomVisible(e,t,s){return e?e.area===t&&e.z===s:!1}getDirectionTowards(e,t){for(const s of se)if(e.exits[s]===t.id)return s;for(const s of se)if(t.exits[s]===e.id)return me[s]}}const ve=.6,A=75,Ee=.025,Se="rgb(225, 255, 225)",W="rgb(120, 72, 0)";function X(c,e){const t=parseInt(c.slice(1,3),16),s=parseInt(c.slice(3,5),16),i=parseInt(c.slice(5,7),16);return`rgba(${t}, ${s}, ${i}, ${e})`}const k=class k{};k.roomSize=ve,k.lineWidth=Ee,k.lineColor=Se,k.instantMapMove=!1,k.highlightCurrentRoom=!0,k.cullingEnabled=!0,k.cullingMode="indexed",k.cullingBounds=null,k.labelRenderMode="image",k.roomShape="rectangle",k.playerMarker={strokeColor:"#00e5b2",strokeAlpha:1,fillColor:"#00e5b2",fillAlpha:0,strokeWidth:.1,sizeFactor:1.7,dash:[.05,.05],dashEnabled:!0};let n=k;class ke{constructor(e,t){this.highlights=new Map,this.currentZoom=1,this.currentRoomOverlay=[],this.roomNodes=new Map,this.centerOnResize=!0,this.standaloneExitNodes=[],this.spatialBucketSize=5,this.roomSpatialIndex=new Map,this.exitSpatialIndex=new Map,this.visibleRooms=new Set,this.visibleStandaloneExitNodes=new Set,this.cullingScheduled=!1,this.stage=new m.Stage({container:e,width:e.clientWidth,height:e.clientHeight,draggable:!0}),window.addEventListener("resize",()=>{this.onResize(e)}),e.addEventListener("resize",()=>{this.onResize(e)}),this.linkLayer=new m.Layer({listening:!1}),this.stage.add(this.linkLayer),this.roomLayer=new m.Layer,this.stage.add(this.roomLayer),this.positionLayer=new m.Layer({listening:!1}),this.stage.add(this.positionLayer),this.overlayLayer=new m.Layer({listening:!1}),this.stage.add(this.overlayLayer),this.mapReader=t,this.exitRenderer=new be(t,this),this.pathRenderer=new we(t,this.overlayLayer),this.initScaling(1.1),this.stage.on("dragmove",()=>this.scheduleRoomCulling()),this.stage.on("dragend",()=>this.scheduleRoomCulling())}onResize(e){this.stage.width(e.clientWidth),this.stage.height(e.clientHeight),this.centerOnResize&&this.currentRoomId&&this.centerOnRoom(this.mapReader.getRoom(this.currentRoomId),!1),this.stage.batchDraw(),this.scheduleRoomCulling()}initScaling(e){m.hitOnDragEnabled=!0;let t,s=!1,i=!1;this.stage.on("touchstart",r=>{const o=r.evt.touches;o&&o.length>1?(i=!0,this.stage.isDragging()&&(this.stage.stopDrag(),s=!0),this.stage.draggable(!1)):(i=!1,this.stage.draggable(!0))}),this.stage.on("touchend touchcancel",r=>{t=void 0;const o=r.evt.touches;(!o||o.length<=1)&&(i=!1,this.stage.draggable(!0))}),this.stage.on("wheel",r=>{r.evt.preventDefault();const o=this.stage.scaleX(),a=this.stage.getPointerPosition();if(!a)return;const h={x:(a.x-this.stage.x())/o,y:(a.y-this.stage.y())/o};let d=r.evt.deltaY>0?-1:1;r.evt.ctrlKey&&(d=-d);const u=d>0?this.currentZoom*e:this.currentZoom/e,l=u*A,y=this.setZoom(u),R={x:a.x-h.x*l,y:a.y-h.y*l};this.stage.position(R),this.scheduleRoomCulling(),y&&this.emitZoomChangeEvent()}),this.stage.on("touchmove",r=>{const o=r.evt.touches,a=o?.[0],h=o?.[1];if(h||i&&(i=!1,this.stage.draggable(!0)),a&&!h&&s&&!this.stage.isDragging()&&(this.stage.startDrag(),s=!1),!a||!h){t=void 0;return}r.evt.preventDefault(),this.stage.isDragging()&&(this.stage.stopDrag(),s=!0),i||(i=!0,this.stage.draggable(!1));const d=this.stage.container().getBoundingClientRect(),u={x:a.clientX-d.left,y:a.clientY-d.top},l={x:h.clientX-d.left,y:h.clientY-d.top},y=Math.hypot(u.x-l.x,u.y-l.y);if(t===void 0){t=y;return}if(t===0)return;const R=this.stage.scaleX(),w=this.stage.x(),b=this.stage.y(),g={x:this.stage.width()/2,y:this.stage.height()/2},p={x:(g.x-w)/R,y:(g.y-b)/R},f=this.currentZoom*(y/t),M=this.setZoom(f),I=this.stage.scaleX(),N={x:g.x-p.x*I,y:g.y-p.y*I};this.stage.position(N),this.stage.batchDraw(),this.scheduleRoomCulling(),t=y,M&&this.emitZoomChangeEvent()})}drawArea(e,t){const s=this.mapReader.getArea(e);if(!s)return;const i=s.getPlane(t);i&&(this.currentArea=e,this.currentAreaInstance=s,this.currentZIndex=t,this.currentAreaVersion=s.getVersion(),this.clearCurrentRoomOverlay(),this.roomLayer.destroyChildren(),this.linkLayer.destroyChildren(),this.roomNodes.clear(),this.standaloneExitNodes=[],this.standaloneExitBoundsRoomSize=void 0,this.roomSpatialIndex.clear(),this.exitSpatialIndex.clear(),this.visibleRooms.clear(),this.visibleStandaloneExitNodes.clear(),this.spatialBucketSize=this.computeSpatialBucketSize(),this.stage.scale({x:A*this.currentZoom,y:A*this.currentZoom}),this.renderLabels(i.getLabels()),this.renderExits(s.getLinkExits(t)),this.renderRooms(i.getRooms()??[]),this.refreshHighlights(),this.stage.batchDraw(),this.scheduleRoomCulling())}computeSpatialBucketSize(){return Math.max(n.roomSize*10,5)}getBucketKey(e,t){return`${e},${t}`}forEachBucket(e,t,s,i,r){const o=this.spatialBucketSize,a=Math.min(e,s),h=Math.max(e,s),d=Math.min(t,i),u=Math.max(t,i),l=Math.floor(a/o),y=Math.floor(h/o),R=Math.floor(d/o),w=Math.floor(u/o);for(let b=l;b<=y;b++)for(let g=R;g<=w;g++)r(this.getBucketKey(b,g))}addRoomToSpatialIndex(e){const t=n.roomSize/2,s=e.room.x-t,i=e.room.x+t,r=e.room.y-t,o=e.room.y+t;this.forEachBucket(s,r,i,o,a=>{let h=this.roomSpatialIndex.get(a);h||(h=new Set,this.roomSpatialIndex.set(a,h)),h.add(e)})}addStandaloneExitToSpatialIndex(e){const{bounds:t}=e,s=t.x,i=t.x+t.width,r=t.y,o=t.y+t.height;this.forEachBucket(s,r,i,o,a=>{let h=this.exitSpatialIndex.get(a);h||(h=new Set,this.exitSpatialIndex.set(a,h)),h.add(e)})}collectRoomCandidates(e,t,s,i){const r=new Set;return this.forEachBucket(e,t,s,i,o=>{this.roomSpatialIndex.get(o)?.forEach(h=>r.add(h))}),r}collectStandaloneExitCandidates(e,t,s,i){const r=new Set;return this.forEachBucket(e,t,s,i,o=>{this.exitSpatialIndex.get(o)?.forEach(h=>r.add(h))}),r}refreshStandaloneExitBoundsIfNeeded(){this.standaloneExitBoundsRoomSize!==n.roomSize&&(this.exitSpatialIndex.clear(),this.standaloneExitNodes.forEach(e=>{e.bounds=e.node.getClientRect({relativeTo:this.linkLayer}),this.addStandaloneExitToSpatialIndex(e)}),this.standaloneExitBoundsRoomSize=n.roomSize)}emitRoomContextEvent(e,t,s){const i=this.stage.container(),r=i.getBoundingClientRect(),o={roomId:e,position:{x:t-r.left,y:s-r.top}},a=new CustomEvent("roomcontextmenu",{detail:o});i.dispatchEvent(a)}emitZoomChangeEvent(){const e=new CustomEvent("zoom",{detail:{zoom:this.currentZoom}});this.stage.container().dispatchEvent(e)}setZoom(e){return this.currentZoom===e?!1:(this.currentZoom=e,this.stage.scale({x:A*e,y:A*e}),this.scheduleRoomCulling(),!0)}zoomToCenter(e){if(this.currentZoom===e)return!1;const t=this.stage.scaleX(),s=this.stage.width(),i=this.stage.height(),r=s/2,o=i/2,a={x:(r-this.stage.x())/t,y:(o-this.stage.y())/t};this.currentZoom=e;const h=A*e;this.stage.scale({x:h,y:h});const d={x:r-a.x*h,y:o-a.y*h};return this.stage.position(d),this.stage.batchDraw(),this.scheduleRoomCulling(),!0}getZoom(){return this.currentZoom}setCullingMode(e){n.cullingMode=e,n.cullingEnabled=e!=="none",this.scheduleRoomCulling()}getCullingMode(){return n.cullingMode}getCurrentArea(){return this.currentArea?this.mapReader.getArea(this.currentArea):void 0}refreshCurrentRoomOverlay(){if(this.currentRoomId!==void 0){const e=this.mapReader.getRoom(this.currentRoomId);e&&this.updateCurrentRoomOverlay(e)}}refresh(){this.currentRoomId!==void 0&&this.currentArea!==void 0&&this.currentZIndex!==void 0&&(this.drawArea(this.currentArea,this.currentZIndex),this.setPosition(this.currentRoomId))}updatePositionMarker(e){const t=this.mapReader.getRoom(e);if(!t)return;if(t.area!==this.currentArea||t.z!==this.currentZIndex){this.positionRender&&(this.positionRender.hide(),this.positionLayer.batchDraw());return}this.currentRoomId=e,this.updateCurrentRoomOverlay(t);const s=X(n.playerMarker.strokeColor,n.playerMarker.strokeAlpha),i=X(n.playerMarker.fillColor,n.playerMarker.fillAlpha),r=n.roomSize/2*n.playerMarker.sizeFactor;this.positionRender?(this.positionRender.position({x:t.x,y:t.y}),this.positionRender.radius(r),this.positionRender.stroke(s),this.positionRender.fill(i),this.positionRender.strokeWidth(n.playerMarker.strokeWidth),this.positionRender.dash(n.playerMarker.dash??[]),this.positionRender.dashEnabled(n.playerMarker.dashEnabled),this.positionRender.show()):(this.positionRender=new m.Circle({x:t.x,y:t.y,radius:r,stroke:s,fill:i,strokeWidth:n.playerMarker.strokeWidth,dash:n.playerMarker.dash,dashEnabled:n.playerMarker.dashEnabled}),this.positionLayer.add(this.positionRender)),this.positionLayer.batchDraw()}setPosition(e,t=!0){const s=this.mapReader.getRoom(e);if(!s)return;const i=this.mapReader.getArea(s.area),r=i?.getVersion();let o=this.currentArea!==s.area||this.currentZIndex!==s.z;(this.currentArea!==s.area||this.currentZIndex!==s.z||r!==void 0&&this.currentAreaVersion!==r||i!==void 0&&this.currentAreaInstance!==i)&&this.drawArea(s.area,s.z),t?this.centerOnRoom(s,o):this.currentRoomId=e,this.updateCurrentRoomOverlay(s);const a=X(n.playerMarker.strokeColor,n.playerMarker.strokeAlpha),h=X(n.playerMarker.fillColor,n.playerMarker.fillAlpha),d=n.roomSize/2*n.playerMarker.sizeFactor;this.positionRender?(this.positionRender.radius(d),this.positionRender.stroke(a),this.positionRender.fill(h),this.positionRender.strokeWidth(n.playerMarker.strokeWidth),this.positionRender.dash(n.playerMarker.dash??[]),this.positionRender.dashEnabled(n.playerMarker.dashEnabled)):(this.positionRender=new m.Circle({x:s.x,y:s.y,radius:d,stroke:a,fill:h,strokeWidth:n.playerMarker.strokeWidth,dash:n.playerMarker.dash,dashEnabled:n.playerMarker.dashEnabled}),this.positionLayer.add(this.positionRender))}renderPath(e,t){return this.pathRenderer.renderPath(e,this.currentArea,this.currentZIndex,t)}clearPaths(){this.pathRenderer.clearPaths()}renderHighlight(e,t){const s=this.mapReader.getRoom(e);if(!s)return;const i=this.highlights.get(e);i?.shape&&(i.shape.destroy(),delete i.shape);const r={color:t,area:s.area,z:s.z};if(this.highlights.set(e,r),s.area===this.currentArea&&s.z===this.currentZIndex){const o=this.createHighlightShape(s,t);return this.overlayLayer.add(o),r.shape=o,this.overlayLayer.batchDraw(),o}return r.shape}clearHighlights(){this.highlights.forEach(({shape:e})=>e?.destroy()),this.highlights.clear(),this.overlayLayer.batchDraw()}refreshHighlights(){this.highlights.forEach((e,t)=>{if(e.shape?.destroy(),delete e.shape,e.area!==this.currentArea||e.z!==this.currentZIndex)return;const s=this.mapReader.getRoom(t);if(!s)return;const i=this.createHighlightShape(s,e.color);this.overlayLayer.add(i),e.shape=i}),this.overlayLayer.batchDraw()}createHighlightShape(e,t){return n.roomShape==="circle"?new m.Circle({x:e.x,y:e.y,radius:n.roomSize/2*1.5,stroke:t,strokeWidth:.1,dash:[.05,.05],dashEnabled:!0,listening:!1}):new m.Rect({x:e.x-n.roomSize/2*1.5,y:e.y-n.roomSize/2*1.5,width:n.roomSize*1.5,height:n.roomSize*1.5,stroke:t,strokeWidth:.1,dash:[.05,.05],dashEnabled:!0,listening:!1})}centerOnRoom(e,t=!1){this.currentRoomId=e.id;const s={x:e.x,y:e.y};this.positionRender?.position(e);const r=this.stage.getAbsoluteTransform().point(s),o={x:this.stage.width()/2,y:this.stage.height()/2},a=o.x-r.x,h=o.y-r.y;this.currentTransition&&(this.currentTransition.pause(),this.currentTransition.destroy(),delete this.currentTransition),t||n.instantMapMove?(this.stage.position({x:this.stage.x()+a,y:this.stage.y()+h}),this.scheduleRoomCulling()):(this.currentTransition=new m.Tween({node:this.stage,x:this.stage.x()+a,y:this.stage.y()+h,duration:.2,easing:m.Easings.EaseInOut,onUpdate:()=>this.scheduleRoomCulling(),onFinish:()=>this.scheduleRoomCulling()}),this.currentTransition.play())}renderRooms(e){e.forEach(t=>{const s=new m.Group({x:t.x-n.roomSize/2,y:t.y-n.roomSize/2}),i=this.mapReader.getColorValue(t.env),r=n.lineColor,a=n.roomShape==="circle"?new m.Circle({x:n.roomSize/2,y:n.roomSize/2,radius:n.roomSize/2,fill:i,strokeWidth:n.lineWidth,stroke:r,perfectDrawEnabled:!1}):new m.Rect({x:0,y:0,width:n.roomSize,height:n.roomSize,fill:i,strokeWidth:n.lineWidth,stroke:r,perfectDrawEnabled:!1}),h=(g,p)=>this.emitRoomContextEvent(t.id,g,p);s.on("mouseenter",()=>{this.stage.container().style.cursor="pointer"}),s.on("mouseleave",()=>{this.stage.container().style.cursor="auto"}),s.on("contextmenu",g=>{g.evt.preventDefault();const p=g.evt;h(p.clientX,p.clientY)});let d,u,l;const y=()=>{l!==void 0&&(this.stage.draggable(l),l=void 0)},R=()=>{d!==void 0&&(window.clearTimeout(d),d=void 0),u=void 0,y()};s.on("touchstart",g=>{if(R(),g.evt.touches&&g.evt.touches.length>1)return;const p=g.evt.touches?.[0];p&&(u={clientX:p.clientX,clientY:p.clientY},l=this.stage.draggable(),this.stage.draggable(!1),d=window.setTimeout(()=>{u&&h(u.clientX,u.clientY),R()},500))}),s.on("touchend",R),s.on("touchmove",g=>{if(!u)return;const p=g.evt.touches?.[0];if(!p){R();return}const f=p.clientX-u.clientX,M=p.clientY-u.clientY,I=f*f+M*M,N=10;if(I>N*N){const T=l;R(),T&&this.stage.startDrag()}}),s.on("touchcancel",R),s.add(a),this.renderSymbol(t,s),this.roomLayer.add(s);const w=[];this.exitRenderer.renderSpecialExits(t).forEach(g=>{this.linkLayer.add(g);const p=g.getClientRect({relativeTo:this.linkLayer}),f={node:g,bounds:p};this.standaloneExitNodes.push(f),this.addStandaloneExitToSpatialIndex(f)}),this.exitRenderer.renderStubs(t).forEach(g=>{this.linkLayer.add(g),w.push(g)}),this.exitRenderer.renderInnerExits(t).forEach(g=>{this.roomLayer.add(g)});const b={room:t,group:s,linkNodes:w};this.roomNodes.set(t.id,b),this.addRoomToSpatialIndex(b)})}scheduleRoomCulling(){this.cullingScheduled||(this.cullingScheduled=!0,window.requestAnimationFrame(()=>{this.cullingScheduled=!1,this.updateRoomCulling()}))}updateRoomCulling(){if(this.roomNodes.size===0&&this.standaloneExitNodes.length===0)return;const e=this.stage.scaleX();if(!e)return;const t=this.stage.position(),s=n.roomSize/2,i=n.cullingBounds,r=i?i.x:0,o=i?i.x+i.width:this.stage.width(),a=i?i.y:0,h=i?i.y+i.height:this.stage.height(),d=Math.min(r,o),u=Math.max(r,o),l=Math.min(a,h),y=Math.max(a,h),R=(d-t.x)/e,w=(u-t.x)/e,b=(l-t.y)/e,g=(y-t.y)/e;let p=!1,f=!1;const M=n.cullingEnabled?n.cullingMode??"indexed":"none",I=R-s,N=w+s,T=b-s,K=g+s;if(this.refreshStandaloneExitBoundsIfNeeded(),M==="none"){this.roomNodes.forEach(x=>{x.group.visible()||(x.group.visible(!0),p=!0),x.linkNodes.forEach(E=>{E.visible()||(E.visible(!0),f=!0)})}),this.standaloneExitNodes.forEach(x=>{const{node:E}=x;E.visible()||(f=!0,E.visible(!0))}),p&&this.roomLayer.batchDraw(),f&&this.linkLayer.batchDraw(),this.visibleRooms=new Set(this.roomNodes.values()),this.visibleStandaloneExitNodes=new Set(this.standaloneExitNodes);return}if(M==="basic"){const x=new Set;this.roomNodes.forEach(v=>{const O=v.room.x-s,C=v.room.x+s,D=v.room.y-s,P=v.room.y+s,z=C>=R&&O<=w&&P>=b&&D<=g;v.group.visible()!==z&&(v.group.visible(z),p=!0),v.linkNodes.forEach(Y=>{Y.visible()!==z&&(Y.visible(z),f=!0)}),z&&x.add(v)});const E=new Set;this.standaloneExitNodes.forEach(v=>{const{node:O,bounds:C}=v,D=C.x,P=C.x+C.width,z=C.y,Y=C.y+C.height,Z=P>=R&&D<=w&&Y>=b&&z<=g;O.visible()!==Z&&(O.visible(Z),f=!0),Z&&E.add(v)}),this.visibleRooms=x,this.visibleStandaloneExitNodes=E,p&&this.roomLayer.batchDraw(),f&&this.linkLayer.batchDraw();return}const pe=this.collectRoomCandidates(I,T,N,K),Q=new Set,U=new Set;pe.forEach(x=>{Q.add(x);const E=x.room.x-s,v=x.room.x+s,O=x.room.y-s,C=x.room.y+s,D=v>=R&&E<=w&&C>=b&&O<=g;x.group.visible()!==D&&(x.group.visible(D),p=!0),x.linkNodes.forEach(P=>{P.visible()!==D&&(P.visible(D),f=!0)}),D&&U.add(x)}),this.visibleRooms.forEach(x=>{Q.has(x)||(x.group.visible()&&(x.group.visible(!1),p=!0),x.linkNodes.forEach(E=>{E.visible()&&(E.visible(!1),f=!0)}))}),this.visibleRooms=U;const ge=this.collectStandaloneExitCandidates(I,T,N,K),J=new Set,ee=new Set;ge.forEach(x=>{J.add(x);const{node:E,bounds:v}=x,O=v.x,C=v.x+v.width,D=v.y,P=v.y+v.height,z=C>=R&&O<=w&&P>=b&&D<=g;E.visible()!==z&&(E.visible(z),f=!0),z&&ee.add(x)}),this.visibleStandaloneExitNodes.forEach(x=>{const{node:E}=x;!J.has(x)&&E.visible()&&(E.visible(!1),f=!0)}),this.visibleStandaloneExitNodes=ee,p&&this.roomLayer.batchDraw(),f&&this.linkLayer.batchDraw()}clearCurrentRoomOverlay(){this.currentRoomOverlay.forEach(e=>e.destroy()),this.currentRoomOverlay=[],this.positionLayer.batchDraw()}updateCurrentRoomOverlay(e){if(this.clearCurrentRoomOverlay(),e.area!==this.currentArea||e.z!==this.currentZIndex){this.positionLayer.batchDraw();return}const t=new Map;t.set(e.id,e);const s=[],i=this.currentAreaInstance instanceof B?this.currentAreaInstance:void 0;this.currentAreaInstance&&this.currentZIndex!==void 0&&this.currentAreaInstance.getLinkExits(this.currentZIndex).filter(h=>h.a===e.id||h.b===e.id).forEach(h=>{const d=n.highlightCurrentRoom?this.exitRenderer.renderWithColor(h,W,this.currentZIndex):this.exitRenderer.render(h,this.currentZIndex);d&&s.push(d)});const r=n.highlightCurrentRoom?W:void 0;this.exitRenderer.renderSpecialExits(e,r).forEach(a=>{s.push(a)}),(n.highlightCurrentRoom?this.exitRenderer.renderStubs(e,W):this.exitRenderer.renderStubs(e)).forEach(a=>{s.push(a)}),[...Object.values(e.exits),...Object.values(e.specialExits)].forEach(a=>{const h=this.mapReader.getRoom(a),d=!i||i.hasVisitedRoom(a);h&&h.area===this.currentArea&&h.z===this.currentZIndex&&d&&t.set(a,h)}),s.forEach(a=>{this.positionLayer.add(a),this.currentRoomOverlay.push(a)}),t.forEach((a,h)=>{const d=h===e.id,u=this.createOverlayRoomGroup(a,{stroke:d&&n.highlightCurrentRoom?W:n.lineColor});this.positionLayer.add(u),this.currentRoomOverlay.push(u),this.exitRenderer.renderInnerExits(a).forEach(l=>{this.positionLayer.add(l),this.currentRoomOverlay.push(l)})}),this.positionRender&&this.positionRender.moveToTop(),this.positionLayer.batchDraw()}createOverlayRoomGroup(e,t){const s=new m.Group({x:e.x-n.roomSize/2,y:e.y-n.roomSize/2,listening:!1}),i=this.mapReader.getColorValue(e.env),r=t.stroke,o=n.roomShape==="circle"?new m.Circle({x:n.roomSize/2,y:n.roomSize/2,radius:n.roomSize/2,fill:i,stroke:r,strokeWidth:n.lineWidth}):new m.Rect({x:0,y:0,width:n.roomSize,height:n.roomSize,fill:i,stroke:r,strokeWidth:n.lineWidth});return s.add(o),this.renderSymbol(e,s),s}renderSymbol(e,t){if(e.roomChar!==void 0){const s=n.roomSize*.75,i=new m.Text({x:0,y:0,text:e.roomChar,fontSize:s,fontStyle:"bold",fill:this.mapReader.getSymbolColor(e.env),align:"center",verticalAlign:"middle",width:n.roomSize,height:n.roomSize});t.add(i)}}renderExits(e){e.forEach(t=>{const s=this.exitRenderer.render(t,this.currentZIndex);if(!s)return;this.linkLayer.add(s);const i=s.getClientRect({relativeTo:this.linkLayer}),r={node:s,bounds:i};this.standaloneExitNodes.push(r),this.addStandaloneExitToSpatialIndex(r)}),this.standaloneExitBoundsRoomSize=n.roomSize}renderLabels(e){e.forEach(t=>{if(n.labelRenderMode==="image"){if(!t.pixMap)return;const s=new Image;s.src=`data:image/png;base64,${t.pixMap}`;const i=new m.Image({x:t.X,y:-t.Y,width:t.Width,height:t.Height,image:s,listening:!1});this.linkLayer.add(i);return}this.renderLabelAsData(t)})}renderLabelAsData(e){const t=new m.Group({listening:!1}),s=new m.Rect({x:e.X,y:-e.Y,width:e.Width,height:e.Height,listening:!1});(e.BgColor?.alpha??0)>0&&!n.transparentLabels?s.fill(this.getLabelColor(e.BgColor)):s.fillEnabled(!1),t.add(s);const i=Math.min(.75,e.Width/Math.max(e.Text.length/2,1)),r=Math.max(.1,Math.min(i,Math.max(e.Height*.9,.1))),o=new m.Text({x:e.X,y:-e.Y,width:e.Width,height:e.Height,text:e.Text,fontSize:r,fillEnabled:!0,fill:this.getLabelColor(e.FgColor),align:"center",verticalAlign:"middle",listening:!1});t.add(o),this.linkLayer.add(t)}getLabelColor(e){const t=(e?.alpha??255)/255,s=i=>Math.min(255,Math.max(0,i??0));return`rgba(${s(e?.r)}, ${s(e?.g)}, ${s(e?.b)}, ${t})`}}const re={rgbValue:"rgb(114, 1, 0)",symbolColor:[225,225,225]};function oe(c){const e=c[0]/255,t=c[1]/255,s=c[2]/255,i=Math.max(e,t,s),r=Math.min(e,t,s);return(i+r)/2}class Me{constructor(e,t){this.rooms={},this.areas={},this.areaSources={},this.explorationEnabled=!1,this.colors={},e.forEach(s=>{s.rooms.forEach(r=>{r.y=-r.y,this.rooms[r.id]=r});const i=parseInt(s.areaId);this.areas[i]=new _(s),this.areaSources[i]=s}),this.colors=t.reduce((s,i)=>({...s,[i.envId]:{rgb:i.colors,rgbValue:`rgb(${i.colors.join(",")})`,symbolColor:oe(i.colors)>.41?[25,25,25]:[225,255,255],symbolColorValue:oe(i.colors)>.41?"rgb(25,25,25)":"rgb(225,255,255)"}}),{})}getArea(e){return this.areas[e]}getExplorationArea(e){const t=this.areas[e];if(t instanceof B)return t}getAreas(){return Object.values(this.areas)}getRooms(){return Object.values(this.rooms)}getRoom(e){return this.rooms[e]}ensureVisitedRooms(){return this.visitedRooms||(this.visitedRooms=new Set),this.visitedRooms}applyExplorationDecoration(){this.visitedRooms&&Object.entries(this.areaSources).forEach(([e,t])=>{const s=parseInt(e,10);this.areas[s]=new B(t,this.visitedRooms)})}decorateWithExploration(e){return e!==void 0?this.setVisitedRooms(e):this.ensureVisitedRooms(),this.applyExplorationDecoration(),this.explorationEnabled=!0,this.visitedRooms}getVisitedRooms(){return this.visitedRooms}clearExplorationDecoration(){Object.entries(this.areaSources).forEach(([e,t])=>{const s=parseInt(e,10);this.areas[s]=new _(t)}),this.explorationEnabled=!1}isExplorationEnabled(){return this.explorationEnabled}setVisitedRooms(e){return this.visitedRooms=e instanceof Set?e:new Set(e),this.explorationEnabled&&this.applyExplorationDecoration(),this.visitedRooms}addVisitedRoom(e){if(this.explorationEnabled){const i=this.getRoom(e);if(i){const r=this.getExplorationArea(i.area);if(r)return r.addVisitedRoom(e)}}const t=this.ensureVisitedRooms(),s=t.has(e);return t.add(e),!s}addVisitedRooms(e){const t=this.ensureVisitedRooms();let s=0;for(const i of e){if(this.explorationEnabled){const o=this.getRoom(i);if(o){const a=this.getExplorationArea(o.area);if(a){a.addVisitedRoom(i)&&s++;continue}}}const r=t.has(i);t.add(i),r||s++}return s}hasVisitedRoom(e){return this.visitedRooms?.has(e)??!1}getColorValue(e){return this.colors[e]?.rgbValue??re.rgbValue}getSymbolColor(e,t){const s=this.colors[e]?.symbolColor??re.symbolColor,i=Math.min(Math.max(t??1,0),1),r=s.join(",");return i!=1?`rgba(${r}, ${i})`:`rgba(${r})`}}function Ce(c){return c&&c.__esModule&&Object.prototype.hasOwnProperty.call(c,"default")?c.default:c}var F,ne;function De(){if(ne)return F;ne=1;class c{constructor(){this.keys=new Set,this.queue=[]}sort(){this.queue.sort((t,s)=>t.priority-s.priority)}set(t,s){const i=Number(s);if(isNaN(i))throw new TypeError('"priority" must be a number');return this.keys.has(t)?this.queue.map(r=>(r.key===t&&Object.assign(r,{priority:i}),r)):(this.keys.add(t),this.queue.push({key:t,priority:i})),this.sort(),this.queue.length}next(){const t=this.queue.shift();return this.keys.delete(t.key),t}isEmpty(){return this.queue.length===0}has(t){return this.keys.has(t)}get(t){return this.queue.find(s=>s.key===t)}}return F=c,F}var $,ae;function ze(){if(ae)return $;ae=1;function c(e,t){const s=new Map;for(const[i,r]of e)i!==t&&r instanceof Map?s.set(i,c(r,t)):i!==t&&s.set(i,r);return s}return $=c,$}var j,he;function Ie(){if(he)return j;he=1;function c(t){const s=Number(t);return!(isNaN(s)||s<=0)}function e(t){const s=new Map;return Object.keys(t).forEach(r=>{const o=t[r];if(o!==null&&typeof o=="object"&&!Array.isArray(o))return s.set(r,e(o));if(!c(o))throw new Error(`Could not add node at key "${r}", make sure it's a valid node`,o);return s.set(r,Number(o))}),s}return j=e,j}var q,le;function Le(){if(le)return q;le=1;function c(e){if(!(e instanceof Map))throw new Error(`Invalid graph: Expected Map instead found ${typeof e}`);e.forEach((t,s)=>{if(typeof t=="object"&&t instanceof Map){c(t);return}if(typeof t!="number"||t<=0)throw new Error(`Values must be numbers greater than 0. Found value ${t} at ${s}`)})}return q=c,q}var G,ce;function Oe(){if(ce)return G;ce=1;const c=De(),e=ze(),t=Ie(),s=Le();class i{constructor(o){o instanceof Map?(s(o),this.graph=o):o?this.graph=t(o):this.graph=new Map}addNode(o,a){let h;return a instanceof Map?(s(a),h=a):h=t(a),this.graph.set(o,h),this}addVertex(o,a){return this.addNode(o,a)}removeNode(o){return this.graph=e(this.graph,o),this}path(o,a,h={}){if(!this.graph.size)return h.cost?{path:null,cost:0}:null;const d=new Set,u=new c,l=new Map;let y=[],R=0,w=[];if(h.avoid&&(w=[].concat(h.avoid)),w.includes(o))throw new Error(`Starting node (${o}) cannot be avoided`);if(w.includes(a))throw new Error(`Ending node (${a}) cannot be avoided`);for(u.set(o,0);!u.isEmpty();){const b=u.next();if(b.key===a){R=b.priority;let p=b.key;for(;l.has(p);)y.push(p),p=l.get(p);break}d.add(b.key),(this.graph.get(b.key)||new Map).forEach((p,f)=>{if(d.has(f)||w.includes(f))return null;if(!u.has(f))return l.set(f,b.key),u.set(f,b.priority+p);const M=u.get(f).priority,I=b.priority+p;return I<M?(l.set(f,b.key),u.set(f,I)):null})}return y.length?(h.trim?y.shift():y=y.concat([o]),h.reverse||(y=y.reverse()),h.cost?{path:y,cost:R}:y):h.cost?{path:null,cost:0}:null}shortestPath(...o){return this.path(...o)}}return G=i,G}var Pe=Oe();const Ne=Ce(Pe),Ve={1:"north",2:"northeast",3:"northwest",4:"east",5:"west",6:"south",7:"southeast",8:"southwest",9:"up",10:"down",11:"in",12:"out"};class Ae{constructor(e){this.cache=new Map,this.mapReader=e,this.graph=this.buildGraph()}buildGraph(){const e={};return this.mapReader.getRooms().forEach(t=>{const s={},i=new Set((t.exitLocks??[]).map(o=>Ve[o]).filter(o=>!!o)),r=new Set(t.mSpecialExitLocks??[]);Object.entries(t.exits??{}).forEach(([o,a])=>{i.has(o)||this.mapReader.getRoom(a)&&(s[a.toString()]=1)}),Object.values(t.specialExits??{}).forEach(o=>{r.has(o)||this.mapReader.getRoom(o)&&(s[o.toString()]=1)}),e[t.id.toString()]=s}),new Ne(e)}findPath(e,t){const s=`${e}->${t}`;if(this.cache.has(s))return this.cache.get(s);if(e===t){const a=this.mapReader.getRoom(e)?[e]:null;return this.cache.set(s,a),a}if(!this.mapReader.getRoom(e)||!this.mapReader.getRoom(t))return this.cache.set(s,null),null;const i=this.graph.path(e.toString(),t.toString()),r=Array.isArray(i)?i:i?.path,o=r?r.map(a=>Number(a)):null;return this.cache.set(s,o),o}}exports.ExplorationArea=B;exports.MapReader=Me;exports.PathFinder=Ae;exports.Renderer=ke;exports.Settings=n;
2
2
  //# sourceMappingURL=index.cjs.map