diff --git a/src/block/Crops.php b/src/block/Crops.php index 350268863..e90ac6236 100644 --- a/src/block/Crops.php +++ b/src/block/Crops.php @@ -25,6 +25,7 @@ namespace pocketmine\block; use pocketmine\block\utils\AgeableTrait; use pocketmine\block\utils\BlockEventHelper; +use pocketmine\block\utils\CropGrowthHelper; use pocketmine\block\utils\StaticSupportTrait; use pocketmine\item\Fertilizer; use pocketmine\item\Item; @@ -66,7 +67,7 @@ abstract class Crops extends Flowable{ } public function onRandomTick() : void{ - if($this->age < self::MAX_AGE && mt_rand(0, 2) === 1){ + if($this->age < self::MAX_AGE && CropGrowthHelper::canGrow($this)){ $block = clone $this; ++$block->age; BlockEventHelper::grow($this, $block, null); diff --git a/src/block/DoublePitcherCrop.php b/src/block/DoublePitcherCrop.php index db700a625..e34dd1baf 100644 --- a/src/block/DoublePitcherCrop.php +++ b/src/block/DoublePitcherCrop.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace pocketmine\block; use pocketmine\block\utils\AgeableTrait; +use pocketmine\block\utils\CropGrowthHelper; use pocketmine\data\runtime\RuntimeDataDescriber; use pocketmine\event\block\StructureGrowEvent; use pocketmine\item\Fertilizer; @@ -34,7 +35,6 @@ use pocketmine\math\Facing; use pocketmine\math\Vector3; use pocketmine\player\Player; use pocketmine\world\BlockTransaction; -use function mt_rand; final class DoublePitcherCrop extends DoublePlant{ use AgeableTrait { @@ -101,9 +101,8 @@ final class DoublePitcherCrop extends DoublePlant{ } public function onRandomTick() : void{ - //TODO: the growth speed is influenced by farmland and nearby crops //only the bottom half of the plant can grow randomly - if(mt_rand(0, 2) === 0 && !$this->top){ + if(CropGrowthHelper::canGrow($this) && !$this->top){ $this->grow(null); } } diff --git a/src/block/PitcherCrop.php b/src/block/PitcherCrop.php index 2d9a02162..e0b9af3d2 100644 --- a/src/block/PitcherCrop.php +++ b/src/block/PitcherCrop.php @@ -25,6 +25,7 @@ namespace pocketmine\block; use pocketmine\block\utils\AgeableTrait; use pocketmine\block\utils\BlockEventHelper; +use pocketmine\block\utils\CropGrowthHelper; use pocketmine\block\utils\StaticSupportTrait; use pocketmine\event\block\StructureGrowEvent; use pocketmine\item\Fertilizer; @@ -35,7 +36,6 @@ use pocketmine\math\Facing; use pocketmine\math\Vector3; use pocketmine\player\Player; use pocketmine\world\BlockTransaction; -use function mt_rand; final class PitcherCrop extends Flowable{ use AgeableTrait; @@ -97,8 +97,7 @@ final class PitcherCrop extends Flowable{ } public function onRandomTick() : void{ - //TODO: the growth speed is influenced by farmland and nearby crops - if(mt_rand(0, 2) === 0){ + if(CropGrowthHelper::canGrow($this)){ $this->grow(null); } } diff --git a/src/block/Stem.php b/src/block/Stem.php index d7bf8a51a..2ac95aa3f 100644 --- a/src/block/Stem.php +++ b/src/block/Stem.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace pocketmine\block; use pocketmine\block\utils\BlockEventHelper; +use pocketmine\block\utils\CropGrowthHelper; use pocketmine\data\runtime\RuntimeDataDescriber; use pocketmine\item\Item; use pocketmine\math\Facing; @@ -63,7 +64,7 @@ abstract class Stem extends Crops{ } public function onRandomTick() : void{ - if($this->facing === Facing::UP && mt_rand(0, 2) === 1){ + if($this->facing === Facing::UP && CropGrowthHelper::canGrow($this)){ $world = $this->position->getWorld(); if($this->age < self::MAX_AGE){ $block = clone $this; diff --git a/src/block/TorchflowerCrop.php b/src/block/TorchflowerCrop.php index 75efe142b..033b08552 100644 --- a/src/block/TorchflowerCrop.php +++ b/src/block/TorchflowerCrop.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace pocketmine\block; use pocketmine\block\utils\BlockEventHelper; +use pocketmine\block\utils\CropGrowthHelper; use pocketmine\block\utils\StaticSupportTrait; use pocketmine\data\runtime\RuntimeDataDescriber; use pocketmine\item\Fertilizer; @@ -32,7 +33,6 @@ use pocketmine\item\VanillaItems; use pocketmine\math\Facing; use pocketmine\math\Vector3; use pocketmine\player\Player; -use function mt_rand; final class TorchflowerCrop extends Flowable{ use StaticSupportTrait; @@ -79,7 +79,7 @@ final class TorchflowerCrop extends Flowable{ } public function onRandomTick() : void{ - if(mt_rand(0, 2) === 1){ + if(CropGrowthHelper::canGrow($this)){ BlockEventHelper::grow($this, $this->getNextState(), null); } } diff --git a/src/block/utils/CropGrowthHelper.php b/src/block/utils/CropGrowthHelper.php new file mode 100644 index 000000000..2f2cc1ed3 --- /dev/null +++ b/src/block/utils/CropGrowthHelper.php @@ -0,0 +1,105 @@ +getPosition(); + + $world = $position->getWorld(); + $baseX = $position->getFloorX(); + $baseY = $position->getFloorY(); + $baseZ = $position->getFloorZ(); + + $farmland = $world->getBlockAt($baseX, $baseY - 1, $baseZ); + + if($farmland instanceof Farmland){ + $result += $farmland->getWetness() > 0 ? self::ON_HYDRATED_FARMLAND_BONUS : self::ON_DRY_FARMLAND_BONUS; + } + + $xRow = false; + $zRow = false; + $diagonalRow = false; + for($x = -1; $x <= 1; $x++){ + for($z = -1; $z <= 1; $z++){ + if($x === 0 && $z === 0){ + continue; + } + $nextFarmland = $world->getBlockAt($baseX + $x, $baseY - 1, $baseZ + $z); + + if($nextFarmland instanceof Farmland){ + $result += $nextFarmland->getWetness() > 0 ? self::ADJACENT_HYDRATED_FARMLAND_BONUS : self::ADJACENT_DRY_FARMLAND_BONUS; + } + + $nextCrop = $world->getBlockAt($baseX + $x, $baseY, $baseZ + $z); + if($nextCrop->hasSameTypeId($block)){ + match(0){ + $x => $xRow = true, + $z => $zRow = true, + default => $diagonalRow = true, + }; + } + } + } + + //crops can be arranged in rows, but the rows must not cross and must be spaced apart by at least one block + if(($xRow && $zRow) || $diagonalRow){ + $result /= self::IMPROPER_ARRANGEMENT_DIVISOR; + } + + return $result; + } + + public static function canGrow(Block $block) : bool{ + //while it may be tempting to use mt_rand(0, 25) < multiplier, this would make crops grow a bit faster than + //vanilla in most cases due to the remainder of 25 / multiplier not being discarded + return mt_rand(0, (int) (25 / self::calculateMultiplier($block))) === 0; + } +}