public void killMinecart(DamageSource par1DamageSource) {
    super.killMinecart(par1DamageSource);

    if (!par1DamageSource.isExplosion()) {
      this.entityDropItem(new ItemStack(Block.furnaceIdle, 1), 0.0F);
    }
  }
 private boolean canUpdateCart(EntityMinecart minecart) {
   if (minecart == null) return false;
   if (minecart instanceof IMinecartCompat) {
     return ((IMinecartCompat) minecart).canUpdateManually();
   }
   return !blacklistClasses.contains(minecart.getClass());
 }
  @SubscribeEvent
  public void onEntityTick(MinecartUpdateEvent event) {
    EntityMinecart minecart = event.minecart;
    if (!canUpdateCart(minecart)) return;
    Vec3 cartPoint = new Vec3(minecart.posX, minecart.posY, minecart.posZ);

    List<BehaviourWrapper[]> wrappers = new ArrayList<>();
    for (BlockPos pos :
        BlockPos.getAllInBox(
            new BlockPos(cartPoint).add(-2, -2, -2), new BlockPos(cartPoint).add(2, 2, 2))) {
      IBlockState state = minecart.worldObj.getBlockState(pos);
      wrappers.add(TrackPathProvider.INSTANCE.getTracksAsArray(minecart.worldObj, pos, state));
    }
    double angDiff = Integer.MAX_VALUE;
    double posDiff = 2;
    BehaviourWrapper best = null;
    RayTraceTrackPath bestTrace = null;
    boolean reverse = false;
    for (BehaviourWrapper[] wrapperArray : wrappers) {
      for (BehaviourWrapper w : wrapperArray) {
        RayTraceTrackPath rayTrace =
            w.getPath().rayTrace(cartPoint.addVector(0, -0.5, 0), new Vec3(0, 1, 0));
        if (rayTrace == null) continue;
        if (rayTrace.distance > posDiff) continue;
        boolean rev = false;

        Vec3 cartAngle = new Vec3(minecart.motionX, minecart.motionY, minecart.motionZ).normalize();
        Vec3 pathAngle = w.getPath().direction(rayTrace.interp).normalize();
        if (cartAngle.distanceTo(pathAngle)
            > cartAngle.distanceTo(pathAngle.subtractReverse(new Vec3(0, 0, 0)))) {
          pathAngle = pathAngle.subtractReverse(new Vec3(0, 0, 0));
          rev = true;
        }

        double diff = cartAngle.distanceTo(pathAngle);
        if (diff > angDiff) continue;

        best = w;
        posDiff = rayTrace.distance;
        angDiff = rayTrace.distance;
        bestTrace = rayTrace;
        reverse = rev;
      }
    }
    if (best != null && bestTrace != null) {
      Vec3 pathDir = best.getPath().direction(bestTrace.interp).normalize();
      if (reverse) pathDir = pathDir.subtractReverse(new Vec3(0, 0, 0));
      Vec3 cartAngle = new Vec3(minecart.motionX, minecart.motionY, minecart.motionZ);
      double speed = cartAngle.lengthVector();
      speed = Math.min(speed, 0.2);
      minecart.motionX = pathDir.xCoord * speed;
      minecart.motionY = pathDir.yCoord * speed;
      minecart.motionZ = pathDir.zCoord * speed;

      Vec3 pathPos = bestTrace.closestPoint;
      minecart.posX = pathPos.xCoord + minecart.motionX;
      minecart.posY = pathPos.yCoord + minecart.motionY;
      minecart.posZ = pathPos.zCoord + minecart.motionZ;
    }
  }
  /** Called to update the entity's position/logic. */
  public void onUpdate() {
    super.onUpdate();

    if (this.fuel > 0) {
      --this.fuel;
    }

    if (this.fuel <= 0) {
      this.pushX = this.pushZ = 0.0D;
    }

    this.setMinecartPowered(this.fuel > 0);

    if (this.isMinecartPowered() && this.rand.nextInt(4) == 0) {
      this.worldObj.spawnParticle(
          "largesmoke", this.posX, this.posY + 0.8D, this.posZ, 0.0D, 0.0D, 0.0D);
    }
  }
  protected void updateOnTrack(
      int par1, int par2, int par3, double par4, double par6, int par8, int par9) {
    super.updateOnTrack(par1, par2, par3, par4, par6, par8, par9);
    double d2 = this.pushX * this.pushX + this.pushZ * this.pushZ;

    if (d2 > 1.0E-4D && this.motionX * this.motionX + this.motionZ * this.motionZ > 0.001D) {
      d2 = (double) MathHelper.sqrt_double(d2);
      this.pushX /= d2;
      this.pushZ /= d2;

      if (this.pushX * this.motionX + this.pushZ * this.motionZ < 0.0D) {
        this.pushX = 0.0D;
        this.pushZ = 0.0D;
      } else {
        this.pushX = this.motionX;
        this.pushZ = this.motionZ;
      }
    }
  }
  protected void applyDrag() {
    double d0 = this.pushX * this.pushX + this.pushZ * this.pushZ;

    if (d0 > 1.0E-4D) {
      d0 = (double) MathHelper.sqrt_double(d0);
      this.pushX /= d0;
      this.pushZ /= d0;
      double d1 = 0.05D;
      this.motionX *= 0.800000011920929D;
      this.motionY *= 0.0D;
      this.motionZ *= 0.800000011920929D;
      this.motionX += this.pushX * d1;
      this.motionZ += this.pushZ * d1;
    } else {
      this.motionX *= 0.9800000190734863D;
      this.motionY *= 0.0D;
      this.motionZ *= 0.9800000190734863D;
    }

    super.applyDrag();
  }
 protected void entityInit() {
   super.entityInit();
   this.dataWatcher.addObject(16, new Byte((byte) 0));
 }
 /** (abstract) Protected helper method to read subclass entity data from NBT. */
 protected void readEntityFromNBT(NBTTagCompound par1NBTTagCompound) {
   super.readEntityFromNBT(par1NBTTagCompound);
   this.pushX = par1NBTTagCompound.getDouble("PushX");
   this.pushZ = par1NBTTagCompound.getDouble("PushZ");
   this.fuel = par1NBTTagCompound.getShort("Fuel");
 }
 /** (abstract) Protected helper method to write subclass entity data to NBT. */
 protected void writeEntityToNBT(NBTTagCompound par1NBTTagCompound) {
   super.writeEntityToNBT(par1NBTTagCompound);
   par1NBTTagCompound.setDouble("PushX", this.pushX);
   par1NBTTagCompound.setDouble("PushZ", this.pushZ);
   par1NBTTagCompound.setShort("Fuel", (short) this.fuel);
 }
 /** Called to update the entity's position/logic. */
 public void onUpdate() {
   super.onUpdate();
   this.mobSpawnerLogic.updateSpawner();
 }
 /** (abstract) Protected helper method to write subclass entity data to NBT. */
 protected void writeEntityToNBT(NBTTagCompound par1NBTTagCompound) {
   super.writeEntityToNBT(par1NBTTagCompound);
   this.mobSpawnerLogic.writeToNBT(par1NBTTagCompound);
 }
 /** (abstract) Protected helper method to read subclass entity data from NBT. */
 protected void readEntityFromNBT(NBTTagCompound par1NBTTagCompound) {
   super.readEntityFromNBT(par1NBTTagCompound);
   this.mobSpawnerLogic.readFromNBT(par1NBTTagCompound);
 }