Implemented modifiers for crop growth speed

closes #6070

there are some unresolved questions about the growth speed of beetroots, pitcher plants and torchflower crops, but that's a topic for another commit.
this change also doesn't account for the light levels.
This commit is contained in:
Dylan K. Taylor 2023-11-02 15:16:11 +00:00
parent 1e4a1565bb
commit 109673382d
No known key found for this signature in database
GPG Key ID: 8927471A91CAFD3D
6 changed files with 115 additions and 10 deletions

View File

@ -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);

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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;

View File

@ -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);
}
}

View File

@ -0,0 +1,105 @@
<?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\block\utils;
use pocketmine\block\Block;
use pocketmine\block\Farmland;
use function mt_rand;
final class CropGrowthHelper{
private const ON_HYDRATED_FARMLAND_BONUS = 3;
private const ON_DRY_FARMLAND_BONUS = 1;
private const ADJACENT_HYDRATED_FARMLAND_BONUS = 3 / 4;
private const ADJACENT_DRY_FARMLAND_BONUS = 1 / 4;
private const IMPROPER_ARRANGEMENT_DIVISOR = 2;
private function __construct(){
//NOOP
}
/**
* Returns the speed at which this crop will grow, depending on its surroundings.
* The default is once every 26 random ticks.
*
* Things which influence this include nearby farmland (bonus for hydrated farmland) and the position of other
* nearby crops of the same type (nearby crops of the same type will negatively influence growth speed unless
* planted in rows and properly spaced apart).
*/
public static function calculateMultiplier(Block $block) : float{
$result = 1;
$position = $block->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;
}
}