mudlet-map-renderer 1.0.0 → 1.2.0

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.
Files changed (106) hide show
  1. package/README.md +520 -0
  2. package/dist/AreaMapRenderer.d.ts +125 -0
  3. package/dist/CullingManager.d.ts +15 -0
  4. package/dist/ExitRenderer.d.ts +109 -0
  5. package/dist/InteractionHandler.d.ts +47 -0
  6. package/dist/MapGraph.d.ts +28 -0
  7. package/dist/MapReader-mU_4JWv_.js +224 -0
  8. package/dist/MapReader-mU_4JWv_.js.map +1 -0
  9. package/dist/MapState.d.ts +110 -0
  10. package/dist/PathData.d.ts +18 -0
  11. package/dist/PathFinder.d.ts +12 -0
  12. package/dist/ScenePipeline.d.ts +226 -0
  13. package/dist/SvgTypes.d.ts +21 -0
  14. package/dist/TypedEventEmitter.d.ts +17 -0
  15. package/dist/binary/BinaryMapReader.d.ts +36 -0
  16. package/dist/binary/index.d.ts +2 -0
  17. package/dist/binary.mjs +34 -0
  18. package/dist/binary.mjs.map +1 -0
  19. package/dist/camera/Camera.d.ts +118 -0
  20. package/dist/coord/CoordFn.d.ts +13 -0
  21. package/dist/directions.d.ts +25 -0
  22. package/dist/draw/DrawCommand.d.ts +104 -0
  23. package/dist/draw/DrawCommandBuilder.d.ts +19 -0
  24. package/dist/export/CanvasExporter.d.ts +71 -0
  25. package/dist/export/Exporter.d.ts +58 -0
  26. package/dist/export/PngExporter.d.ts +23 -0
  27. package/dist/export/SvgExporter.d.ts +19 -0
  28. package/dist/export/canvasToBytes.d.ts +19 -0
  29. package/dist/export/clipSceneToViewport.d.ts +48 -0
  30. package/dist/export/flushSceneShapes.d.ts +21 -0
  31. package/dist/export/sceneBounds.d.ts +24 -0
  32. package/dist/hit/HitTester.d.ts +101 -0
  33. package/dist/index.d.ts +61 -0
  34. package/dist/index.mjs +6670 -0
  35. package/dist/index.mjs.map +1 -0
  36. package/dist/lens/ExplorationLens.d.ts +29 -0
  37. package/dist/lens/RoomLens.d.ts +47 -0
  38. package/dist/lens/composeLenses.d.ts +31 -0
  39. package/dist/lens/index.d.ts +5 -0
  40. package/dist/overlay/AmbientLightOverlay.d.ts +32 -0
  41. package/dist/overlay/LiveEffect.d.ts +33 -0
  42. package/dist/overlay/SceneOverlay.d.ts +68 -0
  43. package/dist/reader/Area.d.ts +63 -0
  44. package/dist/reader/Exit.d.ts +15 -0
  45. package/dist/reader/MapReader.d.ts +34 -0
  46. package/dist/reader/Plane.d.ts +33 -0
  47. package/dist/render/CanvasRenderer.d.ts +17 -0
  48. package/dist/render/RecordingLayer.d.ts +158 -0
  49. package/dist/render/SvgRenderer.d.ts +7 -0
  50. package/dist/render/shapeToRecording.d.ts +3 -0
  51. package/dist/rendering/KonvaRenderBackend.d.ts +122 -0
  52. package/dist/rendering/MapRenderer.d.ts +213 -0
  53. package/dist/rendering/SceneManager.d.ts +54 -0
  54. package/dist/scene/AmbientLightStyle.d.ts +29 -0
  55. package/dist/scene/GridStyle.d.ts +21 -0
  56. package/dist/scene/InnerExitStyle.d.ts +24 -0
  57. package/dist/scene/OverlayStyle.d.ts +47 -0
  58. package/dist/scene/RoomStyle.d.ts +32 -0
  59. package/dist/scene/Shape.d.ts +151 -0
  60. package/dist/scene/SpecialExitStyle.d.ts +37 -0
  61. package/dist/scene/StubStyle.d.ts +15 -0
  62. package/dist/scene/elements/ExitLayout.d.ts +22 -0
  63. package/dist/scene/elements/GridLayout.d.ts +24 -0
  64. package/dist/scene/elements/LabelLayout.d.ts +11 -0
  65. package/dist/scene/elements/OverlayLayout.d.ts +14 -0
  66. package/dist/scene/elements/RoomLayout.d.ts +19 -0
  67. package/dist/scene/elements/SpecialExitLayout.d.ts +19 -0
  68. package/dist/scene/elements/StubLayout.d.ts +19 -0
  69. package/dist/style/Style.d.ts +60 -0
  70. package/dist/style/applyStyle.d.ts +3 -0
  71. package/dist/style/index.d.ts +21 -0
  72. package/dist/style/shape/BlueprintStyle.d.ts +11 -0
  73. package/dist/style/shape/ConstructionStyle.d.ts +17 -0
  74. package/dist/style/shape/IsometricStyle.d.ts +32 -0
  75. package/dist/style/shape/NeonStyle.d.ts +17 -0
  76. package/dist/style/shape/ParchmentStyle.d.ts +13 -0
  77. package/dist/style/shape/SciFiStyle.d.ts +16 -0
  78. package/dist/style/shape/SketchyStyle.d.ts +22 -0
  79. package/dist/style/shape/index.d.ts +25 -0
  80. package/dist/style/shape/paintMap.d.ts +25 -0
  81. package/dist/style/shape/wobble.d.ts +24 -0
  82. package/{src/types/MapData.ts → dist/types/MapData.d.ts} +70 -90
  83. package/dist/types/Settings.d.ts +206 -0
  84. package/dist/utils/color.d.ts +12 -0
  85. package/dist/utils/textMeasure.d.ts +38 -0
  86. package/package.json +67 -37
  87. package/demo/colors.json +0 -1
  88. package/demo/index.html +0 -102
  89. package/demo/main.ts +0 -389
  90. package/demo/mapExport.json +0 -1
  91. package/demo/tsconfig.json +0 -11
  92. package/src/ExitRenderer.ts +0 -275
  93. package/src/PathFinder.ts +0 -93
  94. package/src/PathRenderer.ts +0 -129
  95. package/src/Renderer.ts +0 -374
  96. package/src/directions.ts +0 -66
  97. package/src/index.ts +0 -4
  98. package/src/reader/Area.ts +0 -96
  99. package/src/reader/Exit.ts +0 -36
  100. package/src/reader/ExplorationArea.ts +0 -132
  101. package/src/reader/MapReader.ts +0 -123
  102. package/src/reader/Plane.ts +0 -42
  103. package/tsconfig.json +0 -17
  104. package/vercel.json +0 -5
  105. package/vite.config.ts +0 -29
  106. package/vite.demo.config.ts +0 -15
package/src/Renderer.ts DELETED
@@ -1,374 +0,0 @@
1
- import Konva from "konva";
2
- import ExitRenderer from "./ExitRenderer";
3
- import MapReader from "./reader/MapReader";
4
- import Exit from "./reader/Exit";
5
- import PathRenderer from "./PathRenderer";
6
-
7
- const defaultRoomSize = 0.6;
8
- const padding = 1;
9
- const defaultZoom = 75
10
- const lineColor = 'rgb(225, 255, 225)';
11
-
12
- export class Settings {
13
- static roomSize = defaultRoomSize;
14
- static lineColor = lineColor;
15
- }
16
-
17
- type HighlightData = {
18
- color: string;
19
- area: number;
20
- z: number;
21
- shape?: Konva.Circle;
22
- };
23
-
24
- export class Renderer {
25
-
26
- private readonly stage: Konva.Stage;
27
- private readonly roomLayer: Konva.Layer;
28
- private readonly linkLayer: Konva.Layer;
29
- private readonly overlayLayer: Konva.Layer;
30
- private readonly positionLayer: Konva.Layer;
31
- private mapReader: MapReader;
32
- private exitRenderer: ExitRenderer;
33
- private pathRenderer: PathRenderer;
34
- private highlights: Map<number, HighlightData> = new Map();
35
- private currentArea?: number;
36
- private currentZIndex?: number;
37
- private currentAreaVersion?: number;
38
- private positionRender?: Konva.Circle;
39
- private currentTransition?: Konva.Tween;
40
- private currentZoom: number = 1;
41
-
42
- constructor(container: HTMLDivElement, mapReader: MapReader) {
43
- this.stage = new Konva.Stage({
44
- container: container,
45
- width: container.clientWidth,
46
- height: container.clientHeight,
47
- draggable: true
48
- });
49
- container.addEventListener('resize', () => {
50
- this.stage.width(container.clientWidth);
51
- this.stage.height(container.clientHeight);
52
- this.stage.batchDraw();
53
- })
54
- this.linkLayer = new Konva.Layer({
55
- listening: false,
56
- });
57
- this.stage.add(this.linkLayer);
58
- this.roomLayer = new Konva.Layer();
59
- this.stage.add(this.roomLayer);
60
- this.overlayLayer = new Konva.Layer({
61
- listening: false,
62
- })
63
- this.stage.add(this.overlayLayer);
64
- this.positionLayer = new Konva.Layer({
65
- listening: false,
66
- });
67
- this.stage.add(this.positionLayer);
68
- this.mapReader = mapReader;
69
- this.exitRenderer = new ExitRenderer(mapReader);
70
- this.pathRenderer = new PathRenderer(mapReader, this.overlayLayer);
71
-
72
- const scaleBy = 1.1;
73
- this.initScaling(scaleBy);
74
- }
75
-
76
- private initScaling(scaleBy: number) {
77
- this.stage.on('wheel', (e) => {
78
- e.evt.preventDefault();
79
-
80
- const oldScale = this.stage.scaleX();
81
- const pointer = this.stage.getPointerPosition();
82
- if (!pointer) {
83
- return;
84
- }
85
-
86
- const mousePointTo = {
87
- x: (pointer.x - this.stage.x()) / oldScale,
88
- y: (pointer.y - this.stage.y()) / oldScale,
89
- };
90
-
91
- let direction = e.evt.deltaY > 0 ? -1 : 1;
92
-
93
- if (e.evt.ctrlKey) {
94
- direction = -direction;
95
- }
96
-
97
- const newZoom = direction > 0 ? this.currentZoom * scaleBy : this.currentZoom / scaleBy;
98
- const newScale = newZoom * defaultZoom;
99
- this.setZoom(newZoom);
100
-
101
- const newPos = {
102
- x: pointer.x - mousePointTo.x * newScale,
103
- y: pointer.y - mousePointTo.y * newScale,
104
- };
105
-
106
- this.stage.position(newPos);
107
- });
108
- }
109
-
110
- drawArea(id: number, zIndex: number) {
111
- const area = this.mapReader.getArea(id);
112
- if (!area) {
113
- return;
114
- }
115
- const plane = area.getPlane(zIndex);
116
- if (!plane) {
117
- return;
118
- }
119
- this.currentArea = id;
120
- this.currentZIndex = zIndex;
121
- this.currentAreaVersion = area.getVersion();
122
- this.roomLayer.destroyChildren();
123
- this.linkLayer.destroyChildren();
124
-
125
- const {minX, maxX, minY, maxY} = plane.getBounds();
126
-
127
- this.stage.offset({x: minX - padding, y: minY - padding});
128
- this.stage.scale({x: defaultZoom * this.currentZoom, y: defaultZoom * this.currentZoom});
129
-
130
- this.renderLabels(plane.getLabels());
131
- this.renderRooms(plane.getRooms() ?? []);
132
- this.renderExits(area.getLinkExits(zIndex));
133
- this.refreshHighlights();
134
- this.stage.batchDraw();
135
- }
136
-
137
- setZoom(zoom: number) {
138
- this.currentZoom = zoom;
139
- this.stage.scale({x: defaultZoom * zoom, y: defaultZoom * zoom});
140
- }
141
-
142
- getZoom() {
143
- return this.currentZoom;
144
- }
145
-
146
- getCurrentArea() {
147
- return this.currentArea ? this.mapReader.getArea(this.currentArea) : undefined
148
- }
149
-
150
- setPosition(roomId: number) {
151
- const room = this.mapReader.getRoom(roomId);
152
- if (!room) return;
153
- const area = this.mapReader.getArea(room.area);
154
- const areaVersion = area?.getVersion();
155
- let instant = this.currentArea !== room.area || this.currentZIndex !== room.z
156
- if (this.currentArea !== room.area || this.currentZIndex !== room.z || (areaVersion !== undefined && this.currentAreaVersion !== areaVersion)) {
157
- this.drawArea(room.area, room.z);
158
- }
159
- if (!this.positionRender) {
160
- this.positionRender = new Konva.Circle({
161
- x: room.x,
162
- y: room.y,
163
- radius: defaultRoomSize * 0.85,
164
- stroke: "rgb(0, 229, 178)",
165
- strokeWidth: 0.1,
166
- dash: [0.05, 0.05],
167
- dashEnabled: true,
168
- })
169
- this.positionLayer.add(this.positionRender);
170
- }
171
- this.centerOnRoom(room, instant);
172
- }
173
-
174
- renderPath(locations: number[]) {
175
- return this.pathRenderer.renderPath(locations, this.currentArea, this.currentZIndex);
176
- }
177
-
178
- clearPaths() {
179
- this.pathRenderer.clearPaths();
180
- }
181
-
182
- renderHighlight(roomId: number, color: string) {
183
- const room = this.mapReader.getRoom(roomId);
184
- if (!room) {
185
- return;
186
- }
187
-
188
- const existing = this.highlights.get(roomId);
189
- if (existing?.shape) {
190
- existing.shape.destroy();
191
- delete existing.shape;
192
- }
193
-
194
- const highlightData: HighlightData = {color, area: room.area, z: room.z};
195
-
196
- this.highlights.set(roomId, highlightData);
197
-
198
- if (room.area === this.currentArea && room.z === this.currentZIndex) {
199
- const shape = this.createHighlightShape(room, color);
200
- this.overlayLayer.add(shape);
201
- highlightData.shape = shape;
202
- this.overlayLayer.batchDraw();
203
- return shape;
204
- }
205
-
206
- return highlightData.shape;
207
- }
208
-
209
- clearHighlights() {
210
- this.highlights.forEach(({shape}) => shape?.destroy());
211
- this.highlights.clear();
212
- this.overlayLayer.batchDraw();
213
- }
214
-
215
- private refreshHighlights() {
216
- this.highlights.forEach((highlight, roomId) => {
217
- highlight.shape?.destroy();
218
- delete highlight.shape;
219
-
220
- if (highlight.area !== this.currentArea || highlight.z !== this.currentZIndex) {
221
- return;
222
- }
223
-
224
- const room = this.mapReader.getRoom(roomId);
225
- if (!room) {
226
- return;
227
- }
228
-
229
- const shape = this.createHighlightShape(room, highlight.color);
230
- this.overlayLayer.add(shape);
231
- highlight.shape = shape;
232
- });
233
-
234
- this.overlayLayer.batchDraw();
235
- }
236
-
237
- private createHighlightShape(room: MapData.Room, color: string) {
238
- return new Konva.Circle({
239
- x: room.x,
240
- y: room.y,
241
- radius: Settings.roomSize * 0.9,
242
- stroke: color,
243
- strokeWidth: 0.15,
244
- dash: [0.1, 0.05],
245
- dashEnabled: true,
246
- listening: false,
247
- });
248
- }
249
-
250
- private centerOnRoom(room: MapData.Room, instant: boolean = false) {
251
- const roomCenter = {x: room.x, y: room.y};
252
-
253
- this.positionRender?.position(room)
254
-
255
- const abs = this.stage.getAbsoluteTransform()
256
- const screenPoint = abs.point(roomCenter);
257
-
258
- const target = {
259
- x: this.stage.width() / 2,
260
- y: this.stage.height() / 2,
261
- };
262
-
263
- const dx = target.x - screenPoint.x;
264
- const dy = target.y - screenPoint.y;
265
-
266
- if (this.currentTransition) {
267
- this.currentTransition.pause()
268
- this.currentTransition.destroy()
269
- delete this.currentTransition;
270
- }
271
-
272
- if (instant) {
273
- this.stage.position({
274
- x: this.stage.x() + dx,
275
- y: this.stage.y() + dy,
276
- })
277
- } else {
278
- this.currentTransition = new Konva.Tween({
279
- node: this.stage,
280
- x: this.stage.x() + dx,
281
- y: this.stage.y() + dy,
282
- duration: 0.2,
283
- easing: Konva.Easings.EaseInOut,
284
- })
285
- this.currentTransition.play()
286
- }
287
- }
288
-
289
- private renderRooms(rooms: MapData.Room[]) {
290
- rooms.forEach(room => {
291
- const roomRender = new Konva.Group({
292
- x: room.x - Settings.roomSize / 2,
293
- y: room.y - Settings.roomSize / 2,
294
- });
295
- const roomRect = new Konva.Rect({
296
- x: 0,
297
- y: 0,
298
- width: Settings.roomSize,
299
- height: Settings.roomSize,
300
- fill: this.mapReader.getColorValue(room.env),
301
- strokeWidth: 0.025,
302
- stroke: Settings.lineColor,
303
- });
304
- roomRender.on('mouseenter', () => {
305
- this.stage.container().style.cursor = 'pointer';
306
- })
307
- roomRender.on('mouseleave', () => {
308
- this.stage.container().style.cursor = 'auto';
309
- })
310
- roomRender.add(roomRect);
311
- this.renderSymbol(room, roomRender);
312
- this.roomLayer.add(roomRender);
313
-
314
- this.exitRenderer.renderSpecialExits(room).forEach(render => {
315
- this.linkLayer.add(render)
316
- })
317
- this.exitRenderer.renderStubs(room).forEach(render => {
318
- this.linkLayer.add(render)
319
- })
320
- this.exitRenderer.renderInnerExits(room).forEach(render => {
321
- this.roomLayer.add(render)
322
- })
323
- })
324
- }
325
-
326
- private renderSymbol(room: MapData.Room, roomRender: Konva.Group) {
327
- if (room.roomChar !== undefined) {
328
- const roomChar = new Konva.Text({
329
- x: 0,
330
- y: 0,
331
- text: room.roomChar,
332
- fontSize: 0.45,
333
- fontStyle: "bold",
334
- fill: this.mapReader.getSymbolColor(room.env),
335
- align: "center",
336
- verticalAlign: "middle",
337
- width: Settings.roomSize,
338
- height: Settings.roomSize,
339
- })
340
- roomRender.add(roomChar);
341
- }
342
- }
343
-
344
- private renderExits(exits: Exit[]) {
345
- exits.forEach(exit => {
346
- const render = this.exitRenderer.render(exit);
347
- if (!render) {
348
- return;
349
- }
350
- this.linkLayer.add(render);
351
- })
352
-
353
- }
354
-
355
- private renderLabels(Labels: MapData.Label[]) {
356
- Labels.forEach(label => {
357
- if (!label.pixMap) {
358
- return
359
- }
360
- const image = new Image()
361
- image.src = `data:image/png;base64,${label.pixMap}`
362
- const labelRender = new Konva.Image({
363
- x: label.X,
364
- y: -label.Y,
365
- width: label.Width,
366
- height: label.Height,
367
- image: image
368
- })
369
- this.linkLayer.add(labelRender)
370
- })
371
- }
372
-
373
-
374
- }
package/src/directions.ts DELETED
@@ -1,66 +0,0 @@
1
- export type PlanarDirection =
2
- | "north"
3
- | "south"
4
- | "east"
5
- | "west"
6
- | "northeast"
7
- | "northwest"
8
- | "southeast"
9
- | "southwest";
10
-
11
- const planarDirectionOffsets: Record<PlanarDirection, {x: number; y: number}> = {
12
- north: {x: 0, y: -1},
13
- south: {x: 0, y: 1},
14
- east: {x: 1, y: 0},
15
- west: {x: -1, y: 0},
16
- northeast: {x: 1, y: -1},
17
- northwest: {x: -1, y: -1},
18
- southeast: {x: 1, y: 1},
19
- southwest: {x: -1, y: 1},
20
- };
21
-
22
- export const planarDirections: PlanarDirection[] = [
23
- "north",
24
- "south",
25
- "east",
26
- "west",
27
- "northeast",
28
- "northwest",
29
- "southeast",
30
- "southwest",
31
- ];
32
-
33
- export const oppositeDirections: Record<PlanarDirection, PlanarDirection> = {
34
- north: "south",
35
- south: "north",
36
- east: "west",
37
- west: "east",
38
- northeast: "southwest",
39
- northwest: "southeast",
40
- southeast: "northwest",
41
- southwest: "northeast",
42
- };
43
-
44
- function isPlanarDirection(direction: MapData.direction | undefined): direction is PlanarDirection {
45
- if (!direction) {
46
- return false;
47
- }
48
- return Object.prototype.hasOwnProperty.call(planarDirectionOffsets, direction);
49
- }
50
-
51
- export function movePoint(
52
- x: number,
53
- y: number,
54
- direction?: MapData.direction,
55
- distance: number = 1,
56
- ) {
57
- if (!isPlanarDirection(direction)) {
58
- return {x, y};
59
- }
60
-
61
- const offset = planarDirectionOffsets[direction];
62
- return {
63
- x: x + offset.x * distance,
64
- y: y + offset.y * distance,
65
- };
66
- }
package/src/index.ts DELETED
@@ -1,4 +0,0 @@
1
- export * from './Renderer';
2
- export { default as MapReader } from './reader/MapReader';
3
- export { default as PathFinder } from './PathFinder';
4
- export { default as ExplorationArea } from './reader/ExplorationArea';
@@ -1,96 +0,0 @@
1
- import Plane from "./Plane";
2
-
3
- import Exit, {longToShort, regularExits} from "./Exit";
4
-
5
- export default class Area {
6
-
7
- private readonly planes: Record<number, Plane> = {};
8
- private readonly area: MapData.Area;
9
- private readonly exits: Map<string, Exit> = new Map();
10
- private version = 0;
11
-
12
- constructor(area: MapData.Area) {
13
- this.area = area;
14
- this.planes = this.createPlanes();
15
- this.createExits();
16
- }
17
-
18
- getAreaName() {
19
- return this.area.areaName
20
- }
21
-
22
- getAreaId() {
23
- return parseInt(this.area.areaId)
24
- }
25
-
26
- getVersion() {
27
- return this.version;
28
- }
29
-
30
- protected markDirty() {
31
- this.version++;
32
- }
33
-
34
- getPlane(zIndex: number) {
35
- return this.planes[zIndex];
36
- }
37
-
38
- getPlanes() {
39
- return Object.values(this.planes);
40
- }
41
-
42
- getRooms() {
43
- return this.area.rooms
44
- }
45
-
46
- getLinkExits(zIndex: number) {
47
- return Array.from(this.exits.values()).filter(e => e.zIndex.includes(zIndex));
48
- }
49
-
50
- private createPlanes() {
51
- const grouped = this.area.rooms.reduce<Record<number, MapData.Room[]>>((acc, room) => {
52
- if (!acc[room.z]) {
53
- acc[room.z] = [];
54
- }
55
- // @ts-ignore
56
- acc[room.z].push(room);
57
- return acc;
58
- }, {});
59
- return Object.entries(grouped).reduce(
60
- (acc, [z, rooms]) => {
61
- acc[+z] = new Plane(rooms, this.area.labels.filter(label => label.Z === +z));
62
- return acc;
63
- },
64
- {} as Record<number, Plane>
65
- );
66
- }
67
-
68
- private createExits() {
69
- this.area.rooms.forEach(room => {
70
- Object.entries(room.exits)
71
- .filter(([direction, _]) => regularExits.indexOf(direction as MapData.direction) > -1 && !room.customLines.hasOwnProperty(longToShort[direction as MapData.direction]))
72
- .forEach(([direction, targetRoomId]) => this.createHalfExit(room.id, targetRoomId, room.z, direction as MapData.direction))
73
- })
74
- }
75
-
76
- private createHalfExit(originRoom: number, targetRoom: number, zIndex: number, direction: MapData.direction,) {
77
- if (originRoom === targetRoom) {
78
- return
79
- }
80
- const a = Math.min(originRoom, targetRoom);
81
- const b = Math.max(originRoom, targetRoom);
82
- const key = `${a}-${b}`;
83
- let edge = this.exits.get(key);
84
- if (!edge) {
85
- edge = {a: a, b: b, zIndex: [zIndex]};
86
- }
87
- if (a == originRoom) {
88
- edge.aDir = direction;
89
- } else {
90
- edge.bDir = direction;
91
- }
92
- edge.zIndex.push(zIndex);
93
- this.exits.set(key, edge);
94
- }
95
-
96
- }
@@ -1,36 +0,0 @@
1
- export type Kind = "exit" | "specialExit";
2
-
3
- export default interface Exit {
4
- a: number;
5
- b: number;
6
- aDir?: MapData.direction;
7
- bDir?: MapData.direction;
8
- kind?: Kind;
9
- zIndex: number[];
10
- }
11
-
12
- export const regularExits: MapData.direction[] = ["north", "south", "east", "west", "northeast", "northwest", "southeast", "southwest"];
13
- export const shortTolong: Record<string, MapData.direction> = {
14
- "n": "north",
15
- "s": "south",
16
- "e": "east",
17
- "w": "west",
18
- "ne": "northeast",
19
- "nw": "northwest",
20
- "se": "southeast",
21
- "sw": "southwest",
22
- }
23
- export const longToShort: Record<MapData.direction, string> = {
24
- "north": "n",
25
- "south": "s",
26
- "east": "e",
27
- "west": "w",
28
- "northeast": "ne",
29
- "northwest": "nw",
30
- "southeast": "se",
31
- "southwest": "sw",
32
- "up": "u",
33
- "down": "d",
34
- "in": "i",
35
- "out": "o"
36
- }
@@ -1,132 +0,0 @@
1
- import Area from "./Area";
2
- import Plane from "./Plane";
3
- import Exit from "./Exit";
4
-
5
- class ExplorationPlane extends Plane {
6
-
7
- private readonly basePlane: Plane;
8
- private readonly visitedRooms: Set<number>;
9
-
10
- constructor(plane: Plane, visitedRooms: Set<number>) {
11
- super(plane.getRooms(), plane.getLabels());
12
- this.basePlane = plane;
13
- this.visitedRooms = visitedRooms;
14
- }
15
-
16
- override getRooms() {
17
- return this.basePlane.getRooms().filter(room => this.visitedRooms.has(room.id));
18
- }
19
-
20
- override getLabels() {
21
- return this.basePlane.getLabels();
22
- }
23
-
24
- override getBounds() {
25
- const rooms = this.getRooms();
26
- if (!rooms.length) {
27
- return this.basePlane.getBounds();
28
- }
29
- return rooms.reduce(
30
- (acc, room) => ({
31
- minX: Math.min(acc.minX, room.x),
32
- maxX: Math.max(acc.maxX, room.x),
33
- minY: Math.min(acc.minY, room.y),
34
- maxY: Math.max(acc.maxY, room.y),
35
- }),
36
- {
37
- minX: Number.POSITIVE_INFINITY,
38
- maxX: Number.NEGATIVE_INFINITY,
39
- minY: Number.POSITIVE_INFINITY,
40
- maxY: Number.NEGATIVE_INFINITY,
41
- }
42
- );
43
- }
44
-
45
- }
46
-
47
- export default class ExplorationArea extends Area {
48
-
49
- private readonly visitedRooms: Set<number>;
50
- private readonly areaRoomIds: Set<number>;
51
- private readonly planeCache: WeakMap<Plane, ExplorationPlane> = new WeakMap();
52
-
53
- constructor(area: MapData.Area, visitedRooms?: Iterable<number> | Set<number>) {
54
- super(area);
55
- this.visitedRooms = visitedRooms instanceof Set ? visitedRooms : new Set(visitedRooms ?? []);
56
- this.areaRoomIds = new Set(area.rooms.map(room => room.id));
57
- }
58
-
59
- override getPlane(zIndex: number) {
60
- const basePlane = super.getPlane(zIndex);
61
- if (!basePlane) {
62
- return basePlane;
63
- }
64
- let decorated = this.planeCache.get(basePlane);
65
- if (!decorated) {
66
- decorated = new ExplorationPlane(basePlane, this.visitedRooms);
67
- this.planeCache.set(basePlane, decorated);
68
- }
69
- return decorated;
70
- }
71
-
72
- override getPlanes() {
73
- return super.getPlanes().map(plane => {
74
- let decorated = this.planeCache.get(plane);
75
- if (!decorated) {
76
- decorated = new ExplorationPlane(plane, this.visitedRooms);
77
- this.planeCache.set(plane, decorated);
78
- }
79
- return decorated;
80
- });
81
- }
82
-
83
- override getLinkExits(zIndex: number) {
84
- return super
85
- .getLinkExits(zIndex)
86
- .filter((exit: Exit) => this.visitedRooms.has(exit.a) || this.visitedRooms.has(exit.b));
87
- }
88
-
89
- getVisitedRoomCount() {
90
- return super.getRooms().reduce((count, room) => count + (this.visitedRooms.has(room.id) ? 1 : 0), 0);
91
- }
92
-
93
- getTotalRoomCount() {
94
- return this.areaRoomIds.size;
95
- }
96
-
97
- hasVisitedRoom(roomId: number) {
98
- return this.areaRoomIds.has(roomId) && this.visitedRooms.has(roomId);
99
- }
100
-
101
- getVisitedRoomIds() {
102
- return super.getRooms()
103
- .filter(room => this.visitedRooms.has(room.id))
104
- .map(room => room.id);
105
- }
106
-
107
- addVisitedRoom(roomId: number) {
108
- const wasVisited = this.visitedRooms.has(roomId);
109
- this.visitedRooms.add(roomId);
110
- const newlyVisited = !wasVisited && this.areaRoomIds.has(roomId);
111
- if (newlyVisited) {
112
- this.markDirty();
113
- }
114
- return newlyVisited;
115
- }
116
-
117
- addVisitedRooms(roomIds: Iterable<number>) {
118
- let newlyVisited = 0;
119
- for (const roomId of roomIds) {
120
- const wasVisited = this.visitedRooms.has(roomId);
121
- this.visitedRooms.add(roomId);
122
- if (!wasVisited && this.areaRoomIds.has(roomId)) {
123
- newlyVisited++;
124
- }
125
- }
126
- if (newlyVisited > 0) {
127
- this.markDirty();
128
- }
129
- return newlyVisited;
130
- }
131
-
132
- }