Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added entity middle-click feature #5397

Merged
merged 18 commits into from
Nov 15, 2024
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 40 additions & 0 deletions src/entity/Entity.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@
use pocketmine\event\entity\EntityRegainHealthEvent;
use pocketmine\event\entity\EntitySpawnEvent;
use pocketmine\event\entity\EntityTeleportEvent;
use pocketmine\item\Item;
use pocketmine\item\VanillaItems;
use pocketmine\math\AxisAlignedBB;
use pocketmine\math\Facing;
use pocketmine\math\Vector2;
Expand Down Expand Up @@ -497,6 +499,12 @@ public function saveNBT() : CompoundTag{
return $nbt;
}

public function getCleanedNBT() : CompoundTag{
$nbt = $this->saveNBT();
$nbt->removeTag("identifier", "Pos", "Motion", "Rotation", "FallDistance", "OnGround");
return $nbt;
}

protected function initEntity(CompoundTag $nbt) : void{
$this->fireTicks = $nbt->getShort("Fire", 0);

Expand All @@ -516,6 +524,18 @@ protected function initEntity(CompoundTag $nbt) : void{
}
}

/**
* @internal
*/
public function copyDataFromItem(Item $item) : void{
if(($entityNbt = $item->getCustomEntityData()) !== null){
$this->initEntity($entityNbt);
}
if($item->hasCustomName()){ //this should take precedence over saved NBT
$this->setNameTag($item->getCustomName());
}
}

protected function addAttributes() : void{

}
Expand Down Expand Up @@ -1535,6 +1555,26 @@ public function despawnFromAll() : void{
}
}

/**
* Returns the item that can be used to spawn this entity, by default it returns air if there isn't one
*/
public function getSpawnItem() : Item{
JavierLeon9966 marked this conversation as resolved.
Show resolved Hide resolved
return VanillaItems::AIR();
JavierLeon9966 marked this conversation as resolved.
Show resolved Hide resolved
}

/**
* Returns the item that players will equip when middle-clicking on this entity.
* If addUserData is true, additional data may be added, such as name tag, fire ticks, etc.
JavierLeon9966 marked this conversation as resolved.
Show resolved Hide resolved
*/
public function getPickedItem(bool $addUserData) : Item{
JavierLeon9966 marked this conversation as resolved.
Show resolved Hide resolved
$item = $this->getSpawnItem();
if($addUserData){
$item->setCustomEntityData($this->getCleanedNBT());
$item->setLore(["+(DATA)"]);
}
return $item;
JavierLeon9966 marked this conversation as resolved.
Show resolved Hide resolved
}

/**
* Flags the entity to be removed from the world on the next tick.
*/
Expand Down
5 changes: 5 additions & 0 deletions src/entity/Squid.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
use pocketmine\entity\animation\SquidInkCloudAnimation;
use pocketmine\event\entity\EntityDamageByEntityEvent;
use pocketmine\event\entity\EntityDamageEvent;
use pocketmine\item\Item;
use pocketmine\item\VanillaItems;
use pocketmine\math\Vector3;
use pocketmine\nbt\tag\CompoundTag;
Expand Down Expand Up @@ -126,4 +127,8 @@ public function getDrops() : array{
VanillaItems::INK_SAC()->setCount(mt_rand(1, 3))
];
}

public function getSpawnItem() : Item{
return VanillaItems::SQUID_SPAWN_EGG();
}
}
6 changes: 6 additions & 0 deletions src/entity/Villager.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@

namespace pocketmine\entity;

use pocketmine\item\Item;
use pocketmine\item\VanillaItems;
use pocketmine\nbt\tag\CompoundTag;
use pocketmine\network\mcpe\protocol\types\entity\EntityIds;
use pocketmine\network\mcpe\protocol\types\entity\EntityMetadataCollection;
Expand Down Expand Up @@ -85,6 +87,10 @@ public function isBaby() : bool{
return $this->baby;
}

public function getSpawnItem() : Item{
return VanillaItems::VILLAGER_SPAWN_EGG();
}

protected function syncNetworkData(EntityMetadataCollection $properties) : void{
parent::syncNetworkData($properties);
$properties->setGenericFlag(EntityMetadataFlags::BABY, $this->baby);
Expand Down
5 changes: 5 additions & 0 deletions src/entity/Zombie.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@

namespace pocketmine\entity;

use pocketmine\item\Item;
use pocketmine\item\VanillaItems;
use pocketmine\network\mcpe\protocol\types\entity\EntityIds;
use function mt_rand;
Expand Down Expand Up @@ -65,4 +66,8 @@ public function getXpDropAmount() : int{
//TODO: check for equipment and whether it's a baby
return 5;
}

public function getSpawnItem() : Item{
return VanillaItems::ZOMBIE_SPAWN_EGG();
}
}
5 changes: 5 additions & 0 deletions src/entity/object/FallingBlock.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
use pocketmine\entity\Location;
use pocketmine\event\entity\EntityBlockChangeEvent;
use pocketmine\event\entity\EntityDamageEvent;
use pocketmine\item\Item;
use pocketmine\math\Vector3;
use pocketmine\nbt\tag\ByteTag;
use pocketmine\nbt\tag\CompoundTag;
Expand Down Expand Up @@ -144,6 +145,10 @@ public function saveNBT() : CompoundTag{
return $nbt;
}

public function getPickedItem(bool $addUserData) : Item{
return $this->block->asItem();
}

protected function syncNetworkData(EntityMetadataCollection $properties) : void{
parent::syncNetworkData($properties);

Expand Down
9 changes: 9 additions & 0 deletions src/entity/object/Painting.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
use pocketmine\entity\EntitySizeInfo;
use pocketmine\entity\Location;
use pocketmine\event\entity\EntityDamageByEntityEvent;
use pocketmine\item\Item;
use pocketmine\item\VanillaItems;
use pocketmine\math\AxisAlignedBB;
use pocketmine\math\Facing;
Expand Down Expand Up @@ -162,6 +163,14 @@ protected function sendSpawnPacket(Player $player) : void{
));
}

public function getSpawnItem() : Item{
return VanillaItems::PAINTING();
}

public function getPickedItem(bool $addUserData) : Item{
return $this->getSpawnItem();
}

/**
* Returns the painting motive (which image is displayed on the painting)
*/
Expand Down
10 changes: 10 additions & 0 deletions src/entity/object/PrimedTNT.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,13 @@

namespace pocketmine\entity\object;

use pocketmine\block\VanillaBlocks;
use pocketmine\entity\Entity;
use pocketmine\entity\EntitySizeInfo;
use pocketmine\entity\Explosive;
use pocketmine\event\entity\EntityDamageEvent;
use pocketmine\event\entity\ExplosionPrimeEvent;
use pocketmine\item\Item;
use pocketmine\math\Vector3;
use pocketmine\nbt\tag\CompoundTag;
use pocketmine\network\mcpe\protocol\types\entity\EntityIds;
Expand Down Expand Up @@ -128,6 +130,14 @@ public function explode() : void{
}
}

public function getSpawnItem() : Item{
return VanillaBlocks::TNT()->setWorksUnderwater($this->worksUnderwater)->asItem();
}

public function getPickedItem(bool $addUserData) : Item{
return $this->getSpawnItem();
}

protected function syncNetworkData(EntityMetadataCollection $properties) : void{
parent::syncNetworkData($properties);

Expand Down
53 changes: 53 additions & 0 deletions src/event/player/PlayerEntityPickEvent.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<?php

/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/

declare(strict_types=1);

namespace pocketmine\event\player;

use pocketmine\entity\Entity;
use pocketmine\event\Cancellable;
use pocketmine\event\CancellableTrait;
use pocketmine\item\Item;
use pocketmine\player\Player;

/**
* Called when a player middle-clicks on a entity to get an item in creative mode.
ipad54 marked this conversation as resolved.
Show resolved Hide resolved
*/
class PlayerEntityPickEvent extends PlayerEvent implements Cancellable{
use CancellableTrait;

public function __construct(
Player $player,
private Entity $entityClicked,
private Item $resultItem
){
$this->player = $player;
}

public function getEntity() : Entity{
return $this->entityClicked;
}

public function getResultItem() : Item{
return $this->resultItem;
}
}
30 changes: 30 additions & 0 deletions src/item/Item.php
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ class Item implements \JsonSerializable{
public const TAG_ENCH = "ench";
public const TAG_DISPLAY = "display";
public const TAG_BLOCK_ENTITY_TAG = "BlockEntityTag";
public const TAG_ENTITY_TAG = "EntityTag";
JavierLeon9966 marked this conversation as resolved.
Show resolved Hide resolved

public const TAG_DISPLAY_NAME = "Name";
public const TAG_DISPLAY_LORE = "Lore";
Expand All @@ -84,6 +85,7 @@ class Item implements \JsonSerializable{
* @var CompoundTag|null
*/
protected $blockEntityTag = null;
protected ?CompoundTag $entityTag = null;

/**
* @var string[]
Expand Down Expand Up @@ -138,6 +140,28 @@ public function getCustomBlockData() : ?CompoundTag{
return $this->blockEntityTag;
}

/**
* @return $this
*/
public function clearCustomEntityData() : Item{
$this->entityTag = null;

return $this;
}

/**
* @return $this
*/
public function setCustomEntityData(CompoundTag $compound) : Item{
$this->entityTag = clone $compound;

return $this;
}

public function getCustomEntityData() : ?CompoundTag{
return $this->entityTag;
}

public function hasCustomName() : bool{
return $this->customName !== "";
}
Expand Down Expand Up @@ -304,6 +328,8 @@ protected function deserializeCompoundTag(CompoundTag $tag) : void{

$this->blockEntityTag = $tag->getCompoundTag(self::TAG_BLOCK_ENTITY_TAG);

$this->entityTag = $tag->getCompoundTag(self::TAG_ENTITY_TAG);

$this->canPlaceOn = [];
$canPlaceOn = $tag->getListTag("CanPlaceOn");
if($canPlaceOn !== null && $canPlaceOn->getTagType() === NBT::TAG_String){
Expand Down Expand Up @@ -359,6 +385,10 @@ protected function serializeCompoundTag(CompoundTag $tag) : void{
$tag->setTag(self::TAG_BLOCK_ENTITY_TAG, clone $blockData) :
$tag->removeTag(self::TAG_BLOCK_ENTITY_TAG);

($entityData = $this->getCustomEntityData()) !== null ?
$tag->setTag(self::TAG_ENTITY_TAG, clone $entityData) :
$tag->removeTag(self::TAG_ENTITY_TAG);

if(count($this->canPlaceOn) > 0){
$canPlaceOn = new ListTag();
foreach($this->canPlaceOn as $item){
Expand Down
4 changes: 1 addition & 3 deletions src/item/SpawnEgg.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,8 @@ abstract protected function createEntity(World $world, Vector3 $pos, float $yaw,

public function onInteractBlock(Player $player, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector) : ItemUseResult{
$entity = $this->createEntity($player->getWorld(), $blockReplace->getPosition()->add(0.5, 0, 0.5), lcg_value() * 360, 0);
$entity->copyDataFromItem($this);

if($this->hasCustomName()){
$entity->setNameTag($this->getCustomName());
}
$this->pop();
$entity->spawnToAll();
//TODO: what if the entity was marked for deletion?
Expand Down
2 changes: 1 addition & 1 deletion src/network/mcpe/handler/InGamePacketHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -590,7 +590,7 @@ public function handleBlockPickRequest(BlockPickRequestPacket $packet) : bool{
}

public function handleActorPickRequest(ActorPickRequestPacket $packet) : bool{
return false; //TODO
return $this->player->pickEntity($packet->actorUniqueId, $packet->addUserData);
}

public function handlePlayerAction(PlayerActionPacket $packet) : bool{
Expand Down
Loading