2022-09-15 14:09:10 -05:00
|
|
|
/* eslint-disable react/prefer-stateless-function */
|
2022-09-15 12:51:46 -05:00
|
|
|
import {expect} from 'chai';
|
|
|
|
|
|
|
|
import Component from '../src/component';
|
|
|
|
import Ecs from '../src/ecs';
|
|
|
|
import System from '../src/system';
|
|
|
|
|
|
|
|
class Empty extends Component {}
|
|
|
|
|
|
|
|
class Position extends Component {
|
|
|
|
|
|
|
|
static schema = {
|
|
|
|
x: {type: 'int32', defaultValue: 32},
|
|
|
|
y: 'int32',
|
|
|
|
z: 'int32',
|
|
|
|
};
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
it('can create entities with components', () => {
|
|
|
|
const ecs = new Ecs({Empty, Position});
|
2022-09-15 14:09:10 -05:00
|
|
|
const entity = ecs.create({Empty: {}, Position: {y: 420}});
|
2022-09-15 12:51:46 -05:00
|
|
|
expect(JSON.stringify(ecs.get(entity)))
|
|
|
|
.to.deep.equal(JSON.stringify({Empty: {}, Position: {x: 32, y: 420, z: 0}}));
|
|
|
|
});
|
|
|
|
|
|
|
|
it('can tick systems', () => {
|
|
|
|
class Momentum extends Component {
|
|
|
|
|
|
|
|
static schema = {
|
|
|
|
x: 'int32',
|
|
|
|
y: 'int32',
|
|
|
|
z: 'int32',
|
|
|
|
};
|
|
|
|
|
|
|
|
}
|
|
|
|
const ecs = new Ecs({Momentum, Position});
|
|
|
|
class Physics extends System {
|
|
|
|
|
|
|
|
static queries() {
|
|
|
|
return {
|
|
|
|
default: ['Position', 'Momentum'],
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
tick(elapsed) {
|
|
|
|
expect(elapsed)
|
|
|
|
.to.equal(1);
|
|
|
|
// eslint-disable-next-line no-restricted-syntax
|
|
|
|
for (const [position, momentum] of this.select('default')) {
|
|
|
|
position.x += momentum.x * elapsed;
|
|
|
|
position.y += momentum.y * elapsed;
|
|
|
|
position.z += momentum.z * elapsed;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
ecs.addSystem(Physics);
|
2022-09-15 14:09:10 -05:00
|
|
|
const entity = ecs.create({Momentum: {}, Position: {y: 420}});
|
2022-09-15 12:51:46 -05:00
|
|
|
const position = JSON.stringify(ecs.get(entity).Position);
|
|
|
|
ecs.tick(1);
|
|
|
|
expect(JSON.stringify(ecs.get(entity).Position))
|
|
|
|
.to.deep.equal(position);
|
|
|
|
ecs.get(1).Momentum.y = 30;
|
|
|
|
ecs.tick(1);
|
|
|
|
expect(JSON.stringify(ecs.get(entity).Position))
|
|
|
|
.to.deep.equal(JSON.stringify({x: 32, y: 450, z: 0}));
|
|
|
|
});
|
|
|
|
|
|
|
|
it('can create entities when ticking systems', () => {
|
|
|
|
const ecs = new Ecs();
|
|
|
|
class Spawn extends System {
|
|
|
|
|
|
|
|
tick() {
|
|
|
|
this.createEntity();
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
ecs.addSystem(Spawn);
|
|
|
|
ecs.create();
|
|
|
|
expect(ecs.get(2))
|
|
|
|
.to.be.undefined;
|
|
|
|
ecs.tick(1);
|
|
|
|
expect(ecs.get(2))
|
|
|
|
.to.not.be.undefined;
|
|
|
|
});
|
|
|
|
|
|
|
|
it('can schedule entities to be deleted when ticking systems', () => {
|
|
|
|
const ecs = new Ecs();
|
|
|
|
class Despawn extends System {
|
|
|
|
|
|
|
|
tick() {
|
|
|
|
this.destroyEntity(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
ecs.addSystem(Despawn);
|
|
|
|
ecs.createExact(1);
|
|
|
|
ecs.tick(1);
|
|
|
|
expect(ecs.get(1))
|
|
|
|
.to.not.be.undefined;
|
|
|
|
ecs.tickFinalize();
|
|
|
|
expect(ecs.get(1))
|
|
|
|
.to.be.undefined;
|
|
|
|
});
|
|
|
|
|
|
|
|
it('can encode and decode an ecs', () => {
|
|
|
|
const ecs = new Ecs({Empty, Position});
|
2022-09-15 14:09:10 -05:00
|
|
|
const entity = ecs.create({Empty: {}, Position: {y: 420}});
|
2022-09-15 12:51:46 -05:00
|
|
|
const view = new DataView(new ArrayBuffer(1024));
|
|
|
|
ecs.encode([[entity, true]], view);
|
|
|
|
const newEcs = new Ecs({Empty, Position});
|
|
|
|
newEcs.decode(view);
|
|
|
|
expect(JSON.stringify(newEcs.get(entity)))
|
|
|
|
.to.deep.equal(JSON.stringify(ecs.get(entity)));
|
|
|
|
ecs.setClean();
|
|
|
|
ecs.encode([[entity, true]], view);
|
|
|
|
const newEcs2 = new Ecs({Empty, Position});
|
|
|
|
newEcs2.decode(view);
|
|
|
|
expect(newEcs2.get(entity))
|
|
|
|
.to.be.undefined;
|
|
|
|
ecs.encode([entity], view);
|
|
|
|
newEcs2.decode(view);
|
|
|
|
expect(newEcs2.get(entity))
|
|
|
|
.to.not.be.undefined;
|
|
|
|
});
|