mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-09-08 10:53:05 +00:00
Removed pocketmine subdirectory, map PSR-4 style
This commit is contained in:
131
src/block/tile/Banner.php
Normal file
131
src/block/tile/Banner.php
Normal file
@ -0,0 +1,131 @@
|
||||
<?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\tile;
|
||||
|
||||
use Ds\Deque;
|
||||
use pocketmine\block\utils\BannerPattern;
|
||||
use pocketmine\block\utils\DyeColor;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\nbt\tag\CompoundTag;
|
||||
use pocketmine\nbt\tag\IntTag;
|
||||
use pocketmine\nbt\tag\ListTag;
|
||||
use pocketmine\world\World;
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
* @see \pocketmine\block\Banner
|
||||
*/
|
||||
class Banner extends Spawnable{
|
||||
|
||||
public const TAG_BASE = "Base";
|
||||
public const TAG_PATTERNS = "Patterns";
|
||||
public const TAG_PATTERN_COLOR = "Color";
|
||||
public const TAG_PATTERN_NAME = "Pattern";
|
||||
|
||||
/** @var DyeColor */
|
||||
private $baseColor;
|
||||
|
||||
/** @var BannerPattern[]|Deque */
|
||||
private $patterns = [];
|
||||
|
||||
public function __construct(World $world, Vector3 $pos){
|
||||
$this->baseColor = DyeColor::BLACK();
|
||||
$this->patterns = new Deque();
|
||||
parent::__construct($world, $pos);
|
||||
}
|
||||
|
||||
public function readSaveData(CompoundTag $nbt) : void{
|
||||
if($nbt->hasTag(self::TAG_BASE, IntTag::class)){
|
||||
$this->baseColor = DyeColor::fromMagicNumber($nbt->getInt(self::TAG_BASE), true);
|
||||
}
|
||||
|
||||
$patterns = $nbt->getListTag(self::TAG_PATTERNS);
|
||||
if($patterns !== null){
|
||||
/** @var CompoundTag $pattern */
|
||||
foreach($patterns as $pattern){
|
||||
$this->patterns[] = new BannerPattern($pattern->getString(self::TAG_PATTERN_NAME), DyeColor::fromMagicNumber($pattern->getInt(self::TAG_PATTERN_COLOR), true));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected function writeSaveData(CompoundTag $nbt) : void{
|
||||
$nbt->setInt(self::TAG_BASE, $this->baseColor->getInvertedMagicNumber());
|
||||
$patterns = new ListTag();
|
||||
foreach($this->patterns as $pattern){
|
||||
$patterns->push(CompoundTag::create()
|
||||
->setString(self::TAG_PATTERN_NAME, $pattern->getId())
|
||||
->setInt(self::TAG_PATTERN_COLOR, $pattern->getColor()->getInvertedMagicNumber())
|
||||
);
|
||||
}
|
||||
$nbt->setTag(self::TAG_PATTERNS, $patterns);
|
||||
}
|
||||
|
||||
protected function addAdditionalSpawnData(CompoundTag $nbt) : void{
|
||||
$nbt->setInt(self::TAG_BASE, $this->baseColor->getInvertedMagicNumber());
|
||||
$patterns = new ListTag();
|
||||
foreach($this->patterns as $pattern){
|
||||
$patterns->push(CompoundTag::create()
|
||||
->setString(self::TAG_PATTERN_NAME, $pattern->getId())
|
||||
->setInt(self::TAG_PATTERN_COLOR, $pattern->getColor()->getInvertedMagicNumber())
|
||||
);
|
||||
}
|
||||
$nbt->setTag(self::TAG_PATTERNS, $patterns);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the color of the banner base.
|
||||
*
|
||||
* @return DyeColor
|
||||
*/
|
||||
public function getBaseColor() : DyeColor{
|
||||
return $this->baseColor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the color of the banner base.
|
||||
*
|
||||
* @param DyeColor $color
|
||||
*/
|
||||
public function setBaseColor(DyeColor $color) : void{
|
||||
$this->baseColor = $color;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BannerPattern[]|Deque
|
||||
*/
|
||||
public function getPatterns() : Deque{
|
||||
return $this->patterns;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param BannerPattern[]|Deque $patterns
|
||||
*/
|
||||
public function setPatterns(Deque $patterns) : void{
|
||||
$this->patterns = $patterns;
|
||||
}
|
||||
|
||||
public function getDefaultName() : string{
|
||||
return "Banner";
|
||||
}
|
||||
}
|
63
src/block/tile/Bed.php
Normal file
63
src/block/tile/Bed.php
Normal file
@ -0,0 +1,63 @@
|
||||
<?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\tile;
|
||||
|
||||
use pocketmine\block\utils\DyeColor;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\nbt\tag\ByteTag;
|
||||
use pocketmine\nbt\tag\CompoundTag;
|
||||
use pocketmine\world\World;
|
||||
|
||||
class Bed extends Spawnable{
|
||||
public const TAG_COLOR = "color";
|
||||
/** @var DyeColor */
|
||||
private $color;
|
||||
|
||||
public function __construct(World $world, Vector3 $pos){
|
||||
$this->color = DyeColor::RED();
|
||||
parent::__construct($world, $pos);
|
||||
}
|
||||
|
||||
public function getColor() : DyeColor{
|
||||
return $this->color;
|
||||
}
|
||||
|
||||
public function setColor(DyeColor $color) : void{
|
||||
$this->color = $color;
|
||||
}
|
||||
|
||||
public function readSaveData(CompoundTag $nbt) : void{
|
||||
if($nbt->hasTag(self::TAG_COLOR, ByteTag::class)){
|
||||
$this->color = DyeColor::fromMagicNumber($nbt->getByte(self::TAG_COLOR));
|
||||
}
|
||||
}
|
||||
|
||||
protected function writeSaveData(CompoundTag $nbt) : void{
|
||||
$nbt->setByte(self::TAG_COLOR, $this->color->getMagicNumber());
|
||||
}
|
||||
|
||||
protected function addAdditionalSpawnData(CompoundTag $nbt) : void{
|
||||
$nbt->setByte(self::TAG_COLOR, $this->color->getMagicNumber());
|
||||
}
|
||||
}
|
113
src/block/tile/BrewingStand.php
Normal file
113
src/block/tile/BrewingStand.php
Normal file
@ -0,0 +1,113 @@
|
||||
<?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\tile;
|
||||
|
||||
use pocketmine\inventory\BrewingStandInventory;
|
||||
use pocketmine\inventory\CallbackInventoryChangeListener;
|
||||
use pocketmine\inventory\Inventory;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\nbt\tag\CompoundTag;
|
||||
use pocketmine\world\World;
|
||||
|
||||
class BrewingStand extends Spawnable implements Container, Nameable{
|
||||
|
||||
use ContainerTrait;
|
||||
use NameableTrait;
|
||||
|
||||
private const TAG_BREW_TIME = "BrewTime"; //TAG_Short
|
||||
private const TAG_BREW_TIME_PE = "CookTime"; //TAG_Short
|
||||
private const TAG_MAX_FUEL_TIME = "FuelTotal"; //TAG_Short
|
||||
private const TAG_REMAINING_FUEL_TIME = "Fuel"; //TAG_Byte
|
||||
private const TAG_REMAINING_FUEL_TIME_PE = "FuelAmount"; //TAG_Short
|
||||
|
||||
/** @var BrewingStandInventory */
|
||||
private $inventory;
|
||||
|
||||
/** @var int */
|
||||
private $brewTime = 0;
|
||||
/** @var int */
|
||||
private $maxFuelTime = 0;
|
||||
/** @var int */
|
||||
private $remainingFuelTime = 0;
|
||||
|
||||
|
||||
public function __construct(World $world, Vector3 $pos){
|
||||
$this->inventory = new BrewingStandInventory($this);
|
||||
$this->inventory->addChangeListeners(CallbackInventoryChangeListener::onAnyChange(function(Inventory $unused){
|
||||
$this->world->scheduleDelayedBlockUpdate($this->getBlock(), 1);
|
||||
}));
|
||||
parent::__construct($world, $pos);
|
||||
}
|
||||
|
||||
public function readSaveData(CompoundTag $nbt) : void{
|
||||
$this->loadName($nbt);
|
||||
$this->loadItems($nbt);
|
||||
|
||||
$this->brewTime = $nbt->getShort(self::TAG_BREW_TIME, $nbt->getShort(self::TAG_BREW_TIME_PE, 0));
|
||||
$this->maxFuelTime = $nbt->getShort(self::TAG_MAX_FUEL_TIME, 0);
|
||||
$this->remainingFuelTime = $nbt->getByte(self::TAG_REMAINING_FUEL_TIME, $nbt->getShort(self::TAG_REMAINING_FUEL_TIME_PE, 0));
|
||||
if($this->maxFuelTime === 0){
|
||||
$this->maxFuelTime = $this->remainingFuelTime;
|
||||
}
|
||||
if($this->remainingFuelTime === 0){
|
||||
$this->maxFuelTime = $this->remainingFuelTime = $this->brewTime = 0;
|
||||
}
|
||||
}
|
||||
|
||||
protected function writeSaveData(CompoundTag $nbt) : void{
|
||||
$this->saveName($nbt);
|
||||
$this->saveItems($nbt);
|
||||
|
||||
$nbt->setShort(self::TAG_BREW_TIME_PE, $this->brewTime);
|
||||
$nbt->setShort(self::TAG_MAX_FUEL_TIME, $this->maxFuelTime);
|
||||
$nbt->setShort(self::TAG_REMAINING_FUEL_TIME_PE, $this->remainingFuelTime);
|
||||
}
|
||||
|
||||
public function getDefaultName() : string{
|
||||
return "Brewing Stand";
|
||||
}
|
||||
|
||||
public function close() : void{
|
||||
if(!$this->closed){
|
||||
$this->inventory->removeAllViewers();
|
||||
$this->inventory = null;
|
||||
|
||||
parent::close();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BrewingStandInventory
|
||||
*/
|
||||
public function getInventory(){
|
||||
return $this->inventory;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BrewingStandInventory
|
||||
*/
|
||||
public function getRealInventory(){
|
||||
return $this->inventory;
|
||||
}
|
||||
}
|
242
src/block/tile/Chest.php
Normal file
242
src/block/tile/Chest.php
Normal file
@ -0,0 +1,242 @@
|
||||
<?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\tile;
|
||||
|
||||
use pocketmine\inventory\ChestInventory;
|
||||
use pocketmine\inventory\DoubleChestInventory;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\nbt\tag\CompoundTag;
|
||||
use pocketmine\nbt\tag\IntTag;
|
||||
use pocketmine\world\World;
|
||||
use function abs;
|
||||
|
||||
class Chest extends Spawnable implements Container, Nameable{
|
||||
use NameableTrait {
|
||||
addAdditionalSpawnData as addNameSpawnData;
|
||||
}
|
||||
use ContainerTrait {
|
||||
onBlockDestroyedHook as containerTraitBlockDestroyedHook;
|
||||
}
|
||||
|
||||
public const TAG_PAIRX = "pairx";
|
||||
public const TAG_PAIRZ = "pairz";
|
||||
public const TAG_PAIR_LEAD = "pairlead";
|
||||
|
||||
/** @var ChestInventory */
|
||||
protected $inventory;
|
||||
/** @var DoubleChestInventory */
|
||||
protected $doubleInventory = null;
|
||||
|
||||
/** @var int|null */
|
||||
private $pairX;
|
||||
/** @var int|null */
|
||||
private $pairZ;
|
||||
|
||||
public function __construct(World $world, Vector3 $pos){
|
||||
$this->inventory = new ChestInventory($this);
|
||||
parent::__construct($world, $pos);
|
||||
}
|
||||
|
||||
public function readSaveData(CompoundTag $nbt) : void{
|
||||
if($nbt->hasTag(self::TAG_PAIRX, IntTag::class) and $nbt->hasTag(self::TAG_PAIRZ, IntTag::class)){
|
||||
$pairX = $nbt->getInt(self::TAG_PAIRX);
|
||||
$pairZ = $nbt->getInt(self::TAG_PAIRZ);
|
||||
if(
|
||||
($this->x === $pairX and abs($this->z - $pairZ) === 1) or
|
||||
($this->z === $pairZ and abs($this->x - $pairX) === 1)
|
||||
){
|
||||
$this->pairX = $pairX;
|
||||
$this->pairZ = $pairZ;
|
||||
}else{
|
||||
$this->pairX = $this->pairZ = null;
|
||||
}
|
||||
}
|
||||
$this->loadName($nbt);
|
||||
$this->loadItems($nbt);
|
||||
}
|
||||
|
||||
protected function writeSaveData(CompoundTag $nbt) : void{
|
||||
if($this->isPaired()){
|
||||
$nbt->setInt(self::TAG_PAIRX, $this->pairX);
|
||||
$nbt->setInt(self::TAG_PAIRZ, $this->pairZ);
|
||||
}
|
||||
$this->saveName($nbt);
|
||||
$this->saveItems($nbt);
|
||||
}
|
||||
|
||||
public function getCleanedNBT() : ?CompoundTag{
|
||||
$tag = parent::getCleanedNBT();
|
||||
if($tag !== null){
|
||||
//TODO: replace this with a purpose flag on writeSaveData()
|
||||
$tag->removeTag(self::TAG_PAIRX, self::TAG_PAIRZ);
|
||||
}
|
||||
return $tag;
|
||||
}
|
||||
|
||||
public function close() : void{
|
||||
if(!$this->closed){
|
||||
$this->inventory->removeAllViewers();
|
||||
|
||||
if($this->doubleInventory !== null){
|
||||
if($this->isPaired() and $this->world->isChunkLoaded($this->pairX >> 4, $this->pairZ >> 4)){
|
||||
$this->doubleInventory->removeAllViewers();
|
||||
$this->doubleInventory->invalidate();
|
||||
if(($pair = $this->getPair()) !== null){
|
||||
$pair->doubleInventory = null;
|
||||
}
|
||||
}
|
||||
$this->doubleInventory = null;
|
||||
}
|
||||
|
||||
$this->inventory = null;
|
||||
|
||||
parent::close();
|
||||
}
|
||||
}
|
||||
|
||||
protected function onBlockDestroyedHook() : void{
|
||||
$this->unpair();
|
||||
$this->containerTraitBlockDestroyedHook();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ChestInventory|DoubleChestInventory
|
||||
*/
|
||||
public function getInventory(){
|
||||
if($this->isPaired() and $this->doubleInventory === null){
|
||||
$this->checkPairing();
|
||||
}
|
||||
return $this->doubleInventory instanceof DoubleChestInventory ? $this->doubleInventory : $this->inventory;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ChestInventory
|
||||
*/
|
||||
public function getRealInventory(){
|
||||
return $this->inventory;
|
||||
}
|
||||
|
||||
protected function checkPairing(){
|
||||
if($this->isPaired() and !$this->getWorld()->isInLoadedTerrain(new Vector3($this->pairX, $this->y, $this->pairZ))){
|
||||
//paired to a tile in an unloaded chunk
|
||||
$this->doubleInventory = null;
|
||||
|
||||
}elseif(($pair = $this->getPair()) instanceof Chest){
|
||||
if(!$pair->isPaired()){
|
||||
$pair->createPair($this);
|
||||
$pair->checkPairing();
|
||||
}
|
||||
if($this->doubleInventory === null){
|
||||
if($pair->doubleInventory !== null){
|
||||
$this->doubleInventory = $pair->doubleInventory;
|
||||
}else{
|
||||
if(($pair->x + ($pair->z << 15)) > ($this->x + ($this->z << 15))){ //Order them correctly
|
||||
$this->doubleInventory = $pair->doubleInventory = new DoubleChestInventory($pair, $this);
|
||||
}else{
|
||||
$this->doubleInventory = $pair->doubleInventory = new DoubleChestInventory($this, $pair);
|
||||
}
|
||||
}
|
||||
}
|
||||
}else{
|
||||
$this->doubleInventory = null;
|
||||
$this->pairX = $this->pairZ = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getDefaultName() : string{
|
||||
return "Chest";
|
||||
}
|
||||
|
||||
public function isPaired(){
|
||||
return $this->pairX !== null and $this->pairZ !== null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Chest|null
|
||||
*/
|
||||
public function getPair() : ?Chest{
|
||||
if($this->isPaired()){
|
||||
$tile = $this->getWorld()->getTileAt($this->pairX, $this->y, $this->pairZ);
|
||||
if($tile instanceof Chest){
|
||||
return $tile;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public function pairWith(Chest $tile){
|
||||
if($this->isPaired() or $tile->isPaired()){
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->createPair($tile);
|
||||
|
||||
$this->setDirty();
|
||||
$tile->setDirty();
|
||||
$this->checkPairing();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private function createPair(Chest $tile){
|
||||
$this->pairX = $tile->x;
|
||||
$this->pairZ = $tile->z;
|
||||
|
||||
$tile->pairX = $this->x;
|
||||
$tile->pairZ = $this->z;
|
||||
}
|
||||
|
||||
public function unpair(){
|
||||
if(!$this->isPaired()){
|
||||
return false;
|
||||
}
|
||||
|
||||
$tile = $this->getPair();
|
||||
$this->pairX = $this->pairZ = null;
|
||||
|
||||
$this->setDirty();
|
||||
|
||||
if($tile instanceof Chest){
|
||||
$tile->pairX = $tile->pairZ = null;
|
||||
$tile->checkPairing();
|
||||
$tile->setDirty();
|
||||
}
|
||||
$this->checkPairing();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function addAdditionalSpawnData(CompoundTag $nbt) : void{
|
||||
if($this->isPaired()){
|
||||
$nbt->setInt(self::TAG_PAIRX, $this->pairX);
|
||||
$nbt->setInt(self::TAG_PAIRZ, $this->pairZ);
|
||||
}
|
||||
|
||||
$this->addNameSpawnData($nbt);
|
||||
}
|
||||
}
|
60
src/block/tile/Comparator.php
Normal file
60
src/block/tile/Comparator.php
Normal file
@ -0,0 +1,60 @@
|
||||
<?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\tile;
|
||||
|
||||
use pocketmine\block\RedstoneComparator;
|
||||
use pocketmine\nbt\tag\CompoundTag;
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
* @see RedstoneComparator
|
||||
*/
|
||||
class Comparator extends Tile{
|
||||
private const TAG_OUTPUT_SIGNAL = "OutputSignal"; //int
|
||||
|
||||
/** @var int */
|
||||
protected $signalStrength = 0;
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getSignalStrength() : int{
|
||||
return $this->signalStrength;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $signalStrength
|
||||
*/
|
||||
public function setSignalStrength(int $signalStrength) : void{
|
||||
$this->signalStrength = $signalStrength;
|
||||
}
|
||||
|
||||
public function readSaveData(CompoundTag $nbt) : void{
|
||||
$this->signalStrength = $nbt->getInt(self::TAG_OUTPUT_SIGNAL, 0, true);
|
||||
}
|
||||
|
||||
protected function writeSaveData(CompoundTag $nbt) : void{
|
||||
$nbt->setInt(self::TAG_OUTPUT_SIGNAL, $this->signalStrength);
|
||||
}
|
||||
}
|
46
src/block/tile/Container.php
Normal file
46
src/block/tile/Container.php
Normal file
@ -0,0 +1,46 @@
|
||||
<?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\tile;
|
||||
|
||||
use pocketmine\inventory\Inventory;
|
||||
use pocketmine\inventory\InventoryHolder;
|
||||
|
||||
interface Container extends InventoryHolder{
|
||||
public const TAG_ITEMS = "Items";
|
||||
public const TAG_LOCK = "Lock";
|
||||
|
||||
/**
|
||||
* @return Inventory
|
||||
*/
|
||||
public function getRealInventory();
|
||||
|
||||
/**
|
||||
* Returns whether this container can be opened by an item with the given custom name.
|
||||
*
|
||||
* @param string $key
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function canOpenWith(string $key) : bool;
|
||||
}
|
108
src/block/tile/ContainerTrait.php
Normal file
108
src/block/tile/ContainerTrait.php
Normal file
@ -0,0 +1,108 @@
|
||||
<?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\tile;
|
||||
|
||||
use pocketmine\inventory\Inventory;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\nbt\NBT;
|
||||
use pocketmine\nbt\tag\CompoundTag;
|
||||
use pocketmine\nbt\tag\ListTag;
|
||||
use pocketmine\nbt\tag\StringTag;
|
||||
use pocketmine\world\Position;
|
||||
|
||||
/**
|
||||
* This trait implements most methods in the {@link Container} interface. It should only be used by Tiles.
|
||||
*/
|
||||
trait ContainerTrait{
|
||||
/** @var string|null */
|
||||
private $lock = null;
|
||||
|
||||
/**
|
||||
* @return Inventory
|
||||
*/
|
||||
abstract public function getRealInventory();
|
||||
|
||||
protected function loadItems(CompoundTag $tag) : void{
|
||||
if($tag->hasTag(Container::TAG_ITEMS, ListTag::class)){
|
||||
$inventoryTag = $tag->getListTag(Container::TAG_ITEMS);
|
||||
|
||||
$inventory = $this->getRealInventory();
|
||||
$listeners = $inventory->getChangeListeners();
|
||||
$inventory->removeChangeListeners(...$listeners); //prevent any events being fired by initialization
|
||||
$inventory->clearAll();
|
||||
/** @var CompoundTag $itemNBT */
|
||||
foreach($inventoryTag as $itemNBT){
|
||||
$inventory->setItem($itemNBT->getByte("Slot"), Item::nbtDeserialize($itemNBT));
|
||||
}
|
||||
$inventory->addChangeListeners(...$listeners);
|
||||
}
|
||||
|
||||
if($tag->hasTag(Container::TAG_LOCK, StringTag::class)){
|
||||
$this->lock = $tag->getString(Container::TAG_LOCK);
|
||||
}
|
||||
}
|
||||
|
||||
protected function saveItems(CompoundTag $tag) : void{
|
||||
$items = [];
|
||||
foreach($this->getRealInventory()->getContents() as $slot => $item){
|
||||
$items[] = $item->nbtSerialize($slot);
|
||||
}
|
||||
|
||||
$tag->setTag(Container::TAG_ITEMS, new ListTag($items, NBT::TAG_Compound));
|
||||
|
||||
if($this->lock !== null){
|
||||
$tag->setString(Container::TAG_LOCK, $this->lock);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see Container::canOpenWith()
|
||||
*
|
||||
* @param string $key
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function canOpenWith(string $key) : bool{
|
||||
return $this->lock === null or $this->lock === $key;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see Position::asPosition()
|
||||
* @return Position
|
||||
*/
|
||||
abstract protected function asPosition() : Position;
|
||||
|
||||
/**
|
||||
* @see Tile::onBlockDestroyedHook()
|
||||
*/
|
||||
protected function onBlockDestroyedHook() : void{
|
||||
$inv = $this->getRealInventory();
|
||||
$pos = $this->asPosition();
|
||||
|
||||
foreach($inv->getContents() as $k => $item){
|
||||
$pos->world->dropItem($pos->add(0.5, 0.5, 0.5), $item);
|
||||
}
|
||||
$inv->clearAll(false);
|
||||
}
|
||||
}
|
44
src/block/tile/DaylightSensor.php
Normal file
44
src/block/tile/DaylightSensor.php
Normal file
@ -0,0 +1,44 @@
|
||||
<?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\tile;
|
||||
|
||||
use pocketmine\nbt\tag\CompoundTag;
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
* As per the wiki, this is an old hack to force daylight sensors to get updated every game tick. This is necessary to
|
||||
* ensure that the daylight sensor's power output is always up to date with the current world time.
|
||||
* It's theoretically possible to implement this without a blockentity, but this is here to ensure that vanilla can
|
||||
* understand daylight sensors in worlds created by PM.
|
||||
*/
|
||||
class DaylightSensor extends Tile{
|
||||
|
||||
public function readSaveData(CompoundTag $nbt) : void{
|
||||
|
||||
}
|
||||
|
||||
protected function writeSaveData(CompoundTag $nbt) : void{
|
||||
|
||||
}
|
||||
}
|
38
src/block/tile/EnchantTable.php
Normal file
38
src/block/tile/EnchantTable.php
Normal file
@ -0,0 +1,38 @@
|
||||
<?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\tile;
|
||||
|
||||
class EnchantTable extends Spawnable implements Nameable{
|
||||
use NameableTrait {
|
||||
loadName as public readSaveData;
|
||||
saveName as writeSaveData;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getDefaultName() : string{
|
||||
return "Enchanting Table";
|
||||
}
|
||||
}
|
41
src/block/tile/EnderChest.php
Normal file
41
src/block/tile/EnderChest.php
Normal file
@ -0,0 +1,41 @@
|
||||
<?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\tile;
|
||||
|
||||
use pocketmine\nbt\tag\CompoundTag;
|
||||
|
||||
class EnderChest extends Spawnable{
|
||||
|
||||
public function readSaveData(CompoundTag $nbt) : void{
|
||||
|
||||
}
|
||||
|
||||
protected function writeSaveData(CompoundTag $nbt) : void{
|
||||
|
||||
}
|
||||
|
||||
protected function addAdditionalSpawnData(CompoundTag $nbt) : void{
|
||||
|
||||
}
|
||||
}
|
81
src/block/tile/FlowerPot.php
Normal file
81
src/block/tile/FlowerPot.php
Normal file
@ -0,0 +1,81 @@
|
||||
<?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\tile;
|
||||
|
||||
use pocketmine\block\Air;
|
||||
use pocketmine\block\Block;
|
||||
use pocketmine\block\BlockFactory;
|
||||
use pocketmine\nbt\tag\CompoundTag;
|
||||
use pocketmine\nbt\tag\IntTag;
|
||||
use pocketmine\nbt\tag\ShortTag;
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
* @see \pocketmine\block\FlowerPot
|
||||
*/
|
||||
class FlowerPot extends Spawnable{
|
||||
private const TAG_ITEM = "item";
|
||||
private const TAG_ITEM_DATA = "mData";
|
||||
|
||||
/** @var Block|null */
|
||||
private $plant = null;
|
||||
|
||||
public function readSaveData(CompoundTag $nbt) : void{
|
||||
if($nbt->hasTag(self::TAG_ITEM, ShortTag::class) and $nbt->hasTag(self::TAG_ITEM_DATA, IntTag::class)){
|
||||
try{
|
||||
$this->setPlant(BlockFactory::get($nbt->getShort(self::TAG_ITEM), $nbt->getInt(self::TAG_ITEM_DATA)));
|
||||
}catch(\InvalidArgumentException $e){
|
||||
//noop
|
||||
}
|
||||
}else{
|
||||
//TODO: new PlantBlock tag
|
||||
}
|
||||
}
|
||||
|
||||
protected function writeSaveData(CompoundTag $nbt) : void{
|
||||
if($this->plant !== null){
|
||||
$nbt->setShort(self::TAG_ITEM, $this->plant->getId());
|
||||
$nbt->setInt(self::TAG_ITEM_DATA, $this->plant->getMeta());
|
||||
}
|
||||
}
|
||||
|
||||
public function getPlant() : ?Block{
|
||||
return $this->plant !== null ? clone $this->plant : null;
|
||||
}
|
||||
|
||||
public function setPlant(?Block $plant) : void{
|
||||
if($plant === null or $plant instanceof Air){
|
||||
$this->plant = null;
|
||||
}else{
|
||||
$this->plant = clone $plant;
|
||||
}
|
||||
}
|
||||
|
||||
protected function addAdditionalSpawnData(CompoundTag $nbt) : void{
|
||||
if($this->plant !== null){
|
||||
$nbt->setShort(self::TAG_ITEM, $this->plant->getId());
|
||||
$nbt->setInt(self::TAG_ITEM_DATA, $this->plant->getMeta());
|
||||
}
|
||||
}
|
||||
}
|
224
src/block/tile/Furnace.php
Normal file
224
src/block/tile/Furnace.php
Normal file
@ -0,0 +1,224 @@
|
||||
<?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\tile;
|
||||
|
||||
use pocketmine\block\Furnace as BlockFurnace;
|
||||
use pocketmine\crafting\FurnaceRecipe;
|
||||
use pocketmine\event\inventory\FurnaceBurnEvent;
|
||||
use pocketmine\event\inventory\FurnaceSmeltEvent;
|
||||
use pocketmine\inventory\CallbackInventoryChangeListener;
|
||||
use pocketmine\inventory\FurnaceInventory;
|
||||
use pocketmine\inventory\Inventory;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\ItemFactory;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\nbt\tag\CompoundTag;
|
||||
use pocketmine\network\mcpe\protocol\ContainerSetDataPacket;
|
||||
use pocketmine\world\World;
|
||||
use function max;
|
||||
|
||||
class Furnace extends Spawnable implements Container, Nameable{
|
||||
use NameableTrait;
|
||||
use ContainerTrait;
|
||||
|
||||
public const TAG_BURN_TIME = "BurnTime";
|
||||
public const TAG_COOK_TIME = "CookTime";
|
||||
public const TAG_MAX_TIME = "MaxTime";
|
||||
|
||||
/** @var FurnaceInventory */
|
||||
protected $inventory;
|
||||
/** @var int */
|
||||
private $remainingFuelTime = 0;
|
||||
/** @var int */
|
||||
private $cookTime = 0;
|
||||
/** @var int */
|
||||
private $maxFuelTime = 0;
|
||||
|
||||
public function __construct(World $world, Vector3 $pos){
|
||||
$this->inventory = new FurnaceInventory($this);
|
||||
$this->inventory->addChangeListeners(CallbackInventoryChangeListener::onAnyChange(
|
||||
function(Inventory $unused) : void{
|
||||
$this->world->scheduleDelayedBlockUpdate($this->asVector3(), 1);
|
||||
})
|
||||
);
|
||||
|
||||
parent::__construct($world, $pos);
|
||||
}
|
||||
|
||||
public function readSaveData(CompoundTag $nbt) : void{
|
||||
$this->remainingFuelTime = max(0, $nbt->getShort(self::TAG_BURN_TIME, $this->remainingFuelTime, true));
|
||||
|
||||
$this->cookTime = $nbt->getShort(self::TAG_COOK_TIME, $this->cookTime, true);
|
||||
if($this->remainingFuelTime === 0){
|
||||
$this->cookTime = 0;
|
||||
}
|
||||
|
||||
$this->maxFuelTime = $nbt->getShort(self::TAG_MAX_TIME, $this->maxFuelTime, true);
|
||||
if($this->maxFuelTime === 0){
|
||||
$this->maxFuelTime = $this->remainingFuelTime;
|
||||
}
|
||||
|
||||
$this->loadName($nbt);
|
||||
$this->loadItems($nbt);
|
||||
}
|
||||
|
||||
protected function writeSaveData(CompoundTag $nbt) : void{
|
||||
$nbt->setShort(self::TAG_BURN_TIME, $this->remainingFuelTime);
|
||||
$nbt->setShort(self::TAG_COOK_TIME, $this->cookTime);
|
||||
$nbt->setShort(self::TAG_MAX_TIME, $this->maxFuelTime);
|
||||
$this->saveName($nbt);
|
||||
$this->saveItems($nbt);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getDefaultName() : string{
|
||||
return "Furnace";
|
||||
}
|
||||
|
||||
public function close() : void{
|
||||
if(!$this->closed){
|
||||
$this->inventory->removeAllViewers();
|
||||
$this->inventory = null;
|
||||
|
||||
parent::close();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return FurnaceInventory
|
||||
*/
|
||||
public function getInventory(){
|
||||
return $this->inventory;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return FurnaceInventory
|
||||
*/
|
||||
public function getRealInventory(){
|
||||
return $this->getInventory();
|
||||
}
|
||||
|
||||
protected function checkFuel(Item $fuel){
|
||||
$ev = new FurnaceBurnEvent($this, $fuel, $fuel->getFuelTime());
|
||||
$ev->call();
|
||||
if($ev->isCancelled()){
|
||||
return;
|
||||
}
|
||||
|
||||
$this->maxFuelTime = $this->remainingFuelTime = $ev->getBurnTime();
|
||||
|
||||
$block = $this->getBlock();
|
||||
if($block instanceof BlockFurnace and !$block->isLit()){
|
||||
$block->setLit(true);
|
||||
$this->getWorld()->setBlock($block, $block);
|
||||
}
|
||||
|
||||
if($this->remainingFuelTime > 0 and $ev->isBurning()){
|
||||
$fuel->pop();
|
||||
$this->inventory->setFuel($fuel);
|
||||
}
|
||||
}
|
||||
|
||||
public function onUpdate() : bool{
|
||||
//TODO: move this to Block
|
||||
if($this->closed){
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->timings->startTiming();
|
||||
|
||||
$prevCookTime = $this->cookTime;
|
||||
$prevRemainingFuelTime = $this->remainingFuelTime;
|
||||
$prevMaxFuelTime = $this->maxFuelTime;
|
||||
|
||||
$ret = false;
|
||||
|
||||
$fuel = $this->inventory->getFuel();
|
||||
$raw = $this->inventory->getSmelting();
|
||||
$product = $this->inventory->getResult();
|
||||
$smelt = $this->world->getServer()->getCraftingManager()->matchFurnaceRecipe($raw);
|
||||
$canSmelt = ($smelt instanceof FurnaceRecipe and $raw->getCount() > 0 and (($smelt->getResult()->equals($product) and $product->getCount() < $product->getMaxStackSize()) or $product->isNull()));
|
||||
|
||||
if($this->remainingFuelTime <= 0 and $canSmelt and $fuel->getFuelTime() > 0 and $fuel->getCount() > 0){
|
||||
$this->checkFuel($fuel);
|
||||
}
|
||||
|
||||
if($this->remainingFuelTime > 0){
|
||||
--$this->remainingFuelTime;
|
||||
|
||||
if($smelt instanceof FurnaceRecipe and $canSmelt){
|
||||
++$this->cookTime;
|
||||
|
||||
if($this->cookTime >= 200){ //10 seconds
|
||||
$product = ItemFactory::get($smelt->getResult()->getId(), $smelt->getResult()->getMeta(), $product->getCount() + 1);
|
||||
|
||||
$ev = new FurnaceSmeltEvent($this, $raw, $product);
|
||||
$ev->call();
|
||||
|
||||
if(!$ev->isCancelled()){
|
||||
$this->inventory->setResult($ev->getResult());
|
||||
$raw->pop();
|
||||
$this->inventory->setSmelting($raw);
|
||||
}
|
||||
|
||||
$this->cookTime -= 200;
|
||||
}
|
||||
}elseif($this->remainingFuelTime <= 0){
|
||||
$this->remainingFuelTime = $this->cookTime = $this->maxFuelTime = 0;
|
||||
}else{
|
||||
$this->cookTime = 0;
|
||||
}
|
||||
$ret = true;
|
||||
}else{
|
||||
$block = $this->getBlock();
|
||||
if($block instanceof BlockFurnace and $block->isLit()){
|
||||
$block->setLit(false);
|
||||
$this->getWorld()->setBlock($block, $block);
|
||||
}
|
||||
$this->remainingFuelTime = $this->cookTime = $this->maxFuelTime = 0;
|
||||
}
|
||||
|
||||
if($prevCookTime !== $this->cookTime){
|
||||
foreach($this->inventory->getViewers() as $v){
|
||||
$v->getNetworkSession()->getInvManager()->syncData($this->inventory, ContainerSetDataPacket::PROPERTY_FURNACE_SMELT_PROGRESS, $this->cookTime);
|
||||
}
|
||||
}
|
||||
if($prevRemainingFuelTime !== $this->remainingFuelTime){
|
||||
foreach($this->inventory->getViewers() as $v){
|
||||
$v->getNetworkSession()->getInvManager()->syncData($this->inventory, ContainerSetDataPacket::PROPERTY_FURNACE_REMAINING_FUEL_TIME, $this->remainingFuelTime);
|
||||
}
|
||||
}
|
||||
if($prevMaxFuelTime !== $this->maxFuelTime){
|
||||
foreach($this->inventory->getViewers() as $v){
|
||||
$v->getNetworkSession()->getInvManager()->syncData($this->inventory, ContainerSetDataPacket::PROPERTY_FURNACE_MAX_FUEL_TIME, $this->maxFuelTime);
|
||||
}
|
||||
}
|
||||
|
||||
$this->timings->stopTiming();
|
||||
|
||||
return $ret;
|
||||
}
|
||||
}
|
89
src/block/tile/Hopper.php
Normal file
89
src/block/tile/Hopper.php
Normal file
@ -0,0 +1,89 @@
|
||||
<?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\tile;
|
||||
|
||||
use pocketmine\inventory\HopperInventory;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\nbt\tag\CompoundTag;
|
||||
use pocketmine\world\World;
|
||||
|
||||
class Hopper extends Spawnable implements Container, Nameable{
|
||||
|
||||
use ContainerTrait;
|
||||
use NameableTrait;
|
||||
|
||||
private const TAG_TRANSFER_COOLDOWN = "TransferCooldown";
|
||||
|
||||
/** @var HopperInventory */
|
||||
private $inventory;
|
||||
|
||||
/** @var int */
|
||||
private $transferCooldown = 0;
|
||||
|
||||
public function __construct(World $world, Vector3 $pos){
|
||||
$this->inventory = new HopperInventory($this);
|
||||
parent::__construct($world, $pos);
|
||||
}
|
||||
|
||||
public function readSaveData(CompoundTag $nbt) : void{
|
||||
$this->loadItems($nbt);
|
||||
$this->loadName($nbt);
|
||||
|
||||
$this->transferCooldown = $nbt->getInt(self::TAG_TRANSFER_COOLDOWN, 0);
|
||||
}
|
||||
|
||||
protected function writeSaveData(CompoundTag $nbt) : void{
|
||||
$this->saveItems($nbt);
|
||||
$this->saveName($nbt);
|
||||
|
||||
$nbt->setInt(self::TAG_TRANSFER_COOLDOWN, $this->transferCooldown);
|
||||
}
|
||||
|
||||
public function close() : void{
|
||||
if(!$this->closed){
|
||||
$this->inventory->removeAllViewers();
|
||||
$this->inventory = null;
|
||||
|
||||
parent::close();
|
||||
}
|
||||
}
|
||||
|
||||
public function getDefaultName() : string{
|
||||
return "Hopper";
|
||||
}
|
||||
|
||||
/**
|
||||
* @return HopperInventory
|
||||
*/
|
||||
public function getInventory(){
|
||||
return $this->inventory;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return HopperInventory
|
||||
*/
|
||||
public function getRealInventory(){
|
||||
return $this->inventory;
|
||||
}
|
||||
}
|
104
src/block/tile/ItemFrame.php
Normal file
104
src/block/tile/ItemFrame.php
Normal file
@ -0,0 +1,104 @@
|
||||
<?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\tile;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\ItemFactory;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\nbt\tag\CompoundTag;
|
||||
use pocketmine\world\World;
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
* @see \pocketmine\block\ItemFrame
|
||||
*/
|
||||
class ItemFrame extends Spawnable{
|
||||
public const TAG_ITEM_ROTATION = "ItemRotation";
|
||||
public const TAG_ITEM_DROP_CHANCE = "ItemDropChance";
|
||||
public const TAG_ITEM = "Item";
|
||||
|
||||
/** @var Item */
|
||||
private $item;
|
||||
/** @var int */
|
||||
private $itemRotation = 0;
|
||||
/** @var float */
|
||||
private $itemDropChance = 1.0;
|
||||
|
||||
public function __construct(World $world, Vector3 $pos){
|
||||
$this->item = ItemFactory::air();
|
||||
parent::__construct($world, $pos);
|
||||
}
|
||||
|
||||
public function readSaveData(CompoundTag $nbt) : void{
|
||||
if(($itemTag = $nbt->getCompoundTag(self::TAG_ITEM)) !== null){
|
||||
$this->item = Item::nbtDeserialize($itemTag);
|
||||
}
|
||||
$this->itemRotation = $nbt->getByte(self::TAG_ITEM_ROTATION, $this->itemRotation, true);
|
||||
$this->itemDropChance = $nbt->getFloat(self::TAG_ITEM_DROP_CHANCE, $this->itemDropChance, true);
|
||||
}
|
||||
|
||||
protected function writeSaveData(CompoundTag $nbt) : void{
|
||||
$nbt->setFloat(self::TAG_ITEM_DROP_CHANCE, $this->itemDropChance);
|
||||
$nbt->setByte(self::TAG_ITEM_ROTATION, $this->itemRotation);
|
||||
$nbt->setTag(self::TAG_ITEM, $this->item->nbtSerialize());
|
||||
}
|
||||
|
||||
public function hasItem() : bool{
|
||||
return !$this->item->isNull();
|
||||
}
|
||||
|
||||
public function getItem() : Item{
|
||||
return clone $this->item;
|
||||
}
|
||||
|
||||
public function setItem(?Item $item) : void{
|
||||
if($item !== null and !$item->isNull()){
|
||||
$this->item = clone $item;
|
||||
}else{
|
||||
$this->item = ItemFactory::air();
|
||||
}
|
||||
}
|
||||
|
||||
public function getItemRotation() : int{
|
||||
return $this->itemRotation;
|
||||
}
|
||||
|
||||
public function setItemRotation(int $rotation) : void{
|
||||
$this->itemRotation = $rotation;
|
||||
}
|
||||
|
||||
public function getItemDropChance() : float{
|
||||
return $this->itemDropChance;
|
||||
}
|
||||
|
||||
public function setItemDropChance(float $chance) : void{
|
||||
$this->itemDropChance = $chance;
|
||||
}
|
||||
|
||||
protected function addAdditionalSpawnData(CompoundTag $nbt) : void{
|
||||
$nbt->setFloat(self::TAG_ITEM_DROP_CHANCE, $this->itemDropChance);
|
||||
$nbt->setByte(self::TAG_ITEM_ROTATION, $this->itemRotation);
|
||||
$nbt->setTag(self::TAG_ITEM, $this->item->nbtSerialize());
|
||||
}
|
||||
}
|
152
src/block/tile/MonsterSpawner.php
Normal file
152
src/block/tile/MonsterSpawner.php
Normal file
@ -0,0 +1,152 @@
|
||||
<?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\tile;
|
||||
|
||||
use pocketmine\nbt\tag\CompoundTag;
|
||||
use pocketmine\nbt\tag\IntTag;
|
||||
use pocketmine\nbt\tag\ListTag;
|
||||
use pocketmine\nbt\tag\StringTag;
|
||||
use pocketmine\network\mcpe\protocol\AddActorPacket;
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
class MonsterSpawner extends Spawnable{
|
||||
|
||||
private const TAG_LEGACY_ENTITY_TYPE_ID = "EntityId"; //TAG_Int
|
||||
private const TAG_ENTITY_TYPE_ID = "EntityIdentifier"; //TAG_String
|
||||
private const TAG_SPAWN_DELAY = "Delay"; //TAG_Short
|
||||
private const TAG_SPAWN_POTENTIALS = "SpawnPotentials"; //TAG_List<TAG_Compound>
|
||||
private const TAG_SPAWN_DATA = "SpawnData"; //TAG_Compound
|
||||
private const TAG_MIN_SPAWN_DELAY = "MinSpawnDelay"; //TAG_Short
|
||||
private const TAG_MAX_SPAWN_DELAY = "MaxSpawnDelay"; //TAG_Short
|
||||
private const TAG_SPAWN_PER_ATTEMPT = "SpawnCount"; //TAG_Short
|
||||
private const TAG_MAX_NEARBY_ENTITIES = "MaxNearbyEntities"; //TAG_Short
|
||||
private const TAG_REQUIRED_PLAYER_RANGE = "RequiredPlayerRange"; //TAG_Short
|
||||
private const TAG_SPAWN_RANGE = "SpawnRange"; //TAG_Short
|
||||
private const TAG_ENTITY_WIDTH = "DisplayEntityWidth"; //TAG_Float
|
||||
private const TAG_ENTITY_HEIGHT = "DisplayEntityHeight"; //TAG_Float
|
||||
private const TAG_ENTITY_SCALE = "DisplayEntityScale"; //TAG_Float
|
||||
|
||||
public const DEFAULT_MIN_SPAWN_DELAY = 200; //ticks
|
||||
public const DEFAULT_MAX_SPAWN_DELAY = 800;
|
||||
|
||||
public const DEFAULT_MAX_NEARBY_ENTITIES = 6;
|
||||
public const DEFAULT_SPAWN_RANGE = 4; //blocks
|
||||
public const DEFAULT_REQUIRED_PLAYER_RANGE = 16;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
* TODO: replace this with a cached entity or something of that nature
|
||||
*/
|
||||
private $entityTypeId = ":";
|
||||
/**
|
||||
* @var ListTag|null
|
||||
* TODO: deserialize this properly and drop the NBT (PC and PE formats are different, just for fun)
|
||||
*/
|
||||
private $spawnPotentials = null;
|
||||
/**
|
||||
* @var CompoundTag|null
|
||||
* TODO: deserialize this properly and drop the NBT (PC and PE formats are different, just for fun)
|
||||
*/
|
||||
private $spawnData = null;
|
||||
|
||||
/** @var float */
|
||||
private $displayEntityWidth = 1;
|
||||
/** @var float */
|
||||
private $displayEntityHeight = 1;
|
||||
/** @var float */
|
||||
private $displayEntityScale = 1;
|
||||
|
||||
/** @var int */
|
||||
private $spawnDelay = self::DEFAULT_MIN_SPAWN_DELAY;
|
||||
/** @var int */
|
||||
private $minSpawnDelay = self::DEFAULT_MIN_SPAWN_DELAY;
|
||||
/** @var int */
|
||||
private $maxSpawnDelay = self::DEFAULT_MAX_SPAWN_DELAY;
|
||||
/** @var int */
|
||||
private $spawnPerAttempt = 1;
|
||||
/** @var int */
|
||||
private $maxNearbyEntities = self::DEFAULT_MAX_NEARBY_ENTITIES;
|
||||
/** @var int */
|
||||
private $spawnRange = self::DEFAULT_SPAWN_RANGE;
|
||||
/** @var int */
|
||||
private $requiredPlayerRange = self::DEFAULT_REQUIRED_PLAYER_RANGE;
|
||||
|
||||
public function readSaveData(CompoundTag $nbt) : void{
|
||||
if($nbt->hasTag(self::TAG_LEGACY_ENTITY_TYPE_ID, IntTag::class)){
|
||||
//TODO: this will cause unexpected results when there's no mapping for the entity
|
||||
$this->entityTypeId = AddActorPacket::LEGACY_ID_MAP_BC[$nbt->getInt(self::TAG_LEGACY_ENTITY_TYPE_ID)] ?? ":";
|
||||
}elseif($nbt->hasTag(self::TAG_ENTITY_TYPE_ID, StringTag::class)){
|
||||
$this->entityTypeId = $nbt->getString(self::TAG_ENTITY_TYPE_ID);
|
||||
}else{
|
||||
$this->entityTypeId = ":"; //default - TODO: replace this with a constant
|
||||
}
|
||||
|
||||
$this->spawnData = $nbt->getCompoundTag(self::TAG_SPAWN_DATA);
|
||||
$this->spawnPotentials = $nbt->getListTag(self::TAG_SPAWN_POTENTIALS);
|
||||
|
||||
$this->spawnDelay = $nbt->getShort(self::TAG_SPAWN_DELAY, self::DEFAULT_MIN_SPAWN_DELAY);
|
||||
$this->minSpawnDelay = $nbt->getShort(self::TAG_MIN_SPAWN_DELAY, self::DEFAULT_MIN_SPAWN_DELAY);
|
||||
$this->maxSpawnDelay = $nbt->getShort(self::TAG_MAX_SPAWN_DELAY, self::DEFAULT_MAX_SPAWN_DELAY);
|
||||
$this->spawnPerAttempt = $nbt->getShort(self::TAG_SPAWN_PER_ATTEMPT, 1);
|
||||
$this->maxNearbyEntities = $nbt->getShort(self::TAG_MAX_NEARBY_ENTITIES, self::DEFAULT_MAX_NEARBY_ENTITIES);
|
||||
$this->requiredPlayerRange = $nbt->getShort(self::TAG_REQUIRED_PLAYER_RANGE, self::DEFAULT_REQUIRED_PLAYER_RANGE);
|
||||
$this->spawnRange = $nbt->getShort(self::TAG_SPAWN_RANGE, self::DEFAULT_SPAWN_RANGE);
|
||||
|
||||
$this->displayEntityWidth = $nbt->getFloat(self::TAG_ENTITY_WIDTH, 1.0);
|
||||
$this->displayEntityHeight = $nbt->getFloat(self::TAG_ENTITY_HEIGHT, 1.0);
|
||||
$this->displayEntityScale = $nbt->getFloat(self::TAG_ENTITY_SCALE, 1.0);
|
||||
}
|
||||
|
||||
protected function writeSaveData(CompoundTag $nbt) : void{
|
||||
$nbt->setString(self::TAG_ENTITY_TYPE_ID, $this->entityTypeId);
|
||||
if($this->spawnData !== null){
|
||||
$nbt->setTag(self::TAG_SPAWN_DATA, clone $this->spawnData);
|
||||
}
|
||||
if($this->spawnPotentials !== null){
|
||||
$nbt->setTag(self::TAG_SPAWN_POTENTIALS, clone $this->spawnPotentials);
|
||||
}
|
||||
|
||||
$nbt->setShort(self::TAG_SPAWN_DELAY, $this->spawnDelay);
|
||||
$nbt->setShort(self::TAG_MIN_SPAWN_DELAY, $this->minSpawnDelay);
|
||||
$nbt->setShort(self::TAG_MAX_SPAWN_DELAY, $this->maxSpawnDelay);
|
||||
$nbt->setShort(self::TAG_SPAWN_PER_ATTEMPT, $this->spawnPerAttempt);
|
||||
$nbt->setShort(self::TAG_MAX_NEARBY_ENTITIES, $this->maxNearbyEntities);
|
||||
$nbt->setShort(self::TAG_REQUIRED_PLAYER_RANGE, $this->requiredPlayerRange);
|
||||
$nbt->setShort(self::TAG_SPAWN_RANGE, $this->spawnRange);
|
||||
|
||||
$nbt->setFloat(self::TAG_ENTITY_WIDTH, $this->displayEntityWidth);
|
||||
$nbt->setFloat(self::TAG_ENTITY_HEIGHT, $this->displayEntityHeight);
|
||||
$nbt->setFloat(self::TAG_ENTITY_SCALE, $this->displayEntityScale);
|
||||
}
|
||||
|
||||
protected function addAdditionalSpawnData(CompoundTag $nbt) : void{
|
||||
$nbt->setString(self::TAG_ENTITY_TYPE_ID, $this->entityTypeId);
|
||||
|
||||
//TODO: we can't set SpawnData here because it might crash the client if it's from a PC world (we need to implement full deserialization)
|
||||
|
||||
$nbt->setFloat(self::TAG_ENTITY_SCALE, $this->displayEntityScale);
|
||||
}
|
||||
}
|
48
src/block/tile/Nameable.php
Normal file
48
src/block/tile/Nameable.php
Normal file
@ -0,0 +1,48 @@
|
||||
<?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\tile;
|
||||
|
||||
interface Nameable{
|
||||
public const TAG_CUSTOM_NAME = "CustomName";
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getDefaultName() : string;
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getName() : string;
|
||||
|
||||
/**
|
||||
* @param string $str
|
||||
*/
|
||||
public function setName(string $str) : void;
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function hasName() : bool;
|
||||
}
|
95
src/block/tile/NameableTrait.php
Normal file
95
src/block/tile/NameableTrait.php
Normal file
@ -0,0 +1,95 @@
|
||||
<?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\tile;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\nbt\tag\CompoundTag;
|
||||
use pocketmine\nbt\tag\StringTag;
|
||||
|
||||
/**
|
||||
* This trait implements most methods in the {@link Nameable} interface. It should only be used by Tiles.
|
||||
*/
|
||||
trait NameableTrait{
|
||||
/** @var string|null */
|
||||
private $customName = null;
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
abstract public function getDefaultName() : string;
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getName() : string{
|
||||
return $this->customName ?? $this->getDefaultName();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
*/
|
||||
public function setName(string $name) : void{
|
||||
if($name === ""){
|
||||
$this->customName = null;
|
||||
}else{
|
||||
$this->customName = $name;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function hasName() : bool{
|
||||
return $this->customName !== null;
|
||||
}
|
||||
|
||||
public function addAdditionalSpawnData(CompoundTag $nbt) : void{
|
||||
if($this->customName !== null){
|
||||
$nbt->setString(Nameable::TAG_CUSTOM_NAME, $this->customName);
|
||||
}
|
||||
}
|
||||
|
||||
protected function loadName(CompoundTag $tag) : void{
|
||||
if($tag->hasTag(Nameable::TAG_CUSTOM_NAME, StringTag::class)){
|
||||
$this->customName = $tag->getString(Nameable::TAG_CUSTOM_NAME);
|
||||
}
|
||||
}
|
||||
|
||||
protected function saveName(CompoundTag $tag) : void{
|
||||
if($this->customName !== null){
|
||||
$tag->setString(Nameable::TAG_CUSTOM_NAME, $this->customName);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Item $item
|
||||
* @see Tile::copyDataFromItem()
|
||||
*/
|
||||
public function copyDataFromItem(Item $item) : void{
|
||||
parent::copyDataFromItem($item);
|
||||
if($item->hasCustomName()){ //this should take precedence over saved NBT
|
||||
$this->setName($item->getCustomName());
|
||||
}
|
||||
}
|
||||
}
|
62
src/block/tile/Note.php
Normal file
62
src/block/tile/Note.php
Normal file
@ -0,0 +1,62 @@
|
||||
<?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\tile;
|
||||
|
||||
use pocketmine\block\Note as BlockNote;
|
||||
use pocketmine\nbt\tag\CompoundTag;
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
class Note extends Tile{
|
||||
/** @var int */
|
||||
private $pitch = 0;
|
||||
|
||||
public function readSaveData(CompoundTag $nbt) : void{
|
||||
if(($pitch = $nbt->getByte("note", $this->pitch)) > BlockNote::MIN_PITCH and $pitch <= BlockNote::MAX_PITCH){
|
||||
$this->pitch = $pitch;
|
||||
}
|
||||
}
|
||||
|
||||
protected function writeSaveData(CompoundTag $nbt) : void{
|
||||
$nbt->setByte("note", $this->pitch);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getPitch() : int{
|
||||
return $this->pitch;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $pitch
|
||||
*/
|
||||
public function setPitch(int $pitch) : void{
|
||||
if($pitch < BlockNote::MIN_PITCH or $pitch > BlockNote::MAX_PITCH){
|
||||
throw new \InvalidArgumentException("Pitch must be in range " . BlockNote::MIN_PITCH . " - " . BlockNote::MAX_PITCH);
|
||||
}
|
||||
$this->pitch = $pitch;
|
||||
}
|
||||
}
|
98
src/block/tile/Sign.php
Normal file
98
src/block/tile/Sign.php
Normal file
@ -0,0 +1,98 @@
|
||||
<?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\tile;
|
||||
|
||||
use pocketmine\block\utils\SignText;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\nbt\tag\CompoundTag;
|
||||
use pocketmine\nbt\tag\StringTag;
|
||||
use pocketmine\world\World;
|
||||
use function array_pad;
|
||||
use function array_slice;
|
||||
use function explode;
|
||||
use function implode;
|
||||
use function mb_scrub;
|
||||
use function sprintf;
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
* @see \pocketmine\block\Sign
|
||||
*/
|
||||
class Sign extends Spawnable{
|
||||
public const TAG_TEXT_BLOB = "Text";
|
||||
public const TAG_TEXT_LINE = "Text%d"; //sprintf()able
|
||||
|
||||
public static function fixTextBlob(string $blob) : array{
|
||||
return array_slice(array_pad(explode("\n", $blob), 4, ""), 0, 4);
|
||||
}
|
||||
|
||||
/** @var SignText */
|
||||
protected $text;
|
||||
|
||||
public function __construct(World $world, Vector3 $pos){
|
||||
$this->text = new SignText();
|
||||
parent::__construct($world, $pos);
|
||||
}
|
||||
|
||||
public function readSaveData(CompoundTag $nbt) : void{
|
||||
if($nbt->hasTag(self::TAG_TEXT_BLOB, StringTag::class)){ //MCPE 1.2 save format
|
||||
$this->text = SignText::fromBlob(mb_scrub($nbt->getString(self::TAG_TEXT_BLOB), 'UTF-8'));
|
||||
}else{
|
||||
$this->text = new SignText();
|
||||
for($i = 0; $i < SignText::LINE_COUNT; ++$i){
|
||||
$textKey = sprintf(self::TAG_TEXT_LINE, $i + 1);
|
||||
if($nbt->hasTag($textKey, StringTag::class)){
|
||||
$this->text->setLine($i, mb_scrub($nbt->getString($textKey), 'UTF-8'));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected function writeSaveData(CompoundTag $nbt) : void{
|
||||
$nbt->setString(self::TAG_TEXT_BLOB, implode("\n", $this->text->getLines()));
|
||||
|
||||
for($i = 0; $i < SignText::LINE_COUNT; ++$i){ //Backwards-compatibility
|
||||
$textKey = sprintf(self::TAG_TEXT_LINE, $i + 1);
|
||||
$nbt->setString($textKey, $this->text->getLine($i));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return SignText
|
||||
*/
|
||||
public function getText() : SignText{
|
||||
return $this->text;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param SignText $text
|
||||
*/
|
||||
public function setText(SignText $text) : void{
|
||||
$this->text = $text;
|
||||
}
|
||||
|
||||
protected function addAdditionalSpawnData(CompoundTag $nbt) : void{
|
||||
$nbt->setString(self::TAG_TEXT_BLOB, implode("\n", $this->text->getLines()));
|
||||
}
|
||||
}
|
92
src/block/tile/Skull.php
Normal file
92
src/block/tile/Skull.php
Normal file
@ -0,0 +1,92 @@
|
||||
<?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\tile;
|
||||
|
||||
use pocketmine\block\utils\SkullType;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\nbt\tag\ByteTag;
|
||||
use pocketmine\nbt\tag\CompoundTag;
|
||||
use pocketmine\world\World;
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
* @see \pocketmine\block\Skull
|
||||
*/
|
||||
class Skull extends Spawnable{
|
||||
|
||||
private const TAG_SKULL_TYPE = "SkullType"; //TAG_Byte
|
||||
private const TAG_ROT = "Rot"; //TAG_Byte
|
||||
private const TAG_MOUTH_MOVING = "MouthMoving"; //TAG_Byte
|
||||
private const TAG_MOUTH_TICK_COUNT = "MouthTickCount"; //TAG_Int
|
||||
|
||||
/** @var SkullType */
|
||||
private $skullType;
|
||||
/** @var int */
|
||||
private $skullRotation = 0;
|
||||
|
||||
public function __construct(World $world, Vector3 $pos){
|
||||
$this->skullType = SkullType::SKELETON();
|
||||
parent::__construct($world, $pos);
|
||||
}
|
||||
|
||||
public function readSaveData(CompoundTag $nbt) : void{
|
||||
if($nbt->hasTag(self::TAG_SKULL_TYPE, ByteTag::class)){
|
||||
try{
|
||||
$this->skullType = SkullType::fromMagicNumber($nbt->getByte(self::TAG_SKULL_TYPE));
|
||||
}catch(\InvalidArgumentException $e){
|
||||
//bad data, drop it
|
||||
}
|
||||
}
|
||||
$rotation = $nbt->getByte(self::TAG_ROT, 0, true);
|
||||
if($rotation >= 0 and $rotation <= 15){
|
||||
$this->skullRotation = $rotation;
|
||||
}
|
||||
}
|
||||
|
||||
protected function writeSaveData(CompoundTag $nbt) : void{
|
||||
$nbt->setByte(self::TAG_SKULL_TYPE, $this->skullType->getMagicNumber());
|
||||
$nbt->setByte(self::TAG_ROT, $this->skullRotation);
|
||||
}
|
||||
|
||||
public function setSkullType(SkullType $type) : void{
|
||||
$this->skullType = $type;
|
||||
}
|
||||
|
||||
public function getSkullType() : SkullType{
|
||||
return $this->skullType;
|
||||
}
|
||||
|
||||
public function getRotation() : int{
|
||||
return $this->skullRotation;
|
||||
}
|
||||
|
||||
public function setRotation(int $rotation) : void{
|
||||
$this->skullRotation = $rotation;
|
||||
}
|
||||
|
||||
protected function addAdditionalSpawnData(CompoundTag $nbt) : void{
|
||||
$nbt->setByte(self::TAG_SKULL_TYPE, $this->skullType->getMagicNumber());
|
||||
$nbt->setByte(self::TAG_ROT, $this->skullRotation);
|
||||
}
|
||||
}
|
97
src/block/tile/Spawnable.php
Normal file
97
src/block/tile/Spawnable.php
Normal file
@ -0,0 +1,97 @@
|
||||
<?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\tile;
|
||||
|
||||
use pocketmine\nbt\tag\CompoundTag;
|
||||
use pocketmine\nbt\TreeRoot;
|
||||
use pocketmine\network\mcpe\serializer\NetworkNbtSerializer;
|
||||
use function get_class;
|
||||
|
||||
abstract class Spawnable extends Tile{
|
||||
/** @var string|null */
|
||||
private $spawnCompoundCache = null;
|
||||
/** @var bool */
|
||||
private $dirty = true; //default dirty, until it's been spawned appropriately on the world
|
||||
|
||||
/** @var NetworkNbtSerializer|null */
|
||||
private static $nbtWriter = null;
|
||||
|
||||
/**
|
||||
* Returns whether the tile needs to be respawned to viewers.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isDirty() : bool{
|
||||
return $this->dirty;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $dirty
|
||||
*/
|
||||
public function setDirty(bool $dirty = true) : void{
|
||||
if($dirty){
|
||||
$this->spawnCompoundCache = null;
|
||||
}
|
||||
$this->dirty = $dirty;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns encoded NBT (varint, little-endian) used to spawn this tile to clients. Uses cache where possible,
|
||||
* populates cache if it is null.
|
||||
*
|
||||
* @return string encoded NBT
|
||||
*/
|
||||
final public function getSerializedSpawnCompound() : string{
|
||||
if($this->spawnCompoundCache === null){
|
||||
if(self::$nbtWriter === null){
|
||||
self::$nbtWriter = new NetworkNbtSerializer();
|
||||
}
|
||||
|
||||
$this->spawnCompoundCache = self::$nbtWriter->write(new TreeRoot($this->getSpawnCompound()));
|
||||
}
|
||||
|
||||
return $this->spawnCompoundCache;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return CompoundTag
|
||||
*/
|
||||
final public function getSpawnCompound() : CompoundTag{
|
||||
$nbt = CompoundTag::create()
|
||||
->setString(self::TAG_ID, TileFactory::getSaveId(get_class($this))) //TODO: disassociate network ID from save ID
|
||||
->setInt(self::TAG_X, $this->x)
|
||||
->setInt(self::TAG_Y, $this->y)
|
||||
->setInt(self::TAG_Z, $this->z);
|
||||
$this->addAdditionalSpawnData($nbt);
|
||||
return $nbt;
|
||||
}
|
||||
|
||||
/**
|
||||
* An extension to getSpawnCompound() for
|
||||
* further modifying the generic tile NBT.
|
||||
*
|
||||
* @param CompoundTag $nbt
|
||||
*/
|
||||
abstract protected function addAdditionalSpawnData(CompoundTag $nbt) : void;
|
||||
}
|
141
src/block/tile/Tile.php
Normal file
141
src/block/tile/Tile.php
Normal file
@ -0,0 +1,141 @@
|
||||
<?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);
|
||||
|
||||
/**
|
||||
* All the Tile classes and related classes
|
||||
*/
|
||||
|
||||
namespace pocketmine\block\tile;
|
||||
|
||||
use pocketmine\block\Block;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\nbt\tag\CompoundTag;
|
||||
use pocketmine\timings\Timings;
|
||||
use pocketmine\timings\TimingsHandler;
|
||||
use pocketmine\world\Position;
|
||||
use pocketmine\world\World;
|
||||
use function get_class;
|
||||
|
||||
abstract class Tile extends Position{
|
||||
|
||||
public const TAG_ID = "id";
|
||||
public const TAG_X = "x";
|
||||
public const TAG_Y = "y";
|
||||
public const TAG_Z = "z";
|
||||
|
||||
/** @var bool */
|
||||
public $closed = false;
|
||||
/** @var TimingsHandler */
|
||||
protected $timings;
|
||||
|
||||
public function __construct(World $world, Vector3 $pos){
|
||||
$this->timings = Timings::getTileEntityTimings($this);
|
||||
parent::__construct($pos->getFloorX(), $pos->getFloorY(), $pos->getFloorZ(), $world);
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* Reads additional data from the CompoundTag on tile creation.
|
||||
*
|
||||
* @param CompoundTag $nbt
|
||||
*/
|
||||
abstract public function readSaveData(CompoundTag $nbt) : void;
|
||||
|
||||
/**
|
||||
* Writes additional save data to a CompoundTag, not including generic things like ID and coordinates.
|
||||
*
|
||||
* @param CompoundTag $nbt
|
||||
*/
|
||||
abstract protected function writeSaveData(CompoundTag $nbt) : void;
|
||||
|
||||
public function saveNBT() : CompoundTag{
|
||||
$nbt = CompoundTag::create()
|
||||
->setString(self::TAG_ID, TileFactory::getSaveId(get_class($this)))
|
||||
->setInt(self::TAG_X, $this->x)
|
||||
->setInt(self::TAG_Y, $this->y)
|
||||
->setInt(self::TAG_Z, $this->z);
|
||||
$this->writeSaveData($nbt);
|
||||
|
||||
return $nbt;
|
||||
}
|
||||
|
||||
public function getCleanedNBT() : ?CompoundTag{
|
||||
$this->writeSaveData($tag = new CompoundTag());
|
||||
return $tag->getCount() > 0 ? $tag : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*
|
||||
* @param Item $item
|
||||
*
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function copyDataFromItem(Item $item) : void{
|
||||
if($item->hasCustomBlockData()){ //TODO: check item root tag (MCPE doesn't use BlockEntityTag)
|
||||
$this->readSaveData($item->getCustomBlockData());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Block
|
||||
*/
|
||||
public function getBlock() : Block{
|
||||
return $this->world->getBlockAt($this->x, $this->y, $this->z);
|
||||
}
|
||||
|
||||
public function isClosed() : bool{
|
||||
return $this->closed;
|
||||
}
|
||||
|
||||
public function __destruct(){
|
||||
$this->close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the tile's block is destroyed.
|
||||
*/
|
||||
final public function onBlockDestroyed() : void{
|
||||
$this->onBlockDestroyedHook();
|
||||
$this->close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Override this method to do actions you need to do when this tile is destroyed due to block being broken.
|
||||
*/
|
||||
protected function onBlockDestroyedHook() : void{
|
||||
|
||||
}
|
||||
|
||||
public function close() : void{
|
||||
if(!$this->closed){
|
||||
$this->closed = true;
|
||||
|
||||
if($this->isValid()){
|
||||
$this->world->removeTile($this);
|
||||
$this->setWorld(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
182
src/block/tile/TileFactory.php
Normal file
182
src/block/tile/TileFactory.php
Normal file
@ -0,0 +1,182 @@
|
||||
<?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\tile;
|
||||
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\nbt\tag\CompoundTag;
|
||||
use pocketmine\utils\Utils;
|
||||
use pocketmine\world\World;
|
||||
use function assert;
|
||||
use function in_array;
|
||||
use function is_a;
|
||||
use function reset;
|
||||
|
||||
final class TileFactory{
|
||||
|
||||
/** @var string[] classes that extend Tile */
|
||||
private static $knownTiles = [];
|
||||
/** @var string[][] */
|
||||
private static $saveNames = [];
|
||||
/** @var string[] base class => overridden class */
|
||||
private static $classMapping = [];
|
||||
|
||||
private function __construct(){
|
||||
//NOOP
|
||||
}
|
||||
|
||||
public static function init() : void{
|
||||
self::register(Banner::class, ["Banner", "minecraft:banner"]);
|
||||
self::register(Bed::class, ["Bed", "minecraft:bed"]);
|
||||
self::register(BrewingStand::class, ["BrewingStand", "minecraft:brewing_stand"]);
|
||||
self::register(Chest::class, ["Chest", "minecraft:chest"]);
|
||||
self::register(Comparator::class, ["Comparator", "minecraft:comparator"]);
|
||||
self::register(DaylightSensor::class, ["DaylightDetector", "minecraft:daylight_detector"]);
|
||||
self::register(EnchantTable::class, ["EnchantTable", "minecraft:enchanting_table"]);
|
||||
self::register(EnderChest::class, ["EnderChest", "minecraft:ender_chest"]);
|
||||
self::register(FlowerPot::class, ["FlowerPot", "minecraft:flower_pot"]);
|
||||
self::register(Furnace::class, ["Furnace", "minecraft:furnace"]);
|
||||
self::register(Hopper::class, ["Hopper", "minecraft:hopper"]);
|
||||
self::register(ItemFrame::class, ["ItemFrame"]); //this is an entity in PC
|
||||
self::register(MonsterSpawner::class, ["MobSpawner", "minecraft:mob_spawner"]);
|
||||
self::register(Note::class, ["Music", "minecraft:noteblock"]);
|
||||
self::register(Sign::class, ["Sign", "minecraft:sign"]);
|
||||
self::register(Skull::class, ["Skull", "minecraft:skull"]);
|
||||
|
||||
//TODO: Barrel
|
||||
//TODO: Beacon
|
||||
//TODO: Bell
|
||||
//TODO: BlastFurnace
|
||||
//TODO: Campfire
|
||||
//TODO: Cauldron
|
||||
//TODO: ChalkboardBlock
|
||||
//TODO: ChemistryTable
|
||||
//TODO: CommandBlock
|
||||
//TODO: Conduit
|
||||
//TODO: Dispenser
|
||||
//TODO: Dropper
|
||||
//TODO: EndGateway
|
||||
//TODO: EndPortal
|
||||
//TODO: JigsawBlock
|
||||
//TODO: Jukebox
|
||||
//TODO: Lectern
|
||||
//TODO: MovingBlock
|
||||
//TODO: NetherReactor
|
||||
//TODO: PistonArm
|
||||
//TODO: ShulkerBox
|
||||
//TODO: Smoker
|
||||
//TODO: StructureBlock
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $className
|
||||
* @param string[] $saveNames
|
||||
*/
|
||||
public static function register(string $className, array $saveNames = []) : void{
|
||||
Utils::testValidInstance($className, Tile::class);
|
||||
|
||||
self::$classMapping[$className] = $className;
|
||||
|
||||
$shortName = (new \ReflectionClass($className))->getShortName();
|
||||
if(!in_array($shortName, $saveNames, true)){
|
||||
$saveNames[] = $shortName;
|
||||
}
|
||||
|
||||
foreach($saveNames as $name){
|
||||
self::$knownTiles[$name] = $className;
|
||||
}
|
||||
|
||||
self::$saveNames[$className] = $saveNames;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $baseClass Already-registered tile class to override
|
||||
* @param string $newClass Class which extends the base class
|
||||
*
|
||||
* @throws \InvalidArgumentException if the base class is not a registered tile
|
||||
*/
|
||||
public static function override(string $baseClass, string $newClass) : void{
|
||||
if(!isset(self::$classMapping[$baseClass])){
|
||||
throw new \InvalidArgumentException("Class $baseClass is not a registered tile");
|
||||
}
|
||||
|
||||
Utils::testValidInstance($newClass, $baseClass);
|
||||
self::$classMapping[$baseClass] = $newClass;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $baseClass
|
||||
* @param World $world
|
||||
* @param Vector3 $pos
|
||||
*
|
||||
* @return Tile (will be an instanceof $baseClass)
|
||||
* @throws \InvalidArgumentException if the specified class is not a registered tile
|
||||
*/
|
||||
public static function create(string $baseClass, World $world, Vector3 $pos) : Tile{
|
||||
if(isset(self::$classMapping[$baseClass])){
|
||||
$class = self::$classMapping[$baseClass];
|
||||
assert(is_a($class, $baseClass, true));
|
||||
/**
|
||||
* @var Tile $tile
|
||||
* @see Tile::__construct()
|
||||
*/
|
||||
$tile = new $class($world, $pos);
|
||||
|
||||
return $tile;
|
||||
}
|
||||
|
||||
throw new \InvalidArgumentException("Class $baseClass is not a registered tile");
|
||||
}
|
||||
|
||||
/**
|
||||
* @param World $world
|
||||
* @param CompoundTag $nbt
|
||||
*
|
||||
* @return Tile|null
|
||||
*@internal
|
||||
*
|
||||
*/
|
||||
public static function createFromData(World $world, CompoundTag $nbt) : ?Tile{
|
||||
$type = $nbt->getString(Tile::TAG_ID, "", true);
|
||||
if(!isset(self::$knownTiles[$type])){
|
||||
return null;
|
||||
}
|
||||
$class = self::$knownTiles[$type];
|
||||
assert(is_a($class, Tile::class, true));
|
||||
/**
|
||||
* @var Tile $tile
|
||||
* @see Tile::__construct()
|
||||
*/
|
||||
$tile = new $class($world, new Vector3($nbt->getInt(Tile::TAG_X), $nbt->getInt(Tile::TAG_Y), $nbt->getInt(Tile::TAG_Z)));
|
||||
$tile->readSaveData($nbt);
|
||||
|
||||
return $tile;
|
||||
}
|
||||
|
||||
public static function getSaveId(string $class) : string{
|
||||
if(isset(self::$saveNames[$class])){
|
||||
return reset(self::$saveNames[$class]);
|
||||
}
|
||||
throw new \InvalidArgumentException("Tile $class is not registered");
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user