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) { for (const [entity, packets] of this.packetsToSynchronize.entries()) { const mergedPackets = this._mergePackets(packets); flusher(entity, Array.from(mergedPackets.values())); } this.packetsToSynchronize = new Map(); } _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); }); } }