38 public const MAX_WETNESS = 7;
40 private const WATER_SEARCH_HORIZONTAL_LENGTH = 9;
42 private const WATER_SEARCH_VERTICAL_LENGTH = 2;
44 private const WATER_POSITION_INDEX_UNKNOWN = -1;
46 private const WATER_POSITION_INDICES_TOTAL = (self::WATER_SEARCH_HORIZONTAL_LENGTH ** 2) * 2;
48 protected int $wetness = 0;
63 private int $waterPositionIndex = self::WATER_POSITION_INDEX_UNKNOWN;
66 $w->boundedIntAuto(0, self::MAX_WETNESS, $this->wetness);
67 $w->
boundedIntAuto(-1, self::WATER_POSITION_INDICES_TOTAL - 1, $this->waterPositionIndex);
70 public function getWetness() : int{ return $this->wetness; }
74 if($wetness < 0 || $wetness > self::MAX_WETNESS){
75 throw new \InvalidArgumentException(
"Wetness must be in range 0 ... " . self::MAX_WETNESS);
77 $this->wetness = $wetness;
84 public function getWaterPositionIndex() : int{ return $this->waterPositionIndex; }
89 public function setWaterPositionIndex(
int $waterPositionIndex) : self{
90 if($waterPositionIndex < -1 || $waterPositionIndex >= self::WATER_POSITION_INDICES_TOTAL){
91 throw new \InvalidArgumentException(
"Water XZ index must be in range -1 ... " . (self::WATER_POSITION_INDICES_TOTAL - 1));
93 $this->waterPositionIndex = $waterPositionIndex;
102 if($this->getSide(
Facing::UP)->isSolid()){
103 $this->position->getWorld()->setBlock($this->position, VanillaBlocks::DIRT());
112 $world = $this->position->getWorld();
115 $oldWaterPositionIndex = $this->waterPositionIndex;
118 if(!$this->canHydrate()){
119 if($this->wetness > 0){
122 if(!$event->isCancelled()){
123 $this->wetness = $event->getNewHydration();
124 $world->setBlock($this->position, $this,
false);
128 $world->setBlock($this->position, VanillaBlocks::DIRT());
131 }elseif($this->wetness < self::MAX_WETNESS){
134 if(!$event->isCancelled()){
135 $this->wetness = $event->getNewHydration();
136 $world->setBlock($this->position, $this,
false);
141 if(!$changed && $oldWaterPositionIndex !== $this->waterPositionIndex){
143 $world->setBlock($this->position, $this,
false);
148 if($entity instanceof
Living &&
Utils::getRandomFloat() < $entity->getFallDistance() - 0.5){
151 if(!$ev->isCancelled()){
152 $this->position->getWorld()->setBlock($this->position, VanillaBlocks::DIRT());
158 protected function canHydrate() : bool{
159 $world = $this->position->getWorld();
161 $startX = $this->position->getFloorX() - (
int) (self::WATER_SEARCH_HORIZONTAL_LENGTH / 2);
162 $startY = $this->position->getFloorY();
163 $startZ = $this->position->getFloorZ() - (
int) (self::WATER_SEARCH_HORIZONTAL_LENGTH / 2);
165 if($this->waterPositionIndex !== self::WATER_POSITION_INDEX_UNKNOWN){
166 $raw = $this->waterPositionIndex;
167 $x = $raw % self::WATER_SEARCH_HORIZONTAL_LENGTH;
168 $raw = intdiv($raw, self::WATER_SEARCH_HORIZONTAL_LENGTH);
169 $z = $raw % self::WATER_SEARCH_HORIZONTAL_LENGTH;
170 $raw = intdiv($raw, self::WATER_SEARCH_HORIZONTAL_LENGTH);
171 $y = $raw % self::WATER_SEARCH_VERTICAL_LENGTH;
173 if($world->getBlockAt($startX + $x, $startY + $y, $startZ + $z) instanceof Water){
180 for($y = 0; $y < self::WATER_SEARCH_VERTICAL_LENGTH; $y++){
181 for($x = 0; $x < self::WATER_SEARCH_HORIZONTAL_LENGTH; $x++){
182 for($z = 0; $z < self::WATER_SEARCH_HORIZONTAL_LENGTH; $z++){
183 if($world->getBlockAt($startX + $x, $startY + $y, $startZ + $z) instanceof Water){
184 $this->waterPositionIndex = $x + ($z * self::WATER_SEARCH_HORIZONTAL_LENGTH) + ($y * self::WATER_SEARCH_HORIZONTAL_LENGTH ** 2);
191 $this->waterPositionIndex = self::WATER_POSITION_INDEX_UNKNOWN;