36    public function __construct(
 
   37        protected Block $trunkBlock,
 
   38        protected Block $leafBlock,
 
   39        protected int $treeHeight = 7
 
   42    public function canPlaceObject(
ChunkManager $world, 
int $x, 
int $y, 
int $z, 
Random $random) : 
bool{
 
   44        for($yy = 0; $yy < $this->treeHeight + 3; ++$yy){
 
   45            if($yy === 1 || $yy === $this->treeHeight){
 
   48            for($xx = -$radiusToCheck; $xx < ($radiusToCheck + 1); ++$xx){
 
   49                for($zz = -$radiusToCheck; $zz < ($radiusToCheck + 1); ++$zz){
 
   50                    if(!$this->canOverride($world->
getBlockAt($x + $xx, $y + $yy, $z + $zz))){
 
   65        if(!$this->canPlaceObject($world, $x, $y, $z, $random)){
 
   70        $this->placeTrunk($x, $y, $z, $random, $this->generateTrunkHeight($random), $transaction);
 
   71        $this->placeCanopy($x, $y, $z, $random, $transaction);
 
 
   76    protected function generateTrunkHeight(
Random $random) : int{
 
   77        return $this->treeHeight - 1;
 
   80    protected function placeTrunk(
int $x, 
int $y, 
int $z, Random $random, 
int $trunkHeight, 
BlockTransaction $transaction) : void{
 
   82        $transaction->addBlockAt($x, $y - 1, $z, 
VanillaBlocks::DIRT());
 
   84        for($yy = 0; $yy < $trunkHeight; ++$yy){
 
   85            if($this->canOverride($transaction->
fetchBlockAt($x, $y + $yy, $z))){
 
   86                $transaction->
addBlockAt($x, $y + $yy, $z, $this->trunkBlock);
 
   91    protected function placeCanopy(
int $x, 
int $y, 
int $z, Random $random, BlockTransaction $transaction) : void{
 
   92        for($yy = $y - 3 + $this->treeHeight; $yy <= $y + $this->treeHeight; ++$yy){
 
   93            $yOff = $yy - ($y + $this->treeHeight);
 
   94            $mid = (int) (1 - $yOff / 2);
 
   95            for($xx = $x - $mid; $xx <= $x + $mid; ++$xx){
 
   96                $xOff = abs($xx - $x);
 
   97                for($zz = $z - $mid; $zz <= $z + $mid; ++$zz){
 
   98                    $zOff = abs($zz - $z);
 
   99                    if($xOff === $mid && $zOff === $mid && ($yOff === 0 || $random->nextBoundedInt(2) === 0)){
 
  102                    if(!$transaction->fetchBlockAt($xx, $yy, $zz)->isSolid()){
 
  103                        $transaction->addBlockAt($xx, $yy, $zz, $this->leafBlock);
 
  110    protected function canOverride(Block $block) : bool{
 
  111        return $block->canBeReplaced() || $block instanceof Sapling || $block instanceof Leaves;