mudlet-map-renderer 0.0.25 → 0.1.1-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/ExitRenderer.d.ts +25 -0
- package/dist/PathFinder.d.ts +9 -0
- package/dist/PathRenderer.d.ts +16 -0
- package/dist/Renderer.d.ts +44 -0
- package/dist/directions.d.ts +7 -0
- package/dist/index.cjs +2 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.mjs +1074 -0
- package/dist/index.mjs.map +1 -0
- package/dist/reader/Area.d.ts +20 -0
- package/dist/reader/Exit.d.ts +12 -0
- package/dist/reader/ExplorationArea.d.ts +32 -0
- package/dist/reader/MapReader.d.ts +22 -0
- package/dist/reader/Plane.d.ts +15 -0
- package/dist/types/MapData.d.ts +67 -0
- package/package.json +37 -23
- package/.prettierrc +0 -5
- package/CHANGELOG.md +0 -69
- package/README.md +0 -59
- package/exports.js +0 -5
- package/map-fragment/draw/controls.js +0 -172
- package/map-fragment/draw/renderer.js +0 -819
- package/map-fragment/reader/Area.js +0 -74
- package/map-fragment/reader/MapReader.js +0 -89
- package/map-fragment/reader/PathFinder.js +0 -26
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.mjs","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) {\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: 'green',\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 PathRenderer from \"./PathRenderer\";\r\n\r\nconst defaultRoomSize = 0.6;\r\nconst padding = 1;\r\nconst defaultZoom = 75\r\nconst lineColor = 'rgb(225, 255, 225)';\r\n\r\nexport class Settings {\r\n static roomSize = defaultRoomSize;\r\n static lineColor = lineColor;\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 currentZIndex?: number;\r\n private currentAreaVersion?: 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 container.addEventListener('resize', () => {\r\n this.stage.width(container.clientWidth);\r\n this.stage.height(container.clientHeight);\r\n this.stage.batchDraw();\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 initScaling(scaleBy: number) {\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 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 }\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.currentZIndex = zIndex;\r\n this.currentAreaVersion = area.getVersion();\r\n this.roomLayer.destroyChildren();\r\n this.linkLayer.destroyChildren();\r\n\r\n const {minX, maxX, minY, maxY} = plane.getBounds();\r\n\r\n this.stage.offset({x: minX - padding, y: minY - padding});\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 setZoom(zoom: number) {\r\n this.currentZoom = zoom;\r\n this.stage.scale({x: defaultZoom * zoom, y: defaultZoom * zoom});\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 (this.currentArea !== room.area || this.currentZIndex !== room.z || (areaVersion !== undefined && this.currentAreaVersion !== areaVersion)) {\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 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 if (instant) {\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 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.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 decorateWithExploration(visitedRooms?: Iterable<number> | Set<number>) {\r\n this.visitedRooms = visitedRooms instanceof Set ? visitedRooms : new Set(visitedRooms ?? []);\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 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 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","e","type","PathRenderer","overlayLayer","locations","currentArea","currentZIndex","rooms","location","segments","currentSegment","finalizeSegment","ensureSegment","index","previousRoom","nextRoom","segment","directionToPrevious","directionToNext","endPoint","paths","path","from","to","defaultRoomSize","padding","defaultZoom","lineColor","_Settings","Renderer","container","scaleBy","oldScale","pointer","mousePointTo","newZoom","newScale","newPos","id","zIndex","area","plane","minX","maxX","minY","maxY","zoom","roomId","areaVersion","instant","color","existing","highlightData","shape","highlight","_a","roomCenter","screenPoint","target","dx","dy","roomRender","roomRect","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]}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { default as Plane } from './Plane';
|
|
2
|
+
import { default as Exit } from './Exit';
|
|
3
|
+
export default class Area {
|
|
4
|
+
private readonly planes;
|
|
5
|
+
private readonly area;
|
|
6
|
+
private readonly exits;
|
|
7
|
+
private version;
|
|
8
|
+
constructor(area: MapData.Area);
|
|
9
|
+
getAreaName(): string;
|
|
10
|
+
getAreaId(): number;
|
|
11
|
+
getVersion(): number;
|
|
12
|
+
protected markDirty(): void;
|
|
13
|
+
getPlane(zIndex: number): Plane;
|
|
14
|
+
getPlanes(): Plane[];
|
|
15
|
+
getRooms(): MapData.Room[];
|
|
16
|
+
getLinkExits(zIndex: number): Exit[];
|
|
17
|
+
private createPlanes;
|
|
18
|
+
private createExits;
|
|
19
|
+
private createHalfExit;
|
|
20
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export type Kind = "exit" | "specialExit";
|
|
2
|
+
export default interface Exit {
|
|
3
|
+
a: number;
|
|
4
|
+
b: number;
|
|
5
|
+
aDir?: MapData.direction;
|
|
6
|
+
bDir?: MapData.direction;
|
|
7
|
+
kind?: Kind;
|
|
8
|
+
zIndex: number[];
|
|
9
|
+
}
|
|
10
|
+
export declare const regularExits: MapData.direction[];
|
|
11
|
+
export declare const shortTolong: Record<string, MapData.direction>;
|
|
12
|
+
export declare const longToShort: Record<MapData.direction, string>;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { default as Area } from './Area';
|
|
2
|
+
import { default as Plane } from './Plane';
|
|
3
|
+
import { default as Exit } from './Exit';
|
|
4
|
+
declare class ExplorationPlane extends Plane {
|
|
5
|
+
private readonly basePlane;
|
|
6
|
+
private readonly visitedRooms;
|
|
7
|
+
constructor(plane: Plane, visitedRooms: Set<number>);
|
|
8
|
+
getRooms(): MapData.Room[];
|
|
9
|
+
getLabels(): MapData.Label[];
|
|
10
|
+
getBounds(): {
|
|
11
|
+
minX: number;
|
|
12
|
+
maxX: number;
|
|
13
|
+
minY: number;
|
|
14
|
+
maxY: number;
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
export default class ExplorationArea extends Area {
|
|
18
|
+
private readonly visitedRooms;
|
|
19
|
+
private readonly areaRoomIds;
|
|
20
|
+
private readonly planeCache;
|
|
21
|
+
constructor(area: MapData.Area, visitedRooms?: Iterable<number> | Set<number>);
|
|
22
|
+
getPlane(zIndex: number): ExplorationPlane;
|
|
23
|
+
getPlanes(): ExplorationPlane[];
|
|
24
|
+
getLinkExits(zIndex: number): Exit[];
|
|
25
|
+
getVisitedRoomCount(): number;
|
|
26
|
+
getTotalRoomCount(): number;
|
|
27
|
+
hasVisitedRoom(roomId: number): boolean;
|
|
28
|
+
getVisitedRoomIds(): number[];
|
|
29
|
+
addVisitedRoom(roomId: number): boolean;
|
|
30
|
+
addVisitedRooms(roomIds: Iterable<number>): number;
|
|
31
|
+
}
|
|
32
|
+
export {};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { default as Area } from './Area';
|
|
2
|
+
import { default as ExplorationArea } from './ExplorationArea';
|
|
3
|
+
export default class MapReader {
|
|
4
|
+
private rooms;
|
|
5
|
+
private areas;
|
|
6
|
+
private areaSources;
|
|
7
|
+
private visitedRooms?;
|
|
8
|
+
private explorationEnabled;
|
|
9
|
+
private colors;
|
|
10
|
+
constructor(map: MapData.Map, envs: MapData.Env[]);
|
|
11
|
+
getArea(areaId: number): Area;
|
|
12
|
+
getExplorationArea(areaId: number): ExplorationArea | undefined;
|
|
13
|
+
getAreas(): Area[];
|
|
14
|
+
getRooms(): MapData.Room[];
|
|
15
|
+
getRoom(roomId: number): MapData.Room;
|
|
16
|
+
decorateWithExploration(visitedRooms?: Iterable<number> | Set<number>): Set<number>;
|
|
17
|
+
getVisitedRooms(): Set<number> | undefined;
|
|
18
|
+
clearExplorationDecoration(): void;
|
|
19
|
+
isExplorationEnabled(): boolean;
|
|
20
|
+
getColorValue(envId: number): string;
|
|
21
|
+
getSymbolColor(envId: number, opacity?: number): string;
|
|
22
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export default class Plane {
|
|
2
|
+
private readonly bounds;
|
|
3
|
+
private readonly rooms;
|
|
4
|
+
private readonly labels;
|
|
5
|
+
constructor(rooms: MapData.Room[], labels: MapData.Label[]);
|
|
6
|
+
getRooms(): MapData.Room[];
|
|
7
|
+
getLabels(): MapData.Label[];
|
|
8
|
+
getBounds(): {
|
|
9
|
+
minX: number;
|
|
10
|
+
maxX: number;
|
|
11
|
+
minY: number;
|
|
12
|
+
maxY: number;
|
|
13
|
+
};
|
|
14
|
+
private createBounds;
|
|
15
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
declare namespace MapData {
|
|
2
|
+
type direction = "north" | "south" | "east" | "west" | "northwest" | "northeast" | "southeast" | "southwest" | "up" | "down" | "in" | "out";
|
|
3
|
+
interface Color {
|
|
4
|
+
alpha: number;
|
|
5
|
+
r: number;
|
|
6
|
+
g: number;
|
|
7
|
+
b: number;
|
|
8
|
+
}
|
|
9
|
+
interface Line {
|
|
10
|
+
points: Point[];
|
|
11
|
+
attributes: LineAttribute;
|
|
12
|
+
}
|
|
13
|
+
interface Point {
|
|
14
|
+
x: number;
|
|
15
|
+
y: number;
|
|
16
|
+
}
|
|
17
|
+
interface LineAttribute {
|
|
18
|
+
color: Color;
|
|
19
|
+
style: string;
|
|
20
|
+
arrow: boolean;
|
|
21
|
+
}
|
|
22
|
+
interface Room {
|
|
23
|
+
id: number;
|
|
24
|
+
area: number;
|
|
25
|
+
x: number;
|
|
26
|
+
y: number;
|
|
27
|
+
z: number;
|
|
28
|
+
areaId: string;
|
|
29
|
+
weight: number;
|
|
30
|
+
roomChar: string;
|
|
31
|
+
name: string;
|
|
32
|
+
userData: Record<string, string>;
|
|
33
|
+
customLines: Record<string, Line>;
|
|
34
|
+
stubs: number[];
|
|
35
|
+
hash: string;
|
|
36
|
+
env: number;
|
|
37
|
+
exits: Record<direction, number>;
|
|
38
|
+
doors: Record<string, 1 | 2 | 3>;
|
|
39
|
+
specialExits: Record<string, number>;
|
|
40
|
+
exitLocks?: number[];
|
|
41
|
+
mSpecialExitLocks?: number[];
|
|
42
|
+
}
|
|
43
|
+
interface Label {
|
|
44
|
+
labelId: number;
|
|
45
|
+
areaId: number;
|
|
46
|
+
pixMap: string;
|
|
47
|
+
X: number;
|
|
48
|
+
Y: number;
|
|
49
|
+
Z: number;
|
|
50
|
+
Width: number;
|
|
51
|
+
Height: number;
|
|
52
|
+
Text: string;
|
|
53
|
+
FgColor: Color;
|
|
54
|
+
BgColor: Color;
|
|
55
|
+
}
|
|
56
|
+
interface Area {
|
|
57
|
+
areaName: string;
|
|
58
|
+
areaId: string;
|
|
59
|
+
rooms: Room[];
|
|
60
|
+
labels: Label[];
|
|
61
|
+
}
|
|
62
|
+
type Map = Area[];
|
|
63
|
+
interface Env {
|
|
64
|
+
envId: number;
|
|
65
|
+
colors: number[];
|
|
66
|
+
}
|
|
67
|
+
}
|
package/package.json
CHANGED
|
@@ -1,26 +1,40 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
},
|
|
15
|
-
"homepage": "https://github.com/Delwing/js-mudlet-map-renderer#readme",
|
|
16
|
-
"license": "MIT",
|
|
17
|
-
"dependencies": {
|
|
18
|
-
"node-dijkstra": "^2.5.0",
|
|
19
|
-
"paper-jsdom": "^0.12.17"
|
|
20
|
-
},
|
|
21
|
-
"main": "./exports.js",
|
|
22
|
-
"devDependencies": {
|
|
23
|
-
"babelify": "^10.0.0",
|
|
24
|
-
"@babel/core": "^7.20.12"
|
|
2
|
+
"name": "mudlet-map-renderer",
|
|
3
|
+
"version": "0.1.1-konva",
|
|
4
|
+
"license": "MIT",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.cjs",
|
|
7
|
+
"module": "./dist/index.mjs",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"import": "./dist/index.mjs",
|
|
13
|
+
"require": "./dist/index.cjs"
|
|
25
14
|
}
|
|
15
|
+
},
|
|
16
|
+
"sideEffects": false,
|
|
17
|
+
"scripts": {
|
|
18
|
+
"dev": "vite",
|
|
19
|
+
"build": "tsc -p tsconfig.json && vite build",
|
|
20
|
+
"preview": "vite preview",
|
|
21
|
+
"demo:dev": "vite --config vite.demo.config.ts",
|
|
22
|
+
"demo:build": "vite build --config vite.demo.config.ts",
|
|
23
|
+
"demo:preview": "vite preview --config vite.demo.config.ts"
|
|
24
|
+
},
|
|
25
|
+
"dependencies": {
|
|
26
|
+
"konva": "^10.0.2",
|
|
27
|
+
"node-dijkstra": "^2.5.1"
|
|
28
|
+
},
|
|
29
|
+
"devDependencies": {
|
|
30
|
+
"tslib": "^2.8.1",
|
|
31
|
+
"tsx": "^4.19.1",
|
|
32
|
+
"typescript": "^5.6.3",
|
|
33
|
+
"vite": "^5.4.8",
|
|
34
|
+
"vite-plugin-dts": "^4.3.0",
|
|
35
|
+
"@types/node-dijkstra": "^2.5.6"
|
|
36
|
+
},
|
|
37
|
+
"files": [
|
|
38
|
+
"dist"
|
|
39
|
+
]
|
|
26
40
|
}
|
package/.prettierrc
DELETED
package/CHANGELOG.md
DELETED
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
# 0.0.24
|
|
2
|
-
- respect room weights
|
|
3
|
-
# 0.0.23
|
|
4
|
-
- do not draw path fragments no on the level of displayed area
|
|
5
|
-
|
|
6
|
-
# 0.0.22
|
|
7
|
-
- handle not existing paths
|
|
8
|
-
|
|
9
|
-
# 0.0.21
|
|
10
|
-
- fixes in special links to other areas
|
|
11
|
-
- add controls for paths
|
|
12
|
-
|
|
13
|
-
# 0.0.20
|
|
14
|
-
|
|
15
|
-
# 0.0.19
|
|
16
|
-
- add path renders
|
|
17
|
-
|
|
18
|
-
# 0.0.18
|
|
19
|
-
- drag event will be fired actually on drag not only on release
|
|
20
|
-
|
|
21
|
-
# 0.0.17
|
|
22
|
-
- fix emboss
|
|
23
|
-
|
|
24
|
-
# 0.0.16
|
|
25
|
-
- add emoss setting
|
|
26
|
-
- add drag event
|
|
27
|
-
|
|
28
|
-
# 0.0.15
|
|
29
|
-
- additional fix for custom exit lines exit
|
|
30
|
-
# 0.0.14
|
|
31
|
-
- add area change clicks on custom exit lines
|
|
32
|
-
# 0.0.13
|
|
33
|
-
- add line color (experimental)
|
|
34
|
-
|
|
35
|
-
# 0.0.12
|
|
36
|
-
- try to limit label font size to fit within label bounds
|
|
37
|
-
|
|
38
|
-
# 0.0.11
|
|
39
|
-
- another fix frame mode for background selection
|
|
40
|
-
|
|
41
|
-
# 0.0.10
|
|
42
|
-
- fix frame mode for background selection
|
|
43
|
-
|
|
44
|
-
# 0.0.9
|
|
45
|
-
- add transparent labels option
|
|
46
|
-
|
|
47
|
-
# 0.0.8
|
|
48
|
-
- remove wrong limits for drag
|
|
49
|
-
# 0.0.7
|
|
50
|
-
- fix renderer compliation error
|
|
51
|
-
# 0.0.6
|
|
52
|
-
- fix controls error when zooming out max
|
|
53
|
-
- make JS code not use experimental features
|
|
54
|
-
# 0.0.5
|
|
55
|
-
- add limit function for areas
|
|
56
|
-
|
|
57
|
-
# 0.0.4
|
|
58
|
-
- fix exports
|
|
59
|
-
|
|
60
|
-
# 0.0.3
|
|
61
|
-
- add option to set font and background color
|
|
62
|
-
- multiple fixes
|
|
63
|
-
|
|
64
|
-
# 0.0.2
|
|
65
|
-
- add option to set font for text labels
|
|
66
|
-
- fix README example
|
|
67
|
-
|
|
68
|
-
# 0.0.1
|
|
69
|
-
- initial release
|
package/README.md
DELETED
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
# Mudlet Map Renderer
|
|
2
|
-
|
|
3
|
-
Mudlet map rendering library. Can be used in Node.js and in browser.
|
|
4
|
-
|
|
5
|
-
Until version `1.0.0` API is subject of change. Use with caution!
|
|
6
|
-
|
|
7
|
-
## TODO
|
|
8
|
-
|
|
9
|
-
- [ ] Publish some examples (with data)
|
|
10
|
-
- [ ] Convert to .ts
|
|
11
|
-
- [ ] Document functions
|
|
12
|
-
- [ ] Add test
|
|
13
|
-
- [ ] Add lint
|
|
14
|
-
- [ ] Align model with mudlet-map-binary-reader
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
## Very basic example
|
|
18
|
-
|
|
19
|
-
```js
|
|
20
|
-
const fs = require("fs");
|
|
21
|
-
const { MudletMapReader } = require("mudlet-map-binary-reader") //npm mudlet-map-binary-reader
|
|
22
|
-
const { Renderer, MapReader } = require("mudlet-map-renderer")
|
|
23
|
-
|
|
24
|
-
let map = MudletMapReader.read("./data/map.dat");
|
|
25
|
-
MudletMapReader.export(map, "./data");
|
|
26
|
-
let mapData = require("./data/mapExport.json");
|
|
27
|
-
let mapColors = require("./data/colors.json");
|
|
28
|
-
|
|
29
|
-
let reader = new MapReader(mapData, mapColors);
|
|
30
|
-
|
|
31
|
-
const roomId = 1;
|
|
32
|
-
const scale = 40;
|
|
33
|
-
let area = reader.getAreaByRoomId(roomId);
|
|
34
|
-
let settings = { scale: scale }
|
|
35
|
-
let renderer = new Renderer(null, reader, area, reader.getColors(), settings);
|
|
36
|
-
fs.writeFileSync("mapFull.svg", renderer.exportSvg());
|
|
37
|
-
fs.writeFileSync("mapFragment.svg", renderer.exportSvg(roomId, 10));
|
|
38
|
-
console.log("Map generated");
|
|
39
|
-
```
|
|
40
|
-
|
|
41
|
-
## Settings and their default values
|
|
42
|
-
```js
|
|
43
|
-
class Settings {
|
|
44
|
-
isRound = false;
|
|
45
|
-
scale = 55;
|
|
46
|
-
roomSize = 10;
|
|
47
|
-
exitsSize = 2;
|
|
48
|
-
borders = false;
|
|
49
|
-
frameMode = false;
|
|
50
|
-
areaName = true;
|
|
51
|
-
showLabels = true;
|
|
52
|
-
uniformLevelSize = false;
|
|
53
|
-
fontFamily = 'sans-serif';
|
|
54
|
-
mapBackground = "#000000";
|
|
55
|
-
linesColor = '#FFFFFF';
|
|
56
|
-
transparentLabels = false;
|
|
57
|
-
emboss = false;
|
|
58
|
-
}
|
|
59
|
-
```
|