@draug/engine 1.0.20 → 1.0.23

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.js CHANGED
@@ -1,942 +1,52 @@
1
- // src/core/graph/dag.ts
2
- var VisitedState = /* @__PURE__ */ ((VisitedState2) => {
3
- VisitedState2[VisitedState2["Unvisited"] = 0] = "Unvisited";
4
- VisitedState2[VisitedState2["Visiting"] = 1] = "Visiting";
5
- VisitedState2[VisitedState2["Visited"] = 2] = "Visited";
6
- return VisitedState2;
7
- })(VisitedState || {});
8
- var DAGNode = class {
9
- data;
10
- vertices = [];
11
- constructor(data, vertices) {
12
- this.data = data;
13
- if (vertices)
14
- this.vertices = vertices;
15
- }
16
- };
17
- var ErrDAGCycleDetected = class extends Error {
18
- constructor() {
19
- super(`Cycle detected!`);
20
- }
21
- };
22
- function topologicalSort(nodes) {
23
- const visited = /* @__PURE__ */ new Map();
24
- const result = [];
25
- const dfs = (node) => {
26
- const state = visited.get(node) ?? 0 /* Unvisited */;
27
- if (state === 2 /* Visited */) return;
28
- if (state === 1 /* Visiting */) {
29
- throw new ErrDAGCycleDetected();
30
- }
31
- visited.set(node, 1 /* Visiting */);
32
- for (const child of node.vertices) {
33
- dfs(child);
34
- }
35
- visited.set(node, 2 /* Visited */);
36
- result.push(node);
37
- };
38
- for (const node of nodes) {
39
- dfs(node);
40
- }
41
- return result.reverse();
42
- }
43
-
44
- // src/ecs/system.ts
45
- var SystemError = class extends Error {
46
- constructor(target) {
47
- super(`[System Error] (System "${target.name}".`);
48
- }
49
- };
50
- var ErrNotASystem = class extends Error {
51
- constructor(target) {
52
- super(`Provided class "${target.name}" is not a System! Extend your class from SystemBase.`);
53
- }
54
- };
55
- var ErrMissingSystemMetadata = class extends SystemError {
56
- constructor(target) {
57
- super(target);
58
- this.message = `${this.message}: Missing system metadata! Define system class with @System decorator.`;
59
- }
60
- };
61
- var SystemPhase = /* @__PURE__ */ ((SystemPhase2) => {
62
- SystemPhase2[SystemPhase2["PRE"] = 0] = "PRE";
63
- SystemPhase2[SystemPhase2["MAIN"] = 1] = "MAIN";
64
- SystemPhase2[SystemPhase2["POST"] = 2] = "POST";
65
- return SystemPhase2;
66
- })(SystemPhase || {});
67
- var SystemMetadataSymbol = /* @__PURE__ */ Symbol("system");
68
- function System(props) {
69
- return (target) => {
70
- const systemTarget = target;
71
- if ("__proto__" in systemTarget && systemTarget.__proto__ !== SystemBase) {
72
- throw new ErrNotASystem(target);
73
- }
74
- const query = { ...props.query };
75
- const requiredComponents = new Set(props.requiredComponents);
76
- const computeAfter = new Set(props.computeAfter);
77
- const phase = props.phase ?? 1 /* MAIN */;
78
- const name = props.name ?? target.name;
79
- const metadata = { query, requiredComponents, computeAfter, phase, name };
80
- systemTarget[SystemMetadataSymbol] = metadata;
81
- };
82
- }
83
- function getSystemMetadata(system) {
84
- if (hasMetadata(system)) {
85
- return system[SystemMetadataSymbol];
86
- }
87
- throw new ErrMissingSystemMetadata(system);
88
- }
89
- function hasMetadata(ctor) {
90
- return SystemMetadataSymbol in ctor;
91
- }
92
- function isSystem(ctor) {
93
- return hasMetadata(ctor);
94
- }
95
- var SystemBase = class {
96
- };
97
- var SystemsManager = class {
98
- constructor(world, logger) {
99
- this.world = world;
100
- this.logger = logger;
101
- }
102
- world;
103
- logger;
104
- systems_ = /* @__PURE__ */ new Map();
105
- executionOrder_ = [];
106
- requiredComponents_ = /* @__PURE__ */ new Set();
107
- dirty_ = true;
108
- getRequiredComponents() {
109
- return Array.from(this.requiredComponents_);
110
- }
111
- register(sys) {
112
- const ctor = sys.constructor;
113
- if (this.systems_.has(ctor)) throw new Error("Duplicate system");
114
- const { query, requiredComponents } = getSystemMetadata(ctor);
115
- this.systems_.set(ctor, sys);
116
- const q = query;
117
- for (const c of q.include ?? [])
118
- this.requiredComponents_.add(c);
119
- for (const c of q.exclude ?? [])
120
- this.requiredComponents_.add(c);
121
- for (const c of q.anyOf ?? [])
122
- this.requiredComponents_.add(c);
123
- for (const c of requiredComponents)
124
- this.requiredComponents_.add(c);
125
- const meta = getSystemMetadata(ctor);
126
- this.logger.debug(() => `[Systems]: system "${meta.name}" was registered`);
127
- }
128
- build() {
129
- this.buildSystemsArray();
130
- for (const sys of this.systems_.values()) {
131
- sys.onInit?.({ world: this.world, logger: this.logger });
132
- }
133
- this.logger.debug(() => `Built ${this.systems_.size} systems`);
134
- this.dirty_ = false;
135
- }
136
- rebuild() {
137
- this.build();
138
- }
139
- get(ctor) {
140
- const s = this.systems_.get(ctor);
141
- if (!s)
142
- throw new Error("System not registered");
143
- return s;
144
- }
145
- update(time) {
146
- if (this.dirty_)
147
- this.rebuild();
148
- this.world.events.swapAll();
149
- for (const s of this.executionOrder_) {
150
- const { query } = getSystemMetadata(s.constructor);
151
- const entities = this.world.query(query);
152
- s.compute({
153
- world: this.world,
154
- entities,
155
- time,
156
- logger: this.logger
157
- });
158
- }
159
- }
160
- buildSystemsArray() {
161
- const pre = [];
162
- const main = [];
163
- const post = [];
164
- const map = /* @__PURE__ */ new Map();
165
- for (const [ctor, system] of this.systems_.entries()) {
166
- const meta = getSystemMetadata(ctor);
167
- switch (meta.phase) {
168
- case 0 /* PRE */:
169
- pre.push(system);
170
- break;
171
- case 1 /* MAIN */:
172
- post.push(system);
173
- break;
174
- default:
175
- main.push(system);
176
- map.set(ctor, new DAGNode(system));
177
- break;
178
- }
179
- }
180
- for (const ctor of map.keys()) {
181
- const currentNode = map.get(ctor);
182
- const { computeAfter } = getSystemMetadata(ctor);
183
- for (const depCtor of computeAfter ?? []) {
184
- const depNode = map.get(depCtor);
185
- if (!depNode) {
186
- throw new Error(`Dependency ${depCtor.name} not registered`);
187
- }
188
- depNode.vertices.push(currentNode);
189
- }
190
- }
191
- this.executionOrder_ = [
192
- ...pre,
193
- ...topologicalSort(map.values()).map((x) => x.data),
194
- ...post
195
- ];
196
- }
197
- };
198
-
199
- // src/ecs/entity.ts
200
- var UnregisteredComponentStorageError = class extends Error {
201
- constructor(component) {
202
- super(`Cannot get storage for component ${component.name}. Seems like it's not registered in world.`);
203
- }
204
- };
205
- var EntityMaskNotFoundError = class extends Error {
206
- constructor(id2) {
207
- super(`Cannot find bitmask for entity [${id2}]. Seems like it's not registered in the EntityManager.`);
208
- }
209
- };
210
- var EntitiesManager = class {
211
- constructor(logger) {
212
- this.logger = logger;
213
- }
214
- logger;
215
- id_ = 0;
216
- nextId() {
217
- return ++this.id_;
218
- }
219
- create() {
220
- const id2 = this.nextId();
221
- this.logger.debug(() => `[Entities]: Created new entity with ID ${id2}`);
222
- return id2;
223
- }
224
- };
225
- var EntityRef = class {
226
- constructor(world, id2) {
227
- this.world = world;
228
- this.id = id2;
229
- }
230
- world;
231
- id;
232
- with(...components) {
233
- return components.map((c) => {
234
- const s = this.world.components.getStorage(c);
235
- return s.tryGet(this.id);
236
- });
237
- }
238
- };
239
-
240
- // src/ecs/constant.ts
241
- var ECS_DEFAULTS = {
242
- MAX_ENTITY_COUNT: Math.pow(2, 12)
243
- };
244
-
245
- // src/ecs/events-buffer.ts
246
- var EventBuffer = class {
247
- readBuf = [];
248
- writeBuf = [];
249
- write(event) {
250
- this.writeBuf.push(event);
251
- }
252
- /**
253
- * Advances the buffer to the next frame.
254
- *
255
- * Performs a double-buffer flip:
256
- * - Promotes all events written during the previous frame (`writeBuf`)
257
- * to be readable in the current frame (`readBuf`).
258
- * - Reuses the previous `readBuf` as the new `writeBuf` and clears it
259
- * to collect events for the next frame.
260
- *
261
- * After calling this method:
262
- * - `get()` will return a stable snapshot of events produced in the previous frame.
263
- * - `add()` will write into an empty buffer for the current frame.
264
- *
265
- * Guarantees:
266
- * - No events written during the current frame are visible until the next `swap()`.
267
- * - Readers observe a consistent, immutable snapshot within a frame.
268
- *
269
- * Expected to be called exactly once per frame, before system execution.
270
- */
271
- swap() {
272
- const tmp = this.readBuf;
273
- this.readBuf = this.writeBuf;
274
- this.writeBuf = tmp;
275
- this.writeBuf.length = 0;
276
- }
277
- read() {
278
- return this.readBuf;
279
- }
280
- size() {
281
- return this.readBuf.length;
282
- }
283
- };
284
- function createEventKey(description) {
285
- return Symbol(description);
286
- }
287
- var EventBus = class {
288
- storage = /* @__PURE__ */ new Map();
289
- swapAll() {
290
- this.storage.forEach((s) => s.swap());
291
- }
292
- getBuffer(key) {
293
- let buf = this.storage.get(key);
294
- if (!buf) {
295
- buf = new EventBuffer();
296
- this.storage.set(key, buf);
297
- }
298
- return buf;
299
- }
300
- };
301
-
302
- // src/core/memory/pool.ts
303
- var ObjectPool = class {
304
- pool_;
305
- factory_;
306
- cursor_;
307
- constructor(factory, initialSize = 0) {
308
- this.pool_ = new Array(initialSize);
309
- this.factory_ = factory;
310
- this.cursor_ = initialSize - 1;
311
- }
312
- acquire() {
313
- if (this.cursor_ >= 0) {
314
- return this.pool_[this.cursor_--];
315
- }
316
- return this.factory_();
317
- }
318
- release(obj) {
319
- this.pool_[++this.cursor_] = obj;
320
- }
321
- grow() {
322
- const oldSize = this.pool_.length;
323
- const newSize = oldSize * 2;
324
- for (let i = oldSize; i < newSize; i++) this.pool_[i] = this.factory_();
325
- this.cursor_ = newSize - 1;
326
- this.pool_.length = newSize;
327
- }
328
- };
329
-
330
- // src/ecs/components/component-storage.ts
331
- import { Bitmap } from "bitmap-index";
332
- var ComponentStorage = class {
333
- bits_;
334
- data_ = [];
335
- entityIds_ = [];
336
- indexMap_ = /* @__PURE__ */ new Map();
337
- pool_;
338
- id_ = 0;
339
- size_ = 0;
340
- cls;
341
- constructor(cap = ECS_DEFAULTS.MAX_ENTITY_COUNT, factory, cls) {
342
- this.bits_ = new Bitmap(cap);
343
- this.pool_ = new ObjectPool(factory, 0);
344
- this.cls = cls;
345
- }
346
- bitmap() {
347
- return this.bits_;
348
- }
349
- get id() {
350
- return this.id_;
351
- }
352
- _internalSetId(id2) {
353
- return this.id_ = id2;
354
- }
355
- add(id2, initFn) {
356
- if (this.indexMap_.has(id2)) {
357
- throw new Error(`[ComponentStorage "${this.cls.name}"]: Entity ${id2} already has this component`);
358
- }
359
- const obj = this.pool_.acquire();
360
- initFn?.(obj);
361
- const index = this.data_.length;
362
- this.data_.push(obj);
363
- this.entityIds_.push(id2);
364
- this.indexMap_.set(id2, index);
365
- this.bits_.set(id2);
366
- this.size_++;
367
- return obj;
368
- }
369
- remove(id2) {
370
- const index = this.indexMap_.get(id2);
371
- if (index === void 0) return;
372
- this.bits_.remove(id2);
373
- const lastIndex = this.data_.length - 1;
374
- const lastEntityId = this.entityIds_[lastIndex];
375
- const removedObj = this.data_[index];
376
- if (index !== lastIndex) {
377
- this.data_[index] = this.data_[lastIndex];
378
- this.entityIds_[index] = lastEntityId;
379
- this.indexMap_.set(lastEntityId, index);
380
- }
381
- this.data_.pop();
382
- this.entityIds_.pop();
383
- this.indexMap_.delete(id2);
384
- this.pool_.release(removedObj);
385
- this.size_--;
386
- }
387
- get(id2) {
388
- const index = this.indexMap_.get(id2);
389
- return index !== void 0 ? this.data_[index] : null;
390
- }
391
- tryGet(id2) {
392
- const index = this.indexMap_.get(id2);
393
- if (index === void 0)
394
- throw new Error(`[ComponentStorage "${this.cls.name}"]: Requesting non-existing item with ID ${id2}.`);
395
- return this.data_[index];
396
- }
397
- writeComponentsToBuf(ids, out) {
398
- let len = 0;
399
- for (const id2 of ids) {
400
- const index = this.indexMap_.get(id2);
401
- if (index !== void 0) out[len++] = this.data_[index];
402
- }
403
- return len;
404
- }
405
- has(id2) {
406
- return this.bits_.contains(id2);
407
- }
408
- size() {
409
- return this.size_;
410
- }
411
- forEach(cb) {
412
- for (const id2 of this.entityIds_) {
413
- cb(id2);
414
- }
415
- }
416
- };
417
-
418
- // src/ecs/components/utils.ts
419
- var registry = /* @__PURE__ */ new Map();
420
- var id = 0;
421
- var ComponentMetadataSymbol = /* @__PURE__ */ Symbol("component");
422
- function Component(options) {
423
- return (target) => {
424
- const metadata = {
425
- name: options.name,
426
- id: ++id
427
- };
428
- registry.set(target, metadata.id);
429
- target[ComponentMetadataSymbol] = metadata;
430
- };
431
- }
432
- function getComponentId(ctor) {
433
- const id2 = registry.get(ctor);
434
- if (id2 === void 0) {
435
- throw new Error(`Component not registered: ${ctor.name}`);
436
- }
437
- return id2;
438
- }
439
- var ErrNotComponent = class extends Error {
440
- constructor(ctor) {
441
- super(`Class ${ctor.name} is not a Component. Use @Component decorator to define components.`);
442
- }
443
- };
444
- function getComponentMetadata(component) {
445
- if (isComponent(component)) {
446
- return component[ComponentMetadataSymbol];
447
- }
448
- throw new ErrNotComponent(component);
449
- }
450
- function isComponent(ctor) {
451
- return ComponentMetadataSymbol in ctor;
452
- }
453
-
454
- // src/ecs/components/manager.ts
455
- var ComponentAlreadyRegisteredError = class extends Error {
456
- constructor(component) {
457
- super(`Component ${component.name} already registered!`);
458
- }
459
- };
460
- var ComponentsManager = class {
461
- constructor(logger, maxEntityCount = ECS_DEFAULTS.MAX_ENTITY_COUNT) {
462
- this.logger = logger;
463
- this.maxEntityCount = maxEntityCount;
464
- }
465
- logger;
466
- maxEntityCount;
467
- storages_ = /* @__PURE__ */ new Map();
468
- currId_ = 0;
469
- nextId() {
470
- return ++this.currId_;
471
- }
472
- register(component, opts) {
473
- if (this.storages_.has(component))
474
- return this.storages_.get(component);
475
- const store = this.createComponentStore(component, opts);
476
- this.storages_.set(component, store);
477
- const meta = getComponentMetadata(component);
478
- this.logger.debug(() => `[Components]: Registered component "${meta.name}"`);
479
- return store;
480
- }
481
- createComponentStore(component, opts) {
482
- const factory = opts?.factory ?? ((...args) => new component(...args));
483
- const store = new ComponentStorage(this.maxEntityCount, factory, component);
484
- store._internalSetId(this.nextId());
485
- return store;
486
- }
487
- getStorage(component) {
488
- const store = this.storages_.get(component);
489
- if (store === void 0)
490
- throw new UnregisteredComponentStorageError(component);
491
- return store;
492
- }
493
- getComponentId(ctor) {
494
- return getComponentId(ctor);
495
- }
496
- };
497
-
498
- // src/ecs/resources/resources.ts
499
- var ResourceMetadataSymbol = /* @__PURE__ */ Symbol("resource");
500
- function Resource(params) {
501
- return (target) => {
502
- const metadata = {
503
- name: params.name
504
- };
505
- target[ResourceMetadataSymbol] = metadata;
506
- };
507
- }
508
- var ErrNotResource = class extends Error {
509
- constructor(ctor) {
510
- super(`Class ${ctor.name} is not a Resource. Use @Resource decorator to define resources.`);
511
- }
512
- };
513
- function getResourceMetadata(resource) {
514
- if (isResource(resource)) {
515
- return resource[ResourceMetadataSymbol];
516
- }
517
- throw new ErrNotResource(resource);
518
- }
519
- function isResource(ctor) {
520
- return ResourceMetadataSymbol in ctor;
521
- }
522
- var ResourcesManager = class {
523
- constructor(logger) {
524
- this.logger = logger;
525
- }
526
- logger;
527
- items_ = /* @__PURE__ */ new Map();
528
- insert(type, value) {
529
- this.items_.set(type, value);
530
- const metadata = getResourceMetadata(type);
531
- this.logger.debug(() => `[Resources]: Inserted new Resource "${metadata.name}"`);
532
- return value;
533
- }
534
- get(type) {
535
- const value = this.items_.get(type);
536
- const meta = getResourceMetadata(type);
537
- if (!value)
538
- throw new Error(`Resource of class ${meta.name} does not exist!`);
539
- return value;
540
- }
541
- getOrInsert(type, factory) {
542
- let value = this.items_.get(type) ?? null;
543
- if (value === null) {
544
- value = factory();
545
- this.insert(type, value);
546
- }
547
- return value;
548
- }
549
- remove(type) {
550
- const meta = getResourceMetadata(type);
551
- this.logger.debug(() => `[Resources]: Removed resource "${meta.name}"`);
552
- this.items_.delete(type);
553
- }
554
- };
555
-
556
- // src/ecs/command.ts
557
- function entry(component, init = () => {
558
- }) {
559
- return [component, init];
560
- }
561
- var Commands = class {
562
- constructor(world, logger) {
563
- this.world = world;
564
- this.logger = logger;
565
- }
566
- world;
567
- logger;
568
- commandsQueue_ = [];
569
- add(cmd) {
570
- this.commandsQueue_.push(cmd);
571
- }
572
- flush(world) {
573
- for (const cmd of this.commandsQueue_)
574
- cmd(world);
575
- this.commandsQueue_.length = 0;
576
- }
577
- createEntity(...entries) {
578
- const id2 = this.world.entities.create();
579
- const cmd = (world) => {
580
- for (const [cls, initFn] of entries) {
581
- world.addComponent(id2, cls, initFn);
582
- }
583
- };
584
- this.add(cmd);
585
- this.logger.debug(() => {
586
- const components = entries.map((x) => getComponentMetadata(x[0]).name).join(", ");
587
- return `[Commands.createEntity]: Created new entity with ID ${id2}. Linked components: [${components}]`;
588
- });
589
- return id2;
590
- }
591
- };
592
-
593
- // src/ecs/query.ts
594
- import { Bitmap as Bitmap2 } from "bitmap-index";
595
- var QueryManager = class {
596
- constructor(world) {
597
- this.world = world;
598
- }
599
- world;
600
- cache = /* @__PURE__ */ new Map();
601
- get(params) {
602
- const key = this.getKey(params);
603
- let entry2 = this.cache.get(key);
604
- if (!entry2) {
605
- entry2 = {
606
- params,
607
- bitmap: this.compute(params),
608
- dirty: false,
609
- deps: this.collectDeps(params)
610
- };
611
- this.cache.set(key, entry2);
612
- }
613
- if (entry2.dirty) {
614
- entry2.bitmap = this.compute(entry2.params);
615
- entry2.dirty = false;
616
- }
617
- let targetBitmap = entry2.bitmap;
618
- if (params.excludeEntitiesIds?.length) {
619
- targetBitmap = entry2.bitmap.clone();
620
- const excludeBm = new Bitmap2();
621
- for (const id2 of params.excludeEntitiesIds) {
622
- excludeBm.set(id2);
623
- }
624
- targetBitmap.andNot(excludeBm);
625
- }
626
- if (params.filter) {
627
- const result = [];
628
- targetBitmap.range((id2) => {
629
- if (params.filter(id2)) result.push(id2);
630
- });
631
- return result;
632
- }
633
- return this.extractIds(targetBitmap);
634
- }
635
- invalidate(component) {
636
- for (const entry2 of this.cache.values()) {
637
- if (entry2.deps.has(component)) {
638
- entry2.dirty = true;
639
- }
640
- }
641
- }
642
- getKey(q) {
643
- return [
644
- this.ids(q.include),
645
- this.ids(q.exclude),
646
- this.ids(q.anyOf)
647
- ].join("|");
648
- }
649
- ids(arr) {
650
- if (!arr || arr.length === 0) return "";
651
- return arr.map((c) => this.world.components.getComponentId(c)).sort((a, b) => a - b).join(",");
652
- }
653
- collectDeps(q) {
654
- const set = /* @__PURE__ */ new Set();
655
- q.include?.forEach((c) => set.add(c));
656
- q.exclude?.forEach((c) => set.add(c));
657
- q.anyOf?.forEach((c) => set.add(c));
658
- return set;
659
- }
660
- compute(params) {
661
- let result = this.combineBitmaps(params.include, "and");
662
- const any = this.combineBitmaps(params.anyOf, "or");
663
- if (any) {
664
- result = result ? result.and(any) : any;
665
- }
666
- if (!result) {
667
- return new Bitmap2();
668
- }
669
- this.applyExclusions(result, params.exclude);
670
- return result;
671
- }
672
- combineBitmaps(components, op) {
673
- if (!components?.length) return null;
674
- let result = null;
675
- let hasAtLeastOneValid = false;
676
- for (const c of components) {
677
- const bm = this.world.components.getStorage(c)?.bitmap();
678
- if (!bm) {
679
- if (op === "and") {
680
- return new Bitmap2();
681
- }
682
- continue;
683
- }
684
- hasAtLeastOneValid = true;
685
- if (!result) {
686
- result = bm.clone();
687
- } else {
688
- op === "and" ? result.and(bm) : result.or(bm);
689
- }
690
- }
691
- if (op === "or" && !hasAtLeastOneValid) {
692
- return new Bitmap2();
693
- }
694
- return result;
695
- }
696
- applyExclusions(target, excludeComponents) {
697
- if (excludeComponents?.length) {
698
- for (const c of excludeComponents) {
699
- const bm = this.world.components.getStorage(c)?.bitmap();
700
- if (bm) target.andNot(bm);
701
- }
702
- }
703
- }
704
- extractIds(bitmap) {
705
- const result = [];
706
- bitmap.range((id2) => {
707
- result.push(id2);
708
- });
709
- return result;
710
- }
711
- };
712
-
713
- // src/ecs/plugin/plugin.ts
714
- var PluginMetadataSymbol = /* @__PURE__ */ Symbol("plugin");
715
- function Plugin(metadata) {
716
- return (target) => {
717
- if ("__proto__" in target && target.__proto__ !== PluginBase)
718
- throw new ErrNotAPlugin(target);
719
- target[PluginMetadataSymbol] = metadata;
720
- };
721
- }
722
- function getPluginMetadata(plugin) {
723
- if (hasMetadata2(plugin)) {
724
- return plugin[PluginMetadataSymbol];
725
- }
726
- throw new ErrMissingPluginMetadata(plugin);
727
- }
728
- function hasMetadata2(ctor) {
729
- return PluginMetadataSymbol in ctor;
730
- }
731
- function isPlugin(ctor) {
732
- return hasMetadata2(ctor);
733
- }
734
- var PluginBase = class {
735
- onPluginLoad;
736
- onPluginUnload;
737
- onAfterWorldInit;
738
- };
739
- var PluginError = class extends Error {
740
- constructor(pluginId) {
741
- super(`Plugin error! Plugin [${pluginId}]`);
742
- }
743
- };
744
- var ErrNotAPlugin = class extends Error {
745
- constructor(target) {
746
- super(`Provided class ${target.name} is not a Plugin! Every plugin must extends of PluginBase class.`);
747
- }
748
- };
749
- var ErrMissingPluginMetadata = class extends Error {
750
- constructor(plugin) {
751
- super(`Provided class ${plugin.name}: Missing plugin metadata! Define plugin class with @Plugin decorator.`);
752
- }
753
- };
754
- var ErrUnknownPlugin = class extends PluginError {
755
- constructor(pluginId) {
756
- super(pluginId);
757
- this.message = `${super.message}: Plugin not found in manager.`;
758
- }
759
- };
760
- var ErrPluginNotInit = class extends PluginError {
761
- constructor(pluginId) {
762
- super(pluginId);
763
- this.message = `${super.message}: Plugin not initiated yet. You must use PluginsManager.build() before getting instance.`;
764
- }
765
- };
766
- var ErrMissingPluginDependency = class extends PluginError {
767
- constructor(pluginId, missingDepId) {
768
- super(pluginId);
769
- this.message = `${super.message}: Missing required dependency [${missingDepId}]. Install it first.`;
770
- }
771
- };
772
- var ErrDAGCycleDetectedPlugin = class extends Error {
773
- constructor() {
774
- super(`Cycle detected in plugin dependencies!`);
775
- }
776
- };
777
- var PluginsManager = class {
778
- constructor(logger) {
779
- this.logger = logger;
780
- }
781
- logger;
782
- plugins_ = /* @__PURE__ */ new Map();
783
- isInitiated_ = false;
784
- install(plugin, ...constructorProps) {
785
- if (!isPlugin(plugin))
786
- throw new ErrMissingPluginMetadata(plugin);
787
- const metadata = getPluginMetadata(plugin);
788
- if (this.plugins_.has(plugin))
789
- return;
790
- const entry2 = {
791
- ctor: plugin,
792
- ctorParams: constructorProps,
793
- metadata
794
- };
795
- this.plugins_.set(plugin, entry2);
796
- this.logger.debug(() => `[Plugins]: Installed plugin ${metadata.name} (${metadata.version})`);
797
- }
798
- build() {
799
- if (this.plugins_.size === 0) {
800
- return;
801
- }
802
- const nodes = /* @__PURE__ */ new Map();
803
- for (const id2 of this.plugins_.keys()) {
804
- nodes.set(id2, new DAGNode(id2));
805
- }
806
- for (const [plugin, entry2] of this.plugins_) {
807
- const node = nodes.get(plugin);
808
- const depPlugins = entry2.metadata.dependencies?.plugins ?? [];
809
- for (const dep of depPlugins) {
810
- const depNode = nodes.get(dep.plugin);
811
- if (!depNode) {
812
- throw new ErrMissingPluginDependency(plugin, dep.plugin);
813
- }
814
- depNode.vertices.push(node);
815
- }
816
- }
817
- let sortedNodes;
818
- try {
819
- sortedNodes = topologicalSort(nodes.values());
820
- } catch (e) {
821
- if (e instanceof ErrDAGCycleDetected) {
822
- throw new ErrDAGCycleDetectedPlugin();
823
- }
824
- throw e;
825
- }
826
- for (const node of sortedNodes) {
827
- const entry2 = this.plugins_.get(node.data);
828
- const { ctor, ctorParams } = entry2;
829
- const instance = new ctor(...ctorParams);
830
- entry2.instance = instance;
831
- instance.onPluginLoad?.();
832
- }
833
- this.isInitiated_ = true;
834
- this.logger.debug(() => `[Plugins]: Plugins built successfully!`);
835
- }
836
- /**
837
- * @internal
838
- */
839
- __internal__onAfterWorldInit(world) {
840
- for (const p of this.plugins_.values()) {
841
- p.instance?.onAfterWorldInit?.(world);
842
- }
843
- }
844
- getPluginMetadata(plugin) {
845
- const entry2 = this.plugins_.get(plugin);
846
- if (!entry2) throw new ErrUnknownPlugin(plugin);
847
- return entry2.metadata;
848
- }
849
- getPluginInstance(plugin) {
850
- const entry2 = this.plugins_.get(plugin);
851
- if (!entry2) throw new ErrUnknownPlugin(plugin);
852
- if (!entry2.instance) throw new ErrPluginNotInit(plugin);
853
- if (!this.isInitiated_) {
854
- throw new ErrPluginNotInit(plugin);
855
- }
856
- return entry2.instance;
857
- }
858
- resolveId(pluginOrId) {
859
- if (typeof pluginOrId === "string") {
860
- return pluginOrId;
861
- }
862
- if (!isPlugin(pluginOrId)) {
863
- throw new ErrMissingPluginMetadata(pluginOrId);
864
- }
865
- return getPluginMetadata(pluginOrId).id;
866
- }
867
- };
868
-
869
- // src/ecs/world.ts
870
- var World3 = class {
871
- entities;
872
- components;
873
- systems;
874
- events;
875
- resources;
876
- commands;
877
- queries;
878
- plugins;
879
- logger;
880
- entityRefs_ = /* @__PURE__ */ new Map();
881
- updatesCount_ = 0;
882
- get updatesCount() {
883
- return this.updatesCount_;
884
- }
885
- constructor(params) {
886
- this.entities = new EntitiesManager(params.logger);
887
- this.components = new ComponentsManager(params.logger, params.maxEntityCount ?? ECS_DEFAULTS.MAX_ENTITY_COUNT);
888
- this.systems = new SystemsManager(this, params.logger);
889
- this.events = new EventBus();
890
- this.resources = new ResourcesManager(params.logger);
891
- this.commands = new Commands(this, params.logger);
892
- this.queries = new QueryManager(this);
893
- this.plugins = new PluginsManager(params.logger);
894
- this.logger = params.logger;
895
- }
896
- getEntityRef(id2) {
897
- let ref = this.entityRefs_.get(id2);
898
- if (!ref) {
899
- ref = new EntityRef(this, id2);
900
- this.entityRefs_.set(id2, ref);
901
- }
902
- return ref;
903
- }
904
- query(params) {
905
- return this.queries.get(params);
906
- }
907
- removeComponent(entity, component) {
908
- const id2 = typeof entity === "number" ? entity : entity.id;
909
- const storage = this.components.getStorage(component);
910
- storage.remove(id2);
911
- this.queries.invalidate(component);
912
- }
913
- addComponent(entity, component, initFn) {
914
- const storage = this.components.getStorage(component);
915
- let id2;
916
- if (typeof entity === "number") {
917
- id2 = entity;
918
- } else {
919
- id2 = entity.id;
920
- }
921
- const c = storage.add(id2, (o) => {
922
- if (initFn) {
923
- initFn(o);
924
- }
925
- return o;
926
- });
927
- this.queries.invalidate(component);
928
- return c;
929
- }
930
- update(clock) {
931
- this.systems.update(clock.getTime());
932
- this.commands.flush(this);
933
- this.updatesCount_++;
934
- }
935
- build() {
936
- this.plugins.build();
937
- this.logger.debug(() => "World was built successfully");
938
- }
939
- };
1
+ import {
2
+ MovementSystem
3
+ } from "./chunk-BYP45ZLQ.js";
4
+ import {
5
+ Commands,
6
+ Component,
7
+ ComponentAlreadyRegisteredError,
8
+ ComponentStorage,
9
+ ComponentsManager,
10
+ DAGNode,
11
+ ECS_DEFAULTS,
12
+ EntitiesManager,
13
+ EntityMaskNotFoundError,
14
+ EntityRef,
15
+ ErrDAGCycleDetected,
16
+ ErrMissingPluginMetadata,
17
+ ErrMissingSystemMetadata,
18
+ ErrNotAPlugin,
19
+ ErrNotASystem,
20
+ ErrPluginNotInit,
21
+ ErrUnknownPlugin,
22
+ EventBuffer,
23
+ EventBus,
24
+ ObjectPool,
25
+ Plugin,
26
+ PluginBase,
27
+ PluginError,
28
+ PluginsManager,
29
+ Resource,
30
+ ResourcesManager,
31
+ System,
32
+ SystemBase,
33
+ SystemError,
34
+ SystemPhase,
35
+ SystemsManager,
36
+ Transform,
37
+ UnregisteredComponentStorageError,
38
+ Velocity,
39
+ VisitedState,
40
+ World,
41
+ createEventKey,
42
+ entry,
43
+ getPluginMetadata,
44
+ getResourceMetadata,
45
+ getSystemMetadata,
46
+ isPlugin,
47
+ isSystem,
48
+ topologicalSort
49
+ } from "./chunk-SWTBVK53.js";
940
50
 
941
51
  // src/runtime/runtime.ts
942
52
  var Runtime = class {
@@ -1015,8 +125,8 @@ var AssetState = /* @__PURE__ */ ((AssetState2) => {
1015
125
  return AssetState2;
1016
126
  })(AssetState || {});
1017
127
  var Asset = class {
1018
- constructor(id2, url, loader, disposer) {
1019
- this.id = id2;
128
+ constructor(id, url, loader, disposer) {
129
+ this.id = id;
1020
130
  this.url = url;
1021
131
  this.loader = loader;
1022
132
  this.disposer = disposer;
@@ -1076,36 +186,36 @@ var AssetStorage = class {
1076
186
  defaultLoader_;
1077
187
  defaultDisposer_;
1078
188
  items_ = /* @__PURE__ */ new Map();
1079
- newAsset(id2, url, loader, disposer) {
1080
- return new Asset(id2, url, loader, disposer);
189
+ newAsset(id, url, loader, disposer) {
190
+ return new Asset(id, url, loader, disposer);
1081
191
  }
1082
192
  add(url) {
1083
- const id2 = this.nextIdFn_();
1084
- const rs = this.newAsset(id2, url, this.defaultLoader_, this.defaultDisposer_);
1085
- this.items_.set(id2, rs);
193
+ const id = this.nextIdFn_();
194
+ const rs = this.newAsset(id, url, this.defaultLoader_, this.defaultDisposer_);
195
+ this.items_.set(id, rs);
1086
196
  return rs;
1087
197
  }
1088
198
  addCustom(url, customLoader, customDisposer) {
1089
- const id2 = this.nextIdFn_();
1090
- const rs = this.newAsset(id2, url, customLoader, customDisposer);
1091
- this.items_.set(id2, rs);
199
+ const id = this.nextIdFn_();
200
+ const rs = this.newAsset(id, url, customLoader, customDisposer);
201
+ this.items_.set(id, rs);
1092
202
  return rs;
1093
203
  }
1094
- get(id2) {
1095
- const item = this.items_.get(id2);
204
+ get(id) {
205
+ const item = this.items_.get(id);
1096
206
  return item ?? null;
1097
207
  }
1098
- tryGet(id2) {
1099
- const item = this.items_.get(id2);
208
+ tryGet(id) {
209
+ const item = this.items_.get(id);
1100
210
  if (!item)
1101
- throw new Error(`Asset with id ${id2} in storage ${this.constructor.name} not exist`);
211
+ throw new Error(`Asset with id ${id} in storage ${this.constructor.name} not exist`);
1102
212
  return item;
1103
213
  }
1104
- async remove(id2) {
1105
- const item = this.items_.get(id2);
214
+ async remove(id) {
215
+ const item = this.items_.get(id);
1106
216
  if (!item) return;
1107
217
  await item.dispose();
1108
- this.items_.delete(id2);
218
+ this.items_.delete(id);
1109
219
  }
1110
220
  async loadAll() {
1111
221
  await Promise.all(
@@ -1172,6 +282,13 @@ var NoopLogger = class {
1172
282
  }
1173
283
  };
1174
284
 
285
+ // src/std/utils.ts
286
+ function injectStd(world) {
287
+ world.components.register(Transform);
288
+ world.components.register(Velocity);
289
+ world.systems.register(new MovementSystem());
290
+ }
291
+
1175
292
  // src/engine.ts
1176
293
  var Engine = class {
1177
294
  runtime;
@@ -1181,10 +298,14 @@ var Engine = class {
1181
298
  constructor(params) {
1182
299
  this.runtime = new Runtime(params.loop);
1183
300
  this.logger = params.logger ?? new NoopLogger();
1184
- this.world = new World3({
301
+ this.world = new World({
1185
302
  logger: this.logger,
1186
303
  maxEntityCount: params.maxEntityCount ?? ECS_DEFAULTS.MAX_ENTITY_COUNT
1187
304
  });
305
+ injectStd(this.world);
306
+ }
307
+ getTick() {
308
+ return this.world.updatesCount;
1188
309
  }
1189
310
  init() {
1190
311
  this.world.build();
@@ -1235,7 +356,7 @@ export {
1235
356
  SystemsManager,
1236
357
  UnregisteredComponentStorageError,
1237
358
  VisitedState,
1238
- World3 as World,
359
+ World,
1239
360
  createEventKey,
1240
361
  entry,
1241
362
  getPluginMetadata,