mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-09-09 03:06:55 +00:00
PlayerRespawnAnchorUseEvent is also added with options SET_SPAWN and EXPLODE, which allows plugins to customise the outcome of using the anchor in PM, which currently doesn't support dimensions. The event is also cancellable.
148 lines
4.3 KiB
PHP
148 lines
4.3 KiB
PHP
<?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\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\EntityPreExplodeEvent;
|
|
use pocketmine\item\Item;
|
|
use pocketmine\math\Vector3;
|
|
use pocketmine\nbt\tag\CompoundTag;
|
|
use pocketmine\network\mcpe\protocol\types\entity\EntityIds;
|
|
use pocketmine\network\mcpe\protocol\types\entity\EntityMetadataCollection;
|
|
use pocketmine\network\mcpe\protocol\types\entity\EntityMetadataFlags;
|
|
use pocketmine\network\mcpe\protocol\types\entity\EntityMetadataProperties;
|
|
use pocketmine\world\Explosion;
|
|
use pocketmine\world\Position;
|
|
|
|
class PrimedTNT extends Entity implements Explosive{
|
|
|
|
private const TAG_FUSE = "Fuse"; //TAG_Short
|
|
|
|
public static function getNetworkTypeId() : string{ return EntityIds::TNT; }
|
|
|
|
protected int $fuse;
|
|
protected bool $worksUnderwater = false;
|
|
|
|
protected function getInitialSizeInfo() : EntitySizeInfo{ return new EntitySizeInfo(0.98, 0.98); }
|
|
|
|
protected function getInitialDragMultiplier() : float{ return 0.02; }
|
|
|
|
protected function getInitialGravity() : float{ return 0.04; }
|
|
|
|
public function getFuse() : int{
|
|
return $this->fuse;
|
|
}
|
|
|
|
public function setFuse(int $fuse) : void{
|
|
if($fuse < 0 || $fuse > 32767){
|
|
throw new \InvalidArgumentException("Fuse must be in the range 0-32767");
|
|
}
|
|
$this->fuse = $fuse;
|
|
$this->networkPropertiesDirty = true;
|
|
}
|
|
|
|
public function worksUnderwater() : bool{ return $this->worksUnderwater; }
|
|
|
|
public function setWorksUnderwater(bool $worksUnderwater) : void{
|
|
$this->worksUnderwater = $worksUnderwater;
|
|
$this->networkPropertiesDirty = true;
|
|
}
|
|
|
|
public function attack(EntityDamageEvent $source) : void{
|
|
if($source->getCause() === EntityDamageEvent::CAUSE_VOID){
|
|
parent::attack($source);
|
|
}
|
|
}
|
|
|
|
protected function initEntity(CompoundTag $nbt) : void{
|
|
parent::initEntity($nbt);
|
|
|
|
$this->fuse = $nbt->getShort(self::TAG_FUSE, 80);
|
|
}
|
|
|
|
public function canCollideWith(Entity $entity) : bool{
|
|
return false;
|
|
}
|
|
|
|
public function saveNBT() : CompoundTag{
|
|
$nbt = parent::saveNBT();
|
|
$nbt->setShort(self::TAG_FUSE, $this->fuse);
|
|
|
|
return $nbt;
|
|
}
|
|
|
|
protected function entityBaseTick(int $tickDiff = 1) : bool{
|
|
if($this->closed){
|
|
return false;
|
|
}
|
|
|
|
$hasUpdate = parent::entityBaseTick($tickDiff);
|
|
|
|
if(!$this->isFlaggedForDespawn()){
|
|
$this->fuse -= $tickDiff;
|
|
$this->networkPropertiesDirty = true;
|
|
|
|
if($this->fuse <= 0){
|
|
$this->flagForDespawn();
|
|
$this->explode();
|
|
}
|
|
}
|
|
|
|
return $hasUpdate || $this->fuse >= 0;
|
|
}
|
|
|
|
public function explode() : void{
|
|
$ev = new EntityPreExplodeEvent($this, 4);
|
|
$ev->call();
|
|
if(!$ev->isCancelled()){
|
|
//TODO: deal with underwater TNT (underwater TNT treats water as if it has a blast resistance of 0)
|
|
$explosion = new Explosion(Position::fromObject($this->location->add(0, $this->size->getHeight() / 2, 0), $this->getWorld()), $ev->getRadius(), $this, $ev->getFireChance());
|
|
if($ev->isBlockBreaking()){
|
|
$explosion->explodeA();
|
|
}
|
|
$explosion->explodeB();
|
|
}
|
|
}
|
|
|
|
public function getPickedItem() : ?Item{
|
|
return VanillaBlocks::TNT()->setWorksUnderwater($this->worksUnderwater)->asItem();
|
|
}
|
|
|
|
protected function syncNetworkData(EntityMetadataCollection $properties) : void{
|
|
parent::syncNetworkData($properties);
|
|
|
|
$properties->setGenericFlag(EntityMetadataFlags::IGNITED, true);
|
|
$properties->setInt(EntityMetadataProperties::VARIANT, $this->worksUnderwater ? 1 : 0);
|
|
$properties->setInt(EntityMetadataProperties::FUSE_LENGTH, $this->fuse);
|
|
}
|
|
|
|
public function getOffsetPosition(Vector3 $vector3) : Vector3{
|
|
return $vector3->add(0, 0.49, 0);
|
|
}
|
|
}
|