PocketMine-MP 5.19.1 git-5cc1068cd43264d3363295eb8d6901e02f467897
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
47use function array_map;
48use function count;
49use function ksort;
50use const SORT_NUMERIC;
51
53
54 public function __construct(
55 private PacketBroadcaster $broadcaster,
56 private TypeConverter $typeConverter
57 ){}
58
62 private function sendDataPacket(array $recipients, ClientboundPacket $packet) : void{
63 $this->broadcaster->broadcastPackets($recipients, [$packet]);
64 }
65
66 public function syncAttributes(array $recipients, Living $entity, array $attributes) : void{
67 if(count($attributes) > 0){
68 $this->sendDataPacket($recipients, UpdateAttributesPacket::create(
69 $entity->getId(),
70 array_map(fn(Attribute $attr) => new UpdateAttribute($attr->getId(), $attr->getMinValue(), $attr->getMaxValue(), $attr->getValue(), $attr->getMinValue(), $attr->getMaxValue(), $attr->getDefaultValue(), []), $attributes),
71 0
72 ));
73 }
74 }
75
76 public function syncActorData(array $recipients, Entity $entity, array $properties) : void{
77 //TODO: HACK! as of 1.18.10, the client responds differently to the same data ordered in different orders - for
78 //example, sending HEIGHT in the list before FLAGS when unsetting the SWIMMING flag results in a hitbox glitch
79 ksort($properties, SORT_NUMERIC);
80 $this->sendDataPacket($recipients, SetActorDataPacket::create($entity->getId(), $properties, new PropertySyncData([], []), 0));
81 }
82
83 public function onEntityEffectAdded(array $recipients, Living $entity, EffectInstance $effect, bool $replacesOldEffect) : void{
84 //TODO: we may need yet another effect <=> ID map in the future depending on protocol changes
85 $this->sendDataPacket($recipients, MobEffectPacket::add(
86 $entity->getId(),
87 $replacesOldEffect,
88 EffectIdMap::getInstance()->toId($effect->getType()),
89 $effect->getAmplifier(),
90 $effect->isVisible(),
91 $effect->getDuration(),
92 tick: 0
93 ));
94 }
95
96 public function onEntityEffectRemoved(array $recipients, Living $entity, EffectInstance $effect) : void{
97 $this->sendDataPacket($recipients, MobEffectPacket::remove($entity->getId(), EffectIdMap::getInstance()->toId($effect->getType()), tick: 0));
98 }
99
100 public function onEntityRemoved(array $recipients, Entity $entity) : void{
101 $this->sendDataPacket($recipients, RemoveActorPacket::create($entity->getId()));
102 }
103
104 public function onMobMainHandItemChange(array $recipients, Human $mob) : void{
105 //TODO: we could send zero for slot here because remote players don't need to know which slot was selected
106 $inv = $mob->getInventory();
107 $this->sendDataPacket($recipients, MobEquipmentPacket::create(
108 $mob->getId(),
109 ItemStackWrapper::legacy($this->typeConverter->coreItemStackToNet($inv->getItemInHand())),
110 $inv->getHeldItemIndex(),
111 $inv->getHeldItemIndex(),
112 ContainerIds::INVENTORY
113 ));
114 }
115
116 public function onMobOffHandItemChange(array $recipients, Human $mob) : void{
117 $inv = $mob->getOffHandInventory();
118 $this->sendDataPacket($recipients, MobEquipmentPacket::create(
119 $mob->getId(),
120 ItemStackWrapper::legacy($this->typeConverter->coreItemStackToNet($inv->getItem(0))),
121 0,
122 0,
123 ContainerIds::OFFHAND
124 ));
125 }
126
127 public function onMobArmorChange(array $recipients, Living $mob) : void{
128 $inv = $mob->getArmorInventory();
129 $converter = $this->typeConverter;
130 $this->sendDataPacket($recipients, MobArmorEquipmentPacket::create(
131 $mob->getId(),
132 ItemStackWrapper::legacy($converter->coreItemStackToNet($inv->getHelmet())),
133 ItemStackWrapper::legacy($converter->coreItemStackToNet($inv->getChestplate())),
134 ItemStackWrapper::legacy($converter->coreItemStackToNet($inv->getLeggings())),
135 ItemStackWrapper::legacy($converter->coreItemStackToNet($inv->getBoots())),
136 new ItemStackWrapper(0, ItemStack::null())
137 ));
138 }
139
140 public function onPickUpItem(array $recipients, Entity $collector, Entity $pickedUp) : void{
141 $this->sendDataPacket($recipients, TakeItemActorPacket::create($collector->getId(), $pickedUp->getId()));
142 }
143
144 public function onEmote(array $recipients, Human $from, string $emoteId) : void{
145 $this->sendDataPacket($recipients, EmotePacket::create(
146 $from->getId(),
147 $emoteId,
148 0, //seems to be irrelevant for the client, we cannot risk rebroadcasting random values received
149 "",
150 "",
151 EmotePacket::FLAG_SERVER | EmotePacket::FLAG_MUTE_ANNOUNCEMENT
152 ));
153 }
154}
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)