avocado-old/packages/topdown/room.synchronized.js

236 lines
5.6 KiB
JavaScript
Raw Normal View History

2019-03-26 17:04:52 -05:00
import * as I from 'immutable';
2019-04-28 23:45:03 -05:00
import {compose, EventEmitter, Property} from '@avocado/core';
2019-03-27 23:22:05 -05:00
import {Vector} from '@avocado/math';
2019-09-29 13:19:57 -05:00
import {SynchronizedMixin} from '@avocado/net';
2019-03-27 23:22:05 -05:00
import {RectangleShape} from '@avocado/physics';
2019-05-21 03:08:57 -05:00
import {Resource} from '@avocado/resource';
2019-03-26 17:04:52 -05:00
2019-03-27 01:52:24 -05:00
import {Layers} from './layers';
2019-09-29 13:19:57 -05:00
import {RoomUpdateSizePacket} from './packets/room-update-size.packet';
import {RoomUpdateLayersPacket} from './packets/room-update-layers.packet';
2019-03-27 01:52:24 -05:00
2019-04-26 00:24:13 -05:00
const ROOM_BOUND_SIZE = 64;
const HALF_ROOM_BOUND_SIZE = ROOM_BOUND_SIZE / 2;
2019-03-27 01:52:24 -05:00
const decorate = compose(
EventEmitter,
2019-09-29 13:19:57 -05:00
SynchronizedMixin,
2019-03-27 16:11:37 -05:00
Property('world', {
track: true,
}),
2019-03-27 23:22:05 -05:00
Vector.Mixin('size', 'width', 'height', {
default: [0, 0],
2019-03-28 02:04:29 -05:00
track: true,
2019-04-16 17:52:56 -05:00
}),
2019-03-27 01:52:24 -05:00
);
2019-09-29 13:19:57 -05:00
let synchronizationId = 1;
2019-05-21 03:08:57 -05:00
export class Room extends decorate(Resource) {
2019-03-26 17:04:52 -05:00
2019-05-17 05:49:11 -05:00
constructor(json) {
super();
2019-03-27 23:22:05 -05:00
this.bounds = [];
2019-09-29 13:19:57 -05:00
this._sizeChanged = false;
this._synchronizationId = synchronizationId++;
2019-05-17 05:49:11 -05:00
const layerJSON = 'undefined' !== typeof json ? json.layers : undefined;
this.layers = new Layers(layerJSON);
2019-03-27 01:52:24 -05:00
// Listeners.
2019-04-12 18:58:38 -05:00
this.layers.on('entityAdded', this.onEntityAddedToRoom, this);
this.layers.on('entityRemoved', this.onEntityRemovedFromRoom, this);
2019-04-12 20:16:31 -05:00
this.layers.on('layerAdded', this.onLayerAdded, this);
2019-09-29 13:19:57 -05:00
const allEntities = this.allEntities();
for (let i = 0; i < allEntities.length; i++) {
this.onEntityAddedToRoom(allEntities[i]);
}
2019-04-12 18:58:38 -05:00
this.on('sizeChanged', this.onSizeChanged, this);
this.on('worldChanged', this.onWorldChanged, this);
2019-05-17 05:49:11 -05:00
if ('undefined' !== typeof json && json.size) {
this.size = json.size;
}
2019-03-27 01:52:24 -05:00
}
2019-05-13 21:07:51 -05:00
acceptPacket(packet) {
2019-09-29 13:19:57 -05:00
// Size update.
if (packet instanceof RoomUpdateSizePacket) {
this.size = packet.data.size;
}
// Layer updates.
if (packet instanceof RoomUpdateLayersPacket) {
const {layersPackets} = packet.data;
for (let i = 0; i < layersPackets.length; ++i) {
this.layers.acceptPacket(layersPackets[i]);
}
2019-05-13 21:07:51 -05:00
}
}
2019-03-27 01:52:24 -05:00
addEntityToLayer(entity, layerIndex = 0) {
this.layers.addEntityToLayer(entity, layerIndex);
}
2019-04-28 22:33:20 -05:00
allEntities() {
return this.layers.allEntities();
}
2019-09-29 13:19:57 -05:00
cleanPackets() {
super.cleanPackets();
this._sizeChanged = false;
this.layers.cleanPackets();
}
2019-03-27 01:52:24 -05:00
destroy() {
2019-09-29 13:19:57 -05:00
super.destroy();
2019-03-27 01:52:24 -05:00
this.layers.destroy();
2019-03-27 16:11:37 -05:00
this.layers.off('entityAdded', this.onEntityAddedToRoom);
this.layers.off('entityRemoved', this.onEntityRemovedFromRoom);
this.off('worldChanged', this.onWorldChanged);
2019-03-26 17:04:52 -05:00
}
2019-03-27 17:36:57 -05:00
findEntity(uuid) {
return this.layers.findEntity(uuid);
}
2019-03-26 17:04:52 -05:00
fromJSON(json) {
if (json.layers) {
2019-03-27 01:52:24 -05:00
this.layers.fromJSON(json.layers);
2019-03-26 17:04:52 -05:00
}
2019-03-27 23:22:05 -05:00
if (json.size) {
this.size = json.size;
}
2019-03-26 17:04:52 -05:00
return this;
}
2019-03-27 17:15:53 -05:00
layer(index) {
return this.layers.layer(index);
}
2019-03-27 01:52:24 -05:00
onEntityAddedToRoom(entity) {
2019-05-26 12:03:24 -05:00
entity.setIntoRoom(this);
2019-03-27 01:52:24 -05:00
this.emit('entityAdded', entity)
}
onEntityRemovedFromRoom(entity) {
2019-05-26 12:03:24 -05:00
entity.removeFromRoom();
2019-03-27 01:52:24 -05:00
this.emit('entityRemoved', entity);
}
2019-05-13 21:07:51 -05:00
onLayerAdded(layer) {
2019-04-12 20:16:31 -05:00
layer.world = this.world;
}
2019-03-27 23:22:05 -05:00
onSizeChanged() {
2019-09-29 13:19:57 -05:00
this._sizeChanged = true;
2019-03-27 23:22:05 -05:00
this.updateBounds();
}
2019-03-27 16:11:37 -05:00
onWorldChanged() {
2019-03-27 23:22:05 -05:00
const world = this.world;
2019-09-29 13:19:57 -05:00
for (const {index, layer} of this.layers) {
2019-04-12 20:16:31 -05:00
layer.world = world;
2019-03-27 16:11:37 -05:00
for (const entity of layer.entityList) {
if (entity.is('physical')) {
2019-03-27 23:22:05 -05:00
entity.world = world;
2019-03-27 16:11:37 -05:00
}
}
}
2019-03-27 23:22:05 -05:00
// Update bounds.
this.updateBounds();
2019-03-27 16:11:37 -05:00
}
2019-09-29 13:19:57 -05:00
packets(informed) {
const payload = [];
if (this._sizeChanged) {
payload.push(new RoomUpdateSizePacket({
size: this.size,
}));
2019-05-13 21:07:51 -05:00
}
2019-09-29 13:19:57 -05:00
// Layer updates.
const layersPackets = this.layers.packets(informed);
if (layersPackets.length > 0) {
payload.push(new RoomUpdateLayersPacket({
layersPackets,
}));
2019-05-13 21:07:51 -05:00
}
2019-09-29 13:19:57 -05:00
return payload;
}
packetsAreIdempotent() {
return false;
2019-03-27 01:52:24 -05:00
}
2019-05-13 21:07:51 -05:00
removeEntityFromLayer(entity, layerIndex) {
this.layers.removeEntityFromLayer(entity, layerIndex);
2019-04-07 11:43:50 -05:00
}
2019-09-29 13:19:57 -05:00
synchronizationId() {
return this._synchronizationId;
}
tick(elapsed) {
this.layers.tick(elapsed);
if (this.world) {
this.world.tick(elapsed);
}
}
toNetwork(informed) {
return {
layers: this.layers.toNetwork(informed),
size: this.size,
};
}
toJSON() {
return {
layer: this.layers.toJSON(),
size: this.size,
};
}
2019-03-27 23:22:05 -05:00
updateBounds() {
const world = this.world;
if (!world) {
return;
}
for (const bound of this.bounds) {
world.removeBody(bound);
}
if (Vector.isZero(this.size)) {
return;
}
this.bounds = [
// Top.
world.createBody((new RectangleShape()).fromJSON({
2019-04-26 00:24:13 -05:00
position: [this.width / 2, -HALF_ROOM_BOUND_SIZE],
2019-04-28 22:43:24 -05:00
size: [this.width + ROOM_BOUND_SIZE, ROOM_BOUND_SIZE],
2019-03-27 23:22:05 -05:00
})),
// Right.
world.createBody((new RectangleShape()).fromJSON({
2019-04-26 00:24:13 -05:00
position: [this.width + HALF_ROOM_BOUND_SIZE, this.height / 2],
2019-04-28 22:43:24 -05:00
size: [ROOM_BOUND_SIZE, this.height + ROOM_BOUND_SIZE],
2019-03-27 23:22:05 -05:00
})),
// Bottom.
world.createBody((new RectangleShape()).fromJSON({
2019-04-26 00:24:13 -05:00
position: [this.width / 2, this.height + HALF_ROOM_BOUND_SIZE],
2019-04-28 22:43:24 -05:00
size: [this.width + ROOM_BOUND_SIZE, ROOM_BOUND_SIZE],
2019-03-27 23:22:05 -05:00
})),
// Left.
world.createBody((new RectangleShape()).fromJSON({
2019-04-26 00:24:13 -05:00
position: [-HALF_ROOM_BOUND_SIZE, this.height / 2],
2019-04-28 22:43:24 -05:00
size: [ROOM_BOUND_SIZE, this.height + ROOM_BOUND_SIZE],
2019-03-27 23:22:05 -05:00
})),
];
this.bounds.forEach((bound) => {
bound.static = true;
world.addBody(bound);
});
}
visibleEntities(query) {
return this.layers.visibleEntities(query);
}
2019-03-27 16:11:37 -05:00
}