public void reachedTarget(TileEntity end) {
    this.setDead();
    IELogger.debug("last tick at " + System.currentTimeMillis());
    if (!(this.riddenByEntity instanceof EntityPlayer)) return;
    ItemStack hook = ((EntityPlayer) this.riddenByEntity).getCurrentEquippedItem();
    if (hook == null || !(hook.getItem() instanceof ItemSkyhook)) return;
    Connection line =
        SkylineHelper.getTargetConnection(
            worldObj,
            target.posX,
            target.posY,
            target.posZ,
            (EntityLivingBase) this.riddenByEntity,
            connection);

    if (line != null) {
      ((EntityPlayer) this.riddenByEntity)
          .setItemInUse(hook, hook.getItem().getMaxItemUseDuration(hook));
      SkylineHelper.spawnHook((EntityPlayer) this.riddenByEntity, end, line);
      //					ChunkCoordinates cc0 = line.end==target?line.start:line.end;
      //					ChunkCoordinates cc1 = line.end==target?line.end:line.start;
      //					double dx = cc0.posX-cc1.posX;
      //					double dy = cc0.posY-cc1.posY;
      //					double dz = cc0.posZ-cc1.posZ;
      //
      //					EntityZiplineHook zip = new EntityZiplineHook(worldObj,
      // target.posX+.5,target.posY+.5,target.posZ+.5, line, cc0);
      //					zip.motionX = dx*.05f;
      //					zip.motionY = dy*.05f;
      //					zip.motionZ = dz*.05f;
      //					if(!worldObj.isRemote)
      //						worldObj.spawnEntityInWorld(zip);
      //					ItemSkyHook.existingHooks.put(this.riddenByEntity.getCommandSenderName(), zip);
      //					this.riddenByEntity.mountEntity(zip);
    } else {
      ((EntityPlayer) this.riddenByEntity).motionX = motionX;
      ((EntityPlayer) this.riddenByEntity).motionY = motionY;
      ((EntityPlayer) this.riddenByEntity).motionZ = motionZ;
      IELogger.debug(
          "player motion: "
              + ((EntityPlayer) this.riddenByEntity).motionX
              + ","
              + ((EntityPlayer) this.riddenByEntity).motionY
              + ","
              + ((EntityPlayer) this.riddenByEntity).motionZ);
    }
  }
 @SubscribeEvent
 public void onPlayerTick(TickEvent.PlayerTickEvent event) {
   if (event.side.isClient()
       && event.phase == TickEvent.Phase.START
       && event.player != null
       && event.player == ClientUtils.mc().renderViewEntity) {
     skyhookGrabableConnections.clear();
     EntityPlayer player = event.player;
     ItemStack stack = player.getCurrentEquippedItem();
     if (stack != null && stack.getItem() instanceof ItemSkyhook) {
       TileEntity connector = null;
       double lastDist = 0;
       Connection line = null;
       double py = player.posY + player.getEyeHeight();
       for (int xx = -2; xx <= 2; xx++)
         for (int zz = -2; zz <= 2; zz++)
           for (int yy = 0; yy <= 3; yy++) {
             TileEntity tile =
                 player.worldObj.getTileEntity(
                     (int) player.posX + xx, (int) py + yy, (int) player.posZ + zz);
             if (tile != null) {
               Connection con =
                   SkylineHelper.getTargetConnection(
                       player.worldObj, tile.xCoord, tile.yCoord, tile.zCoord, player, null);
               if (con != null) {
                 double d = tile.getDistanceFrom(player.posX, py, player.posZ);
                 if (connector == null || d < lastDist) {
                   connector = tile;
                   lastDist = d;
                   line = con;
                 }
               }
             }
           }
       if (line != null && connector != null) skyhookGrabableConnections.add(line);
     }
   }
   if (event.side.isClient() && event.phase == TickEvent.Phase.END && event.player != null) {
     EntityPlayer player = event.player;
     ItemStack stack = player.getCurrentEquippedItem();
     if (stack != null
         && stack.getItem() instanceof ItemDrill
         && (player != ClientUtils.mc().renderViewEntity
             || ClientUtils.mc().gameSettings.thirdPersonView != 0)) {
       if (player.getItemInUseCount() <= 0) {
         player.clearItemInUse();
         player.setItemInUse(stack, 2147483647);
       }
     }
   }
 }
  @Override
  public void onUpdate() {
    if (this.ticksExisted == 1 && !worldObj.isRemote)
      IELogger.debug("init tick at " + System.currentTimeMillis());
    super.onUpdate();
    //		if(this.ticksExisted>40)
    //			this.setDead();
    if (worldObj.isRemote) return;

    EntityPlayer player = null;
    if (this.riddenByEntity instanceof EntityPlayer) player = ((EntityPlayer) this.riddenByEntity);

    if (subPoints != null && targetPoint < subPoints.length - 1) {
      double dist = subPoints[targetPoint].distanceTo(Vec3.createVectorHelper(posX, posY, posZ));
      IELogger.debug("dist: " + dist);
      if (dist <= .05) {
        this.posX = subPoints[targetPoint].xCoord;
        this.posY = subPoints[targetPoint].yCoord;
        this.posZ = subPoints[targetPoint].zCoord;
        targetPoint++;
        IELogger.debug("next vertex: " + targetPoint);
        //				double dx = (subPoints[targetPoint].xCoord-posX);//connection.length;
        //				double dy = (subPoints[targetPoint].yCoord-posY);//connection.length;
        //				double dz = (subPoints[targetPoint].zCoord-posZ);//connection.length;
        //				Vec3 moveVec = Vec3.createVectorHelper(dx,dy,dz);
        float speed = 3f;
        if (player != null
            && player.getCurrentEquippedItem() != null
            && player.getCurrentEquippedItem().getItem() instanceof ItemSkyhook)
          speed =
              ((ItemSkyhook) player.getCurrentEquippedItem().getItem())
                  .getSkylineSpeed(player.getCurrentEquippedItem());
        Vec3 moveVec =
            SkylineHelper.getSubMovementVector(
                Vec3.createVectorHelper(posX, posY, posZ), subPoints[targetPoint], speed);
        motionX = moveVec.xCoord; // *speed;
        motionY = moveVec.yCoord; // *speed;
        motionZ = moveVec.zCoord; // *speed;
        return;
      }
    }

    if (target != null && targetPoint == subPoints.length - 1) {
      TileEntity end = this.worldObj.getTileEntity(target.posX, target.posY, target.posZ);
      IImmersiveConnectable iicEnd = Utils.toIIC(end, worldObj);
      if (iicEnd == null) {
        this.setDead();
        return;
      }
      Vec3 vEnd = Vec3.createVectorHelper(target.posX, target.posY, target.posZ);
      vEnd = Utils.addVectors(vEnd, iicEnd.getConnectionOffset(connection));

      double gDist = vEnd.distanceTo(Vec3.createVectorHelper(posX, posY, posZ));
      IELogger.debug("distance to goal: " + gDist);
      if (gDist <= .3) {
        reachedTarget(end);
        return;
      } else if (gDist > 5) {
        setDead();
        return;
      }
    }
    this.posX += this.motionX;
    this.posY += this.motionY;
    this.posZ += this.motionZ;
    float f1 = MathHelper.sqrt_double(this.motionX * this.motionX + this.motionZ * this.motionZ);
    this.rotationYaw = (float) (Math.atan2(this.motionZ, this.motionX) * 180.0D / Math.PI) + 90.0F;

    for (this.rotationPitch =
            (float) (Math.atan2((double) f1, this.motionY) * 180.0D / Math.PI) - 90.0F;
        this.rotationPitch - this.prevRotationPitch < -180.0F;
        this.prevRotationPitch -= 360.0F) ;

    while (this.rotationPitch - this.prevRotationPitch >= 180.0F) this.prevRotationPitch += 360.0F;
    while (this.rotationYaw - this.prevRotationYaw < -180.0F) this.prevRotationYaw -= 360.0F;
    while (this.rotationYaw - this.prevRotationYaw >= 180.0F) this.prevRotationYaw += 360.0F;

    this.rotationPitch =
        this.prevRotationPitch + (this.rotationPitch - this.prevRotationPitch) * 0.2F;
    this.rotationYaw = this.prevRotationYaw + (this.rotationYaw - this.prevRotationYaw) * 0.2F;

    if (this.isInWater()) {
      for (int j = 0; j < 4; ++j) {
        float f3 = 0.25F;
        this.worldObj.spawnParticle(
            "bubble",
            this.posX - this.motionX * (double) f3,
            this.posY - this.motionY * (double) f3,
            this.posZ - this.motionZ * (double) f3,
            this.motionX,
            this.motionY,
            this.motionZ);
      }
    }

    this.setPosition(this.posX, this.posY, this.posZ);
  }