mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-06-06 03:47:16 +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{
|
||||
$tile = $this->level->getTileAt($packet->x, $packet->y, $packet->z);
|
||||
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);
|
||||
if($this->isSpectator() or $this->level->checkSpawnProtection($this, $tile)){
|
||||
$ev->setCancelled();
|
||||
|
@ -34,8 +34,8 @@ class Air extends Transparent{
|
||||
|
||||
protected $id = self::AIR;
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->setDamage($meta);
|
||||
public function __construct(){
|
||||
|
||||
}
|
||||
|
||||
public function getName() : string{
|
||||
|
@ -28,6 +28,7 @@ use pocketmine\item\Item;
|
||||
use pocketmine\item\TieredTool;
|
||||
use pocketmine\math\AxisAlignedBB;
|
||||
use pocketmine\math\Bearing;
|
||||
use pocketmine\math\Facing;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\Player;
|
||||
|
||||
@ -37,10 +38,19 @@ class Anvil extends Fallable{
|
||||
public const TYPE_SLIGHTLY_DAMAGED = 4;
|
||||
public const TYPE_VERY_DAMAGED = 8;
|
||||
|
||||
protected $id = self::ANVIL;
|
||||
/** @var int */
|
||||
protected $facing = Facing::NORTH;
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->setDamage($meta);
|
||||
protected function writeStateToMeta() : int{
|
||||
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{
|
||||
@ -55,19 +65,6 @@ class Anvil extends Fallable{
|
||||
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{
|
||||
return BlockToolType::TYPE_PICKAXE;
|
||||
}
|
||||
@ -79,7 +76,7 @@ class Anvil extends Fallable{
|
||||
public function recalculateBoundingBox() : ?AxisAlignedBB{
|
||||
$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);
|
||||
}else{
|
||||
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{
|
||||
$direction = $player !== null ? Bearing::rotate($player->getDirection(), 1) : 0;
|
||||
$this->meta = $this->getVariant() | $direction;
|
||||
if($player !== null){
|
||||
$this->facing = Bearing::toFacing(Bearing::rotate($player->getDirection(), 1));
|
||||
}
|
||||
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_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 CONNECTIONS = [
|
||||
@ -76,8 +69,28 @@ abstract class BaseRail extends Flowable{
|
||||
]
|
||||
];
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->setDamage($meta);
|
||||
/** @var int[] */
|
||||
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{
|
||||
@ -121,9 +134,11 @@ abstract class BaseRail extends Flowable{
|
||||
/**
|
||||
* Returns the connection directions of this rail (depending on the current block state)
|
||||
*
|
||||
* @param int $meta
|
||||
*
|
||||
* @return int[]
|
||||
*/
|
||||
abstract protected function getConnectionsForState() : array;
|
||||
abstract protected function getConnectionsFromMeta(int $meta) : array;
|
||||
|
||||
/**
|
||||
* Returns all the directions this rail is already connected in.
|
||||
@ -135,7 +150,7 @@ abstract class BaseRail extends Flowable{
|
||||
$connections = [];
|
||||
|
||||
/** @var int $connection */
|
||||
foreach($this->getConnectionsForState() as $connection){
|
||||
foreach($this->connections as $connection){
|
||||
$other = $this->getSide($connection & ~self::FLAG_ASCEND);
|
||||
$otherConnection = Facing::opposite($connection & ~self::FLAG_ASCEND);
|
||||
|
||||
@ -149,7 +164,7 @@ abstract class BaseRail extends Flowable{
|
||||
|
||||
if(
|
||||
$other instanceof BaseRail and
|
||||
in_array($otherConnection, $other->getConnectionsForState(), true)
|
||||
in_array($otherConnection, $other->connections, true)
|
||||
){
|
||||
$connections[] = $connection;
|
||||
}
|
||||
@ -248,20 +263,20 @@ abstract class BaseRail extends Flowable{
|
||||
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
|
||||
}
|
||||
|
||||
public function onNearbyBlockChange() : void{
|
||||
if($this->getSide(Facing::DOWN)->isTransparent() or (
|
||||
isset(self::ASCENDING_SIDES[$this->meta & 0x07]) and
|
||||
$this->getSide(self::ASCENDING_SIDES[$this->meta & 0x07])->isTransparent()
|
||||
)){
|
||||
$this->getLevel()->useBreakOn($this);
|
||||
if($this->getSide(Facing::DOWN)->isTransparent()){
|
||||
$this->level->useBreakOn($this);
|
||||
}else{
|
||||
foreach($this->connections as $connection){
|
||||
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;
|
||||
|
||||
class Bed extends Transparent{
|
||||
public const BITFLAG_OCCUPIED = 0x04;
|
||||
public const BITFLAG_HEAD = 0x08;
|
||||
private const BITFLAG_OCCUPIED = 0x04;
|
||||
private const BITFLAG_HEAD = 0x08;
|
||||
|
||||
protected $id = self::BED_BLOCK;
|
||||
|
||||
protected $itemId = Item::BED;
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->setDamage($meta);
|
||||
/** @var int */
|
||||
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{
|
||||
@ -61,51 +84,39 @@ class Bed extends Transparent{
|
||||
}
|
||||
|
||||
public function isHeadPart() : bool{
|
||||
return ($this->meta & self::BITFLAG_HEAD) !== 0;
|
||||
return $this->head;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function isOccupied() : bool{
|
||||
return ($this->meta & self::BITFLAG_OCCUPIED) !== 0;
|
||||
return $this->occupied;
|
||||
}
|
||||
|
||||
public function setOccupied(bool $occupied = true){
|
||||
if($occupied){
|
||||
$this->meta |= self::BITFLAG_OCCUPIED;
|
||||
}else{
|
||||
$this->meta &= ~self::BITFLAG_OCCUPIED;
|
||||
}
|
||||
$this->occupied = $occupied;
|
||||
$this->level->setBlock($this, $this, false, false);
|
||||
|
||||
$this->getLevel()->setBlock($this, $this, false, false);
|
||||
|
||||
if(($other = $this->getOtherHalf()) !== null and $other->isOccupied() !== $occupied){
|
||||
$other->setOccupied($occupied);
|
||||
if(($other = $this->getOtherHalf()) !== null){
|
||||
$other->occupied = $occupied;
|
||||
$this->level->setBlock($other, $other, false, false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $meta
|
||||
* @param bool $isHead
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public static function getOtherHalfSide(int $meta, bool $isHead = false) : int{
|
||||
$side = Bearing::toFacing($meta & 0x03);
|
||||
if($isHead){
|
||||
$side = Facing::opposite($side);
|
||||
}
|
||||
|
||||
return $side;
|
||||
private function getOtherHalfSide() : int{
|
||||
return $this->head ? Facing::opposite($this->facing) : $this->facing;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Bed|null
|
||||
*/
|
||||
public function getOtherHalf() : ?Bed{
|
||||
$other = $this->getSide(self::getOtherHalfSide($this->meta, $this->isHeadPart()));
|
||||
if($other instanceof Bed and $other->getId() === $this->getId() and $other->isHeadPart() !== $this->isHeadPart() and (($other->getDamage() & 0x03) === ($this->getDamage() & 0x03))){
|
||||
$other = $this->getSide($this->getOtherHalfSide());
|
||||
if($other instanceof Bed and $other->head !== $this->head and $other->facing === $this->facing){
|
||||
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{
|
||||
$down = $this->getSide(Facing::DOWN);
|
||||
if(!$down->isTransparent()){
|
||||
$this->meta = $player instanceof Player ? $player->getDirection() : 0;
|
||||
$next = $this->getSide(self::getOtherHalfSide($this->meta));
|
||||
$this->facing = $player !== null ? Bearing::toFacing($player->getDirection()) : Facing::NORTH;
|
||||
|
||||
$next = $this->getSide($this->getOtherHalfSide());
|
||||
if($next->canBeReplaced() and !$next->getSide(Facing::DOWN)->isTransparent()){
|
||||
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($next, $face, $item, $player));
|
||||
|
@ -29,8 +29,8 @@ class Bedrock extends Solid{
|
||||
|
||||
protected $id = self::BEDROCK;
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->setDamage($meta);
|
||||
public function __construct(){
|
||||
|
||||
}
|
||||
|
||||
public function getName() : string{
|
||||
|
@ -30,16 +30,12 @@ class Beetroot extends Crops{
|
||||
|
||||
protected $id = self::BEETROOT_BLOCK;
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->setDamage($meta);
|
||||
}
|
||||
|
||||
public function getName() : string{
|
||||
return "Beetroot Block";
|
||||
}
|
||||
|
||||
public function getDropsForCompatibleTool(Item $item) : array{
|
||||
if($this->meta >= 0x07){
|
||||
if($this->age >= 7){
|
||||
return [
|
||||
ItemFactory::get(Item::BEETROOT),
|
||||
ItemFactory::get(Item::BEETROOT_SEEDS, 0, mt_rand(0, 3))
|
||||
|
@ -60,7 +60,7 @@ class Block extends Position implements BlockIds, Metadatable{
|
||||
/** @var int */
|
||||
protected $id;
|
||||
/** @var int */
|
||||
protected $meta = 0;
|
||||
protected $variant = 0;
|
||||
/** @var string|null */
|
||||
protected $fallbackName;
|
||||
/** @var int|null */
|
||||
@ -74,14 +74,18 @@ class Block extends Position implements BlockIds, Metadatable{
|
||||
protected $collisionBoxes = null;
|
||||
|
||||
/**
|
||||
* @param int $id The block type's ID, 0-255
|
||||
* @param int $meta Meta value of the block type
|
||||
* @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 $id The block type's ID, 0-255
|
||||
* @param int $variant Meta value of the block type
|
||||
* @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.
|
||||
*/
|
||||
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->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->itemId = $itemId;
|
||||
}
|
||||
@ -122,30 +126,26 @@ class Block extends Position implements BlockIds, Metadatable{
|
||||
* @return 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
|
||||
*/
|
||||
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.
|
||||
* Returns a bitmask used to extract state bits from block metadata.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getVariantBitmask() : int{
|
||||
return -1;
|
||||
public function getStateBitmask() : int{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -153,10 +153,9 @@ class Block extends Position implements BlockIds, Metadatable{
|
||||
* @return int
|
||||
*/
|
||||
public function getVariant() : int{
|
||||
return $this->meta & $this->getVariantBitmask();
|
||||
return $this->variant;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* AKA: Block->isPlaceable
|
||||
* @return bool
|
||||
|
@ -23,6 +23,8 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\block\utils\Color;
|
||||
use pocketmine\block\utils\WoodType;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\level\Position;
|
||||
|
||||
@ -32,6 +34,8 @@ use pocketmine\level\Position;
|
||||
class BlockFactory{
|
||||
/** @var \SplFixedArray<Block> */
|
||||
private static $fullList = null;
|
||||
/** @var \SplFixedArray|\Closure[] */
|
||||
private static $getInterceptors = null;
|
||||
|
||||
/** @var \SplFixedArray<int> */
|
||||
public static $lightFilter = null;
|
||||
@ -40,6 +44,9 @@ class BlockFactory{
|
||||
/** @var \SplFixedArray<float> */
|
||||
public static $blastResistance = null;
|
||||
|
||||
/** @var \SplFixedArray|int[] */
|
||||
public static $stateMasks = null;
|
||||
|
||||
/** @var int[] */
|
||||
public static $staticRuntimeIdMap = [];
|
||||
|
||||
@ -55,56 +62,138 @@ class BlockFactory{
|
||||
*/
|
||||
public static function init() : void{
|
||||
self::$fullList = new \SplFixedArray(4096);
|
||||
self::$getInterceptors = new \SplFixedArray(4096);
|
||||
|
||||
self::$lightFilter = \SplFixedArray::fromArray(array_fill(0, 256, 1));
|
||||
self::$diffusesSkyLight = \SplFixedArray::fromArray(array_fill(0, 256, false));
|
||||
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 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 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 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 Water());
|
||||
self::registerBlock(new StillWater());
|
||||
self::registerBlock(new Lava());
|
||||
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 GoldOre());
|
||||
self::registerBlock(new IronOre());
|
||||
self::registerBlock(new CoalOre());
|
||||
self::registerBlock(new Wood());
|
||||
self::registerBlock(new Leaves());
|
||||
self::registerBlock(new Sponge());
|
||||
self::registerBlock(new Glass());
|
||||
self::registerBlock(new Glass(Block::GLASS, 0, "Glass"));
|
||||
self::registerBlock(new LapisOre());
|
||||
self::registerBlock(new Lapis());
|
||||
//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 Bed());
|
||||
self::registerBlock(new PoweredRail());
|
||||
self::registerBlock(new DetectorRail());
|
||||
//TODO: STICKY_PISTON
|
||||
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());
|
||||
//TODO: PISTON
|
||||
//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 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 RedMushroom());
|
||||
self::registerBlock(new Gold());
|
||||
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 TNT());
|
||||
self::registerBlock(new Bookshelf());
|
||||
@ -121,8 +210,16 @@ class BlockFactory{
|
||||
self::registerBlock(new CraftingTable());
|
||||
self::registerBlock(new Wheat());
|
||||
self::registerBlock(new Farmland());
|
||||
|
||||
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 WoodenDoor(Block::OAK_DOOR_BLOCK, 0, "Oak Door", Item::OAK_DOOR));
|
||||
self::registerBlock(new Ladder());
|
||||
@ -134,9 +231,23 @@ class BlockFactory{
|
||||
self::registerBlock(new IronDoor());
|
||||
self::registerBlock(new WoodenPressurePlate());
|
||||
self::registerBlock(new RedstoneOre());
|
||||
self::registerBlock(new GlowingRedstoneOre());
|
||||
self::registerBlock(new RedstoneTorchUnlit());
|
||||
self::addGetInterceptor(Block::GLOWING_REDSTONE_ORE, 0, function() : Block{
|
||||
$block = self::get(Block::REDSTONE_ORE);
|
||||
if($block instanceof RedstoneOre){
|
||||
$block->setLit();
|
||||
}
|
||||
return $block;
|
||||
});
|
||||
|
||||
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 SnowLayer());
|
||||
self::registerBlock(new Ice());
|
||||
@ -145,7 +256,7 @@ class BlockFactory{
|
||||
self::registerBlock(new Clay());
|
||||
self::registerBlock(new Sugarcane());
|
||||
//TODO: JUKEBOX
|
||||
self::registerBlock(new WoodenFence());
|
||||
|
||||
self::registerBlock(new Pumpkin());
|
||||
self::registerBlock(new Netherrack());
|
||||
self::registerBlock(new SoulSand());
|
||||
@ -158,11 +269,16 @@ class BlockFactory{
|
||||
//TODO: INVISIBLEBEDROCK
|
||||
self::registerBlock(new Trapdoor());
|
||||
//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 RedMushroomBlock());
|
||||
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 PumpkinStem());
|
||||
self::registerBlock(new MelonStem());
|
||||
@ -184,7 +300,14 @@ class BlockFactory{
|
||||
self::registerBlock(new EndStone());
|
||||
//TODO: DRAGON_EGG
|
||||
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
|
||||
self::registerBlock(new ActivatorRail());
|
||||
self::registerBlock(new CocoaBlock());
|
||||
@ -199,50 +322,76 @@ class BlockFactory{
|
||||
self::registerBlock(new WoodenStairs(Block::JUNGLE_STAIRS, 0, "Jungle Stairs"));
|
||||
//TODO: COMMAND_BLOCK
|
||||
//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 Carrot());
|
||||
self::registerBlock(new Potato());
|
||||
self::registerBlock(new WoodenButton());
|
||||
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 WeightedPressurePlateLight());
|
||||
self::registerBlock(new WeightedPressurePlateHeavy());
|
||||
//TODO: COMPARATOR_BLOCK
|
||||
//TODO: POWERED_COMPARATOR
|
||||
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 NetherQuartzOre());
|
||||
//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 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::DARK_OAK_STAIRS, 0, "Dark Oak Stairs"));
|
||||
//TODO: SLIME
|
||||
|
||||
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 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 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 WallBanner());
|
||||
//TODO: DAYLIGHT_DETECTOR_INVERTED
|
||||
self::registerBlock(new RedSandstone());
|
||||
|
||||
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::BIRCH_FENCE_GATE, 0, "Birch 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 ItemFrame());
|
||||
//TODO: CHORUS_FLOWER
|
||||
self::registerBlock(new Purpur());
|
||||
|
||||
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::RED_GLAZED_TERRACOTTA, 0, "Red 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
|
||||
self::registerBlock(new StainedGlass());
|
||||
|
||||
self::registerBlock(new Podzol());
|
||||
self::registerBlock(new Beetroot());
|
||||
@ -327,20 +472,17 @@ class BlockFactory{
|
||||
*/
|
||||
public static function registerBlock(Block $block, bool $override = false) : void{
|
||||
$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");
|
||||
}
|
||||
|
||||
for($meta = 0; $meta < 16; ++$meta){
|
||||
$variant = clone $block;
|
||||
$variant->setDamage($meta);
|
||||
self::$fullList[($id << 4) | $meta] = $variant;
|
||||
self::$fullList[($id << 4) | $variant] = clone $block;
|
||||
if($variant === 0){
|
||||
//TODO: allow these to differ for different variants
|
||||
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");
|
||||
}
|
||||
|
||||
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{
|
||||
if(self::$fullList[($id << 4) | $meta] !== null){
|
||||
$block = clone self::$fullList[($id << 4) | $meta];
|
||||
}else{
|
||||
$block = new UnknownBlock($id, $meta);
|
||||
if(self::$getInterceptors[$index] !== null){
|
||||
$block = (self::$getInterceptors[$index])();
|
||||
}elseif(self::$fullList[$index] !== null){
|
||||
$block = clone self::$fullList[$index];
|
||||
}
|
||||
}catch(\RuntimeException $e){
|
||||
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){
|
||||
$block->x = $pos->getFloorX();
|
||||
$block->y = $pos->getFloorY();
|
||||
@ -377,22 +537,32 @@ class BlockFactory{
|
||||
return $block;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* @return \SplFixedArray
|
||||
*/
|
||||
public static function getBlockStatesArray() : \SplFixedArray{
|
||||
return self::$fullList;
|
||||
public static function addGetInterceptor(int $id, int $variant, \Closure $interceptor) : void{
|
||||
$block = $interceptor();
|
||||
if(!($block instanceof Block)){
|
||||
throw new \InvalidArgumentException("Interceptor must return an instance of " . Block::class);
|
||||
}
|
||||
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.
|
||||
*
|
||||
* @param int $id
|
||||
* @param int $variant
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function isRegistered(int $id) : bool{
|
||||
$b = self::$fullList[$id << 4];
|
||||
public static function isRegistered(int $id, int $variant = 0) : bool{
|
||||
$b = self::$fullList[($id << 4) | $variant];
|
||||
return $b !== null and !($b instanceof UnknownBlock);
|
||||
}
|
||||
|
||||
|
@ -23,18 +23,20 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\block\utils\PillarRotationHelper;
|
||||
use pocketmine\block\utils\PillarRotationTrait;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\TieredTool;
|
||||
use pocketmine\math\Facing;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\Player;
|
||||
|
||||
class BoneBlock extends Solid{
|
||||
use PillarRotationTrait;
|
||||
|
||||
protected $id = Block::BONE_BLOCK;
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->setDamage($meta);
|
||||
public function __construct(){
|
||||
|
||||
}
|
||||
|
||||
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{
|
||||
$this->meta = PillarRotationHelper::getMetaFromFace($this->meta, $face);
|
||||
$this->axis = Facing::axis($face);
|
||||
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;
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->setDamage($meta);
|
||||
public function __construct(){
|
||||
|
||||
}
|
||||
|
||||
public function getName() : string{
|
||||
|
@ -32,8 +32,29 @@ class BrewingStand extends Transparent{
|
||||
|
||||
protected $itemId = Item::BREWING_STAND;
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->setDamage($meta);
|
||||
/** @var bool */
|
||||
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{
|
||||
@ -52,9 +73,5 @@ class BrewingStand extends Transparent{
|
||||
return TieredTool::TIER_WOODEN;
|
||||
}
|
||||
|
||||
public function getVariantBitmask() : int{
|
||||
return 0;
|
||||
}
|
||||
|
||||
//TODO
|
||||
}
|
||||
|
@ -29,8 +29,8 @@ class BrickStairs extends Stair{
|
||||
|
||||
protected $id = self::BRICK_STAIRS;
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->setDamage($meta);
|
||||
public function __construct(){
|
||||
|
||||
}
|
||||
|
||||
public function getHardness() : float{
|
||||
|
@ -29,8 +29,8 @@ class Bricks extends Solid{
|
||||
|
||||
protected $id = self::BRICK_BLOCK;
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->setDamage($meta);
|
||||
public function __construct(){
|
||||
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\math\Facing;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\Player;
|
||||
|
||||
abstract class Button extends Flowable{
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->setDamage($meta);
|
||||
/** @var int */
|
||||
protected $facing = Facing::DOWN;
|
||||
/** @var bool */
|
||||
protected $powered = false;
|
||||
|
||||
public function __construct(){
|
||||
|
||||
}
|
||||
|
||||
public function getVariantBitmask() : int{
|
||||
return 0;
|
||||
protected function writeStateToMeta() : int{
|
||||
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{
|
||||
//TODO: check valid target block
|
||||
$this->meta = $face;
|
||||
$this->facing = $face;
|
||||
return parent::place($item, $blockReplace, $blockClicked, $face, $clickVector, $player);
|
||||
}
|
||||
|
||||
|
@ -38,8 +38,23 @@ class Cactus extends Transparent{
|
||||
|
||||
protected $id = self::CACTUS;
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->setDamage($meta);
|
||||
/** @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 0b1111;
|
||||
}
|
||||
|
||||
public function getHardness() : float{
|
||||
@ -85,7 +100,7 @@ class Cactus extends Transparent{
|
||||
|
||||
public function onRandomTick() : void{
|
||||
if($this->getSide(Facing::DOWN)->getId() !== self::CACTUS){
|
||||
if($this->meta === 0x0f){
|
||||
if($this->age === 15){
|
||||
for($y = 1; $y < 3; ++$y){
|
||||
$b = $this->getLevel()->getBlockAt($this->x, $this->y + $y, $this->z);
|
||||
if($b->getId() === self::AIR){
|
||||
@ -95,10 +110,10 @@ class Cactus extends Transparent{
|
||||
}
|
||||
}
|
||||
}
|
||||
$this->meta = 0;
|
||||
$this->age = 0;
|
||||
$this->getLevel()->setBlock($this, $this);
|
||||
}else{
|
||||
++$this->meta;
|
||||
++$this->age;
|
||||
$this->getLevel()->setBlock($this, $this);
|
||||
}
|
||||
}
|
||||
@ -118,8 +133,4 @@ class Cactus extends Transparent{
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function getVariantBitmask() : int{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
@ -38,8 +38,23 @@ class Cake extends Transparent implements FoodSource{
|
||||
|
||||
protected $itemId = Item::CAKE;
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->setDamage($meta);
|
||||
/** @var int */
|
||||
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{
|
||||
@ -51,7 +66,7 @@ class Cake extends Transparent implements FoodSource{
|
||||
}
|
||||
|
||||
protected function recalculateBoundingBox() : ?AxisAlignedBB{
|
||||
$f = $this->getDamage() * 0.125; //1 slice width
|
||||
$f = $this->bites * 0.125; //1 slice width
|
||||
|
||||
return new AxisAlignedBB(
|
||||
0.0625 + $f,
|
||||
@ -112,8 +127,8 @@ class Cake extends Transparent implements FoodSource{
|
||||
*/
|
||||
public function getResidue(){
|
||||
$clone = clone $this;
|
||||
$clone->meta++;
|
||||
if($clone->meta > 0x06){
|
||||
$clone->bites++;
|
||||
if($clone->bites > 6){
|
||||
$clone = BlockFactory::get(Block::AIR);
|
||||
}
|
||||
return $clone;
|
||||
|
@ -23,7 +23,6 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\block\utils\ColorBlockMetaHelper;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\math\AxisAlignedBB;
|
||||
use pocketmine\math\Facing;
|
||||
@ -32,12 +31,6 @@ use pocketmine\Player;
|
||||
|
||||
class Carpet extends Flowable{
|
||||
|
||||
protected $id = self::CARPET;
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->setDamage($meta);
|
||||
}
|
||||
|
||||
public function getHardness() : float{
|
||||
return 0.1;
|
||||
}
|
||||
@ -46,10 +39,6 @@ class Carpet extends Flowable{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getName() : string{
|
||||
return ColorBlockMetaHelper::getColorFromMeta($this->meta) . " Carpet";
|
||||
}
|
||||
|
||||
protected function recalculateBoundingBox() : ?AxisAlignedBB{
|
||||
return new AxisAlignedBB(0, 0, 0, 1, 0.0625, 1);
|
||||
}
|
||||
|
@ -30,17 +30,13 @@ class Carrot extends Crops{
|
||||
|
||||
protected $id = self::CARROT_BLOCK;
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->setDamage($meta);
|
||||
}
|
||||
|
||||
public function getName() : string{
|
||||
return "Carrot Block";
|
||||
}
|
||||
|
||||
public function getDropsForCompatibleTool(Item $item) : array{
|
||||
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;
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->setDamage($meta);
|
||||
/** @var int */
|
||||
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{
|
||||
@ -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{
|
||||
$chest = null;
|
||||
if($player !== null){
|
||||
$this->meta = Bearing::toFacing(Bearing::opposite($player->getDirection()));
|
||||
$this->facing = Bearing::toFacing(Bearing::opposite($player->getDirection()));
|
||||
}
|
||||
|
||||
foreach([
|
||||
@ -68,7 +83,7 @@ class Chest extends Transparent{
|
||||
Bearing::toFacing(Bearing::rotate($player->getDirection(), 1))
|
||||
] as $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);
|
||||
if($tile instanceof TileChest and !$tile->isPaired()){
|
||||
$chest = $tile;
|
||||
@ -116,10 +131,6 @@ class Chest extends Transparent{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getVariantBitmask() : int{
|
||||
return 0;
|
||||
}
|
||||
|
||||
public function getFuelTime() : int{
|
||||
return 300;
|
||||
}
|
||||
|
@ -30,8 +30,8 @@ class Clay extends Solid{
|
||||
|
||||
protected $id = self::CLAY_BLOCK;
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->setDamage($meta);
|
||||
public function __construct(){
|
||||
|
||||
}
|
||||
|
||||
public function getHardness() : float{
|
||||
|
@ -29,8 +29,8 @@ class Coal extends Solid{
|
||||
|
||||
protected $id = self::COAL_BLOCK;
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->setDamage($meta);
|
||||
public function __construct(){
|
||||
|
||||
}
|
||||
|
||||
public function getHardness() : float{
|
||||
|
@ -31,8 +31,8 @@ class CoalOre extends Solid{
|
||||
|
||||
protected $id = self::COAL_ORE;
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->setDamage($meta);
|
||||
public function __construct(){
|
||||
|
||||
}
|
||||
|
||||
public function getHardness() : float{
|
||||
|
@ -29,8 +29,8 @@ class Cobblestone extends Solid{
|
||||
|
||||
protected $id = self::COBBLESTONE;
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->setDamage($meta);
|
||||
public function __construct(){
|
||||
|
||||
}
|
||||
|
||||
public function getToolType() : int{
|
||||
|
@ -29,8 +29,8 @@ class CobblestoneStairs extends Stair{
|
||||
|
||||
protected $id = self::COBBLESTONE_STAIRS;
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->setDamage($meta);
|
||||
public function __construct(){
|
||||
|
||||
}
|
||||
|
||||
public function getHardness() : float{
|
||||
|
@ -31,12 +31,6 @@ class CobblestoneWall extends Transparent{
|
||||
public const NONE_MOSSY_WALL = 0;
|
||||
public const MOSSY_WALL = 1;
|
||||
|
||||
protected $id = self::COBBLESTONE_WALL;
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->setDamage($meta);
|
||||
}
|
||||
|
||||
public function getToolType() : int{
|
||||
return BlockToolType::TYPE_PICKAXE;
|
||||
}
|
||||
@ -49,14 +43,6 @@ class CobblestoneWall extends Transparent{
|
||||
return 2;
|
||||
}
|
||||
|
||||
public function getName() : string{
|
||||
if($this->meta === 0x01){
|
||||
return "Mossy Cobblestone Wall";
|
||||
}
|
||||
|
||||
return "Cobblestone Wall";
|
||||
}
|
||||
|
||||
protected function recalculateBoundingBox() : ?AxisAlignedBB{
|
||||
//walls don't have any special collision boxes like fences do
|
||||
|
||||
|
@ -31,8 +31,8 @@ class Cobweb extends Flowable{
|
||||
|
||||
protected $id = self::COBWEB;
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->setDamage($meta);
|
||||
public function __construct(){
|
||||
|
||||
}
|
||||
|
||||
public function hasEntityCollision() : bool{
|
||||
|
@ -23,12 +23,38 @@ declare(strict_types=1);
|
||||
|
||||
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{
|
||||
|
||||
protected $id = self::COCOA_BLOCK;
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->setDamage($meta);
|
||||
/** @var int */
|
||||
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{
|
||||
|
@ -23,21 +23,10 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\block\utils\ColorBlockMetaHelper;
|
||||
use pocketmine\item\TieredTool;
|
||||
|
||||
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{
|
||||
return 1.8;
|
||||
}
|
||||
|
@ -23,21 +23,10 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\block\utils\ColorBlockMetaHelper;
|
||||
use pocketmine\math\Facing;
|
||||
|
||||
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{
|
||||
return 0.5;
|
||||
}
|
||||
@ -70,7 +59,7 @@ class ConcretePowder extends Fallable{
|
||||
continue;
|
||||
}
|
||||
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;
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->setDamage($meta);
|
||||
public function __construct(){
|
||||
|
||||
}
|
||||
|
||||
public function getHardness() : float{
|
||||
|
@ -31,6 +31,24 @@ use pocketmine\Player;
|
||||
use pocketmine\Server;
|
||||
|
||||
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{
|
||||
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{
|
||||
if($item->getId() === Item::DYE and $item->getDamage() === 0x0F){ //Bonemeal
|
||||
$block = clone $this;
|
||||
$block->meta += mt_rand(2, 5);
|
||||
if($block->meta > 7){
|
||||
$block->meta = 7;
|
||||
$block->age += mt_rand(2, 5);
|
||||
if($block->age > 7){
|
||||
$block->age = 7;
|
||||
}
|
||||
|
||||
Server::getInstance()->getPluginManager()->callEvent($ev = new BlockGrowEvent($this, $block));
|
||||
@ -75,9 +93,9 @@ abstract class Crops extends Flowable{
|
||||
|
||||
public function onRandomTick() : void{
|
||||
if(mt_rand(0, 2) === 1){
|
||||
if($this->meta < 0x07){
|
||||
if($this->age < 7){
|
||||
$block = clone $this;
|
||||
++$block->meta;
|
||||
++$block->age;
|
||||
Server::getInstance()->getPluginManager()->callEvent($ev = new BlockGrowEvent($this, $block));
|
||||
|
||||
if(!$ev->isCancelled()){
|
||||
|
@ -32,8 +32,8 @@ class Dandelion extends Flowable{
|
||||
|
||||
protected $id = self::DANDELION;
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->setDamage($meta);
|
||||
public function __construct(){
|
||||
|
||||
}
|
||||
|
||||
public function getName() : string{
|
||||
|
@ -25,10 +25,40 @@ namespace pocketmine\block;
|
||||
|
||||
class DaylightSensor extends Transparent{
|
||||
|
||||
protected $id = self::DAYLIGHT_SENSOR;
|
||||
protected $itemId = self::DAYLIGHT_SENSOR;
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->setDamage($meta);
|
||||
/** @var int */
|
||||
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{
|
||||
|
@ -33,8 +33,8 @@ class DeadBush extends Flowable{
|
||||
|
||||
protected $id = self::DEAD_BUSH;
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->setDamage($meta);
|
||||
public function __construct(){
|
||||
|
||||
}
|
||||
|
||||
public function getName() : string{
|
||||
|
@ -29,8 +29,8 @@ class Diamond extends Solid{
|
||||
|
||||
protected $id = self::DIAMOND_BLOCK;
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->setDamage($meta);
|
||||
public function __construct(){
|
||||
|
||||
}
|
||||
|
||||
public function getHardness() : float{
|
||||
|
@ -31,8 +31,8 @@ class DiamondOre extends Solid{
|
||||
|
||||
protected $id = self::DIAMOND_ORE;
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->setDamage($meta);
|
||||
public function __construct(){
|
||||
|
||||
}
|
||||
|
||||
public function getHardness() : float{
|
||||
|
@ -28,12 +28,8 @@ use pocketmine\item\Item;
|
||||
use pocketmine\Player;
|
||||
|
||||
class Dirt extends Solid{
|
||||
|
||||
protected $id = self::DIRT;
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->setDamage($meta);
|
||||
}
|
||||
public const NORMAL = 0;
|
||||
public const COARSE = 1;
|
||||
|
||||
public function getHardness() : float{
|
||||
return 0.5;
|
||||
@ -43,17 +39,10 @@ class Dirt extends Solid{
|
||||
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{
|
||||
if($item instanceof Hoe){
|
||||
$item->applyDamage(1);
|
||||
if($this->meta === 1){
|
||||
if($this->variant === self::COARSE){
|
||||
$this->getLevel()->setBlock($this, BlockFactory::get(Block::DIRT), true);
|
||||
}else{
|
||||
$this->getLevel()->setBlock($this, BlockFactory::get(Block::FARMLAND), true);
|
||||
|
@ -33,41 +33,72 @@ use pocketmine\Player;
|
||||
|
||||
|
||||
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{
|
||||
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{
|
||||
$f = 0.1875;
|
||||
$damage = $this->getFullDamage();
|
||||
$this->updateStateFromOtherHalf();
|
||||
|
||||
$bb = new AxisAlignedBB(0, 0, 0, 1, 2, 1);
|
||||
|
||||
$j = $damage & 0x03;
|
||||
$isOpen = (($damage & 0x04) > 0);
|
||||
$isRight = (($damage & 0x10) > 0);
|
||||
|
||||
if($j === 0){
|
||||
if($isOpen){
|
||||
if(!$isRight){
|
||||
if($this->facing === Facing::EAST){
|
||||
if($this->open){
|
||||
if(!$this->hingeRight){
|
||||
$bb->setBounds(0, 0, 0, 1, 1, $f);
|
||||
}else{
|
||||
$bb->setBounds(0, 0, 1 - $f, 1, 1, 1);
|
||||
@ -75,9 +106,9 @@ abstract class Door extends Transparent{
|
||||
}else{
|
||||
$bb->setBounds(0, 0, 0, $f, 1, 1);
|
||||
}
|
||||
}elseif($j === 1){
|
||||
if($isOpen){
|
||||
if(!$isRight){
|
||||
}elseif($this->facing === Facing::SOUTH){
|
||||
if($this->open){
|
||||
if(!$this->hingeRight){
|
||||
$bb->setBounds(1 - $f, 0, 0, 1, 1, 1);
|
||||
}else{
|
||||
$bb->setBounds(0, 0, 0, $f, 1, 1);
|
||||
@ -85,9 +116,9 @@ abstract class Door extends Transparent{
|
||||
}else{
|
||||
$bb->setBounds(0, 0, 0, 1, 1, $f);
|
||||
}
|
||||
}elseif($j === 2){
|
||||
if($isOpen){
|
||||
if(!$isRight){
|
||||
}elseif($this->facing === Facing::WEST){
|
||||
if($this->open){
|
||||
if(!$this->hingeRight){
|
||||
$bb->setBounds(0, 0, 1 - $f, 1, 1, 1);
|
||||
}else{
|
||||
$bb->setBounds(0, 0, 0, 1, 1, $f);
|
||||
@ -95,9 +126,9 @@ abstract class Door extends Transparent{
|
||||
}else{
|
||||
$bb->setBounds(1 - $f, 0, 0, 1, 1, 1);
|
||||
}
|
||||
}elseif($j === 3){
|
||||
if($isOpen){
|
||||
if(!$isRight){
|
||||
}elseif($this->facing === Facing::NORTH){
|
||||
if($this->open){
|
||||
if(!$this->hingeRight){
|
||||
$bb->setBounds(0, 0, 0, $f, 1, 1);
|
||||
}else{
|
||||
$bb->setBounds(1 - $f, 0, 0, 1, 1, 1);
|
||||
@ -127,21 +158,22 @@ abstract class Door extends Transparent{
|
||||
return false;
|
||||
}
|
||||
|
||||
//door faces this way when opened (unless it's right, in which case it's the opposite)
|
||||
$direction = $player !== null ? Bearing::rotate($player->getDirection(), 1) : Bearing::NORTH;
|
||||
|
||||
$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;
|
||||
if($player !== null){
|
||||
$this->facing = Bearing::toFacing($player->getDirection());
|
||||
}
|
||||
|
||||
$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);
|
||||
$this->getLevel()->setBlock($blockUp, BlockFactory::get($this->getId(), $metaUp), true); //Top
|
||||
$this->level->setBlock($blockUp, $topHalf, true); //Top
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -149,31 +181,23 @@ abstract class Door extends Transparent{
|
||||
}
|
||||
|
||||
public function onActivate(Item $item, Player $player = null) : bool{
|
||||
if(($this->getDamage() & 0x08) === 0x08){ //Top
|
||||
$down = $this->getSide(Facing::DOWN);
|
||||
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;
|
||||
}
|
||||
$this->updateStateFromOtherHalf();
|
||||
$this->open = !$this->open;
|
||||
|
||||
return false;
|
||||
}else{
|
||||
$this->meta ^= 0x04;
|
||||
$this->level->setBlock($this, $this, true);
|
||||
$this->level->addSound(new DoorSound($this));
|
||||
$other = $this->getSide($this->top ? Facing::DOWN : Facing::UP);
|
||||
if($other instanceof Door and $this->getId() === $other->getId()){
|
||||
$other->open = $this->open;
|
||||
$this->level->setBlock($other, $other, true, true);
|
||||
}
|
||||
|
||||
$this->level->setBlock($this, $this, true, true);
|
||||
$this->level->addSound(new DoorSound($this));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getVariantBitmask() : int{
|
||||
return 0;
|
||||
}
|
||||
|
||||
public function getDropsForCompatibleTool(Item $item) : array{
|
||||
if(($this->meta & 0x08) === 0){ //bottom half only
|
||||
if(!$this->top){ //bottom half only
|
||||
return parent::getDropsForCompatibleTool($item);
|
||||
}
|
||||
|
||||
@ -185,18 +209,10 @@ abstract class Door extends Transparent{
|
||||
}
|
||||
|
||||
public function getAffectedBlocks() : array{
|
||||
if(($this->getDamage() & 0x08) === 0x08){
|
||||
$down = $this->getSide(Facing::DOWN);
|
||||
if($down->getId() === $this->getId()){
|
||||
return [$this, $down];
|
||||
}
|
||||
}else{
|
||||
$up = $this->getSide(Facing::UP);
|
||||
if($up->getId() === $this->getId()){
|
||||
return [$this, $up];
|
||||
}
|
||||
$other = $this->getSide($this->top ? Facing::DOWN : Facing::UP);
|
||||
if($other->getId() === $this->getId()){
|
||||
return [$this, $other];
|
||||
}
|
||||
|
||||
return parent::getAffectedBlocks();
|
||||
}
|
||||
}
|
||||
|
@ -30,35 +30,34 @@ use pocketmine\math\Vector3;
|
||||
use pocketmine\Player;
|
||||
|
||||
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){
|
||||
$this->setDamage($meta);
|
||||
protected function writeStateToMeta() : int{
|
||||
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{
|
||||
return $this->meta === 2 or $this->meta === 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()] ?? "";
|
||||
return $this->variant === 2 or $this->variant === 3; //grass or fern
|
||||
}
|
||||
|
||||
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
|
||||
$id = $blockReplace->getSide(Facing::DOWN)->getId();
|
||||
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->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;
|
||||
}
|
||||
@ -71,39 +70,32 @@ class DoublePlant extends Flowable{
|
||||
* @return bool
|
||||
*/
|
||||
public function isValidHalfPlant() : bool{
|
||||
if($this->meta & self::BITFLAG_TOP){
|
||||
$other = $this->getSide(Facing::DOWN);
|
||||
}else{
|
||||
$other = $this->getSide(Facing::UP);
|
||||
}
|
||||
$other = $this->getSide($this->top ? Facing::DOWN : Facing::UP);
|
||||
|
||||
return (
|
||||
$other instanceof DoublePlant and
|
||||
$other->getId() === $this->getId() and
|
||||
$other->getVariant() === $this->getVariant() and
|
||||
($other->getDamage() & self::BITFLAG_TOP) !== ($this->getDamage() & self::BITFLAG_TOP)
|
||||
$other->getVariant() === $this->variant and
|
||||
$other->top !== $this->top
|
||||
);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
public function getVariantBitmask() : int{
|
||||
return 0x07;
|
||||
}
|
||||
|
||||
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{
|
||||
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{
|
||||
if($this->meta & self::BITFLAG_TOP){
|
||||
if($this->top){
|
||||
if($this->isCompatibleWithTool($item)){
|
||||
return parent::getDrops($item);
|
||||
}
|
||||
@ -120,7 +112,7 @@ class DoublePlant extends Flowable{
|
||||
|
||||
public function getAffectedBlocks() : array{
|
||||
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();
|
||||
|
@ -26,21 +26,46 @@ namespace pocketmine\block;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\ItemFactory;
|
||||
|
||||
abstract class DoubleSlab extends Solid{
|
||||
class DoubleSlab extends Solid{
|
||||
/** @var int */
|
||||
protected $singleId;
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->setDamage($meta);
|
||||
public function __construct(int $id, int $singleId, int $variant = 0){
|
||||
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{
|
||||
return "Double " . BlockFactory::get($this->getSlabId(), $this->getVariant())->getName();
|
||||
return "Double " . $this->getSingle()->getName();
|
||||
}
|
||||
|
||||
public function getDropsForCompatibleTool(Item $item) : array{
|
||||
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;
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->setDamage($meta);
|
||||
public function __construct(){
|
||||
|
||||
}
|
||||
|
||||
public function getHardness() : float{
|
||||
|
@ -31,8 +31,8 @@ class EmeraldOre extends Solid{
|
||||
|
||||
protected $id = self::EMERALD_ORE;
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->setDamage($meta);
|
||||
public function __construct(){
|
||||
|
||||
}
|
||||
|
||||
public function getName() : string{
|
||||
|
@ -35,8 +35,8 @@ class EnchantingTable extends Transparent{
|
||||
|
||||
protected $id = self::ENCHANTING_TABLE;
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->setDamage($meta);
|
||||
public function __construct(){
|
||||
|
||||
}
|
||||
|
||||
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\math\AxisAlignedBB;
|
||||
use pocketmine\math\Bearing;
|
||||
use pocketmine\math\Facing;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\Player;
|
||||
|
||||
class EndPortalFrame extends Solid{
|
||||
|
||||
protected $id = self::END_PORTAL_FRAME;
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->setDamage($meta);
|
||||
/** @var int */
|
||||
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{
|
||||
@ -55,14 +77,20 @@ class EndPortalFrame extends Solid{
|
||||
}
|
||||
|
||||
protected function recalculateBoundingBox() : ?AxisAlignedBB{
|
||||
|
||||
return new AxisAlignedBB(
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
(($this->getDamage() & 0x04) > 0 ? 1 : 0.8125),
|
||||
$this->eye ? 1 : 0.8125,
|
||||
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;
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->setDamage($meta);
|
||||
/** @var int */
|
||||
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{
|
||||
@ -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{
|
||||
if(Facing::axis($face) === Facing::AXIS_Y){
|
||||
$this->meta = $face;
|
||||
}else{
|
||||
$this->meta = $face ^ 0x01;
|
||||
}
|
||||
if($blockClicked instanceof EndRod and $blockClicked->getDamage() === $this->meta){
|
||||
$this->meta ^= 0x01;
|
||||
$this->facing = $face;
|
||||
if($blockClicked instanceof EndRod and $blockClicked->facing === $this->facing){
|
||||
$this->facing = Facing::opposite($face);
|
||||
}
|
||||
|
||||
return parent::place($item, $blockReplace, $blockClicked, $face, $clickVector, $player);
|
||||
@ -63,7 +81,7 @@ class EndRod extends Flowable{
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
switch($m){
|
||||
@ -98,8 +116,4 @@ class EndRod extends Flowable{
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public function getVariantBitmask() : int{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
@ -29,8 +29,8 @@ class EndStone extends Solid{
|
||||
|
||||
protected $id = self::END_STONE;
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->setDamage($meta);
|
||||
public function __construct(){
|
||||
|
||||
}
|
||||
|
||||
public function getName() : string{
|
||||
|
@ -29,8 +29,8 @@ class EndStoneBricks extends Solid{
|
||||
|
||||
protected $id = self::END_BRICKS;
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->setDamage($meta);
|
||||
public function __construct(){
|
||||
|
||||
}
|
||||
|
||||
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{
|
||||
if($player !== null){
|
||||
$this->meta = Bearing::toFacing(Bearing::opposite($player->getDirection()));
|
||||
if($player !== null){ //same as normal chest - TODO: clean up inheritance here
|
||||
$this->facing = Bearing::toFacing(Bearing::opposite($player->getDirection()));
|
||||
}
|
||||
|
||||
if(Block::place($item, $blockReplace, $blockClicked, $face, $clickVector, $player)){
|
||||
|
@ -32,8 +32,23 @@ class Farmland extends Transparent{
|
||||
|
||||
protected $id = self::FARMLAND;
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->setDamage($meta);
|
||||
/** @var int */
|
||||
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{
|
||||
@ -64,14 +79,14 @@ class Farmland extends Transparent{
|
||||
|
||||
public function onRandomTick() : void{
|
||||
if(!$this->canHydrate()){
|
||||
if($this->meta > 0){
|
||||
$this->meta--;
|
||||
if($this->wetness > 0){
|
||||
$this->wetness--;
|
||||
$this->level->setBlock($this, $this, false, false);
|
||||
}else{
|
||||
$this->level->setBlock($this, BlockFactory::get(Block::DIRT), false, true);
|
||||
}
|
||||
}elseif($this->meta < 7){
|
||||
$this->meta = 7;
|
||||
}elseif($this->wetness < 7){
|
||||
$this->wetness = 7;
|
||||
$this->level->setBlock($this, $this, false, false);
|
||||
}
|
||||
}
|
||||
|
@ -28,10 +28,6 @@ use pocketmine\math\Facing;
|
||||
|
||||
abstract class Fence extends Transparent{
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->setDamage($meta);
|
||||
}
|
||||
|
||||
public function getThickness() : float{
|
||||
return 0.25;
|
||||
}
|
||||
|
@ -26,10 +26,29 @@ namespace pocketmine\block;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\level\sound\DoorSound;
|
||||
use pocketmine\math\AxisAlignedBB;
|
||||
use pocketmine\math\Bearing;
|
||||
use pocketmine\math\Facing;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\Player;
|
||||
|
||||
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{
|
||||
return 2;
|
||||
@ -41,12 +60,11 @@ class FenceGate extends Transparent{
|
||||
|
||||
|
||||
protected function recalculateBoundingBox() : ?AxisAlignedBB{
|
||||
if(($this->getDamage() & 0x04) > 0){
|
||||
if($this->open){
|
||||
return null;
|
||||
}
|
||||
|
||||
$i = ($this->getDamage() & 0x03);
|
||||
if($i === 2 or $i === 0){
|
||||
if(Facing::axis($this->facing) === Facing::AXIS_Z){
|
||||
return new AxisAlignedBB(
|
||||
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{
|
||||
if($player !== null){
|
||||
$this->meta = $player->getDirection();
|
||||
$this->facing = Bearing::toFacing($player->getDirection());
|
||||
}
|
||||
|
||||
return parent::place($item, $blockReplace, $blockClicked, $face, $clickVector, $player);
|
||||
}
|
||||
|
||||
public function getVariantBitmask() : int{
|
||||
return 0;
|
||||
}
|
||||
|
||||
public function onActivate(Item $item, Player $player = null) : bool{
|
||||
$this->meta = (($this->meta ^ 0x04) & ~0x02);
|
||||
|
||||
if($player !== null){
|
||||
$this->meta |= ($player->getDirection() & 0x02); //open towards the player, retaining axis
|
||||
$this->open = !$this->open;
|
||||
if($this->open and $player !== null){
|
||||
$playerFacing = Bearing::toFacing($player->getDirection());
|
||||
if($playerFacing === Facing::opposite($this->facing)){
|
||||
$this->facing = $playerFacing;
|
||||
}
|
||||
}
|
||||
|
||||
$this->getLevel()->setBlock($this, $this, true);
|
||||
|
@ -37,8 +37,23 @@ class Fire extends Flowable{
|
||||
|
||||
protected $id = self::FIRE;
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->setDamage($meta);
|
||||
/** @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 0b1111;
|
||||
}
|
||||
|
||||
public function hasEntityCollision() : bool{
|
||||
@ -95,22 +110,22 @@ class Fire extends Flowable{
|
||||
$down = $this->getSide(Facing::DOWN);
|
||||
|
||||
$result = null;
|
||||
if($this->meta < 15 and mt_rand(0, 2) === 0){
|
||||
$this->meta++;
|
||||
if($this->age < 15 and mt_rand(0, 2) === 0){
|
||||
$this->age++;
|
||||
$result = $this;
|
||||
}
|
||||
$canSpread = true;
|
||||
|
||||
if(!$down->burnsForever()){
|
||||
//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
|
||||
$canSpread = false;
|
||||
$result = BlockFactory::get(Block::AIR);
|
||||
}
|
||||
}elseif(!$this->hasAdjacentFlammableBlocks()){
|
||||
$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);
|
||||
}
|
||||
}
|
||||
@ -157,8 +172,10 @@ class Fire extends Flowable{
|
||||
if(!$ev->isCancelled()){
|
||||
$block->onIncinerate();
|
||||
|
||||
if(mt_rand(0, $this->meta + 9) < 5){ //TODO: check rain
|
||||
$this->level->setBlock($block, BlockFactory::get(Block::FIRE, min(15, $this->meta + (mt_rand(0, 4) >> 2))));
|
||||
if(mt_rand(0, $this->age + 9) < 5){ //TODO: check rain
|
||||
$fire = clone $this;
|
||||
$fire->age = min(15, $fire->age + (mt_rand(0, 4) >> 2));
|
||||
$this->level->setBlock($block, $fire);
|
||||
}else{
|
||||
$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_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{
|
||||
$down = $this->getSide(Facing::DOWN);
|
||||
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{
|
||||
|
||||
public const STATE_EMPTY = 0;
|
||||
public const STATE_FULL = 1;
|
||||
|
||||
protected $id = self::FLOWER_POT_BLOCK;
|
||||
protected $itemId = Item::FLOWER_POT;
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->setDamage($meta);
|
||||
/** @var bool */
|
||||
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{
|
||||
@ -80,17 +92,13 @@ class FlowerPot extends Flowable{
|
||||
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);
|
||||
$pot->setItem($item->pop());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getVariantBitmask() : int{
|
||||
return 0;
|
||||
}
|
||||
|
||||
public function getDropsForCompatibleTool(Item $item) : array{
|
||||
$items = parent::getDropsForCompatibleTool($item);
|
||||
|
||||
|
@ -23,16 +23,98 @@ declare(strict_types=1);
|
||||
|
||||
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{
|
||||
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{
|
||||
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{
|
||||
|
||||
protected $id = self::GLASS;
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->setDamage($meta);
|
||||
}
|
||||
|
||||
public function getName() : string{
|
||||
return "Glass";
|
||||
}
|
||||
|
||||
public function getHardness() : float{
|
||||
return 0.3;
|
||||
}
|
||||
|
@ -27,16 +27,6 @@ use pocketmine\item\Item;
|
||||
|
||||
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{
|
||||
return 0.3;
|
||||
}
|
||||
|
@ -27,11 +27,27 @@ 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;
|
||||
|
||||
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{
|
||||
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{
|
||||
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);
|
||||
}
|
||||
|
||||
public function getVariantBitmask() : int{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
@ -30,8 +30,8 @@ class GlowingObsidian extends Solid{
|
||||
|
||||
protected $id = self::GLOWING_OBSIDIAN;
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->setDamage($meta);
|
||||
public function __construct(){
|
||||
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->setDamage($meta);
|
||||
public function __construct(){
|
||||
|
||||
}
|
||||
|
||||
public function getName() : string{
|
||||
|
@ -29,8 +29,8 @@ class Gold extends Solid{
|
||||
|
||||
protected $id = self::GOLD_BLOCK;
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->setDamage($meta);
|
||||
public function __construct(){
|
||||
|
||||
}
|
||||
|
||||
public function getName() : string{
|
||||
|
@ -29,8 +29,8 @@ class GoldOre extends Solid{
|
||||
|
||||
protected $id = self::GOLD_ORE;
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->setDamage($meta);
|
||||
public function __construct(){
|
||||
|
||||
}
|
||||
|
||||
public function getName() : string{
|
||||
|
@ -37,8 +37,8 @@ class Grass extends Solid{
|
||||
|
||||
protected $id = self::GRASS;
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->setDamage($meta);
|
||||
public function __construct(){
|
||||
|
||||
}
|
||||
|
||||
public function getName() : string{
|
||||
|
@ -32,8 +32,8 @@ class GrassPath extends Transparent{
|
||||
|
||||
protected $id = self::GRASS_PATH;
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->setDamage($meta);
|
||||
public function __construct(){
|
||||
|
||||
}
|
||||
|
||||
public function getName() : string{
|
||||
|
@ -30,8 +30,8 @@ class Gravel extends Fallable{
|
||||
|
||||
protected $id = self::GRAVEL;
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->setDamage($meta);
|
||||
public function __construct(){
|
||||
|
||||
}
|
||||
|
||||
public function getName() : string{
|
||||
|
@ -27,16 +27,6 @@ use pocketmine\item\TieredTool;
|
||||
|
||||
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{
|
||||
return BlockToolType::TYPE_PICKAXE;
|
||||
}
|
||||
|
@ -23,17 +23,19 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\block\utils\PillarRotationHelper;
|
||||
use pocketmine\block\utils\PillarRotationTrait;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\math\Facing;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\Player;
|
||||
|
||||
class HayBale extends Solid{
|
||||
use PillarRotationTrait;
|
||||
|
||||
protected $id = self::HAY_BALE;
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->setDamage($meta);
|
||||
public function __construct(){
|
||||
|
||||
}
|
||||
|
||||
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{
|
||||
$this->meta = PillarRotationHelper::getMetaFromFace($this->meta, $face);
|
||||
$this->axis = Facing::axis($face);
|
||||
return parent::place($item, $blockReplace, $blockClicked, $face, $clickVector, $player);
|
||||
}
|
||||
|
||||
public function getVariantBitmask() : int{
|
||||
return 0x03;
|
||||
}
|
||||
|
||||
public function getFlameEncouragement() : int{
|
||||
return 60;
|
||||
}
|
||||
|
@ -31,8 +31,8 @@ class Ice extends Transparent{
|
||||
|
||||
protected $id = self::ICE;
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->setDamage($meta);
|
||||
public function __construct(){
|
||||
|
||||
}
|
||||
|
||||
public function getName() : string{
|
||||
|
@ -29,8 +29,8 @@ class Iron extends Solid{
|
||||
|
||||
protected $id = self::IRON_BLOCK;
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->setDamage($meta);
|
||||
public function __construct(){
|
||||
|
||||
}
|
||||
|
||||
public function getName() : string{
|
||||
|
@ -29,8 +29,8 @@ class IronBars extends Thin{
|
||||
|
||||
protected $id = self::IRON_BARS;
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->setDamage($meta);
|
||||
public function __construct(){
|
||||
|
||||
}
|
||||
|
||||
public function getName() : string{
|
||||
@ -48,8 +48,4 @@ class IronBars extends Thin{
|
||||
public function getToolHarvestLevel() : int{
|
||||
return TieredTool::TIER_WOODEN;
|
||||
}
|
||||
|
||||
public function getVariantBitmask() : int{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
@ -32,8 +32,8 @@ class IronDoor extends Door{
|
||||
|
||||
protected $itemId = Item::IRON_DOOR;
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->setDamage($meta);
|
||||
public function __construct(){
|
||||
|
||||
}
|
||||
|
||||
public function getName() : string{
|
||||
|
@ -29,8 +29,8 @@ class IronOre extends Solid{
|
||||
|
||||
protected $id = self::IRON_ORE;
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->setDamage($meta);
|
||||
public function __construct(){
|
||||
|
||||
}
|
||||
|
||||
public function getName() : string{
|
||||
|
@ -35,8 +35,23 @@ class ItemFrame extends Flowable{
|
||||
|
||||
protected $itemId = Item::ITEM_FRAME;
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->setDamage($meta);
|
||||
/** @var int */
|
||||
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{
|
||||
@ -59,7 +74,7 @@ class ItemFrame extends Flowable{
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
@ -69,7 +84,7 @@ class ItemFrame extends Flowable{
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->meta = 5 - $face;
|
||||
$this->facing = $face;
|
||||
|
||||
if(parent::place($item, $blockReplace, $blockClicked, $face, $clickVector, $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{
|
||||
$drops = parent::getDropsForCompatibleTool($item);
|
||||
|
||||
|
@ -34,8 +34,23 @@ class Ladder extends Transparent{
|
||||
|
||||
protected $id = self::LADDER;
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->setDamage($meta);
|
||||
/** @var int */
|
||||
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{
|
||||
@ -69,13 +84,13 @@ class Ladder extends Transparent{
|
||||
$minX = $minZ = 0;
|
||||
$maxX = $maxZ = 1;
|
||||
|
||||
if($this->meta === 2){
|
||||
if($this->facing === Facing::NORTH){
|
||||
$minZ = 1 - $f;
|
||||
}elseif($this->meta === 3){
|
||||
}elseif($this->facing === Facing::SOUTH){
|
||||
$maxZ = $f;
|
||||
}elseif($this->meta === 4){
|
||||
}elseif($this->facing === Facing::WEST){
|
||||
$minX = 1 - $f;
|
||||
}elseif($this->meta === 5){
|
||||
}elseif($this->facing === Facing::EAST){
|
||||
$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{
|
||||
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);
|
||||
}
|
||||
|
||||
@ -100,7 +115,7 @@ class Ladder extends Transparent{
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
@ -108,8 +123,4 @@ class Ladder extends Transparent{
|
||||
public function getToolType() : int{
|
||||
return BlockToolType::TYPE_AXE;
|
||||
}
|
||||
|
||||
public function getVariantBitmask() : int{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
@ -29,8 +29,8 @@ class Lapis extends Solid{
|
||||
|
||||
protected $id = self::LAPIS_BLOCK;
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->setDamage($meta);
|
||||
public function __construct(){
|
||||
|
||||
}
|
||||
|
||||
public function getName() : string{
|
||||
|
@ -31,8 +31,8 @@ class LapisOre extends Solid{
|
||||
|
||||
protected $id = self::LAPIS_ORE;
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->setDamage($meta);
|
||||
public function __construct(){
|
||||
|
||||
}
|
||||
|
||||
public function getHardness() : float{
|
||||
|
@ -35,8 +35,8 @@ class Lava extends Liquid{
|
||||
|
||||
protected $id = self::FLOWING_LAVA;
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->setDamage($meta);
|
||||
public function __construct(){
|
||||
|
||||
}
|
||||
|
||||
public function getLightLevel() : int{
|
||||
@ -48,11 +48,11 @@ class Lava extends Liquid{
|
||||
}
|
||||
|
||||
public function getStillForm() : Block{
|
||||
return BlockFactory::get(Block::STILL_LAVA, $this->meta);
|
||||
return BlockFactory::get(Block::STILL_LAVA, $this->getDamage());
|
||||
}
|
||||
|
||||
public function getFlowingForm() : Block{
|
||||
return BlockFactory::get(Block::FLOWING_LAVA, $this->meta);
|
||||
return BlockFactory::get(Block::FLOWING_LAVA, $this->getDamage());
|
||||
}
|
||||
|
||||
public function getBucketFillSound() : int{
|
||||
@ -85,19 +85,19 @@ class Lava extends Liquid{
|
||||
}
|
||||
|
||||
if($colliding !== null){
|
||||
if($this->getDamage() === 0){
|
||||
if($this->decay === 0){
|
||||
$this->liquidCollide($colliding, BlockFactory::get(Block::OBSIDIAN));
|
||||
}elseif($this->getDamage() <= 4){
|
||||
}elseif($this->decay <= 4){
|
||||
$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){
|
||||
$block->liquidCollide($this, BlockFactory::get(Block::STONE));
|
||||
}else{
|
||||
parent::flowIntoBlock($block, $newFlowDecay);
|
||||
parent::flowIntoBlock($block, $newFlowDecay, $falling);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -23,6 +23,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\block\utils\WoodType;
|
||||
use pocketmine\event\block\LeavesDecayEvent;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\ItemFactory;
|
||||
@ -32,17 +33,30 @@ use pocketmine\math\Vector3;
|
||||
use pocketmine\Player;
|
||||
|
||||
class Leaves extends Transparent{
|
||||
public const OAK = 0;
|
||||
public const SPRUCE = 1;
|
||||
public const BIRCH = 2;
|
||||
public const JUNGLE = 3;
|
||||
public const ACACIA = 0;
|
||||
public const DARK_OAK = 1;
|
||||
/** @var int */
|
||||
protected $woodType;
|
||||
|
||||
protected $id = self::LEAVES;
|
||||
/** @var bool */
|
||||
protected $noDecay = false;
|
||||
/** @var bool */
|
||||
protected $checkDecay = false;
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->setDamage($meta);
|
||||
public function __construct(int $id, int $variant, int $woodType, ?string $name = null){
|
||||
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{
|
||||
@ -53,16 +67,6 @@ class Leaves extends Transparent{
|
||||
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{
|
||||
return true;
|
||||
}
|
||||
@ -80,7 +84,7 @@ class Leaves extends Transparent{
|
||||
return true;
|
||||
}
|
||||
|
||||
if($pos->getId() === $this->id and $distance <= 4){
|
||||
if($pos->getId() === $this->getId() and $distance <= 4){
|
||||
foreach(Facing::ALL as $side){
|
||||
if($this->findLog($pos->getSide($side), $visited, $distance + 1)){
|
||||
return true;
|
||||
@ -92,8 +96,8 @@ class Leaves extends Transparent{
|
||||
}
|
||||
|
||||
public function onNearbyBlockChange() : void{
|
||||
if(($this->meta & 0b00001100) === 0){
|
||||
$this->meta |= 0x08;
|
||||
if(!$this->noDecay and !$this->checkDecay){
|
||||
$this->checkDecay = true;
|
||||
$this->getLevel()->setBlock($this, $this, true, false);
|
||||
}
|
||||
}
|
||||
@ -103,9 +107,7 @@ class Leaves extends Transparent{
|
||||
}
|
||||
|
||||
public function onRandomTick() : void{
|
||||
if(($this->meta & 0b00001100) === 0x08){
|
||||
$this->meta &= 0x03;
|
||||
|
||||
if(!$this->noDecay and $this->checkDecay){
|
||||
$this->getLevel()->getServer()->getPluginManager()->callEvent($ev = new LeavesDecayEvent($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{
|
||||
$this->meta |= 0x04;
|
||||
$this->noDecay = true; //artificial leaves don't decay
|
||||
return parent::place($item, $blockReplace, $blockClicked, $face, $clickVector, $player);
|
||||
}
|
||||
|
||||
public function getVariantBitmask() : int{
|
||||
return 0x03;
|
||||
}
|
||||
|
||||
public function getDrops(Item $item) : array{
|
||||
if($item->getBlockToolType() & BlockToolType::TYPE_SHEARS){
|
||||
return $this->getDropsForCompatibleTool($item);
|
||||
@ -132,23 +130,15 @@ class Leaves extends Transparent{
|
||||
|
||||
$drops = [];
|
||||
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);
|
||||
}
|
||||
|
||||
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{
|
||||
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;
|
||||
|
||||
class Lever extends Flowable{
|
||||
protected const BOTTOM = 0;
|
||||
protected const SIDE = 1;
|
||||
protected const TOP = 2;
|
||||
|
||||
protected $id = self::LEVER;
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->setDamage($meta);
|
||||
/** @var int */
|
||||
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{
|
||||
@ -45,49 +86,34 @@ class Lever extends Flowable{
|
||||
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{
|
||||
if(!$blockClicked->isSolid()){
|
||||
return false;
|
||||
}
|
||||
|
||||
if($face === Facing::DOWN){
|
||||
$this->meta = 0;
|
||||
}else{
|
||||
$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;
|
||||
}
|
||||
if(Facing::axis($face) === Facing::AXIS_Y){
|
||||
if($player !== null){
|
||||
$this->facing = Bearing::toFacing(Bearing::opposite($player->getDirection()));
|
||||
}
|
||||
$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);
|
||||
}
|
||||
|
||||
public function onNearbyBlockChange() : void{
|
||||
static $faces = [
|
||||
0 => Facing::UP,
|
||||
1 => Facing::WEST,
|
||||
2 => Facing::EAST,
|
||||
3 => Facing::NORTH,
|
||||
4 => Facing::SOUTH,
|
||||
5 => Facing::DOWN,
|
||||
6 => Facing::DOWN,
|
||||
7 => Facing::UP
|
||||
];
|
||||
if(!$this->getSide($faces[$this->meta & 0x07])->isSolid()){
|
||||
if($this->position === self::BOTTOM){
|
||||
$face = Facing::UP;
|
||||
}elseif($this->position === self::TOP){
|
||||
$face = Facing::DOWN;
|
||||
}else{
|
||||
$face = Facing::opposite($this->facing);
|
||||
}
|
||||
|
||||
if(!$this->getSide($face)->isSolid()){
|
||||
$this->level->useBreakOn($this);
|
||||
}
|
||||
}
|
||||
|
@ -44,6 +44,24 @@ abstract class Liquid extends Transparent{
|
||||
private const CAN_FLOW = 0;
|
||||
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{
|
||||
return true;
|
||||
}
|
||||
@ -84,35 +102,20 @@ abstract class Liquid extends Transparent{
|
||||
|
||||
abstract public function getBucketEmptySound() : int;
|
||||
|
||||
public function getFluidHeightPercent(){
|
||||
$d = $this->meta;
|
||||
if($d >= 8){
|
||||
$d = 0;
|
||||
}
|
||||
|
||||
return ($d + 1) / 9;
|
||||
public function isSource() : bool{
|
||||
return !$this->falling and $this->decay === 0;
|
||||
}
|
||||
|
||||
protected function getFlowDecay(Block $block) : int{
|
||||
if($block->getId() !== $this->getId()){
|
||||
return -1;
|
||||
}
|
||||
|
||||
return $block->getDamage();
|
||||
public function getFluidHeightPercent(){
|
||||
return (($this->falling ? 0 : $this->decay) + 1) / 9;
|
||||
}
|
||||
|
||||
protected function getEffectiveFlowDecay(Block $block) : int{
|
||||
if($block->getId() !== $this->getId()){
|
||||
if(!($block instanceof Liquid) or $block->getId() !== $this->getId()){
|
||||
return -1;
|
||||
}
|
||||
|
||||
$decay = $block->getDamage();
|
||||
|
||||
if($decay >= 8){
|
||||
$decay = 0;
|
||||
}
|
||||
|
||||
return $decay;
|
||||
return $block->falling ? 0 : $block->decay;
|
||||
}
|
||||
|
||||
public function clearCaches() : void{
|
||||
@ -170,7 +173,7 @@ abstract class Liquid extends Transparent{
|
||||
}
|
||||
}
|
||||
|
||||
if($this->getDamage() >= 8){
|
||||
if($this->falling){
|
||||
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
|
||||
@ -214,10 +217,9 @@ abstract class Liquid extends Transparent{
|
||||
}
|
||||
|
||||
public function onScheduledUpdate() : void{
|
||||
$decay = $this->getFlowDecay($this);
|
||||
$multiplier = $this->getFlowDecayPerBlock();
|
||||
|
||||
if($decay > 0){
|
||||
if(!$this->isSource()){
|
||||
$smallestFlowDecay = -100;
|
||||
$this->adjacentSources = 0;
|
||||
$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);
|
||||
|
||||
$newDecay = $smallestFlowDecay + $multiplier;
|
||||
$falling = false;
|
||||
|
||||
if($newDecay >= 8 or $smallestFlowDecay < 0){
|
||||
$newDecay = -1;
|
||||
}
|
||||
|
||||
if(($topFlowDecay = $this->getFlowDecay($this->level->getBlockAt($this->x, $this->y + 1, $this->z))) >= 0){
|
||||
$newDecay = $topFlowDecay | 0x08;
|
||||
if($this->getEffectiveFlowDecay($this->level->getBlockAt($this->x, $this->y + 1, $this->z)) >= 0){
|
||||
$falling = true;
|
||||
}
|
||||
|
||||
if($this->adjacentSources >= 2 and $this instanceof Water){
|
||||
$bottomBlock = $this->level->getBlockAt($this->x, $this->y - 1, $this->z);
|
||||
if($bottomBlock->isSolid()){
|
||||
$newDecay = 0;
|
||||
}elseif($bottomBlock instanceof Water and $bottomBlock->getDamage() === 0){
|
||||
if($bottomBlock->isSolid() or ($bottomBlock instanceof Water and $bottomBlock->isSource())){
|
||||
$newDecay = 0;
|
||||
$falling = false;
|
||||
}
|
||||
}
|
||||
|
||||
if($newDecay !== $decay){
|
||||
$decay = $newDecay;
|
||||
if($decay < 0){
|
||||
if($newDecay !== $this->decay or $falling !== $this->falling){
|
||||
if(!$falling and $newDecay < 0){
|
||||
$this->level->setBlock($this, BlockFactory::get(Block::AIR), true, true);
|
||||
}else{
|
||||
$this->level->setBlock($this, BlockFactory::get($this->id, $decay), true, true);
|
||||
$this->level->scheduleDelayedBlockUpdate($this, $this->tickRate());
|
||||
return;
|
||||
}
|
||||
|
||||
$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){
|
||||
$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();
|
||||
}
|
||||
$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($block->getId() > 0){
|
||||
$this->level->useBreakOn($block);
|
||||
}
|
||||
|
||||
$this->level->setBlock($block, BlockFactory::get($this->getId(), $newFlowDecay), true, true);
|
||||
$this->level->scheduleDelayedBlockUpdate($block, $this->tickRate());
|
||||
$new = clone $this;
|
||||
$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{
|
||||
$blockDecay = $this->getFlowDecay($block);
|
||||
|
||||
if($blockDecay < 0){
|
||||
if(!($block instanceof Liquid) or $block->getId() !== $this->getId()){
|
||||
return $decay;
|
||||
}elseif($blockDecay === 0){
|
||||
}
|
||||
|
||||
$blockDecay = $block->decay;
|
||||
|
||||
if($block->isSource()){
|
||||
++$this->adjacentSources;
|
||||
}elseif($blockDecay >= 8){
|
||||
}elseif($block->falling){
|
||||
$blockDecay = 0;
|
||||
}
|
||||
|
||||
@ -433,6 +438,6 @@ abstract class Liquid extends Transparent{
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->setDamage($meta);
|
||||
public function __construct(){
|
||||
|
||||
}
|
||||
|
||||
public function getName() : string{
|
||||
|
@ -30,8 +30,8 @@ class Melon extends Transparent{
|
||||
|
||||
protected $id = self::MELON_BLOCK;
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->setDamage($meta);
|
||||
public function __construct(){
|
||||
|
||||
}
|
||||
|
||||
public function getName() : string{
|
||||
|
@ -37,15 +37,11 @@ class MelonStem extends Crops{
|
||||
return "Melon Stem";
|
||||
}
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->setDamage($meta);
|
||||
}
|
||||
|
||||
public function onRandomTick() : void{
|
||||
if(mt_rand(0, 2) === 1){
|
||||
if($this->meta < 0x07){
|
||||
if($this->age < 7){
|
||||
$block = clone $this;
|
||||
++$block->meta;
|
||||
++$block->age;
|
||||
Server::getInstance()->getPluginManager()->callEvent($ev = new BlockGrowEvent($this, $block));
|
||||
if(!$ev->isCancelled()){
|
||||
$this->getLevel()->setBlock($this, $ev->getNewState(), true);
|
||||
|
@ -30,8 +30,8 @@ class MonsterSpawner extends Transparent{
|
||||
|
||||
protected $id = self::MONSTER_SPAWNER;
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->setDamage($meta);
|
||||
public function __construct(){
|
||||
|
||||
}
|
||||
|
||||
public function getHardness() : float{
|
||||
|
@ -33,8 +33,8 @@ class Mycelium extends Solid{
|
||||
|
||||
protected $id = self::MYCELIUM;
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->setDamage($meta);
|
||||
public function __construct(){
|
||||
|
||||
}
|
||||
|
||||
public function getName() : string{
|
||||
|
@ -29,6 +29,10 @@ class NetherBrickFence extends Fence{
|
||||
|
||||
protected $id = self::NETHER_BRICK_FENCE;
|
||||
|
||||
public function __construct(){
|
||||
|
||||
}
|
||||
|
||||
public function getHardness() : float{
|
||||
return 2;
|
||||
}
|
||||
|
@ -29,8 +29,8 @@ class NetherBrickStairs extends Stair{
|
||||
|
||||
protected $id = self::NETHER_BRICK_STAIRS;
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->setDamage($meta);
|
||||
public function __construct(){
|
||||
|
||||
}
|
||||
|
||||
public function getName() : string{
|
||||
|
@ -31,8 +31,8 @@ class NetherQuartzOre extends Solid{
|
||||
|
||||
protected $id = Block::NETHER_QUARTZ_ORE;
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->setDamage($meta);
|
||||
public function __construct(){
|
||||
|
||||
}
|
||||
|
||||
public function getName() : string{
|
||||
|
@ -28,19 +28,33 @@ use pocketmine\item\ItemFactory;
|
||||
use pocketmine\item\TieredTool;
|
||||
|
||||
class NetherReactor extends Solid{
|
||||
protected const STATE_INACTIVE = 0;
|
||||
protected const STATE_ACTIVE = 1;
|
||||
protected const STATE_USED = 2;
|
||||
|
||||
protected $id = Block::NETHER_REACTOR;
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->setDamage($meta);
|
||||
/** @var int */
|
||||
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{
|
||||
static $prefixes = [
|
||||
"",
|
||||
"Active ",
|
||||
"Used "
|
||||
];
|
||||
return ($prefixes[$this->meta] ?? "") . "Nether Reactor Core";
|
||||
return "Nether Reactor Core";
|
||||
}
|
||||
|
||||
public function getToolType() : int{
|
||||
|
@ -27,8 +27,8 @@ class NetherWartBlock extends Solid{
|
||||
|
||||
protected $id = Block::NETHER_WART_BLOCK;
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->setDamage($meta);
|
||||
public function __construct(){
|
||||
|
||||
}
|
||||
|
||||
public function getName() : string{
|
||||
|
@ -36,8 +36,23 @@ class NetherWartPlant extends Flowable{
|
||||
|
||||
protected $itemId = Item::NETHER_WART;
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->setDamage($meta);
|
||||
/** @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 0b11;
|
||||
}
|
||||
|
||||
public function getName() : string{
|
||||
@ -64,9 +79,9 @@ class NetherWartPlant extends Flowable{
|
||||
}
|
||||
|
||||
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->meta++;
|
||||
$block->age++;
|
||||
$this->getLevel()->getServer()->getPluginManager()->callEvent($ev = new BlockGrowEvent($this, $block));
|
||||
|
||||
if(!$ev->isCancelled()){
|
||||
@ -77,7 +92,7 @@ class NetherWartPlant extends Flowable{
|
||||
|
||||
public function getDropsForCompatibleTool(Item $item) : array{
|
||||
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;
|
||||
|
||||
public function __construct(int $meta = 0){
|
||||
$this->setDamage($meta);
|
||||
public function __construct(){
|
||||
|
||||
}
|
||||
|
||||
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