[ 0, 1 ], // 0 vertical, 1 horizontal and same goes for others... 8 => [ 1, 0 ], 9 => [ 1, 1 ], 10 => [ 2, 0 ], 11 => [ 2, 1 ], 12 => [ 2, 2 ], 13 => [ 3, 1 ] ]; const DIAG_LEAVES = [ // Diag poses of the leaves based on the height of the tree.X relative to $lastX and Z from $lastZ 7 => [ [ 4, 4 ], [ - 4, 4 ], [ 4, - 4 ], [ - 4, - 4 ] ], 8 => [ [ 6, 6 ], [ - 6, 6 ], [ 6, - 6 ], [ - 6, - 6 ] ], 9 => [ [ 6, 6 ], [ - 6, 6 ], [ 6, - 6 ], [ - 6, - 6 ] ], 10 => [ [ 6, 6 ], [ - 6, 6 ], [ 6, - 6 ], [ - 6, - 6 ] ], 11 => [ [ 7, 7 ], [ 6, 8 ], [ 8, 6 ], [ - 7, 7 ], [ - 6, 8 ], [ - 8, 6 ], [ 7, - 7 ], [ 6, - 8 ], [ 8, - 6 ], [ - 7, - 7 ], [ - 6, - 8 ], [ - 8, - 6 ] ], 12 => [ [ 7, 7 ], [ 6, 8 ], [ 8, 6 ], [ - 7, 7 ], [ - 6, 8 ], [ - 8, 6 ], [ 7, - 7 ], [ 6, - 8 ], [ 8, - 6 ], [ - 7, - 7 ], [ - 6, - 8 ], [ - 8, - 6 ] ], 13 => [ [ 7, 7 ], [ 6, 8 ], [ 8, 6 ], [ - 7, 7 ], [ - 6, 8 ], [ - 8, 6 ], [ 7, - 7 ], [ 6, - 8 ], [ 8, - 6 ], [ - 7, - 7 ], [ - 6, - 8 ], [ - 8, - 6 ] ] ]; const ADDITIONAL_BLOCKS = [ // Blocks who aren't set to fully fill the tree. X relative to $lastX and Z from $lastZ 7 => [ ], 8 => [ ], 9 => [ ], 10 => [ ], 11 => [ [ 6, 6 ], [ 7, 6 ], [ 6, 7 ], [ - 6, 6 ], [ - 7, 6 ], [ - 6, 7 ], [ 6, - 6 ], [ 7, - 6 ], [ 6, - 7 ], [ - 6, - 6 ], [ - 7, - 6 ], [ - 6, - 7 ] ], 12 => [ [ 6, 6 ], [ 7, 6 ], [ 6, 7 ], [ - 6, 6 ], [ - 7, 6 ], [ - 6, 7 ], [ 6, - 6 ], [ 7, - 6 ], [ 6, - 7 ], [ - 6, - 6 ], [ - 7, - 6 ], [ - 6, - 7 ] ], 13 => [ [ 6, 6 ], [ 7, 6 ], [ 6, 7 ], [ - 6, 6 ], [ - 7, 6 ], [ - 6, 7 ], [ 6, - 6 ], [ 7, - 6 ], [ 6, - 7 ], [ - 6, - 6 ], [ - 7, - 6 ], [ - 6, - 7 ] ] ]; const maxPerChunk = 2; public $trunkHeight = 11; /* * Constructs the class */ public function __construct() { $this->trunkBlock = Block::LOG; $this->leafBlock = Block::WOOL; $this->leafType = 6; $this->leaf2Type = 0; $this->type = Wood::OAK; } /* * Builds the tree. * @param $level \pocketmine\level\ChunkManager * @param $x int * @param $y int * @param $z int * @param $random $random */ public function placeObject(ChunkManager $level, $x, $y, $z, Random $random) { $percentage = $random->nextBoundedInt(100); if ($percentage > 10) { return; } $trunkHeight = 7 + $random->nextBoundedInt(7); $direction = $random->nextBoundedInt(3); // Choosing building north east west south switch ($direction) { case 0 : $xDiff = 0; $zDiff = -1; break; case 1 : $xDiff = 0; $zDiff = 1; break; case 2 : $xDiff = -1; $zDiff = 0; break; case 3 : $xDiff = 1; $zDiff = 0; break; } list($vParts, $hParts ) = self::TRUNK_POS [$trunkHeight]; $this->setLog($level, $x, $y, $z); list($lastX, $lastY, $lastZ ) = [ $x, $y, $z ]; // Filling horisontally if ($hParts > 0) { for($i = 0; $i < $hParts; $i ++) { $lastX += $xDiff * 2; $lastY ++; $lastZ += $zDiff * 2; $this->setLog($level, $lastX - $xDiff, $lastY, $lastZ - $zDiff); $this->setLog($level, $lastX, $lastY, $lastZ); } } // The middle block $lastX += $xDiff; $lastY ++; $lastZ += $zDiff; $this->setLog($level, $lastX, $lastY, $lastZ); // Filling verticaly if ($vParts > 0) { for($i = 0; $i < $vParts; $i ++) { $lastX += $xDiff; $lastY += 2; $lastZ += $zDiff; $this->setLog($level, $lastX, $lastY - 1, $lastZ); $this->setLog($level, $lastX, $lastY, $lastZ); } } // Filling the top trunk. $lastX += $xDiff; $lastY ++; $lastZ += $zDiff; for($i = 0; $i < 4; $i ++) { $this->setLog($level, $lastX, $lastY + $i, $lastZ); } $lastY ++; // FIlling the branches. $branchLen2 = function ($base) { return ceil($base / 2); }; for($dir = 0; $dir < 4; $dir ++) { switch ($dir) { case 0 : $xd = 0; $zd = -1; break; case 1 : $xd = 0; $zd = 1; break; case 2 : $xd = -1; $zd = 0; break; case 3 : $xd = 1; $zd = 0; break; } $stickLen = round($trunkHeight / 3); $stickLen2 = call_user_func($branchLen2, $stickLen); $totalLength = $stickLen + $stickLen2; // Length of the stick $sideLen = $totalLength ** 2; // Side length // First branch part + first leave part for($i = 1; $i < $stickLen + 1; $i ++) { $lX1 = $lastX + ($xd * $i); $lZ1 = $lastZ + ($zd * $i); if ($zd !== 0) for($x = $lX1 - $numForward; $x !== $lX1 + $numForward + 1; $x ++) { $this->setLeave($level, $x, $lastY + 3, $lZ1, $random); } if ($xd !== 0) for($z = $lZ1 - $numForward; $z !== $lZ1 + $numForward + 1; $z ++) { $this->setLeave($level, $lX1, $lastY + 3, $z, $random); } $this->setLog($level, $lX1, $lastY, $lZ1); } // Second branch part. + second leave part $numForward = ($totalLength % 2 == 0) ? $totalLength - 1 : $totalLength; for($i = 1; $i < $stickLen + 1; $i ++) { $lX = $lX1 + ($xd * $i); $lZ = $lZ1 + ($zd * $i); if ($zd !== 0) for($x = $lX - $numForward; $x !== $lX + $numForward + 1; $x ++) { $this->setLeave($level, $x, $lastY + 2, $lZ, $random); } if ($xd !== 0) for($z = $lZ - $numForward; $z !== $lZ + $numForward + 1; $z ++) { $this->setLeave($level, $lX, $lastY + 2, $z, $random); } $this->setLog($level, $lX, $lastY + 1, $lZ); } $lX += $xd; $lZ += $zd; // Leaves falling from the tree forward if ($lastZ !== $lZ) { // Z has changed, using X for setting for($x = $lX - $numForward; $x <= $lX + $numForward; $x ++) { $numDown = $random->nextBoundedInt(3 ) + 1; for($y = $lastY + 1; $y > $lastY - $numDown; $y --) $this->setLeave($level, $x, $y, $lZ, $random); } } else { // Z have stayed, X has changed for($z = $lZ - $numForward; $z <= $lZ + $numForward; $z ++) { $numDown = $random->nextBoundedInt(3 ) + 1; for($y = $lastY + 1; $y > $lastY + 1 - $numDown; $y --) $this->setLeave($level, $lX, $y, $z, $random); } } // continue; switch ($dir + 1) { case 4 : $xd2 = 0; $zd2 = -1; break; case 1 : $xd2 = 0; $zd2 = 1; break; case 2 : $xd2 = -1; $zd2 = 0; break; case 3 : $xd2 = 1; $zd2 = 0; break; } // Leaves falling from the tree diagonaly foreach(self::DIAG_LEAVES [$trunkHeight] as $pos ) { $numDown = $random->nextBoundedInt(3 ) + 1; for($y = $lastY + 1; $y > $lastY - $numDown; $y --) $this->setLeave($level, $lastX + $pos [0], $y, $lastZ + $pos [1], $random); } // Additional leaves foreach(self::ADDITIONAL_BLOCKS [$trunkHeight] as $pos ) { $this->setLeave($level, $lastX + $pos [0], $lastY + 2, $lastZ + $pos [1], $random); } } } /* * Fills a log at. * @param $level pocketmine\level\ChunkManager * @param $x int * @param $y int * @param $z int */ public function setLog(ChunkManager $level, $x, $y, $z) { $level->setBlockIdAt($x, $y, $z, $this->trunkBlock); $level->setBlockDataAt($x, $y, $z, $this->type); } /* * Fills a leave at. * @param $level pocketmine\level\ChunkManager * @param $x int * @param $y int * @param $z int * @param $random pocketmine\utils\Random */ public function setLeave(ChunkManager $level, $x, $y, $z, Random $random) { $data = [ $this->leafType, $this->leaf2Type ] [( int ) $random->nextBoolean ()]; $level->setBlockIdAt($x, $y, $z, $this->leafBlock); $level->setBlockDataAt($x, $y, $z, $data); } }