murow 0.0.1

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 (103) hide show
  1. package/README.md +61 -0
  2. package/dist/core/binary-codec/binary-codec.d.ts +159 -0
  3. package/dist/core/binary-codec/binary-codec.js +336 -0
  4. package/dist/core/binary-codec/index.d.ts +1 -0
  5. package/dist/core/binary-codec/index.js +1 -0
  6. package/dist/core/events/event-system.d.ts +71 -0
  7. package/dist/core/events/event-system.js +88 -0
  8. package/dist/core/events/index.d.ts +1 -0
  9. package/dist/core/events/index.js +1 -0
  10. package/dist/core/fixed-ticker/fixed-ticker.d.ts +105 -0
  11. package/dist/core/fixed-ticker/fixed-ticker.js +91 -0
  12. package/dist/core/fixed-ticker/index.d.ts +1 -0
  13. package/dist/core/fixed-ticker/index.js +1 -0
  14. package/dist/core/generate-id/generate-id.d.ts +21 -0
  15. package/dist/core/generate-id/generate-id.js +25 -0
  16. package/dist/core/generate-id/index.d.ts +1 -0
  17. package/dist/core/generate-id/index.js +1 -0
  18. package/dist/core/index.d.ts +8 -0
  19. package/dist/core/index.js +8 -0
  20. package/dist/core/lerp/index.d.ts +1 -0
  21. package/dist/core/lerp/index.js +1 -0
  22. package/dist/core/lerp/lerp.d.ts +40 -0
  23. package/dist/core/lerp/lerp.js +42 -0
  24. package/dist/core/navmesh/index.d.ts +1 -0
  25. package/dist/core/navmesh/index.js +1 -0
  26. package/dist/core/navmesh/navmesh.d.ts +116 -0
  27. package/dist/core/navmesh/navmesh.js +666 -0
  28. package/dist/core/pooled-codec/index.d.ts +1 -0
  29. package/dist/core/pooled-codec/index.js +1 -0
  30. package/dist/core/pooled-codec/pooled-codec.d.ts +140 -0
  31. package/dist/core/pooled-codec/pooled-codec.js +213 -0
  32. package/dist/core/prediction/index.d.ts +1 -0
  33. package/dist/core/prediction/index.js +1 -0
  34. package/dist/core/prediction/prediction.d.ts +64 -0
  35. package/dist/core/prediction/prediction.js +90 -0
  36. package/dist/core.esm.js +1 -0
  37. package/dist/core.js +1 -0
  38. package/dist/index.d.ts +16 -0
  39. package/dist/index.js +18 -0
  40. package/dist/protocol/index.d.ts +43 -0
  41. package/dist/protocol/index.js +43 -0
  42. package/dist/protocol/intent/index.d.ts +39 -0
  43. package/dist/protocol/intent/index.js +38 -0
  44. package/dist/protocol/intent/intent-registry.d.ts +54 -0
  45. package/dist/protocol/intent/intent-registry.js +73 -0
  46. package/dist/protocol/intent/intent.d.ts +12 -0
  47. package/dist/protocol/intent/intent.js +1 -0
  48. package/dist/protocol/snapshot/index.d.ts +44 -0
  49. package/dist/protocol/snapshot/index.js +43 -0
  50. package/dist/protocol/snapshot/snapshot-codec.d.ts +48 -0
  51. package/dist/protocol/snapshot/snapshot-codec.js +56 -0
  52. package/dist/protocol/snapshot/snapshot-registry.d.ts +100 -0
  53. package/dist/protocol/snapshot/snapshot-registry.js +136 -0
  54. package/dist/protocol/snapshot/snapshot.d.ts +19 -0
  55. package/dist/protocol/snapshot/snapshot.js +30 -0
  56. package/package.json +54 -0
  57. package/src/core/binary-codec/README.md +60 -0
  58. package/src/core/binary-codec/binary-codec.test.ts +300 -0
  59. package/src/core/binary-codec/binary-codec.ts +430 -0
  60. package/src/core/binary-codec/index.ts +1 -0
  61. package/src/core/events/README.md +47 -0
  62. package/src/core/events/event-system.test.ts +243 -0
  63. package/src/core/events/event-system.ts +140 -0
  64. package/src/core/events/index.ts +1 -0
  65. package/src/core/fixed-ticker/README.md +77 -0
  66. package/src/core/fixed-ticker/fixed-ticker.test.ts +151 -0
  67. package/src/core/fixed-ticker/fixed-ticker.ts +158 -0
  68. package/src/core/fixed-ticker/index.ts +1 -0
  69. package/src/core/generate-id/README.md +18 -0
  70. package/src/core/generate-id/generate-id.test.ts +79 -0
  71. package/src/core/generate-id/generate-id.ts +37 -0
  72. package/src/core/generate-id/index.ts +1 -0
  73. package/src/core/index.ts +8 -0
  74. package/src/core/lerp/README.md +79 -0
  75. package/src/core/lerp/index.ts +1 -0
  76. package/src/core/lerp/lerp.test.ts +90 -0
  77. package/src/core/lerp/lerp.ts +42 -0
  78. package/src/core/navmesh/README.md +124 -0
  79. package/src/core/navmesh/index.ts +1 -0
  80. package/src/core/navmesh/navmesh.test.ts +344 -0
  81. package/src/core/navmesh/navmesh.ts +850 -0
  82. package/src/core/pooled-codec/README.md +70 -0
  83. package/src/core/pooled-codec/index.ts +1 -0
  84. package/src/core/pooled-codec/pooled-codec.test.ts +349 -0
  85. package/src/core/pooled-codec/pooled-codec.ts +239 -0
  86. package/src/core/prediction/README.md +64 -0
  87. package/src/core/prediction/index.ts +1 -0
  88. package/src/core/prediction/prediction.test.ts +422 -0
  89. package/src/core/prediction/prediction.ts +101 -0
  90. package/src/index.ts +20 -0
  91. package/src/protocol/README.md +310 -0
  92. package/src/protocol/index.ts +44 -0
  93. package/src/protocol/intent/index.ts +40 -0
  94. package/src/protocol/intent/intent-registry.test.ts +237 -0
  95. package/src/protocol/intent/intent-registry.ts +88 -0
  96. package/src/protocol/intent/intent.ts +12 -0
  97. package/src/protocol/snapshot/index.ts +45 -0
  98. package/src/protocol/snapshot/snapshot-codec.test.ts +138 -0
  99. package/src/protocol/snapshot/snapshot-codec.ts +71 -0
  100. package/src/protocol/snapshot/snapshot-registry.test.ts +302 -0
  101. package/src/protocol/snapshot/snapshot-registry.ts +162 -0
  102. package/src/protocol/snapshot/snapshot.test.ts +76 -0
  103. package/src/protocol/snapshot/snapshot.ts +41 -0
@@ -0,0 +1,88 @@
1
+ /**
2
+ * @description
3
+ * A callback-based event handling system designed to simplify
4
+ * event-driven programming.
5
+ */
6
+ export class EventSystem {
7
+ constructor({ events }) {
8
+ this.callbacks = new Map();
9
+ this.events = events;
10
+ for (const name of this.events) {
11
+ this.callbacks.set(name, new Set());
12
+ }
13
+ }
14
+ /**
15
+ * @description
16
+ * Registers a callback for an event.
17
+ *
18
+ * @param name Event name
19
+ * @param callback Callback to run when the event is emitted
20
+ */
21
+ on(name, callback) {
22
+ const event = this.callbacks.get(name);
23
+ if (!event)
24
+ return console.warn(`Event "${name}" does not exist.`);
25
+ event.add(callback);
26
+ }
27
+ /**
28
+ * @description
29
+ * Registers a callback for an event that runs only once.
30
+ *
31
+ * @param name Event name
32
+ * @param callback Callback to run when the event is emitted
33
+ */
34
+ once(name, callback) {
35
+ const wrapper = (props) => {
36
+ callback(props);
37
+ this.off(name, wrapper);
38
+ };
39
+ this.on(name, wrapper);
40
+ }
41
+ /**
42
+ * @description
43
+ * Emits an event, running all registered callbacks.
44
+ *
45
+ * @param name Event name
46
+ * @param data Event data
47
+ */
48
+ emit(name, data) {
49
+ const event = this.callbacks.get(name);
50
+ if (!event)
51
+ return console.warn(`Event "${name}" does not exist.`);
52
+ for (const callback of event) {
53
+ callback(data);
54
+ }
55
+ }
56
+ /**
57
+ * @description
58
+ * Removes a callback from an event.
59
+ *
60
+ * @param name Event name
61
+ * @param callback Callback to remove
62
+ */
63
+ off(name, callback) {
64
+ const event = this.callbacks.get(name);
65
+ if (!event)
66
+ return console.warn(`Event "${name}" does not exist.`);
67
+ event.delete(callback);
68
+ }
69
+ /**
70
+ * @description
71
+ * Removes all callbacks.
72
+ *
73
+ * @param name Optional event name
74
+ */
75
+ clear(name) {
76
+ if (!name) {
77
+ this.callbacks.clear();
78
+ for (const name of this.events) {
79
+ this.callbacks.set(name, new Set());
80
+ }
81
+ return;
82
+ }
83
+ const event = this.callbacks.get(name);
84
+ if (!event)
85
+ return console.warn(`Event "${name}" does not exist.`);
86
+ event.clear();
87
+ }
88
+ }
@@ -0,0 +1 @@
1
+ export * from './event-system';
@@ -0,0 +1 @@
1
+ export * from './event-system';
@@ -0,0 +1,105 @@
1
+ /**
2
+ * @description
3
+ * A utility class for managing fixed-rate update ticks, useful for deterministic behaviour
4
+ * in both client and server.
5
+ *
6
+ * The `FixedTicker` accumulates elapsed time and determines how many fixed-interval "ticks"
7
+ * should be processed based on a specified tick rate. It also limits the maximum number of
8
+ * ticks per frame to prevent runaway update loops when frame times are long.
9
+ *
10
+ *
11
+ * @remarks
12
+ * - The `tick` method should be called once per frame, passing the elapsed time in seconds.
13
+ * - The class ensures that no more than a safe number of ticks are processed per frame.
14
+ */
15
+ export declare class FixedTicker {
16
+ /**
17
+ * @description Accumulator for the time passed since the last tick
18
+ */
19
+ private accumulator;
20
+ /**
21
+ * @description Rate of ticks per second
22
+ */
23
+ rate: number;
24
+ /**
25
+ * @description
26
+ * Interval in milliseconds per tick
27
+ */
28
+ private intervalMs;
29
+ /**
30
+ * @description
31
+ * Maximum amount of ticks to run per frame, to avoid
32
+ * running too many ticks in a single frame.
33
+ */
34
+ private maxTicksPerFrame;
35
+ /**
36
+ * @description
37
+ * Callback to execute on each tick
38
+ */
39
+ private onTick;
40
+ /**
41
+ * @description
42
+ * Optional callback to execute when ticks are skipped due to high delta time.
43
+ * This can be useful for debugging or logging purposes.
44
+ */
45
+ private onTickSkipped?;
46
+ /**
47
+ * @description
48
+ * Internal counter for the number of ticks processed.
49
+ */
50
+ private _tickCount;
51
+ constructor({ rate, onTick }: FixedTickerProps);
52
+ /**
53
+ * @description
54
+ * Returns how many ticks to run.
55
+ *
56
+ * @param deltaTime Delta time in seconds
57
+ * @returns {number} Amount of ticks to run
58
+ */
59
+ private getTicks;
60
+ /**
61
+ * @description
62
+ * Processes the ticks based on the elapsed time.
63
+ *
64
+ * @param deltaTime Delta time in seconds
65
+ */
66
+ tick(deltaTime: number): void;
67
+ /**
68
+ * @description
69
+ * Returns the number of ticks processed since the last reset.
70
+ *
71
+ * @returns {number} Number of ticks processed
72
+ */
73
+ get tickCount(): number;
74
+ /**
75
+ * @description
76
+ * Resets the tick count to zero.
77
+ */
78
+ resetTickCount(): void;
79
+ /**
80
+ * @description
81
+ * Returns the accumulated time in seconds, useful for interpolation.
82
+ *
83
+ * @returns {number} Accumulated time in seconds
84
+ */
85
+ get accumulatedTime(): number;
86
+ }
87
+ interface FixedTickerProps {
88
+ /**
89
+ * @description
90
+ * Rate of ticks per second
91
+ */
92
+ rate: number;
93
+ /**
94
+ * @description
95
+ * Callback to execute on each tick
96
+ */
97
+ onTick: (deltaTime: number, tick?: number) => void;
98
+ /**
99
+ * @description
100
+ * Optional callback to execute when ticks are skipped due to high delta time.
101
+ * This can be useful for debugging or logging purposes.
102
+ */
103
+ onTickSkipped?: (skippedTicks: number) => void;
104
+ }
105
+ export {};
@@ -0,0 +1,91 @@
1
+ /**
2
+ * @description
3
+ * A utility class for managing fixed-rate update ticks, useful for deterministic behaviour
4
+ * in both client and server.
5
+ *
6
+ * The `FixedTicker` accumulates elapsed time and determines how many fixed-interval "ticks"
7
+ * should be processed based on a specified tick rate. It also limits the maximum number of
8
+ * ticks per frame to prevent runaway update loops when frame times are long.
9
+ *
10
+ *
11
+ * @remarks
12
+ * - The `tick` method should be called once per frame, passing the elapsed time in seconds.
13
+ * - The class ensures that no more than a safe number of ticks are processed per frame.
14
+ */
15
+ export class FixedTicker {
16
+ constructor({ rate, onTick }) {
17
+ /**
18
+ * @description Accumulator for the time passed since the last tick
19
+ */
20
+ this.accumulator = 0;
21
+ /**
22
+ * @description
23
+ * Internal counter for the number of ticks processed.
24
+ */
25
+ this._tickCount = 0;
26
+ this.rate = rate;
27
+ this.intervalMs = 1000 / this.rate;
28
+ this.onTick = onTick;
29
+ // Allow up to rate/2 ticks per frame, but at least 1.
30
+ // Prevents runaway loops if delta is too large.
31
+ this.maxTicksPerFrame = Math.max(1, Math.floor(rate / 2));
32
+ }
33
+ /**
34
+ * @description
35
+ * Returns how many ticks to run.
36
+ *
37
+ * @param deltaTime Delta time in seconds
38
+ * @returns {number} Amount of ticks to run
39
+ */
40
+ getTicks(deltaTime) {
41
+ this.accumulator += deltaTime * 1000;
42
+ let ticks = 0;
43
+ while (this.accumulator >= this.intervalMs &&
44
+ ticks < this.maxTicksPerFrame) {
45
+ this.accumulator -= this.intervalMs;
46
+ ticks++;
47
+ }
48
+ const skippedTicks = Math.floor(this.accumulator / this.intervalMs);
49
+ if (skippedTicks > 0 && this.onTickSkipped) {
50
+ this.onTickSkipped(skippedTicks);
51
+ }
52
+ return ticks;
53
+ }
54
+ /**
55
+ * @description
56
+ * Processes the ticks based on the elapsed time.
57
+ *
58
+ * @param deltaTime Delta time in seconds
59
+ */
60
+ tick(deltaTime) {
61
+ const ticks = this.getTicks(deltaTime);
62
+ for (let i = 0; i < ticks; i++) {
63
+ this.onTick(1 / this.rate, this._tickCount++);
64
+ }
65
+ }
66
+ /**
67
+ * @description
68
+ * Returns the number of ticks processed since the last reset.
69
+ *
70
+ * @returns {number} Number of ticks processed
71
+ */
72
+ get tickCount() {
73
+ return this._tickCount;
74
+ }
75
+ /**
76
+ * @description
77
+ * Resets the tick count to zero.
78
+ */
79
+ resetTickCount() {
80
+ this._tickCount = 0;
81
+ }
82
+ /**
83
+ * @description
84
+ * Returns the accumulated time in seconds, useful for interpolation.
85
+ *
86
+ * @returns {number} Accumulated time in seconds
87
+ */
88
+ get accumulatedTime() {
89
+ return this.accumulator / 1000; // Convert to seconds
90
+ }
91
+ }
@@ -0,0 +1 @@
1
+ export * from './fixed-ticker';
@@ -0,0 +1 @@
1
+ export * from './fixed-ticker';
@@ -0,0 +1,21 @@
1
+ interface GenerateIdOptions {
2
+ /** Optional prefix to prepend to the ID */
3
+ prefix?: string;
4
+ /** Total length of the returned ID including prefix (default 16) */
5
+ size?: number;
6
+ }
7
+ /**
8
+ * @description
9
+ * Generates a unique identifier as a hexadecimal string.
10
+ * Can include a prefix and a custom total length.
11
+ *
12
+ * @param options Optional configuration: prefix and total size
13
+ * @returns A unique identifier string
14
+ *
15
+ * @example
16
+ * generateId(); // "f3a2b1c4d5e67890"
17
+ * generateId({ prefix: 'user_' }); // "user_f3a2b1c4d5e67890"
18
+ * generateId({ prefix: 'user_', size: 24 }); // "user_00f3a2b1c4d5e67890"
19
+ */
20
+ export declare function generateId(options?: GenerateIdOptions): string;
21
+ export {};
@@ -0,0 +1,25 @@
1
+ /**
2
+ * @description
3
+ * Generates a unique identifier as a hexadecimal string.
4
+ * Can include a prefix and a custom total length.
5
+ *
6
+ * @param options Optional configuration: prefix and total size
7
+ * @returns A unique identifier string
8
+ *
9
+ * @example
10
+ * generateId(); // "f3a2b1c4d5e67890"
11
+ * generateId({ prefix: 'user_' }); // "user_f3a2b1c4d5e67890"
12
+ * generateId({ prefix: 'user_', size: 24 }); // "user_00f3a2b1c4d5e67890"
13
+ */
14
+ export function generateId(options = {}) {
15
+ const { prefix = "", size = 16 } = options;
16
+ // compute number of hex characters to generate (subtract prefix length)
17
+ const hexLength = Math.max(size - prefix.length, 8); // min 8 hex chars
18
+ // number of 32-bit integers needed to cover the hexLength
19
+ const numInts = Math.ceil(hexLength / 8);
20
+ const arr = crypto.getRandomValues(new Uint32Array(numInts));
21
+ let id = arr.reduce((acc, val) => acc + val.toString(16).padStart(8, "0"), "");
22
+ // truncate/pad to desired length
23
+ id = id.slice(0, hexLength).padStart(hexLength, "0");
24
+ return `${prefix}${id}`;
25
+ }
@@ -0,0 +1 @@
1
+ export * from './generate-id';
@@ -0,0 +1 @@
1
+ export * from './generate-id';
@@ -0,0 +1,8 @@
1
+ export * from './binary-codec';
2
+ export * from './events';
3
+ export * from './fixed-ticker';
4
+ export * from './generate-id';
5
+ export * from './lerp';
6
+ export * from './navmesh';
7
+ export * from './pooled-codec';
8
+ export * from './prediction';
@@ -0,0 +1,8 @@
1
+ export * from './binary-codec';
2
+ export * from './events';
3
+ export * from './fixed-ticker';
4
+ export * from './generate-id';
5
+ export * from './lerp';
6
+ export * from './navmesh';
7
+ export * from './pooled-codec';
8
+ export * from './prediction';
@@ -0,0 +1 @@
1
+ export * from './lerp';
@@ -0,0 +1 @@
1
+ export * from './lerp';
@@ -0,0 +1,40 @@
1
+ /**
2
+ * @description
3
+ * Performs linear interpolation between two values.
4
+ *
5
+ * Linear interpolation (lerp) calculates a value between a start and end point
6
+ * based on a normalized interpolation factor (t). When t = 0, the result equals
7
+ * the start value; when t = 1, the result equals the end value. Values of t
8
+ * between 0 and 1 produce intermediate results.
9
+ *
10
+ * @remarks
11
+ * - This function does not clamp the interpolation factor. Values of t outside
12
+ * the range [0, 1] will extrapolate beyond the start and end values.
13
+ * - For clamped interpolation, combine with a clamp function on the t parameter.
14
+ * - Commonly used for smooth animations, camera movements, and value transitions.
15
+ *
16
+ * @param start - The starting value (when t = 0)
17
+ * @param end - The ending value (when t = 1)
18
+ * @param t - The interpolation factor, typically in the range [0, 1]
19
+ *
20
+ * @returns {number} The interpolated value between start and end
21
+ *
22
+ * @example
23
+ * ```typescript
24
+ * // Basic interpolation
25
+ * lerp(0, 100, 0.5); // Returns 50
26
+ * lerp(0, 100, 0); // Returns 0
27
+ * lerp(0, 100, 1); // Returns 100
28
+ *
29
+ * // Animation example
30
+ * const startPos = 0;
31
+ * const endPos = 100;
32
+ * const progress = 0.75;
33
+ * const currentPos = lerp(startPos, endPos, progress); // Returns 75
34
+ *
35
+ * // Extrapolation (t outside [0, 1])
36
+ * lerp(0, 100, 1.5); // Returns 150
37
+ * lerp(0, 100, -0.5); // Returns -50
38
+ * ```
39
+ */
40
+ export declare function lerp(start: number, end: number, t: number): number;
@@ -0,0 +1,42 @@
1
+ /**
2
+ * @description
3
+ * Performs linear interpolation between two values.
4
+ *
5
+ * Linear interpolation (lerp) calculates a value between a start and end point
6
+ * based on a normalized interpolation factor (t). When t = 0, the result equals
7
+ * the start value; when t = 1, the result equals the end value. Values of t
8
+ * between 0 and 1 produce intermediate results.
9
+ *
10
+ * @remarks
11
+ * - This function does not clamp the interpolation factor. Values of t outside
12
+ * the range [0, 1] will extrapolate beyond the start and end values.
13
+ * - For clamped interpolation, combine with a clamp function on the t parameter.
14
+ * - Commonly used for smooth animations, camera movements, and value transitions.
15
+ *
16
+ * @param start - The starting value (when t = 0)
17
+ * @param end - The ending value (when t = 1)
18
+ * @param t - The interpolation factor, typically in the range [0, 1]
19
+ *
20
+ * @returns {number} The interpolated value between start and end
21
+ *
22
+ * @example
23
+ * ```typescript
24
+ * // Basic interpolation
25
+ * lerp(0, 100, 0.5); // Returns 50
26
+ * lerp(0, 100, 0); // Returns 0
27
+ * lerp(0, 100, 1); // Returns 100
28
+ *
29
+ * // Animation example
30
+ * const startPos = 0;
31
+ * const endPos = 100;
32
+ * const progress = 0.75;
33
+ * const currentPos = lerp(startPos, endPos, progress); // Returns 75
34
+ *
35
+ * // Extrapolation (t outside [0, 1])
36
+ * lerp(0, 100, 1.5); // Returns 150
37
+ * lerp(0, 100, -0.5); // Returns -50
38
+ * ```
39
+ */
40
+ export function lerp(start, end, t) {
41
+ return start + (end - start) * t;
42
+ }
@@ -0,0 +1 @@
1
+ export * from './navmesh';
@@ -0,0 +1 @@
1
+ export * from './navmesh';
@@ -0,0 +1,116 @@
1
+ type ObstacleId = number;
2
+ export type Obstacle = CircleObstacle | RectObstacle | PolygonObstacle;
3
+ export type ObstacleInput = Omit<CircleObstacle, 'id'> | Omit<RectObstacle, 'id'> | Omit<PolygonObstacle, 'id'>;
4
+ interface Vec2 {
5
+ x: number;
6
+ y: number;
7
+ }
8
+ interface BaseObstacle {
9
+ id: ObstacleId;
10
+ type: 'circle' | 'rect' | 'polygon';
11
+ solid?: boolean;
12
+ }
13
+ export interface CircleObstacle extends BaseObstacle {
14
+ type: 'circle';
15
+ pos: Vec2;
16
+ radius: number;
17
+ }
18
+ export interface RectObstacle extends BaseObstacle {
19
+ type: 'rect';
20
+ pos: Vec2;
21
+ size: Vec2;
22
+ rotation?: number;
23
+ }
24
+ /**
25
+ * Polygon obstacle.
26
+ * IMPORTANT: `points` must be defined relative to local origin (0,0).
27
+ * The polygon will be rotated around (0,0) then translated to `pos`.
28
+ * Do NOT define points in world space.
29
+ */
30
+ export interface PolygonObstacle extends BaseObstacle {
31
+ type: 'polygon';
32
+ points: Vec2[];
33
+ pos: Vec2;
34
+ rotation?: number;
35
+ }
36
+ /**
37
+ * Manages obstacles with spatial hashing for fast queries.
38
+ * Version tracking prevents unnecessary rebuilds.
39
+ */
40
+ declare class Obstacles {
41
+ private items;
42
+ private spatial;
43
+ private _cachedItems;
44
+ dirty: boolean;
45
+ version: number;
46
+ add(obstacle: ObstacleInput): ObstacleId;
47
+ move(id: ObstacleId, pos: Vec2): void;
48
+ remove(id: ObstacleId): void;
49
+ /**
50
+ * Fast spatial query using hash grid.
51
+ * O(1) average case instead of O(n) linear scan.
52
+ */
53
+ at(pos: Vec2): Obstacle | undefined;
54
+ get values(): Obstacle[];
55
+ }
56
+ type NavType = 'grid' | 'graph';
57
+ /**
58
+ * Navigation mesh with spatial hashing and smart rebuild.
59
+ *
60
+ * Features:
61
+ * - Spatial hash: O(1) obstacle queries
62
+ * - Version tracking: zero unnecessary rebuilds
63
+ * - Binary heap A*: handles 10k+ node searches
64
+ * - Simple full rebuild: correct and fast enough
65
+ *
66
+ * Performance characteristics:
67
+ * - Obstacle query: O(1) average via spatial hash
68
+ * - Grid rebuild: O(n * area), < 1ms for typical games
69
+ * - Pathfinding: O(b^d * log n) with binary heap
70
+ *
71
+ * Production ready for:
72
+ * - Grid-based games
73
+ * - RTS with < 1000 dynamic obstacles
74
+ * - Turn-based games
75
+ * - Moderate map sizes (< 1M cells)
76
+ */
77
+ export declare class NavMesh {
78
+ private type;
79
+ private grid?;
80
+ private graph?;
81
+ private lastVersion;
82
+ obstacles: Obstacles;
83
+ constructor(type: NavType);
84
+ /**
85
+ * Adds an obstacle and returns its unique ID.
86
+ * For polygons: ensure points are defined relative to (0,0).
87
+ */
88
+ addObstacle(obstacle: ObstacleInput): ObstacleId;
89
+ /**
90
+ * Moves an existing obstacle to a new position.
91
+ */
92
+ moveObstacle(id: ObstacleId, pos: Vec2): void;
93
+ /**
94
+ * Removes an obstacle by ID.
95
+ */
96
+ removeObstacle(id: ObstacleId): void;
97
+ /**
98
+ * Returns all current obstacles.
99
+ */
100
+ getObstacles(): Obstacle[];
101
+ /**
102
+ * Finds a path from start to goal.
103
+ * Automatically rebuilds navigation data if obstacles changed.
104
+ * Returns empty array if no path exists.
105
+ */
106
+ findPath({ from, to }: {
107
+ from: Vec2;
108
+ to: Vec2;
109
+ }): Vec2[];
110
+ /**
111
+ * Smart rebuild - only rebuilds if obstacles changed.
112
+ * Version checking eliminates unnecessary work.
113
+ */
114
+ rebuild(): void;
115
+ }
116
+ export {};