42 private array $foliageAttachments = [];
44 private const TREE_HEIGHT_BASE = 4;
45 private const TREE_HEIGHT_RANDOM = 3;
46 private const MIN_HEIGHT_FOR_LEAVES = 3;
48 private const LEADUP_SMALL = 2;
49 private const LEADUP_LARGE = 3;
50 private const SIDE_UP_STEPS = 2;
52 public function __construct(){
53 parent::__construct(VanillaBlocks::OAK_LOG(), VanillaBlocks::AZALEA_LEAVES(), 0);
57 $this->treeHeight = $random->nextBoundedInt(self::TREE_HEIGHT_RANDOM) + self::TREE_HEIGHT_BASE;
58 $this->foliageAttachments = [];
59 return parent::getBlockTransaction($world, $x, $y, $z, $random);
62 protected function generateTrunkHeight(
Random $random) : int{
63 return min(self::TREE_HEIGHT_BASE + $random->nextBoundedInt(2), 5);
66 protected function placeTrunk(
int $x,
int $y,
int $z,
Random $random,
int $trunkHeight,
BlockTransaction $transaction) : void{
67 $transaction->addBlockAt($x, $y - 1, $z,
VanillaBlocks::DIRT()->setDirtType(DirtType::ROOTED));
69 $direction = Facing::HORIZONTAL[$random->
nextRange(0, count(Facing::HORIZONTAL) - 1)];
74 $sideUpCount = min(self::SIDE_UP_STEPS, max(0, $trunkHeight - self::LEADUP_SMALL));
75 $leadUpCount = min($trunkHeight - $sideUpCount, self::LEADUP_LARGE);
76 $total = $leadUpCount + $sideUpCount + 1;
77 if($total < $trunkHeight){
78 $leadUpCount += ($trunkHeight - $total);
81 for($i = 0; $i < $total; ++$i){
82 $isLeadUp = $i < $leadUpCount;
83 $isSideUp = $i < $leadUpCount + $sideUpCount - 1;
86 $cx += Facing::OFFSET[$direction->value][0];
87 $cz += Facing::OFFSET[$direction->value][2];
90 if($this->canOverride($transaction->
fetchBlockAt($cx, $cy, $cz))){
91 $transaction->
addBlockAt($cx, $cy, $cz, $this->trunkBlock);
94 if($i >= self::MIN_HEIGHT_FOR_LEAVES){
95 $this->foliageAttachments[] =
new Vector3($cx, $cy, $cz);
98 if($isLeadUp || $isSideUp){
104 protected function placeCanopy(
int $x,
int $y,
int $z, Random $random, BlockTransaction $transaction) : void{
110 foreach($this->foliageAttachments as $attachment){
111 $centerX = $attachment->getFloorX();
112 $centerY = $attachment->getFloorY();
113 $centerZ = $attachment->getFloorZ();
115 for($a = 0; $a < $attempts; ++$a){
116 $dx = $random->nextBoundedInt($radius) - $random->nextBoundedInt($radius);
117 $dy = $random->nextBoundedInt($foliageHeight) - $random->nextBoundedInt($foliageHeight);
118 $dz = $random->nextBoundedInt($radius) - $random->nextBoundedInt($radius);
120 $xx = $centerX + $dx;
121 $yy = $centerY + $dy;
122 $zz = $centerZ + $dz;
124 $hash = World::blockHash($xx, $yy, $zz);
125 if(isset($visited[$hash])){
128 $visited[$hash] =
true;
130 $existing = $transaction->fetchBlockAt($xx, $yy, $zz);
131 if($existing->isTransparent()){
132 $leafBlock = ($random->nextBoundedInt(4) === 0) ? VanillaBlocks::FLOWERING_AZALEA_LEAVES() : VanillaBlocks::AZALEA_LEAVES();
133 $transaction->addBlockAt($xx, $yy, $zz, $leafBlock);
139 protected function canOverride(Block $block) : bool{
140 return parent::canOverride($block)
141 || $block->getTypeId() === BlockTypeIds::AZALEA
142 || $block->getTypeId() === BlockTypeIds::FLOWERING_AZALEA;