35    private int $randomAmount = 1;
 
   36    private int $baseAmount = 0;
 
   37    private TreeType $type;
 
   43        $this->type = $type ?? TreeType::OAK;
 
 
   46    public function setRandomAmount(
int $amount) : void{
 
   47        $this->randomAmount = $amount;
 
   50    public function setBaseAmount(
int $amount) : void{
 
   51        $this->baseAmount = $amount;
 
   54    public function populate(
ChunkManager $world, 
int $chunkX, 
int $chunkZ, Random $random) : void{
 
   55        $amount = $random->nextRange(0, $this->randomAmount) + $this->baseAmount;
 
   56        for($i = 0; $i < $amount; ++$i){
 
   57            $x = $random->nextRange($chunkX << Chunk::COORD_BIT_SIZE, ($chunkX << Chunk::COORD_BIT_SIZE) + Chunk::EDGE_LENGTH);
 
   58            $z = $random->nextRange($chunkZ << Chunk::COORD_BIT_SIZE, ($chunkZ << Chunk::COORD_BIT_SIZE) + Chunk::EDGE_LENGTH);
 
   59            $y = $this->getHighestWorkableBlock($world, $x, $z);
 
   63            $tree = TreeFactory::get($random, $this->type);
 
   64            $transaction = $tree?->getBlockTransaction($world, $x, $y, $z, $random);
 
   65            $transaction?->apply();
 
   69    private function getHighestWorkableBlock(ChunkManager $world, 
int $x, 
int $z) : int{
 
   70        for($y = 127; $y >= 0; --$y){
 
   71            $b = $world->getBlockAt($x, $y, $z);
 
   72            if($b->hasTypeTag(BlockTypeTags::DIRT) || $b->hasTypeTag(BlockTypeTags::MUD)){
 
   74            }elseif($b->getTypeId() !== BlockTypeIds::AIR && $b->getTypeId() !== BlockTypeIds::SNOW_LAYER){