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/index.mjs ADDED
@@ -0,0 +1,1074 @@
1
+ import u from "konva";
2
+ const _ = ["north", "south", "east", "west", "northeast", "northwest", "southeast", "southwest"], w = {
3
+ north: "n",
4
+ south: "s",
5
+ east: "e",
6
+ west: "w",
7
+ northeast: "ne",
8
+ northwest: "nw",
9
+ southeast: "se",
10
+ southwest: "sw",
11
+ up: "u",
12
+ down: "d",
13
+ in: "i",
14
+ out: "o"
15
+ }, M = {
16
+ north: { x: 0, y: -1 },
17
+ south: { x: 0, y: 1 },
18
+ east: { x: 1, y: 0 },
19
+ west: { x: -1, y: 0 },
20
+ northeast: { x: 1, y: -1 },
21
+ northwest: { x: -1, y: -1 },
22
+ southeast: { x: 1, y: 1 },
23
+ southwest: { x: -1, y: 1 }
24
+ }, L = [
25
+ "north",
26
+ "south",
27
+ "east",
28
+ "west",
29
+ "northeast",
30
+ "northwest",
31
+ "southeast",
32
+ "southwest"
33
+ ], j = {
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
+ function X(a) {
44
+ return a ? Object.prototype.hasOwnProperty.call(M, a) : !1;
45
+ }
46
+ function p(a, e, t, s = 1) {
47
+ if (!X(t))
48
+ return { x: a, y: e };
49
+ const r = M[t];
50
+ return {
51
+ x: a + r.x * s,
52
+ y: e + r.y * s
53
+ };
54
+ }
55
+ const y = {
56
+ OPEN_DOOR: "rgb(10, 155, 10)",
57
+ CLOSED_DOOR: "rgb(226, 205, 59)",
58
+ LOCKED_DOOR: "rgb(155, 10, 10)"
59
+ }, F = {
60
+ 1: "north",
61
+ 2: "northeast",
62
+ 3: "northwest",
63
+ 4: "east",
64
+ 5: "west",
65
+ 6: "south",
66
+ 7: "southeast",
67
+ 8: "southwest",
68
+ 9: "up",
69
+ 10: "down",
70
+ 11: "in",
71
+ 12: "out"
72
+ }, Z = ["up", "down", "in", "out"];
73
+ function G(a) {
74
+ switch (a) {
75
+ case 1:
76
+ return y.OPEN_DOOR;
77
+ case 2:
78
+ return y.CLOSED_DOOR;
79
+ default:
80
+ return y.LOCKED_DOOR;
81
+ }
82
+ }
83
+ class H {
84
+ constructor(e) {
85
+ this.mapReader = e;
86
+ }
87
+ render(e) {
88
+ return e.aDir && e.bDir ? this.renderTwoWayExit(e) : this.renderOneWayExit(e);
89
+ }
90
+ renderTwoWayExit(e) {
91
+ const t = this.mapReader.getRoom(e.a), s = this.mapReader.getRoom(e.b);
92
+ if (!t || !s || !e.aDir || !e.bDir)
93
+ return;
94
+ const r = new u.Group(), i = [];
95
+ if (i.push(...Object.values(p(t.x, t.y, e.aDir, c.roomSize / 2))), i.push(...Object.values(p(s.x, s.y, e.bDir, c.roomSize / 2))), t.doors[w[e.aDir]] || s.doors[w[e.bDir]]) {
96
+ const n = this.renderDoor(i, t.doors[w[e.aDir]] ?? s.doors[w[e.bDir]]);
97
+ r.add(n);
98
+ }
99
+ const o = new u.Line({
100
+ points: i,
101
+ stroke: c.lineColor,
102
+ strokeWidth: 0.025
103
+ });
104
+ return r.add(o), r;
105
+ }
106
+ renderOneWayExit(e) {
107
+ const t = e.aDir ? this.mapReader.getRoom(e.a) : this.mapReader.getRoom(e.b), s = e.aDir ? this.mapReader.getRoom(e.b) : this.mapReader.getRoom(e.a), r = e.aDir ? e.aDir : e.bDir;
108
+ if (!t || !s)
109
+ return;
110
+ if (t.area != s.area && r)
111
+ return this.renderAreaExit(t, r);
112
+ let i = { x: s.x, y: s.y };
113
+ (s.area !== t.area || s.z !== t.z) && (i = p(t.x, t.y, r, c.roomSize / 2));
114
+ const o = p(t.x, t.y, r, 0.3), n = o.x - (o.x - i.x) / 2, d = o.y - (o.y - i.y) / 2, l = new u.Group(), h = [];
115
+ h.push(...Object.values(p(t.x, t.y, r, c.roomSize / 2))), h.push(i.x, i.y);
116
+ const f = new u.Line({
117
+ points: h,
118
+ stroke: c.lineColor,
119
+ strokeWidth: 0.025,
120
+ dashEnabled: !0,
121
+ dash: [0.1, 0.05]
122
+ });
123
+ l.add(f);
124
+ const g = new u.Arrow({
125
+ points: [h[0], h[1], n, d],
126
+ pointerLength: 0.5,
127
+ pointerWidth: 0.35,
128
+ strokeWidth: 0.035,
129
+ stroke: c.lineColor,
130
+ fill: "#FF0000",
131
+ dashEnabled: !0,
132
+ dash: [0.1, 0.05]
133
+ });
134
+ return l.add(g), l;
135
+ }
136
+ renderAreaExit(e, t) {
137
+ const s = p(e.x, e.y, t, c.roomSize / 2), r = p(e.x, e.y, t, c.roomSize * 1.5);
138
+ return new u.Arrow({
139
+ points: [s.x, s.y, r.x, r.y],
140
+ pointerLength: 0.3,
141
+ pointerWidth: 0.3,
142
+ strokeWidth: 0.035,
143
+ stroke: this.mapReader.getColorValue(e.env),
144
+ fill: this.mapReader.getColorValue(e.env)
145
+ });
146
+ }
147
+ renderSpecialExits(e) {
148
+ return Object.entries(e.customLines).map(([t, s]) => {
149
+ const r = [e.x, e.y];
150
+ s.points.reduce((d, l) => (d.push(l.x, -l.y), d), r);
151
+ const i = s.attributes.arrow ? u.Arrow : u.Line, o = new i({
152
+ points: r,
153
+ strokeWidth: 0.025,
154
+ stroke: `rgb(${s.attributes.color.r}, ${s.attributes.color.g}, ${s.attributes.color.b})`,
155
+ fill: `rgb(${s.attributes.color.r}, ${s.attributes.color.g} , ${s.attributes.color.b})`,
156
+ pointerLength: 0.3,
157
+ pointerWidth: 0.2
158
+ });
159
+ let n = s.attributes.style;
160
+ return n === "dot line" ? (o.dash([0.05, 0.05]), o.dashOffset(0.1)) : n === "dash line" ? o.dash([0.4, 0.2]) : n === "solid line" || n !== void 0 && console.log("Brak opisu stylu: " + n), o;
161
+ });
162
+ }
163
+ renderStubs(e) {
164
+ return e.stubs.map((t) => {
165
+ const s = F[t], r = p(e.x, e.y, s, c.roomSize / 2), i = p(e.x, e.y, s, c.roomSize / 2 + 0.5), o = [r.x, r.y, i.x, i.y];
166
+ return new u.Line({
167
+ points: o,
168
+ stroke: c.lineColor,
169
+ strokeWidth: 0.025
170
+ });
171
+ });
172
+ }
173
+ renderInnerExits(e) {
174
+ return Z.map((t) => {
175
+ if (e.exits[t]) {
176
+ const s = new u.Group(), r = new u.RegularPolygon({
177
+ x: e.x,
178
+ y: e.y,
179
+ sides: 3,
180
+ fill: this.mapReader.getSymbolColor(e.env, 0.6),
181
+ stroke: this.mapReader.getSymbolColor(e.env),
182
+ strokeWidth: 0.025,
183
+ radius: c.roomSize / 5,
184
+ scaleX: 1.4,
185
+ scaleY: 0.8
186
+ });
187
+ s.add(r);
188
+ let i = e.doors[t];
189
+ if (i !== void 0)
190
+ switch (i) {
191
+ case 1:
192
+ r.stroke(y.OPEN_DOOR);
193
+ break;
194
+ case 2:
195
+ r.stroke(y.CLOSED_DOOR);
196
+ break;
197
+ default:
198
+ r.stroke(y.LOCKED_DOOR);
199
+ }
200
+ switch (t) {
201
+ case "up":
202
+ r.position(p(e.x, e.y, "south", c.roomSize / 4));
203
+ break;
204
+ case "down":
205
+ r.rotation(180), r.position(p(e.x, e.y, "north", c.roomSize / 4));
206
+ break;
207
+ case "in":
208
+ const o = r.clone();
209
+ o.rotation(-90), o.position(p(e.x, e.y, "east", c.roomSize / 4)), s.add(o), r.rotation(90), r.position(p(e.x, e.y, "west", c.roomSize / 4));
210
+ break;
211
+ case "out":
212
+ const n = r.clone();
213
+ n.rotation(90), n.position(p(e.x, e.y, "east", c.roomSize / 4)), s.add(n), r.rotation(-90), r.position(p(e.x, e.y, "west", c.roomSize / 4));
214
+ break;
215
+ }
216
+ return s;
217
+ }
218
+ }).filter((t) => t !== void 0);
219
+ }
220
+ renderDoor(e, t) {
221
+ const s = {
222
+ x: e[0] + (e[2] - e[0]) / 2,
223
+ y: e[1] + (e[3] - e[1]) / 2
224
+ };
225
+ return new u.Rect({
226
+ x: s.x - c.roomSize / 4,
227
+ y: s.y - c.roomSize / 4,
228
+ width: c.roomSize / 2,
229
+ height: c.roomSize / 2,
230
+ stroke: G(t),
231
+ strokeWidth: 0.025
232
+ });
233
+ }
234
+ }
235
+ class B {
236
+ constructor(e, t) {
237
+ this.paths = [], this.mapReader = e, this.overlayLayer = t;
238
+ }
239
+ renderPath(e, t, s) {
240
+ if (t === void 0 || s === void 0)
241
+ return;
242
+ const r = e.map((h) => this.mapReader.getRoom(h)).filter((h) => h !== void 0), i = [];
243
+ let o = null;
244
+ const n = () => {
245
+ o && (o.length < 4 && i.pop(), o = null);
246
+ }, d = () => (o || (o = [], i.push(o)), o);
247
+ r.forEach((h, f) => {
248
+ if (!this.isRoomVisible(h, t, s))
249
+ return;
250
+ const g = f > 0 ? r[f - 1] : void 0, m = f < r.length - 1 ? r[f + 1] : void 0;
251
+ if (this.isRoomVisible(g, t, s))
252
+ d();
253
+ else {
254
+ n();
255
+ const R = d();
256
+ if (g) {
257
+ const b = this.getDirectionTowards(h, g);
258
+ if (b) {
259
+ const D = p(h.x, h.y, b, c.roomSize);
260
+ R.push(D.x, D.y);
261
+ }
262
+ }
263
+ }
264
+ if (o == null || o.push(h.x, h.y), !this.isRoomVisible(m, t, s) && m) {
265
+ const R = this.getDirectionTowards(h, m);
266
+ if (R) {
267
+ const b = p(h.x, h.y, R, c.roomSize);
268
+ o == null || o.push(b.x, b.y);
269
+ }
270
+ n();
271
+ }
272
+ }), n();
273
+ const l = i.filter((h) => h.length >= 4).map((h) => new u.Line({
274
+ points: h,
275
+ stroke: "green",
276
+ strokeWidth: 0.1
277
+ }));
278
+ return l.forEach((h) => {
279
+ this.overlayLayer.add(h), this.paths.push(h);
280
+ }), l[0];
281
+ }
282
+ clearPaths() {
283
+ this.paths.forEach((e) => {
284
+ e.destroy();
285
+ }), this.paths = [];
286
+ }
287
+ isRoomVisible(e, t, s) {
288
+ return e ? e.area === t && e.z === s : !1;
289
+ }
290
+ getDirectionTowards(e, t) {
291
+ for (const s of L)
292
+ if (e.exits[s] === t.id)
293
+ return s;
294
+ for (const s of L)
295
+ if (t.exits[s] === e.id)
296
+ return j[s];
297
+ }
298
+ }
299
+ const T = 0.6, O = 1, x = 75, q = "rgb(225, 255, 225)", E = class E {
300
+ };
301
+ E.roomSize = T, E.lineColor = q;
302
+ let c = E;
303
+ class ue {
304
+ constructor(e, t) {
305
+ this.highlights = /* @__PURE__ */ new Map(), this.currentZoom = 1, this.stage = new u.Stage({
306
+ container: e,
307
+ width: e.clientWidth,
308
+ height: e.clientHeight,
309
+ draggable: !0
310
+ }), e.addEventListener("resize", () => {
311
+ this.stage.width(e.clientWidth), this.stage.height(e.clientHeight), this.stage.batchDraw();
312
+ }), this.linkLayer = new u.Layer({
313
+ listening: !1
314
+ }), this.stage.add(this.linkLayer), this.roomLayer = new u.Layer(), this.stage.add(this.roomLayer), this.overlayLayer = new u.Layer({
315
+ listening: !1
316
+ }), this.stage.add(this.overlayLayer), this.positionLayer = new u.Layer({
317
+ listening: !1
318
+ }), this.stage.add(this.positionLayer), this.mapReader = t, this.exitRenderer = new H(t), this.pathRenderer = new B(t, this.overlayLayer), this.initScaling(1.1);
319
+ }
320
+ initScaling(e) {
321
+ this.stage.on("wheel", (t) => {
322
+ t.evt.preventDefault();
323
+ const s = this.stage.scaleX(), r = this.stage.getPointerPosition();
324
+ if (!r)
325
+ return;
326
+ const i = {
327
+ x: (r.x - this.stage.x()) / s,
328
+ y: (r.y - this.stage.y()) / s
329
+ };
330
+ let o = t.evt.deltaY > 0 ? -1 : 1;
331
+ t.evt.ctrlKey && (o = -o);
332
+ const n = o > 0 ? this.currentZoom * e : this.currentZoom / e, d = n * x;
333
+ this.setZoom(n);
334
+ const l = {
335
+ x: r.x - i.x * d,
336
+ y: r.y - i.y * d
337
+ };
338
+ this.stage.position(l);
339
+ });
340
+ }
341
+ drawArea(e, t) {
342
+ const s = this.mapReader.getArea(e);
343
+ if (!s)
344
+ return;
345
+ const r = s.getPlane(t);
346
+ if (!r)
347
+ return;
348
+ this.currentArea = e, this.currentZIndex = t, this.currentAreaVersion = s.getVersion(), this.roomLayer.destroyChildren(), this.linkLayer.destroyChildren();
349
+ const { minX: i, maxX: o, minY: n, maxY: d } = r.getBounds();
350
+ this.stage.offset({ x: i - O, y: n - O }), this.stage.scale({ x: x * this.currentZoom, y: x * this.currentZoom }), this.renderLabels(r.getLabels()), this.renderRooms(r.getRooms() ?? []), this.renderExits(s.getLinkExits(t)), this.refreshHighlights(), this.stage.batchDraw();
351
+ }
352
+ setZoom(e) {
353
+ this.currentZoom = e, this.stage.scale({ x: x * e, y: x * e });
354
+ }
355
+ getZoom() {
356
+ return this.currentZoom;
357
+ }
358
+ getCurrentArea() {
359
+ return this.currentArea ? this.mapReader.getArea(this.currentArea) : void 0;
360
+ }
361
+ setPosition(e) {
362
+ const t = this.mapReader.getRoom(e);
363
+ if (!t) return;
364
+ const s = this.mapReader.getArea(t.area), r = s == null ? void 0 : s.getVersion();
365
+ let i = this.currentArea !== t.area || this.currentZIndex !== t.z;
366
+ (this.currentArea !== t.area || this.currentZIndex !== t.z || r !== void 0 && this.currentAreaVersion !== r) && this.drawArea(t.area, t.z), this.positionRender || (this.positionRender = new u.Circle({
367
+ x: t.x,
368
+ y: t.y,
369
+ radius: T * 0.85,
370
+ stroke: "rgb(0, 229, 178)",
371
+ strokeWidth: 0.1,
372
+ dash: [0.05, 0.05],
373
+ dashEnabled: !0
374
+ }), this.positionLayer.add(this.positionRender)), this.centerOnRoom(t, i);
375
+ }
376
+ renderPath(e) {
377
+ return this.pathRenderer.renderPath(e, this.currentArea, this.currentZIndex);
378
+ }
379
+ clearPaths() {
380
+ this.pathRenderer.clearPaths();
381
+ }
382
+ renderHighlight(e, t) {
383
+ const s = this.mapReader.getRoom(e);
384
+ if (!s)
385
+ return;
386
+ const r = this.highlights.get(e);
387
+ r != null && r.shape && (r.shape.destroy(), delete r.shape);
388
+ const i = { color: t, area: s.area, z: s.z };
389
+ if (this.highlights.set(e, i), s.area === this.currentArea && s.z === this.currentZIndex) {
390
+ const o = this.createHighlightShape(s, t);
391
+ return this.overlayLayer.add(o), i.shape = o, this.overlayLayer.batchDraw(), o;
392
+ }
393
+ return i.shape;
394
+ }
395
+ clearHighlights() {
396
+ this.highlights.forEach(({ shape: e }) => e == null ? void 0 : e.destroy()), this.highlights.clear(), this.overlayLayer.batchDraw();
397
+ }
398
+ refreshHighlights() {
399
+ this.highlights.forEach((e, t) => {
400
+ var i;
401
+ if ((i = e.shape) == null || i.destroy(), delete e.shape, e.area !== this.currentArea || e.z !== this.currentZIndex)
402
+ return;
403
+ const s = this.mapReader.getRoom(t);
404
+ if (!s)
405
+ return;
406
+ const r = this.createHighlightShape(s, e.color);
407
+ this.overlayLayer.add(r), e.shape = r;
408
+ }), this.overlayLayer.batchDraw();
409
+ }
410
+ createHighlightShape(e, t) {
411
+ return new u.Circle({
412
+ x: e.x,
413
+ y: e.y,
414
+ radius: c.roomSize * 0.9,
415
+ stroke: t,
416
+ strokeWidth: 0.15,
417
+ dash: [0.1, 0.05],
418
+ dashEnabled: !0,
419
+ listening: !1
420
+ });
421
+ }
422
+ centerOnRoom(e, t = !1) {
423
+ var l;
424
+ const s = { x: e.x, y: e.y };
425
+ (l = this.positionRender) == null || l.position(e);
426
+ const i = this.stage.getAbsoluteTransform().point(s), o = {
427
+ x: this.stage.width() / 2,
428
+ y: this.stage.height() / 2
429
+ }, n = o.x - i.x, d = o.y - i.y;
430
+ this.currentTransition && (this.currentTransition.pause(), this.currentTransition.destroy(), delete this.currentTransition), t ? this.stage.position({
431
+ x: this.stage.x() + n,
432
+ y: this.stage.y() + d
433
+ }) : (this.currentTransition = new u.Tween({
434
+ node: this.stage,
435
+ x: this.stage.x() + n,
436
+ y: this.stage.y() + d,
437
+ duration: 0.2,
438
+ easing: u.Easings.EaseInOut
439
+ }), this.currentTransition.play());
440
+ }
441
+ renderRooms(e) {
442
+ e.forEach((t) => {
443
+ const s = new u.Group({
444
+ x: t.x - c.roomSize / 2,
445
+ y: t.y - c.roomSize / 2
446
+ }), r = new u.Rect({
447
+ x: 0,
448
+ y: 0,
449
+ width: c.roomSize,
450
+ height: c.roomSize,
451
+ fill: this.mapReader.getColorValue(t.env),
452
+ strokeWidth: 0.025,
453
+ stroke: c.lineColor
454
+ });
455
+ s.on("mouseenter", () => {
456
+ this.stage.container().style.cursor = "pointer";
457
+ }), s.on("mouseleave", () => {
458
+ this.stage.container().style.cursor = "auto";
459
+ }), s.add(r), this.renderSymbol(t, s), this.roomLayer.add(s), this.exitRenderer.renderSpecialExits(t).forEach((i) => {
460
+ this.linkLayer.add(i);
461
+ }), this.exitRenderer.renderStubs(t).forEach((i) => {
462
+ this.linkLayer.add(i);
463
+ }), this.exitRenderer.renderInnerExits(t).forEach((i) => {
464
+ this.roomLayer.add(i);
465
+ });
466
+ });
467
+ }
468
+ renderSymbol(e, t) {
469
+ if (e.roomChar !== void 0) {
470
+ const s = new u.Text({
471
+ x: 0,
472
+ y: 0,
473
+ text: e.roomChar,
474
+ fontSize: 0.45,
475
+ fontStyle: "bold",
476
+ fill: this.mapReader.getSymbolColor(e.env),
477
+ align: "center",
478
+ verticalAlign: "middle",
479
+ width: c.roomSize,
480
+ height: c.roomSize
481
+ });
482
+ t.add(s);
483
+ }
484
+ }
485
+ renderExits(e) {
486
+ e.forEach((t) => {
487
+ const s = this.exitRenderer.render(t);
488
+ s && this.linkLayer.add(s);
489
+ });
490
+ }
491
+ renderLabels(e) {
492
+ e.forEach((t) => {
493
+ if (!t.pixMap)
494
+ return;
495
+ const s = new Image();
496
+ s.src = `data:image/png;base64,${t.pixMap}`;
497
+ const r = new u.Image({
498
+ x: t.X,
499
+ y: -t.Y,
500
+ width: t.Width,
501
+ height: t.Height,
502
+ image: s
503
+ });
504
+ this.linkLayer.add(r);
505
+ });
506
+ }
507
+ }
508
+ class A {
509
+ constructor(e, t) {
510
+ this.rooms = [], this.labels = [], this.rooms = e, this.bounds = this.createBounds(), this.labels = t;
511
+ }
512
+ getRooms() {
513
+ return this.rooms;
514
+ }
515
+ getLabels() {
516
+ return this.labels;
517
+ }
518
+ getBounds() {
519
+ return this.bounds;
520
+ }
521
+ createBounds() {
522
+ return this.rooms.reduce(
523
+ (e, t) => ({
524
+ minX: Math.min(e.minX, t.x),
525
+ maxX: Math.max(e.maxX, t.x),
526
+ minY: Math.min(e.minY, t.y),
527
+ maxY: Math.max(e.maxY, t.y)
528
+ }),
529
+ {
530
+ minX: Number.POSITIVE_INFINITY,
531
+ maxX: Number.NEGATIVE_INFINITY,
532
+ minY: Number.POSITIVE_INFINITY,
533
+ maxY: Number.NEGATIVE_INFINITY
534
+ }
535
+ );
536
+ }
537
+ }
538
+ class S {
539
+ constructor(e) {
540
+ this.planes = {}, this.exits = /* @__PURE__ */ new Map(), this.version = 0, this.area = e, this.planes = this.createPlanes(), this.createExits();
541
+ }
542
+ getAreaName() {
543
+ return this.area.areaName;
544
+ }
545
+ getAreaId() {
546
+ return parseInt(this.area.areaId);
547
+ }
548
+ getVersion() {
549
+ return this.version;
550
+ }
551
+ markDirty() {
552
+ this.version++;
553
+ }
554
+ getPlane(e) {
555
+ return this.planes[e];
556
+ }
557
+ getPlanes() {
558
+ return Object.values(this.planes);
559
+ }
560
+ getRooms() {
561
+ return this.area.rooms;
562
+ }
563
+ getLinkExits(e) {
564
+ return Array.from(this.exits.values()).filter((t) => t.zIndex.includes(e));
565
+ }
566
+ createPlanes() {
567
+ const e = this.area.rooms.reduce((t, s) => (t[s.z] || (t[s.z] = []), t[s.z].push(s), t), {});
568
+ return Object.entries(e).reduce(
569
+ (t, [s, r]) => (t[+s] = new A(r, this.area.labels.filter((i) => i.Z === +s)), t),
570
+ {}
571
+ );
572
+ }
573
+ createExits() {
574
+ this.area.rooms.forEach((e) => {
575
+ Object.entries(e.exits).filter(([t, s]) => _.indexOf(t) > -1 && !e.customLines.hasOwnProperty(w[t])).forEach(([t, s]) => this.createHalfExit(e.id, s, e.z, t));
576
+ });
577
+ }
578
+ createHalfExit(e, t, s, r) {
579
+ if (e === t)
580
+ return;
581
+ const i = Math.min(e, t), o = Math.max(e, t), n = `${i}-${o}`;
582
+ let d = this.exits.get(n);
583
+ d || (d = { a: i, b: o, zIndex: [s] }), i == e ? d.aDir = r : d.bDir = r, d.zIndex.push(s), this.exits.set(n, d);
584
+ }
585
+ }
586
+ class I extends A {
587
+ constructor(e, t) {
588
+ super(e.getRooms(), e.getLabels()), this.basePlane = e, this.visitedRooms = t;
589
+ }
590
+ getRooms() {
591
+ return this.basePlane.getRooms().filter((e) => this.visitedRooms.has(e.id));
592
+ }
593
+ getLabels() {
594
+ return this.basePlane.getLabels();
595
+ }
596
+ getBounds() {
597
+ const e = this.getRooms();
598
+ return e.length ? e.reduce(
599
+ (t, s) => ({
600
+ minX: Math.min(t.minX, s.x),
601
+ maxX: Math.max(t.maxX, s.x),
602
+ minY: Math.min(t.minY, s.y),
603
+ maxY: Math.max(t.maxY, s.y)
604
+ }),
605
+ {
606
+ minX: Number.POSITIVE_INFINITY,
607
+ maxX: Number.NEGATIVE_INFINITY,
608
+ minY: Number.POSITIVE_INFINITY,
609
+ maxY: Number.NEGATIVE_INFINITY
610
+ }
611
+ ) : this.basePlane.getBounds();
612
+ }
613
+ }
614
+ class P extends S {
615
+ constructor(e, t) {
616
+ super(e), this.planeCache = /* @__PURE__ */ new WeakMap(), this.visitedRooms = t instanceof Set ? t : new Set(t ?? []), this.areaRoomIds = new Set(e.rooms.map((s) => s.id));
617
+ }
618
+ getPlane(e) {
619
+ const t = super.getPlane(e);
620
+ if (!t)
621
+ return t;
622
+ let s = this.planeCache.get(t);
623
+ return s || (s = new I(t, this.visitedRooms), this.planeCache.set(t, s)), s;
624
+ }
625
+ getPlanes() {
626
+ return super.getPlanes().map((e) => {
627
+ let t = this.planeCache.get(e);
628
+ return t || (t = new I(e, this.visitedRooms), this.planeCache.set(e, t)), t;
629
+ });
630
+ }
631
+ getLinkExits(e) {
632
+ return super.getLinkExits(e).filter((t) => this.visitedRooms.has(t.a) || this.visitedRooms.has(t.b));
633
+ }
634
+ getVisitedRoomCount() {
635
+ return super.getRooms().reduce((e, t) => e + (this.visitedRooms.has(t.id) ? 1 : 0), 0);
636
+ }
637
+ getTotalRoomCount() {
638
+ return this.areaRoomIds.size;
639
+ }
640
+ hasVisitedRoom(e) {
641
+ return this.areaRoomIds.has(e) && this.visitedRooms.has(e);
642
+ }
643
+ getVisitedRoomIds() {
644
+ return super.getRooms().filter((e) => this.visitedRooms.has(e.id)).map((e) => e.id);
645
+ }
646
+ addVisitedRoom(e) {
647
+ const t = this.visitedRooms.has(e);
648
+ this.visitedRooms.add(e);
649
+ const s = !t && this.areaRoomIds.has(e);
650
+ return s && this.markDirty(), s;
651
+ }
652
+ addVisitedRooms(e) {
653
+ let t = 0;
654
+ for (const s of e) {
655
+ const r = this.visitedRooms.has(s);
656
+ this.visitedRooms.add(s), !r && this.areaRoomIds.has(s) && t++;
657
+ }
658
+ return t > 0 && this.markDirty(), t;
659
+ }
660
+ }
661
+ const C = {
662
+ rgbValue: "rgb(114, 1, 0)",
663
+ symbolColor: [225, 225, 225]
664
+ };
665
+ function z(a) {
666
+ const e = a[0] / 255, t = a[1] / 255, s = a[2] / 255, r = Math.max(e, t, s), i = Math.min(e, t, s);
667
+ return (r + i) / 2;
668
+ }
669
+ class de {
670
+ constructor(e, t) {
671
+ this.rooms = {}, this.areas = {}, this.areaSources = {}, this.explorationEnabled = !1, this.colors = {}, e.forEach((s) => {
672
+ s.rooms.forEach((i) => {
673
+ i.y = -i.y, this.rooms[i.id] = i;
674
+ });
675
+ const r = parseInt(s.areaId);
676
+ this.areas[r] = new S(s), this.areaSources[r] = s;
677
+ }), this.colors = t.reduce((s, r) => ({
678
+ ...s,
679
+ [r.envId]: {
680
+ rgb: r.colors,
681
+ rgbValue: `rgb(${r.colors.join(",")}`,
682
+ symbolColor: z(r.colors) > 0.41 ? [25, 25, 25] : [225, 255, 255],
683
+ symbolColorValue: z(r.colors) > 0.41 ? "rgb(25,25,25)" : "rgb(225,255,255)"
684
+ }
685
+ }), {});
686
+ }
687
+ getArea(e) {
688
+ return this.areas[e];
689
+ }
690
+ getExplorationArea(e) {
691
+ const t = this.areas[e];
692
+ if (t instanceof P)
693
+ return t;
694
+ }
695
+ getAreas() {
696
+ return Object.values(this.areas);
697
+ }
698
+ getRooms() {
699
+ return Object.values(this.rooms);
700
+ }
701
+ getRoom(e) {
702
+ return this.rooms[e];
703
+ }
704
+ decorateWithExploration(e) {
705
+ return this.visitedRooms = e instanceof Set ? e : new Set(e ?? []), Object.entries(this.areaSources).forEach(([t, s]) => {
706
+ const r = parseInt(t, 10);
707
+ this.areas[r] = new P(s, this.visitedRooms);
708
+ }), this.explorationEnabled = !0, this.visitedRooms;
709
+ }
710
+ getVisitedRooms() {
711
+ return this.visitedRooms;
712
+ }
713
+ clearExplorationDecoration() {
714
+ Object.entries(this.areaSources).forEach(([e, t]) => {
715
+ const s = parseInt(e, 10);
716
+ this.areas[s] = new S(t);
717
+ }), this.explorationEnabled = !1;
718
+ }
719
+ isExplorationEnabled() {
720
+ return this.explorationEnabled;
721
+ }
722
+ getColorValue(e) {
723
+ var t;
724
+ return ((t = this.colors[e]) == null ? void 0 : t.rgbValue) ?? C.rgbValue;
725
+ }
726
+ getSymbolColor(e, t) {
727
+ var o;
728
+ const s = ((o = this.colors[e]) == null ? void 0 : o.symbolColor) ?? C.symbolColor, r = Math.min(Math.max(t ?? 1, 0), 1), i = s.join(",");
729
+ return r != 1 ? `rgba(${i}, ${r})` : `rgba(${i})`;
730
+ }
731
+ }
732
+ function K(a) {
733
+ return a && a.__esModule && Object.prototype.hasOwnProperty.call(a, "default") ? a.default : a;
734
+ }
735
+ class Q {
736
+ /**
737
+ * Creates a new empty priority queue
738
+ */
739
+ constructor() {
740
+ this.keys = /* @__PURE__ */ new Set(), this.queue = [];
741
+ }
742
+ /**
743
+ * Sort the queue to have the least expensive node to visit on top
744
+ *
745
+ * @private
746
+ */
747
+ sort() {
748
+ this.queue.sort((e, t) => e.priority - t.priority);
749
+ }
750
+ /**
751
+ * Sets a priority for a key in the queue.
752
+ * Inserts it in the queue if it does not already exists.
753
+ *
754
+ * @param {any} key Key to update or insert
755
+ * @param {number} value Priority of the key
756
+ * @return {number} Size of the queue
757
+ */
758
+ set(e, t) {
759
+ const s = Number(t);
760
+ if (isNaN(s)) throw new TypeError('"priority" must be a number');
761
+ return this.keys.has(e) ? this.queue.map((r) => (r.key === e && Object.assign(r, { priority: s }), r)) : (this.keys.add(e), this.queue.push({ key: e, priority: s })), this.sort(), this.queue.length;
762
+ }
763
+ /**
764
+ * The next method is used to dequeue a key:
765
+ * It removes the first element from the queue and returns it
766
+ *
767
+ * @return {object} First priority queue entry
768
+ */
769
+ next() {
770
+ const e = this.queue.shift();
771
+ return this.keys.delete(e.key), e;
772
+ }
773
+ /**
774
+ * @return {boolean} `true` when the queue is empty
775
+ */
776
+ isEmpty() {
777
+ return this.queue.length === 0;
778
+ }
779
+ /**
780
+ * Check if the queue has a key in it
781
+ *
782
+ * @param {any} key Key to lookup
783
+ * @return {boolean}
784
+ */
785
+ has(e) {
786
+ return this.keys.has(e);
787
+ }
788
+ /**
789
+ * Get the element in the queue with the specified key
790
+ *
791
+ * @param {any} key Key to lookup
792
+ * @return {object}
793
+ */
794
+ get(e) {
795
+ return this.queue.find((t) => t.key === e);
796
+ }
797
+ }
798
+ var J = Q;
799
+ function Y(a, e) {
800
+ const t = /* @__PURE__ */ new Map();
801
+ for (const [s, r] of a)
802
+ s !== e && r instanceof Map ? t.set(s, Y(r, e)) : s !== e && t.set(s, r);
803
+ return t;
804
+ }
805
+ var U = Y;
806
+ function ee(a) {
807
+ const e = Number(a);
808
+ return !(isNaN(e) || e <= 0);
809
+ }
810
+ function $(a) {
811
+ const e = /* @__PURE__ */ new Map();
812
+ return Object.keys(a).forEach((s) => {
813
+ const r = a[s];
814
+ if (r !== null && typeof r == "object" && !Array.isArray(r))
815
+ return e.set(s, $(r));
816
+ if (!ee(r))
817
+ throw new Error(
818
+ `Could not add node at key "${s}", make sure it's a valid node`,
819
+ r
820
+ );
821
+ return e.set(s, Number(r));
822
+ }), e;
823
+ }
824
+ var te = $;
825
+ function W(a) {
826
+ if (!(a instanceof Map))
827
+ throw new Error(`Invalid graph: Expected Map instead found ${typeof a}`);
828
+ a.forEach((e, t) => {
829
+ if (typeof e == "object" && e instanceof Map) {
830
+ W(e);
831
+ return;
832
+ }
833
+ if (typeof e != "number" || e <= 0)
834
+ throw new Error(
835
+ `Values must be numbers greater than 0. Found value ${e} at ${t}`
836
+ );
837
+ });
838
+ }
839
+ var se = W;
840
+ const re = J, ie = U, V = te, N = se;
841
+ class oe {
842
+ /**
843
+ * Creates a new Graph, optionally initializing it a nodes graph representation.
844
+ *
845
+ * A graph representation is an object that has as keys the name of the point and as values
846
+ * the points reacheable from that node, with the cost to get there:
847
+ *
848
+ * {
849
+ * node (Number|String): {
850
+ * neighbor (Number|String): cost (Number),
851
+ * ...,
852
+ * },
853
+ * }
854
+ *
855
+ * In alternative to an object, you can pass a `Map` of `Map`. This will
856
+ * allow you to specify numbers as keys.
857
+ *
858
+ * @param {Objec|Map} [graph] - Initial graph definition
859
+ * @example
860
+ *
861
+ * const route = new Graph();
862
+ *
863
+ * // Pre-populated graph
864
+ * const route = new Graph({
865
+ * A: { B: 1 },
866
+ * B: { A: 1, C: 2, D: 4 },
867
+ * });
868
+ *
869
+ * // Passing a Map
870
+ * const g = new Map()
871
+ *
872
+ * const a = new Map()
873
+ * a.set('B', 1)
874
+ *
875
+ * const b = new Map()
876
+ * b.set('A', 1)
877
+ * b.set('C', 2)
878
+ * b.set('D', 4)
879
+ *
880
+ * g.set('A', a)
881
+ * g.set('B', b)
882
+ *
883
+ * const route = new Graph(g)
884
+ */
885
+ constructor(e) {
886
+ e instanceof Map ? (N(e), this.graph = e) : e ? this.graph = V(e) : this.graph = /* @__PURE__ */ new Map();
887
+ }
888
+ /**
889
+ * Adds a node to the graph
890
+ *
891
+ * @param {string} name - Name of the node
892
+ * @param {Object|Map} neighbors - Neighbouring nodes and cost to reach them
893
+ * @return {this}
894
+ * @example
895
+ *
896
+ * const route = new Graph();
897
+ *
898
+ * route.addNode('A', { B: 1 });
899
+ *
900
+ * // It's possible to chain the calls
901
+ * route
902
+ * .addNode('B', { A: 1 })
903
+ * .addNode('C', { A: 3 });
904
+ *
905
+ * // The neighbors can be expressed in a Map
906
+ * const d = new Map()
907
+ * d.set('A', 2)
908
+ * d.set('B', 8)
909
+ *
910
+ * route.addNode('D', d)
911
+ */
912
+ addNode(e, t) {
913
+ let s;
914
+ return t instanceof Map ? (N(t), s = t) : s = V(t), this.graph.set(e, s), this;
915
+ }
916
+ /**
917
+ * @deprecated since version 2.0, use `Graph#addNode` instead
918
+ */
919
+ addVertex(e, t) {
920
+ return this.addNode(e, t);
921
+ }
922
+ /**
923
+ * Removes a node and all of its references from the graph
924
+ *
925
+ * @param {string|number} key - Key of the node to remove from the graph
926
+ * @return {this}
927
+ * @example
928
+ *
929
+ * const route = new Graph({
930
+ * A: { B: 1, C: 5 },
931
+ * B: { A: 3 },
932
+ * C: { B: 2, A: 2 },
933
+ * });
934
+ *
935
+ * route.removeNode('C');
936
+ * // The graph now is:
937
+ * // { A: { B: 1 }, B: { A: 3 } }
938
+ */
939
+ removeNode(e) {
940
+ return this.graph = ie(this.graph, e), this;
941
+ }
942
+ /**
943
+ * Compute the shortest path between the specified nodes
944
+ *
945
+ * @param {string} start - Starting node
946
+ * @param {string} goal - Node we want to reach
947
+ * @param {object} [options] - Options
948
+ *
949
+ * @param {boolean} [options.trim] - Exclude the origin and destination nodes from the result
950
+ * @param {boolean} [options.reverse] - Return the path in reversed order
951
+ * @param {boolean} [options.cost] - Also return the cost of the path when set to true
952
+ *
953
+ * @return {array|object} Computed path between the nodes.
954
+ *
955
+ * When `option.cost` is set to true, the returned value will be an object with shape:
956
+ * - `path` *(Array)*: Computed path between the nodes
957
+ * - `cost` *(Number)*: Cost of the path
958
+ *
959
+ * @example
960
+ *
961
+ * const route = new Graph()
962
+ *
963
+ * route.addNode('A', { B: 1 })
964
+ * route.addNode('B', { A: 1, C: 2, D: 4 })
965
+ * route.addNode('C', { B: 2, D: 1 })
966
+ * route.addNode('D', { C: 1, B: 4 })
967
+ *
968
+ * route.path('A', 'D') // => ['A', 'B', 'C', 'D']
969
+ *
970
+ * // trimmed
971
+ * route.path('A', 'D', { trim: true }) // => [B', 'C']
972
+ *
973
+ * // reversed
974
+ * route.path('A', 'D', { reverse: true }) // => ['D', 'C', 'B', 'A']
975
+ *
976
+ * // include the cost
977
+ * route.path('A', 'D', { cost: true })
978
+ * // => {
979
+ * // path: [ 'A', 'B', 'C', 'D' ],
980
+ * // cost: 4
981
+ * // }
982
+ */
983
+ path(e, t, s = {}) {
984
+ if (!this.graph.size)
985
+ return s.cost ? { path: null, cost: 0 } : null;
986
+ const r = /* @__PURE__ */ new Set(), i = new re(), o = /* @__PURE__ */ new Map();
987
+ let n = [], d = 0, l = [];
988
+ if (s.avoid && (l = [].concat(s.avoid)), l.includes(e))
989
+ throw new Error(`Starting node (${e}) cannot be avoided`);
990
+ if (l.includes(t))
991
+ throw new Error(`Ending node (${t}) cannot be avoided`);
992
+ for (i.set(e, 0); !i.isEmpty(); ) {
993
+ const h = i.next();
994
+ if (h.key === t) {
995
+ d = h.priority;
996
+ let g = h.key;
997
+ for (; o.has(g); )
998
+ n.push(g), g = o.get(g);
999
+ break;
1000
+ }
1001
+ r.add(h.key), (this.graph.get(h.key) || /* @__PURE__ */ new Map()).forEach((g, m) => {
1002
+ if (r.has(m) || l.includes(m)) return null;
1003
+ if (!i.has(m))
1004
+ return o.set(m, h.key), i.set(m, h.priority + g);
1005
+ const k = i.get(m).priority, v = h.priority + g;
1006
+ return v < k ? (o.set(m, h.key), i.set(m, v)) : null;
1007
+ });
1008
+ }
1009
+ return n.length ? (s.trim ? n.shift() : n = n.concat([e]), s.reverse || (n = n.reverse()), s.cost ? {
1010
+ path: n,
1011
+ cost: d
1012
+ } : n) : s.cost ? { path: null, cost: 0 } : null;
1013
+ }
1014
+ /**
1015
+ * @deprecated since version 2.0, use `Graph#path` instead
1016
+ */
1017
+ shortestPath(...e) {
1018
+ return this.path(...e);
1019
+ }
1020
+ }
1021
+ var ne = oe;
1022
+ const ae = /* @__PURE__ */ K(ne), he = {
1023
+ 1: "north",
1024
+ 2: "northeast",
1025
+ 3: "northwest",
1026
+ 4: "east",
1027
+ 5: "west",
1028
+ 6: "south",
1029
+ 7: "southeast",
1030
+ 8: "southwest",
1031
+ 9: "up",
1032
+ 10: "down",
1033
+ 11: "in",
1034
+ 12: "out"
1035
+ };
1036
+ class le {
1037
+ constructor(e) {
1038
+ this.cache = /* @__PURE__ */ new Map(), this.mapReader = e, this.graph = this.buildGraph();
1039
+ }
1040
+ buildGraph() {
1041
+ const e = {};
1042
+ return this.mapReader.getRooms().forEach((t) => {
1043
+ const s = {}, r = new Set(
1044
+ (t.exitLocks ?? []).map((o) => he[o]).filter((o) => !!o)
1045
+ ), i = new Set(t.mSpecialExitLocks ?? []);
1046
+ Object.entries(t.exits ?? {}).forEach(([o, n]) => {
1047
+ r.has(o) || this.mapReader.getRoom(n) && (s[n.toString()] = 1);
1048
+ }), Object.values(t.specialExits ?? {}).forEach((o) => {
1049
+ i.has(o) || this.mapReader.getRoom(o) && (s[o.toString()] = 1);
1050
+ }), e[t.id.toString()] = s;
1051
+ }), new ae(e);
1052
+ }
1053
+ findPath(e, t) {
1054
+ const s = `${e}->${t}`;
1055
+ if (this.cache.has(s))
1056
+ return this.cache.get(s);
1057
+ if (e === t) {
1058
+ const n = this.mapReader.getRoom(e) ? [e] : null;
1059
+ return this.cache.set(s, n), n;
1060
+ }
1061
+ if (!this.mapReader.getRoom(e) || !this.mapReader.getRoom(t))
1062
+ return this.cache.set(s, null), null;
1063
+ const r = this.graph.path(e.toString(), t.toString()), i = Array.isArray(r) ? r : r == null ? void 0 : r.path, o = i ? i.map((n) => Number(n)) : null;
1064
+ return this.cache.set(s, o), o;
1065
+ }
1066
+ }
1067
+ export {
1068
+ P as ExplorationArea,
1069
+ de as MapReader,
1070
+ le as PathFinder,
1071
+ ue as Renderer,
1072
+ c as Settings
1073
+ };
1074
+ //# sourceMappingURL=index.mjs.map