PocketMine-MP 5.15.1 git-5ef247620a7c6301a849b54e5ef1009217729fc8
StandardEntityEventBroadcaster.php
1<?php
2
3/*
4 *
5 * ____ _ _ __ __ _ __ __ ____
6 * | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
7 * | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
8 * | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
9 * |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
10 *
11 * This program is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License as published by
13 * the Free Software Foundation, either version 3 of the License, or
14 * (at your option) any later version.
15 *
16 * @author PocketMine Team
17 * @link http://www.pocketmine.net/
18 *
19 *
20 */
21
22declare(strict_types=1);
23
24namespace pocketmine\network\mcpe;
25
46use function array_map;
47use function count;
48use function ksort;
49use const SORT_NUMERIC;
50
52
53 public function __construct(
54 private PacketBroadcaster $broadcaster,
55 private TypeConverter $typeConverter
56 ){}
57
61 private function sendDataPacket(array $recipients, ClientboundPacket $packet) : void{
62 $this->broadcaster->broadcastPackets($recipients, [$packet]);
63 }
64
65 public function syncAttributes(array $recipients, Living $entity, array $attributes) : void{
66 if(count($attributes) > 0){
67 $this->sendDataPacket($recipients, UpdateAttributesPacket::create(
68 $entity->getId(),
69 array_map(fn(Attribute $attr) => new NetworkAttribute($attr->getId(), $attr->getMinValue(), $attr->getMaxValue(), $attr->getValue(), $attr->getDefaultValue(), []), $attributes),
70 0
71 ));
72 }
73 }
74
75 public function syncActorData(array $recipients, Entity $entity, array $properties) : void{
76 //TODO: HACK! as of 1.18.10, the client responds differently to the same data ordered in different orders - for
77 //example, sending HEIGHT in the list before FLAGS when unsetting the SWIMMING flag results in a hitbox glitch
78 ksort($properties, SORT_NUMERIC);
79 $this->sendDataPacket($recipients, SetActorDataPacket::create($entity->getId(), $properties, new PropertySyncData([], []), 0));
80 }
81
82 public function onEntityEffectAdded(array $recipients, Living $entity, EffectInstance $effect, bool $replacesOldEffect) : void{
83 //TODO: we may need yet another effect <=> ID map in the future depending on protocol changes
84 $this->sendDataPacket($recipients, MobEffectPacket::add(
85 $entity->getId(),
86 $replacesOldEffect,
87 EffectIdMap::getInstance()->toId($effect->getType()),
88 $effect->getAmplifier(),
89 $effect->isVisible(),
90 $effect->getDuration(),
91 tick: 0
92 ));
93 }
94
95 public function onEntityEffectRemoved(array $recipients, Living $entity, EffectInstance $effect) : void{
96 $this->sendDataPacket($recipients, MobEffectPacket::remove($entity->getId(), EffectIdMap::getInstance()->toId($effect->getType()), tick: 0));
97 }
98
99 public function onEntityRemoved(array $recipients, Entity $entity) : void{
100 $this->sendDataPacket($recipients, RemoveActorPacket::create($entity->getId()));
101 }
102
103 public function onMobMainHandItemChange(array $recipients, Human $mob) : void{
104 //TODO: we could send zero for slot here because remote players don't need to know which slot was selected
105 $inv = $mob->getInventory();
106 $this->sendDataPacket($recipients, MobEquipmentPacket::create(
107 $mob->getId(),
108 ItemStackWrapper::legacy($this->typeConverter->coreItemStackToNet($inv->getItemInHand())),
109 $inv->getHeldItemIndex(),
110 $inv->getHeldItemIndex(),
111 ContainerIds::INVENTORY
112 ));
113 }
114
115 public function onMobOffHandItemChange(array $recipients, Human $mob) : void{
116 $inv = $mob->getOffHandInventory();
117 $this->sendDataPacket($recipients, MobEquipmentPacket::create(
118 $mob->getId(),
119 ItemStackWrapper::legacy($this->typeConverter->coreItemStackToNet($inv->getItem(0))),
120 0,
121 0,
122 ContainerIds::OFFHAND
123 ));
124 }
125
126 public function onMobArmorChange(array $recipients, Living $mob) : void{
127 $inv = $mob->getArmorInventory();
128 $converter = $this->typeConverter;
129 $this->sendDataPacket($recipients, MobArmorEquipmentPacket::create(
130 $mob->getId(),
131 ItemStackWrapper::legacy($converter->coreItemStackToNet($inv->getHelmet())),
132 ItemStackWrapper::legacy($converter->coreItemStackToNet($inv->getChestplate())),
133 ItemStackWrapper::legacy($converter->coreItemStackToNet($inv->getLeggings())),
134 ItemStackWrapper::legacy($converter->coreItemStackToNet($inv->getBoots()))
135 ));
136 }
137
138 public function onPickUpItem(array $recipients, Entity $collector, Entity $pickedUp) : void{
139 $this->sendDataPacket($recipients, TakeItemActorPacket::create($collector->getId(), $pickedUp->getId()));
140 }
141
142 public function onEmote(array $recipients, Human $from, string $emoteId) : void{
143 $this->sendDataPacket($recipients, EmotePacket::create($from->getId(), $emoteId, "", "", EmotePacket::FLAG_SERVER | EmotePacket::FLAG_MUTE_ANNOUNCEMENT));
144 }
145}
onEntityEffectAdded(array $recipients, Living $entity, EffectInstance $effect, bool $replacesOldEffect)
syncAttributes(array $recipients, Living $entity, array $attributes)
onEmote(array $recipients, Human $from, string $emoteId)
syncActorData(array $recipients, Entity $entity, array $properties)
onEntityEffectRemoved(array $recipients, Living $entity, EffectInstance $effect)
onPickUpItem(array $recipients, Entity $collector, Entity $pickedUp)
static create(int $actorRuntimeId, array $metadata, PropertySyncData $syncedProperties, int $tick)
static create(int $actorRuntimeId, array $entries, int $tick)