mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-06-25 04:44:03 +00:00
168 lines
4.4 KiB
PHP
168 lines
4.4 KiB
PHP
<?php
|
|
|
|
/*
|
|
*
|
|
* ____ _ _ __ __ _ __ __ ____
|
|
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
|
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
|
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
|
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU Lesser General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* @author PocketMine Team
|
|
* @link http://www.pocketmine.net/
|
|
*
|
|
*
|
|
*/
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace pocketmine\level\generator\object;
|
|
|
|
use pocketmine\block\Block;
|
|
use pocketmine\block\BlockFactory;
|
|
use pocketmine\block\Sapling;
|
|
use pocketmine\level\ChunkManager;
|
|
use pocketmine\utils\Random;
|
|
use function abs;
|
|
|
|
abstract class Tree{
|
|
/** @var bool[] */
|
|
public $overridable = [
|
|
Block::AIR => true,
|
|
Block::SAPLING => true,
|
|
Block::LEAVES => true,
|
|
Block::SNOW_LAYER => true,
|
|
Block::LEAVES2 => true
|
|
];
|
|
|
|
/** @var int */
|
|
public $type = 0;
|
|
/** @var int */
|
|
public $trunkBlock = Block::LOG;
|
|
/** @var int */
|
|
public $leafBlock = Block::LEAVES;
|
|
/** @var int */
|
|
public $treeHeight = 7;
|
|
|
|
/**
|
|
* @param ChunkManager $level
|
|
* @param int $x
|
|
* @param int $y
|
|
* @param int $z
|
|
* @param Random $random
|
|
* @param int $type
|
|
*
|
|
* @return void
|
|
*/
|
|
public static function growTree(ChunkManager $level, int $x, int $y, int $z, Random $random, int $type = 0){
|
|
switch($type){
|
|
case Sapling::SPRUCE:
|
|
$tree = new SpruceTree();
|
|
break;
|
|
case Sapling::BIRCH:
|
|
if($random->nextBoundedInt(39) === 0){
|
|
$tree = new BirchTree(true);
|
|
}else{
|
|
$tree = new BirchTree();
|
|
}
|
|
break;
|
|
case Sapling::JUNGLE:
|
|
$tree = new JungleTree();
|
|
break;
|
|
case Sapling::ACACIA:
|
|
case Sapling::DARK_OAK:
|
|
return; //TODO
|
|
default:
|
|
$tree = new OakTree();
|
|
/*if($random->nextRange(0, 9) === 0){
|
|
$tree = new BigTree();
|
|
}else{*/
|
|
|
|
//}
|
|
break;
|
|
}
|
|
if($tree->canPlaceObject($level, $x, $y, $z, $random)){
|
|
$tree->placeObject($level, $x, $y, $z, $random);
|
|
}
|
|
}
|
|
|
|
|
|
public function canPlaceObject(ChunkManager $level, int $x, int $y, int $z, Random $random) : bool{
|
|
$radiusToCheck = 0;
|
|
for($yy = 0; $yy < $this->treeHeight + 3; ++$yy){
|
|
if($yy === 1 or $yy === $this->treeHeight){
|
|
++$radiusToCheck;
|
|
}
|
|
for($xx = -$radiusToCheck; $xx < ($radiusToCheck + 1); ++$xx){
|
|
for($zz = -$radiusToCheck; $zz < ($radiusToCheck + 1); ++$zz){
|
|
if(!isset($this->overridable[$level->getBlockIdAt($x + $xx, $y + $yy, $z + $zz)])){
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* @param ChunkManager $level
|
|
* @param int $x
|
|
* @param int $y
|
|
* @param int $z
|
|
* @param Random $random
|
|
*
|
|
* @return void
|
|
*/
|
|
public function placeObject(ChunkManager $level, int $x, int $y, int $z, Random $random){
|
|
|
|
$this->placeTrunk($level, $x, $y, $z, $random, $this->treeHeight - 1);
|
|
|
|
for($yy = $y - 3 + $this->treeHeight; $yy <= $y + $this->treeHeight; ++$yy){
|
|
$yOff = $yy - ($y + $this->treeHeight);
|
|
$mid = (int) (1 - $yOff / 2);
|
|
for($xx = $x - $mid; $xx <= $x + $mid; ++$xx){
|
|
$xOff = abs($xx - $x);
|
|
for($zz = $z - $mid; $zz <= $z + $mid; ++$zz){
|
|
$zOff = abs($zz - $z);
|
|
if($xOff === $mid and $zOff === $mid and ($yOff === 0 or $random->nextBoundedInt(2) === 0)){
|
|
continue;
|
|
}
|
|
if(!BlockFactory::$solid[$level->getBlockIdAt($xx, $yy, $zz)]){
|
|
$level->setBlockIdAt($xx, $yy, $zz, $this->leafBlock);
|
|
$level->setBlockDataAt($xx, $yy, $zz, $this->type);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param ChunkManager $level
|
|
* @param int $x
|
|
* @param int $y
|
|
* @param int $z
|
|
* @param Random $random
|
|
* @param int $trunkHeight
|
|
*
|
|
* @return void
|
|
*/
|
|
protected function placeTrunk(ChunkManager $level, int $x, int $y, int $z, Random $random, int $trunkHeight){
|
|
// The base dirt block
|
|
$level->setBlockIdAt($x, $y - 1, $z, Block::DIRT);
|
|
|
|
for($yy = 0; $yy < $trunkHeight; ++$yy){
|
|
$blockId = $level->getBlockIdAt($x, $y + $yy, $z);
|
|
if(isset($this->overridable[$blockId])){
|
|
$level->setBlockIdAt($x, $y + $yy, $z, $this->trunkBlock);
|
|
$level->setBlockDataAt($x, $y + $yy, $z, $this->type);
|
|
}
|
|
}
|
|
}
|
|
}
|