From ab75838c89b750a34bf2485e0b9c11a94de7a3c4 Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Sat, 10 Jun 2023 18:35:42 +0100 Subject: [PATCH] First shot at implementing acacia trees this is mostly working, but due to some issue with leaf decay, the edges of the larger canopy will decay within minutes. I don't know why this is yet, but it's likely some incorrect implementation of Leaves causing the problem. In addition, the secondary branch of acacia may generate next to the base block of the trunk, which I've never observed to happen in vanilla. This has a 2% chance of occurring, so I haven't been able to rule it out yet, but it probably shouldn't happen. --- src/world/generator/object/AcaciaTree.php | 132 +++++++++++++++++++++ src/world/generator/object/TreeFactory.php | 2 + 2 files changed, 134 insertions(+) create mode 100644 src/world/generator/object/AcaciaTree.php diff --git a/src/world/generator/object/AcaciaTree.php b/src/world/generator/object/AcaciaTree.php new file mode 100644 index 000000000..75e58a9b3 --- /dev/null +++ b/src/world/generator/object/AcaciaTree.php @@ -0,0 +1,132 @@ +nextRange(0, 2) + $random->nextRange(0, 2); + } + + protected function placeTrunk(int $x, int $y, int $z, Random $random, int $trunkHeight, BlockTransaction $transaction) : void{ + // The base dirt block + $transaction->addBlockAt($x, $y - 1, $z, VanillaBlocks::DIRT()); + + $firstBranchHeight = $trunkHeight - 1 - $random->nextRange(0, 3); + + for($yy = 0; $yy <= $firstBranchHeight; ++$yy){ + $transaction->addBlockAt($x, $y + $yy, $z, $this->trunkBlock); + } + + $mainBranchFacing = Facing::HORIZONTAL[array_rand(Facing::HORIZONTAL)]; + + //this branch may grow a second trunk if the diagonal length is less than the max length + $this->mainBranchTip = $this->placeBranch( + $transaction, + new Vector3($x, $y + $firstBranchHeight, $z), + $mainBranchFacing, + $random->nextRange(1, 3), + $trunkHeight - $firstBranchHeight + ); + + $secondBranchFacing = Facing::HORIZONTAL[array_rand(Facing::HORIZONTAL)]; + if($secondBranchFacing !== $mainBranchFacing){ + $secondBranchLength = $random->nextRange(1, 3); + $this->secondBranchTip = $this->placeBranch( + $transaction, + new Vector3($x, $y + ($firstBranchHeight - $random->nextRange(0, 1)), $z), + $secondBranchFacing, + $secondBranchLength, + $secondBranchLength //the secondary branch may not form a second trunk + ); + } + } + + protected function placeBranch(BlockTransaction $transaction, Vector3 $start, int $branchFacing, int $maxDiagonal, int $length) : Vector3{ + $diagonalPlaced = 0; + + $nextBlockPos = $start; + for($yy = 0; $yy < $length; $yy++){ + $nextBlockPos = $nextBlockPos->up(); + if($diagonalPlaced < $maxDiagonal){ + $nextBlockPos = $nextBlockPos->getSide($branchFacing); + $diagonalPlaced++; + } + $transaction->addBlock($nextBlockPos, $this->trunkBlock); + } + + return $nextBlockPos; + } + + protected function placeCanopyLayer(BlockTransaction $transaction, Vector3 $center, int $radius, int $maxTaxicabDistance) : void{ + $centerX = $center->getFloorX(); + $centerY = $center->getFloorY(); + $centerZ = $center->getFloorZ(); + + for($x = $centerX - $radius; $x <= $centerX + $radius; ++$x){ + for($z = $centerZ - $radius; $z <= $centerZ + $radius; ++$z){ + if( + abs($x - $centerX) + abs($z - $centerZ) <= $maxTaxicabDistance && + $transaction->fetchBlockAt($x, $centerY, $z)->canBeReplaced() + ){ + $transaction->addBlockAt($x, $centerY, $z, $this->leafBlock); + } + } + } + } + + protected function placeCanopy(int $x, int $y, int $z, Random $random, BlockTransaction $transaction) : void{ + $mainBranchTip = $this->mainBranchTip; + if($mainBranchTip !== null){ + $this->placeCanopyLayer($transaction, $mainBranchTip, radius: 3, maxTaxicabDistance: 5); + $this->placeCanopyLayer($transaction, $mainBranchTip->up(), radius: 2, maxTaxicabDistance: 2); + } + $secondBranchTip = $this->secondBranchTip; + if($secondBranchTip !== null){ + $this->placeCanopyLayer($transaction, $secondBranchTip, radius: 2, maxTaxicabDistance: 3); + $this->placeCanopyLayer($transaction, $secondBranchTip->up(), radius: 1, maxTaxicabDistance: 2); + } + } +} diff --git a/src/world/generator/object/TreeFactory.php b/src/world/generator/object/TreeFactory.php index ecab73c79..1d95a77b1 100644 --- a/src/world/generator/object/TreeFactory.php +++ b/src/world/generator/object/TreeFactory.php @@ -49,6 +49,8 @@ final class TreeFactory{ }else{*/ //} + }elseif($type->equals(TreeType::ACACIA())){ + return new AcaciaTree(); } return null; }