public ItemStack b(ISourceBlock isourceblock, ItemStack itemstack) {
    EnumFacing enumfacing = BlockDispenser.b(isourceblock.h());
    double d0 = isourceblock.getX() + (double) enumfacing.c();
    double d1 = (double) ((float) isourceblock.getBlockY() + 0.2F);
    double d2 = isourceblock.getZ() + (double) enumfacing.e();

    // CraftBukkit start
    World world = isourceblock.k();
    ItemStack itemstack1 = itemstack.a(1);
    org.bukkit.block.Block block =
        world
            .getWorld()
            .getBlockAt(
                isourceblock.getBlockX(), isourceblock.getBlockY(), isourceblock.getBlockZ());
    CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1);

    BlockDispenseEvent event =
        new BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector(d0, d1, d2));
    if (!BlockDispenser.eventFired) {
      world.getServer().getPluginManager().callEvent(event);
    }

    if (event.isCancelled()) {
      itemstack.count++;
      return itemstack;
    }

    if (!event.getItem().equals(craftItem)) {
      itemstack.count++;
      // Chain to handler for new item
      ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem());
      IDispenseBehavior idispensebehavior =
          (IDispenseBehavior) BlockDispenser.a.a(eventStack.getItem());
      if (idispensebehavior != IDispenseBehavior.a && idispensebehavior != this) {
        idispensebehavior.a(isourceblock, eventStack);
        return itemstack;
      }
    }

    itemstack1 = CraftItemStack.asNMSCopy(event.getItem());
    EntityFireworks entityfireworks =
        new EntityFireworks(
            isourceblock.k(),
            event.getVelocity().getX(),
            event.getVelocity().getY(),
            event.getVelocity().getZ(),
            itemstack1);

    isourceblock.k().addEntity(entityfireworks);
    // itemstack.a(1); // Handled during event processing
    // CraftBukkit end

    return itemstack;
  }
  public ItemStack b(IBlockSource iblocksource, ItemStack itemstack) {
    EnumFacing enumfacing = BlockDispenser.j_(iblocksource.h());
    World world = iblocksource.k();
    double d0 = iblocksource.a() + (double) ((float) enumfacing.c() * 1.125F);
    double d1 = iblocksource.b() + (double) ((float) enumfacing.d() * 1.125F);
    double d2 = iblocksource.c() + (double) ((float) enumfacing.e() * 1.125F);
    int i0 = iblocksource.d() + enumfacing.c();
    int i1 = iblocksource.e() + enumfacing.d();
    int i2 = iblocksource.f() + enumfacing.e();
    int i3 = world.a(i0, i1, i2);
    double d3;

    if (BlockRailBase.d_(i3)) {
      d3 = 0.0D;
    } else {
      if (i3 != 0 || !BlockRailBase.d_(world.a(i0, i1 - 1, i2))) {
        return this.b.a(iblocksource, itemstack);
      }

      d3 = -1.0D;
    }

    EntityMinecart entityminecart =
        EntityMinecart.a(world, d0, d1 + d3, d2, ((ItemMinecart) itemstack.b()).a);

    // CanaryMod: Dispense
    DispenseHook hook =
        new DispenseHook(
            ((TileEntityDispenser) iblocksource.j()).getCanaryDispenser(),
            entityminecart.getCanaryEntity());

    Canary.hooks().callHook(hook);
    if (!hook.isCanceled()) {
      world.d((Entity) entityminecart);
      itemstack.a(1);
    }
    //
    return itemstack;
  }
  public ItemStack b(IBlockSource iblocksource, ItemStack itemstack) {
    EnumFacing enumfacing = BlockDispenser.j_(iblocksource.h());
    World world = iblocksource.k();
    int i0 = iblocksource.d() + enumfacing.c();
    int i1 = iblocksource.e() + enumfacing.d();
    int i2 = iblocksource.f() + enumfacing.e();
    Material material = world.g(i0, i1, i2);
    int i3 = world.h(i0, i1, i2);
    Item item;

    if (Material.h.equals(material) && i3 == 0) {
      item = Item.ay;
    } else {
      if (!Material.i.equals(material) || i3 != 0) {
        return super.b(iblocksource, itemstack);
      }

      item = Item.az;
    }

    world.i(i0, i1, i2);
    if (--itemstack.a == 0) {
      // CanaryMod: Dispense
      DispenseHook hook =
          new DispenseHook(((TileEntityDispenser) iblocksource.j()).getCanaryDispenser(), null);

      Canary.hooks().callHook(hook);
      if (!hook.isCanceled()) {
        itemstack.c = item.cp;
        itemstack.a = 1;
      }
      //
    } else if (((TileEntityDispenser) iblocksource.j()).a(new ItemStack(item)) < 0) {
      this.b.a(iblocksource, new ItemStack(item));
    }

    return itemstack;
  }
  public ItemStack b(ISourceBlock isourceblock, ItemStack itemstack) {
    ItemBucket itembucket = (ItemBucket) itemstack.getItem();
    BlockPosition blockposition =
        isourceblock.getBlockPosition().shift(BlockDispenser.b(isourceblock.f()));

    // CraftBukkit start
    World world = isourceblock.i();
    int x = blockposition.getX();
    int y = blockposition.getY();
    int z = blockposition.getZ();
    if (world.isEmpty(blockposition)
        || !world.getType(blockposition).getBlock().getMaterial().isBuildable()) {
      org.bukkit.block.Block block =
          world
              .getWorld()
              .getBlockAt(
                  isourceblock.getBlockPosition().getX(),
                  isourceblock.getBlockPosition().getY(),
                  isourceblock.getBlockPosition().getZ());
      CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack);

      BlockDispenseEvent event =
          new BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector(x, y, z));
      if (!BlockDispenser.eventFired) {
        world.getServer().getPluginManager().callEvent(event);
      }

      if (event.isCancelled()) {
        return itemstack;
      }

      if (!event.getItem().equals(craftItem)) {
        // Chain to handler for new item
        ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem());
        IDispenseBehavior idispensebehavior =
            (IDispenseBehavior) BlockDispenser.M.get(eventStack.getItem());
        if (idispensebehavior != IDispenseBehavior.a && idispensebehavior != this) {
          idispensebehavior.a(isourceblock, eventStack);
          return itemstack;
        }
      }

      itembucket = (ItemBucket) CraftItemStack.asNMSCopy(event.getItem()).getItem();
    }
    // CraftBukkit end

    if (itembucket.a(isourceblock.i(), blockposition)) {
      // CraftBukkit start - Handle stacked buckets
      Item item = Items.BUCKET;
      if (--itemstack.count == 0) {
        itemstack.setItem(Items.BUCKET);
        itemstack.count = 1;
      } else if (((TileEntityDispenser) isourceblock.getTileEntity()).addItem(new ItemStack(item))
          < 0) {
        this.b.a(isourceblock, new ItemStack(item));
      }
      // CraftBukkit end
      return itemstack;
    } else {
      return this.b.a(isourceblock, itemstack);
    }
  }
  public ItemStack b(ISourceBlock isourceblock, ItemStack itemstack) {
    World world = isourceblock.i();
    IPosition iposition = BlockDispenser.a(isourceblock);
    EnumDirection enumdirection = BlockDispenser.b(isourceblock.f());
    IProjectile iprojectile = this.a(world, iposition);

    // iprojectile.shoot((double) enumdirection.getAdjacentX(), (double) ((float)
    // enumdirection.getAdjacentY() + 0.1F), (double) enumdirection.getAdjacentZ(), this.b(),
    // this.a());
    // CraftBukkit start
    ItemStack itemstack1 = itemstack.a(1);
    org.bukkit.block.Block block =
        world
            .getWorld()
            .getBlockAt(
                isourceblock.getBlockPosition().getX(),
                isourceblock.getBlockPosition().getY(),
                isourceblock.getBlockPosition().getZ());
    CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1);

    BlockDispenseEvent event =
        new BlockDispenseEvent(
            block,
            craftItem.clone(),
            new org.bukkit.util.Vector(
                (double) enumdirection.getAdjacentX(),
                (double) ((float) enumdirection.getAdjacentY() + 0.1F),
                (double) enumdirection.getAdjacentZ()));
    if (!BlockDispenser.eventFired) {
      world.getServer().getPluginManager().callEvent(event);
    }

    if (event.isCancelled()) {
      itemstack.count++;
      return itemstack;
    }

    if (!event.getItem().equals(craftItem)) {
      itemstack.count++;
      // Chain to handler for new item
      ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem());
      IDispenseBehavior idispensebehavior =
          (IDispenseBehavior) BlockDispenser.N.get(eventStack.getItem());
      if (idispensebehavior != IDispenseBehavior.a && idispensebehavior != this) {
        idispensebehavior.a(isourceblock, eventStack);
        return itemstack;
      }
    }

    iprojectile.shoot(
        event.getVelocity().getX(),
        event.getVelocity().getY(),
        event.getVelocity().getZ(),
        this.b(),
        this.a());
    ((Entity) iprojectile).projectileSource =
        new org.bukkit.craftbukkit.projectiles.CraftBlockProjectileSource(
            (TileEntityDispenser) isourceblock.getTileEntity());
    // CraftBukkit end
    world.addEntity((Entity) iprojectile);
    // itemstack.a(1); // CraftBukkit - Handled during event processing
    return itemstack;
  }