refactor: private vars

This commit is contained in:
cha0s 2021-01-03 22:03:32 -06:00
parent 6950bbd123
commit 85d239eb4c
8 changed files with 168 additions and 166 deletions

View File

@ -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;
}
}

View File

@ -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');

View File

@ -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();
}
}
}

View File

@ -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];
}
}

View File

@ -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();
}
}

View File

@ -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));
}
}

View File

@ -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);
}
}
};

View File

@ -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]);