refactor: lifetimes
This commit is contained in:
parent
8be6c23711
commit
1a7d55f6d3
|
@ -22,6 +22,8 @@ export default class Ecs {
|
||||||
|
|
||||||
deferredChanges = {}
|
deferredChanges = {}
|
||||||
|
|
||||||
|
destroying = new Set();
|
||||||
|
|
||||||
diff = {};
|
diff = {};
|
||||||
|
|
||||||
Systems = {};
|
Systems = {};
|
||||||
|
@ -206,6 +208,10 @@ export default class Ecs {
|
||||||
}
|
}
|
||||||
|
|
||||||
destroy(entityId) {
|
destroy(entityId) {
|
||||||
|
this.destroying.add(entityId);
|
||||||
|
}
|
||||||
|
|
||||||
|
destroyImmediately(entityId) {
|
||||||
this.destroyMany([entityId]);
|
this.destroyMany([entityId]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -427,31 +433,24 @@ export default class Ecs {
|
||||||
}
|
}
|
||||||
|
|
||||||
tick(elapsed) {
|
tick(elapsed) {
|
||||||
const destroying = new Set();
|
|
||||||
for (const systemName in this.Systems) {
|
for (const systemName in this.Systems) {
|
||||||
const System = this.Systems[systemName];
|
const System = this.Systems[systemName];
|
||||||
if (System.active) {
|
if (!System.active) {
|
||||||
if (System.frequency) {
|
continue;
|
||||||
System.elapsed += elapsed;
|
}
|
||||||
if (System.elapsed < System.frequency) {
|
if (!System.frequency) {
|
||||||
continue;
|
System.tick(elapsed);
|
||||||
}
|
continue;
|
||||||
}
|
}
|
||||||
while (!System.frequency || System.elapsed >= System.frequency) {
|
System.elapsed += elapsed;
|
||||||
System.tick(System.frequency ? System.elapsed : elapsed);
|
while (System.elapsed >= System.frequency) {
|
||||||
for (let j = 0; j < System.destroying.length; j++) {
|
System.tick(System.frequency);
|
||||||
destroying.add(System.destroying[j]);
|
System.elapsed -= System.frequency;
|
||||||
}
|
|
||||||
System.tickDestruction();
|
|
||||||
if (!System.frequency) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
System.elapsed -= System.frequency;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (destroying.size > 0) {
|
if (this.destroying.size > 0) {
|
||||||
this.destroyMany(destroying.values());
|
this.destroyMany(this.destroying);
|
||||||
|
this.destroying.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -114,7 +114,7 @@ test('destroys entities', async () => {
|
||||||
expect(ecs.get(entity))
|
expect(ecs.get(entity))
|
||||||
.to.be.undefined;
|
.to.be.undefined;
|
||||||
expect(() => {
|
expect(() => {
|
||||||
ecs.destroy(entity);
|
ecs.destroyImmediately(entity);
|
||||||
})
|
})
|
||||||
.to.throw();
|
.to.throw();
|
||||||
});
|
});
|
||||||
|
@ -170,50 +170,14 @@ test('ticks systems', async () => {
|
||||||
.to.deep.equal(JSON.stringify({y: 128 + 30}));
|
.to.deep.equal(JSON.stringify({y: 128 + 30}));
|
||||||
});
|
});
|
||||||
|
|
||||||
test('creates many entities when ticking systems', () => {
|
|
||||||
const ecs = new Ecs({
|
|
||||||
Systems: {
|
|
||||||
Spawn: class extends System {
|
|
||||||
tick() {
|
|
||||||
this.createManyEntities(Array.from({length: 5}).map(() => []));
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
ecs.system('Spawn').active = true;
|
|
||||||
ecs.create();
|
|
||||||
expect(ecs.get(5))
|
|
||||||
.to.be.undefined;
|
|
||||||
ecs.tick(1);
|
|
||||||
expect(ecs.get(5))
|
|
||||||
.to.not.be.undefined;
|
|
||||||
});
|
|
||||||
|
|
||||||
test('creates entities when ticking systems', () => {
|
|
||||||
const ecs = new Ecs({
|
|
||||||
Systems: {
|
|
||||||
Spawn: class extends System {
|
|
||||||
tick() {
|
|
||||||
this.createEntity();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
ecs.system('Spawn').active = true;
|
|
||||||
ecs.create();
|
|
||||||
expect(ecs.get(2))
|
|
||||||
.to.be.undefined;
|
|
||||||
ecs.tick(1);
|
|
||||||
expect(ecs.get(2))
|
|
||||||
.to.not.be.undefined;
|
|
||||||
});
|
|
||||||
|
|
||||||
test('schedules entities to be deleted when ticking systems', () => {
|
test('schedules entities to be deleted when ticking systems', () => {
|
||||||
const ecs = new Ecs({
|
const ecs = new Ecs({
|
||||||
Systems: {
|
Systems: {
|
||||||
Despawn: class extends System {
|
Despawn: class extends System {
|
||||||
tick() {
|
tick() {
|
||||||
this.destroyEntity(1);
|
this.ecs.destroy(1);
|
||||||
|
expect(ecs.get(1))
|
||||||
|
.to.not.be.undefined;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -225,50 +189,6 @@ test('schedules entities to be deleted when ticking systems', () => {
|
||||||
.to.be.undefined;
|
.to.be.undefined;
|
||||||
});
|
});
|
||||||
|
|
||||||
test('adds components to and remove components from entities when ticking systems', async () => {
|
|
||||||
let promise;
|
|
||||||
const ecs = new Ecs({
|
|
||||||
Components: {Foo: wrapProperties('Foo', {bar: {type: 'uint8'}})},
|
|
||||||
Systems: {
|
|
||||||
AddComponent: class extends System {
|
|
||||||
static queries() {
|
|
||||||
return {
|
|
||||||
default: ['Foo'],
|
|
||||||
};
|
|
||||||
}
|
|
||||||
tick() {
|
|
||||||
promise = this.insertComponents(1, {Foo: {}});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
RemoveComponent: class extends System {
|
|
||||||
static queries() {
|
|
||||||
return {
|
|
||||||
default: ['Foo'],
|
|
||||||
};
|
|
||||||
}
|
|
||||||
tick() {
|
|
||||||
this.removeComponents(1, ['Foo']);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
ecs.system('AddComponent').active = true;
|
|
||||||
ecs.create();
|
|
||||||
ecs.tick(1);
|
|
||||||
await promise;
|
|
||||||
expect(Array.from(ecs.system('AddComponent').select('default')).length)
|
|
||||||
.to.equal(1);
|
|
||||||
expect(ecs.get(1).Foo)
|
|
||||||
.to.not.be.undefined;
|
|
||||||
ecs.system('AddComponent').active = false;
|
|
||||||
ecs.system('RemoveComponent').active = true;
|
|
||||||
ecs.tick(1);
|
|
||||||
expect(Array.from(ecs.system('RemoveComponent').select('default')).length)
|
|
||||||
.to.equal(0);
|
|
||||||
expect(ecs.get(1).Foo)
|
|
||||||
.to.be.undefined;
|
|
||||||
});
|
|
||||||
|
|
||||||
test('generates diffs for entity creation', async () => {
|
test('generates diffs for entity creation', async () => {
|
||||||
const ecs = new Ecs();
|
const ecs = new Ecs();
|
||||||
let entity;
|
let entity;
|
||||||
|
@ -347,7 +267,7 @@ test('generates diffs for deletions', async () => {
|
||||||
let entity;
|
let entity;
|
||||||
entity = await ecs.create();
|
entity = await ecs.create();
|
||||||
ecs.setClean();
|
ecs.setClean();
|
||||||
ecs.destroy(entity);
|
ecs.destroyImmediately(entity);
|
||||||
expect(ecs.diff)
|
expect(ecs.diff)
|
||||||
.to.deep.equal({[entity]: false});
|
.to.deep.equal({[entity]: false});
|
||||||
});
|
});
|
||||||
|
|
|
@ -6,8 +6,6 @@ export default class System {
|
||||||
|
|
||||||
active = false;
|
active = false;
|
||||||
|
|
||||||
destroying = [];
|
|
||||||
|
|
||||||
ecs;
|
ecs;
|
||||||
|
|
||||||
elapsed = 0;
|
elapsed = 0;
|
||||||
|
@ -25,38 +23,12 @@ export default class System {
|
||||||
this.reindex(ecs.entities);
|
this.reindex(ecs.entities);
|
||||||
}
|
}
|
||||||
|
|
||||||
createEntity(components) {
|
|
||||||
return this.ecs.create(components);
|
|
||||||
}
|
|
||||||
|
|
||||||
createManyEntities(componentsList) {
|
|
||||||
return this.ecs.createMany(componentsList);
|
|
||||||
}
|
|
||||||
|
|
||||||
deindex(entityIds) {
|
deindex(entityIds) {
|
||||||
for (const i in this.queries) {
|
for (const i in this.queries) {
|
||||||
this.queries[i].deindex(entityIds);
|
this.queries[i].deindex(entityIds);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
destroyEntity(entityId) {
|
|
||||||
this.destroyManyEntities([entityId]);
|
|
||||||
}
|
|
||||||
|
|
||||||
destroyManyEntities(entityIds) {
|
|
||||||
for (let i = 0; i < entityIds.length; i++) {
|
|
||||||
this.destroying.push(entityIds[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async insertComponents(entityId, components) {
|
|
||||||
return this.ecs.insert(entityId, components);
|
|
||||||
}
|
|
||||||
|
|
||||||
async insertManyComponents(components) {
|
|
||||||
return this.ecs.insertMany(components);
|
|
||||||
}
|
|
||||||
|
|
||||||
static get priority() {
|
static get priority() {
|
||||||
return {
|
return {
|
||||||
phase: 'normal',
|
phase: 'normal',
|
||||||
|
@ -73,14 +45,6 @@ export default class System {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
removeComponents(entityId, components) {
|
|
||||||
this.ecs.remove(entityId, components);
|
|
||||||
}
|
|
||||||
|
|
||||||
removeManyComponents(entityIds) {
|
|
||||||
this.ecs.removeMany(entityIds);
|
|
||||||
}
|
|
||||||
|
|
||||||
select(query) {
|
select(query) {
|
||||||
return this.queries[query].select();
|
return this.queries[query].select();
|
||||||
}
|
}
|
||||||
|
@ -117,13 +81,6 @@ export default class System {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
tickDestruction() {
|
|
||||||
if (this.destroying.length > 0) {
|
|
||||||
this.deindex(this.destroying);
|
|
||||||
}
|
|
||||||
this.destroying = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
tick() {}
|
tick() {}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -322,6 +322,7 @@ export default class Engine {
|
||||||
stop() {
|
stop() {
|
||||||
clearTimeout(this.handle);
|
clearTimeout(this.handle);
|
||||||
this.handle = undefined;
|
this.handle = undefined;
|
||||||
|
this.tick(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
tick(elapsed) {
|
tick(elapsed) {
|
||||||
|
|
|
@ -45,8 +45,8 @@ const engine = new Engine(WorkerServer);
|
||||||
|
|
||||||
onmessage = async (event) => {
|
onmessage = async (event) => {
|
||||||
if (0 === event.data) {
|
if (0 === event.data) {
|
||||||
engine.stop();
|
|
||||||
await engine.disconnectPlayer(0);
|
await engine.disconnectPlayer(0);
|
||||||
|
engine.stop();
|
||||||
await engine.saveEcses();
|
await engine.saveEcses();
|
||||||
postMessage(0);
|
postMessage(0);
|
||||||
return;
|
return;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user