gt:                     BlockPos blockpos = (new BlockPos(vec3d2)).down();
context: package net.minecraft.pathfinding;
  
  import javax.annotation.Nullable;
  import net.minecraft.entity.Entity;
  import net.minecraft.entity.EntityLiving;
  import net.minecraft.entity.SharedMonsterAttributes;
  import net.minecraft.entity.ai.attributes.IAttributeInstance;
  import net.minecraft.util.math.AxisAlignedBB;
  import net.minecraft.util.math.BlockPos;
  import net.minecraft.util.math.MathHelper;
  import net.minecraft.util.math.Vec3d;
  import net.minecraft.world.ChunkCache;
  import net.minecraft.world.World;
  
  public abstract class PathNavigate
  {
      protected EntityLiving theEntity;
      protected World world;
      /** The PathEntity being followed. */
      @Nullable
      protected Path currentPath;
      protected double speed;
      /** The number of blocks (extra) +/- in each axis that get pulled out as cache for the pathfinder's search space */
      private final IAttributeInstance pathSearchRange;
      /** Time, in number of ticks, following the current path */
      private int totalTicks;
      /** The time when the last position check was done (to detect successful movement) */
      private int ticksAtLastPos;
      /** Coordinates of the entity's position last time a check was done (part of monitoring getting 'stuck') */
      private Vec3d lastPosCheck = Vec3d.ZERO;
      private Vec3d timeoutCachedNode = Vec3d.ZERO;
      private long timeoutTimer;
      private long lastTimeoutCheck;
      private double timeoutLimit;
      private float maxDistanceToWaypoint = 0.5F;
      private boolean tryUpdatePath;
      private long lastTimeUpdated;
      protected NodeProcessor nodeProcessor;
      private BlockPos targetPos;
      private final PathFinder pathFinder;
  
      public PathNavigate(EntityLiving entitylivingIn, World worldIn)
      {
          this.theEntity = entitylivingIn;
          this.world = worldIn;
          this.pathSearchRange = entitylivingIn.getEntityAttribute(SharedMonsterAttributes.FOLLOW_RANGE);
          this.pathFinder = this.getPathFinder();
      }
  
      protected abstract PathFinder getPathFinder();
  
      /**
       * Sets the speed
       */
      public void setSpeed(double speedIn)
      {
          this.speed = speedIn;
      }
  
      /**
       * Gets the maximum distance that the path finding will search in.
       */
      public float getPathSearchRange()
      {
          return (float)this.pathSearchRange.getAttributeValue();
      }
  
      /**
       * Returns true if path can be changed by {@link net.minecraft.pathfinding.PathNavigate#onUpdateNavigation()
       * onUpdateNavigation()}
       */
      public boolean canUpdatePathOnTimeout()
      {
          return this.tryUpdatePath;
      }
  
      public void updatePath()
      {
          if (this.world.getTotalWorldTime() - this.lastTimeUpdated > 20L)
          {
              if (this.targetPos != null)
              {
                  this.currentPath = null;
                  this.currentPath = this.getPathToPos(this.targetPos);
                  this.lastTimeUpdated = this.world.getTotalWorldTime();
                  this.tryUpdatePath = false;
              }
          }
          else
          {
              this.tryUpdatePath = true;
          }
      }
  
      /**
       * Returns the path to the given coordinates. Args : x, y, z
       */
      @Nullable
      public final Path getPathToXYZ(double x, double y, double z)
      {
          return this.getPathToPos(new BlockPos(x, y, z));
      }
  
      /**
       * Returns path to given BlockPos
       */
      @Nullable
      public Path getPathToPos(BlockPos pos)
      {
          if (!this.canNavigate())
          {
              return null;
          }
          else if (this.currentPath != null && !this.currentPath.isFinished() && pos.equals(this.targetPos))
          {
              return this.currentPath;
          }
          else
          {
              this.targetPos = pos;
              float f = this.getPathSearchRange();
              this.world.theProfiler.startSection("pathfind");
              BlockPos blockpos = new BlockPos(this.theEntity);
              int i = (int)(f + 8.0F);
              ChunkCache chunkcache = new ChunkCache(this.world, blockpos.add(-i, -i, -i), blockpos.add(i, i, i), 0);
              Path path = this.pathFinder.findPath(chunkcache, this.theEntity, this.targetPos, f);
              this.world.theProfiler.endSection();
              return path;
          }
      }
  
      /**
       * Returns the path to the given EntityLiving. Args : entity
       */
      @Nullable
      public Path getPathToEntityLiving(Entity entityIn)
      {
          if (!this.canNavigate())
          {
              return null;
          }
          else
          {
              BlockPos blockpos = new BlockPos(entityIn);
  
              if (this.currentPath != null && !this.currentPath.isFinished() && blockpos.equals(this.targetPos))
              {
                  return this.currentPath;
              }
              else
              {
                  this.targetPos = blockpos;
                  float f = this.getPathSearchRange();
                  this.world.theProfiler.startSection("pathfind");
                  BlockPos blockpos1 = (new BlockPos(this.theEntity)).up();
                  int i = (int)(f + 16.0F);
                  ChunkCache chunkcache = new ChunkCache(this.world, blockpos1.add(-i, -i, -i), blockpos1.add(i, i, i), 0);
                  Path path = this.pathFinder.findPath(chunkcache, this.theEntity, entityIn, f);
                  this.world.theProfiler.endSection();
                  return path;
              }
          }
      }
  
      /**
       * Try to find and set a path to XYZ. Returns true if successful. Args : x, y, z, speed
       */
      public boolean tryMoveToXYZ(double x, double y, double z, double speedIn)
      {
          return this.setPath(this.getPathToXYZ(x, y, z), speedIn);
      }
  
      /**
       * Try to find and set a path to EntityLiving. Returns true if successful. Args : entity, speed
       */
      public boolean tryMoveToEntityLiving(Entity entityIn, double speedIn)
      {
          Path path = this.getPathToEntityLiving(entityIn);
          return path != null && this.setPath(path, speedIn);
      }
  
      /**
       * Sets a new path. If it's diferent from the old path. Checks to adjust path for sun avoiding, and stores start
       * coords. Args : path, speed
       */
      public boolean setPath(@Nullable Path pathentityIn, double speedIn)
      {
          if (pathentityIn == null)
          {
              this.currentPath = null;
              return false;
          }
          else
          {
              if (!pathentityIn.isSamePath(this.currentPath))
              {
                  this.currentPath = pathentityIn;
              }
  
              this.removeSunnyPath();
  
              if (this.currentPath.getCurrentPathLength() == 0)
              {
                  return false;
              }
              else
              {
                  this.speed = speedIn;
                  Vec3d vec3d = this.getEntityPosition();
                  this.ticksAtLastPos = this.totalTicks;
                  this.lastPosCheck = vec3d;
                  return true;
              }
          }
      }
  
      /**
       * gets the actively used PathEntity
       */
      @Nullable
      public Path getPath()
      {
          return this.currentPath;
      }
  
      public void onUpdateNavigation()
      {
          ++this.totalTicks;
  
          if (this.tryUpdatePath)
          {
              this.updatePath();
          }
  
          if (!this.noPath())
          {
              if (this.canNavigate())
              {
                  this.pathFollow();
              }
              else if (this.currentPath != null && this.currentPath.getCurrentPathIndex() < this.currentPath.getCurrentPathLength())
              {
                  Vec3d vec3d = this.getEntityPosition();
                  Vec3d vec3d1 = this.currentPath.getVectorFromIndex(this.theEntity, this.currentPath.getCurrentPathIndex());
  
                  if (vec3d.yCoord > vec3d1.yCoord && !this.theEntity.onGround && MathHelper.floor(vec3d.xCoord) == MathHelper.floor(vec3d1.xCoord) && MathHelper.floor(vec3d.zCoord) == MathHelper.floor(vec3d1.zCoord))
                  {
                      this.currentPath.setCurrentPathIndex(this.currentPath.getCurrentPathIndex() + 1);
                  }
              }
  
              if (!this.noPath())
              {
                  Vec3d vec3d2 = this.currentPath.getPosition(this.theEntity);
  
                  if (vec3d2 != null)
                  {
  