refactor: safety first

This commit is contained in:
cha0s 2024-07-26 11:36:32 -05:00
parent 5ff4eb2991
commit 091e19c7de
4 changed files with 37 additions and 29 deletions

View File

@ -44,13 +44,13 @@ export default class Ecs {
addDestructionDependency(id, promise) {
if (!this.$$destructionDependencies.has(id)) {
this.$$destructionDependencies.set(id, new Set())
this.$$destructionDependencies.set(id, {promises: new Set()})
}
const dependencies = this.$$destructionDependencies.get(id);
dependencies.add(promise);
const {promises} = this.$$destructionDependencies.get(id);
promises.add(promise);
promise.then(() => {
dependencies.delete(promise);
if (0 === dependencies.size) {
promises.delete(promise);
if (!this.$$destructionDependencies.get(id)?.resolvers) {
this.$$destructionDependencies.delete(id);
}
});
@ -228,13 +228,13 @@ export default class Ecs {
destroy(entityId) {
if (!this.$$destructionDependencies.has(entityId)) {
this.$$destructionDependencies.set(entityId, new Set())
this.$$destructionDependencies.set(entityId, {promises: new Set()});
}
this.$$destructionDependencies.get(entityId).add(0);
}
destroyImmediately(entityId) {
this.destroyMany([entityId]);
const dependencies = this.$$destructionDependencies.get(entityId);
if (!dependencies.resolvers) {
dependencies.resolvers = withResolvers();
}
return dependencies.resolvers.promise;
}
destroyAll() {
@ -462,15 +462,16 @@ export default class Ecs {
}
}
const destroying = new Set();
for (const [id, dependencies] of this.$$destructionDependencies) {
if (1 === dependencies.size && dependencies.has(0)) {
destroying.add(id);
for (const [entityId, {promises, resolvers}] of this.$$destructionDependencies) {
if (0 === promises.size && resolvers) {
destroying.add(entityId);
}
}
if (destroying.size > 0) {
this.destroyMany(destroying);
for (const id of destroying) {
this.$$destructionDependencies.delete(id);
for (const entityId of destroying) {
this.$$destructionDependencies.get(entityId).resolvers.resolve();
this.$$destructionDependencies.delete(entityId);
}
}
}

View File

@ -114,7 +114,7 @@ test('destroys entities', async () => {
expect(ecs.get(entity))
.to.be.undefined;
expect(() => {
ecs.destroyImmediately(entity);
ecs.destroyMany([entity]);
})
.to.throw();
});
@ -275,7 +275,8 @@ test('generates diffs for deletions', async () => {
let entity;
entity = await ecs.create();
ecs.setClean();
ecs.destroyImmediately(entity);
ecs.destroy(entity);
ecs.tick(0);
expect(ecs.diff)
.to.deep.equal({[entity]: false});
});

View File

@ -89,15 +89,18 @@ export default class Engine {
Ecs: {path},
...updates,
};
// remove from old ECS
this.destroyImmediately(entity.id);
const promises = [];
// load if necessary
if (!engine.ecses[path]) {
await engine.loadEcs(path);
promises.push(engine.loadEcs(path));
}
// recreate the entity in the new ECS and again associate it with the connection
connectedPlayer.entity = engine.ecses[path].get(await engine.ecses[path].create(dumped));
connectedPlayer.entity.Player.id = id
// remove from old ECS
promises.push(this.destroy(entity.id));
Promise.all(promises).then(async () => {
// recreate the entity in the new ECS and again associate it with the connection
connectedPlayer.entity = engine.ecses[path].get(await engine.ecses[path].create(dumped));
connectedPlayer.entity.Player.id = id
});
}
}
}
@ -255,12 +258,15 @@ export default class Engine {
if (!connectedPlayer) {
return;
}
const {entity, id} = connectedPlayer;
const ecs = this.ecses[entity.Ecs.path];
await this.savePlayer(id, entity);
ecs.destroyImmediately(entity.id);
this.connectedPlayers.delete(connection);
this.incomingActions.delete(connection);
const {entity, id} = connectedPlayer;
const json = entity.toJSON();
const ecs = this.ecses[entity.Ecs.path];
return Promise.all([
ecs.destroy(entity.id),
this.savePlayer(id, json),
]);
}
async load() {

View File

@ -67,8 +67,8 @@ if (import.meta.hot) {
const before = withResolvers();
const promises = [before.promise];
import.meta.hot.on('vite:beforeUpdate', async () => {
engine.stop();
await engine.disconnectPlayer(0);
engine.stop();
await engine.saveEcses();
before.resolve();
});