35    private const MIN_HEIGHT = 5;
 
   37    private ?
Vector3 $mainBranchTip = 
null;
 
   38    private ?
Vector3 $secondBranchTip = 
null;
 
   40    public function __construct(){
 
   42            VanillaBlocks::ACACIA_LOG(),
 
   43            VanillaBlocks::ACACIA_LEAVES(),
 
   48    protected function generateTrunkHeight(
Random $random) : 
int{
 
   53    protected function placeTrunk(
int $x, 
int $y, 
int $z, 
Random $random, 
int $trunkHeight, 
BlockTransaction $transaction) : 
void{
 
   55        $transaction->
addBlockAt($x, $y - 1, $z, VanillaBlocks::DIRT());
 
   57        $firstBranchHeight = $trunkHeight - 1 - $random->
nextRange(0, 3);
 
   59        for($yy = 0; $yy <= $firstBranchHeight; ++$yy){
 
   60            $transaction->
addBlockAt($x, $y + $yy, $z, $this->trunkBlock);
 
   63        $mainBranchFacing = Facing::HORIZONTAL[array_rand(Facing::HORIZONTAL)];
 
   66        $this->mainBranchTip = $this->placeBranch(
 
   68            new Vector3($x, $y + $firstBranchHeight, $z),
 
   71            $trunkHeight - $firstBranchHeight
 
   74        $secondBranchFacing = Facing::HORIZONTAL[array_rand(Facing::HORIZONTAL)];
 
   75        if($secondBranchFacing !== $mainBranchFacing){
 
   76            $secondBranchLength = $random->
nextRange(1, 3);
 
   77            $this->secondBranchTip = $this->placeBranch(
 
   90        $nextBlockPos = $start;
 
   91        for($yy = 0; $yy < $length; $yy++){
 
   92            $nextBlockPos = $nextBlockPos->up();
 
   93            if($diagonalPlaced < $maxDiagonal){
 
   94                $nextBlockPos = $nextBlockPos->getSide($branchFacing);
 
   97            $transaction->
addBlock($nextBlockPos, $this->trunkBlock);
 
  100        return $nextBlockPos;
 
  103    protected function placeCanopyLayer(
BlockTransaction $transaction, 
Vector3 $center, 
int $radius, 
int $maxTaxicabDistance) : 
void{
 
  104        $centerX = $center->getFloorX();
 
  105        $centerY = $center->getFloorY();
 
  106        $centerZ = $center->getFloorZ();
 
  108        for($x = $centerX - $radius; $x <= $centerX + $radius; ++$x){
 
  109            for($z = $centerZ - $radius; $z <= $centerZ + $radius; ++$z){
 
  111                    abs($x - $centerX) + abs($z - $centerZ) <= $maxTaxicabDistance &&
 
  112                    $transaction->
fetchBlockAt($x, $centerY, $z)->canBeReplaced()
 
  114                    $transaction->
addBlockAt($x, $centerY, $z, $this->leafBlock);
 
  120    protected function placeCanopy(
int $x, 
int $y, 
int $z, 
Random $random, 
BlockTransaction $transaction) : 
void{
 
  121        $mainBranchTip = $this->mainBranchTip;
 
  122        if($mainBranchTip !== 
null){
 
  123            $this->placeCanopyLayer($transaction, $mainBranchTip, radius: 3, maxTaxicabDistance: 5);
 
  124            $this->placeCanopyLayer($transaction, $mainBranchTip->
up(), radius: 2, maxTaxicabDistance: 2);
 
  126        $secondBranchTip = $this->secondBranchTip;
 
  127        if($secondBranchTip !== 
null){
 
  128            $this->placeCanopyLayer($transaction, $secondBranchTip, radius: 2, maxTaxicabDistance: 3);
 
  129            $this->placeCanopyLayer($transaction, $secondBranchTip->
up(), radius: 1, maxTaxicabDistance: 2);