refactor: private vars
This commit is contained in:
parent
6950bbd123
commit
85d239eb4c
|
@ -12,6 +12,12 @@ const decorate = compose(
|
|||
|
||||
export default class Directional extends decorate(Trait) {
|
||||
|
||||
acceptPacket(packet) {
|
||||
if ('TraitUpdateDirectionalDirection' === packet.constructor.type) {
|
||||
this.entity.direction = packet.data;
|
||||
}
|
||||
}
|
||||
|
||||
static defaultParams() {
|
||||
return {
|
||||
directionCount: 1,
|
||||
|
@ -57,15 +63,17 @@ export default class Directional extends decorate(Trait) {
|
|||
};
|
||||
}
|
||||
|
||||
constructor(...args) {
|
||||
super(...args);
|
||||
this.directionCount = this.params.directionCount;
|
||||
}
|
||||
|
||||
acceptPacket(packet) {
|
||||
if ('TraitUpdateDirectionalDirection' === packet.constructor.type) {
|
||||
this.entity.direction = packet.data;
|
||||
listeners() {
|
||||
const listeners = {};
|
||||
if (this.params.trackMovement) {
|
||||
listeners.movementRequest = (vector) => {
|
||||
if (Vector.isZero(vector)) {
|
||||
return;
|
||||
}
|
||||
this.entity.direction = Vector.toDirection(vector, this.params.directionCount);
|
||||
};
|
||||
}
|
||||
return listeners;
|
||||
}
|
||||
|
||||
packets() {
|
||||
|
@ -79,17 +87,4 @@ export default class Directional extends decorate(Trait) {
|
|||
return undefined;
|
||||
}
|
||||
|
||||
listeners() {
|
||||
const listeners = {};
|
||||
if (this.params.trackMovement) {
|
||||
listeners.movementRequest = (vector) => {
|
||||
if (Vector.isZero(vector)) {
|
||||
return;
|
||||
}
|
||||
this.entity.direction = Vector.toDirection(vector, this.directionCount);
|
||||
};
|
||||
}
|
||||
return listeners;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -10,6 +10,13 @@ const decorate = compose(
|
|||
|
||||
export default class Existent extends decorate(Trait) {
|
||||
|
||||
#isDestroying;
|
||||
|
||||
constructor(...args) {
|
||||
super(...args);
|
||||
this.#isDestroying = false;
|
||||
}
|
||||
|
||||
static behaviorTypes() {
|
||||
return {
|
||||
destroy: {
|
||||
|
@ -58,19 +65,14 @@ export default class Existent extends decorate(Trait) {
|
|||
};
|
||||
}
|
||||
|
||||
constructor(...args) {
|
||||
super(...args);
|
||||
this._isDestroying = false;
|
||||
}
|
||||
|
||||
methods() {
|
||||
return {
|
||||
|
||||
destroy: async () => {
|
||||
if (this._isDestroying) {
|
||||
if (this.#isDestroying) {
|
||||
return;
|
||||
}
|
||||
this._isDestroying = true;
|
||||
this.#isDestroying = true;
|
||||
this.entity.isTicking = false;
|
||||
this.entity.emit('destroy');
|
||||
this.entity.emit('destroyed');
|
||||
|
|
|
@ -7,6 +7,38 @@ const {
|
|||
|
||||
export default class Listed extends Trait {
|
||||
|
||||
#quadTreeAabb;
|
||||
|
||||
#quadTreeNodes;
|
||||
|
||||
constructor(...args) {
|
||||
super(...args);
|
||||
this.entity.list = null;
|
||||
this.#quadTreeAabb = [];
|
||||
this.#quadTreeNodes = [];
|
||||
}
|
||||
|
||||
addQuadTreeNodes() {
|
||||
const {list} = this.entity;
|
||||
if (!list) {
|
||||
return;
|
||||
}
|
||||
const aabb = this.entity.visibleAabb;
|
||||
if (Rectangle.isNull(aabb)) {
|
||||
return;
|
||||
}
|
||||
// Expand the AABB so we don't have to update it every single tick.
|
||||
const expandedAabb = Rectangle.expand(aabb, [32, 32]);
|
||||
this.#quadTreeAabb = expandedAabb;
|
||||
const points = Rectangle.toPoints(expandedAabb);
|
||||
this.#quadTreeNodes = points.map((point) => [...point, this.entity, aabb]);
|
||||
// Add points to quad tree.
|
||||
const {quadTree} = list;
|
||||
for (let i = 0; i < this.#quadTreeNodes.length; i++) {
|
||||
quadTree.add(this.#quadTreeNodes[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static behaviorTypes() {
|
||||
return {
|
||||
detachFromList: {
|
||||
|
@ -25,67 +57,10 @@ export default class Listed extends Trait {
|
|||
};
|
||||
}
|
||||
|
||||
constructor(...args) {
|
||||
super(...args);
|
||||
this.entity.list = null;
|
||||
this.quadTreeAabb = [];
|
||||
this.quadTreeNodes = [];
|
||||
}
|
||||
|
||||
destroy() {
|
||||
this.entity.detachFromList();
|
||||
}
|
||||
|
||||
addQuadTreeNodes() {
|
||||
const {list} = this.entity;
|
||||
if (!list) {
|
||||
return;
|
||||
}
|
||||
const aabb = this.entity.visibleAabb;
|
||||
if (Rectangle.isNull(aabb)) {
|
||||
return;
|
||||
}
|
||||
// Expand the AABB so we don't have to update it every single tick.
|
||||
const expandedAabb = Rectangle.expand(aabb, [32, 32]);
|
||||
this.quadTreeAabb = expandedAabb;
|
||||
const points = Rectangle.toPoints(expandedAabb);
|
||||
this.quadTreeNodes = points.map((point) => [...point, this.entity, aabb]);
|
||||
// Add points to quad tree.
|
||||
const {quadTree} = list;
|
||||
for (let i = 0; i < this.quadTreeNodes.length; i++) {
|
||||
quadTree.add(this.quadTreeNodes[i]);
|
||||
}
|
||||
}
|
||||
|
||||
removeQuadTreeNodes() {
|
||||
const {list} = this.entity;
|
||||
if (!list) {
|
||||
return;
|
||||
}
|
||||
if (this.quadTreeNodes.length > 0) {
|
||||
const {quadTree} = list;
|
||||
for (let i = 0; i < this.quadTreeNodes.length; i++) {
|
||||
quadTree.remove(this.quadTreeNodes[i]);
|
||||
}
|
||||
this.quadTreeAabb = [];
|
||||
this.quadTreeNodes = [];
|
||||
}
|
||||
}
|
||||
|
||||
resetQuadTreeNodes() {
|
||||
if ('client' !== SIDE) {
|
||||
const aabb = this.entity.visibleAabb;
|
||||
if (
|
||||
this.quadTreeAabb.length > 0
|
||||
&& Rectangle.isInside(this.quadTreeAabb, aabb)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
this.removeQuadTreeNodes();
|
||||
this.addQuadTreeNodes();
|
||||
}
|
||||
}
|
||||
|
||||
listeners() {
|
||||
return {
|
||||
|
||||
|
@ -122,4 +97,33 @@ export default class Listed extends Trait {
|
|||
};
|
||||
}
|
||||
|
||||
removeQuadTreeNodes() {
|
||||
const {list} = this.entity;
|
||||
if (!list) {
|
||||
return;
|
||||
}
|
||||
if (this.#quadTreeNodes.length > 0) {
|
||||
const {quadTree} = list;
|
||||
for (let i = 0; i < this.#quadTreeNodes.length; i++) {
|
||||
quadTree.remove(this.#quadTreeNodes[i]);
|
||||
}
|
||||
this.#quadTreeAabb = [];
|
||||
this.#quadTreeNodes = [];
|
||||
}
|
||||
}
|
||||
|
||||
resetQuadTreeNodes() {
|
||||
if ('client' !== SIDE) {
|
||||
const aabb = this.entity.visibleAabb;
|
||||
if (
|
||||
this.#quadTreeAabb.length > 0
|
||||
&& Rectangle.isInside(this.#quadTreeAabb, aabb)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
this.removeQuadTreeNodes();
|
||||
this.addQuadTreeNodes();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -10,6 +10,13 @@ const decorate = compose(
|
|||
|
||||
export default class Mobile extends decorate(Trait) {
|
||||
|
||||
#appliedMovement;
|
||||
|
||||
constructor(...args) {
|
||||
super(...args);
|
||||
this.#appliedMovement = [0, 0];
|
||||
}
|
||||
|
||||
static behaviorTypes() {
|
||||
return {
|
||||
moveFor: {
|
||||
|
@ -74,11 +81,6 @@ export default class Mobile extends decorate(Trait) {
|
|||
};
|
||||
}
|
||||
|
||||
constructor(...args) {
|
||||
super(...args);
|
||||
this.appliedMovement = [0, 0];
|
||||
}
|
||||
|
||||
methods() {
|
||||
return {
|
||||
|
||||
|
@ -102,7 +104,7 @@ export default class Mobile extends decorate(Trait) {
|
|||
},
|
||||
|
||||
applyMovement: (vector) => {
|
||||
this.appliedMovement = Vector.add(this.appliedMovement, vector);
|
||||
this.#appliedMovement = Vector.add(this.#appliedMovement, vector);
|
||||
},
|
||||
|
||||
forceMovement: (movement) => {
|
||||
|
@ -118,27 +120,27 @@ export default class Mobile extends decorate(Trait) {
|
|||
Vector.normalize(vector),
|
||||
this.speed,
|
||||
));
|
||||
this.entity.emit('movementRequest', this.appliedMovement);
|
||||
this.entity.emit('movementRequest', this.#appliedMovement);
|
||||
},
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
tick(elapsed) {
|
||||
if (Vector.isZero(this.appliedMovement)) {
|
||||
if (Vector.isZero(this.#appliedMovement)) {
|
||||
return;
|
||||
}
|
||||
if (this.entity.is('physical')) {
|
||||
this.entity.applyImpulse(this.appliedMovement);
|
||||
this.entity.applyImpulse(this.#appliedMovement);
|
||||
}
|
||||
else {
|
||||
const appliedMovement = Vector.scale(
|
||||
this.appliedMovement,
|
||||
this.#appliedMovement,
|
||||
elapsed,
|
||||
);
|
||||
this.entity.forceMovement(appliedMovement);
|
||||
}
|
||||
this.appliedMovement = [0, 0];
|
||||
this.#appliedMovement = [0, 0];
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -6,6 +6,13 @@ const decorate = compose(
|
|||
|
||||
export default class Perishable extends decorate(Trait) {
|
||||
|
||||
#ttl;
|
||||
|
||||
constructor(...args) {
|
||||
super(...args);
|
||||
this.#ttl = this.params.ttl;
|
||||
}
|
||||
|
||||
static defaultParams() {
|
||||
return {
|
||||
ttl: 300,
|
||||
|
@ -21,14 +28,9 @@ export default class Perishable extends decorate(Trait) {
|
|||
};
|
||||
}
|
||||
|
||||
constructor(...args) {
|
||||
super(...args);
|
||||
this.ttl = this.params.ttl;
|
||||
}
|
||||
|
||||
tick(elapsed) {
|
||||
this.ttl -= elapsed;
|
||||
if (this.ttl <= 0) {
|
||||
this.#ttl -= elapsed;
|
||||
if (this.#ttl <= 0) {
|
||||
this.entity.destroy();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ const {
|
|||
|
||||
const decorate = compose(
|
||||
EventEmitter,
|
||||
Vector.Mixin('_position', 'x', 'y', {
|
||||
Vector.Mixin('trackedPosition', 'x', 'y', {
|
||||
track: true,
|
||||
}),
|
||||
Vector.Mixin('serverPosition', 'serverX', 'serverY', {
|
||||
|
@ -21,13 +21,13 @@ export default class Positioned extends decorate(Trait) {
|
|||
|
||||
constructor(...args) {
|
||||
super(...args);
|
||||
this.on('_positionChanged', this.on_positionChanged, this);
|
||||
this.on('trackedPositionChanged', this.onTrackedPositionChanged, this);
|
||||
const {x, y} = this.state;
|
||||
this._position = [x, y];
|
||||
this.trackedPosition = [x, y];
|
||||
this.entity.position[0] = x;
|
||||
this.entity.position[1] = y;
|
||||
if ('client' === SIDE) {
|
||||
this.serverPosition = this._position;
|
||||
this.serverPosition = this.trackedPosition;
|
||||
this.serverPositionDirty = false;
|
||||
this.on('serverPositionChanged', this.onServerPositionChanged, this);
|
||||
}
|
||||
|
@ -78,14 +78,14 @@ export default class Positioned extends decorate(Trait) {
|
|||
}
|
||||
|
||||
destroy() {
|
||||
this.off('_positionChanged', this.on_positionChanged);
|
||||
this.off('trackedPositionChanged', this.ontrackedPositionChanged);
|
||||
if ('client' === SIDE) {
|
||||
this.off('serverPositionChanged', this.onServerPositionChanged);
|
||||
}
|
||||
}
|
||||
|
||||
// eslint-disable-next-line camelcase
|
||||
on_positionChanged(oldPosition, newPosition) {
|
||||
onTrackedPositionChanged(oldPosition, newPosition) {
|
||||
[this.entity.position[0], this.entity.position[1]] = newPosition;
|
||||
if ('client' !== SIDE) {
|
||||
[this.state.x, this.state.y] = newPosition;
|
||||
|
@ -115,7 +115,7 @@ export default class Positioned extends decorate(Trait) {
|
|||
isTickingChanged: () => {
|
||||
// Snap position on ticking change.
|
||||
if ('client' === SIDE) {
|
||||
this._position = this.serverPosition;
|
||||
this.trackedPosition = this.serverPosition;
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -126,7 +126,7 @@ export default class Positioned extends decorate(Trait) {
|
|||
return {
|
||||
|
||||
setPosition: (position) => {
|
||||
this._position = position;
|
||||
this.trackedPosition = position;
|
||||
},
|
||||
|
||||
};
|
||||
|
@ -136,18 +136,18 @@ export default class Positioned extends decorate(Trait) {
|
|||
if (!this.serverPositionDirty) {
|
||||
return;
|
||||
}
|
||||
if (Vector.equals(this._position, this.serverPosition)) {
|
||||
if (Vector.equals(this.trackedPosition, this.serverPosition)) {
|
||||
this.serverPositionDirty = false;
|
||||
return;
|
||||
}
|
||||
if (Vector.equalsClose(this._position, this.serverPosition, 0.1)) {
|
||||
this._position = this.serverPosition;
|
||||
if (Vector.equalsClose(this.trackedPosition, this.serverPosition, 0.1)) {
|
||||
this.trackedPosition = this.serverPosition;
|
||||
this.serverPositionDirty = false;
|
||||
return;
|
||||
}
|
||||
const diff = Vector.sub(this.serverPosition, this._position);
|
||||
const diff = Vector.sub(this.serverPosition, this.trackedPosition);
|
||||
const lerp = 0.5;
|
||||
this._position = Vector.add(this._position, Vector.scale(diff, lerp));
|
||||
this.trackedPosition = Vector.add(this.trackedPosition, Vector.scale(diff, lerp));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -12,6 +12,19 @@ const decorate = compose(
|
|||
|
||||
export default (latus) => class Spawner extends decorate(Trait) {
|
||||
|
||||
#children;
|
||||
|
||||
#childrenListeners;
|
||||
|
||||
#spawnJSONs;
|
||||
|
||||
constructor(...args) {
|
||||
super(...args);
|
||||
this.#children = [];
|
||||
this.#childrenListeners = new Map();
|
||||
this.#spawnJSONs = this.params.spawns;
|
||||
}
|
||||
|
||||
static behaviorTypes() {
|
||||
return {
|
||||
killAllChildren: {
|
||||
|
@ -110,28 +123,21 @@ export default (latus) => class Spawner extends decorate(Trait) {
|
|||
};
|
||||
}
|
||||
|
||||
static optionsForSpawn(entity) {
|
||||
if (!entity) {
|
||||
return undefined;
|
||||
}
|
||||
return Object.keys(entity.traitInstance('spawner').params.spawns)
|
||||
.reduce((r, key) => ({...r, [key]: key}), {});
|
||||
}
|
||||
|
||||
destroy() {
|
||||
while (this.children.length > 0) {
|
||||
const child = this.children.pop();
|
||||
while (this.#children.length > 0) {
|
||||
const child = this.#children.pop();
|
||||
if (child) {
|
||||
this.removeChild(child);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
constructor(...args) {
|
||||
super(...args);
|
||||
this.children = [];
|
||||
this.childrenListeners = new Map();
|
||||
this.spawnJSONs = this.params.spawns;
|
||||
static optionsForSpawn(entity) {
|
||||
if (!entity) {
|
||||
return undefined;
|
||||
}
|
||||
return Object.keys(entity.traitInstance('spawner').params.spawns)
|
||||
.reduce((r, key) => ({...r, [key]: key}), {});
|
||||
}
|
||||
|
||||
// eslint-disable-next-line class-methods-use-this
|
||||
|
@ -171,26 +177,6 @@ export default (latus) => class Spawner extends decorate(Trait) {
|
|||
return undefined;
|
||||
}
|
||||
|
||||
maySpawn() {
|
||||
if (this.maxSpawns <= this.children.length) {
|
||||
return false;
|
||||
}
|
||||
if (!this.destinationEntityList()) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
removeChild(child) {
|
||||
const index = this.children.indexOf(child);
|
||||
if (-1 !== index) {
|
||||
this.children.splice(index, 1);
|
||||
const listener = this.childrenListeners.get(child);
|
||||
child.off('destroy', listener);
|
||||
this.childrenListeners.delete(child);
|
||||
}
|
||||
}
|
||||
|
||||
listeners() {
|
||||
return {
|
||||
|
||||
|
@ -201,12 +187,22 @@ export default (latus) => class Spawner extends decorate(Trait) {
|
|||
};
|
||||
}
|
||||
|
||||
maySpawn() {
|
||||
if (this.maxSpawns <= this.#children.length) {
|
||||
return false;
|
||||
}
|
||||
if (!this.destinationEntityList()) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
methods() {
|
||||
return {
|
||||
|
||||
killAllChildren: () => {
|
||||
// Juggle children since this may cause splices and mess up the array.
|
||||
const children = this.children.slice(0);
|
||||
const children = this.#children.slice(0);
|
||||
for (let i = 0; i < children.length; i++) {
|
||||
children[i].destroyGently();
|
||||
}
|
||||
|
@ -216,7 +212,7 @@ export default (latus) => class Spawner extends decorate(Trait) {
|
|||
if (!this.maySpawn()) {
|
||||
return undefined;
|
||||
}
|
||||
const spawnJSON = this.spawnJSONs[key];
|
||||
const spawnJSON = this.#spawnJSONs[key];
|
||||
if (!spawnJSON) {
|
||||
return undefined;
|
||||
}
|
||||
|
@ -240,15 +236,15 @@ export default (latus) => class Spawner extends decorate(Trait) {
|
|||
return undefined;
|
||||
}
|
||||
// Add null to children to prevent race.
|
||||
const childIndex = this.children.length;
|
||||
this.children.push(null);
|
||||
const childIndex = this.#children.length;
|
||||
this.#children.push(null);
|
||||
const list = this.destinationEntityList();
|
||||
const {fromResourceType: {Entity}} = resource(latus);
|
||||
const child = await Entity.load(json);
|
||||
this.children[childIndex] = child;
|
||||
this.#children[childIndex] = child;
|
||||
// Listen for destroy event.
|
||||
const listener = this.removeChild.bind(this, child);
|
||||
this.childrenListeners.set(child, listener);
|
||||
this.#childrenListeners.set(child, listener);
|
||||
child.once('destroy', listener);
|
||||
// Add child to list.
|
||||
list.addEntity(child);
|
||||
|
@ -264,4 +260,14 @@ export default (latus) => class Spawner extends decorate(Trait) {
|
|||
};
|
||||
}
|
||||
|
||||
removeChild(child) {
|
||||
const index = this.#children.indexOf(child);
|
||||
if (-1 !== index) {
|
||||
this.#children.splice(index, 1);
|
||||
const listener = this.#childrenListeners.get(child);
|
||||
child.off('destroy', listener);
|
||||
this.#childrenListeners.delete(child);
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
|
|
@ -43,15 +43,6 @@ describe(name, () => {
|
|||
entity.tick(1);
|
||||
expect(entity.position).to.deep.equal([100, 0]);
|
||||
});
|
||||
it('can apply movement', async () => {
|
||||
const trait = entity.traitInstance('Mobile');
|
||||
entity.applyMovement([10, 0]);
|
||||
expect(trait.appliedMovement).to.deep.equal([10, 0]);
|
||||
entity.applyMovement([10, 0]);
|
||||
expect(trait.appliedMovement).to.deep.equal([20, 0]);
|
||||
entity.tick(0);
|
||||
expect(trait.appliedMovement).to.deep.equal([0, 0]);
|
||||
});
|
||||
it('can force movement', async () => {
|
||||
expect(entity.speed).to.equal(0);
|
||||
entity.forceMovement([10, 0]);
|
||||
|
|
Loading…
Reference in New Issue
Block a user