mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-05-13 09:19:42 +00:00
Split some block variants into their own classes where behaviour differs
This commit is contained in:
parent
e038c4295d
commit
2600cf5977
@ -24,6 +24,7 @@ declare(strict_types=1);
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\block\utils\Color;
|
||||
use pocketmine\block\utils\PillarRotationTrait;
|
||||
use pocketmine\block\utils\WoodType;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\level\Position;
|
||||
@ -45,7 +46,7 @@ class BlockFactory{
|
||||
public static $blastResistance = null;
|
||||
|
||||
/** @var \SplFixedArray|int[] */
|
||||
public static $stateMasks = null;
|
||||
private static $stateMasks = null;
|
||||
|
||||
/** @var int[] */
|
||||
public static $staticRuntimeIdMap = [];
|
||||
@ -68,12 +69,12 @@ class BlockFactory{
|
||||
self::$diffusesSkyLight = \SplFixedArray::fromArray(array_fill(0, 512, false));
|
||||
self::$blastResistance = \SplFixedArray::fromArray(array_fill(0, 512, 0));
|
||||
|
||||
self::$stateMasks = \SplFixedArray::fromArray(array_fill(0, 512, 0));
|
||||
self::$stateMasks = new \SplFixedArray(512);
|
||||
|
||||
self::registerBlock(new Air());
|
||||
|
||||
//TODO: give smooth stone its own class (different drops)
|
||||
self::registerBlock(new Stone(Block::STONE, Stone::NORMAL, "Stone"));
|
||||
self::registerBlock(new SmoothStone(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"));
|
||||
@ -83,9 +84,8 @@ class BlockFactory{
|
||||
|
||||
self::registerBlock(new Grass());
|
||||
|
||||
//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 CoarseDirt(Block::DIRT, Dirt::COARSE, "Coarse Dirt"));
|
||||
|
||||
self::registerBlock(new Cobblestone());
|
||||
|
||||
@ -355,11 +355,17 @@ class BlockFactory{
|
||||
//TODO: HOPPER_BLOCK
|
||||
|
||||
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 class(Block::QUARTZ_BLOCK, Quartz::CHISELED, "Chiseled Quartz Block") extends Quartz{
|
||||
use PillarRotationTrait;
|
||||
});
|
||||
self::registerBlock(new class(Block::QUARTZ_BLOCK, Quartz::PILLAR, "Quartz Pillar") extends Quartz{
|
||||
use PillarRotationTrait;
|
||||
});
|
||||
|
||||
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 Purpur(Block::PURPUR_BLOCK, 0, "Purpur Block"));
|
||||
self::registerBlock(new class(Block::PURPUR_BLOCK, 2, "Purpur Pillar") extends Purpur{
|
||||
use PillarRotationTrait;
|
||||
});
|
||||
|
||||
self::registerBlock(new QuartzStairs());
|
||||
|
||||
@ -382,9 +388,8 @@ class BlockFactory{
|
||||
|
||||
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 DoubleTallGrass(Block::DOUBLE_PLANT, 2, "Double Tallgrass"));
|
||||
self::registerBlock(new DoubleTallGrass(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"));
|
||||
|
||||
@ -478,6 +483,10 @@ class BlockFactory{
|
||||
throw new \RuntimeException("Trying to overwrite an already registered block");
|
||||
}
|
||||
|
||||
if(self::$stateMasks[$id] !== null and self::$stateMasks[$id] !== $block->getStateBitmask()){
|
||||
throw new \InvalidArgumentException("Blocks with the same ID must have the same state bitmask");
|
||||
}
|
||||
|
||||
self::$fullList[($id << 4) | $variant] = clone $block;
|
||||
if($variant === 0){
|
||||
//TODO: allow these to differ for different variants
|
||||
@ -499,13 +508,9 @@ 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];
|
||||
}
|
||||
$stateMask = self::getStateMask($id);
|
||||
$variant = $meta & ~$stateMask;
|
||||
$state = $meta & $stateMask;
|
||||
|
||||
$index = ($id << 4) | $variant;
|
||||
|
||||
@ -553,6 +558,10 @@ class BlockFactory{
|
||||
self::$stateMasks[$id] = $block->getStateBitmask();
|
||||
}
|
||||
|
||||
public static function getStateMask(int $id) : int{
|
||||
return self::$stateMasks[$id] ?? 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether a specified block ID is already registered in the block factory.
|
||||
*
|
||||
|
@ -24,11 +24,7 @@ declare(strict_types=1);
|
||||
namespace pocketmine\block;
|
||||
|
||||
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;
|
||||
@ -54,9 +50,4 @@ class BoneBlock extends Solid{
|
||||
public function getToolHarvestLevel() : int{
|
||||
return TieredTool::TIER_WOODEN;
|
||||
}
|
||||
|
||||
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
|
||||
$this->axis = Facing::axis($face);
|
||||
return parent::place($item, $blockReplace, $blockClicked, $face, $clickVector, $player);
|
||||
}
|
||||
}
|
||||
|
41
src/pocketmine/block/CoarseDirt.php
Normal file
41
src/pocketmine/block/CoarseDirt.php
Normal file
@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Hoe;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\Player;
|
||||
|
||||
class CoarseDirt extends Dirt{
|
||||
|
||||
public function onActivate(Item $item, Player $player = null) : bool{
|
||||
if($item instanceof Hoe){
|
||||
$item->applyDamage(1);
|
||||
$this->getLevel()->setBlock($this, BlockFactory::get(Block::DIRT));
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
@ -42,11 +42,7 @@ class Dirt extends Solid{
|
||||
public function onActivate(Item $item, Player $player = null) : bool{
|
||||
if($item instanceof Hoe){
|
||||
$item->applyDamage(1);
|
||||
if($this->variant === self::COARSE){
|
||||
$this->getLevel()->setBlock($this, BlockFactory::get(Block::DIRT));
|
||||
}else{
|
||||
$this->getLevel()->setBlock($this, BlockFactory::get(Block::FARMLAND));
|
||||
}
|
||||
$this->getLevel()->setBlock($this, BlockFactory::get(Block::FARMLAND));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -47,10 +47,6 @@ class DoublePlant extends Flowable{
|
||||
return 0b1000;
|
||||
}
|
||||
|
||||
public function canBeReplaced() : bool{
|
||||
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()){
|
||||
@ -85,28 +81,8 @@ class DoublePlant extends Flowable{
|
||||
}
|
||||
}
|
||||
|
||||
public function getToolType() : int{
|
||||
return ($this->variant === 2 or $this->variant === 3) ? BlockToolType::TYPE_SHEARS : BlockToolType::TYPE_NONE;
|
||||
}
|
||||
|
||||
public function getToolHarvestLevel() : int{
|
||||
return ($this->variant === 2 or $this->variant === 3) ? 1 : 0; //only grass or fern require shears
|
||||
}
|
||||
|
||||
public function getDrops(Item $item) : array{
|
||||
if($this->top){
|
||||
if($this->isCompatibleWithTool($item)){
|
||||
return parent::getDrops($item);
|
||||
}
|
||||
|
||||
if(mt_rand(0, 24) === 0){
|
||||
return [
|
||||
ItemFactory::get(Item::SEEDS)
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
return [];
|
||||
return $this->top ? parent::getDrops($item) : [];
|
||||
}
|
||||
|
||||
public function getAffectedBlocks() : array{
|
||||
|
51
src/pocketmine/block/DoubleTallGrass.php
Normal file
51
src/pocketmine/block/DoubleTallGrass.php
Normal file
@ -0,0 +1,51 @@
|
||||
<?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 DoubleTallGrass extends DoublePlant{
|
||||
|
||||
public function canBeReplaced() : bool{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getToolType() : int{
|
||||
return BlockToolType::TYPE_SHEARS;
|
||||
}
|
||||
|
||||
public function getToolHarvestLevel() : int{
|
||||
return 1;
|
||||
}
|
||||
|
||||
public function getDrops(Item $item) : array{
|
||||
if($this->top and !$this->isCompatibleWithTool($item) and mt_rand(0, 7) === 0){
|
||||
return [
|
||||
ItemFactory::get(Item::SEEDS)
|
||||
];
|
||||
}
|
||||
return parent::getDrops($item);
|
||||
}
|
||||
}
|
@ -24,10 +24,6 @@ declare(strict_types=1);
|
||||
namespace pocketmine\block;
|
||||
|
||||
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;
|
||||
@ -46,11 +42,6 @@ class HayBale extends Solid{
|
||||
return 0.5;
|
||||
}
|
||||
|
||||
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
|
||||
$this->axis = Facing::axis($face);
|
||||
return parent::place($item, $blockReplace, $blockClicked, $face, $clickVector, $player);
|
||||
}
|
||||
|
||||
public function getFlameEncouragement() : int{
|
||||
return 60;
|
||||
}
|
||||
|
@ -23,7 +23,17 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
class Purpur extends Quartz{
|
||||
use pocketmine\item\TieredTool;
|
||||
|
||||
class Purpur extends Solid{
|
||||
|
||||
public function getToolType() : int{
|
||||
return BlockToolType::TYPE_PICKAXE;
|
||||
}
|
||||
|
||||
public function getToolHarvestLevel() : int{
|
||||
return TieredTool::TIER_WOODEN;
|
||||
}
|
||||
|
||||
public function getHardness() : float{
|
||||
return 1.5;
|
||||
@ -32,4 +42,8 @@ class Purpur extends Quartz{
|
||||
public function getBlastResistance() : float{
|
||||
return 30;
|
||||
}
|
||||
|
||||
public function getStateBitmask() : int{
|
||||
return 0b1100; //HACK: needs to be consistent for blocks with the same ID :(
|
||||
}
|
||||
}
|
||||
|
@ -23,15 +23,9 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
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 Quartz extends Solid{
|
||||
use PillarRotationTrait;
|
||||
|
||||
public const NORMAL = 0;
|
||||
public const CHISELED = 1;
|
||||
@ -41,13 +35,6 @@ class Quartz extends Solid{
|
||||
return 0.8;
|
||||
}
|
||||
|
||||
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
|
||||
if($this->variant !== self::NORMAL){
|
||||
$this->axis = Facing::axis($face);
|
||||
}
|
||||
return parent::place($item, $blockReplace, $blockClicked, $face, $clickVector, $player);
|
||||
}
|
||||
|
||||
public function getToolType() : int{
|
||||
return BlockToolType::TYPE_PICKAXE;
|
||||
}
|
||||
@ -55,4 +42,8 @@ class Quartz extends Solid{
|
||||
public function getToolHarvestLevel() : int{
|
||||
return TieredTool::TIER_WOODEN;
|
||||
}
|
||||
|
||||
public function getStateBitmask() : int{
|
||||
return 0b1100; //HACK: needs to be consistent for blocks with the same ID :(
|
||||
}
|
||||
}
|
||||
|
36
src/pocketmine/block/SmoothStone.php
Normal file
36
src/pocketmine/block/SmoothStone.php
Normal file
@ -0,0 +1,36 @@
|
||||
<?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 SmoothStone extends Stone{
|
||||
|
||||
public function getDropsForCompatibleTool(Item $item) : array{
|
||||
return [
|
||||
ItemFactory::get(Item::COBBLESTONE)
|
||||
];
|
||||
}
|
||||
}
|
@ -47,14 +47,4 @@ class Stone extends Solid{
|
||||
public function getToolHarvestLevel() : int{
|
||||
return TieredTool::TIER_WOODEN;
|
||||
}
|
||||
|
||||
public function getDropsForCompatibleTool(Item $item) : array{
|
||||
if($this->variant === self::NORMAL){
|
||||
return [
|
||||
ItemFactory::get(Item::COBBLESTONE)
|
||||
];
|
||||
}
|
||||
|
||||
return parent::getDropsForCompatibleTool($item);
|
||||
}
|
||||
}
|
||||
|
@ -24,10 +24,6 @@ declare(strict_types=1);
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\block\utils\PillarRotationTrait;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\math\Facing;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\Player;
|
||||
|
||||
class Wood extends Solid{
|
||||
use PillarRotationTrait;
|
||||
@ -41,11 +37,6 @@ class Wood extends Solid{
|
||||
return 2;
|
||||
}
|
||||
|
||||
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
|
||||
$this->axis = Facing::axis($face);
|
||||
return parent::place($item, $blockReplace, $blockClicked, $face, $clickVector, $player);
|
||||
}
|
||||
|
||||
public function getToolType() : int{
|
||||
return BlockToolType::TYPE_AXE;
|
||||
}
|
||||
|
@ -24,7 +24,10 @@ declare(strict_types=1);
|
||||
namespace pocketmine\block\utils;
|
||||
|
||||
use pocketmine\block\Block;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\math\Facing;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\Player;
|
||||
|
||||
trait PillarRotationTrait{
|
||||
|
||||
@ -73,4 +76,22 @@ trait PillarRotationTrait{
|
||||
];
|
||||
return $bits[$this->axis] << 2;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see Block::place()
|
||||
*
|
||||
* @param Item $item
|
||||
* @param Block $blockReplace
|
||||
* @param Block $blockClicked
|
||||
* @param int $face
|
||||
* @param Vector3 $clickVector
|
||||
* @param Player|null $player
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
|
||||
$this->axis = Facing::axis($face);
|
||||
/** @see Block::place() */
|
||||
return parent::place($item, $blockReplace, $blockClicked, $face, $clickVector, $player);
|
||||
}
|
||||
}
|
||||
|
@ -986,7 +986,7 @@ class Level implements ChunkManager, Metadatable{
|
||||
$blockId = $subChunk->getBlockId($x, $y, $z);
|
||||
$meta = $subChunk->getBlockData($x, $y, $z);
|
||||
|
||||
if($this->randomTickBlocks[($blockId << 4) | ($meta & ~BlockFactory::$stateMasks[$blockId])]){
|
||||
if($this->randomTickBlocks[($blockId << 4) | ($meta & ~BlockFactory::getStateMask($blockId))]){
|
||||
/** @var Block $block */
|
||||
$block = BlockFactory::get($blockId, $meta);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user