@jael-ecs/core 1.1.1 → 1.2.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.
- package/README.md +29 -32
- package/dist/ComponentManager.d.ts +4 -4
- package/dist/EventRegistry.d.ts +9 -11
- package/dist/Query.d.ts +4 -4
- package/dist/World.d.ts +5 -4
- package/dist/jael-build.cjs +1 -1
- package/dist/jael-build.js +56 -61
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -25,6 +25,7 @@ _A modern, performant, and user-friendly Entity Component System library written
|
|
|
25
25
|
- [EventRegistry](#event-registry)
|
|
26
26
|
- [Best Practices](#best-practices)
|
|
27
27
|
- [Advanced Usage](#advanced-usage)
|
|
28
|
+
- [Planned Features](#planned-features)
|
|
28
29
|
- [Contributing](#contributing)
|
|
29
30
|
- [Acknowledgments](#acknowledgments)
|
|
30
31
|
|
|
@@ -89,15 +90,6 @@ const movementSystem: System = {
|
|
|
89
90
|
position.x += velocity.dx * (Time.delta || 0.016);
|
|
90
91
|
position.y += velocity.dy * (Time.delta || 0.016);
|
|
91
92
|
});
|
|
92
|
-
|
|
93
|
-
// Get entity ids from query
|
|
94
|
-
for (const entityId of query.ids) {
|
|
95
|
-
const position = this.world.getComponent<Position>(entityId, "position");
|
|
96
|
-
const velocity = this.world.getComponent<Velocity>(entityId, "velocity");
|
|
97
|
-
|
|
98
|
-
position.x += velocity.dx * (Time.delta || 0.016);
|
|
99
|
-
position.y += velocity.dy * (Time.delta || 0.016);
|
|
100
|
-
}
|
|
101
93
|
},
|
|
102
94
|
};
|
|
103
95
|
|
|
@@ -163,21 +155,21 @@ world.removeSystem(yourSystem);
|
|
|
163
155
|
#### Events
|
|
164
156
|
|
|
165
157
|
```typescript
|
|
166
|
-
// Listen to world events
|
|
167
|
-
world.on("entityCreated", ({
|
|
168
|
-
console.log("Entity created:",
|
|
158
|
+
// Listen to world events
|
|
159
|
+
world.on("entityCreated", ({ entityId }) => {
|
|
160
|
+
console.log("Entity created:", entityId);
|
|
169
161
|
});
|
|
170
162
|
|
|
171
|
-
world.on("entityDestroyed", ({
|
|
172
|
-
console.log("Entity destroyed:",
|
|
163
|
+
world.on("entityDestroyed", ({ entityId }) => {
|
|
164
|
+
console.log("Entity destroyed:", entityId);
|
|
173
165
|
});
|
|
174
166
|
|
|
175
|
-
world.on("componentAdded", ({
|
|
176
|
-
console.log(`Component ${component} added to entity`);
|
|
167
|
+
world.on("componentAdded", ({ entityId, component }) => {
|
|
168
|
+
console.log(`Component ${component} added to entity ${entityId}`);
|
|
177
169
|
});
|
|
178
170
|
|
|
179
|
-
world.on("componentRemoved", ({
|
|
180
|
-
console.log(`Component ${component} removed from entity`);
|
|
171
|
+
world.on("componentRemoved", ({ entityId, component }) => {
|
|
172
|
+
console.log(`Component ${component} removed from entity ${entityId}`);
|
|
181
173
|
});
|
|
182
174
|
|
|
183
175
|
world.on("updated", () => {
|
|
@@ -206,8 +198,7 @@ const posExist = entity.has("position");
|
|
|
206
198
|
// Get curren value of the component
|
|
207
199
|
const compSchema = entity.get("position");
|
|
208
200
|
|
|
209
|
-
entity.id // Returns unique entity id from proxy
|
|
210
|
-
|
|
201
|
+
entity.id; // Returns unique entity id from proxy
|
|
211
202
|
```
|
|
212
203
|
|
|
213
204
|
### System
|
|
@@ -287,18 +278,16 @@ const complexQuery2 = world.include("position", "health").exclude("static");
|
|
|
287
278
|
// Iterate through entities as proxy
|
|
288
279
|
query.entities.forEach((entity) => {
|
|
289
280
|
// Process Entity proxy
|
|
290
|
-
})
|
|
281
|
+
});
|
|
291
282
|
|
|
292
283
|
// Iterate through entities ids
|
|
293
|
-
for(const entityId of query.ids){
|
|
284
|
+
for (const entityId of query.ids) {
|
|
294
285
|
// Process Entity id
|
|
295
286
|
}
|
|
296
287
|
|
|
297
|
-
|
|
298
|
-
|
|
299
288
|
// Get the first value of the query
|
|
300
289
|
const first = query.entities[0];
|
|
301
|
-
const firstId = query.ids.first()
|
|
290
|
+
const firstId = query.ids.first();
|
|
302
291
|
|
|
303
292
|
// Check query size
|
|
304
293
|
const count = query.size();
|
|
@@ -388,7 +377,7 @@ world.on("entityCreated", (data) => {
|
|
|
388
377
|
});
|
|
389
378
|
|
|
390
379
|
// Emit events (handled internally by World)
|
|
391
|
-
world.emit("entityCreated", {
|
|
380
|
+
world.emit("entityCreated", { entityId });
|
|
392
381
|
|
|
393
382
|
// Remove listeners
|
|
394
383
|
world.off("entityCreated", handler);
|
|
@@ -450,9 +439,9 @@ class MovementSystem implements System {
|
|
|
450
439
|
}
|
|
451
440
|
|
|
452
441
|
update() {
|
|
453
|
-
|
|
454
|
-
//
|
|
455
|
-
}
|
|
442
|
+
this.movementQuery.entities.forEach((entity) => {
|
|
443
|
+
// Handle entity movement
|
|
444
|
+
})
|
|
456
445
|
}
|
|
457
446
|
}
|
|
458
447
|
|
|
@@ -469,9 +458,9 @@ const movementSystem: MovementSystem = {
|
|
|
469
458
|
}
|
|
470
459
|
|
|
471
460
|
update(){
|
|
472
|
-
|
|
473
|
-
//
|
|
474
|
-
}
|
|
461
|
+
this.movementQuery?.entities.forEach((entity) => {
|
|
462
|
+
// Handle entity movement
|
|
463
|
+
})
|
|
475
464
|
}
|
|
476
465
|
}
|
|
477
466
|
|
|
@@ -514,6 +503,13 @@ world.on("playerScored", ({ points }) => {
|
|
|
514
503
|
});
|
|
515
504
|
```
|
|
516
505
|
|
|
506
|
+
## Planned Features
|
|
507
|
+
|
|
508
|
+
- Implement basic one level tag manager.
|
|
509
|
+
- Instancing / Prefab system with searilzation.
|
|
510
|
+
- Entity with childrens and parents.
|
|
511
|
+
- React wrapper (?)
|
|
512
|
+
|
|
517
513
|
## Contributing
|
|
518
514
|
|
|
519
515
|
Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.
|
|
@@ -542,6 +538,7 @@ npm run build
|
|
|
542
538
|
## Acknowledgments
|
|
543
539
|
|
|
544
540
|
- Inspiration from ECS frameworks like [ECSY](https://github.com/ecsyjs/ecsy) and [Bevy](https://github.com/bevyengine/bevy)
|
|
541
|
+
- Deep digging documentation at [Austin Morlan Post](https://austinmorlan.com/posts/entity_component_system/)
|
|
545
542
|
- TypeScript for providing excellent type safety and developer experience
|
|
546
543
|
|
|
547
544
|
---
|
|
@@ -12,14 +12,14 @@ export interface ComponentManagerEvents {
|
|
|
12
12
|
};
|
|
13
13
|
}
|
|
14
14
|
export declare class ComponentManager extends EventRegistry<ComponentManagerEvents> {
|
|
15
|
-
componentSet
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
world: World;
|
|
15
|
+
private componentSet;
|
|
16
|
+
private world;
|
|
17
|
+
dirtyEntities: Set<number>;
|
|
19
18
|
constructor(world: World);
|
|
20
19
|
clearComponentSchema(entityId: number): void;
|
|
21
20
|
addComponent<K extends keyof ComponentSchema>(entityId: number, key: K, value: ComponentSchema[K]): void;
|
|
22
21
|
getComponent<K extends keyof ComponentSchema>(entityId: number, key: K): ComponentSchema[K] | undefined;
|
|
22
|
+
cleanDirtyEntities(): void;
|
|
23
23
|
hasComponent<K extends keyof ComponentSchema>(entityId: number, key: K): boolean;
|
|
24
24
|
removeComponent<K extends keyof ComponentSchema>(entityId: number, key: K): void;
|
|
25
25
|
}
|
package/dist/EventRegistry.d.ts
CHANGED
|
@@ -1,14 +1,12 @@
|
|
|
1
|
-
export
|
|
2
|
-
[key: string]:
|
|
3
|
-
}
|
|
4
|
-
export type EventCallback<V> = (event: V[keyof V]) => void;
|
|
5
|
-
export default class EventRegistry<E extends Event<any> = {}> {
|
|
1
|
+
export default class EventRegistry<E extends {
|
|
2
|
+
[key: string]: any;
|
|
3
|
+
} = {}> {
|
|
6
4
|
private _listeners;
|
|
7
|
-
on(type:
|
|
8
|
-
off(type:
|
|
9
|
-
once(type:
|
|
10
|
-
clearEvent(type:
|
|
5
|
+
on<K extends string>(type: K, callback: (e: E[K]) => void): void;
|
|
6
|
+
off<K extends string>(type: K, callback: (e: E[K]) => void): void;
|
|
7
|
+
once<K extends string>(type: K, callback: (e: E[K]) => void): void;
|
|
8
|
+
clearEvent<K extends string>(type: K): void;
|
|
11
9
|
clearAllEvents(): void;
|
|
12
|
-
contains(type:
|
|
13
|
-
emit(type:
|
|
10
|
+
contains<K extends string>(type: K, callback: (e: E[K]) => void): boolean;
|
|
11
|
+
emit<K extends string>(type: K, data?: E[K]): void;
|
|
14
12
|
}
|
package/dist/Query.d.ts
CHANGED
|
@@ -13,18 +13,18 @@ export interface QueryEvents {
|
|
|
13
13
|
export declare class Query extends EventRegistry<QueryEvents> {
|
|
14
14
|
private config;
|
|
15
15
|
private entityMap;
|
|
16
|
-
private entityInstancesCache;
|
|
17
16
|
private world;
|
|
17
|
+
private lastVersion;
|
|
18
|
+
dirty: boolean;
|
|
18
19
|
constructor(config: QueryConfig, world: World);
|
|
19
20
|
hasComponents(entityId: number): boolean;
|
|
20
21
|
size(): number;
|
|
21
22
|
get hash(): number;
|
|
22
23
|
get ids(): SparseSet<number>;
|
|
23
|
-
private getCachedEntity;
|
|
24
24
|
get entities(): Entity[];
|
|
25
25
|
include(...comps: string[]): Query;
|
|
26
26
|
exclude(...comps: string[]): Query;
|
|
27
|
-
|
|
28
|
-
checkEntities(): void;
|
|
27
|
+
markDirty(): void;
|
|
28
|
+
checkEntities(entities?: Set<number>): void;
|
|
29
29
|
static getHash(config: QueryConfig): number;
|
|
30
30
|
}
|
package/dist/World.d.ts
CHANGED
|
@@ -6,17 +6,17 @@ import { SparseSet } from './SparseSet';
|
|
|
6
6
|
import { SystemManager, System } from './SystemManager';
|
|
7
7
|
export interface WorldEvents {
|
|
8
8
|
entityCreated: {
|
|
9
|
-
|
|
9
|
+
entityId: number;
|
|
10
10
|
};
|
|
11
11
|
entityDestroyed: {
|
|
12
|
-
|
|
12
|
+
entityId: number;
|
|
13
13
|
};
|
|
14
14
|
componentAdded: {
|
|
15
|
-
|
|
15
|
+
entityId: number;
|
|
16
16
|
component: keyof ComponentSchema;
|
|
17
17
|
};
|
|
18
18
|
componentRemoved: {
|
|
19
|
-
|
|
19
|
+
entityId: number;
|
|
20
20
|
component: keyof ComponentSchema;
|
|
21
21
|
};
|
|
22
22
|
updated: void;
|
|
@@ -26,6 +26,7 @@ export default class World extends EventRegistry<WorldEvents> {
|
|
|
26
26
|
componentManager: ComponentManager;
|
|
27
27
|
systemManager: SystemManager;
|
|
28
28
|
queries: Map<number, Query>;
|
|
29
|
+
version: number;
|
|
29
30
|
constructor();
|
|
30
31
|
getEntity(id: number): Entity | undefined;
|
|
31
32
|
get entityIds(): SparseSet<number>;
|
package/dist/jael-build.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});class o{_listeners=new Map;on(e,t){if(this.contains(e,t))return;const s=this._listeners.get(e);s?s.add(t):this._listeners.set(e,new Set([t]))}off(e,t){if(!this.contains(e,t))return;const s=this._listeners.get(e);s&&s.delete(t)}once(e,t){const s=
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});class o{_listeners=new Map;on(e,t){if(this.contains(e,t))return;const s=this._listeners.get(e);s?s.add(t):this._listeners.set(e,new Set([t]))}off(e,t){if(!this.contains(e,t))return;const s=this._listeners.get(e);s&&s.delete(t)}once(e,t){const s=i=>{t(i),this.off(e,s)};this.on(e,s)}clearEvent(e){this._listeners.get(e)&&this._listeners.get(e)?.clear()}clearAllEvents(){this._listeners.forEach(e=>e.clear()),this._listeners.clear()}contains(e,t){return this._listeners.get(e)?this._listeners.get(e).has(t):!1}emit(e,t){this._listeners.get(e)&&this._listeners.get(e)?.forEach(s=>{s(t)})}}class c{systemList=[];addSystem(e){this.systemList.push(e),e.init?.(),this.reorder()}reorder(){this.systemList.sort((e,t)=>e.priority-t.priority)}has(e){return this.systemList.indexOf(e)>0}removeSystem(e){if(!this.has(e))return;const t=this.systemList.indexOf(e);t>=0&&(this.systemList.splice(t,1),e.exit?.(),this.reorder())}}class d{denseValues=[];sparse=new Map;[Symbol.iterator](){let e=this.values.length;const t={value:void 0,done:!1};return{next:()=>(t.value=this.values[--e],t.done=e<0,t)}}get values(){return this.denseValues}first(){return this.denseValues[0]}add(e){this.has(e)||(this.denseValues.push(e),this.sparse.set(e,this.denseValues.length-1))}indexOf(e){const t=this.sparse.get(e);return t!==void 0?t:-1}remove(e){if(!this.has(e))return;const t=this.sparse.get(e);this.sparse.delete(e);const s=this.denseValues[this.denseValues.length-1];s!==e&&(this.denseValues[t]=s,this.sparse.set(s,t)),this.denseValues.pop()}forEach(e){for(let t of this)e(t)}size(){return this.denseValues.length}clear(){for(let e of this)this.remove(e)}has(e){return this.sparse.has(e)}}class m{id;_world;constructor(e,t){this.id=t,this._world=e}add(e,t){this._world.addComponent(this.id,e,t)}remove(e){this._world.removeComponent(this.id,e)}has(e){return this._world.componentManager.hasComponent(this.id,e)}get(e){return this._world.componentManager.getComponent(this.id,e)}}class l extends o{entityMap=new d;nextId=0;_world;constructor(e){super(),this._world=e}get entities(){return this.entityMap}create(){const e=this.nextId++;return this.entities.add(e),this.emit("create",e),e}exist(e){return this.entities.has(e)}size(){return this.entities.size()}destroy(e){return this.entities.remove(e),this.emit("destroy",e),e}}class u extends o{componentSet={};world;dirtyEntities=new Set;constructor(e){super(),this.world=e}clearComponentSchema(e){this.componentSet[e]&&delete this.componentSet[e]}addComponent(e,t,s){if(!this.world.exist(e))return;const i=this.componentSet[e];i?i[t]=s:this.componentSet[e]={[t]:s},this.dirtyEntities.add(e),this.emit("add",{entityId:e,component:t})}getComponent(e,t){if(this.hasComponent(e,t))return this.componentSet[e][t]}cleanDirtyEntities(){this.dirtyEntities.clear()}hasComponent(e,t){const s=this.componentSet[e];return s?t in s:!1}removeComponent(e,t){if(!this.componentSet[e])return;const s=this.componentSet[e];s&&s[t]!==void 0&&(delete s[t],Object.keys(s).length===0&&delete this.componentSet[e],this.dirtyEntities.add(e),this.emit("remove",{entityId:e,component:t}))}}class h extends o{config;entityMap;world;lastVersion=0;dirty;constructor(e,t){super(),this.config=e,this.world=t,this.entityMap=new d,this.dirty=!1,this.world.on("entityDestroyed",({entityId:s})=>{this.entityMap.has(s)&&(this.emit("removed",s),this.entityMap.remove(s))})}hasComponents(e){const t=this.world.componentManager;return this.config.include?.every(s=>t.getComponent(e,s))&&this.config.exclude?.every(s=>!t.getComponent(e,s))}size(){return this.ids.size()}get hash(){return h.getHash(this.config)}get ids(){return this.entityMap}get entities(){const e=[];return this.entityMap.forEach(t=>{const s=this.world.getEntity(t);s&&e.push(s)}),e}include(...e){return this.world.include(...e)}exclude(...e){return this.world.exclude(...e)}markDirty(){this.dirty=!0}checkEntities(e){if(!this.dirty||this.world.version===this.lastVersion)return;const t=e||this.world.entityIds;for(let s of t)this.hasComponents(s)&&(this.entityMap.add(s),this.emit("added",s));this.dirty=!1,this.lastVersion=this.world.version}static getHash(e){const t=e.include?.map(n=>n.trim()).filter(n=>n).join("_"),s=e.exclude?.map(n=>n.trim()).filter(n=>n).join("_"),i="in_"+t+"_out_"+s;let a=0;for(const n of i)a=(a<<5)-a+n.charCodeAt(0),a|=0;return a}}class p extends o{_startTime=0;_oldTime=0;_requestId=0;running=!1;delta=0;elapsed=0;constructor(){super()}_loop(){let e=0;if(this.running){const t=performance.now();e=(t-this._oldTime)/1e3,this._oldTime=t,this.elapsed+=e}this.delta=e,this.emit("update"),this._requestId=requestAnimationFrame(this._loop.bind(this))}start(){this._startTime=performance.now(),this._oldTime=this._startTime,this.elapsed=0,this.delta=0,this.running=!0,this._loop()}stop(){this.running=!1,cancelAnimationFrame(this._requestId),this._requestId=0}}let g=new p;class f extends o{entityManager;componentManager;systemManager;queries;version;constructor(){super(),this.entityManager=new l(this),this.componentManager=new u(this),this.systemManager=new c,this.version=0,this.entityManager.on("create",e=>{this.emit("entityCreated",{entityId:e}),this._updateQueries()}),this.entityManager.on("destroy",e=>{this.emit("entityDestroyed",{entityId:e}),this._updateQueries(),this.componentManager.clearComponentSchema(e)}),this.componentManager.on("add",({entityId:e,component:t})=>{this.emit("componentAdded",{entityId:e,component:t}),this._updateQueries()}),this.componentManager.on("remove",({entityId:e,component:t})=>{this.getEntity(e)&&this.emit("componentRemoved",{entityId:e,component:t}),this._updateQueries()}),this.queries=new Map}getEntity(e){return this.exist(e)?new m(this,e):void 0}get entityIds(){return this.entityManager.entities}query(e){const t=h.getHash(e);let i=this.queries.get(t);return i||(i=new h(e,this),this.queries.set(t,i),this._updateQueries()),i}_updateQueries(){const e=this.componentManager.dirtyEntities;this.queries.forEach(t=>{t.markDirty(),t.checkEntities(e.size>0?e:void 0)}),this.componentManager.cleanDirtyEntities(),this.version++}exist(e){return this.entityManager.exist(e)}include(...e){return this.query({include:e,exclude:[]})}exclude(...e){return this.query({include:[],exclude:e})}create(){return this.entityManager.create()}destroy(e){this.entityManager.destroy(e)}addSystem(e){this.systemManager.addSystem(e)}removeSystem(e){this.systemManager.removeSystem(e)}addComponent(e,t,s){this.componentManager.addComponent(e,t,s)}getComponent(e,t){return this.componentManager.getComponent(e,t)}removeComponent(e,t){this.componentManager.removeComponent(e,t)}update(){this.systemManager.systemList.forEach(e=>{e.update()}),this.emit("updated")}}exports.ComponentManager=u;exports.EntityManager=l;exports.EventRegistry=o;exports.Query=h;exports.SparseSet=d;exports.SystemManager=c;exports.Time=g;exports.World=f;
|
package/dist/jael-build.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
class
|
|
1
|
+
class h {
|
|
2
2
|
_listeners = /* @__PURE__ */ new Map();
|
|
3
3
|
on(e, t) {
|
|
4
4
|
if (this.contains(e, t))
|
|
@@ -13,9 +13,9 @@ class a {
|
|
|
13
13
|
s && s.delete(t);
|
|
14
14
|
}
|
|
15
15
|
once(e, t) {
|
|
16
|
-
const s = (
|
|
17
|
-
t(
|
|
18
|
-
}
|
|
16
|
+
const s = (i) => {
|
|
17
|
+
t(i), this.off(e, s);
|
|
18
|
+
};
|
|
19
19
|
this.on(e, s);
|
|
20
20
|
}
|
|
21
21
|
clearEvent(e) {
|
|
@@ -33,7 +33,7 @@ class a {
|
|
|
33
33
|
});
|
|
34
34
|
}
|
|
35
35
|
}
|
|
36
|
-
class
|
|
36
|
+
class c {
|
|
37
37
|
systemList = [];
|
|
38
38
|
addSystem(e) {
|
|
39
39
|
this.systemList.push(e), e.init?.(), this.reorder();
|
|
@@ -98,7 +98,7 @@ class d {
|
|
|
98
98
|
return this.sparse.has(e);
|
|
99
99
|
}
|
|
100
100
|
}
|
|
101
|
-
class
|
|
101
|
+
class l {
|
|
102
102
|
id;
|
|
103
103
|
_world;
|
|
104
104
|
constructor(e, t) {
|
|
@@ -136,7 +136,7 @@ class h {
|
|
|
136
136
|
return this._world.componentManager.getComponent(this.id, e);
|
|
137
137
|
}
|
|
138
138
|
}
|
|
139
|
-
class
|
|
139
|
+
class u extends h {
|
|
140
140
|
entityMap = new d();
|
|
141
141
|
nextId = 0;
|
|
142
142
|
_world;
|
|
@@ -160,9 +160,10 @@ class l extends a {
|
|
|
160
160
|
return this.entities.remove(e), this.emit("destroy", e), e;
|
|
161
161
|
}
|
|
162
162
|
}
|
|
163
|
-
class m extends
|
|
163
|
+
class m extends h {
|
|
164
164
|
componentSet = {};
|
|
165
165
|
world;
|
|
166
|
+
dirtyEntities = /* @__PURE__ */ new Set();
|
|
166
167
|
constructor(e) {
|
|
167
168
|
super(), this.world = e;
|
|
168
169
|
}
|
|
@@ -171,13 +172,16 @@ class m extends a {
|
|
|
171
172
|
}
|
|
172
173
|
addComponent(e, t, s) {
|
|
173
174
|
if (!this.world.exist(e)) return;
|
|
174
|
-
const
|
|
175
|
-
|
|
175
|
+
const i = this.componentSet[e];
|
|
176
|
+
i ? i[t] = s : this.componentSet[e] = { [t]: s }, this.dirtyEntities.add(e), this.emit("add", { entityId: e, component: t });
|
|
176
177
|
}
|
|
177
178
|
getComponent(e, t) {
|
|
178
179
|
if (this.hasComponent(e, t))
|
|
179
180
|
return this.componentSet[e][t];
|
|
180
181
|
}
|
|
182
|
+
cleanDirtyEntities() {
|
|
183
|
+
this.dirtyEntities.clear();
|
|
184
|
+
}
|
|
181
185
|
hasComponent(e, t) {
|
|
182
186
|
const s = this.componentSet[e];
|
|
183
187
|
return s ? t in s : !1;
|
|
@@ -185,17 +189,18 @@ class m extends a {
|
|
|
185
189
|
removeComponent(e, t) {
|
|
186
190
|
if (!this.componentSet[e]) return;
|
|
187
191
|
const s = this.componentSet[e];
|
|
188
|
-
s && s[t] !== void 0 && (delete s[t], Object.keys(s).length === 0 && delete this.componentSet[e], this.emit("remove", { entityId: e, component: t }));
|
|
192
|
+
s && s[t] !== void 0 && (delete s[t], Object.keys(s).length === 0 && delete this.componentSet[e], this.dirtyEntities.add(e), this.emit("remove", { entityId: e, component: t }));
|
|
189
193
|
}
|
|
190
194
|
}
|
|
191
|
-
class
|
|
195
|
+
class a extends h {
|
|
192
196
|
config;
|
|
193
197
|
entityMap;
|
|
194
|
-
entityInstancesCache;
|
|
195
198
|
world;
|
|
199
|
+
lastVersion = 0;
|
|
200
|
+
dirty;
|
|
196
201
|
constructor(e, t) {
|
|
197
|
-
super(), this.config = e, this.world = t, this.
|
|
198
|
-
this.
|
|
202
|
+
super(), this.config = e, this.world = t, this.entityMap = new d(), this.dirty = !1, this.world.on("entityDestroyed", ({ entityId: s }) => {
|
|
203
|
+
this.entityMap.has(s) && (this.emit("removed", s), this.entityMap.remove(s));
|
|
199
204
|
});
|
|
200
205
|
}
|
|
201
206
|
hasComponents(e) {
|
|
@@ -210,30 +215,16 @@ class c extends a {
|
|
|
210
215
|
return this.ids.size();
|
|
211
216
|
}
|
|
212
217
|
get hash() {
|
|
213
|
-
return
|
|
218
|
+
return a.getHash(this.config);
|
|
214
219
|
}
|
|
215
220
|
get ids() {
|
|
216
221
|
return this.entityMap;
|
|
217
222
|
}
|
|
218
|
-
getCachedEntity(e) {
|
|
219
|
-
const t = this.entityInstancesCache.get(e);
|
|
220
|
-
if (t)
|
|
221
|
-
return t;
|
|
222
|
-
{
|
|
223
|
-
const s = this.world.getEntity(e);
|
|
224
|
-
return s ? (this.entityInstancesCache.set(e, s), s) : void 0;
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
223
|
get entities() {
|
|
228
|
-
const e = []
|
|
229
|
-
return this.entityMap.forEach((
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
n && e.push(n);
|
|
233
|
-
} else {
|
|
234
|
-
const n = this.world.getEntity(s);
|
|
235
|
-
n && e.push(n);
|
|
236
|
-
}
|
|
224
|
+
const e = [];
|
|
225
|
+
return this.entityMap.forEach((t) => {
|
|
226
|
+
const s = this.world.getEntity(t);
|
|
227
|
+
s && e.push(s);
|
|
237
228
|
}), e;
|
|
238
229
|
}
|
|
239
230
|
include(...e) {
|
|
@@ -242,25 +233,25 @@ class c extends a {
|
|
|
242
233
|
exclude(...e) {
|
|
243
234
|
return this.world.exclude(...e);
|
|
244
235
|
}
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
this.world.exist(e) || (this.emit("removed", e), this.entityMap.remove(e));
|
|
236
|
+
markDirty() {
|
|
237
|
+
this.dirty = !0;
|
|
248
238
|
}
|
|
249
|
-
checkEntities() {
|
|
250
|
-
this.
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
239
|
+
checkEntities(e) {
|
|
240
|
+
if (!this.dirty || this.world.version === this.lastVersion) return;
|
|
241
|
+
const t = e || this.world.entityIds;
|
|
242
|
+
for (let s of t)
|
|
243
|
+
this.hasComponents(s) && (this.entityMap.add(s), this.emit("added", s));
|
|
244
|
+
this.dirty = !1, this.lastVersion = this.world.version;
|
|
254
245
|
}
|
|
255
246
|
static getHash(e) {
|
|
256
|
-
const t = e.include?.map((
|
|
247
|
+
const t = e.include?.map((n) => n.trim()).filter((n) => n).join("_"), s = e.exclude?.map((n) => n.trim()).filter((n) => n).join("_"), i = "in_" + t + "_out_" + s;
|
|
257
248
|
let o = 0;
|
|
258
|
-
for (const
|
|
259
|
-
o = (o << 5) - o +
|
|
249
|
+
for (const n of i)
|
|
250
|
+
o = (o << 5) - o + n.charCodeAt(0), o |= 0;
|
|
260
251
|
return o;
|
|
261
252
|
}
|
|
262
253
|
}
|
|
263
|
-
class p extends
|
|
254
|
+
class p extends h {
|
|
264
255
|
_startTime = 0;
|
|
265
256
|
_oldTime = 0;
|
|
266
257
|
_requestId = 0;
|
|
@@ -286,45 +277,49 @@ class p extends a {
|
|
|
286
277
|
}
|
|
287
278
|
}
|
|
288
279
|
let g = new p();
|
|
289
|
-
class f extends
|
|
280
|
+
class f extends h {
|
|
290
281
|
entityManager;
|
|
291
282
|
componentManager;
|
|
292
283
|
systemManager;
|
|
293
284
|
queries;
|
|
285
|
+
version;
|
|
294
286
|
constructor() {
|
|
295
|
-
super(), this.entityManager = new
|
|
287
|
+
super(), this.entityManager = new u(this), this.componentManager = new m(this), this.systemManager = new c(), this.version = 0, this.entityManager.on("create", (e) => {
|
|
296
288
|
this.emit("entityCreated", {
|
|
297
|
-
|
|
289
|
+
entityId: e
|
|
298
290
|
}), this._updateQueries();
|
|
299
291
|
}), this.entityManager.on("destroy", (e) => {
|
|
300
292
|
this.emit("entityDestroyed", {
|
|
301
|
-
|
|
293
|
+
entityId: e
|
|
302
294
|
}), this._updateQueries(), this.componentManager.clearComponentSchema(e);
|
|
303
295
|
}), this.componentManager.on("add", ({ entityId: e, component: t }) => {
|
|
304
296
|
this.emit("componentAdded", {
|
|
305
|
-
|
|
297
|
+
entityId: e,
|
|
306
298
|
component: t
|
|
307
299
|
}), this._updateQueries();
|
|
308
300
|
}), this.componentManager.on("remove", ({ entityId: e, component: t }) => {
|
|
309
301
|
this.getEntity(e) && this.emit("componentRemoved", {
|
|
310
|
-
|
|
302
|
+
entityId: e,
|
|
311
303
|
component: t
|
|
312
304
|
}), this._updateQueries();
|
|
313
305
|
}), this.queries = /* @__PURE__ */ new Map();
|
|
314
306
|
}
|
|
315
307
|
getEntity(e) {
|
|
316
|
-
return this.exist(e) ? new
|
|
308
|
+
return this.exist(e) ? new l(this, e) : void 0;
|
|
317
309
|
}
|
|
318
310
|
get entityIds() {
|
|
319
311
|
return this.entityManager.entities;
|
|
320
312
|
}
|
|
321
313
|
query(e) {
|
|
322
|
-
const t =
|
|
323
|
-
let
|
|
324
|
-
return
|
|
314
|
+
const t = a.getHash(e);
|
|
315
|
+
let i = this.queries.get(t);
|
|
316
|
+
return i || (i = new a(e, this), this.queries.set(t, i), this._updateQueries()), i;
|
|
325
317
|
}
|
|
326
318
|
_updateQueries() {
|
|
327
|
-
|
|
319
|
+
const e = this.componentManager.dirtyEntities;
|
|
320
|
+
this.queries.forEach((t) => {
|
|
321
|
+
t.markDirty(), t.checkEntities(e.size > 0 ? e : void 0);
|
|
322
|
+
}), this.componentManager.cleanDirtyEntities(), this.version++;
|
|
328
323
|
}
|
|
329
324
|
exist(e) {
|
|
330
325
|
return this.entityManager.exist(e);
|
|
@@ -364,11 +359,11 @@ class f extends a {
|
|
|
364
359
|
}
|
|
365
360
|
export {
|
|
366
361
|
m as ComponentManager,
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
362
|
+
u as EntityManager,
|
|
363
|
+
h as EventRegistry,
|
|
364
|
+
a as Query,
|
|
370
365
|
d as SparseSet,
|
|
371
|
-
|
|
366
|
+
c as SystemManager,
|
|
372
367
|
g as Time,
|
|
373
368
|
f as World
|
|
374
369
|
};
|