45 public const TAG_TILE_X =
"TileX";
46 public const TAG_TILE_Y =
"TileY";
47 public const TAG_TILE_Z =
"TileZ";
48 public const TAG_FACING_JE =
"Facing";
49 public const TAG_DIRECTION_BE =
"Direction";
50 public const TAG_MOTIVE =
"Motive";
52 public static function getNetworkTypeId() :
string{
return EntityIds::PAINTING; }
54 public const DATA_TO_FACING = [
60 private const FACING_TO_DATA = [
68 protected int $facing;
72 $this->motive = $motive;
74 $this->facing = $facing;
75 parent::__construct($location, $nbt);
87 protected function initEntity(
CompoundTag $nbt) : void{
88 $this->setMaxHealth(1);
90 parent::initEntity($nbt);
94 $nbt = parent::saveNBT();
95 $nbt->
setInt(self::TAG_TILE_X, (
int) $this->blockIn->x);
96 $nbt->setInt(self::TAG_TILE_Y, (
int) $this->blockIn->y);
97 $nbt->setInt(self::TAG_TILE_Z, (
int) $this->blockIn->z);
99 $nbt->setByte(self::TAG_FACING_JE, self::FACING_TO_DATA[$this->facing]);
100 $nbt->setByte(self::TAG_DIRECTION_BE, self::FACING_TO_DATA[$this->facing]);
102 $nbt->setString(self::TAG_MOTIVE, $this->motive->getName());
113 $killer = $this->lastDamageCause->getDamager();
121 $this->getWorld()->dropItem($this->location, VanillaItems::PAINTING());
123 $this->getWorld()->addParticle($this->location->add(0.5, 0.5, 0.5),
new BlockBreakParticle(VanillaBlocks::OAK_PLANKS()));
126 protected function recalculateBoundingBox() : void{
127 $side = $this->blockIn->getSide($this->facing);
128 $this->boundingBox = self::getPaintingBB($this->facing, $this->getMotive())->offset($side->x, $side->y, $side->z);
131 public function onNearbyBlockChange() : void{
132 parent::onNearbyBlockChange();
134 if(!self::canFit($this->getWorld(), $this->blockIn->getSide($this->facing), $this->facing,
false, $this->getMotive())){
143 public function hasMovementUpdate() : bool{
147 protected function updateMovement(
bool $teleport =
false) : void{
151 public function canBeCollidedWith() : bool{
160 ($this->boundingBox->minX + $this->boundingBox->maxX) / 2,
161 ($this->boundingBox->minY + $this->boundingBox->maxY) / 2,
162 ($this->boundingBox->minZ + $this->boundingBox->maxZ) / 2
164 self::FACING_TO_DATA[$this->facing],
165 $this->motive->getName()
177 return $this->motive;
180 public function getFacing() : int{
181 return $this->facing;
188 $width = $motive->getWidth();
189 $height = $motive->getHeight();
191 $horizontalStart = (int) (ceil($width / 2) - 1);
192 $verticalStart = (int) (ceil($height / 2) - 1);
194 return AxisAlignedBB::one()
195 ->trim($facing, 15 / 16)
196 ->extend(Facing::rotateY($facing,
true), $horizontalStart)
197 ->extend(Facing::rotateY($facing,
false), -$horizontalStart + $width - 1)
198 ->extend(Facing::DOWN, $verticalStart)
199 ->extend(Facing::UP, -$verticalStart + $height - 1);
206 $width = $motive->getWidth();
207 $height = $motive->getHeight();
209 $horizontalStart = (int) (ceil($width / 2) - 1);
210 $verticalStart = (int) (ceil($height / 2) - 1);
212 $rotatedFace = Facing::rotateY($facing,
false);
214 $oppositeSide = Facing::opposite($facing);
216 $startPos = $blockIn->
asVector3()->getSide(Facing::opposite($rotatedFace), $horizontalStart)->getSide(Facing::DOWN, $verticalStart);
218 for($w = 0; $w < $width; ++$w){
219 for($h = 0; $h < $height; ++$h){
220 $pos = $startPos->getSide($rotatedFace, $w)->getSide(Facing::UP, $h);
222 $block = $world->
getBlockAt($pos->x, $pos->y, $pos->z);
223 if($block->isSolid() || !$block->getSide($oppositeSide)->isSolid()){
230 $bb = self::getPaintingBB($facing, $motive)->offset($blockIn->x, $blockIn->y, $blockIn->z);
233 if($entity instanceof
self){