mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-06-07 12:18:46 +00:00
Nuke Block->meta, split into variant and state properties, lots of cleanup
This is a major change to the way block metadata is handled within the PM core. This separates variant metadata (which really ought to be part of the ID) from state metadata, and in a couple of cases flattens separate states of blocks together. The result of this is that invalid variants can be much more easily detected, and additionally state handling is much cleaner since meta is only needed at the serialize layer instead of throughout the code.
This commit is contained in:
parent
a55ab54ddb
commit
56d9943b0d
@ -2448,6 +2448,7 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
|||||||
public function handleItemFrameDropItem(ItemFrameDropItemPacket $packet) : bool{
|
public function handleItemFrameDropItem(ItemFrameDropItemPacket $packet) : bool{
|
||||||
$tile = $this->level->getTileAt($packet->x, $packet->y, $packet->z);
|
$tile = $this->level->getTileAt($packet->x, $packet->y, $packet->z);
|
||||||
if($tile instanceof ItemFrame){
|
if($tile instanceof ItemFrame){
|
||||||
|
//TODO: use facing blockstate property instead of damage value
|
||||||
$ev = new PlayerInteractEvent($this, $this->inventory->getItemInHand(), $tile->getBlock(), null, 5 - $tile->getBlock()->getDamage(), PlayerInteractEvent::LEFT_CLICK_BLOCK);
|
$ev = new PlayerInteractEvent($this, $this->inventory->getItemInHand(), $tile->getBlock(), null, 5 - $tile->getBlock()->getDamage(), PlayerInteractEvent::LEFT_CLICK_BLOCK);
|
||||||
if($this->isSpectator() or $this->level->checkSpawnProtection($this, $tile)){
|
if($this->isSpectator() or $this->level->checkSpawnProtection($this, $tile)){
|
||||||
$ev->setCancelled();
|
$ev->setCancelled();
|
||||||
|
@ -34,8 +34,8 @@ class Air extends Transparent{
|
|||||||
|
|
||||||
protected $id = self::AIR;
|
protected $id = self::AIR;
|
||||||
|
|
||||||
public function __construct(int $meta = 0){
|
public function __construct(){
|
||||||
$this->setDamage($meta);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getName() : string{
|
public function getName() : string{
|
||||||
|
@ -28,6 +28,7 @@ use pocketmine\item\Item;
|
|||||||
use pocketmine\item\TieredTool;
|
use pocketmine\item\TieredTool;
|
||||||
use pocketmine\math\AxisAlignedBB;
|
use pocketmine\math\AxisAlignedBB;
|
||||||
use pocketmine\math\Bearing;
|
use pocketmine\math\Bearing;
|
||||||
|
use pocketmine\math\Facing;
|
||||||
use pocketmine\math\Vector3;
|
use pocketmine\math\Vector3;
|
||||||
use pocketmine\Player;
|
use pocketmine\Player;
|
||||||
|
|
||||||
@ -37,10 +38,19 @@ class Anvil extends Fallable{
|
|||||||
public const TYPE_SLIGHTLY_DAMAGED = 4;
|
public const TYPE_SLIGHTLY_DAMAGED = 4;
|
||||||
public const TYPE_VERY_DAMAGED = 8;
|
public const TYPE_VERY_DAMAGED = 8;
|
||||||
|
|
||||||
protected $id = self::ANVIL;
|
/** @var int */
|
||||||
|
protected $facing = Facing::NORTH;
|
||||||
|
|
||||||
public function __construct(int $meta = 0){
|
protected function writeStateToMeta() : int{
|
||||||
$this->setDamage($meta);
|
return Bearing::fromFacing($this->facing);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function readStateFromMeta(int $meta) : void{
|
||||||
|
$this->facing = Bearing::toFacing($meta);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getStateBitmask() : int{
|
||||||
|
return 0b11;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function isTransparent() : bool{
|
public function isTransparent() : bool{
|
||||||
@ -55,19 +65,6 @@ class Anvil extends Fallable{
|
|||||||
return 6000;
|
return 6000;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getVariantBitmask() : int{
|
|
||||||
return 0x0c;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getName() : string{
|
|
||||||
static $names = [
|
|
||||||
self::TYPE_NORMAL => "Anvil",
|
|
||||||
self::TYPE_SLIGHTLY_DAMAGED => "Slightly Damaged Anvil",
|
|
||||||
self::TYPE_VERY_DAMAGED => "Very Damaged Anvil"
|
|
||||||
];
|
|
||||||
return $names[$this->getVariant()] ?? "Anvil";
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getToolType() : int{
|
public function getToolType() : int{
|
||||||
return BlockToolType::TYPE_PICKAXE;
|
return BlockToolType::TYPE_PICKAXE;
|
||||||
}
|
}
|
||||||
@ -79,7 +76,7 @@ class Anvil extends Fallable{
|
|||||||
public function recalculateBoundingBox() : ?AxisAlignedBB{
|
public function recalculateBoundingBox() : ?AxisAlignedBB{
|
||||||
$inset = 0.125;
|
$inset = 0.125;
|
||||||
|
|
||||||
if($this->meta & 0x01){ //east/west
|
if(Facing::axis($this->facing) === Facing::AXIS_X){
|
||||||
return new AxisAlignedBB(0, 0, $inset, 1, 1, 1 - $inset);
|
return new AxisAlignedBB(0, 0, $inset, 1, 1, 1 - $inset);
|
||||||
}else{
|
}else{
|
||||||
return new AxisAlignedBB($inset, 0, 0, 1 - $inset, 1, 1);
|
return new AxisAlignedBB($inset, 0, 0, 1 - $inset, 1, 1);
|
||||||
@ -95,8 +92,9 @@ class Anvil extends Fallable{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
|
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
|
||||||
$direction = $player !== null ? Bearing::rotate($player->getDirection(), 1) : 0;
|
if($player !== null){
|
||||||
$this->meta = $this->getVariant() | $direction;
|
$this->facing = Bearing::toFacing(Bearing::rotate($player->getDirection(), 1));
|
||||||
|
}
|
||||||
return parent::place($item, $blockReplace, $blockClicked, $face, $clickVector, $player);
|
return parent::place($item, $blockReplace, $blockClicked, $face, $clickVector, $player);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -37,13 +37,6 @@ abstract class BaseRail extends Flowable{
|
|||||||
public const ASCENDING_NORTH = 4;
|
public const ASCENDING_NORTH = 4;
|
||||||
public const ASCENDING_SOUTH = 5;
|
public const ASCENDING_SOUTH = 5;
|
||||||
|
|
||||||
private const ASCENDING_SIDES = [
|
|
||||||
self::ASCENDING_NORTH => Facing::NORTH,
|
|
||||||
self::ASCENDING_EAST => Facing::EAST,
|
|
||||||
self::ASCENDING_SOUTH => Facing::SOUTH,
|
|
||||||
self::ASCENDING_WEST => Facing::WEST
|
|
||||||
];
|
|
||||||
|
|
||||||
protected const FLAG_ASCEND = 1 << 24; //used to indicate direction-up
|
protected const FLAG_ASCEND = 1 << 24; //used to indicate direction-up
|
||||||
|
|
||||||
protected const CONNECTIONS = [
|
protected const CONNECTIONS = [
|
||||||
@ -76,8 +69,28 @@ abstract class BaseRail extends Flowable{
|
|||||||
]
|
]
|
||||||
];
|
];
|
||||||
|
|
||||||
public function __construct(int $meta = 0){
|
/** @var int[] */
|
||||||
$this->setDamage($meta);
|
protected $connections = [];
|
||||||
|
|
||||||
|
public function __construct(){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function writeStateToMeta() : int{
|
||||||
|
if(empty($this->connections)){
|
||||||
|
return self::STRAIGHT_NORTH_SOUTH;
|
||||||
|
}
|
||||||
|
return $this->getMetaForState($this->connections);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function readStateFromMeta(int $meta) : void{
|
||||||
|
//on invalid states, this will return an empty array, allowing this rail to transform into any other state
|
||||||
|
//TODO: should this throw instead?
|
||||||
|
$this->connections = $this->getConnectionsFromMeta($meta);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getStateBitmask() : int{
|
||||||
|
return 0b111;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getHardness() : float{
|
public function getHardness() : float{
|
||||||
@ -121,9 +134,11 @@ abstract class BaseRail extends Flowable{
|
|||||||
/**
|
/**
|
||||||
* Returns the connection directions of this rail (depending on the current block state)
|
* Returns the connection directions of this rail (depending on the current block state)
|
||||||
*
|
*
|
||||||
|
* @param int $meta
|
||||||
|
*
|
||||||
* @return int[]
|
* @return int[]
|
||||||
*/
|
*/
|
||||||
abstract protected function getConnectionsForState() : array;
|
abstract protected function getConnectionsFromMeta(int $meta) : array;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns all the directions this rail is already connected in.
|
* Returns all the directions this rail is already connected in.
|
||||||
@ -135,7 +150,7 @@ abstract class BaseRail extends Flowable{
|
|||||||
$connections = [];
|
$connections = [];
|
||||||
|
|
||||||
/** @var int $connection */
|
/** @var int $connection */
|
||||||
foreach($this->getConnectionsForState() as $connection){
|
foreach($this->connections as $connection){
|
||||||
$other = $this->getSide($connection & ~self::FLAG_ASCEND);
|
$other = $this->getSide($connection & ~self::FLAG_ASCEND);
|
||||||
$otherConnection = Facing::opposite($connection & ~self::FLAG_ASCEND);
|
$otherConnection = Facing::opposite($connection & ~self::FLAG_ASCEND);
|
||||||
|
|
||||||
@ -149,7 +164,7 @@ abstract class BaseRail extends Flowable{
|
|||||||
|
|
||||||
if(
|
if(
|
||||||
$other instanceof BaseRail and
|
$other instanceof BaseRail and
|
||||||
in_array($otherConnection, $other->getConnectionsForState(), true)
|
in_array($otherConnection, $other->connections, true)
|
||||||
){
|
){
|
||||||
$connections[] = $connection;
|
$connections[] = $connection;
|
||||||
}
|
}
|
||||||
@ -248,20 +263,20 @@ abstract class BaseRail extends Flowable{
|
|||||||
throw new \InvalidArgumentException("Expected exactly 2 connections, got " . count($connections));
|
throw new \InvalidArgumentException("Expected exactly 2 connections, got " . count($connections));
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->meta = $this->getMetaForState($connections);
|
$this->connections = $connections;
|
||||||
$this->level->setBlock($this, $this, false, false); //avoid recursion
|
$this->level->setBlock($this, $this, false, false); //avoid recursion
|
||||||
}
|
}
|
||||||
|
|
||||||
public function onNearbyBlockChange() : void{
|
public function onNearbyBlockChange() : void{
|
||||||
if($this->getSide(Facing::DOWN)->isTransparent() or (
|
if($this->getSide(Facing::DOWN)->isTransparent()){
|
||||||
isset(self::ASCENDING_SIDES[$this->meta & 0x07]) and
|
$this->level->useBreakOn($this);
|
||||||
$this->getSide(self::ASCENDING_SIDES[$this->meta & 0x07])->isTransparent()
|
}else{
|
||||||
)){
|
foreach($this->connections as $connection){
|
||||||
$this->getLevel()->useBreakOn($this);
|
if(($connection & self::FLAG_ASCEND) !== 0 and $this->getSide($connection & ~self::FLAG_ASCEND)->isTransparent()){
|
||||||
|
$this->level->useBreakOn($this);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getVariantBitmask() : int{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -37,15 +37,38 @@ use pocketmine\tile\Tile;
|
|||||||
use pocketmine\utils\TextFormat;
|
use pocketmine\utils\TextFormat;
|
||||||
|
|
||||||
class Bed extends Transparent{
|
class Bed extends Transparent{
|
||||||
public const BITFLAG_OCCUPIED = 0x04;
|
private const BITFLAG_OCCUPIED = 0x04;
|
||||||
public const BITFLAG_HEAD = 0x08;
|
private const BITFLAG_HEAD = 0x08;
|
||||||
|
|
||||||
protected $id = self::BED_BLOCK;
|
protected $id = self::BED_BLOCK;
|
||||||
|
|
||||||
protected $itemId = Item::BED;
|
protected $itemId = Item::BED;
|
||||||
|
|
||||||
public function __construct(int $meta = 0){
|
/** @var int */
|
||||||
$this->setDamage($meta);
|
protected $facing = Facing::NORTH;
|
||||||
|
/** @var bool */
|
||||||
|
protected $occupied = false;
|
||||||
|
/** @var bool */
|
||||||
|
protected $head = false;
|
||||||
|
|
||||||
|
public function __construct(){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function writeStateToMeta() : int{
|
||||||
|
return Bearing::fromFacing($this->facing) |
|
||||||
|
($this->occupied ? self::BITFLAG_OCCUPIED : 0) |
|
||||||
|
($this->head ? self::BITFLAG_HEAD : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function readStateFromMeta(int $meta) : void{
|
||||||
|
$this->facing = Bearing::toFacing($meta & 0x03);
|
||||||
|
$this->occupied = ($meta & self::BITFLAG_OCCUPIED) !== 0;
|
||||||
|
$this->head = ($meta & self::BITFLAG_HEAD) !== 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getStateBitmask() : int{
|
||||||
|
return 0b1111;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getHardness() : float{
|
public function getHardness() : float{
|
||||||
@ -61,51 +84,39 @@ class Bed extends Transparent{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function isHeadPart() : bool{
|
public function isHeadPart() : bool{
|
||||||
return ($this->meta & self::BITFLAG_HEAD) !== 0;
|
return $this->head;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
public function isOccupied() : bool{
|
public function isOccupied() : bool{
|
||||||
return ($this->meta & self::BITFLAG_OCCUPIED) !== 0;
|
return $this->occupied;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setOccupied(bool $occupied = true){
|
public function setOccupied(bool $occupied = true){
|
||||||
if($occupied){
|
$this->occupied = $occupied;
|
||||||
$this->meta |= self::BITFLAG_OCCUPIED;
|
$this->level->setBlock($this, $this, false, false);
|
||||||
}else{
|
|
||||||
$this->meta &= ~self::BITFLAG_OCCUPIED;
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->getLevel()->setBlock($this, $this, false, false);
|
if(($other = $this->getOtherHalf()) !== null){
|
||||||
|
$other->occupied = $occupied;
|
||||||
if(($other = $this->getOtherHalf()) !== null and $other->isOccupied() !== $occupied){
|
$this->level->setBlock($other, $other, false, false);
|
||||||
$other->setOccupied($occupied);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param int $meta
|
|
||||||
* @param bool $isHead
|
|
||||||
*
|
|
||||||
* @return int
|
* @return int
|
||||||
*/
|
*/
|
||||||
public static function getOtherHalfSide(int $meta, bool $isHead = false) : int{
|
private function getOtherHalfSide() : int{
|
||||||
$side = Bearing::toFacing($meta & 0x03);
|
return $this->head ? Facing::opposite($this->facing) : $this->facing;
|
||||||
if($isHead){
|
|
||||||
$side = Facing::opposite($side);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $side;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Bed|null
|
* @return Bed|null
|
||||||
*/
|
*/
|
||||||
public function getOtherHalf() : ?Bed{
|
public function getOtherHalf() : ?Bed{
|
||||||
$other = $this->getSide(self::getOtherHalfSide($this->meta, $this->isHeadPart()));
|
$other = $this->getSide($this->getOtherHalfSide());
|
||||||
if($other instanceof Bed and $other->getId() === $this->getId() and $other->isHeadPart() !== $this->isHeadPart() and (($other->getDamage() & 0x03) === ($this->getDamage() & 0x03))){
|
if($other instanceof Bed and $other->head !== $this->head and $other->facing === $this->facing){
|
||||||
return $other;
|
return $other;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -152,11 +163,14 @@ class Bed extends Transparent{
|
|||||||
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
|
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
|
||||||
$down = $this->getSide(Facing::DOWN);
|
$down = $this->getSide(Facing::DOWN);
|
||||||
if(!$down->isTransparent()){
|
if(!$down->isTransparent()){
|
||||||
$this->meta = $player instanceof Player ? $player->getDirection() : 0;
|
$this->facing = $player !== null ? Bearing::toFacing($player->getDirection()) : Facing::NORTH;
|
||||||
$next = $this->getSide(self::getOtherHalfSide($this->meta));
|
|
||||||
|
$next = $this->getSide($this->getOtherHalfSide());
|
||||||
if($next->canBeReplaced() and !$next->getSide(Facing::DOWN)->isTransparent()){
|
if($next->canBeReplaced() and !$next->getSide(Facing::DOWN)->isTransparent()){
|
||||||
parent::place($item, $blockReplace, $blockClicked, $face, $clickVector, $player);
|
parent::place($item, $blockReplace, $blockClicked, $face, $clickVector, $player);
|
||||||
$this->getLevel()->setBlock($next, BlockFactory::get($this->id, $this->meta | self::BITFLAG_HEAD), true, true);
|
$nextState = clone $this;
|
||||||
|
$nextState->head = true;
|
||||||
|
$this->getLevel()->setBlock($next, $nextState, true, true);
|
||||||
|
|
||||||
Tile::createTile(Tile::BED, $this->getLevel(), TileBed::createNBT($this, $face, $item, $player));
|
Tile::createTile(Tile::BED, $this->getLevel(), TileBed::createNBT($this, $face, $item, $player));
|
||||||
Tile::createTile(Tile::BED, $this->getLevel(), TileBed::createNBT($next, $face, $item, $player));
|
Tile::createTile(Tile::BED, $this->getLevel(), TileBed::createNBT($next, $face, $item, $player));
|
||||||
|
@ -29,8 +29,8 @@ class Bedrock extends Solid{
|
|||||||
|
|
||||||
protected $id = self::BEDROCK;
|
protected $id = self::BEDROCK;
|
||||||
|
|
||||||
public function __construct(int $meta = 0){
|
public function __construct(){
|
||||||
$this->setDamage($meta);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getName() : string{
|
public function getName() : string{
|
||||||
|
@ -30,16 +30,12 @@ class Beetroot extends Crops{
|
|||||||
|
|
||||||
protected $id = self::BEETROOT_BLOCK;
|
protected $id = self::BEETROOT_BLOCK;
|
||||||
|
|
||||||
public function __construct(int $meta = 0){
|
|
||||||
$this->setDamage($meta);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getName() : string{
|
public function getName() : string{
|
||||||
return "Beetroot Block";
|
return "Beetroot Block";
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getDropsForCompatibleTool(Item $item) : array{
|
public function getDropsForCompatibleTool(Item $item) : array{
|
||||||
if($this->meta >= 0x07){
|
if($this->age >= 7){
|
||||||
return [
|
return [
|
||||||
ItemFactory::get(Item::BEETROOT),
|
ItemFactory::get(Item::BEETROOT),
|
||||||
ItemFactory::get(Item::BEETROOT_SEEDS, 0, mt_rand(0, 3))
|
ItemFactory::get(Item::BEETROOT_SEEDS, 0, mt_rand(0, 3))
|
||||||
|
@ -60,7 +60,7 @@ class Block extends Position implements BlockIds, Metadatable{
|
|||||||
/** @var int */
|
/** @var int */
|
||||||
protected $id;
|
protected $id;
|
||||||
/** @var int */
|
/** @var int */
|
||||||
protected $meta = 0;
|
protected $variant = 0;
|
||||||
/** @var string|null */
|
/** @var string|null */
|
||||||
protected $fallbackName;
|
protected $fallbackName;
|
||||||
/** @var int|null */
|
/** @var int|null */
|
||||||
@ -74,14 +74,18 @@ class Block extends Position implements BlockIds, Metadatable{
|
|||||||
protected $collisionBoxes = null;
|
protected $collisionBoxes = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param int $id The block type's ID, 0-255
|
* @param int $id The block type's ID, 0-255
|
||||||
* @param int $meta Meta value of the block type
|
* @param int $variant Meta value of the block type
|
||||||
* @param string|null $name English name of the block type (TODO: implement translations)
|
* @param string|null $name English name of the block type (TODO: implement translations)
|
||||||
* @param int $itemId The item ID of the block type, used for block picking and dropping items.
|
* @param int $itemId The item ID of the block type, used for block picking and dropping items.
|
||||||
*/
|
*/
|
||||||
public function __construct(int $id, int $meta = 0, string $name = null, int $itemId = null){
|
public function __construct(int $id, int $variant = 0, string $name = null, int $itemId = null){
|
||||||
$this->id = $id;
|
$this->id = $id;
|
||||||
$this->meta = $meta;
|
|
||||||
|
if(($variant & $this->getStateBitmask()) !== 0){
|
||||||
|
throw new \InvalidArgumentException("Variant 0x" . dechex($variant) . " collides with state bitmask 0x" . dechex($this->getStateBitmask()));
|
||||||
|
}
|
||||||
|
$this->variant = $variant;
|
||||||
$this->fallbackName = $name;
|
$this->fallbackName = $name;
|
||||||
$this->itemId = $itemId;
|
$this->itemId = $itemId;
|
||||||
}
|
}
|
||||||
@ -122,30 +126,26 @@ class Block extends Position implements BlockIds, Metadatable{
|
|||||||
* @return int
|
* @return int
|
||||||
*/
|
*/
|
||||||
public function getDamage() : int{
|
public function getDamage() : int{
|
||||||
return $this->meta;
|
$stateMeta = $this->writeStateToMeta();
|
||||||
|
assert(($stateMeta & ~$this->getStateBitmask()) === 0);
|
||||||
|
return $this->variant | $stateMeta;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function writeStateToMeta() : int{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function readStateFromMeta(int $meta) : void{
|
||||||
|
//NOOP
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param int $meta
|
* Returns a bitmask used to extract state bits from block metadata.
|
||||||
*/
|
|
||||||
public function setDamage(int $meta) : void{
|
|
||||||
if($meta < 0 or $meta > 0xf){
|
|
||||||
throw new \InvalidArgumentException("Block damage values must be 0-15, not $meta");
|
|
||||||
}
|
|
||||||
$this->meta = $meta;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Bitmask to use to remove superfluous information from block meta when getting its item form or name.
|
|
||||||
* This defaults to -1 (don't remove any data). Used to remove rotation data and bitflags from block drops.
|
|
||||||
*
|
|
||||||
* If your block should not have any meta value when it's dropped as an item, override this to return 0 in
|
|
||||||
* descendent classes.
|
|
||||||
*
|
*
|
||||||
* @return int
|
* @return int
|
||||||
*/
|
*/
|
||||||
public function getVariantBitmask() : int{
|
public function getStateBitmask() : int{
|
||||||
return -1;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -153,10 +153,9 @@ class Block extends Position implements BlockIds, Metadatable{
|
|||||||
* @return int
|
* @return int
|
||||||
*/
|
*/
|
||||||
public function getVariant() : int{
|
public function getVariant() : int{
|
||||||
return $this->meta & $this->getVariantBitmask();
|
return $this->variant;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* AKA: Block->isPlaceable
|
* AKA: Block->isPlaceable
|
||||||
* @return bool
|
* @return bool
|
||||||
|
@ -23,6 +23,8 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace pocketmine\block;
|
namespace pocketmine\block;
|
||||||
|
|
||||||
|
use pocketmine\block\utils\Color;
|
||||||
|
use pocketmine\block\utils\WoodType;
|
||||||
use pocketmine\item\Item;
|
use pocketmine\item\Item;
|
||||||
use pocketmine\level\Position;
|
use pocketmine\level\Position;
|
||||||
|
|
||||||
@ -32,6 +34,8 @@ use pocketmine\level\Position;
|
|||||||
class BlockFactory{
|
class BlockFactory{
|
||||||
/** @var \SplFixedArray<Block> */
|
/** @var \SplFixedArray<Block> */
|
||||||
private static $fullList = null;
|
private static $fullList = null;
|
||||||
|
/** @var \SplFixedArray|\Closure[] */
|
||||||
|
private static $getInterceptors = null;
|
||||||
|
|
||||||
/** @var \SplFixedArray<int> */
|
/** @var \SplFixedArray<int> */
|
||||||
public static $lightFilter = null;
|
public static $lightFilter = null;
|
||||||
@ -40,6 +44,9 @@ class BlockFactory{
|
|||||||
/** @var \SplFixedArray<float> */
|
/** @var \SplFixedArray<float> */
|
||||||
public static $blastResistance = null;
|
public static $blastResistance = null;
|
||||||
|
|
||||||
|
/** @var \SplFixedArray|int[] */
|
||||||
|
public static $stateMasks = null;
|
||||||
|
|
||||||
/** @var int[] */
|
/** @var int[] */
|
||||||
public static $staticRuntimeIdMap = [];
|
public static $staticRuntimeIdMap = [];
|
||||||
|
|
||||||
@ -55,56 +62,138 @@ class BlockFactory{
|
|||||||
*/
|
*/
|
||||||
public static function init() : void{
|
public static function init() : void{
|
||||||
self::$fullList = new \SplFixedArray(4096);
|
self::$fullList = new \SplFixedArray(4096);
|
||||||
|
self::$getInterceptors = new \SplFixedArray(4096);
|
||||||
|
|
||||||
self::$lightFilter = \SplFixedArray::fromArray(array_fill(0, 256, 1));
|
self::$lightFilter = \SplFixedArray::fromArray(array_fill(0, 256, 1));
|
||||||
self::$diffusesSkyLight = \SplFixedArray::fromArray(array_fill(0, 256, false));
|
self::$diffusesSkyLight = \SplFixedArray::fromArray(array_fill(0, 256, false));
|
||||||
self::$blastResistance = \SplFixedArray::fromArray(array_fill(0, 256, 0));
|
self::$blastResistance = \SplFixedArray::fromArray(array_fill(0, 256, 0));
|
||||||
|
|
||||||
|
self::$stateMasks = \SplFixedArray::fromArray(array_fill(0, 256, 0));
|
||||||
|
|
||||||
self::registerBlock(new Air());
|
self::registerBlock(new Air());
|
||||||
self::registerBlock(new Stone());
|
|
||||||
|
//TODO: give smooth stone its own class (different drops)
|
||||||
|
self::registerBlock(new Stone(Block::STONE, Stone::NORMAL, "Stone"));
|
||||||
|
self::registerBlock(new Stone(Block::STONE, Stone::GRANITE, "Granite"));
|
||||||
|
self::registerBlock(new Stone(Block::STONE, Stone::POLISHED_GRANITE, "Polished Granite"));
|
||||||
|
self::registerBlock(new Stone(Block::STONE, Stone::DIORITE, "Diorite"));
|
||||||
|
self::registerBlock(new Stone(Block::STONE, Stone::POLISHED_DIORITE, "Polished Diorite"));
|
||||||
|
self::registerBlock(new Stone(Block::STONE, Stone::ANDESITE, "Andesite"));
|
||||||
|
self::registerBlock(new Stone(Block::STONE, Stone::POLISHED_ANDESITE, "Polished Andesite"));
|
||||||
|
|
||||||
self::registerBlock(new Grass());
|
self::registerBlock(new Grass());
|
||||||
self::registerBlock(new Dirt());
|
|
||||||
|
//TODO: split these into separate classes
|
||||||
|
self::registerBlock(new Dirt(Block::DIRT, Dirt::NORMAL, "Dirt"));
|
||||||
|
self::registerBlock(new Dirt(Block::DIRT, Dirt::COARSE, "Coarse Dirt"));
|
||||||
|
|
||||||
self::registerBlock(new Cobblestone());
|
self::registerBlock(new Cobblestone());
|
||||||
self::registerBlock(new Planks());
|
|
||||||
self::registerBlock(new Sapling());
|
foreach(WoodType::ALL as $type){
|
||||||
|
self::registerBlock(new Planks(Block::PLANKS, $type, WoodType::NAMES[$type] . " Planks"));
|
||||||
|
self::registerBlock(new Sapling(Block::SAPLING, $type, WoodType::NAMES[$type] . " Sapling"));
|
||||||
|
self::registerBlock(new WoodenFence(Block::FENCE, $type, WoodType::NAMES[$type] . " Fence"));
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach(WoodType::ALL as $type){
|
||||||
|
//TODO: find a better way to deal with this split
|
||||||
|
self::registerBlock(new Wood($type >= 4 ? Block::WOOD2 : Block::WOOD, $type & 0x03, WoodType::NAMES[$type] . " Wood"));
|
||||||
|
self::registerBlock(new Leaves($type >= 4 ? Block::LEAVES2 : Block::LEAVES, $type & 0x03, $type, WoodType::NAMES[$type] . " Leaves"));
|
||||||
|
}
|
||||||
|
|
||||||
self::registerBlock(new Bedrock());
|
self::registerBlock(new Bedrock());
|
||||||
self::registerBlock(new Water());
|
self::registerBlock(new Water());
|
||||||
self::registerBlock(new StillWater());
|
self::registerBlock(new StillWater());
|
||||||
self::registerBlock(new Lava());
|
self::registerBlock(new Lava());
|
||||||
self::registerBlock(new StillLava());
|
self::registerBlock(new StillLava());
|
||||||
self::registerBlock(new Sand());
|
|
||||||
|
self::registerBlock(new Sand(Block::SAND, 0, "Sand"));
|
||||||
|
self::registerBlock(new Sand(Block::SAND, 1, "Red Sand"));
|
||||||
|
|
||||||
self::registerBlock(new Gravel());
|
self::registerBlock(new Gravel());
|
||||||
self::registerBlock(new GoldOre());
|
self::registerBlock(new GoldOre());
|
||||||
self::registerBlock(new IronOre());
|
self::registerBlock(new IronOre());
|
||||||
self::registerBlock(new CoalOre());
|
self::registerBlock(new CoalOre());
|
||||||
self::registerBlock(new Wood());
|
|
||||||
self::registerBlock(new Leaves());
|
|
||||||
self::registerBlock(new Sponge());
|
self::registerBlock(new Sponge());
|
||||||
self::registerBlock(new Glass());
|
self::registerBlock(new Glass(Block::GLASS, 0, "Glass"));
|
||||||
self::registerBlock(new LapisOre());
|
self::registerBlock(new LapisOre());
|
||||||
self::registerBlock(new Lapis());
|
self::registerBlock(new Lapis());
|
||||||
//TODO: DISPENSER
|
//TODO: DISPENSER
|
||||||
self::registerBlock(new Sandstone());
|
|
||||||
|
static $sandstoneTypes = [
|
||||||
|
Sandstone::NORMAL => "",
|
||||||
|
Sandstone::CHISELED => "Chiseled ",
|
||||||
|
Sandstone::SMOOTH => "Smooth "
|
||||||
|
];
|
||||||
|
foreach($sandstoneTypes as $variant => $prefix){
|
||||||
|
self::registerBlock(new Sandstone(Block::SANDSTONE, $variant, $prefix . "Sandstone"));
|
||||||
|
self::registerBlock(new Sandstone(Block::RED_SANDSTONE, $variant, $prefix . "Red Sandstone"));
|
||||||
|
}
|
||||||
|
|
||||||
self::registerBlock(new NoteBlock());
|
self::registerBlock(new NoteBlock());
|
||||||
self::registerBlock(new Bed());
|
self::registerBlock(new Bed());
|
||||||
self::registerBlock(new PoweredRail());
|
self::registerBlock(new PoweredRail());
|
||||||
self::registerBlock(new DetectorRail());
|
self::registerBlock(new DetectorRail());
|
||||||
//TODO: STICKY_PISTON
|
//TODO: STICKY_PISTON
|
||||||
self::registerBlock(new Cobweb());
|
self::registerBlock(new Cobweb());
|
||||||
self::registerBlock(new TallGrass());
|
|
||||||
|
self::registerBlock(new TallGrass(Block::TALL_GRASS, 0, "Fern"));
|
||||||
|
self::registerBlock(new TallGrass(Block::TALL_GRASS, 1, "Tall Grass"));
|
||||||
|
self::registerBlock(new TallGrass(Block::TALL_GRASS, 2, "Fern"));
|
||||||
|
self::registerBlock(new TallGrass(Block::TALL_GRASS, 3, "Fern"));
|
||||||
|
|
||||||
self::registerBlock(new DeadBush());
|
self::registerBlock(new DeadBush());
|
||||||
//TODO: PISTON
|
//TODO: PISTON
|
||||||
//TODO: PISTONARMCOLLISION
|
//TODO: PISTONARMCOLLISION
|
||||||
self::registerBlock(new Wool());
|
|
||||||
|
foreach(Color::ALL as $color){
|
||||||
|
self::registerBlock(new Wool(Block::WOOL, $color, Color::NAMES[$color] . " Wool"));
|
||||||
|
self::registerBlock(new HardenedClay(Block::STAINED_CLAY, $color, Color::NAMES[$color] . " Stained Clay"));
|
||||||
|
self::registerBlock(new Glass(Block::STAINED_GLASS, $color, Color::NAMES[$color] . " Stained Glass"));
|
||||||
|
self::registerBlock(new GlassPane(Block::STAINED_GLASS_PANE, $color, Color::NAMES[$color] . " Stained Glass Pane"));
|
||||||
|
self::registerBlock(new Carpet(Block::CARPET, $color, Color::NAMES[$color] . " Carpet"));
|
||||||
|
self::registerBlock(new Concrete(Block::CONCRETE, $color, Color::NAMES[$color] . " Concrete"));
|
||||||
|
self::registerBlock(new ConcretePowder(Block::CONCRETE_POWDER, $color, Color::NAMES[$color] . " Concrete Powder"));
|
||||||
|
}
|
||||||
|
|
||||||
self::registerBlock(new Dandelion());
|
self::registerBlock(new Dandelion());
|
||||||
self::registerBlock(new Flower());
|
|
||||||
|
self::registerBlock(new Flower(Block::RED_FLOWER, Flower::TYPE_POPPY, "Poppy"));
|
||||||
|
self::registerBlock(new Flower(Block::RED_FLOWER, Flower::TYPE_BLUE_ORCHID, "Blue Orchid"));
|
||||||
|
self::registerBlock(new Flower(Block::RED_FLOWER, Flower::TYPE_ALLIUM, "Allium"));
|
||||||
|
self::registerBlock(new Flower(Block::RED_FLOWER, Flower::TYPE_AZURE_BLUET, "Azure Bluet"));
|
||||||
|
self::registerBlock(new Flower(Block::RED_FLOWER, Flower::TYPE_RED_TULIP, "Red Tulip"));
|
||||||
|
self::registerBlock(new Flower(Block::RED_FLOWER, Flower::TYPE_ORANGE_TULIP, "Orange Tulip"));
|
||||||
|
self::registerBlock(new Flower(Block::RED_FLOWER, Flower::TYPE_WHITE_TULIP, "White Tulip"));
|
||||||
|
self::registerBlock(new Flower(Block::RED_FLOWER, Flower::TYPE_PINK_TULIP, "Pink Tulip"));
|
||||||
|
self::registerBlock(new Flower(Block::RED_FLOWER, Flower::TYPE_OXEYE_DAISY, "Oxeye Daisy"));
|
||||||
|
|
||||||
self::registerBlock(new BrownMushroom());
|
self::registerBlock(new BrownMushroom());
|
||||||
self::registerBlock(new RedMushroom());
|
self::registerBlock(new RedMushroom());
|
||||||
self::registerBlock(new Gold());
|
self::registerBlock(new Gold());
|
||||||
self::registerBlock(new Iron());
|
self::registerBlock(new Iron());
|
||||||
self::registerBlock(new DoubleStoneSlab());
|
|
||||||
self::registerBlock(new StoneSlab());
|
/** @var Slab[] $slabTypes */
|
||||||
|
$slabTypes = [
|
||||||
|
new StoneSlab(Block::STONE_SLAB, Block::DOUBLE_STONE_SLAB, 0, "Stone"),
|
||||||
|
new StoneSlab(Block::STONE_SLAB, Block::DOUBLE_STONE_SLAB, 1, "Sandstone"),
|
||||||
|
new StoneSlab(Block::STONE_SLAB, Block::DOUBLE_STONE_SLAB, 2, "Fake Wooden"),
|
||||||
|
new StoneSlab(Block::STONE_SLAB, Block::DOUBLE_STONE_SLAB, 3, "Cobblestone"),
|
||||||
|
new StoneSlab(Block::STONE_SLAB, Block::DOUBLE_STONE_SLAB, 4, "Brick"),
|
||||||
|
new StoneSlab(Block::STONE_SLAB, Block::DOUBLE_STONE_SLAB, 5, "Stone Brick"),
|
||||||
|
new StoneSlab(Block::STONE_SLAB, Block::DOUBLE_STONE_SLAB, 6, "Quartz"),
|
||||||
|
new StoneSlab(Block::STONE_SLAB, Block::DOUBLE_STONE_SLAB, 7, "Nether Brick"),
|
||||||
|
new StoneSlab(Block::STONE_SLAB2, Block::DOUBLE_STONE_SLAB2, 0, "Red Sandstone"),
|
||||||
|
new StoneSlab(Block::STONE_SLAB2, Block::DOUBLE_STONE_SLAB2, 1, "Purpur")
|
||||||
|
];
|
||||||
|
foreach(WoodType::ALL as $woodType){
|
||||||
|
$slabTypes[] = new WoodenSlab($woodType);
|
||||||
|
}
|
||||||
|
foreach($slabTypes as $type){
|
||||||
|
self::registerBlock($type);
|
||||||
|
self::registerBlock(new DoubleSlab($type->getDoubleSlabId(), $type->getId(), $type->getVariant()));
|
||||||
|
}
|
||||||
|
|
||||||
self::registerBlock(new Bricks());
|
self::registerBlock(new Bricks());
|
||||||
self::registerBlock(new TNT());
|
self::registerBlock(new TNT());
|
||||||
self::registerBlock(new Bookshelf());
|
self::registerBlock(new Bookshelf());
|
||||||
@ -121,8 +210,16 @@ class BlockFactory{
|
|||||||
self::registerBlock(new CraftingTable());
|
self::registerBlock(new CraftingTable());
|
||||||
self::registerBlock(new Wheat());
|
self::registerBlock(new Wheat());
|
||||||
self::registerBlock(new Farmland());
|
self::registerBlock(new Farmland());
|
||||||
|
|
||||||
self::registerBlock(new Furnace());
|
self::registerBlock(new Furnace());
|
||||||
self::registerBlock(new BurningFurnace());
|
self::addGetInterceptor(Block::BURNING_FURNACE, 0, function() : Block{
|
||||||
|
$block = self::get(Block::FURNACE);
|
||||||
|
if($block instanceof Furnace){
|
||||||
|
$block->setLit();
|
||||||
|
}
|
||||||
|
return $block;
|
||||||
|
});
|
||||||
|
|
||||||
self::registerBlock(new SignPost());
|
self::registerBlock(new SignPost());
|
||||||
self::registerBlock(new WoodenDoor(Block::OAK_DOOR_BLOCK, 0, "Oak Door", Item::OAK_DOOR));
|
self::registerBlock(new WoodenDoor(Block::OAK_DOOR_BLOCK, 0, "Oak Door", Item::OAK_DOOR));
|
||||||
self::registerBlock(new Ladder());
|
self::registerBlock(new Ladder());
|
||||||
@ -134,9 +231,23 @@ class BlockFactory{
|
|||||||
self::registerBlock(new IronDoor());
|
self::registerBlock(new IronDoor());
|
||||||
self::registerBlock(new WoodenPressurePlate());
|
self::registerBlock(new WoodenPressurePlate());
|
||||||
self::registerBlock(new RedstoneOre());
|
self::registerBlock(new RedstoneOre());
|
||||||
self::registerBlock(new GlowingRedstoneOre());
|
self::addGetInterceptor(Block::GLOWING_REDSTONE_ORE, 0, function() : Block{
|
||||||
self::registerBlock(new RedstoneTorchUnlit());
|
$block = self::get(Block::REDSTONE_ORE);
|
||||||
|
if($block instanceof RedstoneOre){
|
||||||
|
$block->setLit();
|
||||||
|
}
|
||||||
|
return $block;
|
||||||
|
});
|
||||||
|
|
||||||
self::registerBlock(new RedstoneTorch());
|
self::registerBlock(new RedstoneTorch());
|
||||||
|
self::addGetInterceptor(Block::UNLIT_REDSTONE_TORCH, 0, function() : Block{
|
||||||
|
$block = self::get(Block::REDSTONE_TORCH);
|
||||||
|
if($block instanceof RedstoneTorch){
|
||||||
|
$block->setLit(false); //default state is lit
|
||||||
|
}
|
||||||
|
return $block;
|
||||||
|
});
|
||||||
|
|
||||||
self::registerBlock(new StoneButton());
|
self::registerBlock(new StoneButton());
|
||||||
self::registerBlock(new SnowLayer());
|
self::registerBlock(new SnowLayer());
|
||||||
self::registerBlock(new Ice());
|
self::registerBlock(new Ice());
|
||||||
@ -145,7 +256,7 @@ class BlockFactory{
|
|||||||
self::registerBlock(new Clay());
|
self::registerBlock(new Clay());
|
||||||
self::registerBlock(new Sugarcane());
|
self::registerBlock(new Sugarcane());
|
||||||
//TODO: JUKEBOX
|
//TODO: JUKEBOX
|
||||||
self::registerBlock(new WoodenFence());
|
|
||||||
self::registerBlock(new Pumpkin());
|
self::registerBlock(new Pumpkin());
|
||||||
self::registerBlock(new Netherrack());
|
self::registerBlock(new Netherrack());
|
||||||
self::registerBlock(new SoulSand());
|
self::registerBlock(new SoulSand());
|
||||||
@ -158,11 +269,16 @@ class BlockFactory{
|
|||||||
//TODO: INVISIBLEBEDROCK
|
//TODO: INVISIBLEBEDROCK
|
||||||
self::registerBlock(new Trapdoor());
|
self::registerBlock(new Trapdoor());
|
||||||
//TODO: MONSTER_EGG
|
//TODO: MONSTER_EGG
|
||||||
self::registerBlock(new StoneBricks());
|
|
||||||
|
self::registerBlock(new StoneBricks(Block::STONE_BRICKS, StoneBricks::NORMAL, "Stone Bricks"));
|
||||||
|
self::registerBlock(new StoneBricks(Block::STONE_BRICKS, StoneBricks::MOSSY, "Mossy Stone Bricks"));
|
||||||
|
self::registerBlock(new StoneBricks(Block::STONE_BRICKS, StoneBricks::CRACKED, "Cracked Stone Bricks"));
|
||||||
|
self::registerBlock(new StoneBricks(Block::STONE_BRICKS, StoneBricks::CHISELED, "Chiseled Stone Bricks"));
|
||||||
|
|
||||||
self::registerBlock(new BrownMushroomBlock());
|
self::registerBlock(new BrownMushroomBlock());
|
||||||
self::registerBlock(new RedMushroomBlock());
|
self::registerBlock(new RedMushroomBlock());
|
||||||
self::registerBlock(new IronBars());
|
self::registerBlock(new IronBars());
|
||||||
self::registerBlock(new GlassPane());
|
self::registerBlock(new GlassPane(Block::GLASS_PANE, 0, "Glass Pane"));
|
||||||
self::registerBlock(new Melon());
|
self::registerBlock(new Melon());
|
||||||
self::registerBlock(new PumpkinStem());
|
self::registerBlock(new PumpkinStem());
|
||||||
self::registerBlock(new MelonStem());
|
self::registerBlock(new MelonStem());
|
||||||
@ -184,7 +300,14 @@ class BlockFactory{
|
|||||||
self::registerBlock(new EndStone());
|
self::registerBlock(new EndStone());
|
||||||
//TODO: DRAGON_EGG
|
//TODO: DRAGON_EGG
|
||||||
self::registerBlock(new RedstoneLamp());
|
self::registerBlock(new RedstoneLamp());
|
||||||
self::registerBlock(new LitRedstoneLamp());
|
self::addGetInterceptor(Block::LIT_REDSTONE_LAMP, 0, function() : Block{
|
||||||
|
$block = self::get(Block::REDSTONE_LAMP);
|
||||||
|
if($block instanceof RedstoneLamp){
|
||||||
|
$block->setLit();
|
||||||
|
}
|
||||||
|
return $block;
|
||||||
|
});
|
||||||
|
|
||||||
//TODO: DROPPER
|
//TODO: DROPPER
|
||||||
self::registerBlock(new ActivatorRail());
|
self::registerBlock(new ActivatorRail());
|
||||||
self::registerBlock(new CocoaBlock());
|
self::registerBlock(new CocoaBlock());
|
||||||
@ -199,50 +322,76 @@ class BlockFactory{
|
|||||||
self::registerBlock(new WoodenStairs(Block::JUNGLE_STAIRS, 0, "Jungle Stairs"));
|
self::registerBlock(new WoodenStairs(Block::JUNGLE_STAIRS, 0, "Jungle Stairs"));
|
||||||
//TODO: COMMAND_BLOCK
|
//TODO: COMMAND_BLOCK
|
||||||
//TODO: BEACON
|
//TODO: BEACON
|
||||||
self::registerBlock(new CobblestoneWall());
|
|
||||||
|
self::registerBlock(new CobblestoneWall(Block::COBBLESTONE_WALL, CobblestoneWall::NONE_MOSSY_WALL, "Cobblestone Wall"));
|
||||||
|
self::registerBlock(new CobblestoneWall(Block::COBBLESTONE_WALL, CobblestoneWall::MOSSY_WALL, "Mossy Cobblestone Wall"));
|
||||||
|
|
||||||
self::registerBlock(new FlowerPot());
|
self::registerBlock(new FlowerPot());
|
||||||
self::registerBlock(new Carrot());
|
self::registerBlock(new Carrot());
|
||||||
self::registerBlock(new Potato());
|
self::registerBlock(new Potato());
|
||||||
self::registerBlock(new WoodenButton());
|
self::registerBlock(new WoodenButton());
|
||||||
self::registerBlock(new Skull());
|
self::registerBlock(new Skull());
|
||||||
self::registerBlock(new Anvil());
|
|
||||||
|
self::registerBlock(new Anvil(Block::ANVIL, Anvil::TYPE_NORMAL, "Anvil"));
|
||||||
|
self::registerBlock(new Anvil(Block::ANVIL, Anvil::TYPE_SLIGHTLY_DAMAGED, "Slightly Damaged Anvil"));
|
||||||
|
self::registerBlock(new Anvil(Block::ANVIL, Anvil::TYPE_VERY_DAMAGED, "Very Damaged Anvil"));
|
||||||
|
|
||||||
self::registerBlock(new TrappedChest());
|
self::registerBlock(new TrappedChest());
|
||||||
self::registerBlock(new WeightedPressurePlateLight());
|
self::registerBlock(new WeightedPressurePlateLight());
|
||||||
self::registerBlock(new WeightedPressurePlateHeavy());
|
self::registerBlock(new WeightedPressurePlateHeavy());
|
||||||
//TODO: COMPARATOR_BLOCK
|
//TODO: COMPARATOR_BLOCK
|
||||||
//TODO: POWERED_COMPARATOR
|
//TODO: POWERED_COMPARATOR
|
||||||
self::registerBlock(new DaylightSensor());
|
self::registerBlock(new DaylightSensor());
|
||||||
|
self::addGetInterceptor(Block::DAYLIGHT_SENSOR_INVERTED, 0, function() : Block{
|
||||||
|
$block = self::get(Block::DAYLIGHT_SENSOR);
|
||||||
|
if($block instanceof DaylightSensor){
|
||||||
|
$block->setInverted();
|
||||||
|
}
|
||||||
|
return $block;
|
||||||
|
});
|
||||||
|
|
||||||
self::registerBlock(new Redstone());
|
self::registerBlock(new Redstone());
|
||||||
self::registerBlock(new NetherQuartzOre());
|
self::registerBlock(new NetherQuartzOre());
|
||||||
//TODO: HOPPER_BLOCK
|
//TODO: HOPPER_BLOCK
|
||||||
self::registerBlock(new Quartz());
|
|
||||||
|
self::registerBlock(new Quartz(Block::QUARTZ_BLOCK, Quartz::NORMAL, "Quartz Block"));
|
||||||
|
self::registerBlock(new Quartz(Block::QUARTZ_BLOCK, Quartz::CHISELED, "Chiseled Quartz Block"));
|
||||||
|
self::registerBlock(new Quartz(Block::QUARTZ_BLOCK, Quartz::PILLAR, "Quartz Pillar"));
|
||||||
|
|
||||||
|
self::registerBlock(new Purpur(Block::PURPUR_BLOCK, Purpur::NORMAL, "Purpur Block"));
|
||||||
|
self::registerBlock(new Purpur(Block::PURPUR_BLOCK, Purpur::PILLAR, "Purpur Pillar"));
|
||||||
|
|
||||||
self::registerBlock(new QuartzStairs());
|
self::registerBlock(new QuartzStairs());
|
||||||
self::registerBlock(new DoubleWoodenSlab());
|
|
||||||
self::registerBlock(new WoodenSlab());
|
|
||||||
self::registerBlock(new StainedClay());
|
|
||||||
self::registerBlock(new StainedGlassPane());
|
|
||||||
self::registerBlock(new Leaves2());
|
|
||||||
self::registerBlock(new Wood2());
|
|
||||||
self::registerBlock(new WoodenStairs(Block::ACACIA_STAIRS, 0, "Acacia Stairs"));
|
self::registerBlock(new WoodenStairs(Block::ACACIA_STAIRS, 0, "Acacia Stairs"));
|
||||||
self::registerBlock(new WoodenStairs(Block::DARK_OAK_STAIRS, 0, "Dark Oak Stairs"));
|
self::registerBlock(new WoodenStairs(Block::DARK_OAK_STAIRS, 0, "Dark Oak Stairs"));
|
||||||
//TODO: SLIME
|
//TODO: SLIME
|
||||||
|
|
||||||
self::registerBlock(new IronTrapdoor());
|
self::registerBlock(new IronTrapdoor());
|
||||||
self::registerBlock(new Prismarine());
|
|
||||||
|
self::registerBlock(new Prismarine(Block::PRISMARINE, Prismarine::NORMAL, "Prismarine"));
|
||||||
|
self::registerBlock(new Prismarine(Block::PRISMARINE, Prismarine::DARK, "Dark Prismarine"));
|
||||||
|
self::registerBlock(new Prismarine(Block::PRISMARINE, Prismarine::BRICKS, "Prismarine Bricks"));
|
||||||
|
|
||||||
self::registerBlock(new SeaLantern());
|
self::registerBlock(new SeaLantern());
|
||||||
self::registerBlock(new HayBale());
|
self::registerBlock(new HayBale());
|
||||||
self::registerBlock(new Carpet());
|
|
||||||
self::registerBlock(new HardenedClay());
|
self::registerBlock(new HardenedClay(Block::HARDENED_CLAY, 0, "Hardened Clay"));
|
||||||
self::registerBlock(new Coal());
|
self::registerBlock(new Coal());
|
||||||
self::registerBlock(new PackedIce());
|
self::registerBlock(new PackedIce());
|
||||||
self::registerBlock(new DoublePlant());
|
|
||||||
|
self::registerBlock(new DoublePlant(Block::DOUBLE_PLANT, 0, "Sunflower"));
|
||||||
|
self::registerBlock(new DoublePlant(Block::DOUBLE_PLANT, 1, "Lilac"));
|
||||||
|
//TODO: double tallgrass and large fern have different behaviour than the others, so they should get their own classes
|
||||||
|
self::registerBlock(new DoublePlant(Block::DOUBLE_PLANT, 2, "Double Tallgrass"));
|
||||||
|
self::registerBlock(new DoublePlant(Block::DOUBLE_PLANT, 3, "Large Fern"));
|
||||||
|
self::registerBlock(new DoublePlant(Block::DOUBLE_PLANT, 4, "Rose Bush"));
|
||||||
|
self::registerBlock(new DoublePlant(Block::DOUBLE_PLANT, 5, "Peony"));
|
||||||
|
|
||||||
self::registerBlock(new StandingBanner());
|
self::registerBlock(new StandingBanner());
|
||||||
self::registerBlock(new WallBanner());
|
self::registerBlock(new WallBanner());
|
||||||
//TODO: DAYLIGHT_DETECTOR_INVERTED
|
|
||||||
self::registerBlock(new RedSandstone());
|
|
||||||
self::registerBlock(new RedSandstoneStairs());
|
self::registerBlock(new RedSandstoneStairs());
|
||||||
self::registerBlock(new DoubleStoneSlab2());
|
|
||||||
self::registerBlock(new StoneSlab2());
|
|
||||||
self::registerBlock(new FenceGate(Block::SPRUCE_FENCE_GATE, 0, "Spruce Fence Gate"));
|
self::registerBlock(new FenceGate(Block::SPRUCE_FENCE_GATE, 0, "Spruce Fence Gate"));
|
||||||
self::registerBlock(new FenceGate(Block::BIRCH_FENCE_GATE, 0, "Birch Fence Gate"));
|
self::registerBlock(new FenceGate(Block::BIRCH_FENCE_GATE, 0, "Birch Fence Gate"));
|
||||||
self::registerBlock(new FenceGate(Block::JUNGLE_FENCE_GATE, 0, "Jungle Fence Gate"));
|
self::registerBlock(new FenceGate(Block::JUNGLE_FENCE_GATE, 0, "Jungle Fence Gate"));
|
||||||
@ -259,7 +408,6 @@ class BlockFactory{
|
|||||||
self::registerBlock(new GrassPath());
|
self::registerBlock(new GrassPath());
|
||||||
self::registerBlock(new ItemFrame());
|
self::registerBlock(new ItemFrame());
|
||||||
//TODO: CHORUS_FLOWER
|
//TODO: CHORUS_FLOWER
|
||||||
self::registerBlock(new Purpur());
|
|
||||||
|
|
||||||
self::registerBlock(new PurpurStairs());
|
self::registerBlock(new PurpurStairs());
|
||||||
|
|
||||||
@ -292,11 +440,8 @@ class BlockFactory{
|
|||||||
self::registerBlock(new GlazedTerracotta(Block::GREEN_GLAZED_TERRACOTTA, 0, "Green Glazed Terracotta"));
|
self::registerBlock(new GlazedTerracotta(Block::GREEN_GLAZED_TERRACOTTA, 0, "Green Glazed Terracotta"));
|
||||||
self::registerBlock(new GlazedTerracotta(Block::RED_GLAZED_TERRACOTTA, 0, "Red Glazed Terracotta"));
|
self::registerBlock(new GlazedTerracotta(Block::RED_GLAZED_TERRACOTTA, 0, "Red Glazed Terracotta"));
|
||||||
self::registerBlock(new GlazedTerracotta(Block::BLACK_GLAZED_TERRACOTTA, 0, "Black Glazed Terracotta"));
|
self::registerBlock(new GlazedTerracotta(Block::BLACK_GLAZED_TERRACOTTA, 0, "Black Glazed Terracotta"));
|
||||||
self::registerBlock(new Concrete());
|
|
||||||
self::registerBlock(new ConcretePowder());
|
|
||||||
|
|
||||||
//TODO: CHORUS_PLANT
|
//TODO: CHORUS_PLANT
|
||||||
self::registerBlock(new StainedGlass());
|
|
||||||
|
|
||||||
self::registerBlock(new Podzol());
|
self::registerBlock(new Podzol());
|
||||||
self::registerBlock(new Beetroot());
|
self::registerBlock(new Beetroot());
|
||||||
@ -327,20 +472,17 @@ class BlockFactory{
|
|||||||
*/
|
*/
|
||||||
public static function registerBlock(Block $block, bool $override = false) : void{
|
public static function registerBlock(Block $block, bool $override = false) : void{
|
||||||
$id = $block->getId();
|
$id = $block->getId();
|
||||||
|
$variant = $block->getVariant();
|
||||||
|
|
||||||
if(!$override and self::isRegistered($id)){
|
if(!$override and self::isRegistered($id, $variant)){
|
||||||
throw new \RuntimeException("Trying to overwrite an already registered block");
|
throw new \RuntimeException("Trying to overwrite an already registered block");
|
||||||
}
|
}
|
||||||
|
|
||||||
for($meta = 0; $meta < 16; ++$meta){
|
self::$fullList[($id << 4) | $variant] = clone $block;
|
||||||
$variant = clone $block;
|
if($variant === 0){
|
||||||
$variant->setDamage($meta);
|
//TODO: allow these to differ for different variants
|
||||||
self::$fullList[($id << 4) | $meta] = $variant;
|
self::fillStaticArrays($id, $block);
|
||||||
}
|
}
|
||||||
|
|
||||||
self::$lightFilter[$id] = min(15, $block->getLightFilter() + 1); //opacity plus 1 standard light filter
|
|
||||||
self::$diffusesSkyLight[$id] = $block->diffusesSkyLight();
|
|
||||||
self::$blastResistance[$id] = $block->getBlastResistance();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -357,16 +499,34 @@ class BlockFactory{
|
|||||||
throw new \InvalidArgumentException("Block meta value $meta is out of bounds");
|
throw new \InvalidArgumentException("Block meta value $meta is out of bounds");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(self::$stateMasks[$id] === null){
|
||||||
|
$variant = 0;
|
||||||
|
$state = $meta;
|
||||||
|
}else{
|
||||||
|
$variant = $meta & ~self::$stateMasks[$id];
|
||||||
|
$state = $meta & self::$stateMasks[$id];
|
||||||
|
}
|
||||||
|
|
||||||
|
$index = ($id << 4) | $variant;
|
||||||
|
|
||||||
|
/** @var Block|null $block */
|
||||||
|
$block = null;
|
||||||
try{
|
try{
|
||||||
if(self::$fullList[($id << 4) | $meta] !== null){
|
if(self::$getInterceptors[$index] !== null){
|
||||||
$block = clone self::$fullList[($id << 4) | $meta];
|
$block = (self::$getInterceptors[$index])();
|
||||||
}else{
|
}elseif(self::$fullList[$index] !== null){
|
||||||
$block = new UnknownBlock($id, $meta);
|
$block = clone self::$fullList[$index];
|
||||||
}
|
}
|
||||||
}catch(\RuntimeException $e){
|
}catch(\RuntimeException $e){
|
||||||
throw new \InvalidArgumentException("Block ID $id is out of bounds");
|
throw new \InvalidArgumentException("Block ID $id is out of bounds");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if($block !== null){
|
||||||
|
$block->readStateFromMeta($state);
|
||||||
|
}else{
|
||||||
|
$block = new UnknownBlock($id, $meta);
|
||||||
|
}
|
||||||
|
|
||||||
if($pos !== null){
|
if($pos !== null){
|
||||||
$block->x = $pos->getFloorX();
|
$block->x = $pos->getFloorX();
|
||||||
$block->y = $pos->getFloorY();
|
$block->y = $pos->getFloorY();
|
||||||
@ -377,22 +537,32 @@ class BlockFactory{
|
|||||||
return $block;
|
return $block;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public static function addGetInterceptor(int $id, int $variant, \Closure $interceptor) : void{
|
||||||
* @internal
|
$block = $interceptor();
|
||||||
* @return \SplFixedArray
|
if(!($block instanceof Block)){
|
||||||
*/
|
throw new \InvalidArgumentException("Interceptor must return an instance of " . Block::class);
|
||||||
public static function getBlockStatesArray() : \SplFixedArray{
|
}
|
||||||
return self::$fullList;
|
self::$getInterceptors[($id << 4) | $variant] = $interceptor;
|
||||||
|
self::fillStaticArrays($id, $block);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static function fillStaticArrays(int $id, Block $block) : void{
|
||||||
|
self::$lightFilter[$id] = min(15, $block->getLightFilter() + 1); //opacity plus 1 standard light filter
|
||||||
|
self::$diffusesSkyLight[$id] = $block->diffusesSkyLight();
|
||||||
|
self::$blastResistance[$id] = $block->getBlastResistance();
|
||||||
|
self::$stateMasks[$id] = $block->getStateBitmask();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whether a specified block ID is already registered in the block factory.
|
* Returns whether a specified block ID is already registered in the block factory.
|
||||||
*
|
*
|
||||||
* @param int $id
|
* @param int $id
|
||||||
|
* @param int $variant
|
||||||
|
*
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
public static function isRegistered(int $id) : bool{
|
public static function isRegistered(int $id, int $variant = 0) : bool{
|
||||||
$b = self::$fullList[$id << 4];
|
$b = self::$fullList[($id << 4) | $variant];
|
||||||
return $b !== null and !($b instanceof UnknownBlock);
|
return $b !== null and !($b instanceof UnknownBlock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,18 +23,20 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace pocketmine\block;
|
namespace pocketmine\block;
|
||||||
|
|
||||||
use pocketmine\block\utils\PillarRotationHelper;
|
use pocketmine\block\utils\PillarRotationTrait;
|
||||||
use pocketmine\item\Item;
|
use pocketmine\item\Item;
|
||||||
use pocketmine\item\TieredTool;
|
use pocketmine\item\TieredTool;
|
||||||
|
use pocketmine\math\Facing;
|
||||||
use pocketmine\math\Vector3;
|
use pocketmine\math\Vector3;
|
||||||
use pocketmine\Player;
|
use pocketmine\Player;
|
||||||
|
|
||||||
class BoneBlock extends Solid{
|
class BoneBlock extends Solid{
|
||||||
|
use PillarRotationTrait;
|
||||||
|
|
||||||
protected $id = Block::BONE_BLOCK;
|
protected $id = Block::BONE_BLOCK;
|
||||||
|
|
||||||
public function __construct(int $meta = 0){
|
public function __construct(){
|
||||||
$this->setDamage($meta);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getName() : string{
|
public function getName() : string{
|
||||||
@ -54,11 +56,7 @@ class BoneBlock extends Solid{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
|
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
|
||||||
$this->meta = PillarRotationHelper::getMetaFromFace($this->meta, $face);
|
$this->axis = Facing::axis($face);
|
||||||
return parent::place($item, $blockReplace, $blockClicked, $face, $clickVector, $player);
|
return parent::place($item, $blockReplace, $blockClicked, $face, $clickVector, $player);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getVariantBitmask() : int{
|
|
||||||
return 0x03;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -30,8 +30,8 @@ class Bookshelf extends Solid{
|
|||||||
|
|
||||||
protected $id = self::BOOKSHELF;
|
protected $id = self::BOOKSHELF;
|
||||||
|
|
||||||
public function __construct(int $meta = 0){
|
public function __construct(){
|
||||||
$this->setDamage($meta);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getName() : string{
|
public function getName() : string{
|
||||||
|
@ -32,8 +32,29 @@ class BrewingStand extends Transparent{
|
|||||||
|
|
||||||
protected $itemId = Item::BREWING_STAND;
|
protected $itemId = Item::BREWING_STAND;
|
||||||
|
|
||||||
public function __construct(int $meta = 0){
|
/** @var bool */
|
||||||
$this->setDamage($meta);
|
protected $eastSlot = false;
|
||||||
|
/** @var bool */
|
||||||
|
protected $northwestSlot = false;
|
||||||
|
/** @var bool */
|
||||||
|
protected $southwestSlot = false;
|
||||||
|
|
||||||
|
public function __construct(){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function writeStateToMeta() : int{
|
||||||
|
return ($this->eastSlot ? 0x01 : 0) | ($this->southwestSlot ? 0x02 : 0) | ($this->northwestSlot ? 0x04 : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function readStateFromMeta(int $meta) : void{
|
||||||
|
$this->eastSlot = ($meta & 0x01) !== 0;
|
||||||
|
$this->southwestSlot = ($meta & 0x02) !== 0;
|
||||||
|
$this->northwestSlot = ($meta & 0x04) !== 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getStateBitmask() : int{
|
||||||
|
return 0b111;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getName() : string{
|
public function getName() : string{
|
||||||
@ -52,9 +73,5 @@ class BrewingStand extends Transparent{
|
|||||||
return TieredTool::TIER_WOODEN;
|
return TieredTool::TIER_WOODEN;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getVariantBitmask() : int{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
//TODO
|
//TODO
|
||||||
}
|
}
|
||||||
|
@ -29,8 +29,8 @@ class BrickStairs extends Stair{
|
|||||||
|
|
||||||
protected $id = self::BRICK_STAIRS;
|
protected $id = self::BRICK_STAIRS;
|
||||||
|
|
||||||
public function __construct(int $meta = 0){
|
public function __construct(){
|
||||||
$this->setDamage($meta);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getHardness() : float{
|
public function getHardness() : float{
|
||||||
|
@ -29,8 +29,8 @@ class Bricks extends Solid{
|
|||||||
|
|
||||||
protected $id = self::BRICK_BLOCK;
|
protected $id = self::BRICK_BLOCK;
|
||||||
|
|
||||||
public function __construct(int $meta = 0){
|
public function __construct(){
|
||||||
$this->setDamage($meta);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getHardness() : float{
|
public function getHardness() : float{
|
||||||
|
@ -1,96 +0,0 @@
|
|||||||
<?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\item\Item;
|
|
||||||
use pocketmine\item\TieredTool;
|
|
||||||
use pocketmine\math\Bearing;
|
|
||||||
use pocketmine\math\Vector3;
|
|
||||||
use pocketmine\Player;
|
|
||||||
use pocketmine\tile\Furnace as TileFurnace;
|
|
||||||
use pocketmine\tile\Tile;
|
|
||||||
|
|
||||||
class BurningFurnace extends Solid{
|
|
||||||
|
|
||||||
protected $id = self::BURNING_FURNACE;
|
|
||||||
|
|
||||||
protected $itemId = self::FURNACE;
|
|
||||||
|
|
||||||
public function __construct(int $meta = 0){
|
|
||||||
$this->setDamage($meta);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getName() : string{
|
|
||||||
return "Burning Furnace";
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getHardness() : float{
|
|
||||||
return 3.5;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getToolType() : int{
|
|
||||||
return BlockToolType::TYPE_PICKAXE;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getToolHarvestLevel() : int{
|
|
||||||
return TieredTool::TIER_WOODEN;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getLightLevel() : int{
|
|
||||||
return 13;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
|
|
||||||
if($player !== null){
|
|
||||||
$this->meta = Bearing::toFacing(Bearing::opposite($player->getDirection()));
|
|
||||||
}
|
|
||||||
if(parent::place($item, $blockReplace, $blockClicked, $face, $clickVector, $player)){
|
|
||||||
Tile::createTile(Tile::FURNACE, $this->getLevel(), TileFurnace::createNBT($this, $face, $item, $player));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function onActivate(Item $item, Player $player = null) : bool{
|
|
||||||
if($player instanceof Player){
|
|
||||||
$furnace = $this->getLevel()->getTile($this);
|
|
||||||
if(!($furnace instanceof TileFurnace)){
|
|
||||||
$furnace = Tile::createTile(Tile::FURNACE, $this->getLevel(), TileFurnace::createNBT($this));
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!$furnace->canOpenWith($item->getCustomName())){
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
$player->addWindow($furnace->getInventory());
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getVariantBitmask() : int{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
@ -24,22 +24,38 @@ declare(strict_types=1);
|
|||||||
namespace pocketmine\block;
|
namespace pocketmine\block;
|
||||||
|
|
||||||
use pocketmine\item\Item;
|
use pocketmine\item\Item;
|
||||||
|
use pocketmine\math\Facing;
|
||||||
use pocketmine\math\Vector3;
|
use pocketmine\math\Vector3;
|
||||||
use pocketmine\Player;
|
use pocketmine\Player;
|
||||||
|
|
||||||
abstract class Button extends Flowable{
|
abstract class Button extends Flowable{
|
||||||
|
|
||||||
public function __construct(int $meta = 0){
|
/** @var int */
|
||||||
$this->setDamage($meta);
|
protected $facing = Facing::DOWN;
|
||||||
|
/** @var bool */
|
||||||
|
protected $powered = false;
|
||||||
|
|
||||||
|
public function __construct(){
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getVariantBitmask() : int{
|
protected function writeStateToMeta() : int{
|
||||||
return 0;
|
return $this->facing | ($this->powered ? 0x08 : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function readStateFromMeta(int $meta) : void{
|
||||||
|
//TODO: in PC it's (6 - facing) for every meta except 0 (down)
|
||||||
|
$this->facing = $meta & 0x07;
|
||||||
|
$this->powered = ($meta & 0x08) !== 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getStateBitmask() : int{
|
||||||
|
return 0b1111;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
|
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
|
||||||
//TODO: check valid target block
|
//TODO: check valid target block
|
||||||
$this->meta = $face;
|
$this->facing = $face;
|
||||||
return parent::place($item, $blockReplace, $blockClicked, $face, $clickVector, $player);
|
return parent::place($item, $blockReplace, $blockClicked, $face, $clickVector, $player);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,8 +38,23 @@ class Cactus extends Transparent{
|
|||||||
|
|
||||||
protected $id = self::CACTUS;
|
protected $id = self::CACTUS;
|
||||||
|
|
||||||
public function __construct(int $meta = 0){
|
/** @var int */
|
||||||
$this->setDamage($meta);
|
protected $age = 0;
|
||||||
|
|
||||||
|
public function __construct(){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function writeStateToMeta() : int{
|
||||||
|
return $this->age;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function readStateFromMeta(int $meta) : void{
|
||||||
|
$this->age = $meta;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getStateBitmask() : int{
|
||||||
|
return 0b1111;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getHardness() : float{
|
public function getHardness() : float{
|
||||||
@ -85,7 +100,7 @@ class Cactus extends Transparent{
|
|||||||
|
|
||||||
public function onRandomTick() : void{
|
public function onRandomTick() : void{
|
||||||
if($this->getSide(Facing::DOWN)->getId() !== self::CACTUS){
|
if($this->getSide(Facing::DOWN)->getId() !== self::CACTUS){
|
||||||
if($this->meta === 0x0f){
|
if($this->age === 15){
|
||||||
for($y = 1; $y < 3; ++$y){
|
for($y = 1; $y < 3; ++$y){
|
||||||
$b = $this->getLevel()->getBlockAt($this->x, $this->y + $y, $this->z);
|
$b = $this->getLevel()->getBlockAt($this->x, $this->y + $y, $this->z);
|
||||||
if($b->getId() === self::AIR){
|
if($b->getId() === self::AIR){
|
||||||
@ -95,10 +110,10 @@ class Cactus extends Transparent{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$this->meta = 0;
|
$this->age = 0;
|
||||||
$this->getLevel()->setBlock($this, $this);
|
$this->getLevel()->setBlock($this, $this);
|
||||||
}else{
|
}else{
|
||||||
++$this->meta;
|
++$this->age;
|
||||||
$this->getLevel()->setBlock($this, $this);
|
$this->getLevel()->setBlock($this, $this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -118,8 +133,4 @@ class Cactus extends Transparent{
|
|||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getVariantBitmask() : int{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -38,8 +38,23 @@ class Cake extends Transparent implements FoodSource{
|
|||||||
|
|
||||||
protected $itemId = Item::CAKE;
|
protected $itemId = Item::CAKE;
|
||||||
|
|
||||||
public function __construct(int $meta = 0){
|
/** @var int */
|
||||||
$this->setDamage($meta);
|
protected $bites = 0;
|
||||||
|
|
||||||
|
public function __construct(){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function writeStateToMeta() : int{
|
||||||
|
return $this->bites;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function readStateFromMeta(int $meta) : void{
|
||||||
|
$this->bites = $meta;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getStateBitmask() : int{
|
||||||
|
return 0b111;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getHardness() : float{
|
public function getHardness() : float{
|
||||||
@ -51,7 +66,7 @@ class Cake extends Transparent implements FoodSource{
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected function recalculateBoundingBox() : ?AxisAlignedBB{
|
protected function recalculateBoundingBox() : ?AxisAlignedBB{
|
||||||
$f = $this->getDamage() * 0.125; //1 slice width
|
$f = $this->bites * 0.125; //1 slice width
|
||||||
|
|
||||||
return new AxisAlignedBB(
|
return new AxisAlignedBB(
|
||||||
0.0625 + $f,
|
0.0625 + $f,
|
||||||
@ -112,8 +127,8 @@ class Cake extends Transparent implements FoodSource{
|
|||||||
*/
|
*/
|
||||||
public function getResidue(){
|
public function getResidue(){
|
||||||
$clone = clone $this;
|
$clone = clone $this;
|
||||||
$clone->meta++;
|
$clone->bites++;
|
||||||
if($clone->meta > 0x06){
|
if($clone->bites > 6){
|
||||||
$clone = BlockFactory::get(Block::AIR);
|
$clone = BlockFactory::get(Block::AIR);
|
||||||
}
|
}
|
||||||
return $clone;
|
return $clone;
|
||||||
|
@ -23,7 +23,6 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace pocketmine\block;
|
namespace pocketmine\block;
|
||||||
|
|
||||||
use pocketmine\block\utils\ColorBlockMetaHelper;
|
|
||||||
use pocketmine\item\Item;
|
use pocketmine\item\Item;
|
||||||
use pocketmine\math\AxisAlignedBB;
|
use pocketmine\math\AxisAlignedBB;
|
||||||
use pocketmine\math\Facing;
|
use pocketmine\math\Facing;
|
||||||
@ -32,12 +31,6 @@ use pocketmine\Player;
|
|||||||
|
|
||||||
class Carpet extends Flowable{
|
class Carpet extends Flowable{
|
||||||
|
|
||||||
protected $id = self::CARPET;
|
|
||||||
|
|
||||||
public function __construct(int $meta = 0){
|
|
||||||
$this->setDamage($meta);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getHardness() : float{
|
public function getHardness() : float{
|
||||||
return 0.1;
|
return 0.1;
|
||||||
}
|
}
|
||||||
@ -46,10 +39,6 @@ class Carpet extends Flowable{
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getName() : string{
|
|
||||||
return ColorBlockMetaHelper::getColorFromMeta($this->meta) . " Carpet";
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function recalculateBoundingBox() : ?AxisAlignedBB{
|
protected function recalculateBoundingBox() : ?AxisAlignedBB{
|
||||||
return new AxisAlignedBB(0, 0, 0, 1, 0.0625, 1);
|
return new AxisAlignedBB(0, 0, 0, 1, 0.0625, 1);
|
||||||
}
|
}
|
||||||
|
@ -30,17 +30,13 @@ class Carrot extends Crops{
|
|||||||
|
|
||||||
protected $id = self::CARROT_BLOCK;
|
protected $id = self::CARROT_BLOCK;
|
||||||
|
|
||||||
public function __construct(int $meta = 0){
|
|
||||||
$this->setDamage($meta);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getName() : string{
|
public function getName() : string{
|
||||||
return "Carrot Block";
|
return "Carrot Block";
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getDropsForCompatibleTool(Item $item) : array{
|
public function getDropsForCompatibleTool(Item $item) : array{
|
||||||
return [
|
return [
|
||||||
ItemFactory::get(Item::CARROT, 0, $this->meta >= 0x07 ? mt_rand(1, 4) : 1)
|
ItemFactory::get(Item::CARROT, 0, $this->age >= 7 ? mt_rand(1, 4) : 1)
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,8 +36,23 @@ class Chest extends Transparent{
|
|||||||
|
|
||||||
protected $id = self::CHEST;
|
protected $id = self::CHEST;
|
||||||
|
|
||||||
public function __construct(int $meta = 0){
|
/** @var int */
|
||||||
$this->setDamage($meta);
|
protected $facing = Facing::NORTH;
|
||||||
|
|
||||||
|
public function __construct(){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function writeStateToMeta() : int{
|
||||||
|
return $this->facing;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function readStateFromMeta(int $meta) : void{
|
||||||
|
$this->facing = $meta;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getStateBitmask() : int{
|
||||||
|
return 0b111;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getHardness() : float{
|
public function getHardness() : float{
|
||||||
@ -60,7 +75,7 @@ class Chest extends Transparent{
|
|||||||
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
|
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
|
||||||
$chest = null;
|
$chest = null;
|
||||||
if($player !== null){
|
if($player !== null){
|
||||||
$this->meta = Bearing::toFacing(Bearing::opposite($player->getDirection()));
|
$this->facing = Bearing::toFacing(Bearing::opposite($player->getDirection()));
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach([
|
foreach([
|
||||||
@ -68,7 +83,7 @@ class Chest extends Transparent{
|
|||||||
Bearing::toFacing(Bearing::rotate($player->getDirection(), 1))
|
Bearing::toFacing(Bearing::rotate($player->getDirection(), 1))
|
||||||
] as $side){
|
] as $side){
|
||||||
$c = $this->getSide($side);
|
$c = $this->getSide($side);
|
||||||
if($c->getId() === $this->id and $c->getDamage() === $this->meta){
|
if($c instanceof Chest and $c->getId() === $this->getId() and $c->facing === $this->facing){
|
||||||
$tile = $this->getLevel()->getTile($c);
|
$tile = $this->getLevel()->getTile($c);
|
||||||
if($tile instanceof TileChest and !$tile->isPaired()){
|
if($tile instanceof TileChest and !$tile->isPaired()){
|
||||||
$chest = $tile;
|
$chest = $tile;
|
||||||
@ -116,10 +131,6 @@ class Chest extends Transparent{
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getVariantBitmask() : int{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getFuelTime() : int{
|
public function getFuelTime() : int{
|
||||||
return 300;
|
return 300;
|
||||||
}
|
}
|
||||||
|
@ -30,8 +30,8 @@ class Clay extends Solid{
|
|||||||
|
|
||||||
protected $id = self::CLAY_BLOCK;
|
protected $id = self::CLAY_BLOCK;
|
||||||
|
|
||||||
public function __construct(int $meta = 0){
|
public function __construct(){
|
||||||
$this->setDamage($meta);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getHardness() : float{
|
public function getHardness() : float{
|
||||||
|
@ -29,8 +29,8 @@ class Coal extends Solid{
|
|||||||
|
|
||||||
protected $id = self::COAL_BLOCK;
|
protected $id = self::COAL_BLOCK;
|
||||||
|
|
||||||
public function __construct(int $meta = 0){
|
public function __construct(){
|
||||||
$this->setDamage($meta);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getHardness() : float{
|
public function getHardness() : float{
|
||||||
|
@ -31,8 +31,8 @@ class CoalOre extends Solid{
|
|||||||
|
|
||||||
protected $id = self::COAL_ORE;
|
protected $id = self::COAL_ORE;
|
||||||
|
|
||||||
public function __construct(int $meta = 0){
|
public function __construct(){
|
||||||
$this->setDamage($meta);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getHardness() : float{
|
public function getHardness() : float{
|
||||||
|
@ -29,8 +29,8 @@ class Cobblestone extends Solid{
|
|||||||
|
|
||||||
protected $id = self::COBBLESTONE;
|
protected $id = self::COBBLESTONE;
|
||||||
|
|
||||||
public function __construct(int $meta = 0){
|
public function __construct(){
|
||||||
$this->setDamage($meta);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getToolType() : int{
|
public function getToolType() : int{
|
||||||
|
@ -29,8 +29,8 @@ class CobblestoneStairs extends Stair{
|
|||||||
|
|
||||||
protected $id = self::COBBLESTONE_STAIRS;
|
protected $id = self::COBBLESTONE_STAIRS;
|
||||||
|
|
||||||
public function __construct(int $meta = 0){
|
public function __construct(){
|
||||||
$this->setDamage($meta);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getHardness() : float{
|
public function getHardness() : float{
|
||||||
|
@ -31,12 +31,6 @@ class CobblestoneWall extends Transparent{
|
|||||||
public const NONE_MOSSY_WALL = 0;
|
public const NONE_MOSSY_WALL = 0;
|
||||||
public const MOSSY_WALL = 1;
|
public const MOSSY_WALL = 1;
|
||||||
|
|
||||||
protected $id = self::COBBLESTONE_WALL;
|
|
||||||
|
|
||||||
public function __construct(int $meta = 0){
|
|
||||||
$this->setDamage($meta);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getToolType() : int{
|
public function getToolType() : int{
|
||||||
return BlockToolType::TYPE_PICKAXE;
|
return BlockToolType::TYPE_PICKAXE;
|
||||||
}
|
}
|
||||||
@ -49,14 +43,6 @@ class CobblestoneWall extends Transparent{
|
|||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getName() : string{
|
|
||||||
if($this->meta === 0x01){
|
|
||||||
return "Mossy Cobblestone Wall";
|
|
||||||
}
|
|
||||||
|
|
||||||
return "Cobblestone Wall";
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function recalculateBoundingBox() : ?AxisAlignedBB{
|
protected function recalculateBoundingBox() : ?AxisAlignedBB{
|
||||||
//walls don't have any special collision boxes like fences do
|
//walls don't have any special collision boxes like fences do
|
||||||
|
|
||||||
|
@ -31,8 +31,8 @@ class Cobweb extends Flowable{
|
|||||||
|
|
||||||
protected $id = self::COBWEB;
|
protected $id = self::COBWEB;
|
||||||
|
|
||||||
public function __construct(int $meta = 0){
|
public function __construct(){
|
||||||
$this->setDamage($meta);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function hasEntityCollision() : bool{
|
public function hasEntityCollision() : bool{
|
||||||
|
@ -23,12 +23,38 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace pocketmine\block;
|
namespace pocketmine\block;
|
||||||
|
|
||||||
|
use pocketmine\item\Item;
|
||||||
|
use pocketmine\item\ItemFactory;
|
||||||
|
use pocketmine\math\AxisAlignedBB;
|
||||||
|
use pocketmine\math\Bearing;
|
||||||
|
use pocketmine\math\Facing;
|
||||||
|
use pocketmine\math\Vector3;
|
||||||
|
use pocketmine\Player;
|
||||||
|
|
||||||
class CocoaBlock extends Transparent{
|
class CocoaBlock extends Transparent{
|
||||||
|
|
||||||
protected $id = self::COCOA_BLOCK;
|
protected $id = self::COCOA_BLOCK;
|
||||||
|
|
||||||
public function __construct(int $meta = 0){
|
/** @var int */
|
||||||
$this->setDamage($meta);
|
protected $facing = Facing::NORTH;
|
||||||
|
/** @var int */
|
||||||
|
protected $age = 0;
|
||||||
|
|
||||||
|
public function __construct(){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function writeStateToMeta() : int{
|
||||||
|
return Bearing::fromFacing(Facing::opposite($this->facing)) | ($this->age << 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function readStateFromMeta(int $meta) : void{
|
||||||
|
$this->facing = Facing::opposite(Bearing::toFacing($meta & 0x03));
|
||||||
|
$this->age = $meta >> 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getStateBitmask() : int{
|
||||||
|
return 0b1111;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getName() : string{
|
public function getName() : string{
|
||||||
|
@ -23,21 +23,10 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace pocketmine\block;
|
namespace pocketmine\block;
|
||||||
|
|
||||||
use pocketmine\block\utils\ColorBlockMetaHelper;
|
|
||||||
use pocketmine\item\TieredTool;
|
use pocketmine\item\TieredTool;
|
||||||
|
|
||||||
class Concrete extends Solid{
|
class Concrete extends Solid{
|
||||||
|
|
||||||
protected $id = Block::CONCRETE;
|
|
||||||
|
|
||||||
public function __construct(int $meta = 0){
|
|
||||||
$this->setDamage($meta);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getName() : string{
|
|
||||||
return ColorBlockMetaHelper::getColorFromMeta($this->meta) . " Concrete";
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getHardness() : float{
|
public function getHardness() : float{
|
||||||
return 1.8;
|
return 1.8;
|
||||||
}
|
}
|
||||||
|
@ -23,21 +23,10 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace pocketmine\block;
|
namespace pocketmine\block;
|
||||||
|
|
||||||
use pocketmine\block\utils\ColorBlockMetaHelper;
|
|
||||||
use pocketmine\math\Facing;
|
use pocketmine\math\Facing;
|
||||||
|
|
||||||
class ConcretePowder extends Fallable{
|
class ConcretePowder extends Fallable{
|
||||||
|
|
||||||
protected $id = self::CONCRETE_POWDER;
|
|
||||||
|
|
||||||
public function __construct(int $meta = 0){
|
|
||||||
$this->setDamage($meta);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getName() : string{
|
|
||||||
return ColorBlockMetaHelper::getColorFromMeta($this->meta) . " Concrete Powder";
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getHardness() : float{
|
public function getHardness() : float{
|
||||||
return 0.5;
|
return 0.5;
|
||||||
}
|
}
|
||||||
@ -70,7 +59,7 @@ class ConcretePowder extends Fallable{
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if($this->getSide($i) instanceof Water){
|
if($this->getSide($i) instanceof Water){
|
||||||
return BlockFactory::get(Block::CONCRETE, $this->meta);
|
return BlockFactory::get(Block::CONCRETE, $this->variant);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,8 +31,8 @@ class CraftingTable extends Solid{
|
|||||||
|
|
||||||
protected $id = self::CRAFTING_TABLE;
|
protected $id = self::CRAFTING_TABLE;
|
||||||
|
|
||||||
public function __construct(int $meta = 0){
|
public function __construct(){
|
||||||
$this->setDamage($meta);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getHardness() : float{
|
public function getHardness() : float{
|
||||||
|
@ -31,6 +31,24 @@ use pocketmine\Player;
|
|||||||
use pocketmine\Server;
|
use pocketmine\Server;
|
||||||
|
|
||||||
abstract class Crops extends Flowable{
|
abstract class Crops extends Flowable{
|
||||||
|
/** @var int */
|
||||||
|
protected $age = 0;
|
||||||
|
|
||||||
|
public function __construct(){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function writeStateToMeta() : int{
|
||||||
|
return $this->age;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function readStateFromMeta(int $meta) : void{
|
||||||
|
$this->age = $meta;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getStateBitmask() : int{
|
||||||
|
return 0b111;
|
||||||
|
}
|
||||||
|
|
||||||
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
|
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
|
||||||
if($blockReplace->getSide(Facing::DOWN)->getId() === Block::FARMLAND){
|
if($blockReplace->getSide(Facing::DOWN)->getId() === Block::FARMLAND){
|
||||||
@ -44,9 +62,9 @@ abstract class Crops extends Flowable{
|
|||||||
public function onActivate(Item $item, Player $player = null) : bool{
|
public function onActivate(Item $item, Player $player = null) : bool{
|
||||||
if($item->getId() === Item::DYE and $item->getDamage() === 0x0F){ //Bonemeal
|
if($item->getId() === Item::DYE and $item->getDamage() === 0x0F){ //Bonemeal
|
||||||
$block = clone $this;
|
$block = clone $this;
|
||||||
$block->meta += mt_rand(2, 5);
|
$block->age += mt_rand(2, 5);
|
||||||
if($block->meta > 7){
|
if($block->age > 7){
|
||||||
$block->meta = 7;
|
$block->age = 7;
|
||||||
}
|
}
|
||||||
|
|
||||||
Server::getInstance()->getPluginManager()->callEvent($ev = new BlockGrowEvent($this, $block));
|
Server::getInstance()->getPluginManager()->callEvent($ev = new BlockGrowEvent($this, $block));
|
||||||
@ -75,9 +93,9 @@ abstract class Crops extends Flowable{
|
|||||||
|
|
||||||
public function onRandomTick() : void{
|
public function onRandomTick() : void{
|
||||||
if(mt_rand(0, 2) === 1){
|
if(mt_rand(0, 2) === 1){
|
||||||
if($this->meta < 0x07){
|
if($this->age < 7){
|
||||||
$block = clone $this;
|
$block = clone $this;
|
||||||
++$block->meta;
|
++$block->age;
|
||||||
Server::getInstance()->getPluginManager()->callEvent($ev = new BlockGrowEvent($this, $block));
|
Server::getInstance()->getPluginManager()->callEvent($ev = new BlockGrowEvent($this, $block));
|
||||||
|
|
||||||
if(!$ev->isCancelled()){
|
if(!$ev->isCancelled()){
|
||||||
|
@ -32,8 +32,8 @@ class Dandelion extends Flowable{
|
|||||||
|
|
||||||
protected $id = self::DANDELION;
|
protected $id = self::DANDELION;
|
||||||
|
|
||||||
public function __construct(int $meta = 0){
|
public function __construct(){
|
||||||
$this->setDamage($meta);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getName() : string{
|
public function getName() : string{
|
||||||
|
@ -25,10 +25,40 @@ namespace pocketmine\block;
|
|||||||
|
|
||||||
class DaylightSensor extends Transparent{
|
class DaylightSensor extends Transparent{
|
||||||
|
|
||||||
protected $id = self::DAYLIGHT_SENSOR;
|
protected $itemId = self::DAYLIGHT_SENSOR;
|
||||||
|
|
||||||
public function __construct(int $meta = 0){
|
/** @var int */
|
||||||
$this->setDamage($meta);
|
protected $power = 0;
|
||||||
|
|
||||||
|
/** @var bool */
|
||||||
|
protected $inverted = false;
|
||||||
|
|
||||||
|
public function __construct(){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getId() : int{
|
||||||
|
return $this->inverted ? self::DAYLIGHT_SENSOR_INVERTED : self::DAYLIGHT_SENSOR;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function writeStateToMeta() : int{
|
||||||
|
return $this->power;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function readStateFromMeta(int $meta) : void{
|
||||||
|
$this->power = $meta;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getStateBitmask() : int{
|
||||||
|
return 0b1111;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function isInverted() : bool{
|
||||||
|
return $this->inverted;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setInverted(bool $inverted = true) : void{
|
||||||
|
$this->inverted = $inverted;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getName() : string{
|
public function getName() : string{
|
||||||
|
@ -33,8 +33,8 @@ class DeadBush extends Flowable{
|
|||||||
|
|
||||||
protected $id = self::DEAD_BUSH;
|
protected $id = self::DEAD_BUSH;
|
||||||
|
|
||||||
public function __construct(int $meta = 0){
|
public function __construct(){
|
||||||
$this->setDamage($meta);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getName() : string{
|
public function getName() : string{
|
||||||
|
@ -29,8 +29,8 @@ class Diamond extends Solid{
|
|||||||
|
|
||||||
protected $id = self::DIAMOND_BLOCK;
|
protected $id = self::DIAMOND_BLOCK;
|
||||||
|
|
||||||
public function __construct(int $meta = 0){
|
public function __construct(){
|
||||||
$this->setDamage($meta);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getHardness() : float{
|
public function getHardness() : float{
|
||||||
|
@ -31,8 +31,8 @@ class DiamondOre extends Solid{
|
|||||||
|
|
||||||
protected $id = self::DIAMOND_ORE;
|
protected $id = self::DIAMOND_ORE;
|
||||||
|
|
||||||
public function __construct(int $meta = 0){
|
public function __construct(){
|
||||||
$this->setDamage($meta);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getHardness() : float{
|
public function getHardness() : float{
|
||||||
|
@ -28,12 +28,8 @@ use pocketmine\item\Item;
|
|||||||
use pocketmine\Player;
|
use pocketmine\Player;
|
||||||
|
|
||||||
class Dirt extends Solid{
|
class Dirt extends Solid{
|
||||||
|
public const NORMAL = 0;
|
||||||
protected $id = self::DIRT;
|
public const COARSE = 1;
|
||||||
|
|
||||||
public function __construct(int $meta = 0){
|
|
||||||
$this->setDamage($meta);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getHardness() : float{
|
public function getHardness() : float{
|
||||||
return 0.5;
|
return 0.5;
|
||||||
@ -43,17 +39,10 @@ class Dirt extends Solid{
|
|||||||
return BlockToolType::TYPE_SHOVEL;
|
return BlockToolType::TYPE_SHOVEL;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getName() : string{
|
|
||||||
if($this->meta === 1){
|
|
||||||
return "Coarse Dirt";
|
|
||||||
}
|
|
||||||
return "Dirt";
|
|
||||||
}
|
|
||||||
|
|
||||||
public function onActivate(Item $item, Player $player = null) : bool{
|
public function onActivate(Item $item, Player $player = null) : bool{
|
||||||
if($item instanceof Hoe){
|
if($item instanceof Hoe){
|
||||||
$item->applyDamage(1);
|
$item->applyDamage(1);
|
||||||
if($this->meta === 1){
|
if($this->variant === self::COARSE){
|
||||||
$this->getLevel()->setBlock($this, BlockFactory::get(Block::DIRT), true);
|
$this->getLevel()->setBlock($this, BlockFactory::get(Block::DIRT), true);
|
||||||
}else{
|
}else{
|
||||||
$this->getLevel()->setBlock($this, BlockFactory::get(Block::FARMLAND), true);
|
$this->getLevel()->setBlock($this, BlockFactory::get(Block::FARMLAND), true);
|
||||||
|
@ -33,41 +33,72 @@ use pocketmine\Player;
|
|||||||
|
|
||||||
|
|
||||||
abstract class Door extends Transparent{
|
abstract class Door extends Transparent{
|
||||||
|
/** @var int */
|
||||||
|
protected $facing = Facing::NORTH;
|
||||||
|
/** @var bool */
|
||||||
|
protected $top = false;
|
||||||
|
/** @var bool */
|
||||||
|
protected $hingeRight = false;
|
||||||
|
|
||||||
|
/** @var bool */
|
||||||
|
protected $open = false;
|
||||||
|
/** @var bool */
|
||||||
|
protected $powered = false;
|
||||||
|
|
||||||
|
|
||||||
|
protected function writeStateToMeta() : int{
|
||||||
|
if($this->top){
|
||||||
|
return 0x08 | ($this->hingeRight ? 0x01 : 0) | ($this->powered ? 0x02 : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Bearing::rotate(Bearing::fromFacing($this->facing), 1) | ($this->open ? 0x04 : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function readStateFromMeta(int $meta) : void{
|
||||||
|
$this->top = $meta & 0x08;
|
||||||
|
if($this->top){
|
||||||
|
$this->hingeRight = ($meta & 0x01) !== 0;
|
||||||
|
$this->powered = ($meta & 0x02) !== 0;
|
||||||
|
}else{
|
||||||
|
$this->facing = Bearing::toFacing(Bearing::rotate($meta & 0x03, -1));
|
||||||
|
$this->open = ($meta & 0x04) !== 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getStateBitmask() : int{
|
||||||
|
return 0b1111;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copies door properties from the other half of the door, since metadata is split between the two halves.
|
||||||
|
* TODO: the blockstate should be updated directly on creation so these properties can be detected in advance.
|
||||||
|
*/
|
||||||
|
private function updateStateFromOtherHalf() : void{
|
||||||
|
$other = $this->getSide($this->top ? Facing::DOWN : Facing::UP);
|
||||||
|
if($other instanceof Door and $other->getId() === $this->getId()){
|
||||||
|
if($this->top){
|
||||||
|
$this->facing = $other->facing;
|
||||||
|
$this->open = $other->open;
|
||||||
|
}else{
|
||||||
|
$this->hingeRight = $other->hingeRight;
|
||||||
|
$this->powered = $other->powered;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public function isSolid() : bool{
|
public function isSolid() : bool{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function getFullDamage(){
|
|
||||||
$damage = $this->getDamage();
|
|
||||||
$isUp = ($damage & 0x08) > 0;
|
|
||||||
|
|
||||||
if($isUp){
|
|
||||||
$down = $this->getSide(Facing::DOWN)->getDamage();
|
|
||||||
$up = $damage;
|
|
||||||
}else{
|
|
||||||
$down = $damage;
|
|
||||||
$up = $this->getSide(Facing::UP)->getDamage();
|
|
||||||
}
|
|
||||||
|
|
||||||
$isRight = ($up & 0x01) > 0;
|
|
||||||
|
|
||||||
return $down & 0x07 | ($isUp ? 8 : 0) | ($isRight ? 0x10 : 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function recalculateBoundingBox() : ?AxisAlignedBB{
|
protected function recalculateBoundingBox() : ?AxisAlignedBB{
|
||||||
$f = 0.1875;
|
$f = 0.1875;
|
||||||
$damage = $this->getFullDamage();
|
$this->updateStateFromOtherHalf();
|
||||||
|
|
||||||
$bb = new AxisAlignedBB(0, 0, 0, 1, 2, 1);
|
$bb = new AxisAlignedBB(0, 0, 0, 1, 2, 1);
|
||||||
|
|
||||||
$j = $damage & 0x03;
|
if($this->facing === Facing::EAST){
|
||||||
$isOpen = (($damage & 0x04) > 0);
|
if($this->open){
|
||||||
$isRight = (($damage & 0x10) > 0);
|
if(!$this->hingeRight){
|
||||||
|
|
||||||
if($j === 0){
|
|
||||||
if($isOpen){
|
|
||||||
if(!$isRight){
|
|
||||||
$bb->setBounds(0, 0, 0, 1, 1, $f);
|
$bb->setBounds(0, 0, 0, 1, 1, $f);
|
||||||
}else{
|
}else{
|
||||||
$bb->setBounds(0, 0, 1 - $f, 1, 1, 1);
|
$bb->setBounds(0, 0, 1 - $f, 1, 1, 1);
|
||||||
@ -75,9 +106,9 @@ abstract class Door extends Transparent{
|
|||||||
}else{
|
}else{
|
||||||
$bb->setBounds(0, 0, 0, $f, 1, 1);
|
$bb->setBounds(0, 0, 0, $f, 1, 1);
|
||||||
}
|
}
|
||||||
}elseif($j === 1){
|
}elseif($this->facing === Facing::SOUTH){
|
||||||
if($isOpen){
|
if($this->open){
|
||||||
if(!$isRight){
|
if(!$this->hingeRight){
|
||||||
$bb->setBounds(1 - $f, 0, 0, 1, 1, 1);
|
$bb->setBounds(1 - $f, 0, 0, 1, 1, 1);
|
||||||
}else{
|
}else{
|
||||||
$bb->setBounds(0, 0, 0, $f, 1, 1);
|
$bb->setBounds(0, 0, 0, $f, 1, 1);
|
||||||
@ -85,9 +116,9 @@ abstract class Door extends Transparent{
|
|||||||
}else{
|
}else{
|
||||||
$bb->setBounds(0, 0, 0, 1, 1, $f);
|
$bb->setBounds(0, 0, 0, 1, 1, $f);
|
||||||
}
|
}
|
||||||
}elseif($j === 2){
|
}elseif($this->facing === Facing::WEST){
|
||||||
if($isOpen){
|
if($this->open){
|
||||||
if(!$isRight){
|
if(!$this->hingeRight){
|
||||||
$bb->setBounds(0, 0, 1 - $f, 1, 1, 1);
|
$bb->setBounds(0, 0, 1 - $f, 1, 1, 1);
|
||||||
}else{
|
}else{
|
||||||
$bb->setBounds(0, 0, 0, 1, 1, $f);
|
$bb->setBounds(0, 0, 0, 1, 1, $f);
|
||||||
@ -95,9 +126,9 @@ abstract class Door extends Transparent{
|
|||||||
}else{
|
}else{
|
||||||
$bb->setBounds(1 - $f, 0, 0, 1, 1, 1);
|
$bb->setBounds(1 - $f, 0, 0, 1, 1, 1);
|
||||||
}
|
}
|
||||||
}elseif($j === 3){
|
}elseif($this->facing === Facing::NORTH){
|
||||||
if($isOpen){
|
if($this->open){
|
||||||
if(!$isRight){
|
if(!$this->hingeRight){
|
||||||
$bb->setBounds(0, 0, 0, $f, 1, 1);
|
$bb->setBounds(0, 0, 0, $f, 1, 1);
|
||||||
}else{
|
}else{
|
||||||
$bb->setBounds(1 - $f, 0, 0, 1, 1, 1);
|
$bb->setBounds(1 - $f, 0, 0, 1, 1, 1);
|
||||||
@ -127,21 +158,22 @@ abstract class Door extends Transparent{
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//door faces this way when opened (unless it's right, in which case it's the opposite)
|
if($player !== null){
|
||||||
$direction = $player !== null ? Bearing::rotate($player->getDirection(), 1) : Bearing::NORTH;
|
$this->facing = Bearing::toFacing($player->getDirection());
|
||||||
|
|
||||||
$facing = Bearing::toFacing($direction);
|
|
||||||
$next = $this->getSide(Facing::opposite($facing));
|
|
||||||
$next2 = $this->getSide($facing);
|
|
||||||
|
|
||||||
$metaUp = 0x08;
|
|
||||||
if($next->getId() === $this->getId() or (!$next2->isTransparent() and $next->isTransparent())){ //Door hinge
|
|
||||||
$metaUp |= 0x01;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->setDamage($direction);
|
$next = $this->getSide(Facing::rotate($this->facing, Facing::AXIS_Y, false));
|
||||||
|
$next2 = $this->getSide(Facing::rotate($this->facing, Facing::AXIS_Y, true));
|
||||||
|
|
||||||
|
if($next->getId() === $this->getId() or (!$next2->isTransparent() and $next->isTransparent())){ //Door hinge
|
||||||
|
$this->hingeRight = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
$topHalf = clone $this;
|
||||||
|
$topHalf->top = true;
|
||||||
|
|
||||||
parent::place($item, $blockReplace, $blockClicked, $face, $clickVector, $player);
|
parent::place($item, $blockReplace, $blockClicked, $face, $clickVector, $player);
|
||||||
$this->getLevel()->setBlock($blockUp, BlockFactory::get($this->getId(), $metaUp), true); //Top
|
$this->level->setBlock($blockUp, $topHalf, true); //Top
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -149,31 +181,23 @@ abstract class Door extends Transparent{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function onActivate(Item $item, Player $player = null) : bool{
|
public function onActivate(Item $item, Player $player = null) : bool{
|
||||||
if(($this->getDamage() & 0x08) === 0x08){ //Top
|
$this->updateStateFromOtherHalf();
|
||||||
$down = $this->getSide(Facing::DOWN);
|
$this->open = !$this->open;
|
||||||
if($down->getId() === $this->getId()){
|
|
||||||
$meta = $down->getDamage() ^ 0x04;
|
|
||||||
$this->level->setBlock($down, BlockFactory::get($this->getId(), $meta), true);
|
|
||||||
$this->level->addSound(new DoorSound($this));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
$other = $this->getSide($this->top ? Facing::DOWN : Facing::UP);
|
||||||
}else{
|
if($other instanceof Door and $this->getId() === $other->getId()){
|
||||||
$this->meta ^= 0x04;
|
$other->open = $this->open;
|
||||||
$this->level->setBlock($this, $this, true);
|
$this->level->setBlock($other, $other, true, true);
|
||||||
$this->level->addSound(new DoorSound($this));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$this->level->setBlock($this, $this, true, true);
|
||||||
|
$this->level->addSound(new DoorSound($this));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getVariantBitmask() : int{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getDropsForCompatibleTool(Item $item) : array{
|
public function getDropsForCompatibleTool(Item $item) : array{
|
||||||
if(($this->meta & 0x08) === 0){ //bottom half only
|
if(!$this->top){ //bottom half only
|
||||||
return parent::getDropsForCompatibleTool($item);
|
return parent::getDropsForCompatibleTool($item);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -185,18 +209,10 @@ abstract class Door extends Transparent{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function getAffectedBlocks() : array{
|
public function getAffectedBlocks() : array{
|
||||||
if(($this->getDamage() & 0x08) === 0x08){
|
$other = $this->getSide($this->top ? Facing::DOWN : Facing::UP);
|
||||||
$down = $this->getSide(Facing::DOWN);
|
if($other->getId() === $this->getId()){
|
||||||
if($down->getId() === $this->getId()){
|
return [$this, $other];
|
||||||
return [$this, $down];
|
|
||||||
}
|
|
||||||
}else{
|
|
||||||
$up = $this->getSide(Facing::UP);
|
|
||||||
if($up->getId() === $this->getId()){
|
|
||||||
return [$this, $up];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return parent::getAffectedBlocks();
|
return parent::getAffectedBlocks();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -30,35 +30,34 @@ use pocketmine\math\Vector3;
|
|||||||
use pocketmine\Player;
|
use pocketmine\Player;
|
||||||
|
|
||||||
class DoublePlant extends Flowable{
|
class DoublePlant extends Flowable{
|
||||||
public const BITFLAG_TOP = 0x08;
|
private const BITFLAG_TOP = 0x08;
|
||||||
|
|
||||||
protected $id = self::DOUBLE_PLANT;
|
/** @var bool */
|
||||||
|
protected $top = false;
|
||||||
|
|
||||||
public function __construct(int $meta = 0){
|
protected function writeStateToMeta() : int{
|
||||||
$this->setDamage($meta);
|
return ($this->top ? self::BITFLAG_TOP : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function readStateFromMeta(int $meta) : void{
|
||||||
|
$this->top = ($meta & self::BITFLAG_TOP) !== 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getStateBitmask() : int{
|
||||||
|
return 0b1000;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function canBeReplaced() : bool{
|
public function canBeReplaced() : bool{
|
||||||
return $this->meta === 2 or $this->meta === 3; //grass or fern
|
return $this->variant === 2 or $this->variant === 3; //grass or fern
|
||||||
}
|
|
||||||
|
|
||||||
public function getName() : string{
|
|
||||||
static $names = [
|
|
||||||
0 => "Sunflower",
|
|
||||||
1 => "Lilac",
|
|
||||||
2 => "Double Tallgrass",
|
|
||||||
3 => "Large Fern",
|
|
||||||
4 => "Rose Bush",
|
|
||||||
5 => "Peony"
|
|
||||||
];
|
|
||||||
return $names[$this->getVariant()] ?? "";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
|
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
|
||||||
$id = $blockReplace->getSide(Facing::DOWN)->getId();
|
$id = $blockReplace->getSide(Facing::DOWN)->getId();
|
||||||
if(($id === Block::GRASS or $id === Block::DIRT) and $blockReplace->getSide(Facing::UP)->canBeReplaced()){
|
if(($id === Block::GRASS or $id === Block::DIRT) and $blockReplace->getSide(Facing::UP)->canBeReplaced()){
|
||||||
$this->getLevel()->setBlock($blockReplace, $this, false, false);
|
$this->getLevel()->setBlock($blockReplace, $this, false, false);
|
||||||
$this->getLevel()->setBlock($blockReplace->getSide(Facing::UP), BlockFactory::get($this->id, $this->meta | self::BITFLAG_TOP), false, false);
|
$top = clone $this;
|
||||||
|
$top->top = true;
|
||||||
|
$this->getLevel()->setBlock($blockReplace->getSide(Facing::UP), $top, false, false);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -71,39 +70,32 @@ class DoublePlant extends Flowable{
|
|||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
public function isValidHalfPlant() : bool{
|
public function isValidHalfPlant() : bool{
|
||||||
if($this->meta & self::BITFLAG_TOP){
|
$other = $this->getSide($this->top ? Facing::DOWN : Facing::UP);
|
||||||
$other = $this->getSide(Facing::DOWN);
|
|
||||||
}else{
|
|
||||||
$other = $this->getSide(Facing::UP);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
$other instanceof DoublePlant and
|
||||||
$other->getId() === $this->getId() and
|
$other->getId() === $this->getId() and
|
||||||
$other->getVariant() === $this->getVariant() and
|
$other->getVariant() === $this->variant and
|
||||||
($other->getDamage() & self::BITFLAG_TOP) !== ($this->getDamage() & self::BITFLAG_TOP)
|
$other->top !== $this->top
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function onNearbyBlockChange() : void{
|
public function onNearbyBlockChange() : void{
|
||||||
if(!$this->isValidHalfPlant() or (($this->meta & self::BITFLAG_TOP) === 0 and $this->getSide(Facing::DOWN)->isTransparent())){
|
if(!$this->isValidHalfPlant() or (!$this->top and $this->getSide(Facing::DOWN)->isTransparent())){
|
||||||
$this->getLevel()->useBreakOn($this);
|
$this->getLevel()->useBreakOn($this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getVariantBitmask() : int{
|
|
||||||
return 0x07;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getToolType() : int{
|
public function getToolType() : int{
|
||||||
return ($this->meta === 2 or $this->meta === 3) ? BlockToolType::TYPE_SHEARS : BlockToolType::TYPE_NONE;
|
return ($this->variant === 2 or $this->variant === 3) ? BlockToolType::TYPE_SHEARS : BlockToolType::TYPE_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getToolHarvestLevel() : int{
|
public function getToolHarvestLevel() : int{
|
||||||
return ($this->meta === 2 or $this->meta === 3) ? 1 : 0; //only grass or fern require shears
|
return ($this->variant === 2 or $this->variant === 3) ? 1 : 0; //only grass or fern require shears
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getDrops(Item $item) : array{
|
public function getDrops(Item $item) : array{
|
||||||
if($this->meta & self::BITFLAG_TOP){
|
if($this->top){
|
||||||
if($this->isCompatibleWithTool($item)){
|
if($this->isCompatibleWithTool($item)){
|
||||||
return parent::getDrops($item);
|
return parent::getDrops($item);
|
||||||
}
|
}
|
||||||
@ -120,7 +112,7 @@ class DoublePlant extends Flowable{
|
|||||||
|
|
||||||
public function getAffectedBlocks() : array{
|
public function getAffectedBlocks() : array{
|
||||||
if($this->isValidHalfPlant()){
|
if($this->isValidHalfPlant()){
|
||||||
return [$this, $this->getSide(($this->meta & self::BITFLAG_TOP) !== 0 ? Facing::DOWN : Facing::UP)];
|
return [$this, $this->getSide($this->top ? Facing::DOWN : Facing::UP)];
|
||||||
}
|
}
|
||||||
|
|
||||||
return parent::getAffectedBlocks();
|
return parent::getAffectedBlocks();
|
||||||
|
@ -26,21 +26,46 @@ namespace pocketmine\block;
|
|||||||
use pocketmine\item\Item;
|
use pocketmine\item\Item;
|
||||||
use pocketmine\item\ItemFactory;
|
use pocketmine\item\ItemFactory;
|
||||||
|
|
||||||
abstract class DoubleSlab extends Solid{
|
class DoubleSlab extends Solid{
|
||||||
|
/** @var int */
|
||||||
|
protected $singleId;
|
||||||
|
|
||||||
public function __construct(int $meta = 0){
|
public function __construct(int $id, int $singleId, int $variant = 0){
|
||||||
$this->setDamage($meta);
|
parent::__construct($id, $variant);
|
||||||
|
$this->singleId = $singleId;
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract public function getSlabId() : int;
|
protected function getSingle() : Block{
|
||||||
|
return BlockFactory::get($this->singleId, $this->variant);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getHardness() : float{
|
||||||
|
return $this->getSingle()->getHardness();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getToolType() : int{
|
||||||
|
return $this->getSingle()->getToolType();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getToolHarvestLevel() : int{
|
||||||
|
return $this->getSingle()->getToolHarvestLevel();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getFlameEncouragement() : int{
|
||||||
|
return $this->getSingle()->getFlameEncouragement();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getFlammability() : int{
|
||||||
|
return $this->getSingle()->getFlammability();
|
||||||
|
}
|
||||||
|
|
||||||
public function getName() : string{
|
public function getName() : string{
|
||||||
return "Double " . BlockFactory::get($this->getSlabId(), $this->getVariant())->getName();
|
return "Double " . $this->getSingle()->getName();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getDropsForCompatibleTool(Item $item) : array{
|
public function getDropsForCompatibleTool(Item $item) : array{
|
||||||
return [
|
return [
|
||||||
ItemFactory::get($this->getSlabId(), $this->getVariant(), 2)
|
ItemFactory::get($this->singleId, $this->variant, 2)
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,47 +0,0 @@
|
|||||||
<?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\item\TieredTool;
|
|
||||||
|
|
||||||
class DoubleStoneSlab extends DoubleSlab{
|
|
||||||
|
|
||||||
protected $id = self::DOUBLE_STONE_SLAB;
|
|
||||||
|
|
||||||
public function getSlabId() : int{
|
|
||||||
return self::STONE_SLAB;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getHardness() : float{
|
|
||||||
return 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getToolType() : int{
|
|
||||||
return BlockToolType::TYPE_PICKAXE;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getToolHarvestLevel() : int{
|
|
||||||
return TieredTool::TIER_WOODEN;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,33 +0,0 @@
|
|||||||
<?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;
|
|
||||||
|
|
||||||
class DoubleStoneSlab2 extends DoubleStoneSlab{
|
|
||||||
|
|
||||||
protected $id = self::DOUBLE_STONE_SLAB2;
|
|
||||||
|
|
||||||
public function getSlabId() : int{
|
|
||||||
return self::STONE_SLAB2;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,49 +0,0 @@
|
|||||||
<?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;
|
|
||||||
|
|
||||||
class DoubleWoodenSlab extends DoubleSlab{
|
|
||||||
|
|
||||||
protected $id = self::DOUBLE_WOODEN_SLAB;
|
|
||||||
|
|
||||||
public function getSlabId() : int{
|
|
||||||
return self::WOODEN_SLAB;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getHardness() : float{
|
|
||||||
return 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getToolType() : int{
|
|
||||||
return BlockToolType::TYPE_AXE;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getFlameEncouragement() : int{
|
|
||||||
return 5;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getFlammability() : int{
|
|
||||||
return 20;
|
|
||||||
}
|
|
||||||
}
|
|
@ -29,8 +29,8 @@ class Emerald extends Solid{
|
|||||||
|
|
||||||
protected $id = self::EMERALD_BLOCK;
|
protected $id = self::EMERALD_BLOCK;
|
||||||
|
|
||||||
public function __construct(int $meta = 0){
|
public function __construct(){
|
||||||
$this->setDamage($meta);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getHardness() : float{
|
public function getHardness() : float{
|
||||||
|
@ -31,8 +31,8 @@ class EmeraldOre extends Solid{
|
|||||||
|
|
||||||
protected $id = self::EMERALD_ORE;
|
protected $id = self::EMERALD_ORE;
|
||||||
|
|
||||||
public function __construct(int $meta = 0){
|
public function __construct(){
|
||||||
$this->setDamage($meta);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getName() : string{
|
public function getName() : string{
|
||||||
|
@ -35,8 +35,8 @@ class EnchantingTable extends Transparent{
|
|||||||
|
|
||||||
protected $id = self::ENCHANTING_TABLE;
|
protected $id = self::ENCHANTING_TABLE;
|
||||||
|
|
||||||
public function __construct(int $meta = 0){
|
public function __construct(){
|
||||||
$this->setDamage($meta);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
|
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
|
||||||
|
@ -25,13 +25,35 @@ namespace pocketmine\block;
|
|||||||
|
|
||||||
use pocketmine\item\Item;
|
use pocketmine\item\Item;
|
||||||
use pocketmine\math\AxisAlignedBB;
|
use pocketmine\math\AxisAlignedBB;
|
||||||
|
use pocketmine\math\Bearing;
|
||||||
|
use pocketmine\math\Facing;
|
||||||
|
use pocketmine\math\Vector3;
|
||||||
|
use pocketmine\Player;
|
||||||
|
|
||||||
class EndPortalFrame extends Solid{
|
class EndPortalFrame extends Solid{
|
||||||
|
|
||||||
protected $id = self::END_PORTAL_FRAME;
|
protected $id = self::END_PORTAL_FRAME;
|
||||||
|
|
||||||
public function __construct(int $meta = 0){
|
/** @var int */
|
||||||
$this->setDamage($meta);
|
protected $facing = Facing::NORTH;
|
||||||
|
/** @var bool */
|
||||||
|
protected $eye = false;
|
||||||
|
|
||||||
|
public function __construct(){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function writeStateToMeta() : int{
|
||||||
|
return Bearing::fromFacing($this->facing) | ($this->eye ? 0x04 : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function readStateFromMeta(int $meta) : void{
|
||||||
|
$this->facing = Bearing::toFacing($meta & 0x03);
|
||||||
|
$this->eye = ($meta & 0x04) !== 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getStateBitmask() : int{
|
||||||
|
return 0b111;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getLightLevel() : int{
|
public function getLightLevel() : int{
|
||||||
@ -55,14 +77,20 @@ class EndPortalFrame extends Solid{
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected function recalculateBoundingBox() : ?AxisAlignedBB{
|
protected function recalculateBoundingBox() : ?AxisAlignedBB{
|
||||||
|
|
||||||
return new AxisAlignedBB(
|
return new AxisAlignedBB(
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
1,
|
1,
|
||||||
(($this->getDamage() & 0x04) > 0 ? 1 : 0.8125),
|
$this->eye ? 1 : 0.8125,
|
||||||
1
|
1
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
|
||||||
|
if($player !== null){
|
||||||
|
$this->facing = Bearing::toFacing(Bearing::opposite($player->getDirection()));
|
||||||
|
}
|
||||||
|
return parent::place($item, $blockReplace, $blockClicked, $face, $clickVector, $player);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -33,8 +33,30 @@ class EndRod extends Flowable{
|
|||||||
|
|
||||||
protected $id = Block::END_ROD;
|
protected $id = Block::END_ROD;
|
||||||
|
|
||||||
public function __construct(int $meta = 0){
|
/** @var int */
|
||||||
$this->setDamage($meta);
|
protected $facing = Facing::DOWN;
|
||||||
|
|
||||||
|
public function __construct(){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function writeStateToMeta() : int{
|
||||||
|
if(Facing::axis($this->facing) === Facing::AXIS_Y){
|
||||||
|
return $this->facing;
|
||||||
|
}
|
||||||
|
return $this->facing ^ 1; //TODO: in PC this is always the same as facing, just PE is stupid
|
||||||
|
}
|
||||||
|
|
||||||
|
public function readStateFromMeta(int $meta) : void{
|
||||||
|
if($meta === 0 or $meta === 1){
|
||||||
|
$this->facing = $meta;
|
||||||
|
}else{
|
||||||
|
$this->facing = $meta ^ 1; //TODO: see above
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getStateBitmask() : int{
|
||||||
|
return 0b111;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getName() : string{
|
public function getName() : string{
|
||||||
@ -42,13 +64,9 @@ class EndRod extends Flowable{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
|
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
|
||||||
if(Facing::axis($face) === Facing::AXIS_Y){
|
$this->facing = $face;
|
||||||
$this->meta = $face;
|
if($blockClicked instanceof EndRod and $blockClicked->facing === $this->facing){
|
||||||
}else{
|
$this->facing = Facing::opposite($face);
|
||||||
$this->meta = $face ^ 0x01;
|
|
||||||
}
|
|
||||||
if($blockClicked instanceof EndRod and $blockClicked->getDamage() === $this->meta){
|
|
||||||
$this->meta ^= 0x01;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return parent::place($item, $blockReplace, $blockClicked, $face, $clickVector, $player);
|
return parent::place($item, $blockReplace, $blockClicked, $face, $clickVector, $player);
|
||||||
@ -63,7 +81,7 @@ class EndRod extends Flowable{
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected function recalculateBoundingBox() : ?AxisAlignedBB{
|
protected function recalculateBoundingBox() : ?AxisAlignedBB{
|
||||||
$m = $this->meta >> 1; //everything except up/down are inverted, but we can still use this for axis
|
$m = Facing::axis($this->facing);
|
||||||
$width = 0.375;
|
$width = 0.375;
|
||||||
|
|
||||||
switch($m){
|
switch($m){
|
||||||
@ -98,8 +116,4 @@ class EndRod extends Flowable{
|
|||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getVariantBitmask() : int{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -29,8 +29,8 @@ class EndStone extends Solid{
|
|||||||
|
|
||||||
protected $id = self::END_STONE;
|
protected $id = self::END_STONE;
|
||||||
|
|
||||||
public function __construct(int $meta = 0){
|
public function __construct(){
|
||||||
$this->setDamage($meta);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getName() : string{
|
public function getName() : string{
|
||||||
|
@ -29,8 +29,8 @@ class EndStoneBricks extends Solid{
|
|||||||
|
|
||||||
protected $id = self::END_BRICKS;
|
protected $id = self::END_BRICKS;
|
||||||
|
|
||||||
public function __construct(int $meta = 0){
|
public function __construct(){
|
||||||
$this->setDamage($meta);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getName() : string{
|
public function getName() : string{
|
||||||
|
@ -62,8 +62,8 @@ class EnderChest extends Chest{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
|
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
|
||||||
if($player !== null){
|
if($player !== null){ //same as normal chest - TODO: clean up inheritance here
|
||||||
$this->meta = Bearing::toFacing(Bearing::opposite($player->getDirection()));
|
$this->facing = Bearing::toFacing(Bearing::opposite($player->getDirection()));
|
||||||
}
|
}
|
||||||
|
|
||||||
if(Block::place($item, $blockReplace, $blockClicked, $face, $clickVector, $player)){
|
if(Block::place($item, $blockReplace, $blockClicked, $face, $clickVector, $player)){
|
||||||
|
@ -32,8 +32,23 @@ class Farmland extends Transparent{
|
|||||||
|
|
||||||
protected $id = self::FARMLAND;
|
protected $id = self::FARMLAND;
|
||||||
|
|
||||||
public function __construct(int $meta = 0){
|
/** @var int */
|
||||||
$this->setDamage($meta);
|
protected $wetness = 0; //"moisture" blockstate property in PC
|
||||||
|
|
||||||
|
public function __construct(){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function writeStateToMeta() : int{
|
||||||
|
return $this->wetness;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function readStateFromMeta(int $meta) : void{
|
||||||
|
$this->wetness = $meta;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getStateBitmask() : int{
|
||||||
|
return 0b111;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getName() : string{
|
public function getName() : string{
|
||||||
@ -64,14 +79,14 @@ class Farmland extends Transparent{
|
|||||||
|
|
||||||
public function onRandomTick() : void{
|
public function onRandomTick() : void{
|
||||||
if(!$this->canHydrate()){
|
if(!$this->canHydrate()){
|
||||||
if($this->meta > 0){
|
if($this->wetness > 0){
|
||||||
$this->meta--;
|
$this->wetness--;
|
||||||
$this->level->setBlock($this, $this, false, false);
|
$this->level->setBlock($this, $this, false, false);
|
||||||
}else{
|
}else{
|
||||||
$this->level->setBlock($this, BlockFactory::get(Block::DIRT), false, true);
|
$this->level->setBlock($this, BlockFactory::get(Block::DIRT), false, true);
|
||||||
}
|
}
|
||||||
}elseif($this->meta < 7){
|
}elseif($this->wetness < 7){
|
||||||
$this->meta = 7;
|
$this->wetness = 7;
|
||||||
$this->level->setBlock($this, $this, false, false);
|
$this->level->setBlock($this, $this, false, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -28,10 +28,6 @@ use pocketmine\math\Facing;
|
|||||||
|
|
||||||
abstract class Fence extends Transparent{
|
abstract class Fence extends Transparent{
|
||||||
|
|
||||||
public function __construct(int $meta = 0){
|
|
||||||
$this->setDamage($meta);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getThickness() : float{
|
public function getThickness() : float{
|
||||||
return 0.25;
|
return 0.25;
|
||||||
}
|
}
|
||||||
|
@ -26,10 +26,29 @@ namespace pocketmine\block;
|
|||||||
use pocketmine\item\Item;
|
use pocketmine\item\Item;
|
||||||
use pocketmine\level\sound\DoorSound;
|
use pocketmine\level\sound\DoorSound;
|
||||||
use pocketmine\math\AxisAlignedBB;
|
use pocketmine\math\AxisAlignedBB;
|
||||||
|
use pocketmine\math\Bearing;
|
||||||
|
use pocketmine\math\Facing;
|
||||||
use pocketmine\math\Vector3;
|
use pocketmine\math\Vector3;
|
||||||
use pocketmine\Player;
|
use pocketmine\Player;
|
||||||
|
|
||||||
class FenceGate extends Transparent{
|
class FenceGate extends Transparent{
|
||||||
|
/** @var bool */
|
||||||
|
protected $open = false;
|
||||||
|
/** @var int */
|
||||||
|
protected $facing = Facing::NORTH;
|
||||||
|
|
||||||
|
protected function writeStateToMeta() : int{
|
||||||
|
return Bearing::fromFacing($this->facing) | ($this->open ? 0x04 : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function readStateFromMeta(int $meta) : void{
|
||||||
|
$this->facing = Bearing::toFacing($meta & 0x03);
|
||||||
|
$this->open = ($meta & 0x04) !== 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getStateBitmask() : int{
|
||||||
|
return 0b111;
|
||||||
|
}
|
||||||
|
|
||||||
public function getHardness() : float{
|
public function getHardness() : float{
|
||||||
return 2;
|
return 2;
|
||||||
@ -41,12 +60,11 @@ class FenceGate extends Transparent{
|
|||||||
|
|
||||||
|
|
||||||
protected function recalculateBoundingBox() : ?AxisAlignedBB{
|
protected function recalculateBoundingBox() : ?AxisAlignedBB{
|
||||||
if(($this->getDamage() & 0x04) > 0){
|
if($this->open){
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
$i = ($this->getDamage() & 0x03);
|
if(Facing::axis($this->facing) === Facing::AXIS_Z){
|
||||||
if($i === 2 or $i === 0){
|
|
||||||
return new AxisAlignedBB(
|
return new AxisAlignedBB(
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
@ -69,21 +87,19 @@ class FenceGate extends Transparent{
|
|||||||
|
|
||||||
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
|
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
|
||||||
if($player !== null){
|
if($player !== null){
|
||||||
$this->meta = $player->getDirection();
|
$this->facing = Bearing::toFacing($player->getDirection());
|
||||||
}
|
}
|
||||||
|
|
||||||
return parent::place($item, $blockReplace, $blockClicked, $face, $clickVector, $player);
|
return parent::place($item, $blockReplace, $blockClicked, $face, $clickVector, $player);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getVariantBitmask() : int{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function onActivate(Item $item, Player $player = null) : bool{
|
public function onActivate(Item $item, Player $player = null) : bool{
|
||||||
$this->meta = (($this->meta ^ 0x04) & ~0x02);
|
$this->open = !$this->open;
|
||||||
|
if($this->open and $player !== null){
|
||||||
if($player !== null){
|
$playerFacing = Bearing::toFacing($player->getDirection());
|
||||||
$this->meta |= ($player->getDirection() & 0x02); //open towards the player, retaining axis
|
if($playerFacing === Facing::opposite($this->facing)){
|
||||||
|
$this->facing = $playerFacing;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->getLevel()->setBlock($this, $this, true);
|
$this->getLevel()->setBlock($this, $this, true);
|
||||||
|
@ -37,8 +37,23 @@ class Fire extends Flowable{
|
|||||||
|
|
||||||
protected $id = self::FIRE;
|
protected $id = self::FIRE;
|
||||||
|
|
||||||
public function __construct(int $meta = 0){
|
/** @var int */
|
||||||
$this->setDamage($meta);
|
protected $age = 0;
|
||||||
|
|
||||||
|
public function __construct(){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function writeStateToMeta() : int{
|
||||||
|
return $this->age;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function readStateFromMeta(int $meta) : void{
|
||||||
|
$this->age = $meta;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getStateBitmask() : int{
|
||||||
|
return 0b1111;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function hasEntityCollision() : bool{
|
public function hasEntityCollision() : bool{
|
||||||
@ -95,22 +110,22 @@ class Fire extends Flowable{
|
|||||||
$down = $this->getSide(Facing::DOWN);
|
$down = $this->getSide(Facing::DOWN);
|
||||||
|
|
||||||
$result = null;
|
$result = null;
|
||||||
if($this->meta < 15 and mt_rand(0, 2) === 0){
|
if($this->age < 15 and mt_rand(0, 2) === 0){
|
||||||
$this->meta++;
|
$this->age++;
|
||||||
$result = $this;
|
$result = $this;
|
||||||
}
|
}
|
||||||
$canSpread = true;
|
$canSpread = true;
|
||||||
|
|
||||||
if(!$down->burnsForever()){
|
if(!$down->burnsForever()){
|
||||||
//TODO: check rain
|
//TODO: check rain
|
||||||
if($this->meta === 15){
|
if($this->age === 15){
|
||||||
if(!$down->isFlammable() and mt_rand(0, 3) === 3){ //1/4 chance to extinguish
|
if(!$down->isFlammable() and mt_rand(0, 3) === 3){ //1/4 chance to extinguish
|
||||||
$canSpread = false;
|
$canSpread = false;
|
||||||
$result = BlockFactory::get(Block::AIR);
|
$result = BlockFactory::get(Block::AIR);
|
||||||
}
|
}
|
||||||
}elseif(!$this->hasAdjacentFlammableBlocks()){
|
}elseif(!$this->hasAdjacentFlammableBlocks()){
|
||||||
$canSpread = false;
|
$canSpread = false;
|
||||||
if(!$down->isSolid() or $this->meta > 3){ //fire older than 3, or without a solid block below
|
if(!$down->isSolid() or $this->age > 3){
|
||||||
$result = BlockFactory::get(Block::AIR);
|
$result = BlockFactory::get(Block::AIR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -157,8 +172,10 @@ class Fire extends Flowable{
|
|||||||
if(!$ev->isCancelled()){
|
if(!$ev->isCancelled()){
|
||||||
$block->onIncinerate();
|
$block->onIncinerate();
|
||||||
|
|
||||||
if(mt_rand(0, $this->meta + 9) < 5){ //TODO: check rain
|
if(mt_rand(0, $this->age + 9) < 5){ //TODO: check rain
|
||||||
$this->level->setBlock($block, BlockFactory::get(Block::FIRE, min(15, $this->meta + (mt_rand(0, 4) >> 2))));
|
$fire = clone $this;
|
||||||
|
$fire->age = min(15, $fire->age + (mt_rand(0, 4) >> 2));
|
||||||
|
$this->level->setBlock($block, $fire);
|
||||||
}else{
|
}else{
|
||||||
$this->level->setBlock($block, BlockFactory::get(Block::AIR));
|
$this->level->setBlock($block, BlockFactory::get(Block::AIR));
|
||||||
}
|
}
|
||||||
|
@ -39,27 +39,6 @@ class Flower extends Flowable{
|
|||||||
public const TYPE_PINK_TULIP = 7;
|
public const TYPE_PINK_TULIP = 7;
|
||||||
public const TYPE_OXEYE_DAISY = 8;
|
public const TYPE_OXEYE_DAISY = 8;
|
||||||
|
|
||||||
protected $id = self::RED_FLOWER;
|
|
||||||
|
|
||||||
public function __construct(int $meta = 0){
|
|
||||||
$this->setDamage($meta);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getName() : string{
|
|
||||||
static $names = [
|
|
||||||
self::TYPE_POPPY => "Poppy",
|
|
||||||
self::TYPE_BLUE_ORCHID => "Blue Orchid",
|
|
||||||
self::TYPE_ALLIUM => "Allium",
|
|
||||||
self::TYPE_AZURE_BLUET => "Azure Bluet",
|
|
||||||
self::TYPE_RED_TULIP => "Red Tulip",
|
|
||||||
self::TYPE_ORANGE_TULIP => "Orange Tulip",
|
|
||||||
self::TYPE_WHITE_TULIP => "White Tulip",
|
|
||||||
self::TYPE_PINK_TULIP => "Pink Tulip",
|
|
||||||
self::TYPE_OXEYE_DAISY => "Oxeye Daisy"
|
|
||||||
];
|
|
||||||
return $names[$this->meta] ?? "Unknown";
|
|
||||||
}
|
|
||||||
|
|
||||||
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
|
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
|
||||||
$down = $this->getSide(Facing::DOWN);
|
$down = $this->getSide(Facing::DOWN);
|
||||||
if($down->getId() === Block::GRASS or $down->getId() === Block::DIRT or $down->getId() === Block::FARMLAND){
|
if($down->getId() === Block::GRASS or $down->getId() === Block::DIRT or $down->getId() === Block::FARMLAND){
|
||||||
|
@ -33,14 +33,26 @@ use pocketmine\tile\Tile;
|
|||||||
|
|
||||||
class FlowerPot extends Flowable{
|
class FlowerPot extends Flowable{
|
||||||
|
|
||||||
public const STATE_EMPTY = 0;
|
|
||||||
public const STATE_FULL = 1;
|
|
||||||
|
|
||||||
protected $id = self::FLOWER_POT_BLOCK;
|
protected $id = self::FLOWER_POT_BLOCK;
|
||||||
protected $itemId = Item::FLOWER_POT;
|
protected $itemId = Item::FLOWER_POT;
|
||||||
|
|
||||||
public function __construct(int $meta = 0){
|
/** @var bool */
|
||||||
$this->setDamage($meta);
|
protected $occupied = false;
|
||||||
|
|
||||||
|
public function __construct(){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function writeStateToMeta() : int{
|
||||||
|
return $this->occupied ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function readStateFromMeta(int $meta) : void{
|
||||||
|
$this->occupied = $meta !== 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getStateBitmask() : int{
|
||||||
|
return 0b1111; //vanilla uses various values, we only care about 1 and 0 for PE
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getName() : string{
|
public function getName() : string{
|
||||||
@ -80,17 +92,13 @@ class FlowerPot extends Flowable{
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->setDamage(self::STATE_FULL); //specific damage value is unnecessary, it just needs to be non-zero to show an item.
|
$this->occupied = true;
|
||||||
$this->getLevel()->setBlock($this, $this, true, false);
|
$this->getLevel()->setBlock($this, $this, true, false);
|
||||||
$pot->setItem($item->pop());
|
$pot->setItem($item->pop());
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getVariantBitmask() : int{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getDropsForCompatibleTool(Item $item) : array{
|
public function getDropsForCompatibleTool(Item $item) : array{
|
||||||
$items = parent::getDropsForCompatibleTool($item);
|
$items = parent::getDropsForCompatibleTool($item);
|
||||||
|
|
||||||
|
@ -23,16 +23,98 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace pocketmine\block;
|
namespace pocketmine\block;
|
||||||
|
|
||||||
|
use pocketmine\item\Item;
|
||||||
|
use pocketmine\item\TieredTool;
|
||||||
|
use pocketmine\math\Bearing;
|
||||||
|
use pocketmine\math\Facing;
|
||||||
|
use pocketmine\math\Vector3;
|
||||||
|
use pocketmine\Player;
|
||||||
|
use pocketmine\tile\Furnace as TileFurnace;
|
||||||
|
use pocketmine\tile\Tile;
|
||||||
|
|
||||||
class Furnace extends BurningFurnace{
|
class Furnace extends Solid{
|
||||||
|
|
||||||
protected $id = self::FURNACE;
|
protected $itemId = self::FURNACE;
|
||||||
|
|
||||||
|
/** @var int */
|
||||||
|
protected $facing = Facing::NORTH;
|
||||||
|
/** @var bool */
|
||||||
|
protected $lit = false; //this is set based on the blockID
|
||||||
|
|
||||||
|
public function __construct(){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getId() : int{
|
||||||
|
return $this->lit ? Block::BURNING_FURNACE : Block::FURNACE;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function writeStateToMeta() : int{
|
||||||
|
return $this->facing;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function readStateFromMeta(int $meta) : void{
|
||||||
|
$this->facing = $meta;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getStateBitmask() : int{
|
||||||
|
return 0b111;
|
||||||
|
}
|
||||||
|
|
||||||
public function getName() : string{
|
public function getName() : string{
|
||||||
return "Furnace";
|
return "Furnace";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getHardness() : float{
|
||||||
|
return 3.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getToolType() : int{
|
||||||
|
return BlockToolType::TYPE_PICKAXE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getToolHarvestLevel() : int{
|
||||||
|
return TieredTool::TIER_WOODEN;
|
||||||
|
}
|
||||||
|
|
||||||
public function getLightLevel() : int{
|
public function getLightLevel() : int{
|
||||||
return 0;
|
return $this->lit ? 13 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function isLit() : bool{
|
||||||
|
return $this->lit;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setLit(bool $lit = true) : void{
|
||||||
|
$this->lit = $lit;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
|
||||||
|
if($player !== null){
|
||||||
|
$this->facing = Bearing::toFacing(Bearing::opposite($player->getDirection()));
|
||||||
|
}
|
||||||
|
if(parent::place($item, $blockReplace, $blockClicked, $face, $clickVector, $player)){
|
||||||
|
Tile::createTile(Tile::FURNACE, $this->getLevel(), TileFurnace::createNBT($this, $face, $item, $player));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function onActivate(Item $item, Player $player = null) : bool{
|
||||||
|
if($player instanceof Player){
|
||||||
|
$furnace = $this->getLevel()->getTile($this);
|
||||||
|
if(!($furnace instanceof TileFurnace)){
|
||||||
|
$furnace = Tile::createTile(Tile::FURNACE, $this->getLevel(), TileFurnace::createNBT($this));
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!$furnace->canOpenWith($item->getCustomName())){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
$player->addWindow($furnace->getInventory());
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,16 +27,6 @@ use pocketmine\item\Item;
|
|||||||
|
|
||||||
class Glass extends Transparent{
|
class Glass extends Transparent{
|
||||||
|
|
||||||
protected $id = self::GLASS;
|
|
||||||
|
|
||||||
public function __construct(int $meta = 0){
|
|
||||||
$this->setDamage($meta);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getName() : string{
|
|
||||||
return "Glass";
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getHardness() : float{
|
public function getHardness() : float{
|
||||||
return 0.3;
|
return 0.3;
|
||||||
}
|
}
|
||||||
|
@ -27,16 +27,6 @@ use pocketmine\item\Item;
|
|||||||
|
|
||||||
class GlassPane extends Thin{
|
class GlassPane extends Thin{
|
||||||
|
|
||||||
protected $id = self::GLASS_PANE;
|
|
||||||
|
|
||||||
public function __construct(int $meta = 0){
|
|
||||||
$this->setDamage($meta);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getName() : string{
|
|
||||||
return "Glass Pane";
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getHardness() : float{
|
public function getHardness() : float{
|
||||||
return 0.3;
|
return 0.3;
|
||||||
}
|
}
|
||||||
|
@ -27,11 +27,27 @@ namespace pocketmine\block;
|
|||||||
use pocketmine\item\Item;
|
use pocketmine\item\Item;
|
||||||
use pocketmine\item\TieredTool;
|
use pocketmine\item\TieredTool;
|
||||||
use pocketmine\math\Bearing;
|
use pocketmine\math\Bearing;
|
||||||
|
use pocketmine\math\Facing;
|
||||||
use pocketmine\math\Vector3;
|
use pocketmine\math\Vector3;
|
||||||
use pocketmine\Player;
|
use pocketmine\Player;
|
||||||
|
|
||||||
class GlazedTerracotta extends Solid{
|
class GlazedTerracotta extends Solid{
|
||||||
|
|
||||||
|
/** @var int */
|
||||||
|
protected $facing = Facing::NORTH;
|
||||||
|
|
||||||
|
protected function writeStateToMeta() : int{
|
||||||
|
return $this->facing;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function readStateFromMeta(int $meta) : void{
|
||||||
|
$this->facing = $meta;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getStateBitmask() : int{
|
||||||
|
return 0b111;
|
||||||
|
}
|
||||||
|
|
||||||
public function getHardness() : float{
|
public function getHardness() : float{
|
||||||
return 1.4;
|
return 1.4;
|
||||||
}
|
}
|
||||||
@ -46,13 +62,9 @@ class GlazedTerracotta extends Solid{
|
|||||||
|
|
||||||
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
|
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
|
||||||
if($player !== null){
|
if($player !== null){
|
||||||
$this->meta = Bearing::toFacing(Bearing::opposite($player->getDirection()));
|
$this->facing = Bearing::toFacing(Bearing::opposite($player->getDirection()));
|
||||||
}
|
}
|
||||||
|
|
||||||
return parent::place($item, $blockReplace, $blockClicked, $face, $clickVector, $player);
|
return parent::place($item, $blockReplace, $blockClicked, $face, $clickVector, $player);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getVariantBitmask() : int{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -30,8 +30,8 @@ class GlowingObsidian extends Solid{
|
|||||||
|
|
||||||
protected $id = self::GLOWING_OBSIDIAN;
|
protected $id = self::GLOWING_OBSIDIAN;
|
||||||
|
|
||||||
public function __construct(int $meta = 0){
|
public function __construct(){
|
||||||
$this->setDamage($meta);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getName() : string{
|
public function getName() : string{
|
||||||
|
@ -1,58 +0,0 @@
|
|||||||
<?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\item\Item;
|
|
||||||
use pocketmine\Player;
|
|
||||||
|
|
||||||
class GlowingRedstoneOre extends RedstoneOre{
|
|
||||||
|
|
||||||
protected $id = self::GLOWING_REDSTONE_ORE;
|
|
||||||
|
|
||||||
protected $itemId = self::REDSTONE_ORE;
|
|
||||||
|
|
||||||
public function getName() : string{
|
|
||||||
return "Glowing Redstone Ore";
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getLightLevel() : int{
|
|
||||||
return 9;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function onActivate(Item $item, Player $player = null) : bool{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function onNearbyBlockChange() : void{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public function ticksRandomly() : bool{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function onRandomTick() : void{
|
|
||||||
$this->getLevel()->setBlock($this, BlockFactory::get(Block::REDSTONE_ORE, $this->meta), false, false);
|
|
||||||
}
|
|
||||||
}
|
|
@ -30,8 +30,8 @@ class Glowstone extends Transparent{
|
|||||||
|
|
||||||
protected $id = self::GLOWSTONE;
|
protected $id = self::GLOWSTONE;
|
||||||
|
|
||||||
public function __construct(int $meta = 0){
|
public function __construct(){
|
||||||
$this->setDamage($meta);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getName() : string{
|
public function getName() : string{
|
||||||
|
@ -29,8 +29,8 @@ class Gold extends Solid{
|
|||||||
|
|
||||||
protected $id = self::GOLD_BLOCK;
|
protected $id = self::GOLD_BLOCK;
|
||||||
|
|
||||||
public function __construct(int $meta = 0){
|
public function __construct(){
|
||||||
$this->setDamage($meta);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getName() : string{
|
public function getName() : string{
|
||||||
|
@ -29,8 +29,8 @@ class GoldOre extends Solid{
|
|||||||
|
|
||||||
protected $id = self::GOLD_ORE;
|
protected $id = self::GOLD_ORE;
|
||||||
|
|
||||||
public function __construct(int $meta = 0){
|
public function __construct(){
|
||||||
$this->setDamage($meta);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getName() : string{
|
public function getName() : string{
|
||||||
|
@ -37,8 +37,8 @@ class Grass extends Solid{
|
|||||||
|
|
||||||
protected $id = self::GRASS;
|
protected $id = self::GRASS;
|
||||||
|
|
||||||
public function __construct(int $meta = 0){
|
public function __construct(){
|
||||||
$this->setDamage($meta);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getName() : string{
|
public function getName() : string{
|
||||||
|
@ -32,8 +32,8 @@ class GrassPath extends Transparent{
|
|||||||
|
|
||||||
protected $id = self::GRASS_PATH;
|
protected $id = self::GRASS_PATH;
|
||||||
|
|
||||||
public function __construct(int $meta = 0){
|
public function __construct(){
|
||||||
$this->setDamage($meta);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getName() : string{
|
public function getName() : string{
|
||||||
|
@ -30,8 +30,8 @@ class Gravel extends Fallable{
|
|||||||
|
|
||||||
protected $id = self::GRAVEL;
|
protected $id = self::GRAVEL;
|
||||||
|
|
||||||
public function __construct(int $meta = 0){
|
public function __construct(){
|
||||||
$this->setDamage($meta);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getName() : string{
|
public function getName() : string{
|
||||||
|
@ -27,16 +27,6 @@ use pocketmine\item\TieredTool;
|
|||||||
|
|
||||||
class HardenedClay extends Solid{
|
class HardenedClay extends Solid{
|
||||||
|
|
||||||
protected $id = self::HARDENED_CLAY;
|
|
||||||
|
|
||||||
public function __construct(int $meta = 0){
|
|
||||||
$this->setDamage($meta);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getName() : string{
|
|
||||||
return "Hardened Clay";
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getToolType() : int{
|
public function getToolType() : int{
|
||||||
return BlockToolType::TYPE_PICKAXE;
|
return BlockToolType::TYPE_PICKAXE;
|
||||||
}
|
}
|
||||||
|
@ -23,17 +23,19 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace pocketmine\block;
|
namespace pocketmine\block;
|
||||||
|
|
||||||
use pocketmine\block\utils\PillarRotationHelper;
|
use pocketmine\block\utils\PillarRotationTrait;
|
||||||
use pocketmine\item\Item;
|
use pocketmine\item\Item;
|
||||||
|
use pocketmine\math\Facing;
|
||||||
use pocketmine\math\Vector3;
|
use pocketmine\math\Vector3;
|
||||||
use pocketmine\Player;
|
use pocketmine\Player;
|
||||||
|
|
||||||
class HayBale extends Solid{
|
class HayBale extends Solid{
|
||||||
|
use PillarRotationTrait;
|
||||||
|
|
||||||
protected $id = self::HAY_BALE;
|
protected $id = self::HAY_BALE;
|
||||||
|
|
||||||
public function __construct(int $meta = 0){
|
public function __construct(){
|
||||||
$this->setDamage($meta);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getName() : string{
|
public function getName() : string{
|
||||||
@ -45,14 +47,10 @@ class HayBale extends Solid{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
|
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
|
||||||
$this->meta = PillarRotationHelper::getMetaFromFace($this->meta, $face);
|
$this->axis = Facing::axis($face);
|
||||||
return parent::place($item, $blockReplace, $blockClicked, $face, $clickVector, $player);
|
return parent::place($item, $blockReplace, $blockClicked, $face, $clickVector, $player);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getVariantBitmask() : int{
|
|
||||||
return 0x03;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getFlameEncouragement() : int{
|
public function getFlameEncouragement() : int{
|
||||||
return 60;
|
return 60;
|
||||||
}
|
}
|
||||||
|
@ -31,8 +31,8 @@ class Ice extends Transparent{
|
|||||||
|
|
||||||
protected $id = self::ICE;
|
protected $id = self::ICE;
|
||||||
|
|
||||||
public function __construct(int $meta = 0){
|
public function __construct(){
|
||||||
$this->setDamage($meta);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getName() : string{
|
public function getName() : string{
|
||||||
|
@ -29,8 +29,8 @@ class Iron extends Solid{
|
|||||||
|
|
||||||
protected $id = self::IRON_BLOCK;
|
protected $id = self::IRON_BLOCK;
|
||||||
|
|
||||||
public function __construct(int $meta = 0){
|
public function __construct(){
|
||||||
$this->setDamage($meta);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getName() : string{
|
public function getName() : string{
|
||||||
|
@ -29,8 +29,8 @@ class IronBars extends Thin{
|
|||||||
|
|
||||||
protected $id = self::IRON_BARS;
|
protected $id = self::IRON_BARS;
|
||||||
|
|
||||||
public function __construct(int $meta = 0){
|
public function __construct(){
|
||||||
$this->setDamage($meta);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getName() : string{
|
public function getName() : string{
|
||||||
@ -48,8 +48,4 @@ class IronBars extends Thin{
|
|||||||
public function getToolHarvestLevel() : int{
|
public function getToolHarvestLevel() : int{
|
||||||
return TieredTool::TIER_WOODEN;
|
return TieredTool::TIER_WOODEN;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getVariantBitmask() : int{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -32,8 +32,8 @@ class IronDoor extends Door{
|
|||||||
|
|
||||||
protected $itemId = Item::IRON_DOOR;
|
protected $itemId = Item::IRON_DOOR;
|
||||||
|
|
||||||
public function __construct(int $meta = 0){
|
public function __construct(){
|
||||||
$this->setDamage($meta);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getName() : string{
|
public function getName() : string{
|
||||||
|
@ -29,8 +29,8 @@ class IronOre extends Solid{
|
|||||||
|
|
||||||
protected $id = self::IRON_ORE;
|
protected $id = self::IRON_ORE;
|
||||||
|
|
||||||
public function __construct(int $meta = 0){
|
public function __construct(){
|
||||||
$this->setDamage($meta);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getName() : string{
|
public function getName() : string{
|
||||||
|
@ -35,8 +35,23 @@ class ItemFrame extends Flowable{
|
|||||||
|
|
||||||
protected $itemId = Item::ITEM_FRAME;
|
protected $itemId = Item::ITEM_FRAME;
|
||||||
|
|
||||||
public function __construct(int $meta = 0){
|
/** @var int */
|
||||||
$this->setDamage($meta);
|
protected $facing = Facing::NORTH;
|
||||||
|
|
||||||
|
public function __construct(){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function writeStateToMeta() : int{
|
||||||
|
return 5 - $this->facing;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function readStateFromMeta(int $meta) : void{
|
||||||
|
$this->facing = 5 - $meta;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getStateBitmask() : int{
|
||||||
|
return 0b11;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getName() : string{
|
public function getName() : string{
|
||||||
@ -59,7 +74,7 @@ class ItemFrame extends Flowable{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function onNearbyBlockChange() : void{
|
public function onNearbyBlockChange() : void{
|
||||||
if(!$this->getSide(Facing::opposite(5 - $this->meta))->isSolid()){
|
if(!$this->getSide(Facing::opposite($this->facing))->isSolid()){
|
||||||
$this->level->useBreakOn($this);
|
$this->level->useBreakOn($this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -69,7 +84,7 @@ class ItemFrame extends Flowable{
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->meta = 5 - $face;
|
$this->facing = $face;
|
||||||
|
|
||||||
if(parent::place($item, $blockReplace, $blockClicked, $face, $clickVector, $player)){
|
if(parent::place($item, $blockReplace, $blockClicked, $face, $clickVector, $player)){
|
||||||
Tile::createTile(Tile::ITEM_FRAME, $this->getLevel(), TileItemFrame::createNBT($this, $face, $item, $player));
|
Tile::createTile(Tile::ITEM_FRAME, $this->getLevel(), TileItemFrame::createNBT($this, $face, $item, $player));
|
||||||
@ -80,10 +95,6 @@ class ItemFrame extends Flowable{
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getVariantBitmask() : int{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getDropsForCompatibleTool(Item $item) : array{
|
public function getDropsForCompatibleTool(Item $item) : array{
|
||||||
$drops = parent::getDropsForCompatibleTool($item);
|
$drops = parent::getDropsForCompatibleTool($item);
|
||||||
|
|
||||||
|
@ -34,8 +34,23 @@ class Ladder extends Transparent{
|
|||||||
|
|
||||||
protected $id = self::LADDER;
|
protected $id = self::LADDER;
|
||||||
|
|
||||||
public function __construct(int $meta = 0){
|
/** @var int */
|
||||||
$this->setDamage($meta);
|
protected $facing = Facing::NORTH;
|
||||||
|
|
||||||
|
public function __construct(){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function writeStateToMeta() : int{
|
||||||
|
return $this->facing;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function readStateFromMeta(int $meta) : void{
|
||||||
|
$this->facing = $meta;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getStateBitmask() : int{
|
||||||
|
return 0b111;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getName() : string{
|
public function getName() : string{
|
||||||
@ -69,13 +84,13 @@ class Ladder extends Transparent{
|
|||||||
$minX = $minZ = 0;
|
$minX = $minZ = 0;
|
||||||
$maxX = $maxZ = 1;
|
$maxX = $maxZ = 1;
|
||||||
|
|
||||||
if($this->meta === 2){
|
if($this->facing === Facing::NORTH){
|
||||||
$minZ = 1 - $f;
|
$minZ = 1 - $f;
|
||||||
}elseif($this->meta === 3){
|
}elseif($this->facing === Facing::SOUTH){
|
||||||
$maxZ = $f;
|
$maxZ = $f;
|
||||||
}elseif($this->meta === 4){
|
}elseif($this->facing === Facing::WEST){
|
||||||
$minX = 1 - $f;
|
$minX = 1 - $f;
|
||||||
}elseif($this->meta === 5){
|
}elseif($this->facing === Facing::EAST){
|
||||||
$maxX = $f;
|
$maxX = $f;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -92,7 +107,7 @@ class Ladder extends Transparent{
|
|||||||
|
|
||||||
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
|
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
|
||||||
if(!$blockClicked->isTransparent() and Facing::axis($face) !== Facing::AXIS_Y){
|
if(!$blockClicked->isTransparent() and Facing::axis($face) !== Facing::AXIS_Y){
|
||||||
$this->meta = $face;
|
$this->facing = $face;
|
||||||
return parent::place($item, $blockReplace, $blockClicked, $face, $clickVector, $player);
|
return parent::place($item, $blockReplace, $blockClicked, $face, $clickVector, $player);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -100,7 +115,7 @@ class Ladder extends Transparent{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function onNearbyBlockChange() : void{
|
public function onNearbyBlockChange() : void{
|
||||||
if(!$this->getSide($this->meta ^ 0x01)->isSolid()){ //Replace with common break method
|
if(!$this->getSide(Facing::opposite($this->facing))->isSolid()){ //Replace with common break method
|
||||||
$this->level->useBreakOn($this);
|
$this->level->useBreakOn($this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -108,8 +123,4 @@ class Ladder extends Transparent{
|
|||||||
public function getToolType() : int{
|
public function getToolType() : int{
|
||||||
return BlockToolType::TYPE_AXE;
|
return BlockToolType::TYPE_AXE;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getVariantBitmask() : int{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -29,8 +29,8 @@ class Lapis extends Solid{
|
|||||||
|
|
||||||
protected $id = self::LAPIS_BLOCK;
|
protected $id = self::LAPIS_BLOCK;
|
||||||
|
|
||||||
public function __construct(int $meta = 0){
|
public function __construct(){
|
||||||
$this->setDamage($meta);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getName() : string{
|
public function getName() : string{
|
||||||
|
@ -31,8 +31,8 @@ class LapisOre extends Solid{
|
|||||||
|
|
||||||
protected $id = self::LAPIS_ORE;
|
protected $id = self::LAPIS_ORE;
|
||||||
|
|
||||||
public function __construct(int $meta = 0){
|
public function __construct(){
|
||||||
$this->setDamage($meta);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getHardness() : float{
|
public function getHardness() : float{
|
||||||
|
@ -35,8 +35,8 @@ class Lava extends Liquid{
|
|||||||
|
|
||||||
protected $id = self::FLOWING_LAVA;
|
protected $id = self::FLOWING_LAVA;
|
||||||
|
|
||||||
public function __construct(int $meta = 0){
|
public function __construct(){
|
||||||
$this->setDamage($meta);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getLightLevel() : int{
|
public function getLightLevel() : int{
|
||||||
@ -48,11 +48,11 @@ class Lava extends Liquid{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function getStillForm() : Block{
|
public function getStillForm() : Block{
|
||||||
return BlockFactory::get(Block::STILL_LAVA, $this->meta);
|
return BlockFactory::get(Block::STILL_LAVA, $this->getDamage());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getFlowingForm() : Block{
|
public function getFlowingForm() : Block{
|
||||||
return BlockFactory::get(Block::FLOWING_LAVA, $this->meta);
|
return BlockFactory::get(Block::FLOWING_LAVA, $this->getDamage());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getBucketFillSound() : int{
|
public function getBucketFillSound() : int{
|
||||||
@ -85,19 +85,19 @@ class Lava extends Liquid{
|
|||||||
}
|
}
|
||||||
|
|
||||||
if($colliding !== null){
|
if($colliding !== null){
|
||||||
if($this->getDamage() === 0){
|
if($this->decay === 0){
|
||||||
$this->liquidCollide($colliding, BlockFactory::get(Block::OBSIDIAN));
|
$this->liquidCollide($colliding, BlockFactory::get(Block::OBSIDIAN));
|
||||||
}elseif($this->getDamage() <= 4){
|
}elseif($this->decay <= 4){
|
||||||
$this->liquidCollide($colliding, BlockFactory::get(Block::COBBLESTONE));
|
$this->liquidCollide($colliding, BlockFactory::get(Block::COBBLESTONE));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function flowIntoBlock(Block $block, int $newFlowDecay) : void{
|
protected function flowIntoBlock(Block $block, int $newFlowDecay, bool $falling) : void{
|
||||||
if($block instanceof Water){
|
if($block instanceof Water){
|
||||||
$block->liquidCollide($this, BlockFactory::get(Block::STONE));
|
$block->liquidCollide($this, BlockFactory::get(Block::STONE));
|
||||||
}else{
|
}else{
|
||||||
parent::flowIntoBlock($block, $newFlowDecay);
|
parent::flowIntoBlock($block, $newFlowDecay, $falling);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,6 +23,7 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace pocketmine\block;
|
namespace pocketmine\block;
|
||||||
|
|
||||||
|
use pocketmine\block\utils\WoodType;
|
||||||
use pocketmine\event\block\LeavesDecayEvent;
|
use pocketmine\event\block\LeavesDecayEvent;
|
||||||
use pocketmine\item\Item;
|
use pocketmine\item\Item;
|
||||||
use pocketmine\item\ItemFactory;
|
use pocketmine\item\ItemFactory;
|
||||||
@ -32,17 +33,30 @@ use pocketmine\math\Vector3;
|
|||||||
use pocketmine\Player;
|
use pocketmine\Player;
|
||||||
|
|
||||||
class Leaves extends Transparent{
|
class Leaves extends Transparent{
|
||||||
public const OAK = 0;
|
/** @var int */
|
||||||
public const SPRUCE = 1;
|
protected $woodType;
|
||||||
public const BIRCH = 2;
|
|
||||||
public const JUNGLE = 3;
|
|
||||||
public const ACACIA = 0;
|
|
||||||
public const DARK_OAK = 1;
|
|
||||||
|
|
||||||
protected $id = self::LEAVES;
|
/** @var bool */
|
||||||
|
protected $noDecay = false;
|
||||||
|
/** @var bool */
|
||||||
|
protected $checkDecay = false;
|
||||||
|
|
||||||
public function __construct(int $meta = 0){
|
public function __construct(int $id, int $variant, int $woodType, ?string $name = null){
|
||||||
$this->setDamage($meta);
|
parent::__construct($id, $variant, $name);
|
||||||
|
$this->woodType = $woodType;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function writeStateToMeta() : int{
|
||||||
|
return ($this->noDecay ? 0x04 : 0) | ($this->checkDecay ? 0x08 : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function readStateFromMeta(int $meta) : void{
|
||||||
|
$this->noDecay = ($meta & 0x04) !== 0;
|
||||||
|
$this->checkDecay = ($meta & 0x08) !== 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getStateBitmask() : int{
|
||||||
|
return 0b1100;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getHardness() : float{
|
public function getHardness() : float{
|
||||||
@ -53,16 +67,6 @@ class Leaves extends Transparent{
|
|||||||
return BlockToolType::TYPE_SHEARS;
|
return BlockToolType::TYPE_SHEARS;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getName() : string{
|
|
||||||
static $names = [
|
|
||||||
self::OAK => "Oak Leaves",
|
|
||||||
self::SPRUCE => "Spruce Leaves",
|
|
||||||
self::BIRCH => "Birch Leaves",
|
|
||||||
self::JUNGLE => "Jungle Leaves"
|
|
||||||
];
|
|
||||||
return $names[$this->getVariant()];
|
|
||||||
}
|
|
||||||
|
|
||||||
public function diffusesSkyLight() : bool{
|
public function diffusesSkyLight() : bool{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -80,7 +84,7 @@ class Leaves extends Transparent{
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if($pos->getId() === $this->id and $distance <= 4){
|
if($pos->getId() === $this->getId() and $distance <= 4){
|
||||||
foreach(Facing::ALL as $side){
|
foreach(Facing::ALL as $side){
|
||||||
if($this->findLog($pos->getSide($side), $visited, $distance + 1)){
|
if($this->findLog($pos->getSide($side), $visited, $distance + 1)){
|
||||||
return true;
|
return true;
|
||||||
@ -92,8 +96,8 @@ class Leaves extends Transparent{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function onNearbyBlockChange() : void{
|
public function onNearbyBlockChange() : void{
|
||||||
if(($this->meta & 0b00001100) === 0){
|
if(!$this->noDecay and !$this->checkDecay){
|
||||||
$this->meta |= 0x08;
|
$this->checkDecay = true;
|
||||||
$this->getLevel()->setBlock($this, $this, true, false);
|
$this->getLevel()->setBlock($this, $this, true, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -103,9 +107,7 @@ class Leaves extends Transparent{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function onRandomTick() : void{
|
public function onRandomTick() : void{
|
||||||
if(($this->meta & 0b00001100) === 0x08){
|
if(!$this->noDecay and $this->checkDecay){
|
||||||
$this->meta &= 0x03;
|
|
||||||
|
|
||||||
$this->getLevel()->getServer()->getPluginManager()->callEvent($ev = new LeavesDecayEvent($this));
|
$this->getLevel()->getServer()->getPluginManager()->callEvent($ev = new LeavesDecayEvent($this));
|
||||||
|
|
||||||
if($ev->isCancelled() or $this->findLog($this)){
|
if($ev->isCancelled() or $this->findLog($this)){
|
||||||
@ -117,14 +119,10 @@ class Leaves extends Transparent{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
|
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
|
||||||
$this->meta |= 0x04;
|
$this->noDecay = true; //artificial leaves don't decay
|
||||||
return parent::place($item, $blockReplace, $blockClicked, $face, $clickVector, $player);
|
return parent::place($item, $blockReplace, $blockClicked, $face, $clickVector, $player);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getVariantBitmask() : int{
|
|
||||||
return 0x03;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getDrops(Item $item) : array{
|
public function getDrops(Item $item) : array{
|
||||||
if($item->getBlockToolType() & BlockToolType::TYPE_SHEARS){
|
if($item->getBlockToolType() & BlockToolType::TYPE_SHEARS){
|
||||||
return $this->getDropsForCompatibleTool($item);
|
return $this->getDropsForCompatibleTool($item);
|
||||||
@ -132,23 +130,15 @@ class Leaves extends Transparent{
|
|||||||
|
|
||||||
$drops = [];
|
$drops = [];
|
||||||
if(mt_rand(1, 20) === 1){ //Saplings
|
if(mt_rand(1, 20) === 1){ //Saplings
|
||||||
$drops[] = $this->getSaplingItem();
|
$drops[] = ItemFactory::get(Item::SAPLING, $this->woodType);
|
||||||
}
|
}
|
||||||
if($this->canDropApples() and mt_rand(1, 200) === 1){ //Apples
|
if(($this->woodType === WoodType::OAK or $this->woodType === WoodType::DARK_OAK) and mt_rand(1, 200) === 1){ //Apples
|
||||||
$drops[] = ItemFactory::get(Item::APPLE);
|
$drops[] = ItemFactory::get(Item::APPLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $drops;
|
return $drops;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getSaplingItem() : Item{
|
|
||||||
return ItemFactory::get(Item::SAPLING, $this->getVariant());
|
|
||||||
}
|
|
||||||
|
|
||||||
public function canDropApples() : bool{
|
|
||||||
return $this->meta === self::OAK;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getFlameEncouragement() : int{
|
public function getFlameEncouragement() : int{
|
||||||
return 30;
|
return 30;
|
||||||
}
|
}
|
||||||
|
@ -1,48 +0,0 @@
|
|||||||
<?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\item\Item;
|
|
||||||
use pocketmine\item\ItemFactory;
|
|
||||||
|
|
||||||
class Leaves2 extends Leaves{
|
|
||||||
|
|
||||||
protected $id = self::LEAVES2;
|
|
||||||
|
|
||||||
public function getName() : string{
|
|
||||||
static $names = [
|
|
||||||
self::ACACIA => "Acacia Leaves",
|
|
||||||
self::DARK_OAK => "Dark Oak Leaves"
|
|
||||||
];
|
|
||||||
return $names[$this->getVariant()] ?? "Unknown";
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getSaplingItem() : Item{
|
|
||||||
return ItemFactory::get(Item::SAPLING, $this->getVariant() + 4);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function canDropApples() : bool{
|
|
||||||
return $this->meta === self::DARK_OAK;
|
|
||||||
}
|
|
||||||
}
|
|
@ -30,11 +30,52 @@ use pocketmine\math\Vector3;
|
|||||||
use pocketmine\Player;
|
use pocketmine\Player;
|
||||||
|
|
||||||
class Lever extends Flowable{
|
class Lever extends Flowable{
|
||||||
|
protected const BOTTOM = 0;
|
||||||
|
protected const SIDE = 1;
|
||||||
|
protected const TOP = 2;
|
||||||
|
|
||||||
protected $id = self::LEVER;
|
protected $id = self::LEVER;
|
||||||
|
|
||||||
public function __construct(int $meta = 0){
|
/** @var int */
|
||||||
$this->setDamage($meta);
|
protected $position = self::BOTTOM;
|
||||||
|
/** @var int */
|
||||||
|
protected $facing = Facing::NORTH;
|
||||||
|
/** @var bool */
|
||||||
|
protected $powered = false;
|
||||||
|
|
||||||
|
public function __construct(){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function writeStateToMeta() : int{
|
||||||
|
if($this->position === self::BOTTOM){
|
||||||
|
$rotationMeta = Facing::axis($this->facing) === Facing::AXIS_Z ? 7 : 0;
|
||||||
|
}elseif($this->position === self::TOP){
|
||||||
|
$rotationMeta = Facing::axis($this->facing) === Facing::AXIS_Z ? 5 : 6;
|
||||||
|
}else{
|
||||||
|
$rotationMeta = 6 - $this->facing;
|
||||||
|
}
|
||||||
|
return $rotationMeta | ($this->powered ? 0x08 : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function readStateFromMeta(int $meta) : void{
|
||||||
|
$rotationMeta = $meta & 0x07;
|
||||||
|
if($rotationMeta === 5 or $rotationMeta === 6){
|
||||||
|
$this->position = self::TOP;
|
||||||
|
$this->facing = $rotationMeta === 5 ? Facing::SOUTH : Facing::EAST;
|
||||||
|
}elseif($rotationMeta === 7 or $rotationMeta === 0){
|
||||||
|
$this->position = self::BOTTOM;
|
||||||
|
$this->facing = $rotationMeta === 7 ? Facing::SOUTH : Facing::EAST;
|
||||||
|
}else{
|
||||||
|
$this->position = self::SIDE;
|
||||||
|
$this->facing = 6 - $rotationMeta;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->powered = ($meta & 0x08) !== 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getStateBitmask() : int{
|
||||||
|
return 0b1111;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getName() : string{
|
public function getName() : string{
|
||||||
@ -45,49 +86,34 @@ class Lever extends Flowable{
|
|||||||
return 0.5;
|
return 0.5;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getVariantBitmask() : int{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
|
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
|
||||||
if(!$blockClicked->isSolid()){
|
if(!$blockClicked->isSolid()){
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if($face === Facing::DOWN){
|
if(Facing::axis($face) === Facing::AXIS_Y){
|
||||||
$this->meta = 0;
|
if($player !== null){
|
||||||
}else{
|
$this->facing = Bearing::toFacing(Bearing::opposite($player->getDirection()));
|
||||||
$this->meta = 6 - $face;
|
|
||||||
}
|
|
||||||
|
|
||||||
if($player !== null){
|
|
||||||
$bearing = $player->getDirection();
|
|
||||||
if($bearing === Bearing::EAST or $bearing === Bearing::WEST){
|
|
||||||
if($face === Facing::UP){
|
|
||||||
$this->meta = 6;
|
|
||||||
}
|
|
||||||
}else{
|
|
||||||
if($face === Facing::DOWN){
|
|
||||||
$this->meta = 7;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
$this->position = $face === Facing::DOWN ? self::BOTTOM : self::TOP;
|
||||||
|
}else{
|
||||||
|
$this->facing = $face;
|
||||||
|
$this->position = self::SIDE;
|
||||||
}
|
}
|
||||||
|
|
||||||
return parent::place($item, $blockReplace, $blockClicked, $face, $clickVector, $player);
|
return parent::place($item, $blockReplace, $blockClicked, $face, $clickVector, $player);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function onNearbyBlockChange() : void{
|
public function onNearbyBlockChange() : void{
|
||||||
static $faces = [
|
if($this->position === self::BOTTOM){
|
||||||
0 => Facing::UP,
|
$face = Facing::UP;
|
||||||
1 => Facing::WEST,
|
}elseif($this->position === self::TOP){
|
||||||
2 => Facing::EAST,
|
$face = Facing::DOWN;
|
||||||
3 => Facing::NORTH,
|
}else{
|
||||||
4 => Facing::SOUTH,
|
$face = Facing::opposite($this->facing);
|
||||||
5 => Facing::DOWN,
|
}
|
||||||
6 => Facing::DOWN,
|
|
||||||
7 => Facing::UP
|
if(!$this->getSide($face)->isSolid()){
|
||||||
];
|
|
||||||
if(!$this->getSide($faces[$this->meta & 0x07])->isSolid()){
|
|
||||||
$this->level->useBreakOn($this);
|
$this->level->useBreakOn($this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -44,6 +44,24 @@ abstract class Liquid extends Transparent{
|
|||||||
private const CAN_FLOW = 0;
|
private const CAN_FLOW = 0;
|
||||||
private const BLOCKED = -1;
|
private const BLOCKED = -1;
|
||||||
|
|
||||||
|
/** @var bool */
|
||||||
|
protected $falling = false;
|
||||||
|
/** @var int */
|
||||||
|
protected $decay = 0; //PC "level" property
|
||||||
|
|
||||||
|
protected function writeStateToMeta() : int{
|
||||||
|
return $this->decay | ($this->falling ? 0x08 : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function readStateFromMeta(int $meta) : void{
|
||||||
|
$this->decay = $meta & 0x07;
|
||||||
|
$this->falling = ($meta & 0x08) !== 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getStateBitmask() : int{
|
||||||
|
return 0b1111;
|
||||||
|
}
|
||||||
|
|
||||||
public function hasEntityCollision() : bool{
|
public function hasEntityCollision() : bool{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -84,35 +102,20 @@ abstract class Liquid extends Transparent{
|
|||||||
|
|
||||||
abstract public function getBucketEmptySound() : int;
|
abstract public function getBucketEmptySound() : int;
|
||||||
|
|
||||||
public function getFluidHeightPercent(){
|
public function isSource() : bool{
|
||||||
$d = $this->meta;
|
return !$this->falling and $this->decay === 0;
|
||||||
if($d >= 8){
|
|
||||||
$d = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ($d + 1) / 9;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function getFlowDecay(Block $block) : int{
|
public function getFluidHeightPercent(){
|
||||||
if($block->getId() !== $this->getId()){
|
return (($this->falling ? 0 : $this->decay) + 1) / 9;
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $block->getDamage();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function getEffectiveFlowDecay(Block $block) : int{
|
protected function getEffectiveFlowDecay(Block $block) : int{
|
||||||
if($block->getId() !== $this->getId()){
|
if(!($block instanceof Liquid) or $block->getId() !== $this->getId()){
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
$decay = $block->getDamage();
|
return $block->falling ? 0 : $block->decay;
|
||||||
|
|
||||||
if($decay >= 8){
|
|
||||||
$decay = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $decay;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function clearCaches() : void{
|
public function clearCaches() : void{
|
||||||
@ -170,7 +173,7 @@ abstract class Liquid extends Transparent{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if($this->getDamage() >= 8){
|
if($this->falling){
|
||||||
if(
|
if(
|
||||||
!$this->canFlowInto($this->level->getBlockAt($this->x, $this->y, $this->z - 1)) or
|
!$this->canFlowInto($this->level->getBlockAt($this->x, $this->y, $this->z - 1)) or
|
||||||
!$this->canFlowInto($this->level->getBlockAt($this->x, $this->y, $this->z + 1)) or
|
!$this->canFlowInto($this->level->getBlockAt($this->x, $this->y, $this->z + 1)) or
|
||||||
@ -214,10 +217,9 @@ abstract class Liquid extends Transparent{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function onScheduledUpdate() : void{
|
public function onScheduledUpdate() : void{
|
||||||
$decay = $this->getFlowDecay($this);
|
|
||||||
$multiplier = $this->getFlowDecayPerBlock();
|
$multiplier = $this->getFlowDecayPerBlock();
|
||||||
|
|
||||||
if($decay > 0){
|
if(!$this->isSource()){
|
||||||
$smallestFlowDecay = -100;
|
$smallestFlowDecay = -100;
|
||||||
$this->adjacentSources = 0;
|
$this->adjacentSources = 0;
|
||||||
$smallestFlowDecay = $this->getSmallestFlowDecay($this->level->getBlockAt($this->x, $this->y, $this->z - 1), $smallestFlowDecay);
|
$smallestFlowDecay = $this->getSmallestFlowDecay($this->level->getBlockAt($this->x, $this->y, $this->z - 1), $smallestFlowDecay);
|
||||||
@ -226,80 +228,81 @@ abstract class Liquid extends Transparent{
|
|||||||
$smallestFlowDecay = $this->getSmallestFlowDecay($this->level->getBlockAt($this->x + 1, $this->y, $this->z), $smallestFlowDecay);
|
$smallestFlowDecay = $this->getSmallestFlowDecay($this->level->getBlockAt($this->x + 1, $this->y, $this->z), $smallestFlowDecay);
|
||||||
|
|
||||||
$newDecay = $smallestFlowDecay + $multiplier;
|
$newDecay = $smallestFlowDecay + $multiplier;
|
||||||
|
$falling = false;
|
||||||
|
|
||||||
if($newDecay >= 8 or $smallestFlowDecay < 0){
|
if($newDecay >= 8 or $smallestFlowDecay < 0){
|
||||||
$newDecay = -1;
|
$newDecay = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(($topFlowDecay = $this->getFlowDecay($this->level->getBlockAt($this->x, $this->y + 1, $this->z))) >= 0){
|
if($this->getEffectiveFlowDecay($this->level->getBlockAt($this->x, $this->y + 1, $this->z)) >= 0){
|
||||||
$newDecay = $topFlowDecay | 0x08;
|
$falling = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if($this->adjacentSources >= 2 and $this instanceof Water){
|
if($this->adjacentSources >= 2 and $this instanceof Water){
|
||||||
$bottomBlock = $this->level->getBlockAt($this->x, $this->y - 1, $this->z);
|
$bottomBlock = $this->level->getBlockAt($this->x, $this->y - 1, $this->z);
|
||||||
if($bottomBlock->isSolid()){
|
if($bottomBlock->isSolid() or ($bottomBlock instanceof Water and $bottomBlock->isSource())){
|
||||||
$newDecay = 0;
|
|
||||||
}elseif($bottomBlock instanceof Water and $bottomBlock->getDamage() === 0){
|
|
||||||
$newDecay = 0;
|
$newDecay = 0;
|
||||||
|
$falling = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if($newDecay !== $decay){
|
if($newDecay !== $this->decay or $falling !== $this->falling){
|
||||||
$decay = $newDecay;
|
if(!$falling and $newDecay < 0){
|
||||||
if($decay < 0){
|
|
||||||
$this->level->setBlock($this, BlockFactory::get(Block::AIR), true, true);
|
$this->level->setBlock($this, BlockFactory::get(Block::AIR), true, true);
|
||||||
}else{
|
return;
|
||||||
$this->level->setBlock($this, BlockFactory::get($this->id, $decay), true, true);
|
}
|
||||||
$this->level->scheduleDelayedBlockUpdate($this, $this->tickRate());
|
|
||||||
|
$this->falling = $falling;
|
||||||
|
$this->decay = $falling ? 0 : $newDecay;
|
||||||
|
$this->level->setBlock($this, $this, true, true); //local block update will cause an update to be scheduled
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$bottomBlock = $this->level->getBlockAt($this->x, $this->y - 1, $this->z);
|
||||||
|
|
||||||
|
$this->flowIntoBlock($bottomBlock, 0, true);
|
||||||
|
|
||||||
|
if($this->isSource() or !$bottomBlock->canBeFlowedInto()){
|
||||||
|
if($this->falling){
|
||||||
|
$adjacentDecay = 1; //falling liquid behaves like source block
|
||||||
|
}else{
|
||||||
|
$adjacentDecay = $this->decay + $multiplier;
|
||||||
|
}
|
||||||
|
|
||||||
|
if($adjacentDecay < 8){
|
||||||
|
$flags = $this->getOptimalFlowDirections();
|
||||||
|
|
||||||
|
if($flags[0]){
|
||||||
|
$this->flowIntoBlock($this->level->getBlockAt($this->x - 1, $this->y, $this->z), $adjacentDecay, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if($flags[1]){
|
||||||
|
$this->flowIntoBlock($this->level->getBlockAt($this->x + 1, $this->y, $this->z), $adjacentDecay, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if($flags[2]){
|
||||||
|
$this->flowIntoBlock($this->level->getBlockAt($this->x, $this->y, $this->z - 1), $adjacentDecay, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if($flags[3]){
|
||||||
|
$this->flowIntoBlock($this->level->getBlockAt($this->x, $this->y, $this->z + 1), $adjacentDecay, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if($decay >= 0){
|
$this->checkForHarden();
|
||||||
$bottomBlock = $this->level->getBlockAt($this->x, $this->y - 1, $this->z);
|
|
||||||
|
|
||||||
$this->flowIntoBlock($bottomBlock, $decay | 0x08);
|
|
||||||
|
|
||||||
if($decay === 0 or !$bottomBlock->canBeFlowedInto()){
|
|
||||||
if($decay >= 8){
|
|
||||||
$adjacentDecay = 1;
|
|
||||||
}else{
|
|
||||||
$adjacentDecay = $decay + $multiplier;
|
|
||||||
}
|
|
||||||
|
|
||||||
if($adjacentDecay < 8){
|
|
||||||
$flags = $this->getOptimalFlowDirections();
|
|
||||||
|
|
||||||
if($flags[0]){
|
|
||||||
$this->flowIntoBlock($this->level->getBlockAt($this->x - 1, $this->y, $this->z), $adjacentDecay);
|
|
||||||
}
|
|
||||||
|
|
||||||
if($flags[1]){
|
|
||||||
$this->flowIntoBlock($this->level->getBlockAt($this->x + 1, $this->y, $this->z), $adjacentDecay);
|
|
||||||
}
|
|
||||||
|
|
||||||
if($flags[2]){
|
|
||||||
$this->flowIntoBlock($this->level->getBlockAt($this->x, $this->y, $this->z - 1), $adjacentDecay);
|
|
||||||
}
|
|
||||||
|
|
||||||
if($flags[3]){
|
|
||||||
$this->flowIntoBlock($this->level->getBlockAt($this->x, $this->y, $this->z + 1), $adjacentDecay);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->checkForHarden();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function flowIntoBlock(Block $block, int $newFlowDecay) : void{
|
protected function flowIntoBlock(Block $block, int $newFlowDecay, bool $falling) : void{
|
||||||
if($this->canFlowInto($block) and !($block instanceof Liquid)){
|
if($this->canFlowInto($block) and !($block instanceof Liquid)){
|
||||||
if($block->getId() > 0){
|
if($block->getId() > 0){
|
||||||
$this->level->useBreakOn($block);
|
$this->level->useBreakOn($block);
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->level->setBlock($block, BlockFactory::get($this->getId(), $newFlowDecay), true, true);
|
$new = clone $this;
|
||||||
$this->level->scheduleDelayedBlockUpdate($block, $this->tickRate());
|
$new->falling = $falling;
|
||||||
|
$new->decay = $falling ? 0 : $newFlowDecay;
|
||||||
|
$this->level->setBlock($block, $new, true, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -407,13 +410,15 @@ abstract class Liquid extends Transparent{
|
|||||||
}
|
}
|
||||||
|
|
||||||
private function getSmallestFlowDecay(Block $block, int $decay) : int{
|
private function getSmallestFlowDecay(Block $block, int $decay) : int{
|
||||||
$blockDecay = $this->getFlowDecay($block);
|
if(!($block instanceof Liquid) or $block->getId() !== $this->getId()){
|
||||||
|
|
||||||
if($blockDecay < 0){
|
|
||||||
return $decay;
|
return $decay;
|
||||||
}elseif($blockDecay === 0){
|
}
|
||||||
|
|
||||||
|
$blockDecay = $block->decay;
|
||||||
|
|
||||||
|
if($block->isSource()){
|
||||||
++$this->adjacentSources;
|
++$this->adjacentSources;
|
||||||
}elseif($blockDecay >= 8){
|
}elseif($block->falling){
|
||||||
$blockDecay = 0;
|
$blockDecay = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -433,6 +438,6 @@ abstract class Liquid extends Transparent{
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected function canFlowInto(Block $block) : bool{
|
protected function canFlowInto(Block $block) : bool{
|
||||||
return $block->canBeFlowedInto() and !($block instanceof Liquid and $block->meta === 0); //TODO: I think this should only be liquids of the same type
|
return $block->canBeFlowedInto() and !($block instanceof Liquid and $block->isSource()); //TODO: I think this should only be liquids of the same type
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,37 +0,0 @@
|
|||||||
<?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;
|
|
||||||
|
|
||||||
class LitRedstoneLamp extends RedstoneLamp{
|
|
||||||
|
|
||||||
protected $id = self::LIT_REDSTONE_LAMP;
|
|
||||||
|
|
||||||
public function getName() : string{
|
|
||||||
return "Lit Redstone Lamp";
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getLightLevel() : int{
|
|
||||||
return 15;
|
|
||||||
}
|
|
||||||
}
|
|
@ -32,8 +32,8 @@ class Magma extends Solid{
|
|||||||
|
|
||||||
protected $id = Block::MAGMA;
|
protected $id = Block::MAGMA;
|
||||||
|
|
||||||
public function __construct(int $meta = 0){
|
public function __construct(){
|
||||||
$this->setDamage($meta);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getName() : string{
|
public function getName() : string{
|
||||||
|
@ -30,8 +30,8 @@ class Melon extends Transparent{
|
|||||||
|
|
||||||
protected $id = self::MELON_BLOCK;
|
protected $id = self::MELON_BLOCK;
|
||||||
|
|
||||||
public function __construct(int $meta = 0){
|
public function __construct(){
|
||||||
$this->setDamage($meta);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getName() : string{
|
public function getName() : string{
|
||||||
|
@ -37,15 +37,11 @@ class MelonStem extends Crops{
|
|||||||
return "Melon Stem";
|
return "Melon Stem";
|
||||||
}
|
}
|
||||||
|
|
||||||
public function __construct(int $meta = 0){
|
|
||||||
$this->setDamage($meta);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function onRandomTick() : void{
|
public function onRandomTick() : void{
|
||||||
if(mt_rand(0, 2) === 1){
|
if(mt_rand(0, 2) === 1){
|
||||||
if($this->meta < 0x07){
|
if($this->age < 7){
|
||||||
$block = clone $this;
|
$block = clone $this;
|
||||||
++$block->meta;
|
++$block->age;
|
||||||
Server::getInstance()->getPluginManager()->callEvent($ev = new BlockGrowEvent($this, $block));
|
Server::getInstance()->getPluginManager()->callEvent($ev = new BlockGrowEvent($this, $block));
|
||||||
if(!$ev->isCancelled()){
|
if(!$ev->isCancelled()){
|
||||||
$this->getLevel()->setBlock($this, $ev->getNewState(), true);
|
$this->getLevel()->setBlock($this, $ev->getNewState(), true);
|
||||||
|
@ -30,8 +30,8 @@ class MonsterSpawner extends Transparent{
|
|||||||
|
|
||||||
protected $id = self::MONSTER_SPAWNER;
|
protected $id = self::MONSTER_SPAWNER;
|
||||||
|
|
||||||
public function __construct(int $meta = 0){
|
public function __construct(){
|
||||||
$this->setDamage($meta);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getHardness() : float{
|
public function getHardness() : float{
|
||||||
|
@ -33,8 +33,8 @@ class Mycelium extends Solid{
|
|||||||
|
|
||||||
protected $id = self::MYCELIUM;
|
protected $id = self::MYCELIUM;
|
||||||
|
|
||||||
public function __construct(int $meta = 0){
|
public function __construct(){
|
||||||
$this->setDamage($meta);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getName() : string{
|
public function getName() : string{
|
||||||
|
@ -29,6 +29,10 @@ class NetherBrickFence extends Fence{
|
|||||||
|
|
||||||
protected $id = self::NETHER_BRICK_FENCE;
|
protected $id = self::NETHER_BRICK_FENCE;
|
||||||
|
|
||||||
|
public function __construct(){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
public function getHardness() : float{
|
public function getHardness() : float{
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
|
@ -29,8 +29,8 @@ class NetherBrickStairs extends Stair{
|
|||||||
|
|
||||||
protected $id = self::NETHER_BRICK_STAIRS;
|
protected $id = self::NETHER_BRICK_STAIRS;
|
||||||
|
|
||||||
public function __construct(int $meta = 0){
|
public function __construct(){
|
||||||
$this->setDamage($meta);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getName() : string{
|
public function getName() : string{
|
||||||
|
@ -31,8 +31,8 @@ class NetherQuartzOre extends Solid{
|
|||||||
|
|
||||||
protected $id = Block::NETHER_QUARTZ_ORE;
|
protected $id = Block::NETHER_QUARTZ_ORE;
|
||||||
|
|
||||||
public function __construct(int $meta = 0){
|
public function __construct(){
|
||||||
$this->setDamage($meta);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getName() : string{
|
public function getName() : string{
|
||||||
|
@ -28,19 +28,33 @@ use pocketmine\item\ItemFactory;
|
|||||||
use pocketmine\item\TieredTool;
|
use pocketmine\item\TieredTool;
|
||||||
|
|
||||||
class NetherReactor extends Solid{
|
class NetherReactor extends Solid{
|
||||||
|
protected const STATE_INACTIVE = 0;
|
||||||
|
protected const STATE_ACTIVE = 1;
|
||||||
|
protected const STATE_USED = 2;
|
||||||
|
|
||||||
protected $id = Block::NETHER_REACTOR;
|
protected $id = Block::NETHER_REACTOR;
|
||||||
|
|
||||||
public function __construct(int $meta = 0){
|
/** @var int */
|
||||||
$this->setDamage($meta);
|
protected $state = self::STATE_INACTIVE;
|
||||||
|
|
||||||
|
public function __construct(){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function writeStateToMeta() : int{
|
||||||
|
return $this->state;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function readStateFromMeta(int $meta) : void{
|
||||||
|
$this->state = $meta;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getStateBitmask() : int{
|
||||||
|
return 0b11;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getName() : string{
|
public function getName() : string{
|
||||||
static $prefixes = [
|
return "Nether Reactor Core";
|
||||||
"",
|
|
||||||
"Active ",
|
|
||||||
"Used "
|
|
||||||
];
|
|
||||||
return ($prefixes[$this->meta] ?? "") . "Nether Reactor Core";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getToolType() : int{
|
public function getToolType() : int{
|
||||||
|
@ -27,8 +27,8 @@ class NetherWartBlock extends Solid{
|
|||||||
|
|
||||||
protected $id = Block::NETHER_WART_BLOCK;
|
protected $id = Block::NETHER_WART_BLOCK;
|
||||||
|
|
||||||
public function __construct(int $meta = 0){
|
public function __construct(){
|
||||||
$this->setDamage($meta);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getName() : string{
|
public function getName() : string{
|
||||||
|
@ -36,8 +36,23 @@ class NetherWartPlant extends Flowable{
|
|||||||
|
|
||||||
protected $itemId = Item::NETHER_WART;
|
protected $itemId = Item::NETHER_WART;
|
||||||
|
|
||||||
public function __construct(int $meta = 0){
|
/** @var int */
|
||||||
$this->setDamage($meta);
|
protected $age = 0;
|
||||||
|
|
||||||
|
public function __construct(){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function writeStateToMeta() : int{
|
||||||
|
return $this->age;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function readStateFromMeta(int $meta) : void{
|
||||||
|
$this->age = $meta;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getStateBitmask() : int{
|
||||||
|
return 0b11;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getName() : string{
|
public function getName() : string{
|
||||||
@ -64,9 +79,9 @@ class NetherWartPlant extends Flowable{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function onRandomTick() : void{
|
public function onRandomTick() : void{
|
||||||
if($this->meta < 3 and mt_rand(0, 10) === 0){ //Still growing
|
if($this->age < 3 and mt_rand(0, 10) === 0){ //Still growing
|
||||||
$block = clone $this;
|
$block = clone $this;
|
||||||
$block->meta++;
|
$block->age++;
|
||||||
$this->getLevel()->getServer()->getPluginManager()->callEvent($ev = new BlockGrowEvent($this, $block));
|
$this->getLevel()->getServer()->getPluginManager()->callEvent($ev = new BlockGrowEvent($this, $block));
|
||||||
|
|
||||||
if(!$ev->isCancelled()){
|
if(!$ev->isCancelled()){
|
||||||
@ -77,7 +92,7 @@ class NetherWartPlant extends Flowable{
|
|||||||
|
|
||||||
public function getDropsForCompatibleTool(Item $item) : array{
|
public function getDropsForCompatibleTool(Item $item) : array{
|
||||||
return [
|
return [
|
||||||
ItemFactory::get($this->getItemId(), 0, ($this->getDamage() === 3 ? mt_rand(2, 4) : 1))
|
ItemFactory::get($this->getItemId(), 0, ($this->age === 3 ? mt_rand(2, 4) : 1))
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,8 +29,8 @@ class Netherrack extends Solid{
|
|||||||
|
|
||||||
protected $id = self::NETHERRACK;
|
protected $id = self::NETHERRACK;
|
||||||
|
|
||||||
public function __construct(int $meta = 0){
|
public function __construct(){
|
||||||
$this->setDamage($meta);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getName() : string{
|
public function getName() : string{
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user