mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-09-09 03:06:55 +00:00
Implemented Respawn Anchor (#6646)
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.
This commit is contained in:
@ -786,8 +786,9 @@ final class BlockTypeIds{
|
||||
public const RESIN_BRICKS = 10756;
|
||||
public const RESIN_CLUMP = 10757;
|
||||
public const CHISELED_RESIN_BRICKS = 10758;
|
||||
public const RESPAWN_ANCHOR = 10759;
|
||||
|
||||
public const FIRST_UNUSED_BLOCK_ID = 10759;
|
||||
public const FIRST_UNUSED_BLOCK_ID = 10760;
|
||||
|
||||
private static int $nextDynamicId = self::FIRST_UNUSED_BLOCK_ID;
|
||||
|
||||
|
123
src/block/RespawnAnchor.php
Normal file
123
src/block/RespawnAnchor.php
Normal file
@ -0,0 +1,123 @@
|
||||
<?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\block;
|
||||
|
||||
use pocketmine\data\runtime\RuntimeDataDescriber;
|
||||
use pocketmine\event\block\BlockPreExplodeEvent;
|
||||
use pocketmine\event\player\PlayerRespawnAnchorUseEvent;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\ItemTypeIds;
|
||||
use pocketmine\lang\KnownTranslationFactory;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\player\Player;
|
||||
use pocketmine\utils\TextFormat;
|
||||
use pocketmine\world\Explosion;
|
||||
use pocketmine\world\Position;
|
||||
use pocketmine\world\sound\RespawnAnchorChargeSound;
|
||||
use pocketmine\world\sound\RespawnAnchorSetSpawnSound;
|
||||
|
||||
final class RespawnAnchor extends Opaque{
|
||||
private const MIN_CHARGES = 0;
|
||||
private const MAX_CHARGES = 4;
|
||||
|
||||
private int $charges = self::MIN_CHARGES;
|
||||
|
||||
protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{
|
||||
$w->boundedIntAuto(self::MIN_CHARGES, self::MAX_CHARGES, $this->charges);
|
||||
}
|
||||
|
||||
public function getCharges() : int{
|
||||
return $this->charges;
|
||||
}
|
||||
|
||||
/** @return $this */
|
||||
public function setCharges(int $charges) : self{
|
||||
if($charges < self::MIN_CHARGES || $charges > self::MAX_CHARGES){
|
||||
throw new \InvalidArgumentException("Charges must be between " . self::MIN_CHARGES . " and " . self::MAX_CHARGES . ", given: $charges");
|
||||
}
|
||||
$this->charges = $charges;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getLightLevel() : int{
|
||||
return $this->charges > 0 ? ($this->charges * 4) - 1 : 0;
|
||||
}
|
||||
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
|
||||
if($item->getTypeId() === ItemTypeIds::fromBlockTypeId(BlockTypeIds::GLOWSTONE) && $this->charges < self::MAX_CHARGES){
|
||||
$this->position->getWorld()->setBlock($this->position, $this->setCharges($this->charges + 1));
|
||||
$this->position->getWorld()->addSound($this->position, new RespawnAnchorChargeSound());
|
||||
return true;
|
||||
}
|
||||
|
||||
if($this->charges > self::MIN_CHARGES){
|
||||
if($player === null){
|
||||
return false;
|
||||
}
|
||||
|
||||
$ev = new PlayerRespawnAnchorUseEvent($player, $this, PlayerRespawnAnchorUseEvent::ACTION_EXPLODE);
|
||||
$ev->call();
|
||||
if($ev->isCancelled()){
|
||||
return false;
|
||||
}
|
||||
|
||||
switch($ev->getAction()){
|
||||
case PlayerRespawnAnchorUseEvent::ACTION_EXPLODE:
|
||||
$this->explode($player);
|
||||
return false;
|
||||
|
||||
case PlayerRespawnAnchorUseEvent::ACTION_SET_SPAWN:
|
||||
if($player->getSpawn() !== null && $player->getSpawn()->equals($this->position)){
|
||||
return true;
|
||||
}
|
||||
|
||||
$player->setSpawn($this->position);
|
||||
$this->position->getWorld()->addSound($this->position, new RespawnAnchorSetSpawnSound());
|
||||
$player->sendMessage(KnownTranslationFactory::tile_respawn_anchor_respawnSet()->prefix(TextFormat::GRAY));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private function explode(?Player $player) : void{
|
||||
$ev = new BlockPreExplodeEvent($this, 5, $player);
|
||||
$ev->setIncendiary(true);
|
||||
|
||||
$ev->call();
|
||||
if($ev->isCancelled()){
|
||||
return;
|
||||
}
|
||||
|
||||
$this->position->getWorld()->setBlock($this->position, VanillaBlocks::AIR());
|
||||
|
||||
$explosion = new Explosion(Position::fromObject($this->position->add(0.5, 0.5, 0.5), $this->position->getWorld()), $ev->getRadius(), $this);
|
||||
$explosion->setFireChance($ev->getFireChance());
|
||||
|
||||
if($ev->isBlockBreaking()){
|
||||
$explosion->explodeA();
|
||||
}
|
||||
$explosion->explodeB();
|
||||
}
|
||||
}
|
@ -694,6 +694,7 @@ use function strtolower;
|
||||
* @method static Stair RESIN_BRICK_STAIRS()
|
||||
* @method static Wall RESIN_BRICK_WALL()
|
||||
* @method static ResinClump RESIN_CLUMP()
|
||||
* @method static RespawnAnchor RESPAWN_ANCHOR()
|
||||
* @method static DoublePlant ROSE_BUSH()
|
||||
* @method static Sand SAND()
|
||||
* @method static Opaque SANDSTONE()
|
||||
@ -1647,6 +1648,8 @@ final class VanillaBlocks{
|
||||
self::register("warped_roots", fn(BID $id) => new NetherRoots($id, "Warped Roots", $netherRootsInfo));
|
||||
|
||||
self::register("chain", fn(BID $id) => new Chain($id, "Chain", new Info(BreakInfo::pickaxe(5.0, ToolTier::WOOD, 30.0))));
|
||||
|
||||
self::register("respawn_anchor", fn(BID $id) => new RespawnAnchor($id, "Respawn Anchor", new Info(BreakInfo::pickaxe(50.0, ToolTier::DIAMOND, 6000.0))));
|
||||
}
|
||||
|
||||
private static function registerBlocksR17() : void{
|
||||
|
Reference in New Issue
Block a user