import {EntityPacket} from '@avocado/entity'; export class EntityPacketSynchronizer { constructor() { this.packetsToSynchronize = new Map(); this.trackedEntities = new Map(); } acceptPacket(packet) { if (!(packet instanceof EntityPacket)) { return; } for (let i = 0; i < packet.data.length; i++) { const data = packet.data[i]; const packetEntity = this.trackedEntities.get(data.uuid); if (!packetEntity) { continue; } const Packet = packet.constructor; packetEntity.acceptPacket(new Packet([data])); } } flushPackets(flusher) { const flushed = new Map(); const it = this.packetsToSynchronize.entries(); for (let value = it.next(); !value.done; value = it.next()) { const entity = value.value[0]; const packets = value.value[1]; const mergedPackets = this._mergePackets(packets); flushed.set(entity, mergedPackets); } this.packetsToSynchronize.clear(); return flushed; } _mergePackets(packets) { const mergedPackets = new Map(); for (let i = 0; i < packets.length; i++) { const packet = packets[i]; const Packet = packet.constructor; if (!mergedPackets.has(Packet)) { mergedPackets.set(Packet, packet); } else { mergedPackets.get(Packet).mergeWith(packet); } } return mergedPackets; } _queuePacketFor(entity, packet) { if (!this.packetsToSynchronize.has(entity)) { this.packetsToSynchronize.set(entity, []); } this.packetsToSynchronize.get(entity).push(packet); } trackEntity(entity) { this.trackedEntities.set(entity.instanceUuid, entity); entity.once('destroy', () => { this.trackedEntities.delete(entity.instanceUuid); }); this._watchEntityPackets(entity); } _watchEntityPackets(entity) { const onSendPacket = (packet) => { this._queuePacketFor(entity, packet); }; entity.on('sendPacket', onSendPacket); entity.once('destroy', () => { this.packetsToSynchronize.delete(entity); entity.off('sendPacket', onSendPacket); }); } }