refactor: indexing

This commit is contained in:
cha0s 2024-08-04 20:54:56 -05:00
parent eaec1d0022
commit 16a094806e
2 changed files with 42 additions and 48 deletions

View File

@ -23,18 +23,22 @@ export default class Ecs {
deferredChanges = {}
$$deindexing = new Set();
$$destructionDependencies = new Map();
$$detached = new Set();
diff = {};
Systems = {};
$$entities = {};
$$entityFactory = new EntityFactory();
$$reindexing = new Set();
Systems = {};
constructor({Systems, Components} = {}) {
for (const componentName in Components) {
this.Components[componentName] = new Components[componentName](this);
@ -129,8 +133,8 @@ export default class Ecs {
attach(entityIds) {
for (const entityId of entityIds) {
this.$$detached.delete(entityId);
this.$$reindexing.add(entityId);
}
this.reindex(entityIds);
}
changed(criteria) {
@ -209,6 +213,7 @@ export default class Ecs {
}
}
entityIds.add(entityId);
this.$$reindexing.add(entityId);
this.rebuild(entityId, () => componentNames);
for (const componentName of componentNames) {
if (!creating[componentName]) {
@ -234,7 +239,6 @@ export default class Ecs {
this.markChange(entityId, components);
}
}
this.reindex(entityIds);
return entityIds;
}
@ -301,8 +305,9 @@ export default class Ecs {
destroyMany(entityIds) {
const destroying = {};
this.deindex(entityIds);
// this.deindex(entityIds);
for (const entityId of entityIds) {
this.$$deindexing.add(entityId);
if (!this.$$entities[entityId]) {
throw new Error(`can't destroy non-existent entity ${entityId}`);
}
@ -323,8 +328,8 @@ export default class Ecs {
}
detach(entityIds) {
this.deindex(entityIds);
for (const entityId of entityIds) {
this.$$deindexing.add(entityId);
this.$$detached.add(entityId);
}
}
@ -358,6 +363,7 @@ export default class Ecs {
diff[componentName] = {};
inserting[componentName].push([entityId, components[componentName]]);
}
this.$$reindexing.add(entityId);
unique.add(entityId);
this.markChange(entityId, diff);
}
@ -366,7 +372,6 @@ export default class Ecs {
promises.push(this.Components[componentName].insertMany(inserting[componentName]));
}
await Promise.all(promises);
this.reindex(unique);
}
markChange(entityId, components) {
@ -383,13 +388,7 @@ export default class Ecs {
}
// Created?
else if (!this.diff[entityId]) {
const filtered = {};
for (const componentName in components) {
filtered[componentName] = false === components[componentName]
? false
: components[componentName];
}
this.diff[entityId] = filtered;
this.diff[entityId] = components;
}
// Otherwise, merge.
else {
@ -487,6 +486,7 @@ export default class Ecs {
const removing = {};
const unique = new Set();
for (const [entityId, components] of entities) {
this.$$reindexing.add(entityId);
unique.add(entityId);
const diff = {};
for (const componentName of components) {
@ -502,7 +502,6 @@ export default class Ecs {
for (const componentName in removing) {
this.Components[componentName].destroyMany(removing[componentName]);
}
this.reindex(unique);
}
static serialize(ecs, view) {
@ -523,6 +522,26 @@ export default class Ecs {
}
tick(elapsed) {
// destroy entities
const destroying = new Set();
for (const [entityId, {promises}] of this.$$destructionDependencies) {
if (0 === promises.size) {
destroying.add(entityId);
}
}
if (destroying.size > 0) {
this.destroyMany(destroying);
for (const entityId of destroying) {
this.$$destructionDependencies.get(entityId).resolvers.resolve();
this.$$destructionDependencies.delete(entityId);
}
}
// update indices
this.deindex(this.$$deindexing);
this.$$deindexing.clear();
this.reindex(this.$$reindexing);
this.$$reindexing.clear();
// tick systems
for (const systemName in this.Systems) {
const System = this.Systems[systemName];
if (!System.active) {
@ -538,19 +557,6 @@ export default class Ecs {
System.elapsed -= System.frequency;
}
}
const destroying = new Set();
for (const [entityId, {promises}] of this.$$destructionDependencies) {
if (0 === promises.size) {
destroying.add(entityId);
}
}
if (destroying.size > 0) {
this.destroyMany(destroying);
for (const entityId of destroying) {
this.$$destructionDependencies.get(entityId).resolvers.resolve();
this.$$destructionDependencies.delete(entityId);
}
}
}
toJSON() {
@ -583,6 +589,7 @@ export default class Ecs {
}
updating[componentName].push([entityId, components[componentName]]);
}
this.$$reindexing.add(entityId);
unique.add(entityId);
}
const promises = [];
@ -590,7 +597,6 @@ export default class Ecs {
promises.push(this.Components[componentName].updateMany(updating[componentName]));
}
await Promise.all(promises);
this.reindex(unique);
}
}

View File

@ -2,7 +2,7 @@ export default class Query {
$$criteria = {with: [], without: []};
$$ecs;
$$index = new Set();
$$map = new Map();
constructor(parameters, ecs) {
this.$$ecs = ecs;
@ -20,19 +20,19 @@ export default class Query {
}
get count() {
return this.$$index.size;
return this.$$map.size;
}
deindex(entityIds) {
for (const entityId of entityIds) {
this.$$index.delete(entityId);
this.$$map.delete(entityId);
}
}
reindex(entityIds) {
if (0 === this.$$criteria.with.length && 0 === this.$$criteria.without.length) {
for (const entityId of entityIds) {
this.$$index.add(entityId);
this.$$map.set(entityId, this.$$ecs.get(entityId));
}
return;
}
@ -53,28 +53,16 @@ export default class Query {
}
}
if (should) {
this.$$index.add(entityId);
this.$$map.set(entityId, this.$$ecs.get(entityId));
}
else if (!should) {
this.$$index.delete(entityId);
this.$$map.delete(entityId);
}
}
}
select() {
const it = this.$$index.values();
return {
[Symbol.iterator]() {
return this;
},
next: () => {
const result = it.next();
if (result.done) {
return {done: true, value: undefined};
}
return {done: false, value: this.$$ecs.get(result.value)};
},
};
return this.$$map.values();
}
}