67                if(!$this->world->isInWorld($x, $y, $z) || !$this->canFlowInto($this->world->getBlockAt($x, $y, $z))){
 
   88            $realCost = $this->calculateFlowCost($x, $y, $z, $accumulatedCost + 1, $maxCost, $originOpposite, Facing::opposite($j));
 
  102        $flowCost = array_fill_keys(
Facing::HORIZONTAL, 1000);
 
  103        $maxCost = intdiv(4, $this->flowDecayPerBlock);
 
  104        foreach(Facing::HORIZONTAL as $j){
 
  105            [$dx, $dy, $dz] = Facing::OFFSET[$j];
 
  110            if(!$this->world->isInWorld($x, $y, $z) || !$this->canFlowInto($this->world->getBlockAt($x, $y, $z))){
 
  111                $this->flowCostVisited[World::blockHash($x, $y, $z)] = self::BLOCKED;
 
  112            }elseif($this->world->getBlockAt($x, $y - 1, $z)->canBeFlowedInto()){
 
  113                $this->flowCostVisited[World::blockHash($x, $y, $z)] = self::CAN_FLOW_DOWN;
 
  114                $flowCost[$j] = $maxCost = 0;
 
  115            }elseif($maxCost > 0){
 
  116                $this->flowCostVisited[World::blockHash($x, $y, $z)] = self::CAN_FLOW;
 
  117                $opposite = Facing::opposite($j);
 
  118                $flowCost[$j] = $this->calculateFlowCost($x, $y, $z, 1, $maxCost, $opposite, $opposite);
 
  119                $maxCost = min($maxCost, $flowCost[$j]);
 
  123        $this->flowCostVisited = [];
 
  125        $minCost = min($flowCost);
 
  127        $isOptimalFlowDirection = [];
 
  129        foreach($flowCost as $facing => $cost){
 
  130            if($cost === $minCost){
 
  131                $isOptimalFlowDirection[] = $facing;
 
  135        return $isOptimalFlowDirection;