@codehz/ecs 0.3.4 → 0.3.5
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/index.js +37 -18
- package/package.json +1 -1
- package/world.d.ts +9 -0
package/index.js
CHANGED
|
@@ -884,6 +884,7 @@ class World {
|
|
|
884
884
|
commandBuffer = new CommandBuffer((entityId, commands) => this.executeEntityCommands(entityId, commands));
|
|
885
885
|
hooks = new Map;
|
|
886
886
|
exclusiveComponents = new Set;
|
|
887
|
+
cascadeDeleteComponents = new Set;
|
|
887
888
|
constructor(snapshot) {
|
|
888
889
|
if (snapshot && typeof snapshot === "object") {
|
|
889
890
|
if (snapshot.entityManager) {
|
|
@@ -953,14 +954,29 @@ class World {
|
|
|
953
954
|
return entityId;
|
|
954
955
|
}
|
|
955
956
|
destroyEntityImmediate(entityId) {
|
|
956
|
-
const
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
957
|
+
const queue = [entityId];
|
|
958
|
+
const visited = new Set;
|
|
959
|
+
while (queue.length > 0) {
|
|
960
|
+
const cur = queue.shift();
|
|
961
|
+
if (visited.has(cur))
|
|
962
|
+
continue;
|
|
963
|
+
visited.add(cur);
|
|
964
|
+
const archetype = this.entityToArchetype.get(cur);
|
|
965
|
+
if (!archetype) {
|
|
966
|
+
continue;
|
|
967
|
+
}
|
|
968
|
+
const componentReferences = Array.from(this.getEntityReferences(cur));
|
|
969
|
+
for (const [sourceEntityId, componentType] of componentReferences) {
|
|
970
|
+
const sourceArchetype = this.entityToArchetype.get(sourceEntityId);
|
|
971
|
+
if (!sourceArchetype)
|
|
972
|
+
continue;
|
|
973
|
+
const detailedType = getDetailedIdType(componentType);
|
|
974
|
+
if (detailedType.type === "entity-relation" && this.cascadeDeleteComponents.has(detailedType.componentId)) {
|
|
975
|
+
if (!visited.has(sourceEntityId)) {
|
|
976
|
+
queue.push(sourceEntityId);
|
|
977
|
+
}
|
|
978
|
+
continue;
|
|
979
|
+
}
|
|
964
980
|
const currentComponents = new Map;
|
|
965
981
|
let removedComponent = sourceArchetype.get(sourceEntityId, componentType);
|
|
966
982
|
for (const archetypeComponentType of sourceArchetype.componentTypes) {
|
|
@@ -976,17 +992,17 @@ class World {
|
|
|
976
992
|
}
|
|
977
993
|
newArchetype.addEntity(sourceEntityId, currentComponents);
|
|
978
994
|
this.entityToArchetype.set(sourceEntityId, newArchetype);
|
|
979
|
-
this.untrackEntityReference(sourceEntityId, componentType,
|
|
995
|
+
this.untrackEntityReference(sourceEntityId, componentType, cur);
|
|
980
996
|
this.triggerLifecycleHooks(sourceEntityId, new Map, new Map([[componentType, removedComponent]]));
|
|
981
997
|
}
|
|
998
|
+
this.entityReferences.delete(cur);
|
|
999
|
+
archetype.removeEntity(cur);
|
|
1000
|
+
if (archetype.getEntities().length === 0) {
|
|
1001
|
+
this.cleanupEmptyArchetype(archetype);
|
|
1002
|
+
}
|
|
1003
|
+
this.entityToArchetype.delete(cur);
|
|
1004
|
+
this.entityIdManager.deallocate(cur);
|
|
982
1005
|
}
|
|
983
|
-
this.entityReferences.delete(entityId);
|
|
984
|
-
archetype.removeEntity(entityId);
|
|
985
|
-
if (archetype.getEntities().length === 0) {
|
|
986
|
-
this.cleanupEmptyArchetype(archetype);
|
|
987
|
-
}
|
|
988
|
-
this.entityToArchetype.delete(entityId);
|
|
989
|
-
this.entityIdManager.deallocate(entityId);
|
|
990
1006
|
}
|
|
991
1007
|
exists(entityId) {
|
|
992
1008
|
return this.entityToArchetype.has(entityId);
|
|
@@ -1066,6 +1082,9 @@ class World {
|
|
|
1066
1082
|
setExclusive(componentId) {
|
|
1067
1083
|
this.exclusiveComponents.add(componentId);
|
|
1068
1084
|
}
|
|
1085
|
+
setCascadeDelete(componentId) {
|
|
1086
|
+
this.cascadeDeleteComponents.add(componentId);
|
|
1087
|
+
}
|
|
1069
1088
|
update(...params) {
|
|
1070
1089
|
const result = this.systemScheduler.update(...params);
|
|
1071
1090
|
if (result instanceof Promise) {
|
|
@@ -1293,14 +1312,14 @@ class World {
|
|
|
1293
1312
|
untrackEntityReference(sourceEntityId, componentType, targetEntityId) {
|
|
1294
1313
|
const references = this.entityReferences.get(targetEntityId);
|
|
1295
1314
|
if (references) {
|
|
1296
|
-
references.
|
|
1315
|
+
references.remove(sourceEntityId, componentType);
|
|
1297
1316
|
if (references.keyCount === 0) {
|
|
1298
1317
|
this.entityReferences.delete(targetEntityId);
|
|
1299
1318
|
}
|
|
1300
1319
|
}
|
|
1301
1320
|
}
|
|
1302
1321
|
getEntityReferences(targetEntityId) {
|
|
1303
|
-
return this.entityReferences.get(targetEntityId) ??
|
|
1322
|
+
return this.entityReferences.get(targetEntityId) ?? new MultiMap;
|
|
1304
1323
|
}
|
|
1305
1324
|
cleanupEmptyArchetype(archetype) {
|
|
1306
1325
|
if (archetype.getEntities().length > 0) {
|
package/package.json
CHANGED
package/world.d.ts
CHANGED
|
@@ -35,6 +35,8 @@ export declare class World<UpdateParams extends any[] = []> {
|
|
|
35
35
|
private hooks;
|
|
36
36
|
/** Set of component IDs marked as exclusive relations */
|
|
37
37
|
private exclusiveComponents;
|
|
38
|
+
/** Set of component IDs that will cascade delete when the relation target is deleted */
|
|
39
|
+
private cascadeDeleteComponents;
|
|
38
40
|
/**
|
|
39
41
|
* Create a new World.
|
|
40
42
|
* If an optional snapshot object is provided (previously produced by `world.serialize()`),
|
|
@@ -108,6 +110,13 @@ export declare class World<UpdateParams extends any[] = []> {
|
|
|
108
110
|
* For exclusive relations, an entity can have at most one relation per base component
|
|
109
111
|
*/
|
|
110
112
|
setExclusive(componentId: EntityId): void;
|
|
113
|
+
/**
|
|
114
|
+
* Mark a component as cascade-delete relation
|
|
115
|
+
* For cascade relations, when the relation target entity is deleted,
|
|
116
|
+
* the referencing entity will also be deleted (cascade).
|
|
117
|
+
* Only applicable to entity-relation components
|
|
118
|
+
*/
|
|
119
|
+
setCascadeDelete(componentId: EntityId): void;
|
|
111
120
|
/**
|
|
112
121
|
* Update the world (run all systems in dependency order)
|
|
113
122
|
* This function is synchronous when all systems are synchronous,
|