avocado-old/packages/topdown/layer.js

312 lines
7.2 KiB
JavaScript
Raw Normal View History

2019-04-28 23:45:03 -05:00
import {compose, EventEmitter, Property} from '@avocado/core';
2019-09-30 01:36:02 -05:00
import {
Entity,
EntityList,
EntityListUpdateEntityPacket,
} from '@avocado/entity';
2019-04-12 20:16:31 -05:00
import {Vector} from '@avocado/math';
2019-09-30 20:08:05 -05:00
import {
SynchronizedCreatePacket,
SynchronizedDestroyPacket,
} from '@avocado/net';
2019-04-13 13:38:18 -05:00
import {ShapeList} from '@avocado/physics';
2019-03-28 12:31:41 -05:00
2019-09-29 13:19:57 -05:00
import {
LayerUpdateTilesetUriPacket,
} from './packets/layer-update-tileset-uri.packet';
2019-09-30 22:28:33 -05:00
import {
TilesUpdatePacket,
} from './packets/tiles-update.packet';
2019-09-29 13:19:57 -05:00
2019-03-28 12:31:41 -05:00
import {Tiles} from './tiles';
2019-09-19 03:19:24 -05:00
import {Tileset} from './tileset';
2019-03-25 23:39:44 -05:00
2019-03-27 01:52:24 -05:00
const decorate = compose(
EventEmitter,
Property('tilesetUri', {
2019-09-29 13:19:57 -05:00
default: '',
2019-03-27 01:52:24 -05:00
track: true,
}),
2019-04-12 18:49:07 -05:00
Property('tileset', {
track: true,
}),
2019-04-12 20:16:31 -05:00
Property('world', {
track: true,
}),
2019-03-27 01:52:24 -05:00
);
2019-04-16 17:52:56 -05:00
export class Layer extends decorate(class {}) {
2019-03-25 23:39:44 -05:00
2019-05-13 21:07:51 -05:00
constructor(json) {
super();
2019-03-26 17:04:44 -05:00
this.entityList = new EntityList();
2019-05-13 21:07:51 -05:00
this.index = -1;
2019-06-12 22:22:22 -05:00
this.tileEntities = {};
2019-04-12 20:16:31 -05:00
this.tileGeometry = [];
2019-03-27 01:52:24 -05:00
this.tiles = new Tiles();
2019-09-29 13:19:57 -05:00
this._tilesetUriChanged = false;
2019-03-27 01:52:24 -05:00
// Listeners.
2019-04-12 18:58:38 -05:00
this.entityList.on('entityAdded', this.onEntityAddedToLayer, this);
this.entityList.on('entityRemoved', this.onEntityRemovedFromLayer, this);
this.tiles.on('dataChanged', this.onTileDataChanged, this);
2019-04-12 20:16:31 -05:00
this.on('tilesetChanged', this.onTilesetChanged, this);
2019-04-12 18:58:38 -05:00
this.on('tilesetUriChanged', this.onTilesetUriChanged, this);
2019-04-12 20:16:31 -05:00
this.on('worldChanged', this.onWorldChanged, this);
2019-05-13 21:07:51 -05:00
if ('undefined' !== typeof json) {
this.fromJSON(json);
}
}
acceptPacket(packet) {
2019-09-29 13:19:57 -05:00
if (packet instanceof LayerUpdateTilesetUriPacket) {
this.tilesetUri = packet.data;
2019-05-13 21:07:51 -05:00
}
2019-09-30 01:36:02 -05:00
if (packet instanceof EntityListUpdateEntityPacket) {
this.entityList.acceptPacket(packet);
}
2019-09-30 20:08:05 -05:00
// May have to check type...
if (packet instanceof SynchronizedCreatePacket) {
this.entityList.acceptPacket(packet);
}
if (packet instanceof SynchronizedDestroyPacket) {
this.entityList.acceptPacket(packet);
}
2019-09-30 22:28:33 -05:00
if (packet instanceof TilesUpdatePacket) {
this.tiles.acceptPacket(packet);
}
2019-03-27 01:52:24 -05:00
}
addEntity(entity) {
this.entityList.addEntity(entity);
}
2019-06-12 22:22:22 -05:00
addTileEntity(entity, index) {
if (!this.tileEntities[index]) {
this.tileEntities[index] = [];
}
if (-1 !== this.tileEntities[index].indexOf(entity)) {
return;
}
this.tileEntities[index].push(entity);
}
2019-04-12 20:16:31 -05:00
addTileGeometry() {
2019-09-29 13:19:57 -05:00
return false;
2019-04-12 20:16:31 -05:00
const tileset = this.tileset;
if (!tileset) {
return false;
}
const world = this.world;
if (!world) {
return false;
}
2019-04-13 03:40:13 -05:00
const halfTileSize = Vector.scale(tileset.tileSize, 0.5);
2019-04-12 20:16:31 -05:00
this.tiles.forEachTile((tile, x, y, i) => {
const shape = this.tileset.geometry(tile);
if (!shape) {
return;
}
2019-04-13 13:38:18 -05:00
shape.position = Vector.add(
2019-04-12 20:16:31 -05:00
halfTileSize,
Vector.mul([x, y], tileset.tileSize),
);
const body = world.createBody(shape);
body.static = true;
world.addBody(body);
this.tileGeometry.push(body);
2019-04-12 20:16:31 -05:00
});
return true;
}
2019-04-28 22:33:20 -05:00
allEntities() {
return Array.from(this.entityList);
}
2019-09-29 13:19:57 -05:00
cleanPackets() {
this._tilesetUriChanged = false;
2019-09-30 01:36:02 -05:00
this.entityList.cleanPackets();
2019-09-30 22:28:33 -05:00
this.tiles.cleanPackets();
2019-09-29 13:19:57 -05:00
}
2019-03-27 01:52:24 -05:00
destroy() {
this.entityList.destroy();
this.entityList.off('entityAdded', this.onEntityAddedToLayer);
this.entityList.off('entityRemoved', this.onEntityRemovedFromLayer);
2019-04-12 18:49:07 -05:00
this.tiles.off('dataChanged', this.onTileDataChanged);
this.off('tilesetUriChanged', this.onTilesetUriChanged);
if (this.tileset) {
this.tileset.destroy();
}
2019-03-25 23:39:44 -05:00
}
2019-03-27 17:36:57 -05:00
findEntity(uuid) {
return this.entityList.findEntity(uuid);
}
2019-03-25 23:39:44 -05:00
fromJSON(json) {
2019-03-27 01:52:24 -05:00
if (json.entities) {
2019-05-16 23:01:57 -05:00
this.entityList.fromJSON(json.entities);
2019-03-27 01:52:24 -05:00
}
2019-03-25 23:39:44 -05:00
if (json.tiles) {
2019-03-27 01:52:24 -05:00
this.tiles.fromJSON(json.tiles)
2019-03-25 23:39:44 -05:00
}
if (json.tilesetUri) {
this.tilesetUri = json.tilesetUri;
}
return this;
}
2019-06-12 22:22:22 -05:00
hasTileEntityWithUriAt(tilePosition, uri) {
const tileEntities = this.tileEntitiesAt(tilePosition);
if (0 === tileEntities.length) {
return false;
}
const entitiesWithUri = tileEntities.filter((entity) => {
return entity.uri === uri;
});
return entitiesWithUri.length > 0;
}
indexAt(position) {
return this.tiles.indexAt(position);
}
2019-03-27 01:52:24 -05:00
onEntityAddedToLayer(entity) {
entity.setIntoLayer(this);
2019-03-27 01:52:24 -05:00
this.emit('entityAdded', entity)
}
onEntityRemovedFromLayer(entity) {
entity.removeFromLayer();
2019-03-27 01:52:24 -05:00
this.emit('entityRemoved', entity);
}
onTileDataChanged() {
this.emit('tileDataChanged');
}
2019-04-12 20:16:31 -05:00
onTilesetChanged(oldTileset) {
let didChange = false;
if (oldTileset) {
this.removeTileGeometry();
didChange = true;
}
if (this.addTileGeometry()) {
didChange = true;
}
if (didChange) {
this.emit('tileGeometryChanged');
}
}
2019-04-12 18:49:07 -05:00
onTilesetUriChanged() {
2019-09-29 13:19:57 -05:00
this._tilesetUriChanged = true;
2019-04-12 18:49:07 -05:00
if (!this.tilesetUri) {
return;
}
Tileset.load(this.tilesetUri).then((tileset) => {
this.tileset = tileset;
});
}
2019-04-12 20:16:31 -05:00
onWorldChanged(oldWorld) {
let didChange = false;
if (oldWorld) {
this.removeTileGeometry();
didChange = true;
}
if (this.addTileGeometry()) {
didChange = true;
}
if (didChange) {
this.emit('tileGeometryChanged');
}
}
2019-09-29 13:19:57 -05:00
packets(informed) {
2019-05-13 21:07:51 -05:00
const packets = [];
2019-09-29 13:19:57 -05:00
if (this._tilesetUriChanged) {
packets.push(new LayerUpdateTilesetUriPacket(this.tilesetUri));
2019-05-27 21:51:21 -05:00
}
2019-09-30 01:36:02 -05:00
const entityListPackets = this.entityList.packets(informed);
for (let i = 0; i < entityListPackets.length; i++) {
packets.push(entityListPackets[i]);
}
2019-09-30 22:28:33 -05:00
const tilesPackets = this.tiles.packets(informed);
for (let i = 0; i < tilesPackets.length; i++) {
packets.push(tilesPackets[i]);
}
2019-05-13 21:07:51 -05:00
return packets;
}
2019-03-27 01:52:24 -05:00
removeEntity(entity) {
this.entityList.removeEntity(entity);
}
2019-06-12 22:22:22 -05:00
removeTileEntity(entity, index) {
if (!this.tileEntities[index]) {
return;
}
const entityIndex = this.tileEntities[index].indexOf(entity);
if (-1 === entityIndex) {
return;
}
this.tileEntities[index].splice(entityIndex, 1);
}
2019-04-12 20:16:31 -05:00
removeTileGeometry() {
// ... tag geometry in world for removal?
}
2019-05-27 21:51:21 -05:00
setTileAt(position, tile) {
this.tiles.setTileAt(position, tile);
}
tick(elapsed) {
2019-05-13 21:07:51 -05:00
this.entityList.tick(elapsed);
}
2019-05-28 16:51:16 -05:00
tileAt(position) {
return this.tiles.tileAt(position);
}
2019-06-12 22:22:22 -05:00
tileEntitiesAt(tilePosition) {
const index = this.indexAt(tilePosition);
if (!this.tileEntities[index]) {
return [];
}
return this.tileEntities[index];
}
2019-05-13 21:07:51 -05:00
toJSON() {
return {
2019-09-29 13:19:57 -05:00
entities: this.entityList.toJSON(),
2019-05-13 21:07:51 -05:00
tilesetUri: this.tilesetUri,
tiles: this.tiles.toJSON(),
};
}
2019-09-29 13:19:57 -05:00
toNetwork(informed) {
const {areaToInform} = informed;
const visibleEntities = this.visibleEntities(areaToInform);
const visibleEntitiesDiffs = visibleEntities.map((visibleEntity) => {
return visibleEntity.mergeDiff();
});
return {
entities: visibleEntitiesDiffs,
tilesetUri: this.tilesetUri,
tiles: this.tiles.toNetwork(informed),
};
}
2019-03-27 17:39:34 -05:00
visibleEntities(query) {
return this.entityList.visibleEntities(query);
}
2019-06-08 00:23:51 -05:00
visibleEntitiesWithUri(query, uri) {
return this.entityList.visibleEntitiesWithUri(query, uri);
}
2019-03-27 01:52:24 -05:00
}