mudlet-map-renderer 0.3.2-konva → 0.3.3-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 +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +2 -2
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","sources":["../src/reader/Exit.ts","../src/directions.ts","../src/ExitRenderer.ts","../src/PathRenderer.ts","../src/Renderer.ts","../src/reader/Plane.ts","../src/reader/Area.ts","../src/reader/ExplorationArea.ts","../src/reader/MapReader.ts","../node_modules/node-dijkstra/libs/PriorityQueue.js","../node_modules/node-dijkstra/libs/removeDeepFromMap.js","../node_modules/node-dijkstra/libs/toDeepMap.js","../node_modules/node-dijkstra/libs/validateDeep.js","../node_modules/node-dijkstra/libs/Graph.js","../src/PathFinder.ts"],"sourcesContent":["export type Kind = \"exit\" | \"specialExit\";\r\n\r\nexport default interface Exit {\r\n a: number;\r\n b: number;\r\n aDir?: MapData.direction;\r\n bDir?: MapData.direction;\r\n kind?: Kind;\r\n zIndex: number[];\r\n}\r\n\r\nexport const regularExits: MapData.direction[] = [\"north\", \"south\", \"east\", \"west\", \"northeast\", \"northwest\", \"southeast\", \"southwest\"];\r\nexport const shortTolong: Record<string, MapData.direction> = {\r\n \"n\": \"north\",\r\n \"s\": \"south\",\r\n \"e\": \"east\",\r\n \"w\": \"west\",\r\n \"ne\": \"northeast\",\r\n \"nw\": \"northwest\",\r\n \"se\": \"southeast\",\r\n \"sw\": \"southwest\",\r\n}\r\nexport const longToShort: Record<MapData.direction, string> = {\r\n \"north\": \"n\",\r\n \"south\": \"s\",\r\n \"east\": \"e\",\r\n \"west\": \"w\",\r\n \"northeast\": \"ne\",\r\n \"northwest\": \"nw\",\r\n \"southeast\": \"se\",\r\n \"southwest\": \"sw\",\r\n \"up\": \"u\",\r\n \"down\": \"d\",\r\n \"in\": \"i\",\r\n \"out\": \"o\"\r\n}\r\n","export type PlanarDirection =\r\n | \"north\"\r\n | \"south\"\r\n | \"east\"\r\n | \"west\"\r\n | \"northeast\"\r\n | \"northwest\"\r\n | \"southeast\"\r\n | \"southwest\";\r\n\r\nconst planarDirectionOffsets: Record<PlanarDirection, {x: number; y: number}> = {\r\n north: {x: 0, y: -1},\r\n south: {x: 0, y: 1},\r\n east: {x: 1, y: 0},\r\n west: {x: -1, y: 0},\r\n northeast: {x: 1, y: -1},\r\n northwest: {x: -1, y: -1},\r\n southeast: {x: 1, y: 1},\r\n southwest: {x: -1, y: 1},\r\n};\r\n\r\nexport const planarDirections: PlanarDirection[] = [\r\n \"north\",\r\n \"south\",\r\n \"east\",\r\n \"west\",\r\n \"northeast\",\r\n \"northwest\",\r\n \"southeast\",\r\n \"southwest\",\r\n];\r\n\r\nexport const oppositeDirections: Record<PlanarDirection, PlanarDirection> = {\r\n north: \"south\",\r\n south: \"north\",\r\n east: \"west\",\r\n west: \"east\",\r\n northeast: \"southwest\",\r\n northwest: \"southeast\",\r\n southeast: \"northwest\",\r\n southwest: \"northeast\",\r\n};\r\n\r\nfunction isPlanarDirection(direction: MapData.direction | undefined): direction is PlanarDirection {\r\n if (!direction) {\r\n return false;\r\n }\r\n return Object.prototype.hasOwnProperty.call(planarDirectionOffsets, direction);\r\n}\r\n\r\nexport function movePoint(\r\n x: number,\r\n y: number,\r\n direction?: MapData.direction,\r\n distance: number = 1,\r\n) {\r\n if (!isPlanarDirection(direction)) {\r\n return {x, y};\r\n }\r\n\r\n const offset = planarDirectionOffsets[direction];\r\n return {\r\n x: x + offset.x * distance,\r\n y: y + offset.y * distance,\r\n };\r\n}\r\n","import Exit, {longToShort} from \"./reader/Exit\";\r\nimport MapReader from \"./reader/MapReader\";\r\nimport Konva from \"konva\";\r\nimport {Settings} from \"./Renderer\";\r\nimport {movePoint} from \"./directions\";\r\n\r\nconst Colors = {\r\n OPEN_DOOR: 'rgb(10, 155, 10)',\r\n CLOSED_DOOR: 'rgb(226, 205, 59)',\r\n LOCKED_DOOR: 'rgb(155, 10, 10)'\r\n}\r\n\r\nconst dirNumbers: Record<number, MapData.direction> = {\r\n 1: \"north\",\r\n 2: \"northeast\",\r\n 3: \"northwest\",\r\n 4: \"east\",\r\n 5: \"west\",\r\n 6: \"south\",\r\n 7: \"southeast\",\r\n 8: \"southwest\",\r\n 9: \"up\",\r\n 10: \"down\",\r\n 11: \"in\",\r\n 12: \"out\",\r\n};\r\n\r\nconst innerExits: MapData.direction[] = [\"up\", \"down\", \"in\", \"out\"];\r\n\r\nfunction getDoorColor(doorType: 1 | 2 | 3) {\r\n switch (doorType) {\r\n case 1:\r\n return Colors.OPEN_DOOR\r\n case 2:\r\n return Colors.CLOSED_DOOR\r\n default:\r\n return Colors.LOCKED_DOOR\r\n }\r\n}\r\n\r\nexport default class ExitRenderer {\r\n\r\n private mapReader: MapReader;\r\n\r\n constructor(mapReader: MapReader) {\r\n this.mapReader = mapReader;\r\n }\r\n\r\n render(exit: Exit) {\r\n if (exit.aDir && exit.bDir) {\r\n return this.renderTwoWayExit(exit);\r\n } else {\r\n return this.renderOneWayExit(exit);\r\n }\r\n }\r\n\r\n private renderTwoWayExit(exit: Exit) {\r\n const sourceRoom = this.mapReader.getRoom(exit.a)\r\n const targetRoom = this.mapReader.getRoom(exit.b);\r\n\r\n if (!sourceRoom || !targetRoom || !exit.aDir || !exit.bDir) {\r\n return;\r\n }\r\n\r\n const exitRender = new Konva.Group();\r\n\r\n const points = []\r\n points.push(...Object.values(movePoint(sourceRoom.x, sourceRoom.y, exit.aDir, Settings.roomSize / 2)));\r\n points.push(...Object.values(movePoint(targetRoom.x, targetRoom.y, exit.bDir, Settings.roomSize / 2)));\r\n\r\n if (sourceRoom.doors[longToShort[exit.aDir]] || targetRoom.doors[longToShort[exit.bDir]]) {\r\n const door = this.renderDoor(points, sourceRoom.doors[longToShort[exit.aDir]] ?? targetRoom.doors[longToShort[exit.bDir]])\r\n exitRender.add(door);\r\n }\r\n\r\n const link = new Konva.Line({\r\n points,\r\n stroke: Settings.lineColor,\r\n strokeWidth: 0.025,\r\n });\r\n exitRender.add(link);\r\n\r\n return exitRender;\r\n }\r\n\r\n private renderOneWayExit(exit: Exit) {\r\n const sourceRoom = exit.aDir ? this.mapReader.getRoom(exit.a) : this.mapReader.getRoom(exit.b)\r\n const targetRoom = exit.aDir ? this.mapReader.getRoom(exit.b) : this.mapReader.getRoom(exit.a)\r\n const dir = exit.aDir ? exit.aDir : exit.bDir;\r\n\r\n if (!sourceRoom || !targetRoom) {\r\n return;\r\n }\r\n\r\n if (sourceRoom.area != targetRoom.area && dir) {\r\n return this.renderAreaExit(sourceRoom, dir);\r\n }\r\n\r\n let targetPoint = {x: targetRoom.x, y: targetRoom.y};\r\n if (targetRoom.area !== sourceRoom.area || targetRoom.z !== sourceRoom.z) {\r\n targetPoint = movePoint(sourceRoom.x, sourceRoom.y, dir, Settings.roomSize / 2);\r\n }\r\n\r\n const startPoint = movePoint(sourceRoom.x, sourceRoom.y, dir, 0.3);\r\n\r\n const middlePointX = startPoint.x - (startPoint.x - targetPoint.x) / 2;\r\n const middlePointY = startPoint.y - (startPoint.y - targetPoint.y) / 2;\r\n\r\n const group = new Konva.Group();\r\n const points = []\r\n points.push(...Object.values(movePoint(sourceRoom.x, sourceRoom.y, dir, Settings.roomSize / 2)));\r\n points.push(targetPoint.x, targetPoint.y);\r\n const link = new Konva.Line({\r\n points,\r\n stroke: Settings.lineColor,\r\n strokeWidth: 0.025,\r\n dashEnabled: true,\r\n dash: [0.1, 0.05],\r\n });\r\n group.add(link)\r\n\r\n const arrow = new Konva.Arrow({\r\n points: [points[0], points[1], middlePointX, middlePointY],\r\n pointerLength: 0.5,\r\n pointerWidth: 0.35,\r\n strokeWidth: 0.035,\r\n stroke: Settings.lineColor,\r\n fill: '#FF0000',\r\n dashEnabled: true,\r\n dash: [0.1, 0.05],\r\n })\r\n\r\n group.add(arrow)\r\n\r\n return group;\r\n }\r\n\r\n renderAreaExit(room: MapData.Room, dir: MapData.direction) {\r\n const start = movePoint(room.x, room.y, dir, Settings.roomSize / 2)\r\n const end = movePoint(room.x, room.y, dir, Settings.roomSize * 1.5)\r\n return new Konva.Arrow({\r\n points: [start.x, start.y, end.x, end.y],\r\n pointerLength: 0.3,\r\n pointerWidth: 0.3,\r\n strokeWidth: 0.035,\r\n stroke: this.mapReader.getColorValue(room.env),\r\n fill: this.mapReader.getColorValue(room.env),\r\n })\r\n }\r\n\r\n renderSpecialExits(room: MapData.Room) {\r\n return Object.entries(room.customLines).map(([_, line]) => {\r\n const points = [room.x, room.y]\r\n line.points.reduce((acc, point) => {\r\n acc.push(point.x, -point.y);\r\n return acc;\r\n }, points)\r\n\r\n const construct = line.attributes.arrow ? Konva.Arrow : Konva.Line;\r\n const lineRender = new construct({\r\n points: points,\r\n strokeWidth: .025,\r\n stroke: `rgb(${line.attributes.color.r}, ${line.attributes.color.g}, ${line.attributes.color.b})`,\r\n fill: `rgb(${line.attributes.color.r}, ${line.attributes.color.g} , ${line.attributes.color.b})`,\r\n pointerLength: 0.3,\r\n pointerWidth: 0.2,\r\n\r\n })\r\n\r\n let style = line.attributes.style;\r\n if (style === \"dot line\") {\r\n lineRender.dash([0.05, 0.05])\r\n lineRender.dashOffset(0.1)\r\n } else if (style === \"dash line\") {\r\n lineRender.dash([0.4, 0.2])\r\n } else if (style === \"solid line\") {\r\n } else if (style !== undefined) {\r\n console.log(\"Brak opisu stylu: \" + style);\r\n }\r\n\r\n return lineRender;\r\n })\r\n }\r\n\r\n renderStubs(room: MapData.Room) {\r\n return room.stubs.map(stub => {\r\n const direction = dirNumbers[stub];\r\n const start = movePoint(room.x, room.y, direction, Settings.roomSize / 2)\r\n const end = movePoint(room.x, room.y, direction, Settings.roomSize / 2 + 0.5)\r\n const points = [start.x, start.y, end.x, end.y]\r\n return new Konva.Line({\r\n points,\r\n stroke: Settings.lineColor,\r\n strokeWidth: 0.025,\r\n });\r\n })\r\n }\r\n\r\n renderInnerExits(room: MapData.Room) {\r\n return innerExits.map(exit => {\r\n if (room.exits[exit]) {\r\n const render = new Konva.Group();\r\n const triangle = new Konva.RegularPolygon({\r\n x: room.x,\r\n y: room.y,\r\n sides: 3,\r\n fill: this.mapReader.getSymbolColor(room.env, 0.6),\r\n stroke: this.mapReader.getSymbolColor(room.env),\r\n strokeWidth: 0.025,\r\n radius: Settings.roomSize / 5,\r\n scaleX: 1.4,\r\n scaleY: 0.8\r\n })\r\n render.add(triangle);\r\n\r\n let doorType = room.doors[exit];\r\n if (doorType !== undefined) {\r\n switch (doorType) {\r\n case 1:\r\n triangle.stroke(Colors.OPEN_DOOR)\r\n break;\r\n case 2:\r\n triangle.stroke(Colors.CLOSED_DOOR);\r\n break;\r\n default:\r\n triangle.stroke(Colors.LOCKED_DOOR);\r\n }\r\n }\r\n\r\n switch (exit) {\r\n case \"up\":\r\n triangle.position(movePoint(room.x, room.y, \"south\", Settings.roomSize / 4));\r\n break;\r\n case \"down\":\r\n triangle.rotation(180);\r\n triangle.position(movePoint(room.x, room.y, \"north\", Settings.roomSize / 4));\r\n break;\r\n case \"in\":\r\n const inRender = triangle.clone()\r\n inRender.rotation(-90);\r\n inRender.position(movePoint(room.x, room.y, \"east\", Settings.roomSize / 4));\r\n render.add(inRender);\r\n triangle.rotation(90);\r\n triangle.position(movePoint(room.x, room.y, \"west\", Settings.roomSize / 4));\r\n break;\r\n case \"out\":\r\n const outRender = triangle.clone()\r\n outRender.rotation(90);\r\n outRender.position(movePoint(room.x, room.y, \"east\", Settings.roomSize / 4));\r\n render.add(outRender);\r\n triangle.rotation(-90);\r\n triangle.position(movePoint(room.x, room.y, \"west\", Settings.roomSize / 4));\r\n break;\r\n }\r\n return render\r\n }\r\n }).filter(e => e !== undefined)\r\n }\r\n\r\n renderDoor(points: number[], type: 1 | 2 | 3) {\r\n const point = {\r\n x: points[0] + (points[2] - points[0]) / 2,\r\n y: points[1] + (points[3] - points[1]) / 2,\r\n }\r\n return new Konva.Rect({\r\n x: point.x - Settings.roomSize / 4,\r\n y: point.y - Settings.roomSize / 4,\r\n width: Settings.roomSize / 2,\r\n height: Settings.roomSize / 2,\r\n stroke: getDoorColor(type),\r\n strokeWidth: 0.025\r\n })\r\n }\r\n\r\n}","import Konva from \"konva\";\r\nimport MapReader from \"./reader/MapReader\";\r\nimport {Settings} from \"./Renderer\";\r\nimport {movePoint, PlanarDirection, planarDirections, oppositeDirections} from \"./directions\";\r\n\r\nexport default class PathRenderer {\r\n private readonly mapReader: MapReader;\r\n private readonly overlayLayer: Konva.Layer;\r\n private paths: Konva.Line[] = [];\r\n\r\n constructor(mapReader: MapReader, overlayLayer: Konva.Layer) {\r\n this.mapReader = mapReader;\r\n this.overlayLayer = overlayLayer;\r\n }\r\n\r\n renderPath(locations: number[], currentArea?: number, currentZIndex?: number, color: string = '#66E64D') {\r\n if (currentArea === undefined || currentZIndex === undefined) {\r\n return;\r\n }\r\n\r\n const rooms = locations\r\n .map(location => this.mapReader.getRoom(location))\r\n .filter((room): room is MapData.Room => room !== undefined);\r\n\r\n const segments: number[][] = [];\r\n let currentSegment: number[] | null = null;\r\n\r\n const finalizeSegment = () => {\r\n if (!currentSegment) {\r\n return;\r\n }\r\n if (currentSegment.length < 4) {\r\n segments.pop();\r\n }\r\n currentSegment = null;\r\n };\r\n\r\n const ensureSegment = () => {\r\n if (!currentSegment) {\r\n currentSegment = [];\r\n segments.push(currentSegment);\r\n }\r\n return currentSegment;\r\n };\r\n\r\n rooms.forEach((room, index) => {\r\n if (!this.isRoomVisible(room, currentArea, currentZIndex)) {\r\n return;\r\n }\r\n\r\n const previousRoom = index > 0 ? rooms[index - 1] : undefined;\r\n const nextRoom = index < rooms.length - 1 ? rooms[index + 1] : undefined;\r\n const previousVisible = this.isRoomVisible(previousRoom, currentArea, currentZIndex);\r\n\r\n if (!previousVisible) {\r\n finalizeSegment();\r\n const segment = ensureSegment();\r\n if (previousRoom) {\r\n const directionToPrevious = this.getDirectionTowards(room, previousRoom);\r\n if (directionToPrevious) {\r\n const startPoint = movePoint(room.x, room.y, directionToPrevious, Settings.roomSize);\r\n segment.push(startPoint.x, startPoint.y);\r\n }\r\n }\r\n } else {\r\n ensureSegment();\r\n }\r\n\r\n currentSegment?.push(room.x, room.y);\r\n\r\n const nextVisible = this.isRoomVisible(nextRoom, currentArea, currentZIndex);\r\n if (!nextVisible && nextRoom) {\r\n const directionToNext = this.getDirectionTowards(room, nextRoom);\r\n if (directionToNext) {\r\n const endPoint = movePoint(room.x, room.y, directionToNext, Settings.roomSize);\r\n currentSegment?.push(endPoint.x, endPoint.y);\r\n }\r\n finalizeSegment();\r\n }\r\n });\r\n\r\n finalizeSegment();\r\n\r\n const paths = segments\r\n .filter(points => points.length >= 4)\r\n .map(points => new Konva.Line({\r\n points,\r\n stroke: color,\r\n strokeWidth: 0.1\r\n }));\r\n\r\n paths.forEach(path => {\r\n this.overlayLayer.add(path);\r\n this.paths.push(path);\r\n });\r\n\r\n return paths[0];\r\n }\r\n\r\n clearPaths() {\r\n this.paths.forEach(path => {\r\n path.destroy();\r\n });\r\n this.paths = [];\r\n }\r\n\r\n private isRoomVisible(room: MapData.Room | undefined, currentArea: number | undefined, currentZIndex: number | undefined) {\r\n if (!room) {\r\n return false;\r\n }\r\n return room.area === currentArea && room.z === currentZIndex;\r\n }\r\n\r\n private getDirectionTowards(from: MapData.Room, to: MapData.Room): PlanarDirection | undefined {\r\n for (const direction of planarDirections) {\r\n if (from.exits[direction] === to.id) {\r\n return direction;\r\n }\r\n }\r\n\r\n for (const direction of planarDirections) {\r\n if (to.exits[direction] === from.id) {\r\n return oppositeDirections[direction];\r\n }\r\n }\r\n\r\n return undefined;\r\n }\r\n}\r\n","import Konva from \"konva\";\r\nimport ExitRenderer from \"./ExitRenderer\";\r\nimport MapReader from \"./reader/MapReader\";\r\nimport Exit from \"./reader/Exit\";\r\nimport Area from \"./reader/Area\";\r\nimport PathRenderer from \"./PathRenderer\";\r\n\r\nconst defaultRoomSize = 0.6;\r\nconst defaultZoom = 75\r\nconst lineColor = 'rgb(225, 255, 225)';\r\n\r\nexport type RoomContextMenuEventDetail = {\r\n roomId: number;\r\n position: { x: number; y: number };\r\n};\r\n\r\nexport type ZoomChangeEventDetail = {\r\n zoom: number;\r\n};\r\n\r\nexport class Settings {\r\n static roomSize = defaultRoomSize;\r\n static lineColor = lineColor;\r\n static instantMapMove = false\r\n}\r\n\r\ntype HighlightData = {\r\n color: string;\r\n area: number;\r\n z: number;\r\n shape?: Konva.Circle;\r\n};\r\n\r\nexport class Renderer {\r\n\r\n private readonly stage: Konva.Stage;\r\n private readonly roomLayer: Konva.Layer;\r\n private readonly linkLayer: Konva.Layer;\r\n private readonly overlayLayer: Konva.Layer;\r\n private readonly positionLayer: Konva.Layer;\r\n private mapReader: MapReader;\r\n private exitRenderer: ExitRenderer;\r\n private pathRenderer: PathRenderer;\r\n private highlights: Map<number, HighlightData> = new Map();\r\n private currentArea?: number;\r\n private currentAreaInstance?: Area;\r\n private currentZIndex?: number;\r\n private currentAreaVersion?: number;\r\n private currentRoomId?: number;\r\n private positionRender?: Konva.Circle;\r\n private currentTransition?: Konva.Tween;\r\n private currentZoom: number = 1;\r\n\r\n constructor(container: HTMLDivElement, mapReader: MapReader) {\r\n this.stage = new Konva.Stage({\r\n container: container,\r\n width: container.clientWidth,\r\n height: container.clientHeight,\r\n draggable: true\r\n });\r\n window.addEventListener('resize', () => {\r\n this.onResize(container);\r\n })\r\n container.addEventListener('resize', () => {\r\n this.onResize(container);\r\n })\r\n this.linkLayer = new Konva.Layer({\r\n listening: false,\r\n });\r\n this.stage.add(this.linkLayer);\r\n this.roomLayer = new Konva.Layer();\r\n this.stage.add(this.roomLayer);\r\n this.overlayLayer = new Konva.Layer({\r\n listening: false,\r\n })\r\n this.stage.add(this.overlayLayer);\r\n this.positionLayer = new Konva.Layer({\r\n listening: false,\r\n });\r\n this.stage.add(this.positionLayer);\r\n this.mapReader = mapReader;\r\n this.exitRenderer = new ExitRenderer(mapReader);\r\n this.pathRenderer = new PathRenderer(mapReader, this.overlayLayer);\r\n\r\n const scaleBy = 1.1;\r\n this.initScaling(scaleBy);\r\n }\r\n\r\n private onResize(container: HTMLDivElement) {\r\n this.stage.width(container.clientWidth);\r\n this.stage.height(container.clientHeight);\r\n if (this.currentRoomId) {\r\n this.centerOnRoom(this.mapReader.getRoom(this.currentRoomId)!, false);\r\n }\r\n this.stage.batchDraw();\r\n }\r\n\r\n private initScaling(scaleBy: number) {\r\n Konva.hitOnDragEnabled = true;\r\n\r\n let lastPinchDistance: number | undefined;\r\n let lastPinchCenter: { x: number; y: number } | undefined;\r\n let dragStopped = false;\r\n\r\n this.stage.on('touchend touchcancel', () => {\r\n lastPinchDistance = undefined;\r\n lastPinchCenter = undefined;\r\n });\r\n\r\n this.stage.on('wheel', (e) => {\r\n e.evt.preventDefault();\r\n\r\n const oldScale = this.stage.scaleX();\r\n const pointer = this.stage.getPointerPosition();\r\n if (!pointer) {\r\n return;\r\n }\r\n\r\n const mousePointTo = {\r\n x: (pointer.x - this.stage.x()) / oldScale,\r\n y: (pointer.y - this.stage.y()) / oldScale,\r\n };\r\n\r\n let direction = e.evt.deltaY > 0 ? -1 : 1;\r\n\r\n if (e.evt.ctrlKey) {\r\n direction = -direction;\r\n }\r\n\r\n const newZoom = direction > 0 ? this.currentZoom * scaleBy : this.currentZoom / scaleBy;\r\n const newScale = newZoom * defaultZoom;\r\n const zoomChanged = this.setZoom(newZoom);\r\n\r\n const newPos = {\r\n x: pointer.x - mousePointTo.x * newScale,\r\n y: pointer.y - mousePointTo.y * newScale,\r\n };\r\n\r\n this.stage.position(newPos);\r\n\r\n if (zoomChanged) {\r\n this.emitZoomChangeEvent();\r\n }\r\n });\r\n\r\n this.stage.on('touchmove', (e) => {\r\n const touches = e.evt.touches;\r\n const touch1 = touches?.[0];\r\n const touch2 = touches?.[1];\r\n\r\n if (touch1 && !touch2 && dragStopped && !this.stage.isDragging()) {\r\n this.stage.startDrag();\r\n dragStopped = false;\r\n }\r\n\r\n if (!touch1 || !touch2) {\r\n lastPinchDistance = undefined;\r\n lastPinchCenter = undefined;\r\n return;\r\n }\r\n\r\n e.evt.preventDefault();\r\n\r\n if (this.stage.isDragging()) {\r\n this.stage.stopDrag();\r\n dragStopped = true;\r\n }\r\n\r\n const rect = this.stage.container().getBoundingClientRect();\r\n const p1 = {\r\n x: touch1.clientX - rect.left,\r\n y: touch1.clientY - rect.top,\r\n };\r\n const p2 = {\r\n x: touch2.clientX - rect.left,\r\n y: touch2.clientY - rect.top,\r\n };\r\n\r\n const newCenter = {\r\n x: (p1.x + p2.x) / 2,\r\n y: (p1.y + p2.y) / 2,\r\n };\r\n const distance = Math.hypot(p1.x - p2.x, p1.y - p2.y);\r\n\r\n if (lastPinchCenter === undefined) {\r\n lastPinchCenter = newCenter;\r\n }\r\n\r\n if (lastPinchDistance === undefined) {\r\n lastPinchDistance = distance;\r\n return;\r\n }\r\n\r\n if (lastPinchDistance === 0) {\r\n return;\r\n }\r\n\r\n const oldScale = this.stage.scaleX();\r\n const newZoom = this.currentZoom * (distance / lastPinchDistance);\r\n\r\n const pointTo = {\r\n x: (newCenter.x - this.stage.x()) / oldScale,\r\n y: (newCenter.y - this.stage.y()) / oldScale,\r\n };\r\n\r\n const zoomChanged = this.setZoom(newZoom);\r\n\r\n const newScale = this.stage.scaleX();\r\n const dx = newCenter.x - lastPinchCenter.x;\r\n const dy = newCenter.y - lastPinchCenter.y;\r\n const newPos = {\r\n x: newCenter.x - pointTo.x * newScale + dx,\r\n y: newCenter.y - pointTo.y * newScale + dy,\r\n };\r\n\r\n this.stage.position(newPos);\r\n this.stage.batchDraw();\r\n\r\n lastPinchDistance = distance;\r\n lastPinchCenter = newCenter;\r\n\r\n if (zoomChanged) {\r\n this.emitZoomChangeEvent();\r\n }\r\n });\r\n }\r\n\r\n drawArea(id: number, zIndex: number) {\r\n const area = this.mapReader.getArea(id);\r\n if (!area) {\r\n return;\r\n }\r\n const plane = area.getPlane(zIndex);\r\n if (!plane) {\r\n return;\r\n }\r\n this.currentArea = id;\r\n this.currentAreaInstance = area;\r\n this.currentZIndex = zIndex;\r\n this.currentAreaVersion = area.getVersion();\r\n this.roomLayer.destroyChildren();\r\n this.linkLayer.destroyChildren();\r\n\r\n this.stage.scale({x: defaultZoom * this.currentZoom, y: defaultZoom * this.currentZoom});\r\n\r\n this.renderLabels(plane.getLabels());\r\n this.renderRooms(plane.getRooms() ?? []);\r\n this.renderExits(area.getLinkExits(zIndex));\r\n this.refreshHighlights();\r\n this.stage.batchDraw();\r\n }\r\n\r\n private emitRoomContextEvent(roomId: number, clientX: number, clientY: number) {\r\n const container = this.stage.container();\r\n const bounds = container.getBoundingClientRect();\r\n const detail: RoomContextMenuEventDetail = {\r\n roomId,\r\n position: {\r\n x: clientX - bounds.left,\r\n y: clientY - bounds.top,\r\n },\r\n };\r\n const event = new CustomEvent<RoomContextMenuEventDetail>('roomcontextmenu', {detail});\r\n container.dispatchEvent(event);\r\n }\r\n\r\n private emitZoomChangeEvent() {\r\n const event = new CustomEvent<ZoomChangeEventDetail>('zoom', {\r\n detail: {zoom: this.currentZoom},\r\n });\r\n this.stage.container().dispatchEvent(event);\r\n }\r\n\r\n setZoom(zoom: number): boolean {\r\n if (this.currentZoom === zoom) {\r\n return false;\r\n }\r\n\r\n this.currentZoom = zoom;\r\n this.stage.scale({x: defaultZoom * zoom, y: defaultZoom * zoom});\r\n\r\n return true;\r\n }\r\n\r\n getZoom() {\r\n return this.currentZoom;\r\n }\r\n\r\n getCurrentArea() {\r\n return this.currentArea ? this.mapReader.getArea(this.currentArea) : undefined\r\n }\r\n\r\n setPosition(roomId: number) {\r\n const room = this.mapReader.getRoom(roomId);\r\n if (!room) return;\r\n const area = this.mapReader.getArea(room.area);\r\n const areaVersion = area?.getVersion();\r\n let instant = this.currentArea !== room.area || this.currentZIndex !== room.z\r\n if (\r\n this.currentArea !== room.area ||\r\n this.currentZIndex !== room.z ||\r\n (areaVersion !== undefined && this.currentAreaVersion !== areaVersion) ||\r\n (area !== undefined && this.currentAreaInstance !== area)\r\n ) {\r\n this.drawArea(room.area, room.z);\r\n }\r\n if (!this.positionRender) {\r\n this.positionRender = new Konva.Circle({\r\n x: room.x,\r\n y: room.y,\r\n radius: defaultRoomSize * 0.85,\r\n stroke: \"rgb(0, 229, 178)\",\r\n strokeWidth: 0.1,\r\n dash: [0.05, 0.05],\r\n dashEnabled: true,\r\n })\r\n this.positionLayer.add(this.positionRender);\r\n }\r\n this.centerOnRoom(room, instant);\r\n }\r\n\r\n renderPath(locations: number[]) {\r\n return this.pathRenderer.renderPath(locations, this.currentArea, this.currentZIndex);\r\n }\r\n\r\n clearPaths() {\r\n this.pathRenderer.clearPaths();\r\n }\r\n\r\n renderHighlight(roomId: number, color: string) {\r\n const room = this.mapReader.getRoom(roomId);\r\n if (!room) {\r\n return;\r\n }\r\n\r\n const existing = this.highlights.get(roomId);\r\n if (existing?.shape) {\r\n existing.shape.destroy();\r\n delete existing.shape;\r\n }\r\n\r\n const highlightData: HighlightData = {color, area: room.area, z: room.z};\r\n\r\n this.highlights.set(roomId, highlightData);\r\n\r\n if (room.area === this.currentArea && room.z === this.currentZIndex) {\r\n const shape = this.createHighlightShape(room, color);\r\n this.overlayLayer.add(shape);\r\n highlightData.shape = shape;\r\n this.overlayLayer.batchDraw();\r\n return shape;\r\n }\r\n\r\n return highlightData.shape;\r\n }\r\n\r\n clearHighlights() {\r\n this.highlights.forEach(({shape}) => shape?.destroy());\r\n this.highlights.clear();\r\n this.overlayLayer.batchDraw();\r\n }\r\n\r\n private refreshHighlights() {\r\n this.highlights.forEach((highlight, roomId) => {\r\n highlight.shape?.destroy();\r\n delete highlight.shape;\r\n\r\n if (highlight.area !== this.currentArea || highlight.z !== this.currentZIndex) {\r\n return;\r\n }\r\n\r\n const room = this.mapReader.getRoom(roomId);\r\n if (!room) {\r\n return;\r\n }\r\n\r\n const shape = this.createHighlightShape(room, highlight.color);\r\n this.overlayLayer.add(shape);\r\n highlight.shape = shape;\r\n });\r\n\r\n this.overlayLayer.batchDraw();\r\n }\r\n\r\n private createHighlightShape(room: MapData.Room, color: string) {\r\n return new Konva.Circle({\r\n x: room.x,\r\n y: room.y,\r\n radius: Settings.roomSize * 0.9,\r\n stroke: color,\r\n strokeWidth: 0.15,\r\n dash: [0.1, 0.05],\r\n dashEnabled: true,\r\n listening: false,\r\n });\r\n }\r\n\r\n private centerOnRoom(room: MapData.Room, instant: boolean = false) {\r\n this.currentRoomId = room.id;\r\n const roomCenter = {x: room.x, y: room.y};\r\n\r\n this.positionRender?.position(room)\r\n\r\n const abs = this.stage.getAbsoluteTransform()\r\n const screenPoint = abs.point(roomCenter);\r\n\r\n const target = {\r\n x: this.stage.width() / 2,\r\n y: this.stage.height() / 2,\r\n };\r\n\r\n const dx = target.x - screenPoint.x;\r\n const dy = target.y - screenPoint.y;\r\n\r\n if (this.currentTransition) {\r\n this.currentTransition.pause()\r\n this.currentTransition.destroy()\r\n delete this.currentTransition;\r\n }\r\n\r\n console.log(Settings.instantMapMove)\r\n if (instant || Settings.instantMapMove) {\r\n this.stage.position({\r\n x: this.stage.x() + dx,\r\n y: this.stage.y() + dy,\r\n })\r\n } else {\r\n this.currentTransition = new Konva.Tween({\r\n node: this.stage,\r\n x: this.stage.x() + dx,\r\n y: this.stage.y() + dy,\r\n duration: 0.2,\r\n easing: Konva.Easings.EaseInOut,\r\n })\r\n this.currentTransition.play()\r\n }\r\n }\r\n\r\n private renderRooms(rooms: MapData.Room[]) {\r\n rooms.forEach(room => {\r\n const roomRender = new Konva.Group({\r\n x: room.x - Settings.roomSize / 2,\r\n y: room.y - Settings.roomSize / 2,\r\n });\r\n const roomRect = new Konva.Rect({\r\n x: 0,\r\n y: 0,\r\n width: Settings.roomSize,\r\n height: Settings.roomSize,\r\n fill: this.mapReader.getColorValue(room.env),\r\n strokeWidth: 0.025,\r\n stroke: Settings.lineColor,\r\n });\r\n const emitContextEvent = (clientX: number, clientY: number) => this.emitRoomContextEvent(room.id, clientX, clientY);\r\n\r\n roomRender.on('mouseenter', () => {\r\n this.stage.container().style.cursor = 'pointer';\r\n })\r\n roomRender.on('mouseleave', () => {\r\n this.stage.container().style.cursor = 'auto';\r\n })\r\n roomRender.on('contextmenu', (event) => {\r\n event.evt.preventDefault();\r\n const pointerEvent = event.evt as MouseEvent;\r\n emitContextEvent(pointerEvent.clientX, pointerEvent.clientY);\r\n })\r\n\r\n let longPressTimeout: number | undefined;\r\n let longPressStart: { clientX: number; clientY: number } | undefined;\r\n let stageDraggableBeforeLongPress: boolean | undefined;\r\n const restoreStageDraggable = () => {\r\n if (stageDraggableBeforeLongPress !== undefined) {\r\n this.stage.draggable(stageDraggableBeforeLongPress);\r\n stageDraggableBeforeLongPress = undefined;\r\n }\r\n };\r\n const clearLongPressTimeout = () => {\r\n if (longPressTimeout !== undefined) {\r\n window.clearTimeout(longPressTimeout);\r\n longPressTimeout = undefined;\r\n }\r\n longPressStart = undefined;\r\n restoreStageDraggable();\r\n };\r\n\r\n roomRender.on('touchstart', (event) => {\r\n clearLongPressTimeout();\r\n if (event.evt.touches && event.evt.touches.length > 1) {\r\n return;\r\n }\r\n const touch = event.evt.touches?.[0];\r\n if (!touch) {\r\n return;\r\n }\r\n longPressStart = { clientX: touch.clientX, clientY: touch.clientY };\r\n stageDraggableBeforeLongPress = this.stage.draggable();\r\n this.stage.draggable(false);\r\n longPressTimeout = window.setTimeout(() => {\r\n if (longPressStart) {\r\n emitContextEvent(longPressStart.clientX, longPressStart.clientY);\r\n }\r\n clearLongPressTimeout();\r\n }, 500);\r\n });\r\n\r\n roomRender.on('touchend', clearLongPressTimeout);\r\n roomRender.on('touchmove', (event) => {\r\n if (!longPressStart) {\r\n return;\r\n }\r\n const touch = event.evt.touches?.[0];\r\n if (!touch) {\r\n clearLongPressTimeout();\r\n return;\r\n }\r\n const dx = touch.clientX - longPressStart.clientX;\r\n const dy = touch.clientY - longPressStart.clientY;\r\n const distanceSquared = dx * dx + dy * dy;\r\n const movementThreshold = 10;\r\n if (distanceSquared > movementThreshold * movementThreshold) {\r\n const wasDraggable = stageDraggableBeforeLongPress;\r\n clearLongPressTimeout();\r\n if (wasDraggable) {\r\n this.stage.startDrag();\r\n }\r\n }\r\n });\r\n roomRender.on('touchcancel', clearLongPressTimeout);\r\n\r\n roomRender.add(roomRect);\r\n this.renderSymbol(room, roomRender);\r\n this.roomLayer.add(roomRender);\r\n\r\n this.exitRenderer.renderSpecialExits(room).forEach(render => {\r\n this.linkLayer.add(render)\r\n })\r\n this.exitRenderer.renderStubs(room).forEach(render => {\r\n this.linkLayer.add(render)\r\n })\r\n this.exitRenderer.renderInnerExits(room).forEach(render => {\r\n this.roomLayer.add(render)\r\n })\r\n })\r\n }\r\n\r\n private renderSymbol(room: MapData.Room, roomRender: Konva.Group) {\r\n if (room.roomChar !== undefined) {\r\n const roomChar = new Konva.Text({\r\n x: 0,\r\n y: 0,\r\n text: room.roomChar,\r\n fontSize: 0.45,\r\n fontStyle: \"bold\",\r\n fill: this.mapReader.getSymbolColor(room.env),\r\n align: \"center\",\r\n verticalAlign: \"middle\",\r\n width: Settings.roomSize,\r\n height: Settings.roomSize,\r\n })\r\n roomRender.add(roomChar);\r\n }\r\n }\r\n\r\n private renderExits(exits: Exit[]) {\r\n exits.forEach(exit => {\r\n const render = this.exitRenderer.render(exit);\r\n if (!render) {\r\n return;\r\n }\r\n this.linkLayer.add(render);\r\n })\r\n\r\n }\r\n\r\n private renderLabels(Labels: MapData.Label[]) {\r\n Labels.forEach(label => {\r\n if (!label.pixMap) {\r\n return\r\n }\r\n const image = new Image()\r\n image.src = `data:image/png;base64,${label.pixMap}`\r\n const labelRender = new Konva.Image({\r\n x: label.X,\r\n y: -label.Y,\r\n width: label.Width,\r\n height: label.Height,\r\n image: image\r\n })\r\n this.linkLayer.add(labelRender)\r\n })\r\n }\r\n\r\n\r\n}","export default class Plane {\r\n\r\n private readonly bounds: { minX: number, maxX: number, minY: number, maxY: number }\r\n private readonly rooms: MapData.Room[] = [];\r\n private readonly labels: MapData.Label[] = [];\r\n\r\n constructor(rooms: MapData.Room[], labels: MapData.Label[]) {\r\n this.rooms = rooms\r\n this.bounds = this.createBounds();\r\n this.labels = labels\r\n }\r\n\r\n getRooms() {\r\n return this.rooms;\r\n }\r\n\r\n getLabels() {\r\n return this.labels;\r\n }\r\n\r\n getBounds() {\r\n return this.bounds;\r\n }\r\n\r\n private createBounds() {\r\n return this.rooms.reduce(\r\n (acc, r) => ({\r\n minX: Math.min(acc.minX, r.x),\r\n maxX: Math.max(acc.maxX, r.x),\r\n minY: Math.min(acc.minY, r.y),\r\n maxY: Math.max(acc.maxY, r.y),\r\n }),\r\n {\r\n minX: Number.POSITIVE_INFINITY,\r\n maxX: Number.NEGATIVE_INFINITY,\r\n minY: Number.POSITIVE_INFINITY,\r\n maxY: Number.NEGATIVE_INFINITY,\r\n }\r\n );\r\n }\r\n\r\n}","import Plane from \"./Plane\";\r\n\r\nimport Exit, {longToShort, regularExits} from \"./Exit\";\r\n\r\nexport default class Area {\r\n\r\n private readonly planes: Record<number, Plane> = {};\r\n private readonly area: MapData.Area;\r\n private readonly exits: Map<string, Exit> = new Map();\r\n private version = 0;\r\n\r\n constructor(area: MapData.Area) {\r\n this.area = area;\r\n this.planes = this.createPlanes();\r\n this.createExits();\r\n }\r\n\r\n getAreaName() {\r\n return this.area.areaName\r\n }\r\n\r\n getAreaId() {\r\n return parseInt(this.area.areaId)\r\n }\r\n\r\n getVersion() {\r\n return this.version;\r\n }\r\n\r\n protected markDirty() {\r\n this.version++;\r\n }\r\n\r\n getPlane(zIndex: number) {\r\n return this.planes[zIndex];\r\n }\r\n\r\n getPlanes() {\r\n return Object.values(this.planes);\r\n }\r\n\r\n getRooms() {\r\n return this.area.rooms\r\n }\r\n\r\n getLinkExits(zIndex: number) {\r\n return Array.from(this.exits.values()).filter(e => e.zIndex.includes(zIndex));\r\n }\r\n\r\n private createPlanes() {\r\n const grouped = this.area.rooms.reduce<Record<number, MapData.Room[]>>((acc, room) => {\r\n if (!acc[room.z]) {\r\n acc[room.z] = [];\r\n }\r\n // @ts-ignore\r\n acc[room.z].push(room);\r\n return acc;\r\n }, {});\r\n return Object.entries(grouped).reduce(\r\n (acc, [z, rooms]) => {\r\n acc[+z] = new Plane(rooms, this.area.labels.filter(label => label.Z === +z));\r\n return acc;\r\n },\r\n {} as Record<number, Plane>\r\n );\r\n }\r\n\r\n private createExits() {\r\n this.area.rooms.forEach(room => {\r\n Object.entries(room.exits)\r\n .filter(([direction, _]) => regularExits.indexOf(direction as MapData.direction) > -1 && !room.customLines.hasOwnProperty(longToShort[direction as MapData.direction]))\r\n .forEach(([direction, targetRoomId]) => this.createHalfExit(room.id, targetRoomId, room.z, direction as MapData.direction))\r\n })\r\n }\r\n\r\n private createHalfExit(originRoom: number, targetRoom: number, zIndex: number, direction: MapData.direction,) {\r\n if (originRoom === targetRoom) {\r\n return\r\n }\r\n const a = Math.min(originRoom, targetRoom);\r\n const b = Math.max(originRoom, targetRoom);\r\n const key = `${a}-${b}`;\r\n let edge = this.exits.get(key);\r\n if (!edge) {\r\n edge = {a: a, b: b, zIndex: [zIndex]};\r\n }\r\n if (a == originRoom) {\r\n edge.aDir = direction;\r\n } else {\r\n edge.bDir = direction;\r\n }\r\n edge.zIndex.push(zIndex);\r\n this.exits.set(key, edge);\r\n }\r\n\r\n}","import Area from \"./Area\";\r\nimport Plane from \"./Plane\";\r\nimport Exit from \"./Exit\";\r\n\r\nclass ExplorationPlane extends Plane {\r\n\r\n private readonly basePlane: Plane;\r\n private readonly visitedRooms: Set<number>;\r\n\r\n constructor(plane: Plane, visitedRooms: Set<number>) {\r\n super(plane.getRooms(), plane.getLabels());\r\n this.basePlane = plane;\r\n this.visitedRooms = visitedRooms;\r\n }\r\n\r\n override getRooms() {\r\n return this.basePlane.getRooms().filter(room => this.visitedRooms.has(room.id));\r\n }\r\n\r\n override getLabels() {\r\n return this.basePlane.getLabels();\r\n }\r\n\r\n override getBounds() {\r\n const rooms = this.getRooms();\r\n if (!rooms.length) {\r\n return this.basePlane.getBounds();\r\n }\r\n return rooms.reduce(\r\n (acc, room) => ({\r\n minX: Math.min(acc.minX, room.x),\r\n maxX: Math.max(acc.maxX, room.x),\r\n minY: Math.min(acc.minY, room.y),\r\n maxY: Math.max(acc.maxY, room.y),\r\n }),\r\n {\r\n minX: Number.POSITIVE_INFINITY,\r\n maxX: Number.NEGATIVE_INFINITY,\r\n minY: Number.POSITIVE_INFINITY,\r\n maxY: Number.NEGATIVE_INFINITY,\r\n }\r\n );\r\n }\r\n\r\n}\r\n\r\nexport default class ExplorationArea extends Area {\r\n\r\n private readonly visitedRooms: Set<number>;\r\n private readonly areaRoomIds: Set<number>;\r\n private readonly planeCache: WeakMap<Plane, ExplorationPlane> = new WeakMap();\r\n\r\n constructor(area: MapData.Area, visitedRooms?: Iterable<number> | Set<number>) {\r\n super(area);\r\n this.visitedRooms = visitedRooms instanceof Set ? visitedRooms : new Set(visitedRooms ?? []);\r\n this.areaRoomIds = new Set(area.rooms.map(room => room.id));\r\n }\r\n\r\n override getPlane(zIndex: number) {\r\n const basePlane = super.getPlane(zIndex);\r\n if (!basePlane) {\r\n return basePlane;\r\n }\r\n let decorated = this.planeCache.get(basePlane);\r\n if (!decorated) {\r\n decorated = new ExplorationPlane(basePlane, this.visitedRooms);\r\n this.planeCache.set(basePlane, decorated);\r\n }\r\n return decorated;\r\n }\r\n\r\n override getPlanes() {\r\n return super.getPlanes().map(plane => {\r\n let decorated = this.planeCache.get(plane);\r\n if (!decorated) {\r\n decorated = new ExplorationPlane(plane, this.visitedRooms);\r\n this.planeCache.set(plane, decorated);\r\n }\r\n return decorated;\r\n });\r\n }\r\n\r\n override getLinkExits(zIndex: number) {\r\n return super\r\n .getLinkExits(zIndex)\r\n .filter((exit: Exit) => this.visitedRooms.has(exit.a) || this.visitedRooms.has(exit.b));\r\n }\r\n\r\n getVisitedRoomCount() {\r\n return super.getRooms().reduce((count, room) => count + (this.visitedRooms.has(room.id) ? 1 : 0), 0);\r\n }\r\n\r\n getTotalRoomCount() {\r\n return this.areaRoomIds.size;\r\n }\r\n\r\n hasVisitedRoom(roomId: number) {\r\n return this.areaRoomIds.has(roomId) && this.visitedRooms.has(roomId);\r\n }\r\n\r\n getVisitedRoomIds() {\r\n return super.getRooms()\r\n .filter(room => this.visitedRooms.has(room.id))\r\n .map(room => room.id);\r\n }\r\n\r\n addVisitedRoom(roomId: number) {\r\n const wasVisited = this.visitedRooms.has(roomId);\r\n this.visitedRooms.add(roomId);\r\n const newlyVisited = !wasVisited && this.areaRoomIds.has(roomId);\r\n if (newlyVisited) {\r\n this.markDirty();\r\n }\r\n return newlyVisited;\r\n }\r\n\r\n addVisitedRooms(roomIds: Iterable<number>) {\r\n let newlyVisited = 0;\r\n for (const roomId of roomIds) {\r\n const wasVisited = this.visitedRooms.has(roomId);\r\n this.visitedRooms.add(roomId);\r\n if (!wasVisited && this.areaRoomIds.has(roomId)) {\r\n newlyVisited++;\r\n }\r\n }\r\n if (newlyVisited > 0) {\r\n this.markDirty();\r\n }\r\n return newlyVisited;\r\n }\r\n\r\n}\r\n","import Area from \"./Area\";\r\nimport ExplorationArea from \"./ExplorationArea\";\r\n\r\ninterface Color {\r\n rgb: number[];\r\n rgbValue: string;\r\n symbolColor: number[];\r\n symbolColorValue: string,\r\n}\r\n\r\nconst defaultColor: Color = {\r\n rgb: [114, 1, 0],\r\n rgbValue: 'rgb(114, 1, 0)',\r\n symbolColor: [225, 225, 225],\r\n symbolColorValue: 'rgb(225,225,225)'\r\n}\r\n\r\nfunction calculateLuminance(rgb: number[]) {\r\n const rn = rgb[0] / 255;\r\n const gn = rgb[1] / 255;\r\n const bn = rgb[2] / 255;\r\n\r\n const max = Math.max(rn, gn, bn);\r\n const min = Math.min(rn, gn, bn);\r\n\r\n return (max + min) / 2;\r\n}\r\n\r\nexport default class MapReader {\r\n\r\n private rooms: Record<number, MapData.Room> = {};\r\n private areas: Record<number, Area> = {};\r\n private areaSources: Record<number, MapData.Area> = {};\r\n private visitedRooms?: Set<number>;\r\n private explorationEnabled = false;\r\n private colors: Record<number, Color> = {};\r\n\r\n constructor(map: MapData.Map, envs: MapData.Env[]) {\r\n map.forEach(area => {\r\n area.rooms.forEach(room => {\r\n room.y = -room.y;\r\n this.rooms[room.id] = room;\r\n })\r\n const areaId = parseInt(area.areaId);\r\n this.areas[areaId] = new Area(area);\r\n this.areaSources[areaId] = area;\r\n })\r\n this.colors = envs.reduce((acc, c) => ({\r\n ...acc,\r\n [c.envId]: {\r\n rgb: c.colors,\r\n rgbValue: `rgb(${c.colors.join(',')}`,\r\n symbolColor: calculateLuminance(c.colors) > 0.41 ? [25, 25, 25] : [225, 255, 255],\r\n symbolColorValue: calculateLuminance(c.colors) > 0.41 ? 'rgb(25,25,25)' : 'rgb(225,255,255)'\r\n }\r\n }), {});\r\n }\r\n\r\n getArea(areaId: number) {\r\n return this.areas[areaId];\r\n }\r\n\r\n getExplorationArea(areaId: number) {\r\n const area = this.areas[areaId];\r\n if (area instanceof ExplorationArea) {\r\n return area;\r\n }\r\n return undefined;\r\n }\r\n\r\n getAreas() {\r\n return Object.values(this.areas);\r\n }\r\n\r\n getRooms() {\r\n return Object.values(this.rooms);\r\n }\r\n\r\n getRoom(roomId: number) {\r\n return this.rooms[roomId];\r\n }\r\n\r\n private ensureVisitedRooms() {\r\n if (!this.visitedRooms) {\r\n this.visitedRooms = new Set();\r\n }\r\n return this.visitedRooms;\r\n }\r\n\r\n private applyExplorationDecoration() {\r\n if (!this.visitedRooms) {\r\n return;\r\n }\r\n Object.entries(this.areaSources).forEach(([id, area]) => {\r\n const numericId = parseInt(id, 10);\r\n this.areas[numericId] = new ExplorationArea(area, this.visitedRooms);\r\n });\r\n }\r\n\r\n decorateWithExploration(visitedRooms?: Iterable<number> | Set<number>) {\r\n if (visitedRooms !== undefined) {\r\n this.setVisitedRooms(visitedRooms);\r\n } else {\r\n this.ensureVisitedRooms();\r\n }\r\n this.applyExplorationDecoration();\r\n this.explorationEnabled = true;\r\n return this.visitedRooms;\r\n }\r\n\r\n getVisitedRooms() {\r\n return this.visitedRooms;\r\n }\r\n\r\n clearExplorationDecoration() {\r\n Object.entries(this.areaSources).forEach(([id, area]) => {\r\n const numericId = parseInt(id, 10);\r\n this.areas[numericId] = new Area(area);\r\n });\r\n this.explorationEnabled = false;\r\n }\r\n\r\n isExplorationEnabled() {\r\n return this.explorationEnabled;\r\n }\r\n\r\n setVisitedRooms(visitedRooms: Iterable<number> | Set<number>) {\r\n this.visitedRooms = visitedRooms instanceof Set ? visitedRooms : new Set(visitedRooms);\r\n if (this.explorationEnabled) {\r\n this.applyExplorationDecoration();\r\n }\r\n return this.visitedRooms;\r\n }\r\n\r\n addVisitedRoom(roomId: number) {\r\n if (this.explorationEnabled) {\r\n const room = this.getRoom(roomId);\r\n if (room) {\r\n const area = this.getExplorationArea(room.area);\r\n if (area) {\r\n return area.addVisitedRoom(roomId);\r\n }\r\n }\r\n }\r\n const visitedRooms = this.ensureVisitedRooms();\r\n const wasVisited = visitedRooms.has(roomId);\r\n visitedRooms.add(roomId);\r\n return !wasVisited;\r\n }\r\n\r\n addVisitedRooms(roomIds: Iterable<number>) {\r\n const visitedRooms = this.ensureVisitedRooms();\r\n let newlyVisited = 0;\r\n for (const roomId of roomIds) {\r\n if (this.explorationEnabled) {\r\n const room = this.getRoom(roomId);\r\n if (room) {\r\n const area = this.getExplorationArea(room.area);\r\n if (area) {\r\n if (area.addVisitedRoom(roomId)) {\r\n newlyVisited++;\r\n }\r\n continue;\r\n }\r\n }\r\n }\r\n const wasVisited = visitedRooms.has(roomId);\r\n visitedRooms.add(roomId);\r\n if (!wasVisited) {\r\n newlyVisited++;\r\n }\r\n }\r\n return newlyVisited;\r\n }\r\n\r\n hasVisitedRoom(roomId: number) {\r\n return this.visitedRooms?.has(roomId) ?? false;\r\n }\r\n\r\n getColorValue(envId: number): string {\r\n return this.colors[envId]?.rgbValue ?? defaultColor.rgbValue;\r\n }\r\n\r\n getSymbolColor(envId: number, opacity?: number): string {\r\n const color = this.colors[envId]?.symbolColor ?? defaultColor.symbolColor;\r\n const normalizedOpacity = Math.min(Math.max(opacity ?? 1, 0), 1);\r\n const value = color.join(',');\r\n if (normalizedOpacity != 1) {\r\n return `rgba(${value}, ${normalizedOpacity})`;\r\n }\r\n return `rgba(${value})`;\r\n }\r\n\r\n}","/**\n * This very basic implementation of a priority queue is used to select the\n * next node of the graph to walk to.\n *\n * The queue is always sorted to have the least expensive node on top.\n * Some helper methods are also implemented.\n *\n * You should **never** modify the queue directly, but only using the methods\n * provided by the class.\n */\nclass PriorityQueue {\n /**\n * Creates a new empty priority queue\n */\n constructor() {\n // The `keys` set is used to greatly improve the speed at which we can\n // check the presence of a value in the queue\n this.keys = new Set();\n this.queue = [];\n }\n\n /**\n * Sort the queue to have the least expensive node to visit on top\n *\n * @private\n */\n sort() {\n this.queue.sort((a, b) => a.priority - b.priority);\n }\n\n /**\n * Sets a priority for a key in the queue.\n * Inserts it in the queue if it does not already exists.\n *\n * @param {any} key Key to update or insert\n * @param {number} value Priority of the key\n * @return {number} Size of the queue\n */\n set(key, value) {\n const priority = Number(value);\n if (isNaN(priority)) throw new TypeError('\"priority\" must be a number');\n\n if (!this.keys.has(key)) {\n // Insert a new entry if the key is not already in the queue\n this.keys.add(key);\n this.queue.push({ key, priority });\n } else {\n // Update the priority of an existing key\n this.queue.map((element) => {\n if (element.key === key) {\n Object.assign(element, { priority });\n }\n\n return element;\n });\n }\n\n this.sort();\n return this.queue.length;\n }\n\n /**\n * The next method is used to dequeue a key:\n * It removes the first element from the queue and returns it\n *\n * @return {object} First priority queue entry\n */\n next() {\n const element = this.queue.shift();\n\n // Remove the key from the `_keys` set\n this.keys.delete(element.key);\n\n return element;\n }\n\n /**\n * @return {boolean} `true` when the queue is empty\n */\n isEmpty() {\n return Boolean(this.queue.length === 0);\n }\n\n /**\n * Check if the queue has a key in it\n *\n * @param {any} key Key to lookup\n * @return {boolean}\n */\n has(key) {\n return this.keys.has(key);\n }\n\n /**\n * Get the element in the queue with the specified key\n *\n * @param {any} key Key to lookup\n * @return {object}\n */\n get(key) {\n return this.queue.find((element) => element.key === key);\n }\n}\n\nmodule.exports = PriorityQueue;\n","/**\n * Removes a key and all of its references from a map.\n * This function has no side-effects as it returns\n * a brand new map.\n *\n * @param {Map} map - Map to remove the key from\n * @param {string} key - Key to remove from the map\n * @return {Map} New map without the passed key\n */\nfunction removeDeepFromMap(map, key) {\n const newMap = new Map();\n\n for (const [aKey, val] of map) {\n if (aKey !== key && val instanceof Map) {\n newMap.set(aKey, removeDeepFromMap(val, key));\n } else if (aKey !== key) {\n newMap.set(aKey, val);\n }\n }\n\n return newMap;\n}\n\nmodule.exports = removeDeepFromMap;\n","/**\n * Validates a cost for a node\n *\n * @private\n * @param {number} val - Cost to validate\n * @return {bool}\n */\nfunction isValidNode(val) {\n const cost = Number(val);\n\n if (isNaN(cost) || cost <= 0) {\n return false;\n }\n\n return true;\n}\n\n/**\n * Creates a deep `Map` from the passed object.\n *\n * @param {Object} source - Object to populate the map with\n * @return {Map} New map with the passed object data\n */\nfunction toDeepMap(source) {\n const map = new Map();\n const keys = Object.keys(source);\n\n keys.forEach((key) => {\n const val = source[key];\n\n if (val !== null && typeof val === \"object\" && !Array.isArray(val)) {\n return map.set(key, toDeepMap(val));\n }\n\n if (!isValidNode(val)) {\n throw new Error(\n `Could not add node at key \"${key}\", make sure it's a valid node`,\n val\n );\n }\n\n return map.set(key, Number(val));\n });\n\n return map;\n}\n\nmodule.exports = toDeepMap;\n","/**\n * Validate a map to ensure all it's values are either a number or a map\n *\n * @param {Map} map - Map to valiadte\n */\nfunction validateDeep(map) {\n if (!(map instanceof Map)) {\n throw new Error(`Invalid graph: Expected Map instead found ${typeof map}`);\n }\n\n map.forEach((value, key) => {\n if (typeof value === \"object\" && value instanceof Map) {\n validateDeep(value);\n return;\n }\n\n if (typeof value !== \"number\" || value <= 0) {\n throw new Error(\n `Values must be numbers greater than 0. Found value ${value} at ${key}`\n );\n }\n });\n}\n\nmodule.exports = validateDeep;\n","const Queue = require(\"./PriorityQueue\");\nconst removeDeepFromMap = require(\"./removeDeepFromMap\");\nconst toDeepMap = require(\"./toDeepMap\");\nconst validateDeep = require(\"./validateDeep\");\n\n/** Creates and manages a graph */\nclass Graph {\n /**\n * Creates a new Graph, optionally initializing it a nodes graph representation.\n *\n * A graph representation is an object that has as keys the name of the point and as values\n * the points reacheable from that node, with the cost to get there:\n *\n * {\n * node (Number|String): {\n * neighbor (Number|String): cost (Number),\n * ...,\n * },\n * }\n *\n * In alternative to an object, you can pass a `Map` of `Map`. This will\n * allow you to specify numbers as keys.\n *\n * @param {Objec|Map} [graph] - Initial graph definition\n * @example\n *\n * const route = new Graph();\n *\n * // Pre-populated graph\n * const route = new Graph({\n * A: { B: 1 },\n * B: { A: 1, C: 2, D: 4 },\n * });\n *\n * // Passing a Map\n * const g = new Map()\n *\n * const a = new Map()\n * a.set('B', 1)\n *\n * const b = new Map()\n * b.set('A', 1)\n * b.set('C', 2)\n * b.set('D', 4)\n *\n * g.set('A', a)\n * g.set('B', b)\n *\n * const route = new Graph(g)\n */\n constructor(graph) {\n if (graph instanceof Map) {\n validateDeep(graph);\n this.graph = graph;\n } else if (graph) {\n this.graph = toDeepMap(graph);\n } else {\n this.graph = new Map();\n }\n }\n\n /**\n * Adds a node to the graph\n *\n * @param {string} name - Name of the node\n * @param {Object|Map} neighbors - Neighbouring nodes and cost to reach them\n * @return {this}\n * @example\n *\n * const route = new Graph();\n *\n * route.addNode('A', { B: 1 });\n *\n * // It's possible to chain the calls\n * route\n * .addNode('B', { A: 1 })\n * .addNode('C', { A: 3 });\n *\n * // The neighbors can be expressed in a Map\n * const d = new Map()\n * d.set('A', 2)\n * d.set('B', 8)\n *\n * route.addNode('D', d)\n */\n addNode(name, neighbors) {\n let nodes;\n if (neighbors instanceof Map) {\n validateDeep(neighbors);\n nodes = neighbors;\n } else {\n nodes = toDeepMap(neighbors);\n }\n\n this.graph.set(name, nodes);\n\n return this;\n }\n\n /**\n * @deprecated since version 2.0, use `Graph#addNode` instead\n */\n addVertex(name, neighbors) {\n return this.addNode(name, neighbors);\n }\n\n /**\n * Removes a node and all of its references from the graph\n *\n * @param {string|number} key - Key of the node to remove from the graph\n * @return {this}\n * @example\n *\n * const route = new Graph({\n * A: { B: 1, C: 5 },\n * B: { A: 3 },\n * C: { B: 2, A: 2 },\n * });\n *\n * route.removeNode('C');\n * // The graph now is:\n * // { A: { B: 1 }, B: { A: 3 } }\n */\n removeNode(key) {\n this.graph = removeDeepFromMap(this.graph, key);\n\n return this;\n }\n\n /**\n * Compute the shortest path between the specified nodes\n *\n * @param {string} start - Starting node\n * @param {string} goal - Node we want to reach\n * @param {object} [options] - Options\n *\n * @param {boolean} [options.trim] - Exclude the origin and destination nodes from the result\n * @param {boolean} [options.reverse] - Return the path in reversed order\n * @param {boolean} [options.cost] - Also return the cost of the path when set to true\n *\n * @return {array|object} Computed path between the nodes.\n *\n * When `option.cost` is set to true, the returned value will be an object with shape:\n * - `path` *(Array)*: Computed path between the nodes\n * - `cost` *(Number)*: Cost of the path\n *\n * @example\n *\n * const route = new Graph()\n *\n * route.addNode('A', { B: 1 })\n * route.addNode('B', { A: 1, C: 2, D: 4 })\n * route.addNode('C', { B: 2, D: 1 })\n * route.addNode('D', { C: 1, B: 4 })\n *\n * route.path('A', 'D') // => ['A', 'B', 'C', 'D']\n *\n * // trimmed\n * route.path('A', 'D', { trim: true }) // => [B', 'C']\n *\n * // reversed\n * route.path('A', 'D', { reverse: true }) // => ['D', 'C', 'B', 'A']\n *\n * // include the cost\n * route.path('A', 'D', { cost: true })\n * // => {\n * // path: [ 'A', 'B', 'C', 'D' ],\n * // cost: 4\n * // }\n */\n path(start, goal, options = {}) {\n // Don't run when we don't have nodes set\n if (!this.graph.size) {\n if (options.cost) return { path: null, cost: 0 };\n\n return null;\n }\n\n const explored = new Set();\n const frontier = new Queue();\n const previous = new Map();\n\n let path = [];\n let totalCost = 0;\n\n let avoid = [];\n if (options.avoid) avoid = [].concat(options.avoid);\n\n if (avoid.includes(start)) {\n throw new Error(`Starting node (${start}) cannot be avoided`);\n } else if (avoid.includes(goal)) {\n throw new Error(`Ending node (${goal}) cannot be avoided`);\n }\n\n // Add the starting point to the frontier, it will be the first node visited\n frontier.set(start, 0);\n\n // Run until we have visited every node in the frontier\n while (!frontier.isEmpty()) {\n // Get the node in the frontier with the lowest cost (`priority`)\n const node = frontier.next();\n\n // When the node with the lowest cost in the frontier in our goal node,\n // we can compute the path and exit the loop\n if (node.key === goal) {\n // Set the total cost to the current value\n totalCost = node.priority;\n\n let nodeKey = node.key;\n while (previous.has(nodeKey)) {\n path.push(nodeKey);\n nodeKey = previous.get(nodeKey);\n }\n\n break;\n }\n\n // Add the current node to the explored set\n explored.add(node.key);\n\n // Loop all the neighboring nodes\n const neighbors = this.graph.get(node.key) || new Map();\n neighbors.forEach((nCost, nNode) => {\n // If we already explored the node, or the node is to be avoided, skip it\n if (explored.has(nNode) || avoid.includes(nNode)) return null;\n\n // If the neighboring node is not yet in the frontier, we add it with\n // the correct cost\n if (!frontier.has(nNode)) {\n previous.set(nNode, node.key);\n return frontier.set(nNode, node.priority + nCost);\n }\n\n const frontierPriority = frontier.get(nNode).priority;\n const nodeCost = node.priority + nCost;\n\n // Otherwise we only update the cost of this node in the frontier when\n // it's below what's currently set\n if (nodeCost < frontierPriority) {\n previous.set(nNode, node.key);\n return frontier.set(nNode, nodeCost);\n }\n\n return null;\n });\n }\n\n // Return null when no path can be found\n if (!path.length) {\n if (options.cost) return { path: null, cost: 0 };\n\n return null;\n }\n\n // From now on, keep in mind that `path` is populated in reverse order,\n // from destination to origin\n\n // Remove the first value (the goal node) if we want a trimmed result\n if (options.trim) {\n path.shift();\n } else {\n // Add the origin waypoint at the end of the array\n path = path.concat([start]);\n }\n\n // Reverse the path if we don't want it reversed, so the result will be\n // from `start` to `goal`\n if (!options.reverse) {\n path = path.reverse();\n }\n\n // Return an object if we also want the cost\n if (options.cost) {\n return {\n path,\n cost: totalCost,\n };\n }\n\n return path;\n }\n\n /**\n * @deprecated since version 2.0, use `Graph#path` instead\n */\n shortestPath(...args) {\n return this.path(...args);\n }\n}\n\nmodule.exports = Graph;\n","import Graph from \"node-dijkstra\";\r\nimport MapReader from \"./reader/MapReader\";\r\n\r\nconst exitNumberToDirection: Record<number, MapData.direction> = {\r\n 1: \"north\",\r\n 2: \"northeast\",\r\n 3: \"northwest\",\r\n 4: \"east\",\r\n 5: \"west\",\r\n 6: \"south\",\r\n 7: \"southeast\",\r\n 8: \"southwest\",\r\n 9: \"up\",\r\n 10: \"down\",\r\n 11: \"in\",\r\n 12: \"out\",\r\n};\r\n\r\ntype GraphDefinition = Record<string, Record<string, number>>;\r\n\r\nexport default class PathFinder {\r\n\r\n private readonly mapReader: MapReader;\r\n private readonly graph: Graph;\r\n private readonly cache = new Map<string, Array<number> | null>();\r\n\r\n constructor(mapReader: MapReader) {\r\n this.mapReader = mapReader;\r\n this.graph = this.buildGraph();\r\n }\r\n\r\n private buildGraph(): Graph {\r\n const graphDefinition: GraphDefinition = {};\r\n this.mapReader.getRooms().forEach(room => {\r\n const connections: Record<string, number> = {};\r\n\r\n const lockedDirections = new Set(\r\n (room.exitLocks ?? [])\r\n .map(lockId => exitNumberToDirection[lockId])\r\n .filter((direction): direction is MapData.direction => Boolean(direction))\r\n );\r\n\r\n const lockedSpecialTargets = new Set(room.mSpecialExitLocks ?? []);\r\n\r\n Object.entries(room.exits ?? {}).forEach(([direction, targetRoomId]) => {\r\n if (lockedDirections.has(direction as MapData.direction)) {\r\n return;\r\n }\r\n if (this.mapReader.getRoom(targetRoomId)) {\r\n connections[targetRoomId.toString()] = 1;\r\n }\r\n });\r\n\r\n Object.values(room.specialExits ?? {}).forEach(targetRoomId => {\r\n if (lockedSpecialTargets.has(targetRoomId)) {\r\n return;\r\n }\r\n if (this.mapReader.getRoom(targetRoomId)) {\r\n connections[targetRoomId.toString()] = 1;\r\n }\r\n });\r\n\r\n graphDefinition[room.id.toString()] = connections;\r\n });\r\n\r\n return new Graph(graphDefinition);\r\n }\r\n\r\n findPath(from: number, to: number): Array<number> | null {\r\n const cacheKey = `${from}->${to}`;\r\n if (this.cache.has(cacheKey)) {\r\n return this.cache.get(cacheKey)!;\r\n }\r\n\r\n if (from === to) {\r\n const result = this.mapReader.getRoom(from) ? [from] : null;\r\n this.cache.set(cacheKey, result);\r\n return result;\r\n }\r\n\r\n if (!this.mapReader.getRoom(from) || !this.mapReader.getRoom(to)) {\r\n this.cache.set(cacheKey, null);\r\n return null;\r\n }\r\n\r\n const path = this.graph.path(from.toString(), to.toString());\r\n const nodes = Array.isArray(path) ? path : path?.path;\r\n const result = nodes ? nodes.map((id: string) => Number(id)) : null;\r\n this.cache.set(cacheKey, result);\r\n return result;\r\n }\r\n}\r\n\r\n"],"names":["regularExits","longToShort","planarDirectionOffsets","planarDirections","oppositeDirections","isPlanarDirection","direction","movePoint","x","y","distance","offset","Colors","dirNumbers","innerExits","getDoorColor","doorType","ExitRenderer","mapReader","exit","sourceRoom","targetRoom","exitRender","Konva","points","Settings","door","link","dir","targetPoint","startPoint","middlePointX","middlePointY","group","arrow","room","start","end","_","line","acc","point","construct","lineRender","style","stub","render","triangle","inRender","outRender","type","PathRenderer","overlayLayer","locations","currentArea","currentZIndex","color","rooms","location","segments","currentSegment","finalizeSegment","ensureSegment","index","previousRoom","nextRoom","segment","directionToPrevious","directionToNext","endPoint","paths","path","from","to","defaultRoomSize","defaultZoom","lineColor","_Settings","Renderer","container","scaleBy","lastPinchDistance","lastPinchCenter","dragStopped","e","oldScale","pointer","mousePointTo","newZoom","newScale","zoomChanged","newPos","touches","touch1","touch2","rect","p1","p2","newCenter","pointTo","dx","dy","id","zIndex","area","plane","roomId","clientX","clientY","bounds","detail","event","zoom","areaVersion","instant","existing","highlightData","shape","highlight","_a","roomCenter","screenPoint","target","roomRender","roomRect","emitContextEvent","pointerEvent","longPressTimeout","longPressStart","stageDraggableBeforeLongPress","restoreStageDraggable","clearLongPressTimeout","touch","distanceSquared","movementThreshold","wasDraggable","roomChar","exits","Labels","label","image","labelRender","Plane","labels","r","Area","grouped","z","targetRoomId","originRoom","a","b","key","edge","ExplorationPlane","visitedRooms","ExplorationArea","basePlane","decorated","count","wasVisited","newlyVisited","roomIds","defaultColor","calculateLuminance","rgb","rn","gn","bn","max","min","MapReader","map","envs","areaId","c","numericId","envId","opacity","normalizedOpacity","value","PriorityQueue","priority","element","PriorityQueue_1","removeDeepFromMap","newMap","aKey","val","removeDeepFromMap_1","isValidNode","cost","toDeepMap","source","toDeepMap_1","validateDeep","validateDeep_1","Queue","require$$0","require$$1","require$$2","require$$3","Graph","graph","name","neighbors","nodes","goal","options","explored","frontier","previous","totalCost","avoid","node","nodeKey","nCost","nNode","frontierPriority","nodeCost","args","Graph_1","exitNumberToDirection","PathFinder","graphDefinition","connections","lockedDirections","lockId","lockedSpecialTargets","cacheKey","result"],"mappings":"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","x_google_ignoreList":[9,10,11,12,13]}
|
|
1
|
+
{"version":3,"file":"index.cjs","sources":["../src/reader/Exit.ts","../src/directions.ts","../src/ExitRenderer.ts","../src/PathRenderer.ts","../src/Renderer.ts","../src/reader/Plane.ts","../src/reader/Area.ts","../src/reader/ExplorationArea.ts","../src/reader/MapReader.ts","../node_modules/node-dijkstra/libs/PriorityQueue.js","../node_modules/node-dijkstra/libs/removeDeepFromMap.js","../node_modules/node-dijkstra/libs/toDeepMap.js","../node_modules/node-dijkstra/libs/validateDeep.js","../node_modules/node-dijkstra/libs/Graph.js","../src/PathFinder.ts"],"sourcesContent":["export type Kind = \"exit\" | \"specialExit\";\r\n\r\nexport default interface Exit {\r\n a: number;\r\n b: number;\r\n aDir?: MapData.direction;\r\n bDir?: MapData.direction;\r\n kind?: Kind;\r\n zIndex: number[];\r\n}\r\n\r\nexport const regularExits: MapData.direction[] = [\"north\", \"south\", \"east\", \"west\", \"northeast\", \"northwest\", \"southeast\", \"southwest\"];\r\nexport const shortTolong: Record<string, MapData.direction> = {\r\n \"n\": \"north\",\r\n \"s\": \"south\",\r\n \"e\": \"east\",\r\n \"w\": \"west\",\r\n \"ne\": \"northeast\",\r\n \"nw\": \"northwest\",\r\n \"se\": \"southeast\",\r\n \"sw\": \"southwest\",\r\n}\r\nexport const longToShort: Record<MapData.direction, string> = {\r\n \"north\": \"n\",\r\n \"south\": \"s\",\r\n \"east\": \"e\",\r\n \"west\": \"w\",\r\n \"northeast\": \"ne\",\r\n \"northwest\": \"nw\",\r\n \"southeast\": \"se\",\r\n \"southwest\": \"sw\",\r\n \"up\": \"u\",\r\n \"down\": \"d\",\r\n \"in\": \"i\",\r\n \"out\": \"o\"\r\n}\r\n","export type PlanarDirection =\r\n | \"north\"\r\n | \"south\"\r\n | \"east\"\r\n | \"west\"\r\n | \"northeast\"\r\n | \"northwest\"\r\n | \"southeast\"\r\n | \"southwest\";\r\n\r\nconst planarDirectionOffsets: Record<PlanarDirection, {x: number; y: number}> = {\r\n north: {x: 0, y: -1},\r\n south: {x: 0, y: 1},\r\n east: {x: 1, y: 0},\r\n west: {x: -1, y: 0},\r\n northeast: {x: 1, y: -1},\r\n northwest: {x: -1, y: -1},\r\n southeast: {x: 1, y: 1},\r\n southwest: {x: -1, y: 1},\r\n};\r\n\r\nexport const planarDirections: PlanarDirection[] = [\r\n \"north\",\r\n \"south\",\r\n \"east\",\r\n \"west\",\r\n \"northeast\",\r\n \"northwest\",\r\n \"southeast\",\r\n \"southwest\",\r\n];\r\n\r\nexport const oppositeDirections: Record<PlanarDirection, PlanarDirection> = {\r\n north: \"south\",\r\n south: \"north\",\r\n east: \"west\",\r\n west: \"east\",\r\n northeast: \"southwest\",\r\n northwest: \"southeast\",\r\n southeast: \"northwest\",\r\n southwest: \"northeast\",\r\n};\r\n\r\nfunction isPlanarDirection(direction: MapData.direction | undefined): direction is PlanarDirection {\r\n if (!direction) {\r\n return false;\r\n }\r\n return Object.prototype.hasOwnProperty.call(planarDirectionOffsets, direction);\r\n}\r\n\r\nexport function movePoint(\r\n x: number,\r\n y: number,\r\n direction?: MapData.direction,\r\n distance: number = 1,\r\n) {\r\n if (!isPlanarDirection(direction)) {\r\n return {x, y};\r\n }\r\n\r\n const offset = planarDirectionOffsets[direction];\r\n return {\r\n x: x + offset.x * distance,\r\n y: y + offset.y * distance,\r\n };\r\n}\r\n","import Exit, {longToShort} from \"./reader/Exit\";\r\nimport MapReader from \"./reader/MapReader\";\r\nimport Konva from \"konva\";\r\nimport {Settings} from \"./Renderer\";\r\nimport {movePoint} from \"./directions\";\r\n\r\nconst Colors = {\r\n OPEN_DOOR: 'rgb(10, 155, 10)',\r\n CLOSED_DOOR: 'rgb(226, 205, 59)',\r\n LOCKED_DOOR: 'rgb(155, 10, 10)'\r\n}\r\n\r\nconst dirNumbers: Record<number, MapData.direction> = {\r\n 1: \"north\",\r\n 2: \"northeast\",\r\n 3: \"northwest\",\r\n 4: \"east\",\r\n 5: \"west\",\r\n 6: \"south\",\r\n 7: \"southeast\",\r\n 8: \"southwest\",\r\n 9: \"up\",\r\n 10: \"down\",\r\n 11: \"in\",\r\n 12: \"out\",\r\n};\r\n\r\nconst innerExits: MapData.direction[] = [\"up\", \"down\", \"in\", \"out\"];\r\n\r\nfunction getDoorColor(doorType: 1 | 2 | 3) {\r\n switch (doorType) {\r\n case 1:\r\n return Colors.OPEN_DOOR\r\n case 2:\r\n return Colors.CLOSED_DOOR\r\n default:\r\n return Colors.LOCKED_DOOR\r\n }\r\n}\r\n\r\nexport default class ExitRenderer {\r\n\r\n private mapReader: MapReader;\r\n\r\n constructor(mapReader: MapReader) {\r\n this.mapReader = mapReader;\r\n }\r\n\r\n render(exit: Exit) {\r\n if (exit.aDir && exit.bDir) {\r\n return this.renderTwoWayExit(exit);\r\n } else {\r\n return this.renderOneWayExit(exit);\r\n }\r\n }\r\n\r\n private renderTwoWayExit(exit: Exit) {\r\n const sourceRoom = this.mapReader.getRoom(exit.a)\r\n const targetRoom = this.mapReader.getRoom(exit.b);\r\n\r\n if (!sourceRoom || !targetRoom || !exit.aDir || !exit.bDir) {\r\n return;\r\n }\r\n\r\n const exitRender = new Konva.Group();\r\n\r\n const points = []\r\n points.push(...Object.values(movePoint(sourceRoom.x, sourceRoom.y, exit.aDir, Settings.roomSize / 2)));\r\n points.push(...Object.values(movePoint(targetRoom.x, targetRoom.y, exit.bDir, Settings.roomSize / 2)));\r\n\r\n if (sourceRoom.doors[longToShort[exit.aDir]] || targetRoom.doors[longToShort[exit.bDir]]) {\r\n const door = this.renderDoor(points, sourceRoom.doors[longToShort[exit.aDir]] ?? targetRoom.doors[longToShort[exit.bDir]])\r\n exitRender.add(door);\r\n }\r\n\r\n const link = new Konva.Line({\r\n points,\r\n stroke: Settings.lineColor,\r\n strokeWidth: 0.025,\r\n });\r\n exitRender.add(link);\r\n\r\n return exitRender;\r\n }\r\n\r\n private renderOneWayExit(exit: Exit) {\r\n const sourceRoom = exit.aDir ? this.mapReader.getRoom(exit.a) : this.mapReader.getRoom(exit.b)\r\n const targetRoom = exit.aDir ? this.mapReader.getRoom(exit.b) : this.mapReader.getRoom(exit.a)\r\n const dir = exit.aDir ? exit.aDir : exit.bDir;\r\n\r\n if (!sourceRoom || !targetRoom) {\r\n return;\r\n }\r\n\r\n if (sourceRoom.area != targetRoom.area && dir) {\r\n return this.renderAreaExit(sourceRoom, dir);\r\n }\r\n\r\n let targetPoint = {x: targetRoom.x, y: targetRoom.y};\r\n if (targetRoom.area !== sourceRoom.area || targetRoom.z !== sourceRoom.z) {\r\n targetPoint = movePoint(sourceRoom.x, sourceRoom.y, dir, Settings.roomSize / 2);\r\n }\r\n\r\n const startPoint = movePoint(sourceRoom.x, sourceRoom.y, dir, 0.3);\r\n\r\n const middlePointX = startPoint.x - (startPoint.x - targetPoint.x) / 2;\r\n const middlePointY = startPoint.y - (startPoint.y - targetPoint.y) / 2;\r\n\r\n const group = new Konva.Group();\r\n const points = []\r\n points.push(...Object.values(movePoint(sourceRoom.x, sourceRoom.y, dir, Settings.roomSize / 2)));\r\n points.push(targetPoint.x, targetPoint.y);\r\n const link = new Konva.Line({\r\n points,\r\n stroke: Settings.lineColor,\r\n strokeWidth: 0.025,\r\n dashEnabled: true,\r\n dash: [0.1, 0.05],\r\n });\r\n group.add(link)\r\n\r\n const arrow = new Konva.Arrow({\r\n points: [points[0], points[1], middlePointX, middlePointY],\r\n pointerLength: 0.5,\r\n pointerWidth: 0.35,\r\n strokeWidth: 0.035,\r\n stroke: Settings.lineColor,\r\n fill: '#FF0000',\r\n dashEnabled: true,\r\n dash: [0.1, 0.05],\r\n })\r\n\r\n group.add(arrow)\r\n\r\n return group;\r\n }\r\n\r\n renderAreaExit(room: MapData.Room, dir: MapData.direction) {\r\n const start = movePoint(room.x, room.y, dir, Settings.roomSize / 2)\r\n const end = movePoint(room.x, room.y, dir, Settings.roomSize * 1.5)\r\n return new Konva.Arrow({\r\n points: [start.x, start.y, end.x, end.y],\r\n pointerLength: 0.3,\r\n pointerWidth: 0.3,\r\n strokeWidth: 0.035,\r\n stroke: this.mapReader.getColorValue(room.env),\r\n fill: this.mapReader.getColorValue(room.env),\r\n })\r\n }\r\n\r\n renderSpecialExits(room: MapData.Room) {\r\n return Object.entries(room.customLines).map(([_, line]) => {\r\n const points = [room.x, room.y]\r\n line.points.reduce((acc, point) => {\r\n acc.push(point.x, -point.y);\r\n return acc;\r\n }, points)\r\n\r\n const construct = line.attributes.arrow ? Konva.Arrow : Konva.Line;\r\n const lineRender = new construct({\r\n points: points,\r\n strokeWidth: .025,\r\n stroke: `rgb(${line.attributes.color.r}, ${line.attributes.color.g}, ${line.attributes.color.b})`,\r\n fill: `rgb(${line.attributes.color.r}, ${line.attributes.color.g} , ${line.attributes.color.b})`,\r\n pointerLength: 0.3,\r\n pointerWidth: 0.2,\r\n\r\n })\r\n\r\n let style = line.attributes.style;\r\n if (style === \"dot line\") {\r\n lineRender.dash([0.05, 0.05])\r\n lineRender.dashOffset(0.1)\r\n } else if (style === \"dash line\") {\r\n lineRender.dash([0.4, 0.2])\r\n } else if (style === \"solid line\") {\r\n } else if (style !== undefined) {\r\n console.log(\"Brak opisu stylu: \" + style);\r\n }\r\n\r\n return lineRender;\r\n })\r\n }\r\n\r\n renderStubs(room: MapData.Room) {\r\n return room.stubs.map(stub => {\r\n const direction = dirNumbers[stub];\r\n const start = movePoint(room.x, room.y, direction, Settings.roomSize / 2)\r\n const end = movePoint(room.x, room.y, direction, Settings.roomSize / 2 + 0.5)\r\n const points = [start.x, start.y, end.x, end.y]\r\n return new Konva.Line({\r\n points,\r\n stroke: Settings.lineColor,\r\n strokeWidth: 0.025,\r\n });\r\n })\r\n }\r\n\r\n renderInnerExits(room: MapData.Room) {\r\n return innerExits.map(exit => {\r\n if (room.exits[exit]) {\r\n const render = new Konva.Group();\r\n const triangle = new Konva.RegularPolygon({\r\n x: room.x,\r\n y: room.y,\r\n sides: 3,\r\n fill: this.mapReader.getSymbolColor(room.env, 0.6),\r\n stroke: this.mapReader.getSymbolColor(room.env),\r\n strokeWidth: 0.025,\r\n radius: Settings.roomSize / 5,\r\n scaleX: 1.4,\r\n scaleY: 0.8\r\n })\r\n render.add(triangle);\r\n\r\n let doorType = room.doors[exit];\r\n if (doorType !== undefined) {\r\n switch (doorType) {\r\n case 1:\r\n triangle.stroke(Colors.OPEN_DOOR)\r\n break;\r\n case 2:\r\n triangle.stroke(Colors.CLOSED_DOOR);\r\n break;\r\n default:\r\n triangle.stroke(Colors.LOCKED_DOOR);\r\n }\r\n }\r\n\r\n switch (exit) {\r\n case \"up\":\r\n triangle.position(movePoint(room.x, room.y, \"south\", Settings.roomSize / 4));\r\n break;\r\n case \"down\":\r\n triangle.rotation(180);\r\n triangle.position(movePoint(room.x, room.y, \"north\", Settings.roomSize / 4));\r\n break;\r\n case \"in\":\r\n const inRender = triangle.clone()\r\n inRender.rotation(-90);\r\n inRender.position(movePoint(room.x, room.y, \"east\", Settings.roomSize / 4));\r\n render.add(inRender);\r\n triangle.rotation(90);\r\n triangle.position(movePoint(room.x, room.y, \"west\", Settings.roomSize / 4));\r\n break;\r\n case \"out\":\r\n const outRender = triangle.clone()\r\n outRender.rotation(90);\r\n outRender.position(movePoint(room.x, room.y, \"east\", Settings.roomSize / 4));\r\n render.add(outRender);\r\n triangle.rotation(-90);\r\n triangle.position(movePoint(room.x, room.y, \"west\", Settings.roomSize / 4));\r\n break;\r\n }\r\n return render\r\n }\r\n }).filter(e => e !== undefined)\r\n }\r\n\r\n renderDoor(points: number[], type: 1 | 2 | 3) {\r\n const point = {\r\n x: points[0] + (points[2] - points[0]) / 2,\r\n y: points[1] + (points[3] - points[1]) / 2,\r\n }\r\n return new Konva.Rect({\r\n x: point.x - Settings.roomSize / 4,\r\n y: point.y - Settings.roomSize / 4,\r\n width: Settings.roomSize / 2,\r\n height: Settings.roomSize / 2,\r\n stroke: getDoorColor(type),\r\n strokeWidth: 0.025\r\n })\r\n }\r\n\r\n}","import Konva from \"konva\";\r\nimport MapReader from \"./reader/MapReader\";\r\nimport {Settings} from \"./Renderer\";\r\nimport {movePoint, PlanarDirection, planarDirections, oppositeDirections} from \"./directions\";\r\n\r\nexport default class PathRenderer {\r\n private readonly mapReader: MapReader;\r\n private readonly overlayLayer: Konva.Layer;\r\n private paths: Konva.Line[] = [];\r\n\r\n constructor(mapReader: MapReader, overlayLayer: Konva.Layer) {\r\n this.mapReader = mapReader;\r\n this.overlayLayer = overlayLayer;\r\n }\r\n\r\n renderPath(locations: number[], currentArea?: number, currentZIndex?: number, color: string = '#66E64D') {\r\n if (currentArea === undefined || currentZIndex === undefined) {\r\n return;\r\n }\r\n\r\n const rooms = locations\r\n .map(location => this.mapReader.getRoom(location))\r\n .filter((room): room is MapData.Room => room !== undefined);\r\n\r\n const segments: number[][] = [];\r\n let currentSegment: number[] | null = null;\r\n\r\n const finalizeSegment = () => {\r\n if (!currentSegment) {\r\n return;\r\n }\r\n if (currentSegment.length < 4) {\r\n segments.pop();\r\n }\r\n currentSegment = null;\r\n };\r\n\r\n const ensureSegment = () => {\r\n if (!currentSegment) {\r\n currentSegment = [];\r\n segments.push(currentSegment);\r\n }\r\n return currentSegment;\r\n };\r\n\r\n rooms.forEach((room, index) => {\r\n if (!this.isRoomVisible(room, currentArea, currentZIndex)) {\r\n return;\r\n }\r\n\r\n const previousRoom = index > 0 ? rooms[index - 1] : undefined;\r\n const nextRoom = index < rooms.length - 1 ? rooms[index + 1] : undefined;\r\n const previousVisible = this.isRoomVisible(previousRoom, currentArea, currentZIndex);\r\n\r\n if (!previousVisible) {\r\n finalizeSegment();\r\n const segment = ensureSegment();\r\n if (previousRoom) {\r\n const directionToPrevious = this.getDirectionTowards(room, previousRoom);\r\n if (directionToPrevious) {\r\n const startPoint = movePoint(room.x, room.y, directionToPrevious, Settings.roomSize);\r\n segment.push(startPoint.x, startPoint.y);\r\n }\r\n }\r\n } else {\r\n ensureSegment();\r\n }\r\n\r\n currentSegment?.push(room.x, room.y);\r\n\r\n const nextVisible = this.isRoomVisible(nextRoom, currentArea, currentZIndex);\r\n if (!nextVisible && nextRoom) {\r\n const directionToNext = this.getDirectionTowards(room, nextRoom);\r\n if (directionToNext) {\r\n const endPoint = movePoint(room.x, room.y, directionToNext, Settings.roomSize);\r\n currentSegment?.push(endPoint.x, endPoint.y);\r\n }\r\n finalizeSegment();\r\n }\r\n });\r\n\r\n finalizeSegment();\r\n\r\n const paths = segments\r\n .filter(points => points.length >= 4)\r\n .map(points => new Konva.Line({\r\n points,\r\n stroke: color,\r\n strokeWidth: 0.1\r\n }));\r\n\r\n paths.forEach(path => {\r\n this.overlayLayer.add(path);\r\n this.paths.push(path);\r\n });\r\n\r\n return paths[0];\r\n }\r\n\r\n clearPaths() {\r\n this.paths.forEach(path => {\r\n path.destroy();\r\n });\r\n this.paths = [];\r\n }\r\n\r\n private isRoomVisible(room: MapData.Room | undefined, currentArea: number | undefined, currentZIndex: number | undefined) {\r\n if (!room) {\r\n return false;\r\n }\r\n return room.area === currentArea && room.z === currentZIndex;\r\n }\r\n\r\n private getDirectionTowards(from: MapData.Room, to: MapData.Room): PlanarDirection | undefined {\r\n for (const direction of planarDirections) {\r\n if (from.exits[direction] === to.id) {\r\n return direction;\r\n }\r\n }\r\n\r\n for (const direction of planarDirections) {\r\n if (to.exits[direction] === from.id) {\r\n return oppositeDirections[direction];\r\n }\r\n }\r\n\r\n return undefined;\r\n }\r\n}\r\n","import Konva from \"konva\";\r\nimport ExitRenderer from \"./ExitRenderer\";\r\nimport MapReader from \"./reader/MapReader\";\r\nimport Exit from \"./reader/Exit\";\r\nimport Area from \"./reader/Area\";\r\nimport PathRenderer from \"./PathRenderer\";\r\n\r\nconst defaultRoomSize = 0.6;\r\nconst defaultZoom = 75\r\nconst lineColor = 'rgb(225, 255, 225)';\r\n\r\nexport type RoomContextMenuEventDetail = {\r\n roomId: number;\r\n position: { x: number; y: number };\r\n};\r\n\r\nexport type ZoomChangeEventDetail = {\r\n zoom: number;\r\n};\r\n\r\nexport class Settings {\r\n static roomSize = defaultRoomSize;\r\n static lineColor = lineColor;\r\n static instantMapMove = false\r\n}\r\n\r\ntype HighlightData = {\r\n color: string;\r\n area: number;\r\n z: number;\r\n shape?: Konva.Circle;\r\n};\r\n\r\nexport class Renderer {\r\n\r\n private readonly stage: Konva.Stage;\r\n private readonly roomLayer: Konva.Layer;\r\n private readonly linkLayer: Konva.Layer;\r\n private readonly overlayLayer: Konva.Layer;\r\n private readonly positionLayer: Konva.Layer;\r\n private mapReader: MapReader;\r\n private exitRenderer: ExitRenderer;\r\n private pathRenderer: PathRenderer;\r\n private highlights: Map<number, HighlightData> = new Map();\r\n private currentArea?: number;\r\n private currentAreaInstance?: Area;\r\n private currentZIndex?: number;\r\n private currentAreaVersion?: number;\r\n private currentRoomId?: number;\r\n private positionRender?: Konva.Circle;\r\n private currentTransition?: Konva.Tween;\r\n private currentZoom: number = 1;\r\n\r\n constructor(container: HTMLDivElement, mapReader: MapReader) {\r\n this.stage = new Konva.Stage({\r\n container: container,\r\n width: container.clientWidth,\r\n height: container.clientHeight,\r\n draggable: true\r\n });\r\n window.addEventListener('resize', () => {\r\n this.onResize(container);\r\n })\r\n container.addEventListener('resize', () => {\r\n this.onResize(container);\r\n })\r\n this.linkLayer = new Konva.Layer({\r\n listening: false,\r\n });\r\n this.stage.add(this.linkLayer);\r\n this.roomLayer = new Konva.Layer();\r\n this.stage.add(this.roomLayer);\r\n this.overlayLayer = new Konva.Layer({\r\n listening: false,\r\n })\r\n this.stage.add(this.overlayLayer);\r\n this.positionLayer = new Konva.Layer({\r\n listening: false,\r\n });\r\n this.stage.add(this.positionLayer);\r\n this.mapReader = mapReader;\r\n this.exitRenderer = new ExitRenderer(mapReader);\r\n this.pathRenderer = new PathRenderer(mapReader, this.overlayLayer);\r\n\r\n const scaleBy = 1.1;\r\n this.initScaling(scaleBy);\r\n }\r\n\r\n private onResize(container: HTMLDivElement) {\r\n this.stage.width(container.clientWidth);\r\n this.stage.height(container.clientHeight);\r\n if (this.currentRoomId) {\r\n this.centerOnRoom(this.mapReader.getRoom(this.currentRoomId)!, false);\r\n }\r\n this.stage.batchDraw();\r\n }\r\n\r\n private initScaling(scaleBy: number) {\r\n Konva.hitOnDragEnabled = true;\r\n\r\n let lastPinchDistance: number | undefined;\r\n let lastPinchCenter: { x: number; y: number } | undefined;\r\n let dragStopped = false;\r\n\r\n this.stage.on('touchend touchcancel', () => {\r\n lastPinchDistance = undefined;\r\n lastPinchCenter = undefined;\r\n });\r\n\r\n this.stage.on('wheel', (e) => {\r\n e.evt.preventDefault();\r\n\r\n const oldScale = this.stage.scaleX();\r\n const pointer = this.stage.getPointerPosition();\r\n if (!pointer) {\r\n return;\r\n }\r\n\r\n const mousePointTo = {\r\n x: (pointer.x - this.stage.x()) / oldScale,\r\n y: (pointer.y - this.stage.y()) / oldScale,\r\n };\r\n\r\n let direction = e.evt.deltaY > 0 ? -1 : 1;\r\n\r\n if (e.evt.ctrlKey) {\r\n direction = -direction;\r\n }\r\n\r\n const newZoom = direction > 0 ? this.currentZoom * scaleBy : this.currentZoom / scaleBy;\r\n const newScale = newZoom * defaultZoom;\r\n const zoomChanged = this.setZoom(newZoom);\r\n\r\n const newPos = {\r\n x: pointer.x - mousePointTo.x * newScale,\r\n y: pointer.y - mousePointTo.y * newScale,\r\n };\r\n\r\n this.stage.position(newPos);\r\n\r\n if (zoomChanged) {\r\n this.emitZoomChangeEvent();\r\n }\r\n });\r\n\r\n this.stage.on('touchmove', (e) => {\r\n const touches = e.evt.touches;\r\n const touch1 = touches?.[0];\r\n const touch2 = touches?.[1];\r\n\r\n if (touch1 && !touch2 && dragStopped && !this.stage.isDragging()) {\r\n this.stage.startDrag();\r\n dragStopped = false;\r\n }\r\n\r\n if (!touch1 || !touch2) {\r\n lastPinchDistance = undefined;\r\n lastPinchCenter = undefined;\r\n return;\r\n }\r\n\r\n e.evt.preventDefault();\r\n\r\n if (this.stage.isDragging()) {\r\n this.stage.stopDrag();\r\n dragStopped = true;\r\n }\r\n\r\n const rect = this.stage.container().getBoundingClientRect();\r\n const p1 = {\r\n x: touch1.clientX - rect.left,\r\n y: touch1.clientY - rect.top,\r\n };\r\n const p2 = {\r\n x: touch2.clientX - rect.left,\r\n y: touch2.clientY - rect.top,\r\n };\r\n\r\n const newCenter = {\r\n x: (p1.x + p2.x) / 2,\r\n y: (p1.y + p2.y) / 2,\r\n };\r\n const distance = Math.hypot(p1.x - p2.x, p1.y - p2.y);\r\n\r\n if (lastPinchCenter === undefined) {\r\n lastPinchCenter = newCenter;\r\n }\r\n\r\n if (lastPinchDistance === undefined) {\r\n lastPinchDistance = distance;\r\n return;\r\n }\r\n\r\n if (lastPinchDistance === 0) {\r\n return;\r\n }\r\n\r\n const oldScale = this.stage.scaleX();\r\n const newZoom = this.currentZoom * (distance / lastPinchDistance);\r\n\r\n const pointTo = {\r\n x: (newCenter.x - this.stage.x()) / oldScale,\r\n y: (newCenter.y - this.stage.y()) / oldScale,\r\n };\r\n\r\n const zoomChanged = this.setZoom(newZoom);\r\n\r\n const newScale = this.stage.scaleX();\r\n const dx = newCenter.x - lastPinchCenter.x;\r\n const dy = newCenter.y - lastPinchCenter.y;\r\n const newPos = {\r\n x: newCenter.x - pointTo.x * newScale + dx,\r\n y: newCenter.y - pointTo.y * newScale + dy,\r\n };\r\n\r\n this.stage.position(newPos);\r\n this.stage.batchDraw();\r\n\r\n lastPinchDistance = distance;\r\n lastPinchCenter = newCenter;\r\n\r\n if (zoomChanged) {\r\n this.emitZoomChangeEvent();\r\n }\r\n });\r\n }\r\n\r\n drawArea(id: number, zIndex: number) {\r\n const area = this.mapReader.getArea(id);\r\n if (!area) {\r\n return;\r\n }\r\n const plane = area.getPlane(zIndex);\r\n if (!plane) {\r\n return;\r\n }\r\n this.currentArea = id;\r\n this.currentAreaInstance = area;\r\n this.currentZIndex = zIndex;\r\n this.currentAreaVersion = area.getVersion();\r\n this.roomLayer.destroyChildren();\r\n this.linkLayer.destroyChildren();\r\n\r\n this.stage.scale({x: defaultZoom * this.currentZoom, y: defaultZoom * this.currentZoom});\r\n\r\n this.renderLabels(plane.getLabels());\r\n this.renderRooms(plane.getRooms() ?? []);\r\n this.renderExits(area.getLinkExits(zIndex));\r\n this.refreshHighlights();\r\n this.stage.batchDraw();\r\n }\r\n\r\n private emitRoomContextEvent(roomId: number, clientX: number, clientY: number) {\r\n const container = this.stage.container();\r\n const bounds = container.getBoundingClientRect();\r\n const detail: RoomContextMenuEventDetail = {\r\n roomId,\r\n position: {\r\n x: clientX - bounds.left,\r\n y: clientY - bounds.top,\r\n },\r\n };\r\n const event = new CustomEvent<RoomContextMenuEventDetail>('roomcontextmenu', {detail});\r\n container.dispatchEvent(event);\r\n }\r\n\r\n private emitZoomChangeEvent() {\r\n const event = new CustomEvent<ZoomChangeEventDetail>('zoom', {\r\n detail: {zoom: this.currentZoom},\r\n });\r\n this.stage.container().dispatchEvent(event);\r\n }\r\n\r\n setZoom(zoom: number): boolean {\r\n if (this.currentZoom === zoom) {\r\n return false;\r\n }\r\n\r\n this.currentZoom = zoom;\r\n this.stage.scale({x: defaultZoom * zoom, y: defaultZoom * zoom});\r\n\r\n return true;\r\n }\r\n\r\n getZoom() {\r\n return this.currentZoom;\r\n }\r\n\r\n getCurrentArea() {\r\n return this.currentArea ? this.mapReader.getArea(this.currentArea) : undefined\r\n }\r\n\r\n setPosition(roomId: number) {\r\n const room = this.mapReader.getRoom(roomId);\r\n if (!room) return;\r\n const area = this.mapReader.getArea(room.area);\r\n const areaVersion = area?.getVersion();\r\n let instant = this.currentArea !== room.area || this.currentZIndex !== room.z\r\n if (\r\n this.currentArea !== room.area ||\r\n this.currentZIndex !== room.z ||\r\n (areaVersion !== undefined && this.currentAreaVersion !== areaVersion) ||\r\n (area !== undefined && this.currentAreaInstance !== area)\r\n ) {\r\n this.drawArea(room.area, room.z);\r\n }\r\n if (!this.positionRender) {\r\n this.positionRender = new Konva.Circle({\r\n x: room.x,\r\n y: room.y,\r\n radius: defaultRoomSize * 0.85,\r\n stroke: \"rgb(0, 229, 178)\",\r\n strokeWidth: 0.1,\r\n dash: [0.05, 0.05],\r\n dashEnabled: true,\r\n })\r\n this.positionLayer.add(this.positionRender);\r\n }\r\n this.centerOnRoom(room, instant);\r\n }\r\n\r\n renderPath(locations: number[], color?: string) {\r\n return this.pathRenderer.renderPath(locations, this.currentArea, this.currentZIndex, color);\r\n }\r\n\r\n clearPaths() {\r\n this.pathRenderer.clearPaths();\r\n }\r\n\r\n renderHighlight(roomId: number, color: string) {\r\n const room = this.mapReader.getRoom(roomId);\r\n if (!room) {\r\n return;\r\n }\r\n\r\n const existing = this.highlights.get(roomId);\r\n if (existing?.shape) {\r\n existing.shape.destroy();\r\n delete existing.shape;\r\n }\r\n\r\n const highlightData: HighlightData = {color, area: room.area, z: room.z};\r\n\r\n this.highlights.set(roomId, highlightData);\r\n\r\n if (room.area === this.currentArea && room.z === this.currentZIndex) {\r\n const shape = this.createHighlightShape(room, color);\r\n this.overlayLayer.add(shape);\r\n highlightData.shape = shape;\r\n this.overlayLayer.batchDraw();\r\n return shape;\r\n }\r\n\r\n return highlightData.shape;\r\n }\r\n\r\n clearHighlights() {\r\n this.highlights.forEach(({shape}) => shape?.destroy());\r\n this.highlights.clear();\r\n this.overlayLayer.batchDraw();\r\n }\r\n\r\n private refreshHighlights() {\r\n this.highlights.forEach((highlight, roomId) => {\r\n highlight.shape?.destroy();\r\n delete highlight.shape;\r\n\r\n if (highlight.area !== this.currentArea || highlight.z !== this.currentZIndex) {\r\n return;\r\n }\r\n\r\n const room = this.mapReader.getRoom(roomId);\r\n if (!room) {\r\n return;\r\n }\r\n\r\n const shape = this.createHighlightShape(room, highlight.color);\r\n this.overlayLayer.add(shape);\r\n highlight.shape = shape;\r\n });\r\n\r\n this.overlayLayer.batchDraw();\r\n }\r\n\r\n private createHighlightShape(room: MapData.Room, color: string) {\r\n return new Konva.Circle({\r\n x: room.x,\r\n y: room.y,\r\n radius: Settings.roomSize * 0.9,\r\n stroke: color,\r\n strokeWidth: 0.15,\r\n dash: [0.1, 0.05],\r\n dashEnabled: true,\r\n listening: false,\r\n });\r\n }\r\n\r\n private centerOnRoom(room: MapData.Room, instant: boolean = false) {\r\n this.currentRoomId = room.id;\r\n const roomCenter = {x: room.x, y: room.y};\r\n\r\n this.positionRender?.position(room)\r\n\r\n const abs = this.stage.getAbsoluteTransform()\r\n const screenPoint = abs.point(roomCenter);\r\n\r\n const target = {\r\n x: this.stage.width() / 2,\r\n y: this.stage.height() / 2,\r\n };\r\n\r\n const dx = target.x - screenPoint.x;\r\n const dy = target.y - screenPoint.y;\r\n\r\n if (this.currentTransition) {\r\n this.currentTransition.pause()\r\n this.currentTransition.destroy()\r\n delete this.currentTransition;\r\n }\r\n\r\n console.log(Settings.instantMapMove)\r\n if (instant || Settings.instantMapMove) {\r\n this.stage.position({\r\n x: this.stage.x() + dx,\r\n y: this.stage.y() + dy,\r\n })\r\n } else {\r\n this.currentTransition = new Konva.Tween({\r\n node: this.stage,\r\n x: this.stage.x() + dx,\r\n y: this.stage.y() + dy,\r\n duration: 0.2,\r\n easing: Konva.Easings.EaseInOut,\r\n })\r\n this.currentTransition.play()\r\n }\r\n }\r\n\r\n private renderRooms(rooms: MapData.Room[]) {\r\n rooms.forEach(room => {\r\n const roomRender = new Konva.Group({\r\n x: room.x - Settings.roomSize / 2,\r\n y: room.y - Settings.roomSize / 2,\r\n });\r\n const roomRect = new Konva.Rect({\r\n x: 0,\r\n y: 0,\r\n width: Settings.roomSize,\r\n height: Settings.roomSize,\r\n fill: this.mapReader.getColorValue(room.env),\r\n strokeWidth: 0.025,\r\n stroke: Settings.lineColor,\r\n });\r\n const emitContextEvent = (clientX: number, clientY: number) => this.emitRoomContextEvent(room.id, clientX, clientY);\r\n\r\n roomRender.on('mouseenter', () => {\r\n this.stage.container().style.cursor = 'pointer';\r\n })\r\n roomRender.on('mouseleave', () => {\r\n this.stage.container().style.cursor = 'auto';\r\n })\r\n roomRender.on('contextmenu', (event) => {\r\n event.evt.preventDefault();\r\n const pointerEvent = event.evt as MouseEvent;\r\n emitContextEvent(pointerEvent.clientX, pointerEvent.clientY);\r\n })\r\n\r\n let longPressTimeout: number | undefined;\r\n let longPressStart: { clientX: number; clientY: number } | undefined;\r\n let stageDraggableBeforeLongPress: boolean | undefined;\r\n const restoreStageDraggable = () => {\r\n if (stageDraggableBeforeLongPress !== undefined) {\r\n this.stage.draggable(stageDraggableBeforeLongPress);\r\n stageDraggableBeforeLongPress = undefined;\r\n }\r\n };\r\n const clearLongPressTimeout = () => {\r\n if (longPressTimeout !== undefined) {\r\n window.clearTimeout(longPressTimeout);\r\n longPressTimeout = undefined;\r\n }\r\n longPressStart = undefined;\r\n restoreStageDraggable();\r\n };\r\n\r\n roomRender.on('touchstart', (event) => {\r\n clearLongPressTimeout();\r\n if (event.evt.touches && event.evt.touches.length > 1) {\r\n return;\r\n }\r\n const touch = event.evt.touches?.[0];\r\n if (!touch) {\r\n return;\r\n }\r\n longPressStart = { clientX: touch.clientX, clientY: touch.clientY };\r\n stageDraggableBeforeLongPress = this.stage.draggable();\r\n this.stage.draggable(false);\r\n longPressTimeout = window.setTimeout(() => {\r\n if (longPressStart) {\r\n emitContextEvent(longPressStart.clientX, longPressStart.clientY);\r\n }\r\n clearLongPressTimeout();\r\n }, 500);\r\n });\r\n\r\n roomRender.on('touchend', clearLongPressTimeout);\r\n roomRender.on('touchmove', (event) => {\r\n if (!longPressStart) {\r\n return;\r\n }\r\n const touch = event.evt.touches?.[0];\r\n if (!touch) {\r\n clearLongPressTimeout();\r\n return;\r\n }\r\n const dx = touch.clientX - longPressStart.clientX;\r\n const dy = touch.clientY - longPressStart.clientY;\r\n const distanceSquared = dx * dx + dy * dy;\r\n const movementThreshold = 10;\r\n if (distanceSquared > movementThreshold * movementThreshold) {\r\n const wasDraggable = stageDraggableBeforeLongPress;\r\n clearLongPressTimeout();\r\n if (wasDraggable) {\r\n this.stage.startDrag();\r\n }\r\n }\r\n });\r\n roomRender.on('touchcancel', clearLongPressTimeout);\r\n\r\n roomRender.add(roomRect);\r\n this.renderSymbol(room, roomRender);\r\n this.roomLayer.add(roomRender);\r\n\r\n this.exitRenderer.renderSpecialExits(room).forEach(render => {\r\n this.linkLayer.add(render)\r\n })\r\n this.exitRenderer.renderStubs(room).forEach(render => {\r\n this.linkLayer.add(render)\r\n })\r\n this.exitRenderer.renderInnerExits(room).forEach(render => {\r\n this.roomLayer.add(render)\r\n })\r\n })\r\n }\r\n\r\n private renderSymbol(room: MapData.Room, roomRender: Konva.Group) {\r\n if (room.roomChar !== undefined) {\r\n const roomChar = new Konva.Text({\r\n x: 0,\r\n y: 0,\r\n text: room.roomChar,\r\n fontSize: 0.45,\r\n fontStyle: \"bold\",\r\n fill: this.mapReader.getSymbolColor(room.env),\r\n align: \"center\",\r\n verticalAlign: \"middle\",\r\n width: Settings.roomSize,\r\n height: Settings.roomSize,\r\n })\r\n roomRender.add(roomChar);\r\n }\r\n }\r\n\r\n private renderExits(exits: Exit[]) {\r\n exits.forEach(exit => {\r\n const render = this.exitRenderer.render(exit);\r\n if (!render) {\r\n return;\r\n }\r\n this.linkLayer.add(render);\r\n })\r\n\r\n }\r\n\r\n private renderLabels(Labels: MapData.Label[]) {\r\n Labels.forEach(label => {\r\n if (!label.pixMap) {\r\n return\r\n }\r\n const image = new Image()\r\n image.src = `data:image/png;base64,${label.pixMap}`\r\n const labelRender = new Konva.Image({\r\n x: label.X,\r\n y: -label.Y,\r\n width: label.Width,\r\n height: label.Height,\r\n image: image\r\n })\r\n this.linkLayer.add(labelRender)\r\n })\r\n }\r\n\r\n\r\n}","export default class Plane {\r\n\r\n private readonly bounds: { minX: number, maxX: number, minY: number, maxY: number }\r\n private readonly rooms: MapData.Room[] = [];\r\n private readonly labels: MapData.Label[] = [];\r\n\r\n constructor(rooms: MapData.Room[], labels: MapData.Label[]) {\r\n this.rooms = rooms\r\n this.bounds = this.createBounds();\r\n this.labels = labels\r\n }\r\n\r\n getRooms() {\r\n return this.rooms;\r\n }\r\n\r\n getLabels() {\r\n return this.labels;\r\n }\r\n\r\n getBounds() {\r\n return this.bounds;\r\n }\r\n\r\n private createBounds() {\r\n return this.rooms.reduce(\r\n (acc, r) => ({\r\n minX: Math.min(acc.minX, r.x),\r\n maxX: Math.max(acc.maxX, r.x),\r\n minY: Math.min(acc.minY, r.y),\r\n maxY: Math.max(acc.maxY, r.y),\r\n }),\r\n {\r\n minX: Number.POSITIVE_INFINITY,\r\n maxX: Number.NEGATIVE_INFINITY,\r\n minY: Number.POSITIVE_INFINITY,\r\n maxY: Number.NEGATIVE_INFINITY,\r\n }\r\n );\r\n }\r\n\r\n}","import Plane from \"./Plane\";\r\n\r\nimport Exit, {longToShort, regularExits} from \"./Exit\";\r\n\r\nexport default class Area {\r\n\r\n private readonly planes: Record<number, Plane> = {};\r\n private readonly area: MapData.Area;\r\n private readonly exits: Map<string, Exit> = new Map();\r\n private version = 0;\r\n\r\n constructor(area: MapData.Area) {\r\n this.area = area;\r\n this.planes = this.createPlanes();\r\n this.createExits();\r\n }\r\n\r\n getAreaName() {\r\n return this.area.areaName\r\n }\r\n\r\n getAreaId() {\r\n return parseInt(this.area.areaId)\r\n }\r\n\r\n getVersion() {\r\n return this.version;\r\n }\r\n\r\n protected markDirty() {\r\n this.version++;\r\n }\r\n\r\n getPlane(zIndex: number) {\r\n return this.planes[zIndex];\r\n }\r\n\r\n getPlanes() {\r\n return Object.values(this.planes);\r\n }\r\n\r\n getRooms() {\r\n return this.area.rooms\r\n }\r\n\r\n getLinkExits(zIndex: number) {\r\n return Array.from(this.exits.values()).filter(e => e.zIndex.includes(zIndex));\r\n }\r\n\r\n private createPlanes() {\r\n const grouped = this.area.rooms.reduce<Record<number, MapData.Room[]>>((acc, room) => {\r\n if (!acc[room.z]) {\r\n acc[room.z] = [];\r\n }\r\n // @ts-ignore\r\n acc[room.z].push(room);\r\n return acc;\r\n }, {});\r\n return Object.entries(grouped).reduce(\r\n (acc, [z, rooms]) => {\r\n acc[+z] = new Plane(rooms, this.area.labels.filter(label => label.Z === +z));\r\n return acc;\r\n },\r\n {} as Record<number, Plane>\r\n );\r\n }\r\n\r\n private createExits() {\r\n this.area.rooms.forEach(room => {\r\n Object.entries(room.exits)\r\n .filter(([direction, _]) => regularExits.indexOf(direction as MapData.direction) > -1 && !room.customLines.hasOwnProperty(longToShort[direction as MapData.direction]))\r\n .forEach(([direction, targetRoomId]) => this.createHalfExit(room.id, targetRoomId, room.z, direction as MapData.direction))\r\n })\r\n }\r\n\r\n private createHalfExit(originRoom: number, targetRoom: number, zIndex: number, direction: MapData.direction,) {\r\n if (originRoom === targetRoom) {\r\n return\r\n }\r\n const a = Math.min(originRoom, targetRoom);\r\n const b = Math.max(originRoom, targetRoom);\r\n const key = `${a}-${b}`;\r\n let edge = this.exits.get(key);\r\n if (!edge) {\r\n edge = {a: a, b: b, zIndex: [zIndex]};\r\n }\r\n if (a == originRoom) {\r\n edge.aDir = direction;\r\n } else {\r\n edge.bDir = direction;\r\n }\r\n edge.zIndex.push(zIndex);\r\n this.exits.set(key, edge);\r\n }\r\n\r\n}","import Area from \"./Area\";\r\nimport Plane from \"./Plane\";\r\nimport Exit from \"./Exit\";\r\n\r\nclass ExplorationPlane extends Plane {\r\n\r\n private readonly basePlane: Plane;\r\n private readonly visitedRooms: Set<number>;\r\n\r\n constructor(plane: Plane, visitedRooms: Set<number>) {\r\n super(plane.getRooms(), plane.getLabels());\r\n this.basePlane = plane;\r\n this.visitedRooms = visitedRooms;\r\n }\r\n\r\n override getRooms() {\r\n return this.basePlane.getRooms().filter(room => this.visitedRooms.has(room.id));\r\n }\r\n\r\n override getLabels() {\r\n return this.basePlane.getLabels();\r\n }\r\n\r\n override getBounds() {\r\n const rooms = this.getRooms();\r\n if (!rooms.length) {\r\n return this.basePlane.getBounds();\r\n }\r\n return rooms.reduce(\r\n (acc, room) => ({\r\n minX: Math.min(acc.minX, room.x),\r\n maxX: Math.max(acc.maxX, room.x),\r\n minY: Math.min(acc.minY, room.y),\r\n maxY: Math.max(acc.maxY, room.y),\r\n }),\r\n {\r\n minX: Number.POSITIVE_INFINITY,\r\n maxX: Number.NEGATIVE_INFINITY,\r\n minY: Number.POSITIVE_INFINITY,\r\n maxY: Number.NEGATIVE_INFINITY,\r\n }\r\n );\r\n }\r\n\r\n}\r\n\r\nexport default class ExplorationArea extends Area {\r\n\r\n private readonly visitedRooms: Set<number>;\r\n private readonly areaRoomIds: Set<number>;\r\n private readonly planeCache: WeakMap<Plane, ExplorationPlane> = new WeakMap();\r\n\r\n constructor(area: MapData.Area, visitedRooms?: Iterable<number> | Set<number>) {\r\n super(area);\r\n this.visitedRooms = visitedRooms instanceof Set ? visitedRooms : new Set(visitedRooms ?? []);\r\n this.areaRoomIds = new Set(area.rooms.map(room => room.id));\r\n }\r\n\r\n override getPlane(zIndex: number) {\r\n const basePlane = super.getPlane(zIndex);\r\n if (!basePlane) {\r\n return basePlane;\r\n }\r\n let decorated = this.planeCache.get(basePlane);\r\n if (!decorated) {\r\n decorated = new ExplorationPlane(basePlane, this.visitedRooms);\r\n this.planeCache.set(basePlane, decorated);\r\n }\r\n return decorated;\r\n }\r\n\r\n override getPlanes() {\r\n return super.getPlanes().map(plane => {\r\n let decorated = this.planeCache.get(plane);\r\n if (!decorated) {\r\n decorated = new ExplorationPlane(plane, this.visitedRooms);\r\n this.planeCache.set(plane, decorated);\r\n }\r\n return decorated;\r\n });\r\n }\r\n\r\n override getLinkExits(zIndex: number) {\r\n return super\r\n .getLinkExits(zIndex)\r\n .filter((exit: Exit) => this.visitedRooms.has(exit.a) || this.visitedRooms.has(exit.b));\r\n }\r\n\r\n getVisitedRoomCount() {\r\n return super.getRooms().reduce((count, room) => count + (this.visitedRooms.has(room.id) ? 1 : 0), 0);\r\n }\r\n\r\n getTotalRoomCount() {\r\n return this.areaRoomIds.size;\r\n }\r\n\r\n hasVisitedRoom(roomId: number) {\r\n return this.areaRoomIds.has(roomId) && this.visitedRooms.has(roomId);\r\n }\r\n\r\n getVisitedRoomIds() {\r\n return super.getRooms()\r\n .filter(room => this.visitedRooms.has(room.id))\r\n .map(room => room.id);\r\n }\r\n\r\n addVisitedRoom(roomId: number) {\r\n const wasVisited = this.visitedRooms.has(roomId);\r\n this.visitedRooms.add(roomId);\r\n const newlyVisited = !wasVisited && this.areaRoomIds.has(roomId);\r\n if (newlyVisited) {\r\n this.markDirty();\r\n }\r\n return newlyVisited;\r\n }\r\n\r\n addVisitedRooms(roomIds: Iterable<number>) {\r\n let newlyVisited = 0;\r\n for (const roomId of roomIds) {\r\n const wasVisited = this.visitedRooms.has(roomId);\r\n this.visitedRooms.add(roomId);\r\n if (!wasVisited && this.areaRoomIds.has(roomId)) {\r\n newlyVisited++;\r\n }\r\n }\r\n if (newlyVisited > 0) {\r\n this.markDirty();\r\n }\r\n return newlyVisited;\r\n }\r\n\r\n}\r\n","import Area from \"./Area\";\r\nimport ExplorationArea from \"./ExplorationArea\";\r\n\r\ninterface Color {\r\n rgb: number[];\r\n rgbValue: string;\r\n symbolColor: number[];\r\n symbolColorValue: string,\r\n}\r\n\r\nconst defaultColor: Color = {\r\n rgb: [114, 1, 0],\r\n rgbValue: 'rgb(114, 1, 0)',\r\n symbolColor: [225, 225, 225],\r\n symbolColorValue: 'rgb(225,225,225)'\r\n}\r\n\r\nfunction calculateLuminance(rgb: number[]) {\r\n const rn = rgb[0] / 255;\r\n const gn = rgb[1] / 255;\r\n const bn = rgb[2] / 255;\r\n\r\n const max = Math.max(rn, gn, bn);\r\n const min = Math.min(rn, gn, bn);\r\n\r\n return (max + min) / 2;\r\n}\r\n\r\nexport default class MapReader {\r\n\r\n private rooms: Record<number, MapData.Room> = {};\r\n private areas: Record<number, Area> = {};\r\n private areaSources: Record<number, MapData.Area> = {};\r\n private visitedRooms?: Set<number>;\r\n private explorationEnabled = false;\r\n private colors: Record<number, Color> = {};\r\n\r\n constructor(map: MapData.Map, envs: MapData.Env[]) {\r\n map.forEach(area => {\r\n area.rooms.forEach(room => {\r\n room.y = -room.y;\r\n this.rooms[room.id] = room;\r\n })\r\n const areaId = parseInt(area.areaId);\r\n this.areas[areaId] = new Area(area);\r\n this.areaSources[areaId] = area;\r\n })\r\n this.colors = envs.reduce((acc, c) => ({\r\n ...acc,\r\n [c.envId]: {\r\n rgb: c.colors,\r\n rgbValue: `rgb(${c.colors.join(',')}`,\r\n symbolColor: calculateLuminance(c.colors) > 0.41 ? [25, 25, 25] : [225, 255, 255],\r\n symbolColorValue: calculateLuminance(c.colors) > 0.41 ? 'rgb(25,25,25)' : 'rgb(225,255,255)'\r\n }\r\n }), {});\r\n }\r\n\r\n getArea(areaId: number) {\r\n return this.areas[areaId];\r\n }\r\n\r\n getExplorationArea(areaId: number) {\r\n const area = this.areas[areaId];\r\n if (area instanceof ExplorationArea) {\r\n return area;\r\n }\r\n return undefined;\r\n }\r\n\r\n getAreas() {\r\n return Object.values(this.areas);\r\n }\r\n\r\n getRooms() {\r\n return Object.values(this.rooms);\r\n }\r\n\r\n getRoom(roomId: number) {\r\n return this.rooms[roomId];\r\n }\r\n\r\n private ensureVisitedRooms() {\r\n if (!this.visitedRooms) {\r\n this.visitedRooms = new Set();\r\n }\r\n return this.visitedRooms;\r\n }\r\n\r\n private applyExplorationDecoration() {\r\n if (!this.visitedRooms) {\r\n return;\r\n }\r\n Object.entries(this.areaSources).forEach(([id, area]) => {\r\n const numericId = parseInt(id, 10);\r\n this.areas[numericId] = new ExplorationArea(area, this.visitedRooms);\r\n });\r\n }\r\n\r\n decorateWithExploration(visitedRooms?: Iterable<number> | Set<number>) {\r\n if (visitedRooms !== undefined) {\r\n this.setVisitedRooms(visitedRooms);\r\n } else {\r\n this.ensureVisitedRooms();\r\n }\r\n this.applyExplorationDecoration();\r\n this.explorationEnabled = true;\r\n return this.visitedRooms;\r\n }\r\n\r\n getVisitedRooms() {\r\n return this.visitedRooms;\r\n }\r\n\r\n clearExplorationDecoration() {\r\n Object.entries(this.areaSources).forEach(([id, area]) => {\r\n const numericId = parseInt(id, 10);\r\n this.areas[numericId] = new Area(area);\r\n });\r\n this.explorationEnabled = false;\r\n }\r\n\r\n isExplorationEnabled() {\r\n return this.explorationEnabled;\r\n }\r\n\r\n setVisitedRooms(visitedRooms: Iterable<number> | Set<number>) {\r\n this.visitedRooms = visitedRooms instanceof Set ? visitedRooms : new Set(visitedRooms);\r\n if (this.explorationEnabled) {\r\n this.applyExplorationDecoration();\r\n }\r\n return this.visitedRooms;\r\n }\r\n\r\n addVisitedRoom(roomId: number) {\r\n if (this.explorationEnabled) {\r\n const room = this.getRoom(roomId);\r\n if (room) {\r\n const area = this.getExplorationArea(room.area);\r\n if (area) {\r\n return area.addVisitedRoom(roomId);\r\n }\r\n }\r\n }\r\n const visitedRooms = this.ensureVisitedRooms();\r\n const wasVisited = visitedRooms.has(roomId);\r\n visitedRooms.add(roomId);\r\n return !wasVisited;\r\n }\r\n\r\n addVisitedRooms(roomIds: Iterable<number>) {\r\n const visitedRooms = this.ensureVisitedRooms();\r\n let newlyVisited = 0;\r\n for (const roomId of roomIds) {\r\n if (this.explorationEnabled) {\r\n const room = this.getRoom(roomId);\r\n if (room) {\r\n const area = this.getExplorationArea(room.area);\r\n if (area) {\r\n if (area.addVisitedRoom(roomId)) {\r\n newlyVisited++;\r\n }\r\n continue;\r\n }\r\n }\r\n }\r\n const wasVisited = visitedRooms.has(roomId);\r\n visitedRooms.add(roomId);\r\n if (!wasVisited) {\r\n newlyVisited++;\r\n }\r\n }\r\n return newlyVisited;\r\n }\r\n\r\n hasVisitedRoom(roomId: number) {\r\n return this.visitedRooms?.has(roomId) ?? false;\r\n }\r\n\r\n getColorValue(envId: number): string {\r\n return this.colors[envId]?.rgbValue ?? defaultColor.rgbValue;\r\n }\r\n\r\n getSymbolColor(envId: number, opacity?: number): string {\r\n const color = this.colors[envId]?.symbolColor ?? defaultColor.symbolColor;\r\n const normalizedOpacity = Math.min(Math.max(opacity ?? 1, 0), 1);\r\n const value = color.join(',');\r\n if (normalizedOpacity != 1) {\r\n return `rgba(${value}, ${normalizedOpacity})`;\r\n }\r\n return `rgba(${value})`;\r\n }\r\n\r\n}","/**\n * This very basic implementation of a priority queue is used to select the\n * next node of the graph to walk to.\n *\n * The queue is always sorted to have the least expensive node on top.\n * Some helper methods are also implemented.\n *\n * You should **never** modify the queue directly, but only using the methods\n * provided by the class.\n */\nclass PriorityQueue {\n /**\n * Creates a new empty priority queue\n */\n constructor() {\n // The `keys` set is used to greatly improve the speed at which we can\n // check the presence of a value in the queue\n this.keys = new Set();\n this.queue = [];\n }\n\n /**\n * Sort the queue to have the least expensive node to visit on top\n *\n * @private\n */\n sort() {\n this.queue.sort((a, b) => a.priority - b.priority);\n }\n\n /**\n * Sets a priority for a key in the queue.\n * Inserts it in the queue if it does not already exists.\n *\n * @param {any} key Key to update or insert\n * @param {number} value Priority of the key\n * @return {number} Size of the queue\n */\n set(key, value) {\n const priority = Number(value);\n if (isNaN(priority)) throw new TypeError('\"priority\" must be a number');\n\n if (!this.keys.has(key)) {\n // Insert a new entry if the key is not already in the queue\n this.keys.add(key);\n this.queue.push({ key, priority });\n } else {\n // Update the priority of an existing key\n this.queue.map((element) => {\n if (element.key === key) {\n Object.assign(element, { priority });\n }\n\n return element;\n });\n }\n\n this.sort();\n return this.queue.length;\n }\n\n /**\n * The next method is used to dequeue a key:\n * It removes the first element from the queue and returns it\n *\n * @return {object} First priority queue entry\n */\n next() {\n const element = this.queue.shift();\n\n // Remove the key from the `_keys` set\n this.keys.delete(element.key);\n\n return element;\n }\n\n /**\n * @return {boolean} `true` when the queue is empty\n */\n isEmpty() {\n return Boolean(this.queue.length === 0);\n }\n\n /**\n * Check if the queue has a key in it\n *\n * @param {any} key Key to lookup\n * @return {boolean}\n */\n has(key) {\n return this.keys.has(key);\n }\n\n /**\n * Get the element in the queue with the specified key\n *\n * @param {any} key Key to lookup\n * @return {object}\n */\n get(key) {\n return this.queue.find((element) => element.key === key);\n }\n}\n\nmodule.exports = PriorityQueue;\n","/**\n * Removes a key and all of its references from a map.\n * This function has no side-effects as it returns\n * a brand new map.\n *\n * @param {Map} map - Map to remove the key from\n * @param {string} key - Key to remove from the map\n * @return {Map} New map without the passed key\n */\nfunction removeDeepFromMap(map, key) {\n const newMap = new Map();\n\n for (const [aKey, val] of map) {\n if (aKey !== key && val instanceof Map) {\n newMap.set(aKey, removeDeepFromMap(val, key));\n } else if (aKey !== key) {\n newMap.set(aKey, val);\n }\n }\n\n return newMap;\n}\n\nmodule.exports = removeDeepFromMap;\n","/**\n * Validates a cost for a node\n *\n * @private\n * @param {number} val - Cost to validate\n * @return {bool}\n */\nfunction isValidNode(val) {\n const cost = Number(val);\n\n if (isNaN(cost) || cost <= 0) {\n return false;\n }\n\n return true;\n}\n\n/**\n * Creates a deep `Map` from the passed object.\n *\n * @param {Object} source - Object to populate the map with\n * @return {Map} New map with the passed object data\n */\nfunction toDeepMap(source) {\n const map = new Map();\n const keys = Object.keys(source);\n\n keys.forEach((key) => {\n const val = source[key];\n\n if (val !== null && typeof val === \"object\" && !Array.isArray(val)) {\n return map.set(key, toDeepMap(val));\n }\n\n if (!isValidNode(val)) {\n throw new Error(\n `Could not add node at key \"${key}\", make sure it's a valid node`,\n val\n );\n }\n\n return map.set(key, Number(val));\n });\n\n return map;\n}\n\nmodule.exports = toDeepMap;\n","/**\n * Validate a map to ensure all it's values are either a number or a map\n *\n * @param {Map} map - Map to valiadte\n */\nfunction validateDeep(map) {\n if (!(map instanceof Map)) {\n throw new Error(`Invalid graph: Expected Map instead found ${typeof map}`);\n }\n\n map.forEach((value, key) => {\n if (typeof value === \"object\" && value instanceof Map) {\n validateDeep(value);\n return;\n }\n\n if (typeof value !== \"number\" || value <= 0) {\n throw new Error(\n `Values must be numbers greater than 0. Found value ${value} at ${key}`\n );\n }\n });\n}\n\nmodule.exports = validateDeep;\n","const Queue = require(\"./PriorityQueue\");\nconst removeDeepFromMap = require(\"./removeDeepFromMap\");\nconst toDeepMap = require(\"./toDeepMap\");\nconst validateDeep = require(\"./validateDeep\");\n\n/** Creates and manages a graph */\nclass Graph {\n /**\n * Creates a new Graph, optionally initializing it a nodes graph representation.\n *\n * A graph representation is an object that has as keys the name of the point and as values\n * the points reacheable from that node, with the cost to get there:\n *\n * {\n * node (Number|String): {\n * neighbor (Number|String): cost (Number),\n * ...,\n * },\n * }\n *\n * In alternative to an object, you can pass a `Map` of `Map`. This will\n * allow you to specify numbers as keys.\n *\n * @param {Objec|Map} [graph] - Initial graph definition\n * @example\n *\n * const route = new Graph();\n *\n * // Pre-populated graph\n * const route = new Graph({\n * A: { B: 1 },\n * B: { A: 1, C: 2, D: 4 },\n * });\n *\n * // Passing a Map\n * const g = new Map()\n *\n * const a = new Map()\n * a.set('B', 1)\n *\n * const b = new Map()\n * b.set('A', 1)\n * b.set('C', 2)\n * b.set('D', 4)\n *\n * g.set('A', a)\n * g.set('B', b)\n *\n * const route = new Graph(g)\n */\n constructor(graph) {\n if (graph instanceof Map) {\n validateDeep(graph);\n this.graph = graph;\n } else if (graph) {\n this.graph = toDeepMap(graph);\n } else {\n this.graph = new Map();\n }\n }\n\n /**\n * Adds a node to the graph\n *\n * @param {string} name - Name of the node\n * @param {Object|Map} neighbors - Neighbouring nodes and cost to reach them\n * @return {this}\n * @example\n *\n * const route = new Graph();\n *\n * route.addNode('A', { B: 1 });\n *\n * // It's possible to chain the calls\n * route\n * .addNode('B', { A: 1 })\n * .addNode('C', { A: 3 });\n *\n * // The neighbors can be expressed in a Map\n * const d = new Map()\n * d.set('A', 2)\n * d.set('B', 8)\n *\n * route.addNode('D', d)\n */\n addNode(name, neighbors) {\n let nodes;\n if (neighbors instanceof Map) {\n validateDeep(neighbors);\n nodes = neighbors;\n } else {\n nodes = toDeepMap(neighbors);\n }\n\n this.graph.set(name, nodes);\n\n return this;\n }\n\n /**\n * @deprecated since version 2.0, use `Graph#addNode` instead\n */\n addVertex(name, neighbors) {\n return this.addNode(name, neighbors);\n }\n\n /**\n * Removes a node and all of its references from the graph\n *\n * @param {string|number} key - Key of the node to remove from the graph\n * @return {this}\n * @example\n *\n * const route = new Graph({\n * A: { B: 1, C: 5 },\n * B: { A: 3 },\n * C: { B: 2, A: 2 },\n * });\n *\n * route.removeNode('C');\n * // The graph now is:\n * // { A: { B: 1 }, B: { A: 3 } }\n */\n removeNode(key) {\n this.graph = removeDeepFromMap(this.graph, key);\n\n return this;\n }\n\n /**\n * Compute the shortest path between the specified nodes\n *\n * @param {string} start - Starting node\n * @param {string} goal - Node we want to reach\n * @param {object} [options] - Options\n *\n * @param {boolean} [options.trim] - Exclude the origin and destination nodes from the result\n * @param {boolean} [options.reverse] - Return the path in reversed order\n * @param {boolean} [options.cost] - Also return the cost of the path when set to true\n *\n * @return {array|object} Computed path between the nodes.\n *\n * When `option.cost` is set to true, the returned value will be an object with shape:\n * - `path` *(Array)*: Computed path between the nodes\n * - `cost` *(Number)*: Cost of the path\n *\n * @example\n *\n * const route = new Graph()\n *\n * route.addNode('A', { B: 1 })\n * route.addNode('B', { A: 1, C: 2, D: 4 })\n * route.addNode('C', { B: 2, D: 1 })\n * route.addNode('D', { C: 1, B: 4 })\n *\n * route.path('A', 'D') // => ['A', 'B', 'C', 'D']\n *\n * // trimmed\n * route.path('A', 'D', { trim: true }) // => [B', 'C']\n *\n * // reversed\n * route.path('A', 'D', { reverse: true }) // => ['D', 'C', 'B', 'A']\n *\n * // include the cost\n * route.path('A', 'D', { cost: true })\n * // => {\n * // path: [ 'A', 'B', 'C', 'D' ],\n * // cost: 4\n * // }\n */\n path(start, goal, options = {}) {\n // Don't run when we don't have nodes set\n if (!this.graph.size) {\n if (options.cost) return { path: null, cost: 0 };\n\n return null;\n }\n\n const explored = new Set();\n const frontier = new Queue();\n const previous = new Map();\n\n let path = [];\n let totalCost = 0;\n\n let avoid = [];\n if (options.avoid) avoid = [].concat(options.avoid);\n\n if (avoid.includes(start)) {\n throw new Error(`Starting node (${start}) cannot be avoided`);\n } else if (avoid.includes(goal)) {\n throw new Error(`Ending node (${goal}) cannot be avoided`);\n }\n\n // Add the starting point to the frontier, it will be the first node visited\n frontier.set(start, 0);\n\n // Run until we have visited every node in the frontier\n while (!frontier.isEmpty()) {\n // Get the node in the frontier with the lowest cost (`priority`)\n const node = frontier.next();\n\n // When the node with the lowest cost in the frontier in our goal node,\n // we can compute the path and exit the loop\n if (node.key === goal) {\n // Set the total cost to the current value\n totalCost = node.priority;\n\n let nodeKey = node.key;\n while (previous.has(nodeKey)) {\n path.push(nodeKey);\n nodeKey = previous.get(nodeKey);\n }\n\n break;\n }\n\n // Add the current node to the explored set\n explored.add(node.key);\n\n // Loop all the neighboring nodes\n const neighbors = this.graph.get(node.key) || new Map();\n neighbors.forEach((nCost, nNode) => {\n // If we already explored the node, or the node is to be avoided, skip it\n if (explored.has(nNode) || avoid.includes(nNode)) return null;\n\n // If the neighboring node is not yet in the frontier, we add it with\n // the correct cost\n if (!frontier.has(nNode)) {\n previous.set(nNode, node.key);\n return frontier.set(nNode, node.priority + nCost);\n }\n\n const frontierPriority = frontier.get(nNode).priority;\n const nodeCost = node.priority + nCost;\n\n // Otherwise we only update the cost of this node in the frontier when\n // it's below what's currently set\n if (nodeCost < frontierPriority) {\n previous.set(nNode, node.key);\n return frontier.set(nNode, nodeCost);\n }\n\n return null;\n });\n }\n\n // Return null when no path can be found\n if (!path.length) {\n if (options.cost) return { path: null, cost: 0 };\n\n return null;\n }\n\n // From now on, keep in mind that `path` is populated in reverse order,\n // from destination to origin\n\n // Remove the first value (the goal node) if we want a trimmed result\n if (options.trim) {\n path.shift();\n } else {\n // Add the origin waypoint at the end of the array\n path = path.concat([start]);\n }\n\n // Reverse the path if we don't want it reversed, so the result will be\n // from `start` to `goal`\n if (!options.reverse) {\n path = path.reverse();\n }\n\n // Return an object if we also want the cost\n if (options.cost) {\n return {\n path,\n cost: totalCost,\n };\n }\n\n return path;\n }\n\n /**\n * @deprecated since version 2.0, use `Graph#path` instead\n */\n shortestPath(...args) {\n return this.path(...args);\n }\n}\n\nmodule.exports = Graph;\n","import Graph from \"node-dijkstra\";\r\nimport MapReader from \"./reader/MapReader\";\r\n\r\nconst exitNumberToDirection: Record<number, MapData.direction> = {\r\n 1: \"north\",\r\n 2: \"northeast\",\r\n 3: \"northwest\",\r\n 4: \"east\",\r\n 5: \"west\",\r\n 6: \"south\",\r\n 7: \"southeast\",\r\n 8: \"southwest\",\r\n 9: \"up\",\r\n 10: \"down\",\r\n 11: \"in\",\r\n 12: \"out\",\r\n};\r\n\r\ntype GraphDefinition = Record<string, Record<string, number>>;\r\n\r\nexport default class PathFinder {\r\n\r\n private readonly mapReader: MapReader;\r\n private readonly graph: Graph;\r\n private readonly cache = new Map<string, Array<number> | null>();\r\n\r\n constructor(mapReader: MapReader) {\r\n this.mapReader = mapReader;\r\n this.graph = this.buildGraph();\r\n }\r\n\r\n private buildGraph(): Graph {\r\n const graphDefinition: GraphDefinition = {};\r\n this.mapReader.getRooms().forEach(room => {\r\n const connections: Record<string, number> = {};\r\n\r\n const lockedDirections = new Set(\r\n (room.exitLocks ?? [])\r\n .map(lockId => exitNumberToDirection[lockId])\r\n .filter((direction): direction is MapData.direction => Boolean(direction))\r\n );\r\n\r\n const lockedSpecialTargets = new Set(room.mSpecialExitLocks ?? []);\r\n\r\n Object.entries(room.exits ?? {}).forEach(([direction, targetRoomId]) => {\r\n if (lockedDirections.has(direction as MapData.direction)) {\r\n return;\r\n }\r\n if (this.mapReader.getRoom(targetRoomId)) {\r\n connections[targetRoomId.toString()] = 1;\r\n }\r\n });\r\n\r\n Object.values(room.specialExits ?? {}).forEach(targetRoomId => {\r\n if (lockedSpecialTargets.has(targetRoomId)) {\r\n return;\r\n }\r\n if (this.mapReader.getRoom(targetRoomId)) {\r\n connections[targetRoomId.toString()] = 1;\r\n }\r\n });\r\n\r\n graphDefinition[room.id.toString()] = connections;\r\n });\r\n\r\n return new Graph(graphDefinition);\r\n }\r\n\r\n findPath(from: number, to: number): Array<number> | null {\r\n const cacheKey = `${from}->${to}`;\r\n if (this.cache.has(cacheKey)) {\r\n return this.cache.get(cacheKey)!;\r\n }\r\n\r\n if (from === to) {\r\n const result = this.mapReader.getRoom(from) ? [from] : null;\r\n this.cache.set(cacheKey, result);\r\n return result;\r\n }\r\n\r\n if (!this.mapReader.getRoom(from) || !this.mapReader.getRoom(to)) {\r\n this.cache.set(cacheKey, null);\r\n return null;\r\n }\r\n\r\n const path = this.graph.path(from.toString(), to.toString());\r\n const nodes = Array.isArray(path) ? path : path?.path;\r\n const result = nodes ? nodes.map((id: string) => Number(id)) : null;\r\n this.cache.set(cacheKey, result);\r\n return result;\r\n }\r\n}\r\n\r\n"],"names":["regularExits","longToShort","planarDirectionOffsets","planarDirections","oppositeDirections","isPlanarDirection","direction","movePoint","x","y","distance","offset","Colors","dirNumbers","innerExits","getDoorColor","doorType","ExitRenderer","mapReader","exit","sourceRoom","targetRoom","exitRender","Konva","points","Settings","door","link","dir","targetPoint","startPoint","middlePointX","middlePointY","group","arrow","room","start","end","_","line","acc","point","construct","lineRender","style","stub","render","triangle","inRender","outRender","type","PathRenderer","overlayLayer","locations","currentArea","currentZIndex","color","rooms","location","segments","currentSegment","finalizeSegment","ensureSegment","index","previousRoom","nextRoom","segment","directionToPrevious","directionToNext","endPoint","paths","path","from","to","defaultRoomSize","defaultZoom","lineColor","_Settings","Renderer","container","scaleBy","lastPinchDistance","lastPinchCenter","dragStopped","e","oldScale","pointer","mousePointTo","newZoom","newScale","zoomChanged","newPos","touches","touch1","touch2","rect","p1","p2","newCenter","pointTo","dx","dy","id","zIndex","area","plane","roomId","clientX","clientY","bounds","detail","event","zoom","areaVersion","instant","existing","highlightData","shape","highlight","_a","roomCenter","screenPoint","target","roomRender","roomRect","emitContextEvent","pointerEvent","longPressTimeout","longPressStart","stageDraggableBeforeLongPress","restoreStageDraggable","clearLongPressTimeout","touch","distanceSquared","movementThreshold","wasDraggable","roomChar","exits","Labels","label","image","labelRender","Plane","labels","r","Area","grouped","z","targetRoomId","originRoom","a","b","key","edge","ExplorationPlane","visitedRooms","ExplorationArea","basePlane","decorated","count","wasVisited","newlyVisited","roomIds","defaultColor","calculateLuminance","rgb","rn","gn","bn","max","min","MapReader","map","envs","areaId","c","numericId","envId","opacity","normalizedOpacity","value","PriorityQueue","priority","element","PriorityQueue_1","removeDeepFromMap","newMap","aKey","val","removeDeepFromMap_1","isValidNode","cost","toDeepMap","source","toDeepMap_1","validateDeep","validateDeep_1","Queue","require$$0","require$$1","require$$2","require$$3","Graph","graph","name","neighbors","nodes","goal","options","explored","frontier","previous","totalCost","avoid","node","nodeKey","nCost","nNode","frontierPriority","nodeCost","args","Graph_1","exitNumberToDirection","PathFinder","graphDefinition","connections","lockedDirections","lockId","lockedSpecialTargets","cacheKey","result"],"mappings":"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","x_google_ignoreList":[9,10,11,12,13]}
|
package/dist/index.mjs
CHANGED
|
@@ -423,8 +423,8 @@ class ut {
|
|
|
423
423
|
dashEnabled: !0
|
|
424
424
|
}), this.positionLayer.add(this.positionRender)), this.centerOnRoom(e, i);
|
|
425
425
|
}
|
|
426
|
-
renderPath(t) {
|
|
427
|
-
return this.pathRenderer.renderPath(t, this.currentArea, this.currentZIndex);
|
|
426
|
+
renderPath(t, e) {
|
|
427
|
+
return this.pathRenderer.renderPath(t, this.currentArea, this.currentZIndex, e);
|
|
428
428
|
}
|
|
429
429
|
clearPaths() {
|
|
430
430
|
this.pathRenderer.clearPaths();
|