broadcaster->broadcastPackets($recipients, [$packet]); } public function syncAttributes(array $recipients, Living $entity, array $attributes) : void{ if(count($attributes) > 0){ $this->sendDataPacket($recipients, UpdateAttributesPacket::create( $entity->getId(), array_map(fn(Attribute $attr) => new NetworkAttribute($attr->getId(), $attr->getMinValue(), $attr->getMaxValue(), $attr->getValue(), $attr->getDefaultValue(), []), $attributes), 0 )); } } public function syncActorData(array $recipients, Entity $entity, array $properties) : void{ //TODO: HACK! as of 1.18.10, the client responds differently to the same data ordered in different orders - for //example, sending HEIGHT in the list before FLAGS when unsetting the SWIMMING flag results in a hitbox glitch ksort($properties, SORT_NUMERIC); $this->sendDataPacket($recipients, SetActorDataPacket::create($entity->getId(), $properties, new PropertySyncData([], []), 0)); } public function onEntityEffectAdded(array $recipients, Living $entity, EffectInstance $effect, bool $replacesOldEffect) : void{ //TODO: we may need yet another effect <=> ID map in the future depending on protocol changes $this->sendDataPacket($recipients, MobEffectPacket::add( $entity->getId(), $replacesOldEffect, EffectIdMap::getInstance()->toId($effect->getType()), $effect->getAmplifier(), $effect->isVisible(), $effect->getDuration() )); } public function onEntityEffectRemoved(array $recipients, Living $entity, EffectInstance $effect) : void{ $this->sendDataPacket($recipients, MobEffectPacket::remove($entity->getId(), EffectIdMap::getInstance()->toId($effect->getType()))); } public function onEntityRemoved(array $recipients, Entity $entity) : void{ $this->sendDataPacket($recipients, RemoveActorPacket::create($entity->getId())); } public function onMobMainHandItemChange(array $recipients, Human $mob) : void{ //TODO: we could send zero for slot here because remote players don't need to know which slot was selected $inv = $mob->getInventory(); $this->sendDataPacket($recipients, MobEquipmentPacket::create( $mob->getId(), ItemStackWrapper::legacy(TypeConverter::getInstance()->coreItemStackToNet($inv->getItemInHand())), $inv->getHeldItemIndex(), $inv->getHeldItemIndex(), ContainerIds::INVENTORY )); } public function onMobOffHandItemChange(array $recipients, Human $mob) : void{ $inv = $mob->getOffHandInventory(); $this->sendDataPacket($recipients, MobEquipmentPacket::create( $mob->getId(), ItemStackWrapper::legacy(TypeConverter::getInstance()->coreItemStackToNet($inv->getItem(0))), 0, 0, ContainerIds::OFFHAND )); } public function onMobArmorChange(array $recipients, Living $mob) : void{ $inv = $mob->getArmorInventory(); $converter = TypeConverter::getInstance(); $this->sendDataPacket($recipients, MobArmorEquipmentPacket::create( $mob->getId(), ItemStackWrapper::legacy($converter->coreItemStackToNet($inv->getHelmet())), ItemStackWrapper::legacy($converter->coreItemStackToNet($inv->getChestplate())), ItemStackWrapper::legacy($converter->coreItemStackToNet($inv->getLeggings())), ItemStackWrapper::legacy($converter->coreItemStackToNet($inv->getBoots())) )); } public function onPickUpItem(array $recipients, Entity $collector, Entity $pickedUp) : void{ $this->sendDataPacket($recipients, TakeItemActorPacket::create($collector->getId(), $pickedUp->getId())); } public function onEmote(array $recipients, Human $from, string $emoteId) : void{ $this->sendDataPacket($recipients, EmotePacket::create($from->getId(), $emoteId, EmotePacket::FLAG_SERVER)); } }