PocketMine-MP 5.19.1 git-f1b1a7022d7dc67d012d8891bc4c23c2652c825e
CropGrowthHelper.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\block\utils;
25
28use function mt_rand;
29
30final class CropGrowthHelper{
31
32 private const ON_HYDRATED_FARMLAND_BONUS = 3;
33 private const ON_DRY_FARMLAND_BONUS = 1;
34 private const ADJACENT_HYDRATED_FARMLAND_BONUS = 3 / 4;
35 private const ADJACENT_DRY_FARMLAND_BONUS = 1 / 4;
36
37 private const IMPROPER_ARRANGEMENT_DIVISOR = 2;
38
39 private const MIN_LIGHT_LEVEL = 9;
40
41 private function __construct(){
42 //NOOP
43 }
44
53 public static function calculateMultiplier(Block $block) : float{
54 $result = 1;
55
56 $position = $block->getPosition();
57
58 $world = $position->getWorld();
59 $baseX = $position->getFloorX();
60 $baseY = $position->getFloorY();
61 $baseZ = $position->getFloorZ();
62
63 $farmland = $world->getBlockAt($baseX, $baseY - 1, $baseZ);
64
65 if($farmland instanceof Farmland){
66 $result += $farmland->getWetness() > 0 ? self::ON_HYDRATED_FARMLAND_BONUS : self::ON_DRY_FARMLAND_BONUS;
67 }
68
69 $xRow = false;
70 $zRow = false;
71 $improperArrangement = false;
72
73 for($x = -1; $x <= 1; $x++){
74 for($z = -1; $z <= 1; $z++){
75 if($x === 0 && $z === 0){
76 continue;
77 }
78 $nextFarmland = $world->getBlockAt($baseX + $x, $baseY - 1, $baseZ + $z);
79
80 if(!$nextFarmland instanceof Farmland){
81 continue;
82 }
83
84 $result += $nextFarmland->getWetness() > 0 ? self::ADJACENT_HYDRATED_FARMLAND_BONUS : self::ADJACENT_DRY_FARMLAND_BONUS;
85
86 if(!$improperArrangement){
87 $nextCrop = $world->getBlockAt($baseX + $x, $baseY, $baseZ + $z);
88 if($nextCrop->hasSameTypeId($block)){
89 match(0){
90 $x => $zRow ? $improperArrangement = true : $xRow = true,
91 $z => $xRow ? $improperArrangement = true : $zRow = true,
92 default => $improperArrangement = true,
93 };
94 }
95 }
96 }
97 }
98
99 //crops can be arranged in rows, but the rows must not cross and must be spaced apart by at least one block
100 if($improperArrangement){
101 $result /= self::IMPROPER_ARRANGEMENT_DIVISOR;
102 }
103
104 return $result;
105 }
106
107 public static function hasEnoughLight(Block $block, int $minLevel = self::MIN_LIGHT_LEVEL) : bool{
108 $position = $block->getPosition();
109 $world = $position->getWorld();
110
111 //crop growth is not affected by time of day since 1.11 or so
112 return $world->getPotentialLightAt($position->x, $position->y, $position->z) >= $minLevel;
113 }
114
115 public static function canGrow(Block $block) : bool{
116 //while it may be tempting to use mt_rand(0, 25) < multiplier, this would make crops grow a bit faster than
117 //vanilla in most cases due to the remainder of 25 / multiplier not being discarded
118 return mt_rand(0, (int) (25 / self::calculateMultiplier($block))) === 0 && self::hasEnoughLight($block);
119 }
120}