PocketMine-MP 5.36.1 git-eaa7c4834c8fe2f379d24e7f0ee6cc63cfb18ccc
Loading...
Searching...
No Matches
NetherTree.php
1<?php
2
3/*
4 *
5 * ____ _ _ __ __ _ __ __ ____
6 * | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
7 * | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
8 * | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
9 * |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
10 *
11 * This program is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License as published by
13 * the Free Software Foundation, either version 3 of the License, or
14 * (at your option) any later version.
15 *
16 * @author PocketMine Team
17 * @link http://www.pocketmine.net/
18 *
19 *
20 */
21
22declare(strict_types=1);
23
24namespace pocketmine\world\generator\object;
25
33use function abs;
34use function min;
35
36class NetherTree extends Tree{
37
38 public function __construct(
39 Block $stemBlock,
40 Block $hatBlock,
41 private readonly Block $decorBlock,
42 int $treeHeight,
43 private readonly bool $hasVines,
44 private readonly bool $huge
45 ){
46 parent::__construct($stemBlock, $hatBlock, $treeHeight);
47 }
48
49 public function canPlaceObject(ChunkManager $world, int $x, int $y, int $z, Random $random) : bool{
50 return true;
51 }
52
53 protected function placeTrunk(int $x, int $y, int $z, Random $random, int $trunkHeight, BlockTransaction $transaction) : void{
54 $i = $this->huge ? 1 : 0;
55
56 for($j = -$i; $j <= $i; ++$j){
57 for($k = -$i; $k <= $i; ++$k){
58 $isCorner = $this->huge && abs($j) === $i && abs($k) === $i;
59
60 for($l = 0; $l < $trunkHeight; ++$l){
61 $blockX = $x + $j;
62 $blockY = $y + $l;
63 $blockZ = $z + $k;
64
65 if((!$isCorner || $random->nextFloat() < 0.1) && $this->canOverride($transaction->fetchBlockAt($blockX, $blockY, $blockZ))){
66 $transaction->addBlockAt($blockX, $blockY, $blockZ, $this->trunkBlock);
67 }
68 }
69 }
70 }
71 }
72
73 protected function placeCanopy(int $x, int $y, int $z, Random $random, BlockTransaction $transaction) : void{
74 $isCrimson = $this->hasVines;
75 $i = min($random->nextBoundedInt(1 + (int) ($this->treeHeight / 3)) + 5, $this->treeHeight);
76 $j = $this->treeHeight - $i;
77
78 for($k = $j; $k <= $this->treeHeight; ++$k){
79 $l = $k < $this->treeHeight - $random->nextBoundedInt(3) ? 2 : 1;
80
81 if($i > 8 && $k < $j + 4){
82 $l = 3;
83 }
84
85 if($this->huge){
86 ++$l;
87 }
88
89 for($i1 = -$l; $i1 <= $l; ++$i1){
90 for($j1 = -$l; $j1 <= $l; ++$j1){
91 $isEdgeX = $i1 === -$l || $i1 === $l;
92 $isEdgeZ = $j1 === -$l || $j1 === $l;
93 $isInner = !$isEdgeX && !$isEdgeZ && $k !== $this->treeHeight;
94 $isCorner = $isEdgeX && $isEdgeZ;
95 $isLowerSection = $k < $j + 3;
96
97 $blockX = $x + $i1;
98 $blockY = $y + $k;
99 $blockZ = $z + $j1;
100
101 if($this->canOverride($transaction->fetchBlockAt($blockX, $blockY, $blockZ))){
102 if($isLowerSection){
103 if(!$isInner){
104 $this->placeHatDropBlock($blockX, $blockY, $blockZ, $random, $transaction, $isCrimson);
105 }
106 }elseif($isInner){
107 $this->placeHatBlock($blockX, $blockY, $blockZ, $random, $transaction, 0.1, 0.2, $isCrimson ? 0.1 : 0.0);
108 }elseif($isCorner){
109 $this->placeHatBlock($blockX, $blockY, $blockZ, $random, $transaction, 0.01, 0.7, $isCrimson ? 0.083 : 0.0);
110 }else{
111 $this->placeHatBlock($blockX, $blockY, $blockZ, $random, $transaction, 0.0005, 0.98, $isCrimson ? 0.07 : 0.0);
112 }
113 }
114 }
115 }
116 }
117 }
118
119 protected function placeHatBlock(int $x, int $y, int $z, Random $random, BlockTransaction $transaction, float $decorChance, float $hatChance, float $vineChance) : void{
120 if($random->nextFloat() < $decorChance){
121 $transaction->addBlockAt($x, $y, $z, $this->decorBlock);
122 }elseif($random->nextFloat() < $hatChance){
123 $transaction->addBlockAt($x, $y, $z, $this->leafBlock);
124 if($random->nextFloat() < $vineChance){
125 $this->tryPlaceWeepingVines($x, $y, $z, $random, $transaction);
126 }
127 }
128 }
129
130 protected function placeHatDropBlock(int $x, int $y, int $z, Random $random, BlockTransaction $transaction, bool $isCrimson) : void{
131 $blockBelow = $transaction->fetchBlockAt($x, $y - 1, $z);
132 if($blockBelow->getTypeId() === $this->leafBlock->getTypeId()){
133 $transaction->addBlockAt($x, $y, $z, $this->leafBlock);
134 }elseif($random->nextFloat() < 0.15){
135 $transaction->addBlockAt($x, $y, $z, $this->leafBlock);
136 if($isCrimson && $random->nextBoundedInt(11) === 0){
137 $this->tryPlaceWeepingVines($x, $y, $z, $random, $transaction);
138 }
139 }
140 }
141
142 protected function tryPlaceWeepingVines(int $x, int $y, int $z, Random $random, BlockTransaction $transaction) : void{
143 $currentY = $y - 1;
144
145 if($this->canOverride($transaction->fetchBlockAt($x, $currentY, $z))){
146 $i = $random->nextBoundedInt(5) + 1;
147 if($random->nextBoundedInt(7) === 0){
148 $i *= 2;
149 }
150
151 $maxAge = NetherVines::MAX_AGE;
152 $startAge = 23;
153
154 for($v = 0; $v < $i; ++$v){
155 $vy = $currentY - $v;
156 if($vy < 0){
157 break;
158 }
159
160 if($this->canOverride($transaction->fetchBlockAt($x, $vy, $z))){
161 $vineAge = min($maxAge, $startAge + $v);
162 $transaction->addBlockAt($x, $vy, $z, VanillaBlocks::WEEPING_VINES()->setAge($vineAge));
163 }else{
164 break;
165 }
166 }
167 }
168 }
169
170 protected function canOverride(Block $block) : bool{
171 return $block->canBeReplaced() || $block->hasTypeTag(BlockTypeTags::HUGE_FUNGUS_REPLACEABLE);
172 }
173
174 protected function generateTrunkHeight(Random $random) : int{
175 return $this->treeHeight;
176 }
177}
hasTypeTag(string $tag)
Definition Block.php:217
addBlockAt(int $x, int $y, int $z, Block $state)
fetchBlockAt(int $x, int $y, int $z)