diff --git a/src/pocketmine/inventory/PlayerInventory.php b/src/pocketmine/inventory/PlayerInventory.php index fbc2748d1..1ec534a29 100644 --- a/src/pocketmine/inventory/PlayerInventory.php +++ b/src/pocketmine/inventory/PlayerInventory.php @@ -25,11 +25,7 @@ namespace pocketmine\inventory; use pocketmine\entity\Human; use pocketmine\item\Item; -use pocketmine\network\mcpe\protocol\MobEquipmentPacket; -use pocketmine\network\mcpe\protocol\types\ContainerIds; use pocketmine\player\Player; -use function in_array; -use function is_array; class PlayerInventory extends BaseInventory{ @@ -98,11 +94,12 @@ class PlayerInventory extends BaseInventory{ $this->itemInHandIndex = $hotbarSlot; - if($this->getHolder() instanceof Player and $send){ - $this->sendHeldItem($this->getHolder()); + if($this->holder instanceof Player and $send){ + $this->holder->getNetworkSession()->getInvManager()->syncSelectedHotbarSlot(); + } + foreach($this->holder->getViewers() as $viewer){ + $viewer->getNetworkSession()->onMobEquipmentChange($this->holder); } - - $this->sendHeldItem($this->getHolder()->getViewers()); } /** @@ -121,29 +118,8 @@ class PlayerInventory extends BaseInventory{ */ public function setItemInHand(Item $item) : void{ $this->setItem($this->getHeldItemIndex(), $item); - $this->sendHeldItem($this->holder->getViewers()); - } - - /** - * Sends the currently-held item to specified targets. - * - * @param Player|Player[] $target - */ - public function sendHeldItem($target) : void{ - $item = $this->getItemInHand(); - - $pk = MobEquipmentPacket::create($this->getHolder()->getId(), $item, $this->getHeldItemIndex(), ContainerIds::INVENTORY); - - if(!is_array($target)){ - $target->sendDataPacket($pk); - if($target === $this->getHolder()){ - $target->getNetworkSession()->getInvManager()->syncSlot($this, $this->getHeldItemIndex()); - } - }else{ - $this->getHolder()->getWorld()->getServer()->broadcastPacket($target, $pk); - if(in_array($this->getHolder(), $target, true)){ - $target->getNetworkSession()->getInvManager()->syncSlot($this, $this->getHeldItemIndex()); - } + foreach($this->holder->getViewers() as $viewer){ + $viewer->getNetworkSession()->onMobEquipmentChange($this->holder); } } diff --git a/src/pocketmine/network/mcpe/InventoryManager.php b/src/pocketmine/network/mcpe/InventoryManager.php index da285bb87..b88e240ed 100644 --- a/src/pocketmine/network/mcpe/InventoryManager.php +++ b/src/pocketmine/network/mcpe/InventoryManager.php @@ -36,6 +36,7 @@ use pocketmine\network\mcpe\protocol\ContainerOpenPacket; use pocketmine\network\mcpe\protocol\ContainerSetDataPacket; use pocketmine\network\mcpe\protocol\InventoryContentPacket; use pocketmine\network\mcpe\protocol\InventorySlotPacket; +use pocketmine\network\mcpe\protocol\PlayerHotbarPacket; use pocketmine\network\mcpe\protocol\types\ContainerIds; use pocketmine\network\mcpe\protocol\types\WindowTypes; use pocketmine\player\Player; @@ -144,6 +145,10 @@ class InventoryManager{ } } + public function syncSelectedHotbarSlot() : void{ + $this->session->sendDataPacket(PlayerHotbarPacket::create($this->player->getInventory()->getHeldItemIndex(), ContainerIds::INVENTORY)); + } + public function syncCreative() : void{ $items = []; if(!$this->player->isSpectator()){ //fill it for all gamemodes except spectator diff --git a/src/pocketmine/network/mcpe/NetworkSession.php b/src/pocketmine/network/mcpe/NetworkSession.php index 51be86858..a1aa9819e 100644 --- a/src/pocketmine/network/mcpe/NetworkSession.php +++ b/src/pocketmine/network/mcpe/NetworkSession.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace pocketmine\network\mcpe; use pocketmine\entity\effect\EffectInstance; +use pocketmine\entity\Human; use pocketmine\entity\Living; use pocketmine\event\player\PlayerCreationEvent; use pocketmine\event\server\DataPacketReceiveEvent; @@ -47,6 +48,7 @@ use pocketmine\network\mcpe\protocol\DisconnectPacket; use pocketmine\network\mcpe\protocol\GarbageServerboundPacket; use pocketmine\network\mcpe\protocol\MobArmorEquipmentPacket; use pocketmine\network\mcpe\protocol\MobEffectPacket; +use pocketmine\network\mcpe\protocol\MobEquipmentPacket; use pocketmine\network\mcpe\protocol\ModalFormRequestPacket; use pocketmine\network\mcpe\protocol\MovePlayerPacket; use pocketmine\network\mcpe\protocol\NetworkChunkPublisherUpdatePacket; @@ -62,6 +64,7 @@ use pocketmine\network\mcpe\protocol\TransferPacket; use pocketmine\network\mcpe\protocol\types\CommandData; use pocketmine\network\mcpe\protocol\types\CommandEnum; use pocketmine\network\mcpe\protocol\types\CommandParameter; +use pocketmine\network\mcpe\protocol\types\ContainerIds; use pocketmine\network\mcpe\protocol\types\PlayerListEntry; use pocketmine\network\mcpe\protocol\types\PlayerPermissions; use pocketmine\network\mcpe\protocol\UpdateAttributesPacket; @@ -776,6 +779,18 @@ class NetworkSession{ return $this->invManager; } + /** + * TODO: expand this to more than just humans + * TODO: offhand + * + * @param Human $mob + */ + public function onMobEquipmentChange(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(MobEquipmentPacket::create($mob->getId(), $inv->getItemInHand(), $inv->getHeldItemIndex(), ContainerIds::INVENTORY)); + } + public function onMobArmorChange(Living $mob) : void{ $inv = $mob->getArmorInventory(); $this->sendDataPacket(MobArmorEquipmentPacket::create($mob->getId(), $inv->getHelmet(), $inv->getChestplate(), $inv->getLeggings(), $inv->getBoots())); diff --git a/src/pocketmine/network/mcpe/handler/InGamePacketHandler.php b/src/pocketmine/network/mcpe/handler/InGamePacketHandler.php index 2edcae7a7..97a8e9480 100644 --- a/src/pocketmine/network/mcpe/handler/InGamePacketHandler.php +++ b/src/pocketmine/network/mcpe/handler/InGamePacketHandler.php @@ -359,7 +359,7 @@ class InGamePacketHandler extends PacketHandler{ public function handleMobEquipment(MobEquipmentPacket $packet) : bool{ if(!$this->player->selectHotbarSlot($packet->hotbarSlot)){ - $this->player->getInventory()->sendHeldItem($this->player); + $this->session->getInvManager()->syncSelectedHotbarSlot(); } return true; } diff --git a/src/pocketmine/network/mcpe/handler/PreSpawnPacketHandler.php b/src/pocketmine/network/mcpe/handler/PreSpawnPacketHandler.php index 6ff83c492..9aa3ac0a5 100644 --- a/src/pocketmine/network/mcpe/handler/PreSpawnPacketHandler.php +++ b/src/pocketmine/network/mcpe/handler/PreSpawnPacketHandler.php @@ -93,7 +93,7 @@ class PreSpawnPacketHandler extends PacketHandler{ $this->session->getInvManager()->syncAll(); $this->session->getInvManager()->syncCreative(); - $this->player->getInventory()->sendHeldItem($this->player); + $this->session->getInvManager()->syncSelectedHotbarSlot(); $this->session->queueCompressed($this->server->getCraftingManager()->getCraftingDataPacket()); $this->session->syncPlayerList(); diff --git a/src/pocketmine/network/mcpe/protocol/PlayerHotbarPacket.php b/src/pocketmine/network/mcpe/protocol/PlayerHotbarPacket.php index 9cf8dc2f0..02a98a81e 100644 --- a/src/pocketmine/network/mcpe/protocol/PlayerHotbarPacket.php +++ b/src/pocketmine/network/mcpe/protocol/PlayerHotbarPacket.php @@ -28,9 +28,6 @@ namespace pocketmine\network\mcpe\protocol; use pocketmine\network\mcpe\handler\PacketHandler; use pocketmine\network\mcpe\protocol\types\ContainerIds; -/** - * One of the most useless packets. - */ class PlayerHotbarPacket extends DataPacket implements ClientboundPacket, ServerboundPacket{ public const NETWORK_ID = ProtocolInfo::PLAYER_HOTBAR_PACKET; @@ -41,6 +38,14 @@ class PlayerHotbarPacket extends DataPacket implements ClientboundPacket, Server /** @var bool */ public $selectHotbarSlot = true; + public static function create(int $slot, int $windowId, bool $selectSlot = true) : self{ + $result = new self; + $result->selectedHotbarSlot = $slot; + $result->windowId = $windowId; + $result->selectHotbarSlot = $selectSlot; + return $result; + } + protected function decodePayload() : void{ $this->selectedHotbarSlot = $this->getUnsignedVarInt(); $this->windowId = $this->getByte();