22declare(strict_types=1);
35use
function lcg_value;
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;
105 if($this->getSide(
Facing::UP)->isSolid()){
106 $this->position->getWorld()->setBlock($this->position, VanillaBlocks::DIRT());
115 $world = $this->position->getWorld();
118 $oldWaterPositionIndex = $this->waterPositionIndex;
121 if(!$this->canHydrate()){
122 if($this->wetness > 0){
125 if(!$event->isCancelled()){
126 $this->wetness = $event->getNewHydration();
127 $world->setBlock($this->position, $this,
false);
131 $world->setBlock($this->position, VanillaBlocks::DIRT());
134 }elseif($this->wetness < self::MAX_WETNESS){
137 if(!$event->isCancelled()){
138 $this->wetness = $event->getNewHydration();
139 $world->setBlock($this->position, $this,
false);
144 if(!$changed && $oldWaterPositionIndex !== $this->waterPositionIndex){
146 $world->setBlock($this->position, $this,
false);
151 if($entity instanceof
Living && lcg_value() < $entity->getFallDistance() - 0.5){
154 if(!$ev->isCancelled()){
155 $this->position->getWorld()->setBlock($this->position, VanillaBlocks::DIRT());
161 protected function canHydrate() : bool{
162 $world = $this->position->getWorld();
164 $startX = $this->position->getFloorX() - (int) (self::WATER_SEARCH_HORIZONTAL_LENGTH / 2);
165 $startY = $this->position->getFloorY();
166 $startZ = $this->position->getFloorZ() - (int) (self::WATER_SEARCH_HORIZONTAL_LENGTH / 2);
168 if($this->waterPositionIndex !== self::WATER_POSITION_INDEX_UNKNOWN){
169 $raw = $this->waterPositionIndex;
170 $x = $raw % self::WATER_SEARCH_HORIZONTAL_LENGTH;
171 $raw = intdiv($raw, self::WATER_SEARCH_HORIZONTAL_LENGTH);
172 $z = $raw % self::WATER_SEARCH_HORIZONTAL_LENGTH;
173 $raw = intdiv($raw, self::WATER_SEARCH_HORIZONTAL_LENGTH);
174 $y = $raw % self::WATER_SEARCH_VERTICAL_LENGTH;
176 if($world->getBlockAt($startX + $x, $startY + $y, $startZ + $z) instanceof Water){
183 for($y = 0; $y < self::WATER_SEARCH_VERTICAL_LENGTH; $y++){
184 for($x = 0; $x < self::WATER_SEARCH_HORIZONTAL_LENGTH; $x++){
185 for($z = 0; $z < self::WATER_SEARCH_HORIZONTAL_LENGTH; $z++){
186 if($world->getBlockAt($startX + $x, $startY + $y, $startZ + $z) instanceof Water){
187 $this->waterPositionIndex = $x + ($z * self::WATER_SEARCH_HORIZONTAL_LENGTH) + ($y * self::WATER_SEARCH_HORIZONTAL_LENGTH ** 2);
194 $this->waterPositionIndex = self::WATER_POSITION_INDEX_UNKNOWN;
recalculateCollisionBoxes()
getPickedItem(bool $addUserData=false)
onEntityLand(Entity $entity)
describeBlockOnlyState(RuntimeDataDescriber $w)
getDropsForCompatibleTool(Item $item)
boundedIntAuto(int $min, int $max, int &$value)