refactor: actual entity tracking!

This commit is contained in:
cha0s 2019-09-30 20:08:05 -05:00
parent 37028a8bd9
commit d90a345afe
4 changed files with 89 additions and 30 deletions

View File

@ -1,5 +1,9 @@
import {compose, EventEmitter} from '@avocado/core'; import {compose, EventEmitter} from '@avocado/core';
import {QuadTree, Rectangle, Vector} from '@avocado/math'; import {QuadTree, Rectangle, Vector} from '@avocado/math';
import {
SynchronizedCreatePacket,
SynchronizedDestroyPacket,
} from '@avocado/net';
import {EntityListUpdateEntityPacket} from '../packets/entity-list-update-entity.packet'; import {EntityListUpdateEntityPacket} from '../packets/entity-list-update-entity.packet';
import {Entity} from '../entity.synchronized'; import {Entity} from '../entity.synchronized';
@ -14,10 +18,9 @@ export class EntityList extends decorate(class {}) {
super(); super();
this._afterDestructionTickers = []; this._afterDestructionTickers = [];
this._entities = {}; this._entities = {};
this._entitiesJustAdded = [];
this._entitiesJustRemoved = [];
this._entityTickers = [] this._entityTickers = []
this._flatEntities = []; this._flatEntities = [];
this._informedEntities = new Map();
this._quadTree = new QuadTree(); this._quadTree = new QuadTree();
} }
@ -41,6 +44,16 @@ export class EntityList extends decorate(class {}) {
} }
} }
} }
if (packet instanceof SynchronizedCreatePacket) {
const entity = new Entity(packet.data.spec);
this.addEntity(entity);
}
if (packet instanceof SynchronizedDestroyPacket) {
const uuid = packet.data.synchronized.id;
if (this._entities[uuid]) {
this._entities[uuid].destroy();
}
}
} }
addEntity(entity) { addEntity(entity) {
@ -53,7 +66,7 @@ export class EntityList extends decorate(class {}) {
this._flatEntities.push(entity); this._flatEntities.push(entity);
this._entityTickers.push(entity.tick); this._entityTickers.push(entity.tick);
if (AVOCADO_SERVER) { if (AVOCADO_SERVER) {
this._entitiesJustAdded.push(entity); this._informedEntities.set(entity, []);
} }
entity.setIntoList(this); entity.setIntoList(this);
entity.once('destroy', () => { entity.once('destroy', () => {
@ -103,9 +116,20 @@ export class EntityList extends decorate(class {}) {
packets(informed) { packets(informed) {
const packets = []; const packets = [];
// Visible entities.
const {areaToInform} = informed;
const previousVisibleEntities = this._informedEntities.get(informed);
const visibleEntities = this.visibleEntities(areaToInform);
const updates = []; const updates = [];
for (const uuid in this._entities) { for (let i = 0; i < visibleEntities.length; i++) {
const entity = this._entities[uuid]; const entity = visibleEntities[i];
// Newly visible entity.
const index = previousVisibleEntities.indexOf(entity);
if (-1 === index) {
packets.push(entity.createPacket(informed));
}
// Still visible entity.
else {
const entityPackets = entity.packets(informed); const entityPackets = entity.packets(informed);
if (entityPackets.length > 0) { if (entityPackets.length > 0) {
updates.push({ updates.push({
@ -113,7 +137,17 @@ export class EntityList extends decorate(class {}) {
packets: entityPackets, packets: entityPackets,
}); });
} }
previousVisibleEntities.splice(index, 1);
} }
}
for (let i = 0; i < previousVisibleEntities.length; i++) {
const entity = previousVisibleEntities[i];
// Newly removed entity.
if (-1 === visibleEntities.indexOf(entity)) {
packets.push(entity.destroyPacket(informed));
}
}
this._informedEntities.set(informed, visibleEntities);
if (updates.length > 0) { if (updates.length > 0) {
packets.push(new EntityListUpdateEntityPacket(updates)); packets.push(new EntityListUpdateEntityPacket(updates));
} }
@ -130,7 +164,7 @@ export class EntityList extends decorate(class {}) {
return; return;
} }
if (AVOCADO_SERVER) { if (AVOCADO_SERVER) {
this._entitiesJustRemoved.push(entity); this._informedEntities.delete(entity);
} }
entity.removeFromList(); entity.removeFromList();
delete this._entities[uuid]; delete this._entities[uuid];

View File

@ -1,4 +1,4 @@
import {idFromSynchronized, synchronizedFromId} from './registry'; import {idFromSynchronized} from './registry';
import {SynchronizedCreatePacket} from './synchronized-create.packet'; import {SynchronizedCreatePacket} from './synchronized-create.packet';
import {SynchronizedDestroyPacket} from './synchronized-destroy.packet'; import {SynchronizedDestroyPacket} from './synchronized-destroy.packet';
@ -52,28 +52,15 @@ export class ServerSynchronizer {
const payload = []; const payload = [];
for (let i = 0; i < this._synchronizedFlat.length; i++) { for (let i = 0; i < this._synchronizedFlat.length; i++) {
const synchronized = this._synchronizedFlat[i]; const synchronized = this._synchronizedFlat[i];
const id = synchronized.synchronizationId();
const type = idFromSynchronized(synchronized.constructor);
if (-1 !== this._added.indexOf(synchronized)) { if (-1 !== this._added.indexOf(synchronized)) {
const packet = new SynchronizedCreatePacket({ payload.push(synchronized.createPacket(informed));
synchronized: {
id,
type,
},
spec: synchronized.toNetwork(informed),
});
payload.push(packet);
} }
else if (-1 !== this._removed.indexOf(synchronized)) { else if (-1 !== this._removed.indexOf(synchronized)) {
const packet = new SynchronizedDestroyPacket({ payload.push(synchronized.destroyPacket(informed));
synchronized: {
id,
type,
},
});
payload.push(packet);
} }
else { else {
const id = synchronized.synchronizationId();
const type = idFromSynchronized(synchronized.constructor);
const packets = synchronized.packetsFor(informed); const packets = synchronized.packetsFor(informed);
for (let j = 0; j < packets.length; j++) { for (let j = 0; j < packets.length; j++) {
const packet = packets[j]; const packet = packets[j];

View File

@ -1,3 +1,7 @@
import {idFromSynchronized} from './registry';
import {SynchronizedCreatePacket} from './synchronized-create.packet';
import {SynchronizedDestroyPacket} from './synchronized-destroy.packet';
export function SynchronizedMixin(Superclass) { export function SynchronizedMixin(Superclass) {
return class Synchronized extends Superclass { return class Synchronized extends Superclass {
@ -11,8 +15,31 @@ export function SynchronizedMixin(Superclass) {
this._idempotentPackets = []; this._idempotentPackets = [];
} }
createPacket(informed) {
const id = this.synchronizationId();
const type = idFromSynchronized(this.constructor);
return new SynchronizedCreatePacket({
synchronized: {
id,
type,
},
spec: this.toNetwork(informed),
});
}
destroy() {} destroy() {}
destroyPacket(informed) {
const id = this.synchronizationId();
const type = idFromSynchronized(this.constructor);
return new SynchronizedDestroyPacket({
synchronized: {
id,
type,
},
});
}
fromNetwork(json) { fromNetwork(json) {
this.fromJSON(json); this.fromJSON(json);
} }

View File

@ -5,6 +5,10 @@ import {
EntityListUpdateEntityPacket, EntityListUpdateEntityPacket,
} from '@avocado/entity'; } from '@avocado/entity';
import {Vector} from '@avocado/math'; import {Vector} from '@avocado/math';
import {
SynchronizedCreatePacket,
SynchronizedDestroyPacket,
} from '@avocado/net';
import {ShapeList} from '@avocado/physics'; import {ShapeList} from '@avocado/physics';
import { import {
@ -57,6 +61,13 @@ export class Layer extends decorate(class {}) {
if (packet instanceof EntityListUpdateEntityPacket) { if (packet instanceof EntityListUpdateEntityPacket) {
this.entityList.acceptPacket(packet); this.entityList.acceptPacket(packet);
} }
// May have to check type...
if (packet instanceof SynchronizedCreatePacket) {
this.entityList.acceptPacket(packet);
}
if (packet instanceof SynchronizedDestroyPacket) {
this.entityList.acceptPacket(packet);
}
} }
addEntity(entity) { addEntity(entity) {