@woosh/meep-engine 2.50.1 → 2.50.3

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 (78) hide show
  1. package/README.md +42 -0
  2. package/editor/Editor.js +5 -1
  3. package/editor/SelectionVisualizer.js +9 -3
  4. package/editor/tools/paint/TerrainTexturePaintTool.js +6 -1
  5. package/editor/view/EditorView.js +5 -1
  6. package/editor/view/ecs/EntityList.js +48 -37
  7. package/editor/view/makeEntityDecorators.js +125 -0
  8. package/package.json +7 -3
  9. package/samples/generation/README.md +6 -0
  10. package/{src/generation/example → samples/generation}/SampleGenerator0.js +60 -46
  11. package/{src/generation/example → samples/generation}/filters/SampleGroundMoistureFilter.js +14 -12
  12. package/samples/generation/filters/SampleNoise20_0.js +3 -0
  13. package/{src/generation/example → samples/generation}/generators/interactive/mir_generator_place_buff_objects.js +29 -23
  14. package/{src/generation/example → samples/generation}/generators/mir_generator_place_bases.js +33 -25
  15. package/{src/generation/example → samples/generation}/generators/mir_generator_place_road_decorators.js +16 -14
  16. package/samples/generation/generators/mir_generator_place_starting_point.js +60 -0
  17. package/{src/generation/example → samples/generation}/grid/configureMirGrid.js +2 -2
  18. package/{src/generation/example → samples/generation}/main.js +29 -28
  19. package/{src/generation/example → samples/generation}/rules/matcher_not_play_area.js +1 -1
  20. package/samples/generation/rules/matcher_play_area.js +5 -0
  21. package/{src/generation/example → samples/generation}/rules/matcher_tag_not_traversable.js +1 -1
  22. package/samples/generation/rules/matcher_tag_occupied.js +5 -0
  23. package/samples/generation/rules/matcher_tag_traversable.js +5 -0
  24. package/{src/generation/example → samples/generation}/rules/matcher_tag_traversable_unoccupied.js +1 -1
  25. package/{src/generation/example → samples/generation}/rules/matcher_tag_unoccupied.js +1 -1
  26. package/{src/generation/example → samples/generation}/rules/mir_matcher_attack_corridor.js +3 -3
  27. package/{src/generation/example → samples/generation}/themes/SampleTheme0.js +57 -47
  28. package/{src/generation/example → samples/generation}/themes/SampleTheme1.js +4 -4
  29. package/{src/generation/example → samples/generation}/themes/SampleTheme2.js +4 -4
  30. package/src/core/cache/Cache.d.ts +4 -0
  31. package/src/core/cache/Cache.js +31 -15
  32. package/src/core/cache/Cache.spec.js +33 -0
  33. package/src/core/cache/FrequencySketch.js +26 -23
  34. package/src/core/cache/FrequencySketch.spec.js +5 -0
  35. package/src/core/cache/LoadingCache.d.ts +2 -0
  36. package/src/core/cache/LoadingCache.js +16 -7
  37. package/src/core/cache/LoadingCache.spec.js +24 -0
  38. package/src/core/collection/HashMap.d.ts +2 -0
  39. package/src/core/collection/HashMap.spec.js +51 -2
  40. package/src/core/collection/list/List.d.ts +13 -1
  41. package/src/core/collection/list/List.js +702 -684
  42. package/src/core/collection/list/List.spec.js +93 -0
  43. package/src/core/collection/map/AsyncLoadingCache.js +1 -0
  44. package/src/core/fsm/simple/SimpleStateMachine.js +23 -22
  45. package/src/core/function/extractFunctionBody.spec.js +15 -0
  46. package/src/core/geom/2d/convex-hull/convex_hull_monotone_2d.js +69 -33
  47. package/src/core/geom/2d/convex-hull/convex_hull_monotone_2d.spec.js +33 -0
  48. package/src/core/geom/2d/convex-hull/orientation3.js +55 -10
  49. package/src/core/process/matcher/Matchers.js +1 -1
  50. package/src/engine/asset/loaders/image/png/PNG.spec.js +5 -0
  51. package/src/engine/asset/loaders/image/png/PNGReader.spec.js +5 -0
  52. package/src/engine/asset/loaders/image/png/crc.spec.js +15 -0
  53. package/src/engine/ecs/EntityBlueprint.js +4 -0
  54. package/src/engine/ecs/EntityBuilder.js +48 -49
  55. package/src/engine/ecs/EntityBuilderFlags.js +2 -2
  56. package/src/engine/ecs/guid/GUID.js +1 -0
  57. package/src/engine/ecs/{Blueprint.js → storage/json/Blueprint.js} +1 -1
  58. package/src/engine/ecs/{EntityFactory.js → storage/json/EntityFactory.js} +1 -1
  59. package/src/engine/ecs/storage/{JSONDeSerializer.js → json/JSONDeSerializer.js} +4 -4
  60. package/src/engine/ecs/storage/json/README.md +5 -0
  61. package/src/engine/graphics/ecs/mesh-v2/ShadedGeometry.spec.js +5 -0
  62. package/src/engine/intelligence/behavior/Behavior.d.ts +5 -0
  63. package/src/engine/intelligence/behavior/Behavior.js +19 -0
  64. package/src/engine/intelligence/behavior/SelectorBehavior.js +4 -2
  65. package/src/engine/intelligence/behavior/composite/ParallelBehavior.js +2 -0
  66. package/src/engine/intelligence/behavior/composite/SequenceBehavior.js +3 -1
  67. package/src/engine/intelligence/behavior/decorator/AbstractDecoratorBehavior.js +2 -3
  68. package/src/engine/intelligence/behavior/decorator/RepeatBehavior.js +2 -2
  69. package/src/generation/grid/generation/discrete/GridTaskConnectRooms.js +1 -1
  70. package/src/generation/grid/generation/road/GridTaskGenerateRoads.js +2 -2
  71. package/src/view/common/VirtualListView.js +2 -0
  72. package/src/generation/example/filters/SampleNoise20_0.js +0 -3
  73. package/src/generation/example/generators/mir_generator_place_starting_point.js +0 -52
  74. package/src/generation/example/rules/matcher_play_area.js +0 -5
  75. package/src/generation/example/rules/matcher_tag_occupied.js +0 -5
  76. package/src/generation/example/rules/matcher_tag_traversable.js +0 -5
  77. /package/{src/generation/example → samples/generation}/grid/MirGridLayers.js +0 -0
  78. /package/src/engine/ecs/storage/{JSONSerializer.js → json/JSONSerializer.js} +0 -0
@@ -142,7 +142,7 @@ export class Cache {
142
142
  }
143
143
 
144
144
  /**
145
- *
145
+ * Number of elements stored in cache
146
146
  * @returns {number}
147
147
  */
148
148
  size() {
@@ -150,7 +150,7 @@ export class Cache {
150
150
  }
151
151
 
152
152
  /**
153
- *
153
+ * Will cause evictions if current weight is smaller than what we're setting
154
154
  * @param {number} value
155
155
  */
156
156
  setMaxWeight(value) {
@@ -163,6 +163,11 @@ export class Cache {
163
163
  this.evictUntilWeight(this.maxWeight);
164
164
  }
165
165
 
166
+ /**
167
+ * Forces weight to be recomputed for all elements stored in the cache
168
+ * Useful when values are mutated without re-insertion.
169
+ * In general - prefer to treat values as immutable
170
+ */
166
171
  recomputeWeight() {
167
172
  let result = 0;
168
173
 
@@ -175,18 +180,7 @@ export class Cache {
175
180
  }
176
181
 
177
182
  /**
178
- *
179
- * @param {function(Value):number} weigher
180
- */
181
- setValueWeigher(weigher) {
182
- this.valueWeigher = weigher;
183
- //recompute weight
184
- this.recomputeWeight();
185
- this.evictUntilWeight(this.maxWeight);
186
- }
187
-
188
- /**
189
- *
183
+ * @private
190
184
  * @param {Key} key
191
185
  * @param {Value} value
192
186
  * @returns {number}
@@ -223,7 +217,14 @@ export class Cache {
223
217
  }
224
218
  }
225
219
 
220
+ /**
221
+ * Drop data until weight reduces lower or equal to requested weight
222
+ * @param {number} targetWeight
223
+ */
226
224
  evictUntilWeight(targetWeight) {
225
+ assert.isNumber(targetWeight, 'targetWeight');
226
+ assert.notNaN(targetWeight, 'targetWeight');
227
+
227
228
  const target = Math.max(targetWeight, 0);
228
229
 
229
230
  while (this.weight > target) {
@@ -466,7 +467,22 @@ export class Cache {
466
467
  }
467
468
 
468
469
  /**
469
- * Shortcut for "map" compliance
470
+ * Shortcut for "Map" class spec compliance
471
+ * @readonly
470
472
  * @type {Cache.put}
471
473
  */
472
474
  Cache.prototype.set = Cache.prototype.put;
475
+
476
+ /**
477
+ * Shortcut for "Map" class spec compliance
478
+ * @readonly
479
+ * @type {Cache.remove}
480
+ */
481
+ Cache.prototype.delete = Cache.prototype.remove;
482
+
483
+ /**
484
+ * Shortcut for "Map" class spec compliance
485
+ * @readonly
486
+ * @type {Cache.contains}
487
+ */
488
+ Cache.prototype.has = Cache.prototype.contains;
@@ -1,5 +1,6 @@
1
1
  import { jest } from "@jest/globals";
2
2
  import { Cache } from "./Cache.js";
3
+ import { returnOne } from "../function/Functions.js";
3
4
 
4
5
  test("constructor doesn't throw", () => {
5
6
  new Cache({});
@@ -162,3 +163,35 @@ test("calling 'evictOne' on empty cache should return false", () => {
162
163
 
163
164
  expect(cache.evictOne()).toBe(false);
164
165
  });
166
+
167
+ test("recomputeWeight", () => {
168
+ const cache = new Cache({
169
+ valueWeigher: () => 3,
170
+ keyWeigher: returnOne
171
+ });
172
+
173
+ cache.set(1, 1);
174
+
175
+ expect(cache.weight).toBe(4);
176
+
177
+ cache.recomputeWeight();
178
+
179
+ expect(cache.weight).toBe(4);
180
+ });
181
+
182
+ test("silentRemove should not notify", () => {
183
+
184
+ const cache = new Cache();
185
+
186
+ cache.set("x", 1);
187
+
188
+ const mock = jest.fn();
189
+
190
+ cache.onRemoved.add(mock);
191
+
192
+ cache.silentRemove("x");
193
+
194
+ expect(cache.contains('x')).toBe(false);
195
+
196
+ expect(mock).not.toHaveBeenCalled();
197
+ });
@@ -4,7 +4,12 @@ import { ceilPowerOfTwo } from "../binary/operations/ceilPowerOfTwo.js";
4
4
  import { min2 } from "../math/min2.js";
5
5
 
6
6
  const SEED = [ // A mixture of seeds from FNV-1a, CityHash, and Murmur3
7
- 0x97cb3127, 0xbe98f273, 0x2f90404f, 0x84222325];
7
+ 0x97cb3127,
8
+ 0xbe98f273,
9
+ 0x2f90404f,
10
+ 0x84222325
11
+ ];
12
+
8
13
  const RESET_MASK = 0x77777777;
9
14
  const ONE_MASK = 0x11111111;
10
15
 
@@ -49,28 +54,26 @@ const MAX_INT_32 = 2147483647;
49
54
  * @template T
50
55
  */
51
56
  export class FrequencySketch {
52
- constructor() {
53
- /**
54
- *
55
- * @type {number}
56
- */
57
- this.sampleSize = 0;
58
- /**
59
- *
60
- * @type {number}
61
- */
62
- this.tableMask = 0;
63
- /**
64
- *
65
- * @type {Uint32Array|null}
66
- */
67
- this.table = null;
68
- /**
69
- *
70
- * @type {number}
71
- */
72
- this.size = 0;
73
- }
57
+ /**
58
+ *
59
+ * @type {number}
60
+ */
61
+ sampleSize = 0;
62
+ /**
63
+ *
64
+ * @type {number}
65
+ */
66
+ tableMask = 0;
67
+ /**
68
+ *
69
+ * @type {Uint32Array|null}
70
+ */
71
+ table = null;
72
+ /**
73
+ *
74
+ * @type {number}
75
+ */
76
+ size = 0;
74
77
 
75
78
  /**
76
79
  * Initializes and increases the capacity of this <tt>FrequencySketch</tt> instance, if necessary,
@@ -0,0 +1,5 @@
1
+ import { FrequencySketch } from "./FrequencySketch.js";
2
+
3
+ test("constructor does not throw", () => {
4
+ expect(() => new FrequencySketch()).not.toThrow();
5
+ });
@@ -18,4 +18,6 @@ export declare class LoadingCache<K, V> {
18
18
  clear(): void
19
19
 
20
20
  get(key: K): Promise<V>
21
+
22
+ put(key: K, value: V): void
21
23
  }
@@ -51,13 +51,13 @@ export class LoadingCache {
51
51
 
52
52
  /**
53
53
  * @see {@link Cache} for more details on what each parameter means
54
- * @param maxWeight
55
- * @param keyWeigher
56
- * @param valueWeigher
57
- * @param keyHashFunction
58
- * @param keyEqualityFunction
59
- * @param capacity
60
- * @param {number} [timeToLive] in seconds
54
+ * @param [maxWeight]
55
+ * @param [keyWeigher]
56
+ * @param [valueWeigher]
57
+ * @param [keyHashFunction]
58
+ * @param [keyEqualityFunction]
59
+ * @param [capacity]
60
+ * @param {number} [timeToLive] in seconds, default is 10 seconds
61
61
  * @param load
62
62
  * @param {boolean} [retryFailed]
63
63
  */
@@ -141,6 +141,15 @@ export class LoadingCache {
141
141
  return record.value;
142
142
  }
143
143
 
144
+ /**
145
+ * Directly insert value into the cache
146
+ * @param {K} key
147
+ * @param {V} value
148
+ */
149
+ put(key, value) {
150
+ this.#internal.put(key, new Record(Promise.resolve(value), current_time_in_seconds()));
151
+ }
152
+
144
153
  /**
145
154
  *
146
155
  * @param {K} key
@@ -45,3 +45,27 @@ test("timeout reload reuse", async () => {
45
45
 
46
46
  expect(await cache.get(1)).toEqual(3);
47
47
  });
48
+
49
+ test("insert element directly", async () => {
50
+
51
+ const cache = new LoadingCache({
52
+ load: async () => 3
53
+ });
54
+
55
+ cache.put("x", 1);
56
+
57
+ expect(await cache.get("x")).toEqual(1);
58
+ });
59
+
60
+ test("clear", async () => {
61
+
62
+ const cache = new LoadingCache({
63
+ load: async () => 3
64
+ });
65
+
66
+ cache.put("x", 1);
67
+
68
+ cache.clear();
69
+
70
+ expect(await cache.get("x")).toEqual(3);
71
+ });
@@ -21,6 +21,8 @@ export class HashMap<K, V> implements Iterable<[V, K]> {
21
21
 
22
22
  getOrCompute(key: K, compute: (k: K) => V, thisArg?: any): V
23
23
 
24
+ getOrSet(key: K, default_value: V): V
25
+
24
26
  has(key: K): boolean
25
27
 
26
28
  delete(key: K): boolean
@@ -83,6 +83,23 @@ test("getOrCompute", () => {
83
83
  expect(map.getOrCompute("y", compute)).toBe(3);
84
84
  });
85
85
 
86
+ test("getOrSet", () => {
87
+
88
+ const map = new HashMap({
89
+ keyHashFunction: returnOne,
90
+ keyEqualityFunction: strictEquals
91
+ });
92
+
93
+ map.getOrSet(3, "hello");
94
+
95
+ expect(map.get(3)).toBe("hello");
96
+
97
+ map.getOrSet(3, "kitty");
98
+
99
+ expect(map.get(3)).toBe("hello");
100
+
101
+ });
102
+
86
103
  test("retrieval works as intended after hash map grows", () => {
87
104
  const m = new HashMap({
88
105
  keyHashFunction: passThrough,
@@ -155,7 +172,12 @@ test("key iterator", () => {
155
172
 
156
173
  map.set(7, "hello");
157
174
 
158
- expect(map.keys().next().value).toBe(7);
175
+ const iterator = map.keys();
176
+ expect(iterator.next().value).toBe(7);
177
+ expect(iterator.next()).toEqual({
178
+ done: true,
179
+ value: undefined
180
+ });
159
181
  });
160
182
 
161
183
  test("value iterator", () => {
@@ -166,7 +188,34 @@ test("value iterator", () => {
166
188
 
167
189
  map.set(7, "hello");
168
190
 
169
- expect(map.values().next().value).toBe("hello");
191
+ const iterator = map.values();
192
+ expect(iterator.next().value).toBe("hello");
193
+ expect(iterator.next()).toEqual({
194
+ done: true,
195
+ value: undefined
196
+ });
197
+ });
198
+
199
+ test("forEach", () => {
200
+ const map = new HashMap({
201
+ keyHashFunction: returnOne,
202
+ keyEqualityFunction: strictEquals
203
+ });
204
+
205
+ const mock = jest.fn();
206
+
207
+ map.forEach(mock);
208
+
209
+ expect(mock).not.toHaveBeenCalled();
210
+
211
+ map.set(7, "hello");
212
+ map.set(3, "kitty");
213
+
214
+ map.forEach(mock);
215
+
216
+ expect(mock).toHaveBeenCalledTimes(2);
217
+ expect(mock).toHaveBeenCalledWith("kitty", 3, map);
218
+ expect(mock).toHaveBeenCalledWith("hello", 7, map);
170
219
  });
171
220
 
172
221
 
@@ -12,21 +12,33 @@ export default class List<T> {
12
12
 
13
13
  get(index: number): T
14
14
 
15
- add(el: T): List<T>
15
+ add(el: T): this
16
16
 
17
17
  addAll(el: T[]): void
18
18
 
19
+ insert(index: number, element: T): this
20
+
19
21
  remove(index: number): T
20
22
 
21
23
  removeOneOf(value: T): boolean
22
24
 
25
+ removeIf(condition: (element: T) => boolean, thisArg?: any): void
26
+
27
+ removeOneIf(condition: (element: T) => boolean, thisArg?: any): void
28
+
29
+ reset(): void
30
+
23
31
  asArray(): T[]
24
32
 
25
33
  forEach(f: (element: T, index: number) => any, thisArg?: any): void
26
34
 
35
+ map<X>(f: (element: T, index: number) => X, thisArg?: any): X[]
36
+
27
37
  isEmpty(): boolean
28
38
 
29
39
  indexOf(el: T): number
30
40
 
41
+ find(matcher: (element: T) => boolean): T | undefined
42
+
31
43
  equals(other: List<T>): boolean
32
44
  }